Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

F/rainbowkit wagmi 1 #111

Merged
merged 4 commits into from
Nov 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
}
}