diff --git a/.changeset/red-lions-agree.md b/.changeset/red-lions-agree.md new file mode 100644 index 00000000..74bf300d --- /dev/null +++ b/.changeset/red-lions-agree.md @@ -0,0 +1,5 @@ +--- +'@node-real/walletkit': patch +--- + +Add delayTime to trust to wait for it becomes fully available diff --git a/packages/walletkit/__dev__/App.tsx b/packages/walletkit/__dev__/App.tsx index b4b8f8ab..97058d04 100644 --- a/packages/walletkit/__dev__/App.tsx +++ b/packages/walletkit/__dev__/App.tsx @@ -25,13 +25,12 @@ import { walletConnect, } from '@/wallets'; import { SwitchNetworkModal } from '@/components/SwitchNetworkModal'; -import { WalletKitEmbeddedModal } from '@/components/WalletKitEmbeddedModal'; new VConsole(); const config = createConfig( getDefaultConfig({ - autoConnect: false, + autoConnect: true, appName: 'WalletKit', chains, connectors: [ @@ -43,7 +42,11 @@ const config = createConfig( tokenPocket({ isDisabled: true, }), - trustWallet(), + trustWallet({ + connectorOptions: { + delayTime: 2000, + }, + }), walletConnect(), mathWallet(), ], diff --git a/packages/walletkit/src/wallets/trustWallet/connector.ts b/packages/walletkit/src/wallets/trustWallet/connector.ts index 3221afdc..f5a81b21 100644 --- a/packages/walletkit/src/wallets/trustWallet/connector.ts +++ b/packages/walletkit/src/wallets/trustWallet/connector.ts @@ -1,18 +1,20 @@ import { Chain } from 'wagmi'; import { MetaMaskConnector } from 'wagmi/connectors/metaMask'; import { TRUST_WALLET_ID } from '.'; -import { getInjectedProvider } from '../utils'; import { sleep } from '@/utils/common'; -import { WindowProvider } from 'wagmi/window'; export type TrustWalletConnectorOptions = { shimDisconnect?: boolean; + delayTime?: number; }; export class TrustWalletConnector extends MetaMaskConnector { readonly id: any = TRUST_WALLET_ID; protected shimDisconnectKey = `${this.id}.shimDisconnect`; + private delayTime: number; + private twProvider: any; + constructor({ chains, options: _options, @@ -23,7 +25,6 @@ export class TrustWalletConnector extends MetaMaskConnector { const options = { name: 'Trust Wallet', shimDisconnect: true, - getProvider, ..._options, }; @@ -31,24 +32,72 @@ export class TrustWalletConnector extends MetaMaskConnector { chains, options, }); + + this.delayTime = options.delayTime ?? 1500; } public async getProvider() { - if (typeof window !== 'undefined' && !window.trustwallet?.request) { - await sleep(); + if (!this.twProvider) { + await sleep(this.delayTime); + this.twProvider = (await getTrustWalletFromEip6963()) || (await getTrustWalletFromWindow()); + if (this.twProvider?.removeListener === undefined) { + this.twProvider.removeListener = this.twProvider.off; + } } - return this.options.getProvider() as WindowProvider; + return this.twProvider; } } -function getProvider() { - if (typeof window === 'undefined') return; +function getTrustWalletFromEip6963({ timeout } = { timeout: 100 }) { + return new Promise((resolve) => { + window.addEventListener('eip6963:announceProvider', (event: any) => { + const provider = event.detail.provider; + if (provider.isTrust) { + resolve(provider); + } + }); + window.dispatchEvent(new Event('eip6963:requestProvider')); + + setTimeout(() => { + resolve(null); + }, timeout); + }); +} + +function getTrustWalletFromWindow() { + const isTrustWallet = (ethereum: any) => { + // Identify if Trust Wallet injected provider is present. + const trustWallet = !!ethereum.isTrust; - const provider = getInjectedProvider('isTrust') ?? window.trustwallet ?? window.trustWallet; + return trustWallet; + }; + + const injectedProviderExist = + typeof window !== 'undefined' && typeof window.ethereum !== 'undefined'; + + // No injected providers exist. + if (!injectedProviderExist) { + return null; + } + + // Trust Wallet was injected into window.ethereum. + if (isTrustWallet(window.ethereum)) { + return window.ethereum; + } - if (provider && provider.removeListener === undefined) { - provider.removeListener = provider.off; + // Trust Wallet provider might be replaced by another + // injected provider, check the providers array. + if (window.ethereum?.providers) { + // ethereum.providers array is a non-standard way to + // preserve multiple injected providers. Eventually, EIP-5749 + // will become a living standard and we will have to update this. + return window.ethereum.providers.find(isTrustWallet) ?? null; } - return provider; + // Trust Wallet injected provider is available in the global scope. + // There are cases that some cases injected providers can replace window.ethereum + // without updating the ethereum.providers array. To prevent issues where + // the TW connector does not recognize the provider when TW extension is installed, + // we begin our checks by relying on TW's global object. + return window['trustwallet'] ?? null; }