From 49172b3fcd87ce23bd676b8b7d12717eb65bafa2 Mon Sep 17 00:00:00 2001 From: Aleix Date: Thu, 9 Nov 2023 13:10:09 +0100 Subject: [PATCH] Upgrade to wagmi 1, rainbowkit 1 and viem (instead of ethers) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Upgrading to wagmi 1, rainbowkit 1 and viem * Bugfix provider * viem doesn't seem to work with other TS versions than 5.0.2 * Updated inputsWallet & connector --------- Co-authored-by: Òscar Casajuana --- packages/rainbowkit-wallets/package.json | 14 +++--- .../src/lib/inputsWallet.tsx | 7 +-- .../src/lib/localStorageWallet.ts | 21 +++++--- .../src/lib/oAuthWallet.tsx | 7 +-- .../src/wagmi/inputsConnector.ts | 9 ++-- .../src/wagmi/localStorageConnector.ts | 50 +++++++++---------- .../src/wagmi/oAuthConnector.ts | 11 ++-- 7 files changed, 64 insertions(+), 55 deletions(-) diff --git a/packages/rainbowkit-wallets/package.json b/packages/rainbowkit-wallets/package.json index 876c060e..7c0869a6 100644 --- a/packages/rainbowkit-wallets/package.json +++ b/packages/rainbowkit-wallets/package.json @@ -17,22 +17,22 @@ "clean": "rm -rf dist .turbo node_modules" }, "peerDependencies": { - "@rainbow-me/rainbowkit": "^0.12.18", - "@wagmi/core": "^0.10.17", - "ethers": "^5", - "wagmi": "^0.12" + "@rainbow-me/rainbowkit": "^1.1.3", + "@wagmi/core": "^1.4.5", + "wagmi": "^1.4.5" }, "devDependencies": { + "@rainbow-me/rainbowkit": "^1.1.3", "@types/react-modal": "^3.16.0", + "@wagmi/core": "^1.4.5", "clean-package": "^2.2.0", - "ethers": "^5", "localforage": "^1.10.0", "react-modal": "^3.16.1", "tsconfig": "*", - "typescript": "^4.9.5", + "typescript": "5.0.2", "vite": "^4.4.2", "vite-plugin-dts": "^3.2.0", - "wagmi": "^0.12" + "wagmi": "^1.4.5" }, "clean-package": "../../clean-package.config.json" } diff --git a/packages/rainbowkit-wallets/src/lib/inputsWallet.tsx b/packages/rainbowkit-wallets/src/lib/inputsWallet.tsx index 15594067..5315bf97 100644 --- a/packages/rainbowkit-wallets/src/lib/inputsWallet.tsx +++ b/packages/rainbowkit-wallets/src/lib/inputsWallet.tsx @@ -1,7 +1,8 @@ -import { ethers } from 'ethers' import { createRoot } from 'react-dom/client' import { CreateWalletModal } from '../components/CreateWalletModal' import localStorageWallet from './localStorageWallet' +import { WalletClient } from 'viem' +import { WindowProvider } from 'wagmi' /** * This class is used to create a wallet from a form @@ -10,7 +11,7 @@ export class inputsWallet extends localStorageWallet { private data: any private cancel: boolean = false - async create(): Promise { + async create(provider: WindowProvider): Promise { // Create a div to render the modal const myDiv = document.createElement('div') myDiv.setAttribute('id', 'myDiv' + Math.random()) @@ -37,6 +38,6 @@ export class inputsWallet extends localStorageWallet { throw new Error('User cancelled') } - return await localStorageWallet.createWallet(JSON.stringify(this.data)) + return await localStorageWallet.createWallet(JSON.stringify(this.data), provider) } } diff --git a/packages/rainbowkit-wallets/src/lib/localStorageWallet.ts b/packages/rainbowkit-wallets/src/lib/localStorageWallet.ts index 5ba725f2..50d06b59 100644 --- a/packages/rainbowkit-wallets/src/lib/localStorageWallet.ts +++ b/packages/rainbowkit-wallets/src/lib/localStorageWallet.ts @@ -1,16 +1,18 @@ -import { Wallet } from 'ethers' -import { keccak256 } from 'ethers/lib/utils.js' import { Buffer } from 'buffer' +import { keccak256, createWalletClient, custom, publicActions, WalletClient } from 'viem' +import { privateKeyToAccount } from 'viem/accounts' +import { mainnet } from 'wagmi' +import { WindowProvider } from '@wagmi/connectors' export default class localStorageWallet { static storageItemName = 'localstorage-wallet-seed' - public static async getWallet(): Promise { + public static async getWallet(provider: WindowProvider): Promise { try { const value: string = localStorage.getItem(this.storageItemName) as string if (!value) return undefined - return this.createWallet(value) + return this.createWallet(value, provider) } catch (err) { console.error('failed to generate wallet:', err) } @@ -18,13 +20,20 @@ export default class localStorageWallet { return undefined } - public static async createWallet(data: string | string[]): Promise { + public static async createWallet(data: string | string[], provider: WindowProvider): Promise { const inputs = Array.isArray(data) ? data : [data] const hash = inputs.reduce((acc, curr) => acc + curr, '') localStorage.setItem(this.storageItemName, hash) - return new Wallet(keccak256(Buffer.from(hash))) + const account = privateKeyToAccount(keccak256(Buffer.from(hash))) + const client = createWalletClient({ + account, + chain: mainnet, + transport: custom(provider), + }).extend(publicActions) + + return client } public static async deleteWallet(): Promise { diff --git a/packages/rainbowkit-wallets/src/lib/oAuthWallet.tsx b/packages/rainbowkit-wallets/src/lib/oAuthWallet.tsx index af023f7c..117a4086 100644 --- a/packages/rainbowkit-wallets/src/lib/oAuthWallet.tsx +++ b/packages/rainbowkit-wallets/src/lib/oAuthWallet.tsx @@ -1,5 +1,6 @@ -import { ethers } from 'ethers' import localStorageWallet from './localStorageWallet' +import { WalletClient } from 'viem' +import { WindowProvider } from '@wagmi/connectors' /** * This class is used to create a wallet from an external service (OAuth) @@ -17,7 +18,7 @@ export class oAuthWallet extends localStorageWallet { this.oAuthServiceProvider = oAuthServiceProvider } - async create(): Promise { + async create(provider: WindowProvider): Promise { // Open the login popup const url = this.oAuthServiceUrl + (this.oAuthServiceProvider ? `?provider=${this.oAuthServiceProvider}` : '') this.openLoginPopup(url) @@ -44,7 +45,7 @@ export class oAuthWallet extends localStorageWallet { throw new Error('User cancelled') } - return await localStorageWallet.createWallet(JSON.stringify(this.data)) + return await localStorageWallet.createWallet(JSON.stringify(this.data), provider) } private async openLoginPopup(url: string) { diff --git a/packages/rainbowkit-wallets/src/wagmi/inputsConnector.ts b/packages/rainbowkit-wallets/src/wagmi/inputsConnector.ts index f7d69c08..0e9cd270 100644 --- a/packages/rainbowkit-wallets/src/wagmi/inputsConnector.ts +++ b/packages/rainbowkit-wallets/src/wagmi/inputsConnector.ts @@ -1,5 +1,6 @@ import { inputsWallet } from '../lib/inputsWallet' import { localStorageConnector } from './localStorageConnector' +import { WindowProvider } from '@wagmi/connectors' const IS_SERVER = typeof window === 'undefined' @@ -9,13 +10,13 @@ export class inputsConnector extends localStorageConnector { readonly name = 'Inputs' protected async createWallet() { - let wallet = await inputsWallet.getWallet() + const provider = (await this.getProvider()) as WindowProvider + let wallet = await inputsWallet.getWallet(provider) if (!wallet) { const w = new inputsWallet() - wallet = await w.create() + wallet = await w.create(provider) } - wallet.connect(await this.getProvider()) - this.wallet = wallet + this.wallet = wallet?.account } } diff --git a/packages/rainbowkit-wallets/src/wagmi/localStorageConnector.ts b/packages/rainbowkit-wallets/src/wagmi/localStorageConnector.ts index 68188af4..2d29635e 100644 --- a/packages/rainbowkit-wallets/src/wagmi/localStorageConnector.ts +++ b/packages/rainbowkit-wallets/src/wagmi/localStorageConnector.ts @@ -1,7 +1,7 @@ -import { Address, Chain, Connector, UserRejectedRequestError, normalizeChainId } from '@wagmi/core' -import { Signer, Wallet, ethers, getDefaultProvider } from 'ethers' -import { getAddress } from 'ethers/lib/utils.js' -import { ConnectorData } from 'wagmi' +import { type Address, UserRejectedRequestError, getAddress, Account, Chain } from 'viem' +import { ConnectorData, ConnectorNotFoundError, Connector } from 'wagmi' +import { InjectedConnector } from '@wagmi/connectors/injected' +import { WindowProvider, normalizeChainId } from '@wagmi/connectors' import localStorageWallet from '../lib/localStorageWallet' const IS_SERVER = typeof window === 'undefined' @@ -9,14 +9,14 @@ const IS_SERVER = typeof window === 'undefined' /** * A connector that uses the local storage to store seed for a deterministic wallet generation */ -export class localStorageConnector extends Connector { +export class localStorageConnector extends InjectedConnector { ready = !IS_SERVER readonly id: string = 'localStorageConnector' readonly name: string = 'localStorage' protected chainId: number | undefined - protected provider: ethers.providers.BaseProvider | undefined - protected wallet: Wallet | undefined + protected provider: WindowProvider | undefined + protected wallet: Account | undefined constructor(config: { chains: Chain[]; options: any }) { super(config) @@ -30,8 +30,8 @@ export class localStorageConnector extends Connector { if (!this.wallet) { await this.createWallet() } + const account = await this.getAccount() - const provider = await this.getProvider() const chainId = await this.getChainId() const cdata: ConnectorData = { @@ -40,12 +40,11 @@ export class localStorageConnector extends Connector { id: chainId, unsupported: false, }, - provider: provider as any, } return cdata } catch (error) { - throw new UserRejectedRequestError(error) + throw new UserRejectedRequestError(error as Error) } } @@ -53,20 +52,12 @@ export class localStorageConnector extends Connector { const signer = await this.getSigner() if (!signer) throw new Error('No signer available') - const account = await signer.getAddress() + const account = signer.address if (account.startsWith('0x')) return account as Address return `0x${account}` } - async getProvider() { - if (!this.provider) { - //TODO: not sure this should be the default provider - this.provider = getDefaultProvider() - } - return this.provider - } - - async getSigner(): Promise { + async getSigner(): Promise { return this.wallet } @@ -80,26 +71,31 @@ export class localStorageConnector extends Connector { } async isAuthorized() { - let wallet = await localStorageWallet.getWallet() + const provider = await this.getProvider() + if (!provider) throw new ConnectorNotFoundError() + + let wallet = await localStorageWallet.getWallet(provider) if (!wallet) return false - wallet.connect(await this.getProvider()) - this.wallet = wallet + this.wallet = wallet.account - return true + const account = await this.getAccount() + return !!account } - protected onDisconnect(): void { + onDisconnect = async (error: Error): Promise => { this.emit('disconnect') + return Promise.resolve() } - protected onAccountsChanged(accounts: string[]): void { + onAccountsChanged = (accounts: string[]): void => { if (accounts.length === 0) this.emit('disconnect') else this.emit('change', { account: getAddress(accounts[0]) }) } - protected onChainChanged(chainId: string | number): void { + onChainChanged = (chainId: string | number): void => { const id = normalizeChainId(chainId) + const unsupported = this.isChainUnsupported(id) this.emit('change', { chain: { id, unsupported } }) } diff --git a/packages/rainbowkit-wallets/src/wagmi/oAuthConnector.ts b/packages/rainbowkit-wallets/src/wagmi/oAuthConnector.ts index 6680b5b0..5500cce4 100644 --- a/packages/rainbowkit-wallets/src/wagmi/oAuthConnector.ts +++ b/packages/rainbowkit-wallets/src/wagmi/oAuthConnector.ts @@ -1,6 +1,7 @@ -import { Chain } from '@wagmi/core' +import { Chain } from 'wagmi' import { oAuthWallet } from '../lib/oAuthWallet' import { localStorageConnector } from './localStorageConnector' +import { WindowProvider } from '@wagmi/connectors' const IS_SERVER = typeof window === 'undefined' @@ -27,13 +28,13 @@ export class oAuthConnector extends localStorageConnector { } protected async createWallet() { - let wallet = await oAuthWallet.getWallet() + const provider = (await this.getProvider()) as WindowProvider + let wallet = await oAuthWallet.getWallet(provider) if (!wallet) { const w = new oAuthWallet(this.oAuthServiceUrl, this.oAuthServiceProvider) - wallet = await w.create() + wallet = await w.create(provider) } - wallet.connect(await this.getProvider()) - this.wallet = wallet + this.wallet = wallet?.account } }