diff --git a/.changeset/plain-ants-begin.md b/.changeset/plain-ants-begin.md
new file mode 100644
index 0000000000..095d12d523
--- /dev/null
+++ b/.changeset/plain-ants-begin.md
@@ -0,0 +1,27 @@
+---
+'@reown/appkit-adapter-ethers5': patch
+'@reown/appkit-adapter-ethers': patch
+'@reown/appkit-adapter-solana': patch
+'@reown/appkit-adapter-wagmi': patch
+'@reown/appkit-utils': patch
+'@reown/appkit-controllers': patch
+'@reown/appkit': patch
+'@reown/appkit-wallet': patch
+'@reown/appkit-adapter-bitcoin': patch
+'@reown/appkit-cdn': patch
+'@reown/appkit-cli': patch
+'@reown/appkit-codemod': patch
+'@reown/appkit-common': patch
+'@reown/appkit-core': patch
+'@reown/appkit-experimental': patch
+'@reown/appkit-pay': patch
+'@reown/appkit-polyfills': patch
+'@reown/appkit-scaffold-ui': patch
+'@reown/appkit-siwe': patch
+'@reown/appkit-siwx': patch
+'@reown/appkit-testing': patch
+'@reown/appkit-ui': patch
+'@reown/appkit-wallet-button': patch
+---
+
+Add forwarding of custom RPC urls to be used in embedded wallet requests
diff --git a/apps/laboratory/app/flag/custom-rpc-url/page.tsx b/apps/laboratory/app/flag/custom-rpc-url/page.tsx
new file mode 100644
index 0000000000..329695cefa
--- /dev/null
+++ b/apps/laboratory/app/flag/custom-rpc-url/page.tsx
@@ -0,0 +1,50 @@
+'use client'
+
+import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
+import { WagmiProvider } from 'wagmi'
+
+import { WagmiAdapter } from '@reown/appkit-adapter-wagmi'
+
+import { AppKitButtons } from '@/src/components/AppKitButtons'
+import { AppKitConnections } from '@/src/components/AppKitConnections'
+import { AppKitInfo } from '@/src/components/AppKitInfo'
+import { WagmiTests } from '@/src/components/Wagmi/WagmiTests'
+import { AppKitProvider } from '@/src/context/AppKitContext'
+import { ConstantsUtil } from '@/src/utils/ConstantsUtil'
+
+const queryClient = new QueryClient()
+
+const customRpcUrls = {
+ 'eip155:1': [{ url: 'https://ethereum-rpc.publicnode.com' }]
+}
+
+const wagmiAdapter = new WagmiAdapter({
+ ssr: true,
+ networks: ConstantsUtil.EvmNetworks,
+ projectId: ConstantsUtil.ProjectId,
+ customRpcUrls
+})
+
+const config = {
+ adapters: [wagmiAdapter],
+ networks: ConstantsUtil.EvmNetworks,
+ projectId: ConstantsUtil.ProjectId,
+ customWallets: ConstantsUtil.CustomWallets,
+ customRpcUrls
+}
+const wagmiConfig = wagmiAdapter.wagmiConfig
+
+export default function Wagmi() {
+ return (
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/packages/adapters/ethers/src/tests/client.test.ts b/packages/adapters/ethers/src/tests/client.test.ts
index 847174610d..97c764a868 100644
--- a/packages/adapters/ethers/src/tests/client.test.ts
+++ b/packages/adapters/ethers/src/tests/client.test.ts
@@ -964,7 +964,7 @@ describe('EthersAdapter', () => {
providerType: 'AUTH'
})
- expect(mockAuthProvider.switchNetwork).toHaveBeenCalledWith('eip155:1')
+ expect(mockAuthProvider.switchNetwork).toHaveBeenCalledWith({ chainId: 'eip155:1' })
expect(mockAuthProvider.getUser).toHaveBeenCalledWith({
chainId: 'eip155:1',
preferredAccountType: 'smartAccount'
diff --git a/packages/adapters/ethers5/src/tests/client.test.ts b/packages/adapters/ethers5/src/tests/client.test.ts
index 01fc4dcac5..7af627849e 100644
--- a/packages/adapters/ethers5/src/tests/client.test.ts
+++ b/packages/adapters/ethers5/src/tests/client.test.ts
@@ -862,7 +862,7 @@ describe('Ethers5Adapter', () => {
providerType: 'AUTH'
})
- expect(mockAuthProvider.switchNetwork).toHaveBeenCalledWith('eip155:1')
+ expect(mockAuthProvider.switchNetwork).toHaveBeenCalledWith({ chainId: 'eip155:1' })
expect(mockAuthProvider.getUser).toHaveBeenCalledWith({
chainId: 'eip155:1',
preferredAccountType: 'smartAccount'
diff --git a/packages/adapters/solana/src/tests/mocks/W3mFrameProvider.ts b/packages/adapters/solana/src/tests/mocks/W3mFrameProvider.ts
index 52a0ce903e..93245447f7 100644
--- a/packages/adapters/solana/src/tests/mocks/W3mFrameProvider.ts
+++ b/packages/adapters/solana/src/tests/mocks/W3mFrameProvider.ts
@@ -46,7 +46,9 @@ export function mockW3mFrameProvider() {
return Promise.reject(new Error('not implemented'))
}
})
- w3mFrame.switchNetwork = vi.fn((chainId: string | number) => Promise.resolve({ chainId }))
+ w3mFrame.switchNetwork = vi.fn((args: { chainId: string | number }) =>
+ Promise.resolve({ chainId: args.chainId })
+ )
w3mFrame.getUser = vi.fn(() => Promise.resolve(mockSession()))
w3mFrame.user = mockSession()
diff --git a/packages/adapters/wagmi/src/connectors/AuthConnector.ts b/packages/adapters/wagmi/src/connectors/AuthConnector.ts
index a44c21c4a1..55c7724a62 100644
--- a/packages/adapters/wagmi/src/connectors/AuthConnector.ts
+++ b/packages/adapters/wagmi/src/connectors/AuthConnector.ts
@@ -138,6 +138,7 @@ export function authConnector(parameters: AuthParameters) {
chainId?: number
isReconnecting?: boolean
socialUri?: string
+ rpcUrl?: string
} = {}
) {
if (connectSocialPromise) {
diff --git a/packages/adapters/wagmi/src/tests/client.test.ts b/packages/adapters/wagmi/src/tests/client.test.ts
index dd51ba7885..7ea1725367 100644
--- a/packages/adapters/wagmi/src/tests/client.test.ts
+++ b/packages/adapters/wagmi/src/tests/client.test.ts
@@ -877,7 +877,7 @@ describe('WagmiAdapter', () => {
chainId: 'eip155:1',
preferredAccountType: 'smartAccount'
})
- expect(mockAuthProvider.switchNetwork).toHaveBeenCalledWith('eip155:1')
+ expect(mockAuthProvider.switchNetwork).toHaveBeenCalledWith({ chainId: 'eip155:1' })
})
})
diff --git a/packages/appkit/src/adapters/ChainAdapterBlueprint.ts b/packages/appkit/src/adapters/ChainAdapterBlueprint.ts
index ce2c71fd48..a0472fd7b7 100644
--- a/packages/appkit/src/adapters/ChainAdapterBlueprint.ts
+++ b/packages/appkit/src/adapters/ChainAdapterBlueprint.ts
@@ -351,7 +351,7 @@ export abstract class AdapterBlueprint<
if (provider && providerType === 'AUTH') {
const authProvider = provider as W3mFrameProvider
const preferredAccountType = getPreferredAccountType(caipNetwork.chainNamespace)
- await authProvider.switchNetwork(caipNetwork.caipNetworkId)
+ await authProvider.switchNetwork({ chainId: caipNetwork.caipNetworkId })
const user = await authProvider.getUser({
chainId: caipNetwork.caipNetworkId,
preferredAccountType
diff --git a/packages/controllers/src/utils/ConnectorControllerUtil.ts b/packages/controllers/src/utils/ConnectorControllerUtil.ts
index 35f8cc0a50..109c200797 100644
--- a/packages/controllers/src/utils/ConnectorControllerUtil.ts
+++ b/packages/controllers/src/utils/ConnectorControllerUtil.ts
@@ -150,7 +150,11 @@ export const ConnectorControllerUtil = {
properties: { provider: socialProvider }
})
}
- await authConnector.provider.connectSocial(uri)
+ const network = ChainController.state.activeCaipNetwork
+ await authConnector.provider.connectSocial({
+ uri,
+ chainId: network?.caipNetworkId
+ })
if (socialProvider) {
StorageUtil.setConnectedSocialProvider(socialProvider)
diff --git a/packages/siwx/src/configs/DefaultSIWX.ts b/packages/siwx/src/configs/DefaultSIWX.ts
index cd5d59d135..940e789306 100644
--- a/packages/siwx/src/configs/DefaultSIWX.ts
+++ b/packages/siwx/src/configs/DefaultSIWX.ts
@@ -9,7 +9,12 @@ const DEFAULTS = {
new InformalMessenger({
domain: typeof document === 'undefined' ? 'Unknown Domain' : document.location.host,
uri: typeof document === 'undefined' ? 'Unknown URI' : document.location.href,
- getNonce: async () => Promise.resolve(Math.round(Math.random() * 10000).toString())
+ getNonce: async () =>
+ Promise.resolve(
+ Math.round(Math.random() * 100000000)
+ .toString()
+ .padStart(8, '0')
+ )
}),
getDefaultVerifiers: () => [new EIP155Verifier(), new SolanaVerifier(), new BIP122Verifier()],
diff --git a/packages/wallet/src/W3mFrame.ts b/packages/wallet/src/W3mFrame.ts
index f635ae9ff7..ea108a79ac 100644
--- a/packages/wallet/src/W3mFrame.ts
+++ b/packages/wallet/src/W3mFrame.ts
@@ -16,6 +16,30 @@ interface W3mFrameConfig {
isAppClient?: boolean
chainId?: W3mFrameTypes.Network['chainId']
enableLogger?: boolean
+ rpcUrl?: string
+}
+
+function createSecureSiteSdkUrl({
+ projectId,
+ chainId,
+ version,
+ enableLogger,
+ rpcUrl = ConstantsUtil.BLOCKCHAIN_API_RPC_URL
+}: {
+ projectId: string
+ chainId: W3mFrameTypes.Network['chainId']
+ version: string
+ enableLogger: boolean
+ rpcUrl?: string
+}): string {
+ const url = new URL(SECURE_SITE_SDK)
+ url.searchParams.set('projectId', projectId)
+ url.searchParams.set('chainId', String(chainId))
+ url.searchParams.set('version', version)
+ url.searchParams.set('enableLogger', String(enableLogger))
+ url.searchParams.set('rpcUrl', rpcUrl)
+
+ return url.toString()
}
// -- Sdk --------------------------------------------------------------------
@@ -26,7 +50,7 @@ export class W3mFrame {
private projectId: string
- private rpcUrl = ConstantsUtil.BLOCKCHAIN_API_RPC_URL
+ private rpcUrl: string
public frameLoadPromise: Promise
@@ -41,13 +65,15 @@ export class W3mFrame {
projectId,
isAppClient = false,
chainId = 'eip155:1',
- enableLogger = true
+ enableLogger = true,
+ rpcUrl = ConstantsUtil.BLOCKCHAIN_API_RPC_URL
}: W3mFrameConfig) {
this.projectId = projectId
this.frameLoadPromise = new Promise((resolve, reject) => {
this.frameLoadPromiseResolver = { resolve, reject }
})
+ this.rpcUrl = rpcUrl
// Create iframe only when sdk is initialised from dapp / appkit
if (isAppClient) {
this.frameLoadPromise = new Promise((resolve, reject) => {
@@ -56,7 +82,13 @@ export class W3mFrame {
if (W3mFrameHelpers.isClient) {
const iframe = document.createElement('iframe')
iframe.id = 'w3m-iframe'
- iframe.src = `${SECURE_SITE_SDK}?projectId=${projectId}&chainId=${chainId}&version=${SECURE_SITE_SDK_VERSION}&enableLogger=${enableLogger}`
+ iframe.src = createSecureSiteSdkUrl({
+ projectId,
+ chainId,
+ version: SECURE_SITE_SDK_VERSION,
+ enableLogger,
+ rpcUrl: this.rpcUrl
+ })
iframe.name = 'w3m-secure-iframe'
iframe.style.position = 'fixed'
iframe.style.zIndex = '999999'
diff --git a/packages/wallet/src/W3mFrameProvider.ts b/packages/wallet/src/W3mFrameProvider.ts
index e0d3a5c0a9..b98cbc67d3 100644
--- a/packages/wallet/src/W3mFrameProvider.ts
+++ b/packages/wallet/src/W3mFrameProvider.ts
@@ -1,5 +1,9 @@
-import type { ChainNamespace, EmbeddedWalletTimeoutReason } from '@reown/appkit-common'
-import type { CaipNetwork } from '@reown/appkit-common'
+import {
+ type ChainNamespace,
+ type EmbeddedWalletTimeoutReason,
+ ParseUtil
+} from '@reown/appkit-common'
+import type { CaipNetwork, CaipNetworkId } from '@reown/appkit-common'
import { W3mFrame } from './W3mFrame.js'
import { W3mFrameConstants, W3mFrameRpcConstants } from './W3mFrameConstants.js'
@@ -53,8 +57,8 @@ export class W3mFrameProvider {
}
this.abortController = abortController
this.getActiveCaipNetwork = getActiveCaipNetwork
-
- this.w3mFrame = new W3mFrame({ projectId, isAppClient: true, chainId, enableLogger })
+ const rpcUrl = this.getRpcUrl(chainId)
+ this.w3mFrame = new W3mFrame({ projectId, isAppClient: true, chainId, enableLogger, rpcUrl })
this.onTimeout = onTimeout
if (this.getLoginEmailUsed()) {
this.createFrame()
@@ -315,13 +319,15 @@ export class W3mFrameProvider {
if (payload?.socialUri) {
try {
await this.init()
+ const rpcUrl = this.getRpcUrl(payload.chainId)
const response = await this.appEvent<'ConnectSocial'>({
type: W3mFrameConstants.APP_CONNECT_SOCIAL,
payload: {
uri: payload.socialUri,
preferredAccountType: payload.preferredAccountType,
chainId: payload.chainId,
- siwxMessage: payload.siwxMessage
+ siwxMessage: payload.siwxMessage,
+ rpcUrl
}
} as W3mFrameTypes.AppEvent)
@@ -346,7 +352,8 @@ export class W3mFrameProvider {
const response = await this.getUser({
chainId,
preferredAccountType: payload?.preferredAccountType,
- siwxMessage: payload?.siwxMessage
+ siwxMessage: payload?.siwxMessage,
+ rpcUrl: this.getRpcUrl(chainId)
})
this.setLoginSuccess(response.email)
@@ -378,12 +385,21 @@ export class W3mFrameProvider {
}
}
- public async connectSocial(uri: string) {
+ public async connectSocial({
+ uri,
+ chainId,
+ preferredAccountType
+ }: {
+ uri: string
+ chainId?: number | string
+ preferredAccountType?: string
+ }) {
try {
await this.init()
+ const rpcUrl = this.getRpcUrl(chainId)
const response = await this.appEvent<'ConnectSocial'>({
type: W3mFrameConstants.APP_CONNECT_SOCIAL,
- payload: { uri }
+ payload: { uri, chainId, rpcUrl, preferredAccountType }
} as W3mFrameTypes.AppEvent)
if (response.userName) {
@@ -428,11 +444,12 @@ export class W3mFrameProvider {
}
}
- public async switchNetwork(chainId: number | string) {
+ public async switchNetwork({ chainId }: { chainId: number | string }) {
try {
+ const rpcUrl = this.getRpcUrl(chainId)
const response = await this.appEvent<'SwitchNetwork'>({
type: W3mFrameConstants.APP_SWITCH_NETWORK,
- payload: { chainId }
+ payload: { chainId, rpcUrl }
} as W3mFrameTypes.AppEvent)
this.setLastUsedChainId(response.chainId)
@@ -478,8 +495,8 @@ export class W3mFrameProvider {
const namespace = req.chainNamespace || 'eip155'
const chainId = this.getActiveCaipNetwork(namespace)?.id
request.chainNamespace = namespace
-
request.chainId = chainId
+ request.rpcUrl = this.getRpcUrl(chainId)
this.rpcRequestHandler?.(req)
const response = await this.appEvent<'Rpc'>({
@@ -750,6 +767,24 @@ export class W3mFrameProvider {
private persistSmartAccountEnabledNetworks(networks: number[]) {
W3mFrameStorage.set(W3mFrameConstants.SMART_ACCOUNT_ENABLED_NETWORKS, networks.join(','))
}
+
+ private getRpcUrl(chainId?: number | string) {
+ let namespace: ChainNamespace | undefined = chainId === undefined ? undefined : 'eip155'
+
+ if (typeof chainId === 'string') {
+ if (chainId.includes(':')) {
+ namespace = ParseUtil.parseCaipNetworkId(chainId as CaipNetworkId)?.chainNamespace
+ } else if (Number.isInteger(Number(chainId))) {
+ namespace = 'eip155'
+ } else {
+ namespace = 'solana'
+ }
+ }
+
+ const activeNetwork = this.getActiveCaipNetwork(namespace)
+
+ return activeNetwork?.rpcUrls.default.http?.[0]
+ }
}
export interface W3mFrameProviderMethods {
diff --git a/packages/wallet/src/W3mFrameSchema.ts b/packages/wallet/src/W3mFrameSchema.ts
index 2222111332..e36f081aac 100644
--- a/packages/wallet/src/W3mFrameSchema.ts
+++ b/packages/wallet/src/W3mFrameSchema.ts
@@ -52,20 +52,25 @@ export const GetTransactionByHashResponse = z.object({
v: z.string(),
value: z.string()
})
-export const AppSwitchNetworkRequest = z.object({ chainId: z.string().or(z.number()) })
+export const AppSwitchNetworkRequest = z.object({
+ chainId: z.string().or(z.number()),
+ rpcUrl: z.optional(z.string())
+})
export const AppConnectEmailRequest = z.object({ email: z.string().email() })
export const AppConnectOtpRequest = z.object({ otp: z.string() })
export const AppConnectSocialRequest = z.object({
uri: z.string(),
preferredAccountType: z.optional(z.string()),
chainId: z.optional(z.string().or(z.number())),
- siwxMessage: z.optional(SIWXMessage)
+ siwxMessage: z.optional(SIWXMessage),
+ rpcUrl: z.optional(z.string())
})
export const AppGetUserRequest = z.object({
chainId: z.optional(z.string().or(z.number())),
preferredAccountType: z.optional(z.string()),
socialUri: z.optional(z.string()),
- siwxMessage: z.optional(SIWXMessage)
+ siwxMessage: z.optional(SIWXMessage),
+ rpcUrl: z.optional(z.string())
})
export const AppGetSocialRedirectUriRequest = z.object({
provider: z.enum(['google', 'github', 'apple', 'facebook', 'x', 'discord'])
@@ -568,7 +573,8 @@ export const W3mFrameSchema = {
chainId: z.string().or(z.number()).optional(),
chainNamespace: z
.enum(['eip155', 'solana', 'polkadot', 'bip122', 'cosmos'])
- .optional()
+ .optional(),
+ rpcUrl: z.string().optional()
})
)
})
diff --git a/packages/wallet/src/W3mFrameTypes.ts b/packages/wallet/src/W3mFrameTypes.ts
index 24b1b00b36..6f94127359 100644
--- a/packages/wallet/src/W3mFrameTypes.ts
+++ b/packages/wallet/src/W3mFrameTypes.ts
@@ -192,7 +192,7 @@ export namespace W3mFrameTypes {
| z.infer
| z.infer
| z.infer
- ) & { chainNamespace?: ChainNamespace; chainId?: string | number }
+ ) & { chainNamespace?: ChainNamespace; chainId?: string | number; rpcUrl?: string }
export type RPCResponse = z.infer
diff --git a/packages/wallet/tests/W3mFrame.test.ts b/packages/wallet/tests/W3mFrame.test.ts
index 01b1f998a9..30f03e7fc1 100644
--- a/packages/wallet/tests/W3mFrame.test.ts
+++ b/packages/wallet/tests/W3mFrame.test.ts
@@ -1,5 +1,7 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
+import { ConstantsUtil } from '@reown/appkit-common'
+
import { W3mFrame } from '../src/W3mFrame.js'
import { W3mFrameConstants } from '../src/W3mFrameConstants.js'
import { W3mFrameHelpers } from '../src/W3mFrameHelpers.js'
@@ -199,4 +201,32 @@ describe('W3mFrame', () => {
)
})
})
+
+ describe('rpcUrl', () => {
+ it('should default to ConstantsUtil.BLOCKCHAIN_API_RPC_URL when rpcUrl is undefined', () => {
+ w3mFrame = new W3mFrame({ projectId: PROJECT_ID, isAppClient: true })
+
+ const encodedDefaultRpcUrl = encodeURIComponent(ConstantsUtil.BLOCKCHAIN_API_RPC_URL)
+
+ // iframe src should contain the encoded default rpc url
+ expect(w3mFrame['iframe']?.src).toContain(`rpcUrl=${encodedDefaultRpcUrl}`)
+
+ // networks getter should construct rpc urls based on the default value
+ const expectedNetworkRpcUrl = `${ConstantsUtil.BLOCKCHAIN_API_RPC_URL}/v1/?chainId=eip155:1&projectId=${PROJECT_ID}`
+ expect(w3mFrame.networks?.['eip155:1']?.rpcUrl).toBe(expectedNetworkRpcUrl)
+ })
+
+ it('should use the provided custom rpcUrl when supplied', () => {
+ const CUSTOM_RPC_URL = 'https://custom.rpc.domain'
+
+ w3mFrame = new W3mFrame({ projectId: PROJECT_ID, isAppClient: true, rpcUrl: CUSTOM_RPC_URL })
+
+ // iframe src should contain the encoded custom rpc url
+ expect(w3mFrame['iframe']?.src).toContain(`rpcUrl=${encodeURIComponent(CUSTOM_RPC_URL)}`)
+
+ // networks getter should construct rpc urls based on the custom value
+ const expectedNetworkRpcUrl = `${CUSTOM_RPC_URL}/v1/?chainId=eip155:1&projectId=${PROJECT_ID}`
+ expect(w3mFrame.networks['eip155:1']?.rpcUrl).toBe(expectedNetworkRpcUrl)
+ })
+ })
})
diff --git a/packages/wallet/tests/W3mFrameProvider.test.ts b/packages/wallet/tests/W3mFrameProvider.test.ts
index 20be4a279a..06831c5be3 100644
--- a/packages/wallet/tests/W3mFrameProvider.test.ts
+++ b/packages/wallet/tests/W3mFrameProvider.test.ts
@@ -1,7 +1,11 @@
import * as logger from '@walletconnect/logger'
import { beforeEach, describe, expect, it, vi } from 'vitest'
-import type { EmbeddedWalletTimeoutReason } from '@reown/appkit-common'
+import type {
+ CaipNetworkId,
+ ChainNamespace,
+ EmbeddedWalletTimeoutReason
+} from '@reown/appkit-common'
import { W3mFrameConstants } from '../src/W3mFrameConstants.js'
import { W3mFrameProvider } from '../src/W3mFrameProvider.js'
@@ -10,6 +14,15 @@ import { SecureSiteMock } from './mocks/SecureSite.mock.js'
// Mocks
import { W3mFrameHelpers } from './mocks/W3mFrameHelpers.mock.js'
+const getActiveCaipNetwork = () => ({
+ name: 'Ethereum',
+ nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
+ rpcUrls: { default: { http: ['https://rpc.ankr.com/eth'] } },
+ id: 'eip155:1',
+ chainNamespace: 'eip155' as ChainNamespace,
+ caipNetworkId: 'eip155:1' as CaipNetworkId
+})
+
describe('W3mFrameProvider', () => {
const mockTimeout = vi.fn<(reason: EmbeddedWalletTimeoutReason) => void>()
@@ -19,14 +32,19 @@ describe('W3mFrameProvider', () => {
beforeEach(() => {
abortController = new AbortController()
- provider = new W3mFrameProvider({ projectId, abortController, onTimeout: mockTimeout })
+ provider = new W3mFrameProvider({
+ projectId,
+ abortController,
+ onTimeout: mockTimeout,
+ getActiveCaipNetwork
+ })
window.postMessage = vi.fn()
mockTimeout.mockClear()
})
it('should connect email', async () => {
provider['w3mFrame'].frameLoadPromise = Promise.resolve()
- provider.isInitialized = true
+ provider['isInitialized'] = true
const payload = { email: 'test@example.com' }
W3mFrameHelpers.checkIfAllowedToTriggerEmail.mockReturnValue(true)
const responsePayload = { action: 'VERIFY_OTP' }
@@ -53,7 +71,7 @@ describe('W3mFrameProvider', () => {
it('should connect otp', async () => {
provider['w3mFrame'].frameLoadPromise = Promise.resolve()
- provider.isInitialized = true
+ provider['isInitialized'] = true
const payload = { otp: '123456' }
const postAppEventSpy = vi
.spyOn(provider['w3mFrame'].events, 'postAppEvent')
@@ -73,7 +91,7 @@ describe('W3mFrameProvider', () => {
it('should connect', async () => {
provider['w3mFrame'].frameLoadPromise = Promise.resolve()
- provider.isInitialized = true
+ provider['isInitialized'] = true
const payload = { chainId: 1 }
const responsePayload = { address: '0xd34db33f', chainId: 1, email: 'test@walletconnect.com' }
@@ -95,7 +113,7 @@ describe('W3mFrameProvider', () => {
it('should connect social', async () => {
provider['w3mFrame'].frameLoadPromise = Promise.resolve()
- provider.isInitialized = true
+ provider['isInitialized'] = true
const payload = { chainId: 1, socialUri: '?auth=12345678' }
const responsePayload = {
address: '0xd34db33f',
@@ -141,7 +159,7 @@ describe('W3mFrameProvider', () => {
})
})
- const response = await provider.switchNetwork(chainId)
+ const response = await provider.switchNetwork({ chainId })
expect(response).toEqual(responsePayload)
expect(postAppEventSpy).toHaveBeenCalled()
@@ -155,12 +173,13 @@ describe('W3mFrameProvider', () => {
const testProvider = new W3mFrameProvider({
projectId,
onTimeout: onTimeoutMock,
- abortController: testAbortController
+ abortController: testAbortController,
+ getActiveCaipNetwork
})
vi.spyOn(testProvider['w3mFrame'].events, 'postAppEvent').mockImplementation(() => {})
- testProvider.isInitialized = true
+ testProvider['isInitialized'] = true
testProvider['w3mFrame'].iframeIsReady = true
testProvider['w3mFrame'].frameLoadPromise = Promise.resolve()
@@ -181,7 +200,12 @@ describe('W3mFrameProvider', () => {
it('should create logger if enableLogger is undefined', async () => {
const generateChildLoggerSpy = vi.spyOn(logger, 'generateChildLogger')
- provider = new W3mFrameProvider({ projectId, enableLogger: true, abortController })
+ provider = new W3mFrameProvider({
+ projectId,
+ enableLogger: true,
+ abortController,
+ getActiveCaipNetwork
+ })
provider['w3mFrame'].frameLoadPromise = Promise.resolve()
expect(generateChildLoggerSpy).toHaveBeenCalled()
})
@@ -189,7 +213,12 @@ describe('W3mFrameProvider', () => {
it('should create logger if enableLogger is true', async () => {
const generatePlatformLoggerSpy = vi.spyOn(logger, 'generatePlatformLogger')
- provider = new W3mFrameProvider({ projectId, enableLogger: true, abortController })
+ provider = new W3mFrameProvider({
+ projectId,
+ enableLogger: true,
+ abortController,
+ getActiveCaipNetwork
+ })
provider['w3mFrame'].frameLoadPromise = Promise.resolve()
expect(generatePlatformLoggerSpy).toHaveBeenCalled()
})
@@ -197,7 +226,12 @@ describe('W3mFrameProvider', () => {
it('should not create logger if enableLogger is false', async () => {
const generatePlatformLoggerSpy = vi.spyOn(logger, 'generatePlatformLogger')
- provider = new W3mFrameProvider({ projectId, enableLogger: false, abortController })
+ provider = new W3mFrameProvider({
+ projectId,
+ enableLogger: false,
+ abortController,
+ getActiveCaipNetwork
+ })
provider['w3mFrame'].frameLoadPromise = Promise.resolve()
expect(generatePlatformLoggerSpy).not.toHaveBeenCalled()
})
@@ -210,10 +244,11 @@ describe('W3mFrameProvider', () => {
const testProvider = new W3mFrameProvider({
projectId,
onTimeout: onTimeoutMock,
- abortController: testAbortController
+ abortController: testAbortController,
+ getActiveCaipNetwork
})
- testProvider.isInitialized = true
+ testProvider['isInitialized'] = true
testProvider['w3mFrame'].frameLoadPromise = Promise.resolve()
testProvider.connectEmail({ email: 'test@example.com' }).catch(() => {})
@@ -229,4 +264,44 @@ describe('W3mFrameProvider', () => {
vi.useRealTimers()
})
+
+ it('should return correct rpc url based on chainId parameter in getRpcUrl', () => {
+ const eip155RpcUrl = 'https://rpc.ankr.com/eth'
+ const solanaRpcUrl = 'https://api.mainnet-beta.solana.com'
+
+ const customGetActiveCaipNetwork = (namespace?: ChainNamespace) => {
+ if (namespace === 'solana') {
+ return {
+ name: 'Solana',
+ nativeCurrency: { name: 'Sol', symbol: 'SOL', decimals: 9 },
+ rpcUrls: { default: { http: [solanaRpcUrl] } },
+ id: 'solana:1',
+ chainNamespace: 'solana' as ChainNamespace,
+ caipNetworkId: 'solana:1' as CaipNetworkId
+ }
+ }
+
+ return {
+ name: 'Ethereum',
+ nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
+ rpcUrls: { default: { http: [eip155RpcUrl] } },
+ id: 'eip155:1',
+ chainNamespace: 'eip155' as ChainNamespace,
+ caipNetworkId: 'eip155:1' as CaipNetworkId
+ }
+ }
+
+ const rpcProvider = new W3mFrameProvider({
+ projectId,
+ enableLogger: false,
+ abortController: new AbortController(),
+ getActiveCaipNetwork: customGetActiveCaipNetwork
+ })
+
+ expect(rpcProvider['getRpcUrl']()).toBe(eip155RpcUrl)
+ expect(rpcProvider['getRpcUrl'](1)).toBe(eip155RpcUrl)
+ expect(rpcProvider['getRpcUrl']('eip155:1')).toBe(eip155RpcUrl)
+ expect(rpcProvider['getRpcUrl']('1')).toBe(eip155RpcUrl)
+ expect(rpcProvider['getRpcUrl']('AzDjsjkalwnalsdnj2kh')).toBe(solanaRpcUrl)
+ })
})