From 7005eafbc8fca3084eb973504eeab60cca945748 Mon Sep 17 00:00:00 2001 From: Nicolas Brugneaux Date: Tue, 21 Mar 2023 15:53:05 +0100 Subject: [PATCH 1/5] chore: add migration notes from contractkit --- packages/sdk/contractkit/MIGRATION.md | 144 ++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 packages/sdk/contractkit/MIGRATION.md diff --git a/packages/sdk/contractkit/MIGRATION.md b/packages/sdk/contractkit/MIGRATION.md new file mode 100644 index 00000000000..68cc5d56e20 --- /dev/null +++ b/packages/sdk/contractkit/MIGRATION.md @@ -0,0 +1,144 @@ +# Draft: Migration document from Contractkit + +Hello devs 🌱 this is a migration path away from contractkit following the [public deprecation notice](https://forum.celo.org/t/sunsetting-contractkit/5337/1) of contractkit. This aims to give examples to help you move to either [ethers](https://docs.ethers.org/) or [viem](https://viem.sh/). + +## Initialization + +With ethers: + +```diff +- import Web3 from "web3"; +- import { newKitFromWeb3 } from "@celo/contractkit"; + +- const web3 = new Web3("https://alfajores-forno.celo-testnet.org"); +- const kit = newKitFromWeb3(web3); ++ import { providers } from 'ethers' ++ ++ const provider = new providers.JsonRpcProvider('https://alfajores-forno.celo-testnet.org') +``` + +With viem: + +```diff +- import Web3 from "web3"; +- import { newKitFromWeb3 } from "@celo/contractkit"; +- +- const web3 = new Web3("https://alfajores-forno.celo-testnet.org"); +- const kit = newKitFromWeb3(web3); ++ import { createPublicClient, http } from 'viem' ++ import { celo, celoAlfajores } from 'viem/chains' ++ ++ const client = createPublicClient({ ++ chain: celoAlfajores, // or celo for celo's mainnet ++ transport: http() ++ }) +``` + +## Basic usage + +While we cannot here show all the use-cases of contrackit or ethers or viem, let's try to give an overview of how they can be used for different goals. + +### Get address + +With ethers: + +```diff +- const accounts = await kit.web3.eth.getAccounts(); ++ const accounts = await provider.listAccounts(); +const defaultAccount = accounts[0]; +``` + +With viem: + +```diff +- const accounts = await kit.web3.eth.getAccounts(); ++ const accounts = await client.getAddresses() +const defaultAccount = accounts[0]; +``` + +### Get wallet + +With ethers: + +```diff ++ import { Wallet } from 'ethers' + +- const wallet = kit.getWallet(); ++ const wallet = new Wallet('0x...', provider); +``` + +With viem: + +> [viem does not currently support](<[source](https://viem.sh/docs/ethers-migration.html#viem-11)>) client-side signing (it's coming shortly!) – until then, you can use an Ethers Wallet + +### Provider methods + +With ethers: + +```diff +- const provider = kit.connection.web3.currentProvider +- kit.connection.getBlock(...) +- kit.connection.getTransaction(...) +provider.getBlock(...) +provider.getTransaction(...) +``` + +With viem: + +```diff +- const provider = kit.connection.web3.currentProvider +- kit.connection.getBlock(...) +- kit.connection.getTransaction(...) ++ client.getBlock(...) ++ client.getTransaction(...) +``` + +### Signer methods + +With ethers: + +```diff +- const provider = kit.connection.web3.currentProvider +- const signer = provider.getSigner(kit.connection.defaultAccount) ++ const signer = provider.getSigner(address) ++ signer.sendTransaction(...) ++ signer.signMessage(...) +``` + +With viem: + +```diff +- const provider = kit.connection.web3.currentProvider +- const signer = provider.getSigner(kit.connection.defaultAccount) ++ const [address] = await client.getAddresses() ++ const account = getAccount(address) ++ client.sendTransaction({ account, ... }) +``` + +### Contract interaction + +I'll show the most "basic" interaction, which is a CELO transfer: + +With ethers: + +```diff ++ import { tokenAbi } from './abi.json' +- const CELO = await kit.contracts.getGoldToken(); +- const txReceipt = await CELO.transfer('0x...', amount) ++ const tokenAddress = '0x...' ++ const contract = new ethers.Contract(tokenAddress, tokenAbi, signer); ++ const txReceipt = await contract.transfer('0x...', amount); +``` + +With viem: + +```diff ++ import { tokenAbi } from './abi.json' +- const CELO = await kit.contracts.getGoldToken(); +- const txReceipt = await CELO.transfer('0x...', amount) ++ const tokenAddress = '0x...' ++ const transfer = await client.simulateContract({abi, address: tokenAddress, functionName: 'transfer' }) ++ const txReceipt = await transfer('0x...', amount); +``` + +For more in depth examples, I highly recommend checking out the extensive documentations of both [ethers](https://docs.ethers.org/) and [viem](https://viem.sh/). From a8898e5c6a8a8a8307c85be5df68b5ed49a11f51 Mon Sep 17 00:00:00 2001 From: Nicolas Brugneaux Date: Thu, 1 Jun 2023 15:56:31 +0200 Subject: [PATCH 2/5] chore: split into two files --- .../sdk/contractkit/MIGRATION-TO-ETHERS.md | 108 +++++++++++++++++ .../{MIGRATION.md => MIGRATION-TO-VIEM.md} | 111 ++++++++---------- 2 files changed, 154 insertions(+), 65 deletions(-) create mode 100644 packages/sdk/contractkit/MIGRATION-TO-ETHERS.md rename packages/sdk/contractkit/{MIGRATION.md => MIGRATION-TO-VIEM.md} (53%) diff --git a/packages/sdk/contractkit/MIGRATION-TO-ETHERS.md b/packages/sdk/contractkit/MIGRATION-TO-ETHERS.md new file mode 100644 index 00000000000..e79a2680d09 --- /dev/null +++ b/packages/sdk/contractkit/MIGRATION-TO-ETHERS.md @@ -0,0 +1,108 @@ +# Draft: Migration document from Contractkit + +Hello devs 🌱 this is a migration path away from contractkit following the [public deprecation notice](https://forum.celo.org/t/sunsetting-contractkit/5337/1) of contractkit. This aims to give examples to help you move to [ethers](https://docs.ethers.org/). + +## Initialization + +```diff +- import Web3 from "web3"; +- import { newKitFromWeb3 } from "@celo/contractkit"; + +- const web3 = new Web3("https://alfajores-forno.celo-testnet.org"); +- const kit = newKitFromWeb3(web3); ++ import { providers } from 'ethers' ++ ++ const provider = new providers.JsonRpcProvider('https://alfajores-forno.celo-testnet.org') +``` + +## Basic usage + +While we cannot here show all the use-cases of contrackit or ethers or viem, let's try to give an overview of how they can be used for different goals. + +### Get address + +```diff +- const accounts = await kit.web3.eth.getAccounts(); ++ const accounts = await provider.listAccounts(); +const defaultAccount = accounts[0]; +``` + +### Get wallet + +```diff ++ import { Wallet } from 'ethers' + +- const wallet = kit.getWallet(); ++ const wallet = new Wallet('0x...', provider); +``` + +### Provider methods + +```diff +- const provider = kit.connection.web3.currentProvider +- kit.connection.getBlock(...) +- kit.connection.getTransaction(...) +provider.getBlock(...) +provider.getTransaction(...) +``` + +### Signer methods + +```diff +- const provider = kit.connection.web3.currentProvider +- const signer = provider.getSigner(kit.connection.defaultAccount) ++ const signer = provider.getSigner(address) ++ signer.sendTransaction(...) ++ signer.signMessage(...) +``` + +### Contract interaction + +I'll show the most "basic" interaction, which is a transfer. On CELO, it comes with a twist, you can transfer 4 currencies, CELO, cUSD, cEUR, and cREAL. + +You can get the addresses on these tokens by heading to the explorer and getting their abi and addresses, or you can also use our [registry contract](https://docs.celo.org/developer/contractkit/contracts-wrappers-registry). + +```ts +// this address is constant +const REGISTRY_CONTRACT_ADDRESS = '0x000000000000000000000000000000000000ce10' +const registry = new Contract(REGISTRY_CONTRACT_ADDRESS, registryAbi, wallet) + +async function getToken(token: string) { + const goldTokenAddress = await registry.getAddressForString(token) + return goldTokenAddress +} +async function CeloTokens(): Promise<[string, string][]> { + return Promise.all( + ['GoldToken', 'StableToken', 'StableTokenEUR', 'StableTokenBRL'].map(async (token) => [ + token, + await getToken(token), + ]) + ) +} +``` + +#### Balance + +```diff ++ import { tokenAbi } from './abi.json' + +- const contract = await kit.contracts.getGoldToken(); ++ const tokenAddress = '0x...' // Grabbed from the registry or from the explorer ++ const contract = new ethers.Contract(tokenAddress, tokenAbi, signer); +const balance = await contract.balanceOf(wallet.address); +``` + +#### Transfer + +Then, use the address of the token that you need and call the transfer method of the contract. + +```diff ++ import { tokenAbi } from './abi.json' + +- const contract = await kit.contracts.getGoldToken(); ++ const tokenAddress = '0x...' // Grabbed from the registry or from the explorer ++ const contract = new ethers.Contract(tokenAddress, tokenAbi, signer); +const txReceipt = await contract.transfer('0x...', amount); +``` + +For more in depth examples, I highly recommend checking out the extensive documentations of both [ethers](https://docs.ethers.org/) and [viem](https://viem.sh/). diff --git a/packages/sdk/contractkit/MIGRATION.md b/packages/sdk/contractkit/MIGRATION-TO-VIEM.md similarity index 53% rename from packages/sdk/contractkit/MIGRATION.md rename to packages/sdk/contractkit/MIGRATION-TO-VIEM.md index 68cc5d56e20..27cc837b286 100644 --- a/packages/sdk/contractkit/MIGRATION.md +++ b/packages/sdk/contractkit/MIGRATION-TO-VIEM.md @@ -1,24 +1,9 @@ # Draft: Migration document from Contractkit -Hello devs 🌱 this is a migration path away from contractkit following the [public deprecation notice](https://forum.celo.org/t/sunsetting-contractkit/5337/1) of contractkit. This aims to give examples to help you move to either [ethers](https://docs.ethers.org/) or [viem](https://viem.sh/). +Hello devs 🌱 this is a migration path away from contractkit following the [public deprecation notice](https://forum.celo.org/t/sunsetting-contractkit/5337/1) of contractkit. This aims to give examples to help you move to [viem](https://viem.sh/). ## Initialization -With ethers: - -```diff -- import Web3 from "web3"; -- import { newKitFromWeb3 } from "@celo/contractkit"; - -- const web3 = new Web3("https://alfajores-forno.celo-testnet.org"); -- const kit = newKitFromWeb3(web3); -+ import { providers } from 'ethers' -+ -+ const provider = new providers.JsonRpcProvider('https://alfajores-forno.celo-testnet.org') -``` - -With viem: - ```diff - import Web3 from "web3"; - import { newKitFromWeb3 } from "@celo/contractkit"; @@ -40,14 +25,6 @@ While we cannot here show all the use-cases of contrackit or ethers or viem, let ### Get address -With ethers: - -```diff -- const accounts = await kit.web3.eth.getAccounts(); -+ const accounts = await provider.listAccounts(); -const defaultAccount = accounts[0]; -``` - With viem: ```diff @@ -58,32 +35,21 @@ const defaultAccount = accounts[0]; ### Get wallet -With ethers: - -```diff -+ import { Wallet } from 'ethers' - -- const wallet = kit.getWallet(); -+ const wallet = new Wallet('0x...', provider); -``` - With viem: > [viem does not currently support](<[source](https://viem.sh/docs/ethers-migration.html#viem-11)>) client-side signing (it's coming shortly!) – until then, you can use an Ethers Wallet -### Provider methods - -With ethers: - ```diff -- const provider = kit.connection.web3.currentProvider -- kit.connection.getBlock(...) -- kit.connection.getTransaction(...) -provider.getBlock(...) -provider.getTransaction(...) ++ const walletClient = createWalletClient({ ++ transport: http(celoAlfajores.rpcUrls.default.http[0] as string), ++ chain: celoAlfajores, ++ }); ++ const provider = new JsonRpcProvider(celoAlfajores.rpcUrls.default.http[0]); ++ const wallet = new Wallet(privateKey, provider); ++ const account = getAccount(wallet); ``` -With viem: +### Provider methods ```diff - const provider = kit.connection.web3.currentProvider @@ -95,18 +61,6 @@ With viem: ### Signer methods -With ethers: - -```diff -- const provider = kit.connection.web3.currentProvider -- const signer = provider.getSigner(kit.connection.defaultAccount) -+ const signer = provider.getSigner(address) -+ signer.sendTransaction(...) -+ signer.signMessage(...) -``` - -With viem: - ```diff - const provider = kit.connection.web3.currentProvider - const signer = provider.getSigner(kit.connection.defaultAccount) @@ -117,28 +71,55 @@ With viem: ### Contract interaction -I'll show the most "basic" interaction, which is a CELO transfer: +I'll show the most "basic" interaction, which is a transfer. On CELO, it comes with a twist, you can transfer 4 currencies, CELO, cUSD, cEUR, and cREAL. + +You can get the addresses on these tokens by heading to the explorer and getting their abi and addresses, or you can also use our [registry contract](https://docs.celo.org/developer/contractkit/contracts-wrappers-registry). + +```ts +// this address is constant +const REGISTRY_CONTRACT_ADDRESS = '0x000000000000000000000000000000000000ce10' +const registry = new Contract(REGISTRY_CONTRACT_ADDRESS, registryAbi, wallet) + +async function getToken(token: string) { + const tokenAddress = await registry.getAddressForString(token) + return tokenAddress +} +async function CeloTokens(): Promise<[string, string][]> { + return Promise.all( + ['GoldToken', 'StableToken', 'StableTokenEUR', 'StableTokenBRL'].map(async (token) => [ + token, + await getToken(token), + ]) + ) +} +``` -With ethers: +#### Balance ```diff + import { tokenAbi } from './abi.json' -- const CELO = await kit.contracts.getGoldToken(); -- const txReceipt = await CELO.transfer('0x...', amount) -+ const tokenAddress = '0x...' -+ const contract = new ethers.Contract(tokenAddress, tokenAbi, signer); -+ const txReceipt = await contract.transfer('0x...', amount); + +- const contract = await kit.contracts.getGoldToken(); +- const balance = await contract.balanceOf(wallet.address); ++ const tokenAddress = '0x...' // Grabbed from the registry or from the explorer ++ const balance = await client.readContract({ ++ abi: tokenAbi, ++ address: tokenAddress, ++ functionName: "balanceOf", ++ args: [account.address], ++ }); ``` -With viem: +#### Transfer + +Then, use the address of the token that you need and call the transfer method of the contract. ```diff + import { tokenAbi } from './abi.json' - const CELO = await kit.contracts.getGoldToken(); - const txReceipt = await CELO.transfer('0x...', amount) + const tokenAddress = '0x...' -+ const transfer = await client.simulateContract({abi, address: tokenAddress, functionName: 'transfer' }) -+ const txReceipt = await transfer('0x...', amount); ++ const transfer = await walletClient.simulateContract({abi, address: tokenAddress, functionName: 'transfer', args: ['0x...', amount] }) ``` For more in depth examples, I highly recommend checking out the extensive documentations of both [ethers](https://docs.ethers.org/) and [viem](https://viem.sh/). From 3ebb4a6194026e8a14a1dfd72a303a4f594af3ff Mon Sep 17 00:00:00 2001 From: Nicolas Brugneaux Date: Thu, 1 Jun 2023 16:33:55 +0200 Subject: [PATCH 3/5] docs: adjust viem docs using stcelo as feedback --- .../sdk/contractkit/MIGRATION-TO-ETHERS.md | 2 +- packages/sdk/contractkit/MIGRATION-TO-VIEM.md | 128 ++++++++++++++---- 2 files changed, 104 insertions(+), 26 deletions(-) diff --git a/packages/sdk/contractkit/MIGRATION-TO-ETHERS.md b/packages/sdk/contractkit/MIGRATION-TO-ETHERS.md index e79a2680d09..f5171d5b5de 100644 --- a/packages/sdk/contractkit/MIGRATION-TO-ETHERS.md +++ b/packages/sdk/contractkit/MIGRATION-TO-ETHERS.md @@ -60,7 +60,7 @@ provider.getTransaction(...) I'll show the most "basic" interaction, which is a transfer. On CELO, it comes with a twist, you can transfer 4 currencies, CELO, cUSD, cEUR, and cREAL. -You can get the addresses on these tokens by heading to the explorer and getting their abi and addresses, or you can also use our [registry contract](https://docs.celo.org/developer/contractkit/contracts-wrappers-registry). +You can get the addresses on these tokens by heading to the explorer and getting their abi and addresses, or you can also use our [registry contract](https://docs.celo.org/developer/contractkit/contracts-wrappers-registry). You can also use the [`@celo/abis`](https://www.npmjs.com/package/@celo/abis) package to get the ABIs directly. ```ts // this address is constant diff --git a/packages/sdk/contractkit/MIGRATION-TO-VIEM.md b/packages/sdk/contractkit/MIGRATION-TO-VIEM.md index 27cc837b286..1770582ce71 100644 --- a/packages/sdk/contractkit/MIGRATION-TO-VIEM.md +++ b/packages/sdk/contractkit/MIGRATION-TO-VIEM.md @@ -13,7 +13,7 @@ Hello devs 🌱 this is a migration path away from contractkit following the [pu + import { createPublicClient, http } from 'viem' + import { celo, celoAlfajores } from 'viem/chains' + -+ const client = createPublicClient({ ++ const publicClient = createPublicClient({ + chain: celoAlfajores, // or celo for celo's mainnet + transport: http() + }) @@ -29,7 +29,7 @@ With viem: ```diff - const accounts = await kit.web3.eth.getAccounts(); -+ const accounts = await client.getAddresses() ++ const accounts = await publicClient.getAddresses() const defaultAccount = accounts[0]; ``` @@ -37,16 +37,21 @@ const defaultAccount = accounts[0]; With viem: -> [viem does not currently support](<[source](https://viem.sh/docs/ethers-migration.html#viem-11)>) client-side signing (it's coming shortly!) – until then, you can use an Ethers Wallet +> [viem does not full support](<[source](https://viem.sh/docs/ethers-migration.html#viem-11)>) client-side signing (it's coming shortly!) – until then, you can use an Ethers Wallet, however it does support `signMessage` and `signTypedData` already. ```diff ++ import { privateKeyToAccount } from 'viem/accounts' ++ ++ const privateKey = "0x..."; + const walletClient = createWalletClient({ + transport: http(celoAlfajores.rpcUrls.default.http[0] as string), + chain: celoAlfajores, + }); -+ const provider = new JsonRpcProvider(celoAlfajores.rpcUrls.default.http[0]); -+ const wallet = new Wallet(privateKey, provider); -+ const account = getAccount(wallet); ++ const account = privateKeyToAccount(privateKey); ++ await walletClient.signMessage({ ++ account, ++ message: 'hello world', ++ }) ``` ### Provider methods @@ -55,8 +60,26 @@ With viem: - const provider = kit.connection.web3.currentProvider - kit.connection.getBlock(...) - kit.connection.getTransaction(...) -+ client.getBlock(...) -+ client.getTransaction(...) ++ const block = await publicClient.getBlock() ++ /** ++ * { ++ * baseFeePerGas: 10000n, ++ * number: 1234n, ++ * parentHash: "0x....", ++ * ... ++ * } ++ */ ++ const tx = await publicClient.getTransaction({ ++ hash: "0x...", ++ }) ++ /** ++ * { ++ * blockHash: '0x...', ++ * blockNumber: 1234n, ++ * from: '0x...', ++ * ... ++ * } ++ */ ``` ### Signer methods @@ -64,31 +87,33 @@ With viem: ```diff - const provider = kit.connection.web3.currentProvider - const signer = provider.getSigner(kit.connection.defaultAccount) -+ const [address] = await client.getAddresses() -+ const account = getAccount(address) -+ client.sendTransaction({ account, ... }) ++ const [account] = await walletClient.getAddresses() ++ const hash = await walletClient.sendTransaction({ account, to: "0x...", value: 1000n }) ``` ### Contract interaction I'll show the most "basic" interaction, which is a transfer. On CELO, it comes with a twist, you can transfer 4 currencies, CELO, cUSD, cEUR, and cREAL. -You can get the addresses on these tokens by heading to the explorer and getting their abi and addresses, or you can also use our [registry contract](https://docs.celo.org/developer/contractkit/contracts-wrappers-registry). +You can get the addresses on these tokens by heading to the explorer and getting their abi and addresses, or you can also use our [registry contract](https://docs.celo.org/developer/contractkit/contracts-wrappers-registry). You can also use the [`@celo/abis`](https://www.npmjs.com/package/@celo/abis) package to get the ABIs directly. ```ts +import { getContract } from 'viem' +import { registryABI } from '@celo/abis/types/viem' + // this address is constant const REGISTRY_CONTRACT_ADDRESS = '0x000000000000000000000000000000000000ce10' -const registry = new Contract(REGISTRY_CONTRACT_ADDRESS, registryAbi, wallet) +const registryContract = getContract({ + address: REGISTRY_CONTRACT_ADDRESS, + abi: registryABI, + publicClient, +}) -async function getToken(token: string) { - const tokenAddress = await registry.getAddressForString(token) - return tokenAddress -} async function CeloTokens(): Promise<[string, string][]> { return Promise.all( ['GoldToken', 'StableToken', 'StableTokenEUR', 'StableTokenBRL'].map(async (token) => [ token, - await getToken(token), + await registryContract.read.getAddressForString(token), ]) ) } @@ -97,14 +122,15 @@ async function CeloTokens(): Promise<[string, string][]> { #### Balance ```diff -+ import { tokenAbi } from './abi.json' ++ import { stableTokenABI } from '@celo/abis/types/viem' - const contract = await kit.contracts.getGoldToken(); - const balance = await contract.balanceOf(wallet.address); -+ const tokenAddress = '0x...' // Grabbed from the registry or from the explorer ++ const tokenAddresses = await CeloTokens(); ++ const cUSD = tokenAddresses["StableToken] + const balance = await client.readContract({ + abi: tokenAbi, -+ address: tokenAddress, ++ address: cUSD, + functionName: "balanceOf", + args: [account.address], + }); @@ -115,11 +141,63 @@ async function CeloTokens(): Promise<[string, string][]> { Then, use the address of the token that you need and call the transfer method of the contract. ```diff -+ import { tokenAbi } from './abi.json' ++ import { stableTokenABI } from '@celo/abis/types/viem' - const CELO = await kit.contracts.getGoldToken(); - const txReceipt = await CELO.transfer('0x...', amount) -+ const tokenAddress = '0x...' -+ const transfer = await walletClient.simulateContract({abi, address: tokenAddress, functionName: 'transfer', args: ['0x...', amount] }) ++ const tokenAddresses = await CeloTokens(); ++ const cUSD = tokenAddresses["StableToken] ++ const { request } = await walletClient.simulateContract({ ++ abi, ++ address: cUSD, ++ functionName: 'transfer', ++ args: [ ++ '0x...', // to address ++ amount: 1000n, ++ ], ++ account: '0x...', // from address ++ }) ++ const hash = await walletClient.sendTransaction(request); ``` -For more in depth examples, I highly recommend checking out the extensive documentations of both [ethers](https://docs.ethers.org/) and [viem](https://viem.sh/). +#### Multicall + +While contractkit didn't directly support multicall, you could use libraries such as `@dopex-io/web3-multicall` as such: + +```ts +import Multicall from '@dopex-io/web3-multicall' +const MULTICALL_ADDRESS = '0xcA11bde05977b3631167028862bE2a173976CA11' // same on mainnet and alfajores +const multicall = new Multicall({ + provider, + chainId, + multicallAddress: MULTICALL_ADDRESS, +}) +const governance = await kit.contracts._web3Contracts.getGovernance() +const stageTxs = _dequeue.map((proposalId) => governance.methods.getProposalStage(proposalId)) +const stages: string[] = await multicall.aggregate(stageTxs) +``` + +You now can use `viem` directly to multicall since they have the address configured in the `viem/chains` files. + +```ts +const governanceAddress = await registryContract.read.getAddressForString(['Governance']) +const governanceContract = getContract({ + address: governanceAddress, + abi: governanceABI, + publicClient, +}) +const _dequeue = await governanceContract.read.getDequeue() +const stageCalls = _dequeue.map((proposalId) => ({ + address: governanceAddress, + abi: governanceABI, + functionName: 'getProposalStage', + args: [proposalId], +})) +const stages = (await publicClient.multicall({ contracts: stageCalls })).map((x) => x.result) +``` + +### Further reading + +For more in depth examples and documentation about viem specifically, I highly recommend checking out the extensive documentations of [viem](https://viem.sh/). + +Another interesting application to help you migrate could be StCelo-v2. +You can checkout the changes going from `react-celo` + `contractkit` to `rainbowkit` + `wagmi` + `viem` in [this pull-request](https://github.com/celo-org/staked-celo-web-app/pull/129). From 8e2e2c5c53bd7f7c5df4f2a64974555ad0250615 Mon Sep 17 00:00:00 2001 From: Nicolas Brugneaux Date: Thu, 1 Jun 2023 17:19:22 +0200 Subject: [PATCH 4/5] chore: remove deprecation note --- packages/sdk/contractkit/MIGRATION-TO-ETHERS.md | 2 +- packages/sdk/contractkit/MIGRATION-TO-VIEM.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/sdk/contractkit/MIGRATION-TO-ETHERS.md b/packages/sdk/contractkit/MIGRATION-TO-ETHERS.md index f5171d5b5de..b229ea9cb21 100644 --- a/packages/sdk/contractkit/MIGRATION-TO-ETHERS.md +++ b/packages/sdk/contractkit/MIGRATION-TO-ETHERS.md @@ -1,6 +1,6 @@ # Draft: Migration document from Contractkit -Hello devs 🌱 this is a migration path away from contractkit following the [public deprecation notice](https://forum.celo.org/t/sunsetting-contractkit/5337/1) of contractkit. This aims to give examples to help you move to [ethers](https://docs.ethers.org/). +Hello devs 🌱 this is a migration path away from contractkit. This aims to give examples to help you move to [ethers](https://docs.ethers.org/). ## Initialization diff --git a/packages/sdk/contractkit/MIGRATION-TO-VIEM.md b/packages/sdk/contractkit/MIGRATION-TO-VIEM.md index 1770582ce71..7ebbe28bde8 100644 --- a/packages/sdk/contractkit/MIGRATION-TO-VIEM.md +++ b/packages/sdk/contractkit/MIGRATION-TO-VIEM.md @@ -1,6 +1,6 @@ # Draft: Migration document from Contractkit -Hello devs 🌱 this is a migration path away from contractkit following the [public deprecation notice](https://forum.celo.org/t/sunsetting-contractkit/5337/1) of contractkit. This aims to give examples to help you move to [viem](https://viem.sh/). +Hello devs 🌱 this is a migration path away from contractkit. This aims to give examples to help you move to [viem](https://viem.sh/). ## Initialization From a5dac0373858f33f5867e0a516d5d921f285e7f2 Mon Sep 17 00:00:00 2001 From: Nicolas Brugneaux Date: Tue, 26 Sep 2023 09:05:16 +0200 Subject: [PATCH 5/5] Update MIGRATION-TO-VIEM.md --- packages/sdk/contractkit/MIGRATION-TO-VIEM.md | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/packages/sdk/contractkit/MIGRATION-TO-VIEM.md b/packages/sdk/contractkit/MIGRATION-TO-VIEM.md index 7ebbe28bde8..85666524721 100644 --- a/packages/sdk/contractkit/MIGRATION-TO-VIEM.md +++ b/packages/sdk/contractkit/MIGRATION-TO-VIEM.md @@ -195,6 +195,35 @@ const stageCalls = _dequeue.map((proposalId) => ({ const stages = (await publicClient.multicall({ contracts: stageCalls })).map((x) => x.result) ``` +#### Fee Currency + +With Viem's built in Celo transaction serializer and Celo block/transaction formatters it is easy to build a wallet that supports Celo's ability to pay gas fees with various erc20 tokens. Simply, import a Celo chain from `viem/chain` and pass it to Viem's `createWalletClient`. Once the client is created you can add the feeCurrency field to your transaction with the address of the token you want to use for gas. + +```ts + import { celo } from 'viem/chains' + import { createWalletClient, privateKeyToAccount, type SendTransactionParameters, http } from 'viem' + + const account = privateKeyToAccount(PRIVATE_KEY) + + // ALFAJORES ADDRESS: Celo Mainnet can be fetched from the registry + const cUSDAddress = '0x874069Fa1Eb16D44d622F2e0Ca25eeA172369bC1' + + const localAccountClient = createWalletClient({ + account, + chain: celo, + }) + + const sendTransaction = (tx: SendTransactionParameters) => { + return localAccountClient.sendTransaction(tx) + } + + const hash = await sendTransaction({ + feeCurrency: cUSDAddress, + value: BigInt(100000000), + to: '0x22579CA45eE22E2E16dDF72D955D6cf4c767B0eF', + }) +``` + ### Further reading For more in depth examples and documentation about viem specifically, I highly recommend checking out the extensive documentations of [viem](https://viem.sh/).