Skip to content

Commit

Permalink
🧶 WalletConnectV2 connector use @walletconnect/modal (#1118)
Browse files Browse the repository at this point in the history
  • Loading branch information
yivlad authored Jul 4, 2023
1 parent 065365e commit 819e1bf
Show file tree
Hide file tree
Showing 13 changed files with 725 additions and 319 deletions.
5 changes: 5 additions & 0 deletions .changeset/bright-zebras-watch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@usedapp/wallet-connect-v2-connector': patch
---

Use @wallectconnect/modal instead of @web3modal/standalone
6 changes: 4 additions & 2 deletions packages/connectors/wallet-connect-v2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@
"access": "public"
},
"dependencies": {
"@walletconnect/encoding": "^1.0.2",
"@walletconnect/ethereum-provider": "^2.8.6",
"@walletconnect/modal": "^2.5.9",
"@walletconnect/sign-client": "^2.3.3",
"@walletconnect/universal-provider": "^2.3.3",
"@web3modal/standalone": "^2.1.1"
"@walletconnect/universal-provider": "^2.3.3"
},
"devDependencies": {
"@usedapp/core": "workspace:*",
Expand Down
100 changes: 19 additions & 81 deletions packages/connectors/wallet-connect-v2/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Chain, Connector, ConnectorEvent, ConnectorUpdateData, DEFAULT_SUPPORTED_CHAINS } from '@usedapp/core'
import UniversalProvider from "@walletconnect/universal-provider"
import { Web3Modal } from "@web3modal/standalone"
import { Chain, Connector, ConnectorEvent, ConnectorUpdateData } from '@usedapp/core'
import EthereumProvider from "@walletconnect/ethereum-provider"
import { providers } from 'ethers'

