Skip to content

Commit

Permalink
chore: remove re initialization every 10 seconds. Make it reinitializ…
Browse files Browse the repository at this point in the history
…e after 15m. Remove duplicated display_uri handlers and subscribe in client constructors
  • Loading branch information
tomiir committed Aug 5, 2024
1 parent 2ca19d9 commit df03566
Show file tree
Hide file tree
Showing 10 changed files with 129 additions and 87 deletions.
12 changes: 7 additions & 5 deletions packages/core/src/controllers/ConnectionController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export interface ConnectExternalOptions {
}

export interface ConnectionControllerClient {
connectWalletConnect: (onUri: (uri: string) => void) => Promise<void>
connectWalletConnect: () => Promise<void>
disconnect: () => Promise<void>
signMessage: (message: string) => Promise<string>
sendTransaction: (args: SendTransactionArgs) => Promise<`0x${string}` | null>
Expand Down Expand Up @@ -84,10 +84,12 @@ export const ConnectionController = {

async connectWalletConnect() {
StorageUtil.setConnectedConnector('WALLET_CONNECT')
await this._getClient().connectWalletConnect(uri => {
state.wcUri = uri
state.wcPairingExpiry = CoreHelperUtil.getPairingExpiry()
})
await this._getClient().connectWalletConnect()
},

setQRCodeURI(uri: string) {
state.wcUri = uri
state.wcPairingExpiry = CoreHelperUtil.getPairingExpiry()
},

async connectExternal(options: ConnectExternalOptions, chain?: Chain) {
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/utils/CoreHelperUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ export const CoreHelperUtil = {
},

isPairingExpired(expiry?: number) {
return expiry ? expiry - Date.now() <= ConstantsUtil.TEN_SEC_MS : true
// QR code lasts 15mins
return expiry ? expiry - Date.now() <= 15 * 60 * 1000 : true
},

isAllowedRetry(lastRetry: number) {
Expand Down
5 changes: 1 addition & 4 deletions packages/core/tests/controllers/ConnectionController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@ const type = 'AUTH' as ConnectorType
const storageSpy = vi.spyOn(StorageUtil, 'setConnectedConnector')

const client: ConnectionControllerClient = {
connectWalletConnect: async onUri => {
onUri(walletConnectUri)
await Promise.resolve(walletConnectUri)
},
connectWalletConnect: async () => Promise.resolve(),
disconnect: async () => Promise.resolve(),
signMessage: async (message: string) => Promise.resolve(message),
estimateGas: async () => Promise.resolve(BigInt(0)),
Expand Down
10 changes: 5 additions & 5 deletions packages/ethers/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,16 +194,12 @@ export class Web3Modal extends Web3ModalScaffold {
}

const connectionControllerClient: ConnectionControllerClient = {
connectWalletConnect: async onUri => {
connectWalletConnect: async () => {
const WalletConnectProvider = await this.getWalletConnectProvider()
if (!WalletConnectProvider) {
throw new Error('connectionControllerClient:getWalletConnectUri - provider is undefined')
}

WalletConnectProvider.on('display_uri', (uri: string) => {
onUri(uri)
})

// When connecting through walletconnect, we need to set the clientId in the store
const clientId = await WalletConnectProvider.signer?.client?.core?.crypto?.getClientId()
if (clientId) {
Expand Down Expand Up @@ -699,6 +695,10 @@ export class Web3Modal extends Web3ModalScaffold {

this.walletConnectProvider = await EthereumProvider.init(walletConnectProviderOptions)

this.walletConnectProvider.on('display_uri', (uri: string) => {
this.setQRCodeURI(uri)
})

await this.checkActiveWalletConnectProvider()
}

Expand Down
10 changes: 5 additions & 5 deletions packages/ethers5/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,16 +169,12 @@ export class Web3Modal extends Web3ModalScaffold {
}

const connectionControllerClient: ConnectionControllerClient = {
connectWalletConnect: async onUri => {
connectWalletConnect: async () => {
const WalletConnectProvider = await this.getWalletConnectProvider()
if (!WalletConnectProvider) {
throw new Error('connectionControllerClient:getWalletConnectUri - provider is undefined')
}

WalletConnectProvider.on('display_uri', (uri: string) => {
onUri(uri)
})

const params = await siweConfig?.getMessageParams?.()
// Must perform these checks to satify optional types
if (siweConfig?.options?.enabled && params && Object.keys(params || {}).length > 0) {
Expand Down Expand Up @@ -542,6 +538,10 @@ export class Web3Modal extends Web3ModalScaffold {

this.walletConnectProvider = await EthereumProvider.init(walletConnectProviderOptions)

this.walletConnectProvider.on('display_uri', (uri: string) => {
this.setQRCodeURI(uri)
})

await this.checkActiveWalletConnectProvider()
}

Expand Down
110 changes: 60 additions & 50 deletions packages/scaffold-ui/src/views/w3m-connecting-wc-view/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
AssetUtil,
ConnectionController,
ConnectorController,
ConstantsUtil,
CoreHelperUtil,
EventsController,
ModalController,
Expand All @@ -21,8 +20,6 @@ export class W3mConnectingWcView extends LitElement {
// -- Members ------------------------------------------- //
private interval?: ReturnType<typeof setInterval> = undefined

private lastRetry = Date.now()

private wallet = RouterController.state.data?.wallet

// -- State & Properties -------------------------------- //
Expand All @@ -33,7 +30,11 @@ export class W3mConnectingWcView extends LitElement {
public constructor() {
super()
this.initializeConnection()
this.interval = setInterval(this.initializeConnection.bind(this), ConstantsUtil.TEN_SEC_MS)
/*
* For 15minutes, the relay handles retries and reconnections internally.
* We re-initialize the connection after that
*/
this.interval = setInterval(this.initializeConnection.bind(this), 15 * 60 * 1000)
}

public override disconnectedCallback() {
Expand All @@ -55,58 +56,47 @@ export class W3mConnectingWcView extends LitElement {
}

// -- Private ------------------------------------------- //
private async initializeConnection(retry = false) {
try {
const { wcPairingExpiry } = ConnectionController.state
if (retry || CoreHelperUtil.isPairingExpired(wcPairingExpiry)) {
if (this.wallet) {
const url = AssetUtil.getWalletImage(this.wallet)
if (url) {
StorageUtil.setConnectedWalletImageUrl(url)
}
} else {
const connectors = ConnectorController.state.connectors
const connector = connectors.find(c => c.type === 'WALLET_CONNECT')
const url = AssetUtil.getConnectorImage(connector)
if (url) {
StorageUtil.setConnectedWalletImageUrl(url)
}
}

await ConnectionController.connectWalletConnect()
this.finalizeConnection()
if (
StorageUtil.getConnectedConnector() === 'AUTH' &&
OptionsController.state.hasMultipleAddresses
) {
RouterController.push('SelectAddresses')
} else if (OptionsController.state.isSiweEnabled) {
const { SIWEController } = await import('@web3modal/siwe')
if (SIWEController.state.status === 'success') {
ModalController.close()
} else {
RouterController.push('ConnectingSiwe')
}
} else {
ModalController.close()
}
private setConnectorImage() {
if (this.wallet) {
const url = AssetUtil.getWalletImage(this.wallet)
if (url) {
StorageUtil.setConnectedWalletImageUrl(url)
}
} else {
const connectors = ConnectorController.state.connectors
const connector = connectors.find(c => c.type === 'WALLET_CONNECT')
const url = AssetUtil.getConnectorImage(connector)
if (url) {
StorageUtil.setConnectedWalletImageUrl(url)
}
}
}

private async initializeConnection() {
try {
await ConnectionController.connectWalletConnect()
await this.finalizeConnection()
} catch (error) {
/**
* Potential errors:
* 1. User declined connection
* 2. QR Cannot be generated (network issue?)
* 3. QR Code expired
*/
EventsController.sendEvent({
type: 'track',
event: 'CONNECT_ERROR',
properties: { message: (error as BaseError)?.message ?? 'Unknown' }
properties: { message: (error as BaseError)?.message || 'Unknown' }
})
ConnectionController.setWcError(true)
if (CoreHelperUtil.isAllowedRetry(this.lastRetry)) {
SnackController.showError('Declined')
this.lastRetry = Date.now()
this.initializeConnection(true)
}
// ConnectionController.setWcError(true)
SnackController.showError((error as BaseError)?.message || 'Declined')

// We need to re-generate the session
this.initializeConnection()
}
}

private finalizeConnection() {
private async finalizeConnection() {
const { wcLinking, recentWallet } = ConnectionController.state

if (wcLinking) {
Expand All @@ -124,6 +114,26 @@ export class W3mConnectingWcView extends LitElement {
name: this.wallet?.name || 'Unknown'
}
})

// Setup connector images
this.setConnectorImage()

// Route after connect
if (
StorageUtil.getConnectedConnector() === 'AUTH' &&
OptionsController.state.hasMultipleAddresses
) {
RouterController.push('SelectAddresses')
} else if (OptionsController.state.isSiweEnabled) {
const { SIWEController } = await import('@web3modal/siwe')
if (SIWEController.state.status === 'success') {
ModalController.close()
} else {
RouterController.push('ConnectingSiwe')
}
} else {
ModalController.close()
}
}

private determinePlatforms() {
Expand Down Expand Up @@ -171,17 +181,17 @@ export class W3mConnectingWcView extends LitElement {
return html`<w3m-connecting-wc-browser></w3m-connecting-wc-browser>`
case 'desktop':
return html`
<w3m-connecting-wc-desktop .onRetry=${() => this.initializeConnection(true)}>
<w3m-connecting-wc-desktop .onRetry=${() => this.initializeConnection()}>
</w3m-connecting-wc-desktop>
`
case 'web':
return html`
<w3m-connecting-wc-web .onRetry=${() => this.initializeConnection(true)}>
<w3m-connecting-wc-web .onRetry=${() => this.initializeConnection()}>
</w3m-connecting-wc-web>
`
case 'mobile':
return html`
<w3m-connecting-wc-mobile isMobile .onRetry=${() => this.initializeConnection(true)}>
<w3m-connecting-wc-mobile isMobile .onRetry=${() => this.initializeConnection()}>
</w3m-connecting-wc-mobile>
`
case 'qrcode':
Expand Down
4 changes: 4 additions & 0 deletions packages/scaffold/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,10 @@ export class Web3ModalScaffold {
BlockchainApiController.setClientId(clientId)
}

protected setQRCodeURI: (typeof ConnectionController)['setQRCodeURI'] = uri => {
ConnectionController.setQRCodeURI(uri)
}

// -- Private ------------------------------------------------------------------
private async initControllers(options: ScaffoldOptions) {
ChainController.initialize([
Expand Down
13 changes: 10 additions & 3 deletions packages/solana/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,16 +121,14 @@ export class Web3Modal extends Web3ModalScaffold {
}

const connectionControllerClient: ConnectionControllerClient = {
connectWalletConnect: async onUri => {
connectWalletConnect: async () => {
const WalletConnectProvider = await this.WalletConnectConnector.getProvider()
if (!WalletConnectProvider) {
throw new Error('connectionControllerClient:getWalletConnectUri - provider is undefined')
}

WalletConnectProvider.on('display_uri', onUri)
const address = await this.WalletConnectConnector.connect()
this.setWalletConnectProvider(address)
WalletConnectProvider.removeListener('display_uri', onUri)
},

connectExternal: async ({ id }) => {
Expand Down Expand Up @@ -228,6 +226,15 @@ export class Web3Modal extends Web3ModalScaffold {
chains,
qrcode: true
})

this.WalletConnectConnector.getProvider().then(provider => {
if (provider) {
provider.on('display_uri', (uri: string) => {
this.setQRCodeURI(uri)
})
}
})

SolStoreUtil.setConnection(
new Connection(
SolHelpersUtil.detectRpcUrl(chain, OptionsController.state.projectId),
Expand Down
2 changes: 1 addition & 1 deletion packages/solana/src/connectors/walletConnectConnector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { UniversalProviderFactory } from './universalProvider.js'
import { BaseConnector } from './baseConnector.js'

import type { Signer } from '@solana/web3.js'
import type UniversalProvider from '@walletconnect/universal-provider'
import UniversalProvider from '@walletconnect/universal-provider'

import type { Connector } from './baseConnector.js'
import type { Chain } from '../utils/scaffold/SolanaTypesUtil.js'
Expand Down
Loading

0 comments on commit df03566

Please sign in to comment.