From 9ce44feb15f81b54b80c27b0390ad7e277e30f8e Mon Sep 17 00:00:00 2001 From: Enes Date: Thu, 30 Jan 2025 21:23:48 +0300 Subject: [PATCH] refactor: lazy load coinbase package (#3752) Co-authored-by: tomiir --- .changeset/spicy-ducks-search.md | 23 ++++++++ apps/laboratory/package.json | 1 + packages/adapters/bitcoin/src/adapter.ts | 2 +- packages/adapters/ethers/package.json | 4 +- packages/adapters/ethers/src/client.ts | 53 ++++++++++--------- packages/adapters/ethers5/package.json | 4 +- packages/adapters/ethers5/src/client.ts | 53 ++++++++++--------- packages/adapters/solana/src/client.ts | 3 +- packages/adapters/wagmi/package.json | 5 +- packages/adapters/wagmi/src/client.ts | 48 ++++++++++++----- .../src/adapters/ChainAdapterBlueprint.ts | 2 +- .../appkit/src/universal-adapter/client.ts | 2 +- packages/appkit/tests/appkit.test.ts | 8 ++- .../w3m-connect-external-widget/index.ts | 3 +- pnpm-lock.yaml | 27 +++++----- 15 files changed, 153 insertions(+), 85 deletions(-) create mode 100644 .changeset/spicy-ducks-search.md diff --git a/.changeset/spicy-ducks-search.md b/.changeset/spicy-ducks-search.md new file mode 100644 index 0000000000..30285adfe9 --- /dev/null +++ b/.changeset/spicy-ducks-search.md @@ -0,0 +1,23 @@ +--- +'@reown/appkit-adapter-bitcoin': patch +'@reown/appkit-adapter-ethers5': patch +'@reown/appkit-adapter-ethers': patch +'@reown/appkit-adapter-solana': patch +'@reown/appkit-adapter-wagmi': patch +'@reown/appkit-scaffold-ui': patch +'@reown/appkit': patch +'@reown/appkit-utils': patch +'@reown/appkit-cdn': patch +'@reown/appkit-cli': patch +'@reown/appkit-common': patch +'@reown/appkit-core': patch +'@reown/appkit-experimental': patch +'@reown/appkit-polyfills': patch +'@reown/appkit-siwe': patch +'@reown/appkit-siwx': patch +'@reown/appkit-ui': patch +'@reown/appkit-wallet': patch +'@reown/appkit-wallet-button': patch +--- + +Refactors syncConnectors to dynamically import Coinbase Wallet SDK diff --git a/apps/laboratory/package.json b/apps/laboratory/package.json index dc38142428..56b286861a 100644 --- a/apps/laboratory/package.json +++ b/apps/laboratory/package.json @@ -87,6 +87,7 @@ "@bitcoinerlab/secp256k1": "1.1.1", "@chakra-ui/icons": "2.1.1", "@chakra-ui/react": "2.8.2", + "@coinbase/wallet-sdk": "4.2.4", "@emotion/react": "11.11.3", "@emotion/styled": "11.11.0", "@reown/appkit": "workspace:*", diff --git a/packages/adapters/bitcoin/src/adapter.ts b/packages/adapters/bitcoin/src/adapter.ts index 56d39254bc..644ede4a2c 100644 --- a/packages/adapters/bitcoin/src/adapter.ts +++ b/packages/adapters/bitcoin/src/adapter.ts @@ -82,7 +82,7 @@ export class BitcoinAdapter extends AdapterBlueprint { } } - override syncConnectors(_options?: AppKitOptions, appKit?: AppKit): void { + override syncConnectors(_options?: AppKitOptions, appKit?: AppKit) { function getActiveNetwork() { return appKit?.getCaipNetwork() } diff --git a/packages/adapters/ethers/package.json b/packages/adapters/ethers/package.json index b8fe002a53..5316fb7ea3 100644 --- a/packages/adapters/ethers/package.json +++ b/packages/adapters/ethers/package.json @@ -29,9 +29,11 @@ "@walletconnect/universal-provider": "2.18.0", "valtio": "1.11.2" }, + "optionalDependencies": { + "@coinbase/wallet-sdk": "4.2.4" + }, "peerDependencies": { "@ethersproject/sha2": "5.7.0", - "@coinbase/wallet-sdk": "4.2.4", "ethers": ">=6" }, "devDependencies": { diff --git a/packages/adapters/ethers/src/client.ts b/packages/adapters/ethers/src/client.ts index 377ec4691b..2f80ca9223 100644 --- a/packages/adapters/ethers/src/client.ts +++ b/packages/adapters/ethers/src/client.ts @@ -1,4 +1,3 @@ -import { CoinbaseWalletSDK, type ProviderInterface } from '@coinbase/wallet-sdk' import UniversalProvider from '@walletconnect/universal-provider' import { InfuraProvider, JsonRpcProvider, formatEther } from 'ethers' @@ -36,15 +35,12 @@ export class EthersAdapter extends AdapterBlueprint { this.namespace = CommonConstantsUtil.CHAIN.EVM } - private createEthersConfig(options: AppKitOptions) { + private async createEthersConfig(options: AppKitOptions) { if (!options.metadata) { return undefined } let injectedProvider: Provider | undefined = undefined - // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents - let coinbaseProvider: ProviderInterface | undefined = undefined - function getInjectedProvider() { if (injectedProvider) { return injectedProvider @@ -64,26 +60,30 @@ export class EthersAdapter extends AdapterBlueprint { return injectedProvider } - function getCoinbaseProvider() { - if (coinbaseProvider) { - return coinbaseProvider - } + async function getCoinbaseProvider() { + try { + const { createCoinbaseWalletSDK } = await import('@coinbase/wallet-sdk') - if (typeof window === 'undefined') { - return undefined - } + if (typeof window === 'undefined') { + return undefined + } - const coinbaseWallet = new CoinbaseWalletSDK({ - appName: options?.metadata?.name, - appLogoUrl: options?.metadata?.icons[0], - appChainIds: options.networks?.map(caipNetwork => caipNetwork.id as number) || [1, 84532] - }) + const coinbaseSdk = createCoinbaseWalletSDK({ + appName: options?.metadata?.name, + appLogoUrl: options?.metadata?.icons[0], + appChainIds: options.networks?.map(caipNetwork => caipNetwork.id as number) || [1, 84532], + preference: { + options: options.coinbasePreference ?? 'all' + } + }) - coinbaseProvider = coinbaseWallet.makeWeb3Provider({ - options: options.coinbasePreference ?? 'all' - }) + return coinbaseSdk.getProvider() + } catch (error) { + // eslint-disable-next-line no-console + console.error('Failed to import Coinbase Wallet SDK:', error) - return coinbaseProvider + return undefined + } } const providers: ProviderType = { metadata: options.metadata } @@ -93,7 +93,11 @@ export class EthersAdapter extends AdapterBlueprint { } if (options.enableCoinbase !== false) { - providers.coinbase = getCoinbaseProvider() + const coinbaseProvider = await getCoinbaseProvider() + + if (coinbaseProvider) { + providers.coinbase = coinbaseProvider + } } providers.EIP6963 = options.enableEIP6963 !== false @@ -248,8 +252,9 @@ export class EthersAdapter extends AdapterBlueprint { } } - public syncConnectors(options: AppKitOptions) { - this.ethersConfig = this.createEthersConfig(options) + override async syncConnectors(options: AppKitOptions): Promise { + this.ethersConfig = await this.createEthersConfig(options) + if (this.ethersConfig?.EIP6963) { this.listenInjectedConnector(true) } diff --git a/packages/adapters/ethers5/package.json b/packages/adapters/ethers5/package.json index 1c2482286a..fe4680cb1d 100644 --- a/packages/adapters/ethers5/package.json +++ b/packages/adapters/ethers5/package.json @@ -29,9 +29,11 @@ "@walletconnect/universal-provider": "2.18.0", "valtio": "1.11.2" }, + "optionalDependencies": { + "@coinbase/wallet-sdk": "4.2.4" + }, "peerDependencies": { "@ethersproject/sha2": "5.7.0", - "@coinbase/wallet-sdk": "4.2.4", "ethers": ">=4.1 <6.0.0" }, "devDependencies": { diff --git a/packages/adapters/ethers5/src/client.ts b/packages/adapters/ethers5/src/client.ts index e4b9c3c1f8..77b4be91e1 100644 --- a/packages/adapters/ethers5/src/client.ts +++ b/packages/adapters/ethers5/src/client.ts @@ -1,4 +1,3 @@ -import { CoinbaseWalletSDK, type ProviderInterface } from '@coinbase/wallet-sdk' import UniversalProvider from '@walletconnect/universal-provider' import * as ethers from 'ethers' import { formatEther } from 'ethers/lib/utils.js' @@ -37,15 +36,12 @@ export class Ethers5Adapter extends AdapterBlueprint { this.namespace = CommonConstantsUtil.CHAIN.EVM } - private createEthersConfig(options: AppKitOptions) { + private async createEthersConfig(options: AppKitOptions) { if (!options.metadata) { return undefined } let injectedProvider: Provider | undefined = undefined - // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents - let coinbaseProvider: ProviderInterface | undefined = undefined - function getInjectedProvider() { if (injectedProvider) { return injectedProvider @@ -65,26 +61,30 @@ export class Ethers5Adapter extends AdapterBlueprint { return injectedProvider } - function getCoinbaseProvider() { - if (coinbaseProvider) { - return coinbaseProvider - } + async function getCoinbaseProvider() { + try { + const { createCoinbaseWalletSDK } = await import('@coinbase/wallet-sdk') - if (typeof window === 'undefined') { - return undefined - } + if (typeof window === 'undefined') { + return undefined + } - const coinbaseWallet = new CoinbaseWalletSDK({ - appName: options?.metadata?.name, - appLogoUrl: options?.metadata?.icons[0], - appChainIds: options.networks?.map(caipNetwork => caipNetwork.id as number) || [1, 84532] - }) + const coinbaseSdk = createCoinbaseWalletSDK({ + appName: options?.metadata?.name, + appLogoUrl: options?.metadata?.icons[0], + appChainIds: options.networks?.map(caipNetwork => caipNetwork.id as number) || [1, 84532], + preference: { + options: options.coinbasePreference ?? 'all' + } + }) - coinbaseProvider = coinbaseWallet.makeWeb3Provider({ - options: options.coinbasePreference ?? 'all' - }) + return coinbaseSdk.getProvider() + } catch (error) { + // eslint-disable-next-line no-console + console.error('Failed to import Coinbase Wallet SDK:', error) - return coinbaseProvider + return undefined + } } const providers: ProviderType = { metadata: options.metadata } @@ -94,7 +94,11 @@ export class Ethers5Adapter extends AdapterBlueprint { } if (options.enableCoinbase !== false) { - providers.coinbase = getCoinbaseProvider() + const coinbaseProvider = await getCoinbaseProvider() + + if (coinbaseProvider) { + providers.coinbase = coinbaseProvider + } } providers.EIP6963 = options.enableEIP6963 !== false @@ -248,8 +252,9 @@ export class Ethers5Adapter extends AdapterBlueprint { } } - public syncConnectors(options: AppKitOptions) { - this.ethersConfig = this.createEthersConfig(options) + override async syncConnectors(options: AppKitOptions): Promise { + this.ethersConfig = await this.createEthersConfig(options) + if (this.ethersConfig?.EIP6963) { this.listenInjectedConnector(true) } diff --git a/packages/adapters/solana/src/client.ts b/packages/adapters/solana/src/client.ts index 43258a8416..56b32f167c 100644 --- a/packages/adapters/solana/src/client.ts +++ b/packages/adapters/solana/src/client.ts @@ -68,12 +68,11 @@ export class SolanaAdapter extends AdapterBlueprint { ) } - public syncConnectors(options: AppKitOptions, appKit: AppKit) { + override syncConnectors(options: AppKitOptions, appKit: AppKit) { if (!options.projectId) { AlertController.open(ErrorUtil.ALERT_ERRORS.PROJECT_ID_NOT_CONFIGURED, 'error') } - // eslint-disable-next-line arrow-body-style const getActiveChain = () => appKit.getCaipNetwork(this.namespace) // Add Coinbase Wallet if available diff --git a/packages/adapters/wagmi/package.json b/packages/adapters/wagmi/package.json index 19093353b7..6af22d0ccd 100644 --- a/packages/adapters/wagmi/package.json +++ b/packages/adapters/wagmi/package.json @@ -29,9 +29,10 @@ "@walletconnect/universal-provider": "2.18.0", "valtio": "1.11.2" }, + "optionalDependencies": { + "@wagmi/connectors": ">=5.1" + }, "peerDependencies": { - "@coinbase/wallet-sdk": "4.2.4", - "@wagmi/connectors": ">=5.1", "@wagmi/core": ">=2.13", "viem": "2.x", "wagmi": ">=2.12" diff --git a/packages/adapters/wagmi/src/client.ts b/packages/adapters/wagmi/src/client.ts index c2a3c8027b..3dbaa83685 100644 --- a/packages/adapters/wagmi/src/client.ts +++ b/packages/adapters/wagmi/src/client.ts @@ -1,4 +1,3 @@ -import { coinbaseWallet } from '@wagmi/connectors' import { type Config, type Connector, @@ -250,20 +249,38 @@ export class WagmiAdapter extends AdapterBlueprint { }) } - private addWagmiConnectors(options: AppKitOptions, appKit: AppKit) { - const customConnectors: CreateConnectorFn[] = [] + private async addThirdPartyConnectors(options: AppKitOptions) { + const thirdPartyConnectors: CreateConnectorFn[] = [] if (options.enableCoinbase !== false) { - customConnectors.push( - coinbaseWallet({ - version: '4', - appName: options.metadata?.name ?? 'Unknown', - appLogoUrl: options.metadata?.icons[0] ?? 'Unknown', - preference: options.coinbasePreference ?? 'all' - }) - ) + try { + const { coinbaseWallet } = await import('@wagmi/connectors') + + if (coinbaseWallet) { + thirdPartyConnectors.push( + coinbaseWallet({ + version: '4', + appName: options.metadata?.name ?? 'Unknown', + appLogoUrl: options.metadata?.icons[0] ?? 'Unknown', + preference: options.coinbasePreference ?? 'all' + }) + ) + } + } catch (error) { + // eslint-disable-next-line no-console + console.error('Failed to import Coinbase Wallet SDK:', error) + } } + thirdPartyConnectors.forEach(connector => { + const cnctr = this.wagmiConfig._internal.connectors.setup(connector) + this.wagmiConfig._internal.connectors.setState(prev => [...prev, cnctr]) + }) + } + + private addWagmiConnectors(options: AppKitOptions, appKit: AppKit) { + const customConnectors: CreateConnectorFn[] = [] + if (options.enableWalletConnect !== false) { customConnectors.push( walletConnect(options, appKit, this.caipNetworks as [CaipNetwork, ...CaipNetwork[]]) @@ -451,13 +468,16 @@ export class WagmiAdapter extends AdapterBlueprint { connectors.forEach(connector => this.addWagmiConnector(connector, options)) }) - // Add wagmi connectors - this.addWagmiConnectors(options, appKit) - // Add current wagmi connectors to chain adapter blueprint await Promise.all( this.wagmiConfig.connectors.map(connector => this.addWagmiConnector(connector, options)) ) + + // Add wagmi connectors + this.addWagmiConnectors(options, appKit) + + // Add third party connectors + await this.addThirdPartyConnectors(options) } public async syncConnection( diff --git a/packages/appkit/src/adapters/ChainAdapterBlueprint.ts b/packages/appkit/src/adapters/ChainAdapterBlueprint.ts index ab84b4ed1f..ea6a432a5f 100644 --- a/packages/appkit/src/adapters/ChainAdapterBlueprint.ts +++ b/packages/appkit/src/adapters/ChainAdapterBlueprint.ts @@ -277,7 +277,7 @@ export abstract class AdapterBlueprint< * @param {AppKitOptions} [options] - Optional AppKit options * @param {AppKit} [appKit] - Optional AppKit instance */ - public abstract syncConnectors(options?: AppKitOptions, appKit?: AppKit): void + public abstract syncConnectors(options?: AppKitOptions, appKit?: AppKit): void | Promise /** * Synchronizes the connection with the given parameters. diff --git a/packages/appkit/src/universal-adapter/client.ts b/packages/appkit/src/universal-adapter/client.ts index 6ada4a53c2..c60ffdac7c 100644 --- a/packages/appkit/src/universal-adapter/client.ts +++ b/packages/appkit/src/universal-adapter/client.ts @@ -60,7 +60,7 @@ export class UniversalAdapter extends AdapterBlueprint { }) } - public async syncConnectors() { + override async syncConnectors() { return Promise.resolve() } diff --git a/packages/appkit/tests/appkit.test.ts b/packages/appkit/tests/appkit.test.ts index 104bfe8368..c56eb90260 100644 --- a/packages/appkit/tests/appkit.test.ts +++ b/packages/appkit/tests/appkit.test.ts @@ -1280,7 +1280,7 @@ describe('Base', () => { }) }) - it('should initialize UniversalProvider when not provided in options', () => { + it('should initialize UniversalProvider when not provided in options', async () => { vi.spyOn(CoreHelperUtil, 'isClient').mockReturnValue(true) const upSpy = vi.spyOn(UniversalProvider, 'init') @@ -1292,6 +1292,9 @@ describe('Base', () => { adapters: [mockAdapter] }) + // Wait for the promise to fetchIdentity to resolve + await new Promise(resolve => setTimeout(resolve, 10)) + expect(OptionsController.setUsingInjectedUniversalProvider).toHaveBeenCalled() expect(upSpy).toHaveBeenCalled() }) @@ -1309,6 +1312,9 @@ describe('Base', () => { adapters: [mockAdapter] }) + // Wait for the promise to fetchIdentity to resolve + await new Promise(resolve => setTimeout(resolve, 10)) + expect(upSpy).not.toHaveBeenCalled() expect(OptionsController.setUsingInjectedUniversalProvider).toHaveBeenCalled() }) diff --git a/packages/scaffold-ui/src/partials/w3m-connect-external-widget/index.ts b/packages/scaffold-ui/src/partials/w3m-connect-external-widget/index.ts index 7c9494d9dd..cdba9ab74d 100644 --- a/packages/scaffold-ui/src/partials/w3m-connect-external-widget/index.ts +++ b/packages/scaffold-ui/src/partials/w3m-connect-external-widget/index.ts @@ -2,6 +2,7 @@ import { LitElement, html } from 'lit' import { property, state } from 'lit/decorators.js' import { ifDefined } from 'lit/directives/if-defined.js' +import { ConstantsUtil } from '@reown/appkit-common' import type { Connector } from '@reown/appkit-core' import { AssetUtil, ConnectorController, RouterController } from '@reown/appkit-core' import { customElement } from '@reown/appkit-ui' @@ -31,7 +32,7 @@ export class W3mConnectExternalWidget extends LitElement { public override render() { const externalConnectors = this.connectors.filter(connector => connector.type === 'EXTERNAL') const filteredOutCoinbaseConnectors = externalConnectors.filter( - connector => connector.id !== 'coinbaseWalletSDK' + connector => connector.id !== ConstantsUtil.CONNECTOR_ID.COINBASE_SDK ) if (!filteredOutCoinbaseConnectors?.length) { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ac6bc69f93..8d89f6b0d8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -415,6 +415,9 @@ importers: '@chakra-ui/react': specifier: 2.8.2 version: 2.8.2(@emotion/react@11.11.3(@types/react@18.2.62)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.3(@types/react@18.2.62)(react@18.3.1))(@types/react@18.2.62)(react@18.3.1))(@types/react@18.2.62)(framer-motion@10.17.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@coinbase/wallet-sdk': + specifier: 4.2.4 + version: 4.2.4 '@emotion/react': specifier: 11.11.3 version: 11.11.3(@types/react@18.2.62)(react@18.3.1) @@ -1739,9 +1742,6 @@ importers: packages/adapters/ethers: dependencies: - '@coinbase/wallet-sdk': - specifier: 4.2.4 - version: 4.2.4 '@ethersproject/sha2': specifier: 5.7.0 version: 5.7.0 @@ -1781,6 +1781,10 @@ importers: valtio: specifier: 1.11.2 version: 1.11.2(@types/react@18.3.1)(react@18.3.1) + optionalDependencies: + '@coinbase/wallet-sdk': + specifier: 4.2.4 + version: 4.2.4 devDependencies: '@vitest/coverage-v8': specifier: 2.1.3 @@ -1794,9 +1798,6 @@ importers: packages/adapters/ethers5: dependencies: - '@coinbase/wallet-sdk': - specifier: 4.2.4 - version: 4.2.4 '@ethersproject/sha2': specifier: 5.7.0 version: 5.7.0 @@ -1836,6 +1837,10 @@ importers: valtio: specifier: 1.11.2 version: 1.11.2(@types/react@18.3.1)(react@18.3.1) + optionalDependencies: + '@coinbase/wallet-sdk': + specifier: 4.2.4 + version: 4.2.4 devDependencies: '@vitest/coverage-v8': specifier: 2.1.3 @@ -1963,9 +1968,6 @@ importers: packages/adapters/wagmi: dependencies: - '@coinbase/wallet-sdk': - specifier: 4.2.4 - version: 4.2.4 '@reown/appkit': specifier: workspace:* version: link:../../appkit @@ -1990,9 +1992,6 @@ importers: '@reown/appkit-wallet': specifier: workspace:* version: link:../../wallet - '@wagmi/connectors': - specifier: '>=5.1' - version: 5.1.15(@types/react@18.3.1)(@wagmi/core@2.13.8(@tanstack/query-core@5.59.16)(@types/react@18.3.1)(react@18.3.1)(typescript@5.3.3)(viem@2.21.34(bufferutil@4.0.9)(typescript@5.3.3)(utf-8-validate@5.0.10)(zod@3.23.8)))(bufferutil@4.0.9)(db0@0.2.3)(ioredis@5.4.2)(react-dom@18.3.1(react@18.3.1))(react-native@0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.24.7(@babel/core@7.26.7))(@types/react@18.3.1)(bufferutil@4.0.9)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.32.1)(typescript@5.3.3)(utf-8-validate@5.0.10)(viem@2.21.34(bufferutil@4.0.9)(typescript@5.3.3)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) '@wagmi/core': specifier: '>=2.13' version: 2.13.8(@tanstack/query-core@5.59.16)(@types/react@18.3.1)(react@18.3.1)(typescript@5.3.3)(viem@2.21.34(bufferutil@4.0.9)(typescript@5.3.3)(utf-8-validate@5.0.10)(zod@3.23.8)) @@ -2011,6 +2010,10 @@ importers: wagmi: specifier: '>=2.12' version: 2.12.17(@tanstack/query-core@5.59.16)(@tanstack/react-query@5.56.2(react@18.3.1))(@types/react@18.3.1)(bufferutil@4.0.9)(db0@0.2.3)(ioredis@5.4.2)(react-dom@18.3.1(react@18.3.1))(react-native@0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.24.7(@babel/core@7.26.7))(@types/react@18.3.1)(bufferutil@4.0.9)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.32.1)(typescript@5.3.3)(utf-8-validate@5.0.10)(viem@2.21.34(bufferutil@4.0.9)(typescript@5.3.3)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) + optionalDependencies: + '@wagmi/connectors': + specifier: '>=5.1' + version: 5.1.15(@types/react@18.3.1)(@wagmi/core@2.13.8(@tanstack/query-core@5.59.16)(@types/react@18.3.1)(react@18.3.1)(typescript@5.3.3)(viem@2.21.34(bufferutil@4.0.9)(typescript@5.3.3)(utf-8-validate@5.0.10)(zod@3.23.8)))(bufferutil@4.0.9)(db0@0.2.3)(ioredis@5.4.2)(react-dom@18.3.1(react@18.3.1))(react-native@0.77.0(@babel/core@7.26.7)(@babel/preset-env@7.24.7(@babel/core@7.26.7))(@types/react@18.3.1)(bufferutil@4.0.9)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(rollup@4.32.1)(typescript@5.3.3)(utf-8-validate@5.0.10)(viem@2.21.34(bufferutil@4.0.9)(typescript@5.3.3)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) devDependencies: '@types/react': specifier: 18.3.1