Use the ethers js library library as a collection of readable stores for Svelte.
Inspired by the svelte-web3 library by clbrge.
-
Add the
ethers-svelte
package:npm i ethers-svelte
-
Add the ethers js library to your main HTML (
public/index.html
) file in your Svelte app.
<script src="https://cdn.ethers.io/lib/ethers-5.2.umd.min.js" type="application/javascript"></script>
-
By connecting to any Web 3 Providers like
MetaMask
,Web3Modal
withWalletConnect
etc by using theuseWeb3Provider
function. -
By connecting to any RPC provider like
Infura
orAlchemy
directly or even to your local blockchain such asHardhat
orGanache
etc by using theuseJsonRpcProvider
function.
Firstly we have to create a chain store. To do that, import the createChainStore
function:
import { createChainStore } from 'ethers-svelte';
Invoking the createChainStore
function gives us back multiple stores to read from and also other helpers that help intitate our connection to our providers.
const { useWeb3Provider, useJsonRpcProvider, chainStore, signer, provider } = createChainStore();
The useWeb3Provider
and useJsonRpcProvider
returned above are functions that we will use to connect to our provider. The chainstore
is a svelte store we can subscribe to for different values. All these values are also exported as derived stores such as the signer
and provider
shown above.
All values are null
by default until a connection to a provider is established.
Metamask by default provides window.ethereum in the global namespace
const { useWeb3Provider, useJsonRpcProvider, chainStore, signer, provider } = createChainStore();
useWeb3Provider(window.ethereum); //Activates Metamask popup
Once initialized we can use the chainStore
to read multiple values:
$chainStore.account //The current account connected
$chainStore.network //The current network connected
$chainStore.chainId //The current chainId you are connected to
$chainStore.chainData //CAIP-2 representation of chain data
$chainStore.allAccounts //Equivalent to provider.listAccounts()
$chainStore.provider //EthersJs Provider Instance
$chainStore.signer //EthersJs Signer Instance
//All the above values are also exported as standalone derived stores when invoking the createChainStore() function. Example:
$account //The current account connected
$provider //EthersJs Provider Instance
$signer //EthersJs Signer Instance
We can then use the Ethers JS Provider/Signer instance as we would:
$provider.getBalance("0xsomeAddress");
$signer.sendTransaction({to, value, gasLimit});
Ethers-Svelte provides a consistent interface. All values and usage is almost similar for whichever provider interface (web3/JsonRpc) you use.
import { createChainStore } from 'ethers-svelte';
const { useWeb3Provider, useJsonRpcProvider, chainStore, signer, provider } = createChainStore();
const Web3Modal = window.Web3Modal.default;
const WalletConnectProvider = window.WalletConnectProvider.default;
const web3Modal = new Web3Modal({
providerOptions: {
walletconnect: { package: WalletConnectProvider, options: { infuraId: 'infuraId' } }
}
});
web3Modal.connect().then((wcProvider) => {
useWeb3Provider(wcProvider);
});
$: console.log($chainStore.account) //The current account connected
import { createChainStore } from 'ethers-svelte';
const { useWeb3Provider, useJsonRpcProvider, chainStore, signer, provider } = createChainStore();
const hardhatNetwork = 'http://127.0.0.1:8545';
useJsonRpcProvider(hardhatNetwork);
$: console.log($chainStore.account);
$: console.log($signer);
By default, ethers-svelte
will get the default signer at account #0. As a second argument, an index
, address
or wallet
instance can be provided. This is useful when you don't just want to read from the blockchain but also write to it.
The useJsonRpcProvider
also returns an object with a changeSigner
function to change the signer for this store. Continuing from the above example:
useJsonRpcProvider(hardhatNetwork); // Selects the first account at account#0
useJsonRpcProvider(hardhatNetwork, 1); // Select the account at index 1
useJsonRpcProvider(hardhatNetwork, "0xsomeAddress"); // Select the account at address provided
//Any Ethersjs wallet instance can also be provided
const wallet = new ethers.Wallet('privateKeyForAWallet');
useJsonRpcProvider(hardhatNetwork, wallet);
//Finally we can also change the signer
useJsonRpcProvider(hardhatNetwork, 0).then({changeSigner} => {
changeSigner(1);
changeSigner("0xaddress");
changeSigner(wallet);
});
You can use the createContractStore
function from ethers-svelte
to create a contract store.
import { createContractStore, createChainStore, ethers } from "ethers-svelte";
const { useWeb3Provider, signer, provider } = createChainStore();
//A contract store that can read from blockchain
const contractP = createContractStore(contractAddress, abi, provider);
//A contract store that can read/write to blockchain
const contractS = createContractStore(contractAddress, abi, signer);
//Functions can be invoked on that address following the 'Ethers' interface
$contractP.balanceOf("0xAddress");
const amount = ethers.utils.parseUnits(200, 18);
$contractS.transfer("0xAddress", amount);
Make sure a provider
or signer
store is provided to the createContractStore
function and not instances.
createContractStore(contractAddress, abi, provider); //Correct
createContractStore(contractAddress, abi, signer); //Correct
createContractStore(contractAddress, abi, $provider); //Incorrect
createContractStore(contractAddress, abi, $chainStore.provider); //Incorrect
Whenever the provider
or signer
will change, the contractStore
will automatically update to use the updated values.
You can also save your chain store to retreive it later. Simply pass in a key/name when using the createCahinStore
function. If no value is provided, it wont be saved.
import { createChainStore, getChainStore } from 'ethers-svelte';
const { useWeb3Provider, chainStore, signer, provider } = createChainStore('metamaskConnection');
const { useWeb3Provider, chainStore, signer, provider } = getChainStore('metamaskConnection'); //Can retreive it later
Finally ethers-svelte
also exports the ethers
library you imported via CDN and the getChainData
function that returns a CAIP-2 formatted representation of the chain ID provided as an input.
import { ethers, getChainData } from 'ethers-svelte';
const ethereumChain = getChainData("1"); //ChainId for ethereum mainnet is 1
console.log(ethereumChain)
{
"name": "Ethereum Mainnet",
"chain": "ETH",
"network": "mainnet",
"icon": "ethereum",
"rpc": ["https://mainnet.infura.io/v3/${INFURA_API_KEY}", "wss://mainnet.infura.io/ws/v3/${INFURA_API_KEY}", "https://api.mycryptoapi.com/eth", "https://cloudflare-eth.com"],
"faucets": [],
"nativeCurrency": { "name": "Ether", "symbol": "ETH", "decimals": 18 },
"infoURL": "https://ethereum.org",
"shortName": "eth",
"chainId": 1,
"networkId": 1,
"slip44": 60,
"ens": { "registry": "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e" },
"explorers": [{ "name": "etherscan", "url": "https://etherscan.io", "standard": "EIP3091" }],
}
Let us know if you are using ethers-svelte
to build an open source Dapp and want to be listed in this section.
Some basic examples can be found in the examples
folder.