@qinzhehan/rainbow-wallet-kit 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -3
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +22 -2
- package/dist/index.mjs +573 -244
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +2 -2
- package/dist/index.umd.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +1 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../src/types.ts","../src/core/auth.ts","../src/core/deepLinks.ts","../src/core/eventEmitter.ts","../src/core/errors.ts","../src/core/storageSync.ts","../src/wallets/eip1193.ts","../src/wallets/phantom.ts","../src/wallets/index.ts","../src/react/WalletProvider.tsx","../src/react/useWallet.ts","../src/react/ConnectWalletButton.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\n\nexport type ChainType = 'evm' | 'solana';\nexport type WalletId = 'metamask' | 'okx' | 'phantom';\nexport type WalletStatus = 'idle' | 'connecting' | 'connected' | 'disconnected' | 'error';\n\nexport interface WalletAccount {\n address: string;\n chainType: ChainType;\n chainId?: string | number;\n publicKey?: string;\n}\n\nexport interface WalletState {\n status: WalletStatus;\n wallet?: WalletId;\n account?: WalletAccount;\n auth?: AuthSession;\n error?: WalletKitError;\n updatedAt: number;\n}\n\nexport interface AuthSession {\n token: string;\n expiresAt: number;\n refreshToken?: string;\n}\n\nexport interface NonceRequest {\n wallet: WalletId;\n address: string;\n chainType: ChainType;\n audience?: string;\n}\n\nexport interface VerifySignaturePayload extends NonceRequest {\n nonce: string;\n message: string;\n signature: string;\n}\n\nexport interface JwtRefreshRequest {\n token: string;\n refreshToken?: string;\n wallet: WalletId;\n address: string;\n}\n\nexport interface WalletAuthConfig {\n enabled?: boolean;\n audience?: string;\n renewalWindowMs?: number;\n getNonce?: (request: NonceRequest) => Promise<string>;\n verifySignature?: (payload: VerifySignaturePayload) => Promise<AuthSession>;\n refreshJwt?: (request: JwtRefreshRequest) => Promise<AuthSession>;\n}\n\nexport interface DeepLinkConfig {\n enabled?: boolean;\n openOnConnect?: boolean;\n dappUrl?: string;\n metamask?: string;\n okx?: string;\n phantom?: string;\n}\n\nexport interface WalletKitOptions {\n auth?: WalletAuthConfig;\n deepLinks?: DeepLinkConfig;\n connectTimeoutMs?: number;\n storageKey?: string;\n}\n\nexport interface WalletProviderProps extends WalletKitOptions {\n children: ReactNode;\n initialWallet?: WalletId;\n autoConnect?: boolean;\n}\n\nexport type WalletKitErrorCode =\n | 'PROVIDER_NOT_FOUND'\n | 'USER_REJECTED'\n | 'CONNECT_TIMEOUT'\n | 'SIGNATURE_REJECTED'\n | 'AUTH_FAILED'\n | 'JWT_REFRESH_FAILED'\n | 'UNSUPPORTED_CHAIN'\n | 'UNKNOWN';\n\nexport class WalletKitError extends Error {\n code: WalletKitErrorCode;\n cause?: unknown;\n\n constructor(code: WalletKitErrorCode, message: string, cause?: unknown) {\n super(message);\n this.name = 'WalletKitError';\n this.code = code;\n this.cause = cause;\n }\n}\n\nexport interface WalletAdapter {\n id: WalletId;\n name: string;\n chainType: ChainType;\n icon: string;\n installed: () => boolean;\n connect: () => Promise<WalletAccount>;\n disconnect?: () => Promise<void>;\n signMessage: (message: string, account: WalletAccount) => Promise<string>;\n getDeepLink: (targetUrl: string) => string;\n}\n\nexport type WalletEventMap = {\n state: WalletState;\n accountChanged: WalletAccount | undefined;\n disconnect: undefined;\n error: WalletKitError;\n};\n\nexport interface WalletContextValue {\n state: WalletState;\n wallets: WalletAdapter[];\n connect: (wallet: WalletId) => Promise<void>;\n disconnect: () => Promise<void>;\n openWalletApp: (wallet: WalletId) => void;\n refreshAuth: () => Promise<void>;\n}\n","import { WalletKitError } from '../types';\nimport type { AuthSession, WalletAccount, WalletAuthConfig, WalletId } from '../types';\n\nexport function createNonceMessage(input: {\n nonce: string;\n address: string;\n wallet: WalletId;\n chainType: string;\n audience?: string;\n}): string {\n return [\n input.audience ?? 'Wallet Login',\n '',\n `Wallet: ${input.wallet}`,\n `Address: ${input.address}`,\n `Chain: ${input.chainType}`,\n `Nonce: ${input.nonce}`,\n `Issued At: ${new Date().toISOString()}`,\n ].join('\\n');\n}\n\nexport async function authenticateWallet(input: {\n auth?: WalletAuthConfig;\n wallet: WalletId;\n account: WalletAccount;\n signMessage: (message: string) => Promise<string>;\n}): Promise<AuthSession | undefined> {\n if (!input.auth?.enabled) return undefined;\n if (!input.auth.getNonce || !input.auth.verifySignature) {\n throw new WalletKitError('AUTH_FAILED', 'Wallet auth requires getNonce and verifySignature callbacks.');\n }\n\n const nonce = await input.auth.getNonce({\n wallet: input.wallet,\n address: input.account.address,\n chainType: input.account.chainType,\n audience: input.auth.audience,\n });\n const message = createNonceMessage({\n nonce,\n address: input.account.address,\n wallet: input.wallet,\n chainType: input.account.chainType,\n audience: input.auth.audience,\n });\n const signature = await input.signMessage(message).catch((error) => {\n throw new WalletKitError('SIGNATURE_REJECTED', 'Wallet signature was rejected or failed.', error);\n });\n\n return input.auth.verifySignature({\n wallet: input.wallet,\n address: input.account.address,\n chainType: input.account.chainType,\n audience: input.auth.audience,\n nonce,\n message,\n signature,\n });\n}\n\nexport async function refreshJwtSession(input: {\n auth?: WalletAuthConfig;\n session?: AuthSession;\n wallet?: WalletId;\n account?: WalletAccount;\n}): Promise<AuthSession | undefined> {\n if (!input.auth?.enabled || !input.auth.refreshJwt || !input.session || !input.wallet || !input.account) {\n return input.session;\n }\n\n try {\n return await input.auth.refreshJwt({\n token: input.session.token,\n refreshToken: input.session.refreshToken,\n wallet: input.wallet,\n address: input.account.address,\n });\n } catch (error) {\n throw new WalletKitError('JWT_REFRESH_FAILED', 'JWT refresh failed.', error);\n }\n}\n\nexport function getRenewalDelay(session: AuthSession, windowMs = 60_000): number {\n return Math.max(0, session.expiresAt - Date.now() - windowMs);\n}\n","import type { DeepLinkConfig, WalletId } from '../types';\n\nconst DEFAULT_DEEP_LINKS: Required<Pick<DeepLinkConfig, 'metamask' | 'okx' | 'phantom'>> = {\n metamask: 'https://metamask.app.link/dapp/',\n okx: 'okx://wallet/dapp/url?dappUrl=',\n phantom: 'https://phantom.app/ul/browse/',\n};\n\nexport function isMobileH5(): boolean {\n if (typeof navigator === 'undefined') return false;\n return /Android|iPhone|iPad|iPod|Mobile/i.test(navigator.userAgent);\n}\n\nexport function resolveDappUrl(config?: DeepLinkConfig): string {\n if (config?.dappUrl) return config.dappUrl;\n if (typeof window === 'undefined') return '';\n return window.location.href;\n}\n\nexport function getWalletDeepLink(wallet: WalletId, targetUrl: string, config?: DeepLinkConfig): string {\n const encoded = encodeURIComponent(targetUrl);\n if (wallet === 'metamask') return `${config?.metamask ?? DEFAULT_DEEP_LINKS.metamask}${targetUrl.replace(/^https?:\\/\\//, '')}`;\n if (wallet === 'okx') return `${config?.okx ?? DEFAULT_DEEP_LINKS.okx}${encoded}`;\n return `${config?.phantom ?? DEFAULT_DEEP_LINKS.phantom}${encoded}?ref=${encoded}`;\n}\n","type Listener<T> = (payload: T) => void;\n\nexport class EventEmitter<Events extends Record<string, unknown>> {\n private listeners = new Map<keyof Events, Set<Listener<Events[keyof Events]>>>();\n\n on<Key extends keyof Events>(event: Key, listener: Listener<Events[Key]>): () => void {\n const listeners = this.listeners.get(event) ?? new Set();\n listeners.add(listener as Listener<Events[keyof Events]>);\n this.listeners.set(event, listeners);\n return () => this.off(event, listener);\n }\n\n off<Key extends keyof Events>(event: Key, listener: Listener<Events[Key]>): void {\n this.listeners.get(event)?.delete(listener as Listener<Events[keyof Events]>);\n }\n\n emit<Key extends keyof Events>(event: Key, payload: Events[Key]): void {\n this.listeners.get(event)?.forEach((listener) => listener(payload));\n }\n\n removeAllListeners(): void {\n this.listeners.clear();\n }\n}\n","import { WalletKitError } from '../types';\n\nexport function normalizeWalletError(error: unknown): WalletKitError {\n if (error instanceof WalletKitError) return error;\n\n const maybe = error as { code?: number | string; message?: string } | undefined;\n if (maybe?.code === 4001 || maybe?.code === 'ACTION_REJECTED') {\n return new WalletKitError('USER_REJECTED', maybe.message ?? 'User rejected wallet request.', error);\n }\n\n if (maybe?.message?.toLowerCase().includes('timeout')) {\n return new WalletKitError('CONNECT_TIMEOUT', maybe.message, error);\n }\n\n return new WalletKitError('UNKNOWN', maybe?.message ?? 'Unexpected wallet error.', error);\n}\n\nexport function withTimeout<T>(promise: Promise<T>, timeoutMs: number, message: string): Promise<T> {\n let timeout: ReturnType<typeof setTimeout> | undefined;\n const timeoutPromise = new Promise<T>((_, reject) => {\n timeout = setTimeout(() => reject(new WalletKitError('CONNECT_TIMEOUT', message)), timeoutMs);\n });\n\n return Promise.race([promise, timeoutPromise]).finally(() => {\n if (timeout) clearTimeout(timeout);\n });\n}\n","import { EventEmitter } from './eventEmitter';\nimport type { WalletEventMap, WalletState } from '../types';\n\nconst SYNC_EVENT = 'rainbow-wallet-kit:state';\n\nexport class WalletStateSync {\n private channel?: BroadcastChannel;\n private tabId = Math.random().toString(36).slice(2);\n\n constructor(\n private emitter: EventEmitter<WalletEventMap>,\n private storageKey: string,\n ) {\n if (typeof window === 'undefined') return;\n\n if ('BroadcastChannel' in window) {\n this.channel = new BroadcastChannel(SYNC_EVENT);\n this.channel.onmessage = (event: MessageEvent<{ tabId: string; state: WalletState }>) => {\n if (event.data?.tabId !== this.tabId) {\n this.emitter.emit('state', event.data.state);\n }\n };\n }\n\n window.addEventListener('storage', this.handleStorage);\n }\n\n publish(state: WalletState): void {\n if (typeof window === 'undefined') return;\n const payload = { tabId: this.tabId, state };\n localStorage.setItem(this.storageKey, JSON.stringify(payload));\n this.channel?.postMessage(payload);\n }\n\n read(): WalletState | undefined {\n if (typeof window === 'undefined') return undefined;\n const raw = localStorage.getItem(this.storageKey);\n if (!raw) return undefined;\n\n try {\n const parsed = JSON.parse(raw) as { state?: WalletState };\n return parsed.state;\n } catch {\n return undefined;\n }\n }\n\n destroy(): void {\n this.channel?.close();\n if (typeof window !== 'undefined') {\n window.removeEventListener('storage', this.handleStorage);\n }\n }\n\n private handleStorage = (event: StorageEvent) => {\n if (event.key !== this.storageKey || !event.newValue) return;\n try {\n const payload = JSON.parse(event.newValue) as { tabId: string; state: WalletState };\n if (payload.tabId !== this.tabId) {\n this.emitter.emit('state', payload.state);\n }\n } catch {\n // Ignore malformed cross-tab payloads from older package versions.\n }\n };\n}\n","import { getWalletDeepLink } from '../core/deepLinks';\nimport { WalletKitError } from '../types';\nimport type { DeepLinkConfig, WalletAccount, WalletAdapter, WalletId } from '../types';\nimport type { Eip1193Provider } from './providerTypes';\n\nfunction pickInjectedProvider(wallet: WalletId): Eip1193Provider | undefined {\n if (typeof window === 'undefined') return undefined;\n\n const candidates = collectInjectedProviders(wallet);\n const providers = candidates.flatMap((provider) => provider.providers ?? []);\n const allProviders = uniqueProviders([...candidates, ...providers]);\n\n if (wallet === 'okx') {\n const matched = allProviders.find(isOkxProvider);\n if (matched) return matched;\n\n if (window.okxwallet?.request) return window.okxwallet;\n }\n\n if (providers?.length) {\n const matched = providers.find((provider) => {\n if (wallet === 'metamask') return provider.isMetaMask && !provider.isOkxWallet;\n return isOkxProvider(provider);\n });\n if (matched) return matched;\n }\n\n const injected = wallet === 'metamask' ? window.ethereum : window.okxwallet?.ethereum ?? window.ethereum;\n if (wallet === 'metamask' && injected?.isMetaMask && !isOkxProvider(injected)) return injected;\n if (wallet === 'okx' && injected && isOkxProvider(injected)) return injected;\n return undefined;\n}\n\nfunction collectInjectedProviders(wallet: WalletId): Eip1193Provider[] {\n const providers: Array<Eip1193Provider | undefined> = [\n window.ethereum,\n window.okxwallet,\n window.okxwallet?.ethereum,\n ];\n\n if (wallet === 'metamask') {\n return uniqueProviders([window.ethereum, ...(window.ethereum?.providers ?? [])]);\n }\n\n return uniqueProviders(providers);\n}\n\nfunction uniqueProviders(providers: Array<Eip1193Provider | undefined>): Eip1193Provider[] {\n return providers.filter((provider, index, list): provider is Eip1193Provider => {\n return Boolean(provider?.request) && list.indexOf(provider) === index;\n });\n}\n\nfunction isOkxProvider(provider?: Eip1193Provider): boolean {\n return Boolean(provider?.isOkxWallet || provider?.isOKExWallet || provider?.isOKXWallet);\n}\n\nfunction hexToNumber(hex?: string): number | undefined {\n if (!hex) return undefined;\n return Number.parseInt(hex, 16);\n}\n\nexport function createEvmAdapter(options: {\n id: Extract<WalletId, 'metamask' | 'okx'>;\n name: string;\n icon: string;\n deepLinks?: DeepLinkConfig;\n}): WalletAdapter {\n return {\n id: options.id,\n name: options.name,\n chainType: 'evm',\n icon: options.icon,\n installed: () => Boolean(pickInjectedProvider(options.id)),\n connect: async (): Promise<WalletAccount> => {\n const provider = pickInjectedProvider(options.id);\n if (!provider) {\n throw new WalletKitError('PROVIDER_NOT_FOUND', `${options.name} provider was not found.`);\n }\n\n const accounts = await provider.request<string[]>({ method: 'eth_requestAccounts' });\n const chainId = await provider.request<string>({ method: 'eth_chainId' }).catch(() => undefined);\n const address = accounts[0];\n if (!address) throw new WalletKitError('PROVIDER_NOT_FOUND', `${options.name} did not return an address.`);\n\n return {\n address,\n chainType: 'evm',\n chainId: hexToNumber(chainId),\n };\n },\n signMessage: async (message: string, account: WalletAccount): Promise<string> => {\n const provider = pickInjectedProvider(options.id);\n if (!provider) throw new WalletKitError('PROVIDER_NOT_FOUND', `${options.name} provider was not found.`);\n return provider.request<string>({\n method: 'personal_sign',\n params: [message, account.address],\n });\n },\n getDeepLink: (targetUrl: string) => getWalletDeepLink(options.id, targetUrl, options.deepLinks),\n };\n}\n","import { getWalletDeepLink } from '../core/deepLinks';\nimport { WalletKitError } from '../types';\nimport type { DeepLinkConfig, WalletAccount, WalletAdapter } from '../types';\nimport type { PhantomSolanaProvider } from './providerTypes';\n\nfunction getProvider(): PhantomSolanaProvider | undefined {\n if (typeof window === 'undefined') return undefined;\n return window.phantom?.solana?.isPhantom ? window.phantom.solana : undefined;\n}\n\nfunction bytesToBase64(bytes: Uint8Array): string {\n let binary = '';\n bytes.forEach((byte) => {\n binary += String.fromCharCode(byte);\n });\n return btoa(binary);\n}\n\nexport function createPhantomAdapter(deepLinks?: DeepLinkConfig): WalletAdapter {\n return {\n id: 'phantom',\n name: 'Phantom',\n chainType: 'solana',\n icon: 'P',\n installed: () => Boolean(getProvider()),\n connect: async (): Promise<WalletAccount> => {\n const provider = getProvider();\n if (!provider) throw new WalletKitError('PROVIDER_NOT_FOUND', 'Phantom provider was not found.');\n const response = await provider.connect();\n const address = response.publicKey.toString();\n return {\n address,\n publicKey: address,\n chainType: 'solana',\n chainId: 'solana:mainnet',\n };\n },\n disconnect: async () => {\n await getProvider()?.disconnect?.();\n },\n signMessage: async (message: string): Promise<string> => {\n const provider = getProvider();\n if (!provider) throw new WalletKitError('PROVIDER_NOT_FOUND', 'Phantom provider was not found.');\n const encoded = new TextEncoder().encode(message);\n const { signature } = await provider.signMessage(encoded, 'utf8');\n return bytesToBase64(signature);\n },\n getDeepLink: (targetUrl: string) => getWalletDeepLink('phantom', targetUrl, deepLinks),\n };\n}\n","import type { DeepLinkConfig, WalletAdapter } from '../types';\nimport { createEvmAdapter } from './eip1193';\nimport { createPhantomAdapter } from './phantom';\n\nexport function createWalletAdapters(deepLinks?: DeepLinkConfig): WalletAdapter[] {\n return [\n createEvmAdapter({ id: 'metamask', name: 'MetaMask', icon: 'M', deepLinks }),\n createEvmAdapter({ id: 'okx', name: 'OKX Wallet', icon: 'O', deepLinks }),\n createPhantomAdapter(deepLinks),\n ];\n}\n","import { createContext, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { authenticateWallet, getRenewalDelay, refreshJwtSession } from '../core/auth';\nimport { isMobileH5, resolveDappUrl } from '../core/deepLinks';\nimport { EventEmitter } from '../core/eventEmitter';\nimport { normalizeWalletError, withTimeout } from '../core/errors';\nimport { WalletStateSync } from '../core/storageSync';\nimport { WalletKitError } from '../types';\nimport { createWalletAdapters } from '../wallets';\nimport type { WalletContextValue, WalletEventMap, WalletId, WalletProviderProps, WalletState } from '../types';\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\nconst DEFAULT_STORAGE_KEY = 'rainbow-wallet-kit:wallet-state';\n\nconst initialState: WalletState = {\n status: 'idle',\n updatedAt: Date.now(),\n};\n\nexport const WalletContext = createContext<WalletContextValue | undefined>(undefined);\n\nexport function WalletProvider({\n children,\n auth,\n deepLinks,\n connectTimeoutMs = DEFAULT_TIMEOUT_MS,\n storageKey = DEFAULT_STORAGE_KEY,\n initialWallet,\n autoConnect,\n}: WalletProviderProps) {\n const emitterRef = useRef(new EventEmitter<WalletEventMap>());\n const syncRef = useRef<WalletStateSync | null>(null);\n const [state, setState] = useState<WalletState>(initialState);\n const wallets = useMemo(() => createWalletAdapters(deepLinks), [deepLinks]);\n\n const publishState = useCallback((nextState: WalletState) => {\n setState(nextState);\n emitterRef.current.emit('state', nextState);\n syncRef.current?.publish(nextState);\n }, []);\n\n const connect = useCallback(\n async (walletId: WalletId) => {\n const wallet = wallets.find((item) => item.id === walletId);\n if (!wallet) return;\n\n if (!wallet.installed() && deepLinks?.enabled !== false && deepLinks?.openOnConnect && isMobileH5()) {\n window.location.href = wallet.getDeepLink(resolveDappUrl(deepLinks));\n return;\n }\n\n if (!wallet.installed()) {\n const error = new WalletKitError('PROVIDER_NOT_FOUND', `${wallet.name} extension was not found.`);\n publishState({\n status: 'error',\n wallet: walletId,\n error,\n updatedAt: Date.now(),\n });\n emitterRef.current.emit('error', error);\n throw error;\n }\n\n const connectingState: WalletState = {\n ...state,\n status: 'connecting',\n wallet: walletId,\n error: undefined,\n updatedAt: Date.now(),\n };\n publishState(connectingState);\n\n try {\n const account = await withTimeout(\n wallet.connect(),\n connectTimeoutMs,\n `${wallet.name} connection timed out.`,\n );\n const session = await authenticateWallet({\n auth,\n wallet: walletId,\n account,\n signMessage: (message) => wallet.signMessage(message, account),\n });\n publishState({\n status: 'connected',\n wallet: walletId,\n account,\n auth: session,\n updatedAt: Date.now(),\n });\n emitterRef.current.emit('accountChanged', account);\n } catch (error) {\n const normalized = normalizeWalletError(error);\n publishState({\n status: 'error',\n wallet: walletId,\n error: normalized,\n updatedAt: Date.now(),\n });\n emitterRef.current.emit('error', normalized);\n throw normalized;\n }\n },\n [auth, connectTimeoutMs, deepLinks, publishState, state, wallets],\n );\n\n const openWalletApp = useCallback(\n (walletId: WalletId) => {\n const wallet = wallets.find((item) => item.id === walletId);\n if (!wallet || deepLinks?.enabled === false || typeof window === 'undefined') return;\n window.location.href = wallet.getDeepLink(resolveDappUrl(deepLinks));\n },\n [deepLinks, wallets],\n );\n\n const disconnect = useCallback(async () => {\n const wallet = wallets.find((item) => item.id === state.wallet);\n await wallet?.disconnect?.();\n const nextState: WalletState = {\n status: 'disconnected',\n updatedAt: Date.now(),\n };\n publishState(nextState);\n emitterRef.current.emit('disconnect', undefined);\n }, [publishState, state.wallet, wallets]);\n\n const refreshAuth = useCallback(async () => {\n const session = await refreshJwtSession({\n auth,\n session: state.auth,\n wallet: state.wallet,\n account: state.account,\n });\n if (session && state.status === 'connected') {\n publishState({\n ...state,\n auth: session,\n updatedAt: Date.now(),\n });\n }\n }, [auth, publishState, state]);\n\n useEffect(() => {\n const sync = new WalletStateSync(emitterRef.current, storageKey);\n syncRef.current = sync;\n const stored = sync.read();\n if (stored) setState(stored);\n\n const unsubscribe = emitterRef.current.on('state', (nextState) => {\n setState((current) => (nextState.updatedAt >= current.updatedAt ? nextState : current));\n });\n\n return () => {\n unsubscribe();\n sync.destroy();\n };\n }, [storageKey]);\n\n useEffect(() => {\n if (autoConnect && initialWallet) {\n void connect(initialWallet).catch(() => undefined);\n }\n }, [autoConnect, connect, initialWallet]);\n\n useEffect(() => {\n if (!state.auth || state.status !== 'connected') return;\n const delay = getRenewalDelay(state.auth, auth?.renewalWindowMs);\n const timer = window.setTimeout(() => {\n void refreshAuth().catch((error) => {\n const normalized = normalizeWalletError(error);\n publishState({ ...state, status: 'error', error: normalized, updatedAt: Date.now() });\n });\n }, delay);\n return () => window.clearTimeout(timer);\n }, [auth?.renewalWindowMs, publishState, refreshAuth, state]);\n\n const value = useMemo<WalletContextValue>(\n () => ({\n state,\n wallets,\n connect,\n disconnect,\n openWalletApp,\n refreshAuth,\n }),\n [connect, disconnect, openWalletApp, refreshAuth, state, wallets],\n );\n\n return <WalletContext.Provider value={value}>{children}</WalletContext.Provider>;\n}\n","import { useContext } from 'react';\nimport { WalletContext } from './WalletProvider';\n\nexport function useWallet() {\n const context = useContext(WalletContext);\n if (!context) {\n throw new Error('useWallet must be used inside WalletProvider.');\n }\n return context;\n}\n","import { useState } from 'react';\nimport type { WalletId } from '../types';\nimport { useWallet } from './useWallet';\n\nexport interface ConnectWalletButtonProps {\n label?: string;\n className?: string;\n preferredWallets?: WalletId[];\n onError?: (error: unknown) => void;\n}\n\nexport function ConnectWalletButton({\n label = 'Connect Wallet',\n className = '',\n preferredWallets,\n onError,\n}: ConnectWalletButtonProps) {\n const { state, wallets, connect, disconnect } = useWallet();\n const [open, setOpen] = useState(false);\n const orderedWallets = preferredWallets?.length\n ? preferredWallets.flatMap((id) => wallets.filter((wallet) => wallet.id === id))\n : wallets;\n\n if (state.status === 'connected' && state.account) {\n return (\n <div className={`rwk-root ${className}`}>\n <button className=\"rwk-account\" type=\"button\" onClick={() => setOpen((value) => !value)}>\n <span className=\"rwk-status-dot\" />\n <span>{shortenAddress(state.account.address)}</span>\n </button>\n {open ? (\n <div className=\"rwk-panel\" role=\"dialog\" aria-label=\"Wallet account\">\n <div className=\"rwk-account-row\">\n <span>{state.wallet}</span>\n <strong>{shortenAddress(state.account.address)}</strong>\n </div>\n <button className=\"rwk-disconnect\" type=\"button\" onClick={() => void disconnect()}>\n Disconnect\n </button>\n </div>\n ) : null}\n </div>\n );\n }\n\n return (\n <div className={`rwk-root ${className}`}>\n <button\n className=\"rwk-connect\"\n type=\"button\"\n disabled={state.status === 'connecting'}\n onClick={() => setOpen((value) => !value)}\n >\n {state.status === 'connecting' ? 'Connecting...' : label}\n </button>\n {open ? (\n <div className=\"rwk-panel\" role=\"dialog\" aria-label=\"Connect wallet\">\n {orderedWallets.map((wallet) => (\n <button\n className=\"rwk-wallet\"\n key={wallet.id}\n type=\"button\"\n onClick={() => {\n void connect(wallet.id)\n .then(() => setOpen(false))\n .catch((error) => onError?.(error));\n }}\n >\n <span className=\"rwk-wallet-icon\">{wallet.icon}</span>\n <span>{wallet.name}</span>\n <small>{wallet.installed() ? 'Detected' : 'Not installed'}</small>\n </button>\n ))}\n {state.error ? <p className=\"rwk-error\">{state.error.message}</p> : null}\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction shortenAddress(address: string): string {\n if (address.length <= 12) return address;\n return `${address.slice(0, 6)}...${address.slice(-4)}`;\n}\n"],"names":["WalletKitError","code","message","cause","__publicField","createNonceMessage","input","authenticateWallet","_a","nonce","signature","error","refreshJwtSession","getRenewalDelay","session","windowMs","DEFAULT_DEEP_LINKS","isMobileH5","resolveDappUrl","config","getWalletDeepLink","wallet","targetUrl","encoded","EventEmitter","event","listener","listeners","payload","normalizeWalletError","maybe","withTimeout","promise","timeoutMs","timeout","timeoutPromise","_","reject","SYNC_EVENT","WalletStateSync","emitter","storageKey","state","raw","pickInjectedProvider","candidates","collectInjectedProviders","providers","provider","allProviders","uniqueProviders","matched","isOkxProvider","injected","_b","index","list","hexToNumber","hex","createEvmAdapter","options","accounts","chainId","address","account","getProvider","bytesToBase64","bytes","binary","byte","createPhantomAdapter","deepLinks","createWalletAdapters","DEFAULT_TIMEOUT_MS","DEFAULT_STORAGE_KEY","initialState","WalletContext","createContext","WalletProvider","children","auth","connectTimeoutMs","initialWallet","autoConnect","emitterRef","useRef","syncRef","setState","useState","wallets","useMemo","publishState","useCallback","nextState","connect","walletId","item","connectingState","normalized","openWalletApp","disconnect","refreshAuth","useEffect","sync","stored","unsubscribe","current","delay","timer","value","jsx","useWallet","context","useContext","ConnectWalletButton","label","className","preferredWallets","onError","open","setOpen","orderedWallets","id","jsxs","shortenAddress"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/types.ts","../src/core/auth.ts","../src/core/deepLinks.ts","../src/core/eventEmitter.ts","../src/core/errors.ts","../src/core/networks.ts","../src/core/storageSync.ts","../src/assets/metamask.png","../src/assets/okx.png","../src/assets/phantom.png","../src/wallets/eip1193.ts","../src/wallets/phantom.ts","../src/wallets/index.ts","../src/react/WalletProvider.tsx","../src/react/useWallet.ts","../src/react/ConnectWalletButton.tsx"],"sourcesContent":["// 只引入 ReactNode 这个类型,用来描述 Provider 接收的 children。\nimport type { ReactNode } from 'react';\n\n// ChainType 表示当前钱包属于哪一种链生态,evm 是以太坊兼容链,solana 是 Solana 链。\nexport type ChainType = 'evm' | 'solana';\n// WalletId 是这个包内置支持的钱包标识,后续连接时会用这个 id 找到对应适配器。\nexport type WalletId = 'metamask' | 'okx' | 'phantom';\n// WalletStatus 表示钱包连接流程当前处于什么状态,方便 UI 展示不同内容。\nexport type WalletStatus = 'idle' | 'connecting' | 'connected' | 'disconnected' | 'error';\n\n// WalletNetwork 描述一个可以让钱包切换到的网络。\nexport interface WalletNetwork {\n // id 是组件内部使用的网络唯一标识。\n id: string;\n // name 是展示给用户看的网络名称。\n name: string;\n // chainType 表示这个网络属于 EVM 还是 Solana。\n chainType: ChainType;\n // chainId 是钱包切换网络时用到的链 ID。\n chainId: string | number;\n // rpcUrls 是钱包添加新 EVM 网络时需要的 RPC 地址。\n rpcUrls?: string[];\n // nativeCurrency 是钱包添加新 EVM 网络时展示的原生代币信息。\n nativeCurrency?: {\n // name 是代币名称。\n name: string;\n // symbol 是代币符号。\n symbol: string;\n // decimals 是代币小数位。\n decimals: number;\n };\n // blockExplorerUrls 是区块浏览器地址。\n blockExplorerUrls?: string[];\n}\n\n// WalletAccount 描述一次钱包连接成功后拿到的账户信息。\nexport interface WalletAccount {\n // address 是钱包地址,EVM 是 0x 开头地址,Solana 是 publicKey 字符串。\n address: string;\n // chainType 说明这个地址来自 EVM 生态还是 Solana 生态。\n chainType: ChainType;\n // chainId 是链 ID,EVM 常见是数字,Solana 这里用字符串标识。\n chainId?: string | number;\n // publicKey 是 Solana 常用字段,EVM 钱包一般不需要。\n publicKey?: string;\n}\n\n// WalletState 是组件库内部保存的钱包总状态。\nexport interface WalletState {\n // status 表示当前连接状态,比如 connected 表示已连接。\n status: WalletStatus;\n // wallet 表示当前选中或已连接的钱包,比如 metamask。\n wallet?: WalletId;\n // account 表示连接成功后得到的钱包账户。\n account?: WalletAccount;\n // auth 表示签名登录后后端返回的登录态,例如 JWT。\n auth?: AuthSession;\n // error 保存最近一次钱包连接或认证失败的错误。\n error?: WalletKitError;\n // updatedAt 记录状态更新时间,用来解决多 Tab 同步时的新旧状态比较。\n updatedAt: number;\n}\n\n// AuthSession 表示后端认证成功后返回的会话信息。\nexport interface AuthSession {\n // token 通常是 JWT,业务请求可以用它证明用户已经登录。\n token: string;\n // expiresAt 是 token 过期时间戳,单位通常是毫秒。\n expiresAt: number;\n // refreshToken 是可选的刷新令牌,用来换取新的 JWT。\n refreshToken?: string;\n}\n\n// NonceRequest 表示前端向后端请求 nonce 时传递的信息。\nexport interface NonceRequest {\n // wallet 表示用户正在用哪个钱包登录。\n wallet: WalletId;\n // address 表示当前钱包地址。\n address: string;\n // chainType 表示当前链生态。\n chainType: ChainType;\n // audience 是可选的业务系统名,用来写进签名文案。\n audience?: string;\n}\n\n// VerifySignaturePayload 表示前端把签名结果交给后端验签时的数据。\nexport interface VerifySignaturePayload extends NonceRequest {\n // nonce 是后端生成的一次性随机字符串,用来防止旧签名被重复使用。\n nonce: string;\n // message 是用户钱包实际签名的完整文本。\n message: string;\n // signature 是钱包对 message 签出来的结果。\n signature: string;\n}\n\n// JwtRefreshRequest 表示前端请求后端刷新 JWT 时传递的数据。\nexport interface JwtRefreshRequest {\n // token 是当前快过期或需要刷新的 JWT。\n token: string;\n // refreshToken 是可选的刷新令牌。\n refreshToken?: string;\n // wallet 表示当前登录的钱包类型。\n wallet: WalletId;\n // address 表示当前登录的钱包地址。\n address: string;\n}\n\n// WalletAuthConfig 是钱包签名登录相关配置。\nexport interface WalletAuthConfig {\n // enabled 决定是否启用 nonce 签名登录流程。\n enabled?: boolean;\n // audience 是写进签名消息里的业务名称。\n audience?: string;\n // renewalWindowMs 表示 JWT 到期前多久开始自动续期。\n renewalWindowMs?: number;\n // getNonce 是业务方提供的函数,负责从后端拿一次性 nonce。\n getNonce?: (request: NonceRequest) => Promise<string>;\n // verifySignature 是业务方提供的函数,负责把签名交给后端验证。\n verifySignature?: (payload: VerifySignaturePayload) => Promise<AuthSession>;\n // refreshJwt 是业务方提供的函数,负责自动续期 JWT。\n refreshJwt?: (request: JwtRefreshRequest) => Promise<AuthSession>;\n}\n\n// DeepLinkConfig 是移动端跳转钱包 App 的配置。\nexport interface DeepLinkConfig {\n // enabled 控制是否允许使用 DeepLink 功能。\n enabled?: boolean;\n // openOnConnect 控制未检测到扩展时,点击钱包是否自动跳转 App。\n openOnConnect?: boolean;\n // dappUrl 是要传给钱包 App 打开的当前 DApp 地址。\n dappUrl?: string;\n // metamask 可以覆盖默认 MetaMask DeepLink 前缀。\n metamask?: string;\n // okx 可以覆盖默认 OKX Wallet DeepLink 前缀。\n okx?: string;\n // phantom 可以覆盖默认 Phantom DeepLink 前缀。\n phantom?: string;\n}\n\n// WalletKitOptions 是 WalletProvider 可以接收的通用配置。\nexport interface WalletKitOptions {\n // auth 是签名登录配置。\n auth?: WalletAuthConfig;\n // deepLinks 是移动端钱包 App 跳转配置。\n deepLinks?: DeepLinkConfig;\n // connectTimeoutMs 是连接钱包的超时时间。\n connectTimeoutMs?: number;\n // storageKey 是多 Tab 同步时写入 localStorage 的 key。\n storageKey?: string;\n // networks 是业务方可以自定义的网络列表,不传时使用默认 EVM 网络列表。\n networks?: WalletNetwork[];\n}\n\n// WalletProviderProps 是 React Provider 组件的 props。\nexport interface WalletProviderProps extends WalletKitOptions {\n // children 是被 Provider 包住的业务组件。\n children: ReactNode;\n // initialWallet 是可选的默认钱包。\n initialWallet?: WalletId;\n // autoConnect 控制是否在 Provider 初始化时自动连接 initialWallet。\n autoConnect?: boolean;\n}\n\n// WalletKitErrorCode 统一描述钱包组件可能抛出的错误类型。\nexport type WalletKitErrorCode =\n // PROVIDER_NOT_FOUND 表示没有检测到对应钱包插件。\n | 'PROVIDER_NOT_FOUND'\n // USER_REJECTED 表示用户在钱包弹窗里拒绝了操作。\n | 'USER_REJECTED'\n // CONNECT_TIMEOUT 表示连接钱包超时。\n | 'CONNECT_TIMEOUT'\n // REQUEST_PENDING 表示钱包扩展里已经有一个同类请求在等待用户处理。\n | 'REQUEST_PENDING'\n // SIGNATURE_REJECTED 表示用户拒绝签名或签名失败。\n | 'SIGNATURE_REJECTED'\n // AUTH_FAILED 表示签名登录配置或后端认证失败。\n | 'AUTH_FAILED'\n // JWT_REFRESH_FAILED 表示 JWT 自动续期失败。\n | 'JWT_REFRESH_FAILED'\n // UNSUPPORTED_CHAIN 表示当前链不支持。\n | 'UNSUPPORTED_CHAIN'\n // SWITCH_NETWORK_FAILED 表示钱包切换网络失败。\n | 'SWITCH_NETWORK_FAILED'\n // UNKNOWN 表示无法归类的未知错误。\n | 'UNKNOWN';\n\n// WalletKitError 是组件库统一抛出的错误类。\nexport class WalletKitError extends Error {\n // code 保存机器可读的错误码。\n code: WalletKitErrorCode;\n // cause 保存原始错误,方便调试底层钱包报错。\n cause?: unknown;\n\n // constructor 在创建错误对象时保存错误码、错误消息和原始原因。\n constructor(code: WalletKitErrorCode, message: string, cause?: unknown) {\n // 调用 Error 父类构造函数,保存 message。\n super(message);\n // name 帮助调试时看出这是钱包组件库的错误。\n this.name = 'WalletKitError';\n // code 保存统一错误码。\n this.code = code;\n // cause 保存原始错误对象。\n this.cause = cause;\n }\n}\n\n// WalletAdapter 是每个钱包适配器必须实现的统一接口。\nexport interface WalletAdapter {\n // id 是钱包唯一标识。\n id: WalletId;\n // name 是展示给用户看的钱包名称。\n name: string;\n // chainType 表示钱包所属链生态。\n chainType: ChainType;\n // icon 是简化版图标文本,用于按钮左侧展示。\n icon: string;\n // installed 用来判断浏览器里是否检测到这个钱包插件。\n installed: () => boolean;\n // connect 负责真正调用钱包插件并返回账户信息。\n connect: () => Promise<WalletAccount>;\n // disconnect 是可选断开方法,有些钱包提供,有些没有。\n disconnect?: () => Promise<void>;\n // signMessage 负责让钱包对一段文本签名。\n signMessage: (message: string, account: WalletAccount) => Promise<string>;\n // switchNetwork 负责请求钱包切换网络,不支持的钱包可以不实现。\n switchNetwork?: (network: WalletNetwork) => Promise<WalletAccount | undefined>;\n // getDeepLink 负责生成移动端打开钱包 App 的链接。\n getDeepLink: (targetUrl: string) => string;\n}\n\n// WalletEventMap 定义 EventEmitter 里支持的事件和对应数据。\nexport type WalletEventMap = {\n // state 事件在钱包总状态变化时触发。\n state: WalletState;\n // accountChanged 事件在账户变化时触发。\n accountChanged: WalletAccount | undefined;\n // disconnect 事件在断开钱包时触发。\n disconnect: undefined;\n // error 事件在发生钱包错误时触发。\n error: WalletKitError;\n};\n\n// WalletContextValue 是 useWallet 能拿到的上下文能力。\nexport interface WalletContextValue {\n // state 是当前钱包状态。\n state: WalletState;\n // wallets 是所有内置钱包适配器列表。\n wallets: WalletAdapter[];\n // networks 是当前可切换网络列表。\n networks: WalletNetwork[];\n // connect 用来连接指定钱包。\n connect: (wallet: WalletId) => Promise<void>;\n // switchNetwork 用来切换当前钱包网络。\n switchNetwork: (networkId: string) => Promise<void>;\n // disconnect 用来断开当前钱包。\n disconnect: () => Promise<void>;\n // openWalletApp 用来显式打开移动端钱包 App。\n openWalletApp: (wallet: WalletId) => void;\n // refreshAuth 用来手动刷新 JWT 登录态。\n refreshAuth: () => Promise<void>;\n}\n","// 引入统一错误类,认证流程失败时会用它抛出明确错误。\nimport { WalletKitError } from '../types';\n// 引入认证流程需要用到的类型,type import 不会进入最终运行时代码。\nimport type { AuthSession, WalletAccount, WalletAuthConfig, WalletId } from '../types';\n\n// createNonceMessage 用来把 nonce、地址、钱包等信息拼成用户要签名的文本。\nexport function createNonceMessage(input: {\n // nonce 是后端生成的一次性随机字符串。\n nonce: string;\n // address 是当前连接的钱包地址。\n address: string;\n // wallet 是当前使用的钱包类型。\n wallet: WalletId;\n // chainType 是当前链生态。\n chainType: string;\n // audience 是可选业务名称,例如你的 DApp 名称。\n audience?: string;\n}): string {\n // 返回数组再 join,是为了让签名文本结构清晰、每行含义明确。\n return [\n // 第一行显示业务名称,如果没有传 audience 就用默认的 Wallet Login。\n input.audience ?? 'Wallet Login',\n // 插入空行,让钱包签名弹窗里显示更易读。\n '',\n // 写入钱包类型,例如 metamask。\n `Wallet: ${input.wallet}`,\n // 写入钱包地址,后端验签时会用到。\n `Address: ${input.address}`,\n // 写入链类型,例如 evm。\n `Chain: ${input.chainType}`,\n // 写入一次性 nonce,防止旧签名被重复使用。\n `Nonce: ${input.nonce}`,\n // 写入签发时间,方便后端或用户审计。\n `Issued At: ${new Date().toISOString()}`,\n // 用换行符把上面的数组拼成一整段签名文本。\n ].join('\\n');\n}\n\n// authenticateWallet 负责完整的钱包签名登录流程。\nexport async function authenticateWallet(input: {\n // auth 是业务方传入的认证配置。\n auth?: WalletAuthConfig;\n // wallet 是当前连接的钱包 id。\n wallet: WalletId;\n // account 是当前连接成功的钱包账户。\n account: WalletAccount;\n // signMessage 是适配器提供的签名函数。\n signMessage: (message: string) => Promise<string>;\n}): Promise<AuthSession | undefined> {\n // 如果没有启用认证,直接返回 undefined,表示只连接钱包不登录。\n if (!input.auth?.enabled) return undefined;\n // 启用认证时,必须同时提供 getNonce 和 verifySignature。\n if (!input.auth.getNonce || !input.auth.verifySignature) {\n // 配置不完整时抛出统一的认证失败错误。\n throw new WalletKitError('AUTH_FAILED', 'Wallet auth requires getNonce and verifySignature callbacks.');\n }\n\n // 先调用业务后端拿 nonce。\n const nonce = await input.auth.getNonce({\n // 告诉后端当前使用的钱包类型。\n wallet: input.wallet,\n // 告诉后端当前钱包地址。\n address: input.account.address,\n // 告诉后端当前链生态。\n chainType: input.account.chainType,\n // 透传业务名称。\n audience: input.auth.audience,\n });\n // 根据后端返回的 nonce 拼出要让钱包签名的文本。\n const message = createNonceMessage({\n // 放入一次性 nonce。\n nonce,\n // 放入钱包地址。\n address: input.account.address,\n // 放入钱包类型。\n wallet: input.wallet,\n // 放入链生态。\n chainType: input.account.chainType,\n // 放入业务名称。\n audience: input.auth.audience,\n });\n // 调用钱包签名,如果用户拒绝或钱包失败,就转换成统一错误。\n const signature = await input.signMessage(message).catch((error) => {\n // 把底层错误包装成 SIGNATURE_REJECTED,方便业务层统一处理。\n throw new WalletKitError('SIGNATURE_REJECTED', 'Wallet signature was rejected or failed.', error);\n });\n\n // 把签名结果发给业务后端验证,验证成功后应该返回 AuthSession。\n return input.auth.verifySignature({\n // 传回钱包类型。\n wallet: input.wallet,\n // 传回钱包地址。\n address: input.account.address,\n // 传回链生态。\n chainType: input.account.chainType,\n // 传回业务名称。\n audience: input.auth.audience,\n // 传回 nonce,后端要检查它是否有效且未使用。\n nonce,\n // 传回签名原文,后端要验证签名对应的就是这段文本。\n message,\n // 传回钱包签名结果。\n signature,\n });\n}\n\n// refreshJwtSession 负责 JWT 快过期时调用业务方接口续期。\nexport async function refreshJwtSession(input: {\n // auth 是认证配置。\n auth?: WalletAuthConfig;\n // session 是当前已有登录态。\n session?: AuthSession;\n // wallet 是当前钱包类型。\n wallet?: WalletId;\n // account 是当前钱包账户。\n account?: WalletAccount;\n}): Promise<AuthSession | undefined> {\n // 如果没有启用认证、没有刷新函数、没有 session、没有钱包或账户,就保持原 session。\n if (!input.auth?.enabled || !input.auth.refreshJwt || !input.session || !input.wallet || !input.account) {\n // 返回原 session,表示不用刷新。\n return input.session;\n }\n\n // try/catch 用来把业务后端刷新失败统一包装成钱包组件错误。\n try {\n // 调用业务方提供的 refreshJwt 函数刷新登录态。\n return await input.auth.refreshJwt({\n // 传入当前 JWT。\n token: input.session.token,\n // 传入可选 refreshToken。\n refreshToken: input.session.refreshToken,\n // 传入钱包类型。\n wallet: input.wallet,\n // 传入钱包地址。\n address: input.account.address,\n });\n } catch (error) {\n // 刷新失败时抛出统一的 JWT_REFRESH_FAILED 错误。\n throw new WalletKitError('JWT_REFRESH_FAILED', 'JWT refresh failed.', error);\n }\n}\n\n// getRenewalDelay 计算距离下一次自动续期还要等多久。\nexport function getRenewalDelay(session: AuthSession, windowMs = 60_000): number {\n // 用过期时间减去当前时间,再减去提前续期窗口,最小值不能小于 0。\n return Math.max(0, session.expiresAt - Date.now() - windowMs);\n}\n","// 引入 DeepLink 配置类型和钱包 id 类型。\nimport type { DeepLinkConfig, WalletId } from '../types';\n\n// DEFAULT_DEEP_LINKS 保存各钱包默认的移动端打开链接前缀。\nconst DEFAULT_DEEP_LINKS: Required<Pick<DeepLinkConfig, 'metamask' | 'okx' | 'phantom'>> = {\n // MetaMask 的 dapp deep link 前缀。\n metamask: 'https://metamask.app.link/dapp/',\n // OKX Wallet 的 dapp deep link 前缀。\n okx: 'okx://wallet/dapp/url?dappUrl=',\n // Phantom 的浏览 deep link 前缀。\n phantom: 'https://phantom.app/ul/browse/',\n};\n\n// isMobileH5 判断当前是否是手机浏览器环境。\nexport function isMobileH5(): boolean {\n // 如果没有 navigator,说明不是浏览器环境,直接返回 false。\n if (typeof navigator === 'undefined') return false;\n // 用 userAgent 粗略判断 Android、iPhone、iPad 等移动端。\n return /Android|iPhone|iPad|iPod|Mobile/i.test(navigator.userAgent);\n}\n\n// resolveDappUrl 计算要传给钱包 App 的 DApp 地址。\nexport function resolveDappUrl(config?: DeepLinkConfig): string {\n // 如果业务方显式传了 dappUrl,就优先用它。\n if (config?.dappUrl) return config.dappUrl;\n // 如果不是浏览器环境,就没有当前页面地址。\n if (typeof window === 'undefined') return '';\n // 默认使用当前网页地址。\n return window.location.href;\n}\n\n// getWalletDeepLink 根据钱包类型生成移动端打开链接。\nexport function getWalletDeepLink(wallet: WalletId, targetUrl: string, config?: DeepLinkConfig): string {\n // 先把目标 URL 编码,避免特殊字符破坏 deep link 参数。\n const encoded = encodeURIComponent(targetUrl);\n // MetaMask 要求去掉 http/https 前缀后拼到 dapp 后面。\n if (wallet === 'metamask') return `${config?.metamask ?? DEFAULT_DEEP_LINKS.metamask}${targetUrl.replace(/^https?:\\/\\//, '')}`;\n // OKX 把编码后的 DApp URL 放到 dappUrl 参数里。\n if (wallet === 'okx') return `${config?.okx ?? DEFAULT_DEEP_LINKS.okx}${encoded}`;\n // Phantom 使用 browse 链接,并带上 ref 参数。\n return `${config?.phantom ?? DEFAULT_DEEP_LINKS.phantom}${encoded}?ref=${encoded}`;\n}\n","// Listener 表示一个事件监听函数,它接收某个事件对应的数据 payload。\ntype Listener<T> = (payload: T) => void;\n\n// EventEmitter 是一个轻量事件总线,用来在钱包状态变化时通知其它逻辑。\nexport class EventEmitter<Events extends Record<string, unknown>> {\n // listeners 保存所有事件名和对应的监听函数集合。\n private listeners = new Map<keyof Events, Set<Listener<Events[keyof Events]>>>();\n\n // on 用来注册事件监听,并返回一个取消监听的函数。\n on<Key extends keyof Events>(event: Key, listener: Listener<Events[Key]>): () => void {\n // 先取出这个事件已有的监听集合,如果没有就创建一个新的 Set。\n const listeners = this.listeners.get(event) ?? new Set();\n // 把当前监听函数加入集合,类型断言是为了适配泛型事件映射。\n listeners.add(listener as Listener<Events[keyof Events]>);\n // 把更新后的监听集合保存回 Map。\n this.listeners.set(event, listeners);\n // 返回取消函数,调用它就能移除刚才注册的监听。\n return () => this.off(event, listener);\n }\n\n // off 用来移除某个事件上的某个监听函数。\n off<Key extends keyof Events>(event: Key, listener: Listener<Events[Key]>): void {\n // 如果事件存在,就从 Set 中删除这个监听函数。\n this.listeners.get(event)?.delete(listener as Listener<Events[keyof Events]>);\n }\n\n // emit 用来触发事件,把 payload 发给所有监听者。\n emit<Key extends keyof Events>(event: Key, payload: Events[Key]): void {\n // 遍历这个事件的所有监听函数,并把 payload 传进去。\n this.listeners.get(event)?.forEach((listener) => listener(payload));\n }\n\n // removeAllListeners 用来清空所有事件监听。\n removeAllListeners(): void {\n // 清空 Map,释放所有监听引用。\n this.listeners.clear();\n }\n}\n","// 引入统一错误类,方便把不同钱包的错误格式整理成同一种格式。\nimport { WalletKitError } from '../types';\n\n// normalizeWalletError 把未知错误转换成 WalletKitError。\nexport function normalizeWalletError(error: unknown): WalletKitError {\n // 如果本来就是 WalletKitError,就不用重复包装。\n if (error instanceof WalletKitError) return error;\n\n // 把未知错误临时视为可能带 code 和 message 的对象。\n const maybe = error as { code?: number | string; message?: string } | undefined;\n // MetaMask 等 EVM 钱包里,4001 通常表示用户拒绝;ACTION_REJECTED 也是常见拒绝标识。\n if (maybe?.code === 4001 || maybe?.code === 'ACTION_REJECTED') {\n // 返回统一的 USER_REJECTED 错误。\n return new WalletKitError('USER_REJECTED', maybe.message ?? 'User rejected wallet request.', error);\n }\n\n // -32002 是 MetaMask 常见的“已有请求等待处理”错误码。\n if (maybe?.code === -32002 || maybe?.message?.toLowerCase().includes('already pending')) {\n // 返回统一的 REQUEST_PENDING 错误,提示用户先处理钱包扩展里的弹窗。\n return new WalletKitError('REQUEST_PENDING', maybe.message ?? 'Wallet request is already pending.', error);\n }\n\n // 如果错误消息里包含 timeout,就归类为连接超时。\n if (maybe?.message?.toLowerCase().includes('timeout')) {\n // 返回统一的 CONNECT_TIMEOUT 错误。\n return new WalletKitError('CONNECT_TIMEOUT', maybe.message, error);\n }\n\n // 其它无法识别的错误统一归类为 UNKNOWN。\n return new WalletKitError('UNKNOWN', maybe?.message ?? 'Unexpected wallet error.', error);\n}\n\n// withTimeout 给任意 Promise 增加超时能力。\nexport function withTimeout<T>(promise: Promise<T>, timeoutMs: number, message: string): Promise<T> {\n // timeout 保存 setTimeout 返回值,后面成功或失败后要清理。\n let timeout: ReturnType<typeof setTimeout> | undefined;\n // timeoutPromise 会在指定时间后 reject。\n const timeoutPromise = new Promise<T>((_, reject) => {\n // 到时间后抛出统一的 CONNECT_TIMEOUT 错误。\n timeout = setTimeout(() => reject(new WalletKitError('CONNECT_TIMEOUT', message)), timeoutMs);\n });\n\n // Promise.race 表示谁先完成就用谁的结果。\n return Promise.race([promise, timeoutPromise]).finally(() => {\n // 如果定时器还存在,就清掉,避免无意义的定时器残留。\n if (timeout) clearTimeout(timeout);\n });\n}\n","// 引入网络类型。\nimport type { WalletNetwork } from '../types';\n\n// DEFAULT_NETWORKS 是组件内置的常用 EVM 网络列表。\nexport const DEFAULT_NETWORKS: WalletNetwork[] = [\n {\n id: 'ethereum',\n name: 'Ethereum',\n chainType: 'evm',\n chainId: 1,\n rpcUrls: ['https://rpc.ankr.com/eth'],\n nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },\n blockExplorerUrls: ['https://etherscan.io'],\n },\n {\n id: 'polygon',\n name: 'Polygon',\n chainType: 'evm',\n chainId: 137,\n rpcUrls: ['https://polygon-rpc.com'],\n nativeCurrency: { name: 'MATIC', symbol: 'MATIC', decimals: 18 },\n blockExplorerUrls: ['https://polygonscan.com'],\n },\n {\n id: 'bsc',\n name: 'BNB Smart Chain',\n chainType: 'evm',\n chainId: 56,\n rpcUrls: ['https://bsc-dataseed.binance.org'],\n nativeCurrency: { name: 'BNB', symbol: 'BNB', decimals: 18 },\n blockExplorerUrls: ['https://bscscan.com'],\n },\n {\n id: 'arbitrum',\n name: 'Arbitrum One',\n chainType: 'evm',\n chainId: 42161,\n rpcUrls: ['https://arb1.arbitrum.io/rpc'],\n nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },\n blockExplorerUrls: ['https://arbiscan.io'],\n },\n {\n id: 'optimism',\n name: 'Optimism',\n chainType: 'evm',\n chainId: 10,\n rpcUrls: ['https://mainnet.optimism.io'],\n nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },\n blockExplorerUrls: ['https://optimistic.etherscan.io'],\n },\n {\n id: 'solana-mainnet',\n name: 'Solana Mainnet',\n chainType: 'solana',\n chainId: 'solana:mainnet',\n },\n];\n","// 引入包内事件总线,用来把跨 Tab 收到的状态继续广播给 React 层。\nimport { EventEmitter } from './eventEmitter';\n// 引入钱包事件和状态类型。\nimport type { WalletEventMap, WalletState } from '../types';\n\n// SYNC_EVENT 是 BroadcastChannel 的频道名,多 Tab 会通过同一个名字通信。\nconst SYNC_EVENT = 'rainbow-wallet-kit:state';\n\n// WalletStateSync 负责把钱包状态同步到其它浏览器 Tab。\nexport class WalletStateSync {\n // channel 保存 BroadcastChannel 实例,不支持的浏览器里它是 undefined。\n private channel?: BroadcastChannel;\n // tabId 是当前 Tab 的随机 id,用来避免收到自己发出的消息后重复处理。\n private tabId = Math.random().toString(36).slice(2);\n\n // constructor 在创建同步器时接收事件总线和 localStorage key。\n constructor(\n // emitter 用来把跨 Tab 收到的状态继续 emit 给应用内部。\n private emitter: EventEmitter<WalletEventMap>,\n // storageKey 是 localStorage 里存钱包状态的 key。\n private storageKey: string,\n ) {\n // 如果不是浏览器环境,就不做任何同步。\n if (typeof window === 'undefined') return;\n\n // 如果浏览器支持 BroadcastChannel,就优先使用它做实时同步。\n if ('BroadcastChannel' in window) {\n // 创建指定频道名的 BroadcastChannel。\n this.channel = new BroadcastChannel(SYNC_EVENT);\n // 监听其它 Tab 发来的消息。\n this.channel.onmessage = (event: MessageEvent<{ tabId: string; state: WalletState }>) => {\n // 如果消息不是当前 Tab 自己发的,就处理它。\n if (event.data?.tabId !== this.tabId) {\n // 把其它 Tab 的状态通过事件总线发给 React Provider。\n this.emitter.emit('state', event.data.state);\n }\n };\n }\n\n // storage 事件用于兜底同步,也能兼容不支持 BroadcastChannel 的场景。\n window.addEventListener('storage', this.handleStorage);\n }\n\n // publish 用来把当前 Tab 的钱包状态广播出去。\n publish(state: WalletState): void {\n // 非浏览器环境不支持 localStorage 和 BroadcastChannel。\n if (typeof window === 'undefined') return;\n // payload 里带 tabId,方便其它 Tab 判断消息来源。\n const payload = { tabId: this.tabId, state };\n // 写入 localStorage,刷新页面或新 Tab 可以读取最近状态。\n localStorage.setItem(this.storageKey, JSON.stringify(payload));\n // 通过 BroadcastChannel 实时通知其它 Tab。\n this.channel?.postMessage(payload);\n }\n\n // read 用来从 localStorage 读取最近一次钱包状态。\n read(): WalletState | undefined {\n // 非浏览器环境无法读取 localStorage。\n if (typeof window === 'undefined') return undefined;\n // 从 localStorage 读取原始字符串。\n const raw = localStorage.getItem(this.storageKey);\n // 没有缓存就返回 undefined。\n if (!raw) return undefined;\n\n // try/catch 防止 localStorage 里数据损坏导致页面崩溃。\n try {\n // 把 JSON 字符串解析成对象。\n const parsed = JSON.parse(raw) as { state?: WalletState };\n // 返回里面的钱包状态。\n return parsed.state;\n } catch {\n // 解析失败说明缓存数据不可用,直接忽略。\n return undefined;\n }\n }\n\n // destroy 用来清理事件监听和 BroadcastChannel。\n destroy(): void {\n // 关闭 BroadcastChannel,释放浏览器资源。\n this.channel?.close();\n // 如果在浏览器环境,移除 storage 监听。\n if (typeof window !== 'undefined') {\n // 移除构造函数里注册的 storage 事件。\n window.removeEventListener('storage', this.handleStorage);\n }\n }\n\n // handleStorage 是 localStorage 变化时触发的处理函数。\n private handleStorage = (event: StorageEvent) => {\n // 只处理当前钱包状态对应的 key,并且必须有新值。\n if (event.key !== this.storageKey || !event.newValue) return;\n // try/catch 防止其它脚本写入异常 JSON 导致报错。\n try {\n // 解析其它 Tab 写入的状态 payload。\n const payload = JSON.parse(event.newValue) as { tabId: string; state: WalletState };\n // 如果不是当前 Tab 自己写的,就继续同步。\n if (payload.tabId !== this.tabId) {\n // 通过事件总线发出 state 事件。\n this.emitter.emit('state', payload.state);\n }\n } catch {\n // 忽略旧版本或其它脚本写入的异常跨 Tab 数据。\n }\n };\n}\n","export default \"data:image/png;base64,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\"","export default \"data:image/png;base64,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\"","export default \"data:image/png;base64,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\"","// 引入 DeepLink 生成函数,移动端需要打开钱包 App 时会用到。\nimport { getWalletDeepLink } from '../core/deepLinks';\n// 引入统一错误类,找不到钱包或连接失败时会抛出。\nimport { WalletKitError } from '../types';\n// 引入这个文件需要的类型定义。\nimport type { DeepLinkConfig, WalletAccount, WalletAdapter, WalletId, WalletNetwork } from '../types';\n// 引入 EIP-1193 Provider 的类型定义。\nimport type { Eip1193Provider } from './providerTypes';\n\n// pickInjectedProvider 负责从浏览器 window 上找到指定钱包注入的 provider。\nfunction pickInjectedProvider(wallet: WalletId): Eip1193Provider | undefined {\n // 如果当前不是浏览器环境,例如服务端渲染,就没有 window,也就找不到插件。\n if (typeof window === 'undefined') return undefined;\n\n // 收集可能的钱包 provider 候选项。\n const candidates = collectInjectedProviders(wallet);\n // 有些钱包会把多个 provider 放到 providers 数组里,这里把它们摊平成一层数组。\n const providers = candidates.flatMap((provider) => provider.providers ?? []);\n // 合并直接候选 provider 和数组里的 provider,并去重。\n const allProviders = uniqueProviders([...candidates, ...providers]);\n\n // 如果用户要找 OKX 钱包,走 OKX 专门兼容逻辑。\n if (wallet === 'okx') {\n // 从所有 provider 里找标记为 OKX 的 provider。\n const matched = allProviders.find(isOkxProvider);\n // 如果找到了,就直接返回这个 OKX provider。\n if (matched) return matched;\n\n // OKX 官方文档里也可能直接把 request 挂在 window.okxwallet 上。\n if (window.okxwallet?.request) return window.okxwallet;\n }\n\n // 如果 providers 数组存在,优先从数组中精确找对应钱包。\n if (providers?.length) {\n // 遍历 providers 数组,找到 MetaMask 或 OKX。\n const matched = providers.find((provider) => {\n // MetaMask 要求 isMetaMask 为 true,并且不要误选到 OKX。\n if (wallet === 'metamask') return provider.isMetaMask && !provider.isOkxWallet;\n // 其它 EVM 钱包目前这里主要就是 OKX。\n return isOkxProvider(provider);\n });\n // 如果数组中找到了对应 provider,就返回它。\n if (matched) return matched;\n }\n\n // 如果没有 providers 数组,就回退到常见的单 provider 注入位置。\n const injected = wallet === 'metamask' ? window.ethereum : window.okxwallet?.ethereum ?? window.ethereum;\n // 如果目标是 MetaMask,并且注入对象确实像 MetaMask,就返回。\n if (wallet === 'metamask' && injected?.isMetaMask && !isOkxProvider(injected)) return injected;\n // 如果目标是 OKX,并且注入对象带 OKX 标识,就返回。\n if (wallet === 'okx' && injected && isOkxProvider(injected)) return injected;\n // 所有位置都没找到,就返回 undefined。\n return undefined;\n}\n\n// collectInjectedProviders 收集浏览器里可能存在的钱包 provider。\nfunction collectInjectedProviders(wallet: WalletId): Eip1193Provider[] {\n // 这些是常见的 EVM 钱包注入位置。\n const providers: Array<Eip1193Provider | undefined> = [\n // window.ethereum 是 MetaMask 等 EVM 钱包最常见的注入位置。\n window.ethereum,\n // window.okxwallet 是 OKX 新版本/官方文档常见的注入位置。\n window.okxwallet,\n // window.okxwallet.ethereum 是 OKX 也可能提供的 EVM 子 provider。\n window.okxwallet?.ethereum,\n ];\n\n // MetaMask 更应该从 window.ethereum 和它的 providers 数组里找,避免误选 OKX。\n if (wallet === 'metamask') {\n // 返回去重后的 MetaMask 候选项。\n return uniqueProviders([window.ethereum, ...(window.ethereum?.providers ?? [])]);\n }\n\n // OKX 走通用候选列表去重。\n return uniqueProviders(providers);\n}\n\n// uniqueProviders 用来过滤空值、过滤没有 request 方法的对象,并去掉重复对象。\nfunction uniqueProviders(providers: Array<Eip1193Provider | undefined>): Eip1193Provider[] {\n // filter 里使用类型谓词,让 TypeScript 知道过滤后一定是 Eip1193Provider。\n return providers.filter((provider, index, list): provider is Eip1193Provider => {\n // provider 必须存在,必须有 request 方法,并且不能在数组前面已经出现过。\n return Boolean(provider?.request) && list.indexOf(provider) === index;\n });\n}\n\n// isOkxProvider 判断一个 provider 是否像 OKX 钱包。\nfunction isOkxProvider(provider?: Eip1193Provider): boolean {\n // OKX 不同版本可能使用不同标识字段,所以这里同时兼容三个名字。\n return Boolean(provider?.isOkxWallet || provider?.isOKExWallet || provider?.isOKXWallet);\n}\n\n// hexToNumber 把 EVM 钱包返回的十六进制 chainId 转成数字。\nfunction hexToNumber(hex?: string): number | undefined {\n // 如果没有 chainId,就返回 undefined。\n if (!hex) return undefined;\n // Number.parseInt(hex, 16) 表示按 16 进制解析字符串。\n return Number.parseInt(hex, 16);\n}\n\n// toHexChainId 把数字或十进制字符串链 ID 转成钱包要求的 0x 十六进制格式。\nfunction toHexChainId(chainId: string | number): string {\n // 如果传入的本来就是 0x 开头字符串,直接返回。\n if (typeof chainId === 'string' && chainId.startsWith('0x')) return chainId;\n // 其它情况统一转成数字,再转成十六进制。\n return `0x${Number(chainId).toString(16)}`;\n}\n\n// switchEvmNetwork 使用 EIP-3326/EIP-3085 请求钱包切换或添加网络。\nasync function switchEvmNetwork(provider: Eip1193Provider, network: WalletNetwork): Promise<void> {\n // EVM 钱包要求 chainId 使用十六进制字符串。\n const chainId = toHexChainId(network.chainId);\n try {\n // wallet_switchEthereumChain 会请求钱包切换到目标网络。\n await provider.request({\n method: 'wallet_switchEthereumChain',\n params: [{ chainId }],\n });\n } catch (error) {\n // 4902 通常表示钱包还没有添加这个网络。\n const maybe = error as { code?: number } | undefined;\n if (maybe?.code !== 4902) throw error;\n\n // 如果钱包没有这个网络,就尝试用 wallet_addEthereumChain 添加。\n await provider.request({\n method: 'wallet_addEthereumChain',\n params: [\n {\n chainId,\n chainName: network.name,\n nativeCurrency: network.nativeCurrency,\n rpcUrls: network.rpcUrls,\n blockExplorerUrls: network.blockExplorerUrls,\n },\n ],\n });\n }\n}\n\n// createEvmAdapter 创建 MetaMask 或 OKX 这种 EVM 钱包的统一适配器。\nexport function createEvmAdapter(options: {\n // id 只能是 metamask 或 okx。\n id: Extract<WalletId, 'metamask' | 'okx'>;\n // name 是展示给用户看的钱包名称。\n name: string;\n // icon 是按钮里显示的简化图标文本。\n icon: string;\n // deepLinks 是移动端打开钱包 App 的配置。\n deepLinks?: DeepLinkConfig;\n}): WalletAdapter {\n // 返回符合 WalletAdapter 规范的钱包对象。\n return {\n // 保存钱包 id。\n id: options.id,\n // 保存钱包名称。\n name: options.name,\n // EVM 钱包链类型固定是 evm。\n chainType: 'evm',\n // 保存钱包图标。\n icon: options.icon,\n // installed 通过能否找到 provider 判断钱包插件是否安装。\n installed: () => Boolean(pickInjectedProvider(options.id)),\n // connect 是真正发起钱包连接的方法。\n connect: async (): Promise<WalletAccount> => {\n // 每次连接前重新找 provider,避免页面加载后钱包才注入导致拿不到。\n const provider = pickInjectedProvider(options.id);\n // 如果没有 provider,说明浏览器没有检测到对应钱包。\n if (!provider) {\n // 抛出统一的未找到钱包错误。\n throw new WalletKitError('PROVIDER_NOT_FOUND', `${options.name} provider was not found.`);\n }\n\n // eth_requestAccounts 会唤起钱包扩展连接弹窗,用户同意后返回地址数组。\n const accounts = await provider.request<string[]>({ method: 'eth_requestAccounts' });\n // eth_chainId 会读取当前钱包所在链,失败时不阻塞连接。\n const chainId = await provider.request<string>({ method: 'eth_chainId' }).catch(() => undefined);\n // EVM 钱包返回数组,通常第一个地址就是当前选中的账户。\n const address = accounts[0];\n // 如果钱包没有返回地址,就认为连接失败。\n if (!address) throw new WalletKitError('PROVIDER_NOT_FOUND', `${options.name} did not return an address.`);\n\n // 返回统一的 WalletAccount 账户对象。\n return {\n // 保存钱包地址。\n address,\n // 标记这是 EVM 钱包。\n chainType: 'evm',\n // 把十六进制 chainId 转成数字保存。\n chainId: hexToNumber(chainId),\n };\n },\n // signMessage 负责让 EVM 钱包签名一段文本。\n signMessage: async (message: string, account: WalletAccount): Promise<string> => {\n // 签名前重新找 provider,保证拿到当前可用的钱包对象。\n const provider = pickInjectedProvider(options.id);\n // 如果 provider 不存在,就抛出未找到钱包错误。\n if (!provider) throw new WalletKitError('PROVIDER_NOT_FOUND', `${options.name} provider was not found.`);\n // personal_sign 是 EVM 钱包常用的文本签名方法。\n return provider.request<string>({\n // 指定调用钱包的 personal_sign 方法。\n method: 'personal_sign',\n // 传入要签名的文本和签名地址。\n params: [message, account.address],\n });\n },\n // switchNetwork 负责请求 EVM 钱包切换到指定网络。\n switchNetwork: async (network: WalletNetwork): Promise<WalletAccount | undefined> => {\n // EVM 适配器只支持 EVM 网络。\n if (network.chainType !== 'evm') {\n // 如果传入 Solana 网络,就抛出不支持错误。\n throw new WalletKitError('UNSUPPORTED_CHAIN', `${options.name} only supports EVM networks.`);\n }\n // 切换前重新获取 provider。\n const provider = pickInjectedProvider(options.id);\n // 如果 provider 不存在,就抛出未找到钱包错误。\n if (!provider) throw new WalletKitError('PROVIDER_NOT_FOUND', `${options.name} provider was not found.`);\n // 请求钱包切换或添加网络。\n await switchEvmNetwork(provider, network);\n // 切换后重新读取账户和链 ID,返回更新后的账户状态。\n const accounts = await provider.request<string[]>({ method: 'eth_accounts' });\n // eth_accounts 不会弹授权,只读取已连接账户。\n const address = accounts[0];\n // 如果没有地址,说明还没有连接账户,返回 undefined。\n if (!address) return undefined;\n // 返回新的账户状态。\n return {\n address,\n chainType: 'evm',\n chainId: Number(network.chainId),\n };\n },\n // getDeepLink 生成移动端打开当前钱包 App 的链接。\n getDeepLink: (targetUrl: string) => getWalletDeepLink(options.id, targetUrl, options.deepLinks),\n };\n}\n","// 引入 DeepLink 生成函数,移动端打开 Phantom App 时会用到。\nimport { getWalletDeepLink } from '../core/deepLinks';\n// 引入统一错误类,找不到 Phantom 时会抛出。\nimport { WalletKitError } from '../types';\n// 引入 Phantom 适配器需要的通用类型。\nimport type { DeepLinkConfig, WalletAccount, WalletAdapter } from '../types';\n// 引入 Phantom Solana provider 的类型定义。\nimport type { PhantomSolanaProvider } from './providerTypes';\n\n// getProvider 用来从 window 上找到 Phantom 注入的 Solana provider。\nfunction getProvider(): PhantomSolanaProvider | undefined {\n // 服务端渲染或非浏览器环境没有 window,所以直接返回 undefined。\n if (typeof window === 'undefined') return undefined;\n // Phantom 新版本通常注入 window.phantom.solana,部分环境会直接注入 window.solana。\n const provider = window.phantom?.solana ?? window.solana;\n // 如果 provider 存在并且像 Phantom,就返回它。\n return provider?.isPhantom || provider?.connect ? provider : undefined;\n}\n\n// bytesToBase64 把 Phantom 返回的字节签名转换成 base64 字符串。\nfunction bytesToBase64(bytes: Uint8Array): string {\n // binary 用来临时拼接二进制字符。\n let binary = '';\n // 遍历每一个字节。\n bytes.forEach((byte) => {\n // 把字节转成字符并拼起来。\n binary += String.fromCharCode(byte);\n });\n // btoa 把二进制字符串转成 base64。\n return btoa(binary);\n}\n\n// createPhantomAdapter 创建 Phantom 钱包适配器。\nexport function createPhantomAdapter(deepLinks?: DeepLinkConfig, icon = 'P'): WalletAdapter {\n // 返回符合 WalletAdapter 规范的钱包对象。\n return {\n // Phantom 的钱包 id 固定是 phantom。\n id: 'phantom',\n // name 是展示给用户看的钱包名称。\n name: 'Phantom',\n // Phantom 这里接的是 Solana 链,所以 chainType 是 solana。\n chainType: 'solana',\n // icon 是简化版展示字符。\n icon,\n // installed 通过是否找到 Phantom provider 判断是否安装。\n installed: () => Boolean(getProvider()),\n // connect 负责调用 Phantom 扩展发起连接。\n connect: async (): Promise<WalletAccount> => {\n // 连接前重新获取 provider,保证拿到最新注入对象。\n const provider = getProvider();\n // 如果找不到 Phantom,就抛出未找到钱包错误。\n if (!provider) throw new WalletKitError('PROVIDER_NOT_FOUND', 'Phantom provider was not found.');\n // provider.connect 会唤起 Phantom 授权弹窗。\n const response = await provider.connect();\n // Phantom 返回 publicKey,把它转成字符串作为地址。\n const address = response.publicKey.toString();\n // 返回统一的钱包账户对象。\n return {\n // address 保存 Solana 地址。\n address,\n // publicKey 也保存同一个地址,方便 Solana 业务使用。\n publicKey: address,\n // 标记这是 Solana 钱包。\n chainType: 'solana',\n // 这里简单标记主网,实际业务可扩展网络选择。\n chainId: 'solana:mainnet',\n };\n },\n // disconnect 负责断开 Phantom 连接。\n disconnect: async () => {\n // 如果 provider 存在且提供 disconnect,就调用它。\n await getProvider()?.disconnect?.();\n },\n // signMessage 负责让 Phantom 对文本签名。\n signMessage: async (message: string): Promise<string> => {\n // 签名前获取 Phantom provider。\n const provider = getProvider();\n // 找不到 provider 时抛出错误。\n if (!provider) throw new WalletKitError('PROVIDER_NOT_FOUND', 'Phantom provider was not found.');\n // Phantom 需要 Uint8Array 格式的消息,所以先用 TextEncoder 编码。\n const encoded = new TextEncoder().encode(message);\n // 调用 Phantom 的 signMessage,用户会看到签名确认弹窗。\n const { signature } = await provider.signMessage(encoded, 'utf8');\n // 把字节签名转成 base64 字符串返回。\n return bytesToBase64(signature);\n },\n // Phantom 的浏览器注入 provider 通常不允许 DApp 直接切换 Solana 网络。\n switchNetwork: async () => {\n // 抛出统一错误,让 UI 提示用户需要在 Phantom 钱包里手动切换网络。\n throw new WalletKitError('UNSUPPORTED_CHAIN', 'Phantom does not support programmatic Solana network switching.');\n },\n // getDeepLink 生成移动端打开 Phantom App 的链接。\n getDeepLink: (targetUrl: string) => getWalletDeepLink('phantom', targetUrl, deepLinks),\n };\n}\n","// 引入 DeepLink 配置和钱包适配器类型。\nimport type { DeepLinkConfig, WalletAdapter } from '../types';\n// 引入 MetaMask 钱包 logo。\nimport metamaskLogo from '../assets/metamask.png';\n// 引入 OKX Wallet 钱包 logo。\nimport okxLogo from '../assets/okx.png';\n// 引入 Phantom 钱包 logo。\nimport phantomLogo from '../assets/phantom.png';\n// 引入创建 EVM 钱包适配器的函数。\nimport { createEvmAdapter } from './eip1193';\n// 引入创建 Phantom 钱包适配器的函数。\nimport { createPhantomAdapter } from './phantom';\n\n// createWalletAdapters 创建这个组件库内置支持的所有钱包适配器。\nexport function createWalletAdapters(deepLinks?: DeepLinkConfig): WalletAdapter[] {\n // 返回钱包适配器数组,UI 会根据这个数组渲染钱包列表。\n return [\n // 创建 OKX Wallet 适配器。\n createEvmAdapter({ id: 'okx', name: 'OKX Wallet', icon: okxLogo, deepLinks }),\n // 创建 MetaMask 适配器。\n createEvmAdapter({ id: 'metamask', name: 'MetaMask', icon: metamaskLogo, deepLinks }),\n // 创建 Phantom 适配器。\n createPhantomAdapter(deepLinks, phantomLogo),\n ];\n}\n","// 引入 React 创建 Context、Hook 和状态管理需要的 API。\nimport { createContext, useCallback, useEffect, useMemo, useRef, useState } from 'react';\n// 引入钱包签名认证、JWT 续期时间计算、JWT 刷新函数。\nimport { authenticateWallet, getRenewalDelay, refreshJwtSession } from '../core/auth';\n// 引入移动端判断和 DApp URL 解析函数。\nimport { isMobileH5, resolveDappUrl } from '../core/deepLinks';\n// 引入轻量事件总线。\nimport { EventEmitter } from '../core/eventEmitter';\n// 引入错误归一化和超时包装函数。\nimport { normalizeWalletError, withTimeout } from '../core/errors';\n// 引入默认网络列表。\nimport { DEFAULT_NETWORKS } from '../core/networks';\n// 引入多 Tab 状态同步类。\nimport { WalletStateSync } from '../core/storageSync';\n// 引入统一错误类。\nimport { WalletKitError } from '../types';\n// 引入创建钱包适配器列表的函数。\nimport { createWalletAdapters } from '../wallets';\n// 引入 Provider 需要的类型定义。\nimport type { WalletContextValue, WalletEventMap, WalletId, WalletProviderProps, WalletState } from '../types';\n\n// DEFAULT_TIMEOUT_MS 是默认钱包连接超时时间,30 秒。\nconst DEFAULT_TIMEOUT_MS = 30_000;\n// DEFAULT_STORAGE_KEY 是 localStorage 里保存钱包同步状态的默认 key。\nconst DEFAULT_STORAGE_KEY = 'rainbow-wallet-kit:wallet-state';\n\n// initialState 是钱包组件初始状态。\nconst initialState: WalletState = {\n // 初始状态是 idle,表示还没有开始连接。\n status: 'idle',\n // 初始化时记录当前时间,方便后续多 Tab 状态比较。\n updatedAt: Date.now(),\n};\n\n// WalletContext 是 React Context,子组件会通过 useWallet 读取它。\nexport const WalletContext = createContext<WalletContextValue | undefined>(undefined);\n\n// WalletProvider 是整个钱包系统的大脑,负责状态、连接、认证、同步。\nexport function WalletProvider({\n // children 是被 Provider 包裹的业务组件。\n children,\n // auth 是签名登录配置。\n auth,\n // deepLinks 是移动端打开钱包 App 配置。\n deepLinks,\n // connectTimeoutMs 是连接超时时间,默认 30 秒。\n connectTimeoutMs = DEFAULT_TIMEOUT_MS,\n // storageKey 是多 Tab 同步使用的 localStorage key。\n storageKey = DEFAULT_STORAGE_KEY,\n // initialWallet 是可选默认钱包。\n initialWallet,\n // autoConnect 控制是否自动连接 initialWallet。\n autoConnect,\n // networks 是业务方传入的网络列表,不传时使用默认列表。\n networks: configuredNetworks,\n}: WalletProviderProps) {\n // emitterRef 保存事件总线实例,useRef 保证它在组件重渲染时不重新创建。\n const emitterRef = useRef(new EventEmitter<WalletEventMap>());\n // syncRef 保存多 Tab 同步实例,初始为 null。\n const syncRef = useRef<WalletStateSync | null>(null);\n // pendingConnectionsRef 保存正在进行的钱包连接,避免连点按钮触发重复授权请求。\n const pendingConnectionsRef = useRef(new Map<WalletId, Promise<void>>());\n // state 保存当前钱包状态,setState 用来更新它。\n const [state, setState] = useState<WalletState>(initialState);\n // wallets 创建钱包适配器列表,deepLinks 变化时才重新创建。\n const wallets = useMemo(() => createWalletAdapters(deepLinks), [deepLinks]);\n // networks 是最终用于 UI 展示和切换的钱包网络列表。\n const networks = useMemo(() => configuredNetworks ?? DEFAULT_NETWORKS, [configuredNetworks]);\n\n // publishState 是统一更新钱包状态的方法。\n const publishState = useCallback((nextState: WalletState) => {\n // 更新当前 React 组件状态。\n setState(nextState);\n // 通过事件总线通知当前页面内部监听者。\n emitterRef.current.emit('state', nextState);\n // 通过 WalletStateSync 同步给其它浏览器 Tab。\n syncRef.current?.publish(nextState);\n }, []);\n\n // connect 是连接指定钱包的核心方法。\n const connect = useCallback(\n // walletId 表示用户想连接哪个钱包。\n async (walletId: WalletId) => {\n // 如果这个钱包已经有连接请求在进行,就复用那次请求,不再向钱包扩展发第二次请求。\n const pendingConnection = pendingConnectionsRef.current.get(walletId);\n // 直接返回已有 Promise,可以避免 MetaMask 报 wallet_requestPermissions already pending。\n if (pendingConnection) return pendingConnection;\n\n // 从钱包列表中找到用户选择的钱包适配器。\n const wallet = wallets.find((item) => item.id === walletId);\n // 如果没有找到适配器,直接结束。\n if (!wallet) return;\n\n // 如果未安装插件,并且业务开启 openOnConnect,并且当前是移动端,就打开钱包 App。\n if (!wallet.installed() && deepLinks?.enabled !== false && deepLinks?.openOnConnect && isMobileH5()) {\n // 通过 deep link 跳转到对应钱包 App。\n window.location.href = wallet.getDeepLink(resolveDappUrl(deepLinks));\n // 跳转后不继续执行浏览器扩展连接逻辑。\n return;\n }\n\n // 如果没有安装钱包插件,并且没有走 DeepLink,就给出明确错误。\n if (!wallet.installed()) {\n // 创建统一的未找到插件错误。\n const error = new WalletKitError('PROVIDER_NOT_FOUND', `${wallet.name} extension was not found.`);\n // 把状态更新为 error,UI 可以展示错误信息。\n publishState({\n // 标记状态为错误。\n status: 'error',\n // 记录这次尝试连接的钱包。\n wallet: walletId,\n // 保存错误对象。\n error,\n // 更新时间戳。\n updatedAt: Date.now(),\n });\n // 通过事件总线发出 error 事件。\n emitterRef.current.emit('error', error);\n // 抛出错误,让按钮组件的 catch 或业务 onError 能收到。\n throw error;\n }\n\n // 创建 connecting 状态,表示正在连接钱包。\n const connectingState: WalletState = {\n // 保留原状态里的其它字段。\n ...state,\n // 状态改成 connecting。\n status: 'connecting',\n // 记录当前要连接的钱包。\n wallet: walletId,\n // 清除上一次错误。\n error: undefined,\n // 更新时间戳。\n updatedAt: Date.now(),\n };\n // 发布 connecting 状态。\n publishState(connectingState);\n\n // connectionTask 是真正的钱包连接任务,会被保存到 pendingConnectionsRef。\n const connectionTask = (async () => {\n // try/catch 用来把连接、签名、认证过程中的错误统一处理。\n try {\n // 调用钱包适配器的 connect,并加上超时控制。\n const account = await withTimeout(\n // wallet.connect 会真正唤起钱包扩展授权弹窗。\n wallet.connect(),\n // 使用配置的连接超时时间。\n connectTimeoutMs,\n // 超时时显示的钱包名称错误信息。\n `${wallet.name} connection timed out.`,\n );\n // 如果启用了 auth,这里会继续走 nonce 签名登录。\n const session = await authenticateWallet({\n // 传入认证配置。\n auth,\n // 传入当前钱包 id。\n wallet: walletId,\n // 传入刚连接成功的账户。\n account,\n // 告诉认证函数如何让当前钱包签名。\n signMessage: (message) => wallet.signMessage(message, account),\n });\n // 连接和可选认证都成功后,发布 connected 状态。\n publishState({\n // 标记已经连接。\n status: 'connected',\n // 保存当前钱包 id。\n wallet: walletId,\n // 保存钱包账户。\n account,\n // 保存认证会话,未启用 auth 时可能是 undefined。\n auth: session,\n // 更新时间戳。\n updatedAt: Date.now(),\n });\n // 发出 accountChanged 事件,通知账户已经可用。\n emitterRef.current.emit('accountChanged', account);\n } catch (error) {\n // 把任意底层错误转换成 WalletKitError。\n const normalized = normalizeWalletError(error);\n // 发布 error 状态,方便 UI 展示。\n publishState({\n // 标记状态为 error。\n status: 'error',\n // 记录出错的钱包。\n wallet: walletId,\n // 保存归一化错误。\n error: normalized,\n // 更新时间戳。\n updatedAt: Date.now(),\n });\n // 发出 error 事件。\n emitterRef.current.emit('error', normalized);\n // 继续抛出错误,让调用方也能处理。\n throw normalized;\n } finally {\n // 不管成功还是失败,连接任务结束后都要移除防重复锁。\n pendingConnectionsRef.current.delete(walletId);\n }\n })();\n\n // 把当前连接任务记录下来,下一次点击会复用它。\n pendingConnectionsRef.current.set(walletId, connectionTask);\n // 等待连接任务完成。\n return connectionTask;\n },\n // 这些依赖变化时,connect 函数会重新创建。\n [auth, connectTimeoutMs, deepLinks, publishState, state, wallets],\n );\n\n // openWalletApp 是显式打开移动端钱包 App 的方法。\n const openWalletApp = useCallback(\n // walletId 表示要打开哪个钱包 App。\n (walletId: WalletId) => {\n // 找到对应钱包适配器。\n const wallet = wallets.find((item) => item.id === walletId);\n // 没找到钱包、禁用 DeepLink、或不是浏览器环境时不做任何事。\n if (!wallet || deepLinks?.enabled === false || typeof window === 'undefined') return;\n // 跳转到该钱包的 DeepLink。\n window.location.href = wallet.getDeepLink(resolveDappUrl(deepLinks));\n },\n // deepLinks 或 wallets 变化时重新创建函数。\n [deepLinks, wallets],\n );\n\n // disconnect 用来断开当前钱包连接。\n const disconnect = useCallback(async () => {\n // 根据当前 state.wallet 找到对应钱包适配器。\n const wallet = wallets.find((item) => item.id === state.wallet);\n // 如果钱包适配器提供 disconnect,就调用它。\n await wallet?.disconnect?.();\n // 创建断开后的状态。\n const nextState: WalletState = {\n // 标记为 disconnected。\n status: 'disconnected',\n // 更新时间戳。\n updatedAt: Date.now(),\n };\n // 发布断开状态。\n publishState(nextState);\n // 发出 disconnect 事件。\n emitterRef.current.emit('disconnect', undefined);\n }, [publishState, state.wallet, wallets]);\n\n // switchNetwork 用来请求当前钱包切换网络。\n const switchNetwork = useCallback(\n // networkId 是要切换到的网络 id。\n async (networkId: string) => {\n // 找到目标网络配置。\n const network = networks.find((item) => item.id === networkId);\n // 如果没有找到网络,抛出不支持错误。\n if (!network) throw new WalletKitError('UNSUPPORTED_CHAIN', `Network ${networkId} is not configured.`);\n // 当前必须已经选择或连接了某个钱包。\n const wallet = wallets.find((item) => item.id === state.wallet);\n // 没有当前钱包时抛出错误。\n if (!wallet) throw new WalletKitError('PROVIDER_NOT_FOUND', 'Connect a wallet before switching networks.');\n // 钱包适配器没有实现 switchNetwork 时,说明不支持程序化切网。\n if (!wallet.switchNetwork) throw new WalletKitError('UNSUPPORTED_CHAIN', `${wallet.name} does not support network switching.`);\n\n // try/catch 用来把钱包切网失败包装成统一错误。\n try {\n // 调用适配器切换网络,EVM 会唤起钱包扩展确认弹窗。\n const account = await wallet.switchNetwork(network);\n // 如果适配器返回了新账户状态,就更新当前 state。\n if (account && state.status === 'connected') {\n // 发布带新 chainId 的状态。\n publishState({\n ...state,\n account,\n updatedAt: Date.now(),\n });\n }\n } catch (error) {\n // 如果本来就是 UNSUPPORTED_CHAIN,就保持原错误码。\n const normalized =\n error instanceof WalletKitError && error.code === 'UNSUPPORTED_CHAIN'\n ? error\n : new WalletKitError('SWITCH_NETWORK_FAILED', 'Failed to switch wallet network.', error);\n // 切网失败不应该断开钱包,所以保留当前 status,只记录错误信息。\n publishState({ ...state, error: normalized, updatedAt: Date.now() });\n // 抛出错误给按钮组件或业务方。\n throw normalized;\n }\n },\n [networks, publishState, state, wallets],\n );\n\n // refreshAuth 用来手动或自动刷新 JWT 登录态。\n const refreshAuth = useCallback(async () => {\n // 调用核心认证层的刷新函数。\n const session = await refreshJwtSession({\n // 传入认证配置。\n auth,\n // 传入当前登录态。\n session: state.auth,\n // 传入当前钱包 id。\n wallet: state.wallet,\n // 传入当前账户。\n account: state.account,\n });\n // 如果刷新成功并且当前仍然是 connected,就更新 auth。\n if (session && state.status === 'connected') {\n // 发布带新 session 的状态。\n publishState({\n // 保留原钱包状态。\n ...state,\n // 覆盖 auth 为新 session。\n auth: session,\n // 更新时间戳。\n updatedAt: Date.now(),\n });\n }\n }, [auth, publishState, state]);\n\n // 这个 effect 初始化多 Tab 同步,并读取 localStorage 里的历史状态。\n useEffect(() => {\n // 创建多 Tab 同步实例。\n const sync = new WalletStateSync(emitterRef.current, storageKey);\n // 保存同步实例到 ref,publishState 会用到。\n syncRef.current = sync;\n // 读取 localStorage 中缓存的钱包状态。\n const stored = sync.read();\n // 如果有缓存状态,就先恢复到 React state。\n if (stored) setState(stored);\n\n // 监听 EventEmitter 的 state 事件。\n const unsubscribe = emitterRef.current.on('state', (nextState) => {\n // 只有收到的状态不比当前状态旧,才更新当前 React state。\n setState((current) => (nextState.updatedAt >= current.updatedAt ? nextState : current));\n });\n\n // 组件卸载时执行清理函数。\n return () => {\n // 取消事件监听。\n unsubscribe();\n // 销毁多 Tab 同步实例。\n sync.destroy();\n };\n }, [storageKey]);\n\n // 这个 effect 处理可选的自动连接功能。\n useEffect(() => {\n // 如果开启 autoConnect 并且提供 initialWallet,就尝试连接。\n if (autoConnect && initialWallet) {\n // 自动连接失败时静默忽略,避免页面初始化直接崩溃。\n void connect(initialWallet).catch(() => undefined);\n }\n }, [autoConnect, connect, initialWallet]);\n\n // 这个 effect 处理 JWT 自动续期。\n useEffect(() => {\n // 如果没有 auth 或当前不是 connected,就不需要续期。\n if (!state.auth || state.status !== 'connected') return;\n // 计算距离下一次续期还要等多久。\n const delay = getRenewalDelay(state.auth, auth?.renewalWindowMs);\n // 设置定时器,在合适时间触发刷新。\n const timer = window.setTimeout(() => {\n // 调用 refreshAuth,并捕获刷新失败。\n void refreshAuth().catch((error) => {\n // 把刷新失败错误归一化。\n const normalized = normalizeWalletError(error);\n // 把状态更新成 error,方便 UI 或业务处理。\n publishState({ ...state, status: 'error', error: normalized, updatedAt: Date.now() });\n });\n }, delay);\n // 依赖变化或组件卸载时清理定时器。\n return () => window.clearTimeout(timer);\n }, [auth?.renewalWindowMs, publishState, refreshAuth, state]);\n\n // value 是提供给 useWallet 的上下文对象。\n const value = useMemo<WalletContextValue>(\n // 返回所有钱包状态和操作方法。\n () => ({\n // 当前钱包状态。\n state,\n // 所有钱包适配器。\n wallets,\n // 网络列表。\n networks,\n // 连接钱包函数。\n connect,\n // 切换网络函数。\n switchNetwork,\n // 断开钱包函数。\n disconnect,\n // 显式打开钱包 App 函数。\n openWalletApp,\n // 刷新认证函数。\n refreshAuth,\n }),\n // 这些依赖变化时才重新生成 value。\n [connect, disconnect, networks, openWalletApp, refreshAuth, state, switchNetwork, wallets],\n );\n\n // 把钱包上下文提供给所有子组件。\n return <WalletContext.Provider value={value}>{children}</WalletContext.Provider>;\n}\n","// 引入 React 的 useContext,用来读取 Context。\nimport { useContext } from 'react';\n// 引入 WalletProvider 创建的钱包上下文对象。\nimport { WalletContext } from './WalletProvider';\n\n// useWallet 是业务组件读取钱包状态和操作方法的 Hook。\nexport function useWallet() {\n // 从 WalletContext 里读取 Provider 提供的 value。\n const context = useContext(WalletContext);\n // 如果 context 不存在,说明当前组件没有被 WalletProvider 包住。\n if (!context) {\n // 抛出明确错误,提醒使用者必须把组件放在 WalletProvider 内部。\n throw new Error('useWallet must be used inside WalletProvider.');\n }\n // 返回钱包上下文,里面有 state、connect、disconnect 等能力。\n return context;\n}\n","// 引入 React 的 useMemo 和 useState。\nimport { useMemo, useState } from 'react';\n// 引入钱包 id 类型,用来限制 preferredWallets 的取值。\nimport type { WalletId } from '../types';\n// 引入 useWallet,用来读取钱包状态和连接、切网方法。\nimport { useWallet } from './useWallet';\n\n// ConnectWalletButtonProps 描述连接按钮组件支持的配置。\nexport interface ConnectWalletButtonProps {\n // label 是未连接时按钮上显示的文字。\n label?: string;\n // className 允许业务方给最外层追加自定义类名。\n className?: string;\n // preferredWallets 允许业务方控制钱包列表显示顺序或只显示部分钱包。\n preferredWallets?: WalletId[];\n // onError 是连接或切网出错时的回调。\n onError?: (error: unknown) => void;\n}\n\n// ModalView 表示当前打开的是哪个弹窗。\ntype ModalView = 'wallets' | 'account' | 'networks' | null;\n\n// ConnectWalletButton 是用户页面上看到的连接钱包按钮。\nexport function ConnectWalletButton({\n // 默认按钮文字。\n label = 'Connect Wallet',\n // 默认不追加类名。\n className = '',\n // 钱包展示顺序。\n preferredWallets,\n // 错误回调。\n onError,\n}: ConnectWalletButtonProps) {\n // 从 Provider 里拿到状态、钱包、网络、连接、断开、切网函数。\n const { state, wallets, networks, connect, disconnect, switchNetwork } = useWallet();\n // modal 控制当前打开的钱包弹窗、账户弹窗或网络弹窗。\n const [modal, setModal] = useState<ModalView>(null);\n // activeWallet 记录正在连接的钱包,用于右侧状态区显示。\n const [activeWallet, setActiveWallet] = useState<WalletId | undefined>();\n // switchingNetwork 记录正在切换的网络,用于按钮 loading 文案。\n const [switchingNetwork, setSwitchingNetwork] = useState<string | undefined>();\n\n // orderedWallets 根据 preferredWallets 计算最终展示的钱包列表。\n const orderedWallets = preferredWallets?.length\n ? preferredWallets.flatMap((id) => wallets.filter((wallet) => wallet.id === id))\n : wallets;\n\n // activeNetwork 根据当前 chainId 找到当前网络。\n const activeNetwork = useMemo(() => {\n // 取出当前账户的 chainId。\n const chainId = state.account?.chainId;\n // 没有 chainId 时没有当前网络。\n if (chainId === undefined) return undefined;\n // 用字符串比较,兼容数字和字符串两种 chainId。\n return networks.find((network) => String(network.chainId) === String(chainId));\n }, [networks, state.account?.chainId]);\n\n // selectedWallet 是正在连接的钱包适配器。\n const selectedWallet = activeWallet ? wallets.find((wallet) => wallet.id === activeWallet) : undefined;\n\n // handleConnect 处理点击钱包列表项后的连接流程。\n const handleConnect = (walletId: WalletId) => {\n // 记录当前点击的钱包,右侧会显示正在打开它。\n setActiveWallet(walletId);\n // 调用 Provider 的 connect。\n void connect(walletId)\n // 连接成功后关闭弹窗。\n .then(() => {\n setModal(null);\n setActiveWallet(undefined);\n })\n // 连接失败时把错误交给外部,同时保留弹窗让用户看到错误。\n .catch((error) => {\n onError?.(error);\n setActiveWallet(undefined);\n });\n };\n\n // handleSwitchNetwork 处理点击网络列表项后的切网流程。\n const handleSwitchNetwork = (networkId: string) => {\n // 记录正在切换的网络。\n setSwitchingNetwork(networkId);\n // 调用 Provider 的 switchNetwork。\n void switchNetwork(networkId)\n // 切换成功后关闭网络弹窗。\n .then(() => setModal(null))\n // 切换失败时交给外部处理。\n .catch((error) => onError?.(error))\n // 无论成功失败都结束 loading 状态。\n .finally(() => setSwitchingNetwork(undefined));\n };\n\n // renderWalletModal 渲染连接钱包弹窗。\n const renderWalletModal = () => (\n // 遮罩层覆盖页面背景。\n <div className=\"rwk-overlay\" role=\"presentation\" onMouseDown={() => setModal(null)}>\n {/* 弹窗主体阻止点击冒泡,避免点击内容区也关闭。 */}\n <div className=\"rwk-modal rwk-wallet-modal\" role=\"dialog\" aria-label=\"Connect wallet\" onMouseDown={(event) => event.stopPropagation()}>\n {/* 左侧钱包列表。 */}\n <div className=\"rwk-modal-sidebar\">\n <div className=\"rwk-modal-title\">连接钱包</div>\n <div className=\"rwk-modal-section-label\">可用钱包</div>\n {orderedWallets.map((wallet) => (\n <button\n className={`rwk-wallet ${activeWallet === wallet.id ? 'rwk-wallet-active' : ''}`}\n key={wallet.id}\n type=\"button\"\n onClick={() => handleConnect(wallet.id)}\n >\n <img className=\"rwk-wallet-logo\" src={wallet.icon} alt={`${wallet.name} logo`} />\n <span>{wallet.name}</span>\n <small>{wallet.installed() ? '已安装' : '未安装'}</small>\n </button>\n ))}\n </div>\n\n {/* 右侧连接状态。 */}\n <div className=\"rwk-modal-main\">\n <button className=\"rwk-close\" type=\"button\" aria-label=\"Close\" onClick={() => setModal(null)}>\n ×\n </button>\n <div className=\"rwk-connect-status\">\n {selectedWallet ? (\n <>\n <img className=\"rwk-status-logo\" src={selectedWallet.icon} alt={`${selectedWallet.name} logo`} />\n <strong>正在打开 {selectedWallet.name}...</strong>\n <span>请在钱包扩展中确认连接</span>\n <i className=\"rwk-spinner\" />\n </>\n ) : (\n <>\n <strong>选择一个钱包</strong>\n <span>点击左侧钱包后会唤起对应扩展</span>\n </>\n )}\n </div>\n {state.error ? <p className=\"rwk-error\">{state.error.message}</p> : null}\n </div>\n </div>\n </div>\n );\n\n // renderNetworkModal 渲染网络切换弹窗。\n const renderNetworkModal = () => (\n <div className=\"rwk-overlay\" role=\"presentation\" onMouseDown={() => setModal(null)}>\n <div className=\"rwk-modal rwk-network-modal\" role=\"dialog\" aria-label=\"Switch network\" onMouseDown={(event) => event.stopPropagation()}>\n <button className=\"rwk-close\" type=\"button\" aria-label=\"Close\" onClick={() => setModal(null)}>\n ×\n </button>\n <div className=\"rwk-modal-title\">切换网络</div>\n <div className=\"rwk-network-list\">\n {networks.map((network) => {\n const isActive = String(network.chainId) === String(state.account?.chainId);\n return (\n <button\n className={`rwk-network-item ${isActive ? 'rwk-network-active' : ''}`}\n disabled={Boolean(switchingNetwork)}\n key={network.id}\n type=\"button\"\n onClick={() => handleSwitchNetwork(network.id)}\n >\n <span>\n <strong>{network.name}</strong>\n <small>{network.chainType === 'evm' ? `Chain ID ${network.chainId}` : 'Solana 网络'}</small>\n </span>\n <em>{switchingNetwork === network.id ? '切换中' : isActive ? '当前' : '切换'}</em>\n </button>\n );\n })}\n </div>\n {state.error ? <p className=\"rwk-error\">{state.error.message}</p> : null}\n </div>\n </div>\n );\n\n // renderAccountModal 渲染已连接账户弹窗。\n const renderAccountModal = () => (\n <div className=\"rwk-overlay\" role=\"presentation\" onMouseDown={() => setModal(null)}>\n <div className=\"rwk-modal rwk-account-modal\" role=\"dialog\" aria-label=\"Wallet account\" onMouseDown={(event) => event.stopPropagation()}>\n <button className=\"rwk-close\" type=\"button\" aria-label=\"Close\" onClick={() => setModal(null)}>\n ×\n </button>\n <div className=\"rwk-modal-title\">钱包账户</div>\n <div className=\"rwk-account-row\">\n <span>{state.wallet}</span>\n <strong>{state.account ? shortenAddress(state.account.address) : '-'}</strong>\n </div>\n <button className=\"rwk-disconnect\" type=\"button\" onClick={() => void disconnect().then(() => setModal(null))}>\n Disconnect\n </button>\n </div>\n </div>\n );\n\n // 已连接状态展示网络按钮和账户按钮。\n if (state.status === 'connected' && state.account) {\n return (\n <div className={`rwk-root ${className}`}>\n <div className=\"rwk-actions\">\n <button className=\"rwk-network-button\" type=\"button\" onClick={() => setModal('networks')}>\n {activeNetwork?.name ?? `Chain ${state.account.chainId ?? '-'}`}\n </button>\n <button className=\"rwk-account\" type=\"button\" onClick={() => setModal('account')}>\n <span className=\"rwk-status-dot\" />\n <span>{shortenAddress(state.account.address)}</span>\n </button>\n </div>\n {modal === 'networks' ? renderNetworkModal() : null}\n {modal === 'account' ? renderAccountModal() : null}\n </div>\n );\n }\n\n // 未连接状态展示蓝色连接按钮。\n return (\n <div className={`rwk-root ${className}`}>\n <button className=\"rwk-connect\" type=\"button\" disabled={state.status === 'connecting'} onClick={() => setModal('wallets')}>\n {state.status === 'connecting' ? 'Connecting...' : label}\n </button>\n {modal === 'wallets' ? renderWalletModal() : null}\n </div>\n );\n}\n\n// shortenAddress 把很长的钱包地址缩短显示。\nfunction shortenAddress(address: string): string {\n // 如果地址本来就不长,就直接原样返回。\n if (address.length <= 12) return address;\n // 长地址显示前 6 位和后 4 位,中间用省略号。\n return `${address.slice(0, 6)}...${address.slice(-4)}`;\n}\n"],"names":["WalletKitError","code","message","cause","__publicField","createNonceMessage","input","authenticateWallet","_a","nonce","signature","error","refreshJwtSession","getRenewalDelay","session","windowMs","DEFAULT_DEEP_LINKS","isMobileH5","resolveDappUrl","config","getWalletDeepLink","wallet","targetUrl","encoded","EventEmitter","event","listener","listeners","payload","normalizeWalletError","maybe","_b","withTimeout","promise","timeoutMs","timeout","timeoutPromise","_","reject","DEFAULT_NETWORKS","SYNC_EVENT","WalletStateSync","emitter","storageKey","state","raw","metamaskLogo","okxLogo","phantomLogo","pickInjectedProvider","candidates","collectInjectedProviders","providers","provider","allProviders","uniqueProviders","matched","isOkxProvider","injected","index","list","hexToNumber","hex","toHexChainId","chainId","switchEvmNetwork","network","createEvmAdapter","options","accounts","address","account","getProvider","bytesToBase64","bytes","binary","byte","createPhantomAdapter","deepLinks","icon","createWalletAdapters","DEFAULT_TIMEOUT_MS","DEFAULT_STORAGE_KEY","initialState","WalletContext","createContext","WalletProvider","children","auth","connectTimeoutMs","initialWallet","autoConnect","configuredNetworks","emitterRef","useRef","syncRef","pendingConnectionsRef","setState","useState","wallets","useMemo","networks","publishState","useCallback","nextState","connect","walletId","pendingConnection","item","connectingState","connectionTask","normalized","openWalletApp","disconnect","switchNetwork","networkId","refreshAuth","useEffect","sync","stored","unsubscribe","current","delay","timer","value","jsx","useWallet","context","useContext","ConnectWalletButton","label","className","preferredWallets","onError","modal","setModal","activeWallet","setActiveWallet","switchingNetwork","setSwitchingNetwork","orderedWallets","id","activeNetwork","selectedWallet","handleConnect","handleSwitchNetwork","renderWalletModal","jsxs","Fragment","renderNetworkModal","isActive","renderAccountModal","shortenAddress"],"mappings":"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"}
|