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

🧶 WalletConnectV2 connector use @walletconnect/modal #1118

Merged
merged 6 commits into from
Jul 4, 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
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