interface WalletConnectV2ConnectorOptions {
Expand All @@ -16,44 +15,31 @@ export class WalletConnectV2Connector implements Connector {

readonly update = new ConnectorEvent<ConnectorUpdateData>()

private universalProvider: UniversalProvider | undefined
private web3Modal: Web3Modal | undefined
private readonly chains: string[]
private readonly methods: string[]
private readonly events: string[]
private ethereumProvider: EthereumProvider | undefined
private readonly chains: number[]

constructor(private readonly opts: WalletConnectV2ConnectorOptions) {
this.chains = opts.chains.map((chain) => `eip155:${chain.chainId}`)
this.methods = [
"eth_sendTransaction",
"eth_signTransaction",
"eth_sign",
"personal_sign",
"eth_signTypedData",
]
this.events = ["chainChanged", "accountsChanged"]
this.chains = opts.chains.map((chain) => chain.chainId)
}

private async init() {
this.universalProvider = await UniversalProvider.init({
this.ethereumProvider = await EthereumProvider.init({
projectId: this.opts.projectId,
chains: this.chains,
showQrModal: true,
})
}

async connectEagerly(): Promise<void> {
try {
await this.init()
if (!this.universalProvider) {
if (!this.ethereumProvider) {
throw new Error('Could not initialize connector')
}
const accounts = await this.universalProvider.request({ method: "eth_accounts" }) as string[]
const accounts = await this.ethereumProvider.request({ method: "eth_accounts" }) as string[]

if (this.opts.checkGnosisSafe && accounts[0]) {
await this.tryToGuessGnosisChain(accounts[0])
}

const chainId = await this.universalProvider.request({ method: "eth_chainId" }) as any
this.provider = new providers.Web3Provider(this.universalProvider)
const chainId = await this.ethereumProvider.request({ method: "eth_chainId" }) as any
this.provider = new providers.Web3Provider(this.ethereumProvider)
this.update.emit({ chainId: parseInt(chainId), accounts })
} catch (e) {
console.debug(e)
Expand All @@ -63,74 +49,26 @@ export class WalletConnectV2Connector implements Connector {
async activate(): Promise<void> {
try {
await this.init()
if (!this.universalProvider) {
if (!this.ethereumProvider) {
throw new Error('Could not initialize connector')
}
this.web3Modal = new Web3Modal({
walletConnectVersion: 2,
projectId: this.opts.projectId,
standaloneChains: this.chains,
})

this.universalProvider.on("display_uri", (uri: string) => {
this.web3Modal?.openModal({ uri, standaloneChains: this.chains })
})
await this.universalProvider.connect({
namespaces: {
eip155: {
methods: this.methods,
chains: this.chains,
events: this.events,
rpcMap: this.opts.rpcMap,
},
},
await this.ethereumProvider.connect({
chains: this.chains,
})
this.web3Modal?.closeModal()

const accounts = await this.universalProvider.request({ method: "eth_accounts" }) as string[]
const accounts = await this.ethereumProvider.request({ method: "eth_accounts" }) as string[]

if (this.opts.checkGnosisSafe && accounts[0]) {
await this.tryToGuessGnosisChain(accounts[0])
}

const chainId = await this.universalProvider.request({ method: "eth_chainId" }) as any
this.provider = new providers.Web3Provider(this.universalProvider)
const chainId = await this.ethereumProvider.request({ method: "eth_chainId" }) as any
this.provider = new providers.Web3Provider(this.ethereumProvider)
this.update.emit({ chainId: parseInt(chainId), accounts })
} catch (e: any) {
console.log(e)
throw new Error('Could not activate connector: ' + (e.message ?? ''))
}
}

private async tryToGuessGnosisChain(safeAddress: string) {
const resolvedChainIds: number[] = []
await Promise.all(this.opts.chains.map(async ({ chainId }) => {
const chainName = DEFAULT_SUPPORTED_CHAINS
.find(({ chainId: id }) => id === chainId)
?.chainName
?.toLowerCase()
if (!chainName) {
return
}
try {
const response = await fetch(
`https://safe-transaction.${chainName}.gnosis.io/api/v1/safes/${safeAddress}/`
)
if (response.ok) {
resolvedChainIds.push(chainId)
}
} catch {} // eslint-disable-line no-empty
}))
if (resolvedChainIds.length > 0) {
// if found on multiple chains, set the default to the first one
// preserving the order in which the chains are defined
const defaultChainId = this.opts.chains.filter(({ chainId }) => resolvedChainIds.includes(chainId))[0].chainId
this.universalProvider?.setDefaultChain(`eip155:${defaultChainId}`)
}
}

async deactivate(): Promise<void> {
this.universalProvider?.disconnect()
this.ethereumProvider?.disconnect()
this.provider = undefined
}
}
4 changes: 4 additions & 0 deletions packages/connectors/wallet-connect-v2/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
"compilerOptions": {
"outDir": "dist",
"module": "commonjs",
"lib": [
"ES2015",
"DOM"
],
"composite": true,
"declaration": true,
"sourceMap": true,
Expand Down
1 change: 1 addition & 0 deletions packages/docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"@docusaurus/core": "2.0.0-beta.17",
"@docusaurus/preset-classic": "2.0.0-beta.17",
"@docusaurus/remark-plugin-npm2yarn": "^2.0.0-beta.17",
"@docusaurus/utils-validation": "^2.4.1",
"@ethersproject/contracts": "5.6.0",
"@ethersproject/providers": "5.6.2",
"@ethersproject/units": "5.6.0",
Expand Down
5 changes: 0 additions & 5 deletions packages/example-next/pages/wallet-connect/index.tsx

This file was deleted.

58 changes: 0 additions & 58 deletions packages/example/playwright/with-metamask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,63 +294,5 @@ export const withMetamaskTest = (baseUrl: string) => {
})
})
})

describe('Connectors', () => {
it('Can connect to WalletConnect', async () => {
await page.goto(`${baseUrl}connectors`)

let pagesNumber = context.pages().length
await page.click(XPath.text('button', 'Disconnect'))
await page.click(XPath.id('button', 'WalletConnectButton'))
await page.click(XPath.text('a', 'Desktop'))
await page.click(XPath.text('div', 'Ambire'))

// waiting for the ambire page to open
await waitForExpect(() => {
expect(context.pages().length).to.be.equal(pagesNumber + 1)
})

const ambirePage = context.pages()[context.pages().length - 1]
pagesNumber = context.pages().length
await ambirePage.click(XPath.svgWithClass('AddAccount_metamask'))

// waiting for the metamask page to open
await waitForExpect(() => {
expect(context.pages().length).to.be.equal(pagesNumber + 1)
})

const metamaskPage = context.pages()[context.pages().length - 1]

await metamaskPage.click(XPath.text('button', 'Next'))
await metamaskPage.click(XPath.text('button', 'Connect'))
log('Metamask connected to the app.')

await waitForExpect(async () => {
expect(await page.isVisible(XPath.text('span', 'Account:'))).to.be.true
expect(await page.isVisible(XPath.text('span', 'Eth balance:'))).to.be.true
expect(await page.isVisible(XPath.text('span', 'Chain Id:'))).to.be.true
expect(await page.isVisible(XPath.text('span', 'ETH2 staking contract holds:'))).to.be.true
})

await waitForExpect(async () => {
expect(await page.isVisible(XPath.text('p', 'Send transaction'))).to.be.true
})
})

it('Holds WalletConnect session', async () => {
await page.reload()

await waitForExpect(async () => {
expect(await page.isVisible(XPath.text('span', 'Account:'))).to.be.true
expect(await page.isVisible(XPath.text('span', 'Eth balance:'))).to.be.true
expect(await page.isVisible(XPath.text('span', 'Chain Id:'))).to.be.true
expect(await page.isVisible(XPath.text('span', 'ETH2 staking contract holds:'))).to.be.true
})

await waitForExpect(async () => {
expect(await page.isVisible(XPath.text('p', 'Send transaction'))).to.be.true
})
})
})
})
}
2 changes: 0 additions & 2 deletions packages/example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import { NotificationsList } from './components/Transactions/History'
import { Web3Modal } from './pages/Web3Modal'
import { Web3ReactConnector } from './pages/Web3ReactConnector'
import { Multichain } from './pages/Multichain'
import { WalletConnect } from './pages/WalletConnect'
import { ENSExample } from './components/ENS/ENSExample'
import { ConnectorPage } from './pages/ConnectorsPage'

Expand All @@ -35,7 +34,6 @@ export function App() {
<Route exact path="/web3modal" component={Web3Modal} />
<Route exact path="/web3react" component={Web3ReactConnector} />
<Route exact path="/multichain" component={Multichain} />
<Route exact path="/wallet-connect" component={WalletConnect} />
<Route exact path="/connectors" component={ConnectorPage} />
<Redirect exact from="/" to="/balance" />
</Switch>
Expand Down
5 changes: 1 addition & 4 deletions packages/example/src/entrypoint.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
Optimism,
} from '@usedapp/core'
import { App } from './App'
import { WalletConnectConnector } from '@usedapp/wallet-connect-connector'
import { PortisConnector } from '@usedapp/portis-connector'
import { WalletConnectV2Connector } from '@usedapp/wallet-connect-v2-connector'
import { getDefaultProvider } from '@ethersproject/providers'
Expand Down Expand Up @@ -40,13 +39,11 @@ const config: Config = {
noMetamaskDeactivate: true,
connectors: {
metamask: new MetamaskConnector(),
walletConnect: new WalletConnectConnector({ infuraId: 'd8df2cb7844e4a54ab0a782f608749dd' }),
coinbase: new CoinbaseWalletConnector(),
portis: new PortisConnector(PORTIS_DAPP_ID, 'mainnet'),
walletConnectV2: new WalletConnectV2Connector({
projectId: 'bffbe493c0928ee125dc8f23e20167b7',
chains: [Mainnet, Goerli],
checkGnosisSafe: true,
chains: [Mainnet],
rpcMap: {
1: 'https://mainnet.infura.io/v3/d8df2cb7844e4a54ab0a782f608749dd',
5: 'https://goerli.infura.io/v3/d8df2cb7844e4a54ab0a782f608749dd',
Expand Down
96 changes: 0 additions & 96 deletions packages/example/src/pages/WalletConnect.tsx

This file was deleted.

1 change: 0 additions & 1 deletion packages/example/src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ export * from './Prices'
export * from './SendEtherPage'
export * from './Tokens'
export * from './Transactions'
export * from './WalletConnect'
export * from './Web3Modal'
export * from './Web3ReactConnector'
export * from './ConnectorsPage'
Loading

0 comments on commit 819e1bf

Please sign in to comment.