Skip to content

Commit

Permalink
Upgrade to wagmi 1, rainbowkit 1 and viem (instead of ethers)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
nigeon and elboletaire authored Nov 9, 2023
1 parent 8139cab commit 49172b3
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 55 deletions.
14 changes: 7 additions & 7 deletions packages/rainbowkit-wallets/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
7 changes: 4 additions & 3 deletions packages/rainbowkit-wallets/src/lib/inputsWallet.tsx
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -10,7 +11,7 @@ export class inputsWallet extends localStorageWallet {
private data: any
private cancel: boolean = false

async create(): Promise<ethers.Wallet> {
async create(provider: WindowProvider): Promise<WalletClient> {
// Create a div to render the modal
const myDiv = document.createElement('div')
myDiv.setAttribute('id', 'myDiv' + Math.random())
Expand All @@ -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)
}
}
21 changes: 15 additions & 6 deletions packages/rainbowkit-wallets/src/lib/localStorageWallet.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,39 @@
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<Wallet | undefined> {
public static async getWallet(provider: WindowProvider): Promise<WalletClient | undefined> {
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)
}

return undefined
}

public static async createWallet(data: string | string[]): Promise<Wallet> {
public static async createWallet(data: string | string[], provider: WindowProvider): Promise<WalletClient> {
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<void> {
Expand Down
7 changes: 4 additions & 3 deletions packages/rainbowkit-wallets/src/lib/oAuthWallet.tsx
Original file line number Diff line number Diff line change
@@ -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)
Expand All @@ -17,7 +18,7 @@ export class oAuthWallet extends localStorageWallet {
this.oAuthServiceProvider = oAuthServiceProvider
}

async create(): Promise<ethers.Wallet> {
async create(provider: WindowProvider): Promise<WalletClient> {
// Open the login popup
const url = this.oAuthServiceUrl + (this.oAuthServiceProvider ? `?provider=${this.oAuthServiceProvider}` : '')
this.openLoginPopup(url)
Expand All @@ -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) {
Expand Down
9 changes: 5 additions & 4 deletions packages/rainbowkit-wallets/src/wagmi/inputsConnector.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { inputsWallet } from '../lib/inputsWallet'
import { localStorageConnector } from './localStorageConnector'
import { WindowProvider } from '@wagmi/connectors'

const IS_SERVER = typeof window === 'undefined'

Expand All @@ -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
}
}
50 changes: 23 additions & 27 deletions packages/rainbowkit-wallets/src/wagmi/localStorageConnector.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
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'

/**
* 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)
Expand All @@ -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 = {
Expand All @@ -40,33 +40,24 @@ 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)
}
}

async getAccount(): Promise<Address> {
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<Signer | undefined> {
async getSigner(): Promise<Account | undefined> {
return this.wallet
}

Expand All @@ -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<void> => {
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 } })
}
Expand Down
11 changes: 6 additions & 5 deletions packages/rainbowkit-wallets/src/wagmi/oAuthConnector.ts
Original file line number Diff line number Diff line change
@@ -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'

Expand All @@ -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
}
}

0 comments on commit 49172b3

Please sign in to comment.