UNPKG

0xtrails

Version:

SDK for Trails

407 lines (375 loc) 14.6 kB
import { getSequenceProjectAccessKey, getWalletConnectProjectId, } from "./config.js" import WalletConnectLogo from "./widget/assets/WalletConnect-logo-blue-bg.svg" import { Wallet as WalletIcon } from "lucide-react" import { injected, walletConnect, safe, baseAccount, gemini, } from "wagmi/connectors" import { useConnect } from "wagmi" import React from "react" import { sequenceWallet } from "@0xsequence/connect" type Connector = any export interface WalletConfig { id: string name: string icon: string connector?: Connector } // WalletConnect connector singleton to avoid multiple Core initializations let wcConnectorSingleton: ReturnType<typeof walletConnect> | null = null function getWalletConnectConnectorSingleton() { if (!wcConnectorSingleton) { wcConnectorSingleton = walletConnect({ projectId: getWalletConnectProjectId(), showQrModal: false, }) } return wcConnectorSingleton } export const walletConnectConnector: Connector = getWalletConnectConnectorSingleton() export const injectedConnector = injected() export const baseAccountConnector: Connector = baseAccount() export const geminiConnector: Connector = gemini() function isInIframe() { // check if we're in an iframe if (window?.parent === window) { return false } return true } function safeProviderOrWalletConnect() { if (isInIframe()) { return safe() } return walletConnectConnector } export function windowProviderOrWalletConnect( walletId: string, windowObjectIdentifier: string | string[], name: string, ) { if (typeof window !== "undefined") { let provider: any if (Array.isArray(windowObjectIdentifier)) { // Handle array case: ["phantom", "ethereum"] -> window.phantom.ethereum provider = windowObjectIdentifier.reduce( (obj, key) => obj?.[key], window as any, ) } else { // Handle string case: "phantom" -> window.phantom provider = (window as any)[windowObjectIdentifier] } if (provider) { return injected({ target() { return { id: walletId, name: name || walletId, provider: provider, } }, }) } } return walletConnectConnector } export const metamaskConnector = injected({ target() { return { id: "metamask", name: "metamask", provider: typeof window !== "undefined" ? (window as any).ethereum : undefined, } }, }) export const rainbowConnector = windowProviderOrWalletConnect( "rainbow", "rainbow", "Rainbow", ) export const trustwalletConnector = windowProviderOrWalletConnect( "trustwallet", "trustwallet", "Trust", ) export const phantomConnector = windowProviderOrWalletConnect( "phantom", ["phantom", "ethereum"], "Phantom", ) export const okxwalletConnector = windowProviderOrWalletConnect( "okxwallet", "okxwallet", "OKX Wallet", ) export const zerionConnector = windowProviderOrWalletConnect( "zerion", "zerionWallet", "Zerion", ) export const ambireConnector = windowProviderOrWalletConnect( "ambire", "ambire", "Ambire", ) export const rabbyConnector = windowProviderOrWalletConnect( "rabby", "rabby", "Rabby", ) export const coinbaseWalletConnector = windowProviderOrWalletConnect( "coinbase", "coinbaseWalletExtension", "Coinbase Wallet", ) export const sequenceConnector: any = sequenceWallet({ connect: { app: "Trails", projectAccessKey: getSequenceProjectAccessKey(), }, defaultNetwork: 1, walletAppURL: "https://sequence.app", }) export const safeConnector: Connector = safeProviderOrWalletConnect() export const connectors = [ injectedConnector, walletConnectConnector, safeConnector, baseAccountConnector, geminiConnector, coinbaseWalletConnector, metamaskConnector, rainbowConnector, trustwalletConnector, phantomConnector, okxwalletConnector, zerionConnector, ambireConnector, rabbyConnector, ] export const WALLET_CONFIGS: Record<string, WalletConfig> = { injected: { id: "injected", name: "Browser Wallet", connector: injectedConnector, icon: WalletIcon as unknown as string, }, walletconnect: { id: "walletconnect", name: "WalletConnect", connector: walletConnectConnector, icon: WalletConnectLogo as string, }, metamask: { id: "metamask", name: "MetaMask", connector: metamaskConnector, icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzAiIGhlaWdodD0iMzAiIHZpZXdCb3g9IjAgMCAzMCAzMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjIzIiBoZWlnaHQ9IjIzIiB4PSIzLjUiIHk9IjMuNSIgdmlld0JveD0iMCAwIDE0MS41MSAxMzYuNDIiPjxwYXRoIGZpbGw9IiNGRjVDMTYiIGQ9Im0xMzIuMjQgMTMxLjc1LTMwLjQ4LTkuMDctMjIuOTkgMTMuNzQtMTYuMDMtLjAxLTIzLTEzLjc0LTMwLjQ3IDkuMDhMMCAxMDAuNDdsOS4yNy0zNC43M0wwIDM2LjQgOS4yNyAwbDQ3LjYgMjguNDRoMjcuNzZMMTMyLjI0IDBsOS4yNyAzNi4zOC05LjI3IDI5LjM2IDkuMjcgMzQuNzItOS4yNyAzMS4zWiIvPjxwYXRoIGZpbGw9IiNGRjVDMTYiIGQ9Im05LjI3IDAgNDcuNjEgMjguNDZMNTQuOTggNDggOS4yOSAwWm0zMC40NyAxMDAuNDggMjAuOTUgMTUuOTUtMjAuOTUgNi4yNHYtMjIuMlpNNTkuMDEgNzQuMSA1NSA0OCAyOS4yMiA2NS43NWgtLjAybC4wOCAxOC4yNyAxMC40NS05LjkyaDE5LjI5Wk0xMzIuMjUgMGwtNDcuNiAyOC40Nkw4Ni41MSA0OGw0NS43Mi00OFptLTMwLjQ3IDEwMC40OC0yMC45NCAxNS45NSAyMC45NCA2LjI0di0yMi4yWm0xMC41My0zNC43M0w4Ni41MyA0OCA4Mi41IDc0LjFoMTkuMjdsMTAuNDYgOS45LjA3LTE4LjI2WiIvPjxwYXRoIGZpbGw9IiNFMzQ4MDciIGQ9Im0zOS43MyAxMjIuNjctMzAuNDYgOS4wOEwwIDEwMC40OGgzOS43M3YyMi4yWk01OS4wMiA3NC4xbDUuODIgMzcuNzEtOC4wNy0yMC45Ny0yNy40OS02LjgyIDEwLjQ2LTkuOTJINTlabTQyLjc2IDQ4LjU5IDMwLjQ3IDkuMDcgOS4yNy0zMS4yN2gtMzkuNzR6TTgyLjUgNzQuMDlsLTUuODIgMzcuNzEgOC4wNi0yMC45NyAyNy41LTYuODItMTAuNDctOS45MnoiLz48cGF0aCBmaWxsPSIjRkY4RDVEIiBkPSJtMCAxMDAuNDcgOS4yNy0zNC43M0gyOS4ybC4wNyAxOC4yNyAyNy41IDYuODIgOC4wNiAyMC45Ny00LjE1IDQuNjItMjAuOTQtMTUuOTZIMFptMTQxLjUgMC05LjI2LTM0LjczaC0xOS45M2wtLjA3IDE4LjI3LTI3LjUgNi44Mi04LjA2IDIwLjk3IDQuMTUgNC42MiAyMC45NC0xNS45NmgzOS43NFpNODQuNjQgMjguNDRINTYuODhsLTEuODkgMTkuNTQgOS44NCA2My44aDExLjg1bDkuODUtNjMuOC0xLjktMTkuNTRaIi8+PHBhdGggZmlsbD0iIzY2MTgwMCIgZD0iTTkuMjcgMCAwIDM2LjM4bDkuMjcgMjkuMzZIMjkuMkw1NC45OCA0OHptNDMuOTggODEuNjdoLTkuMDNsLTQuOTIgNC44MSAxNy40NyA0LjMzLTMuNTItOS4xNVpNMTMyLjI0IDBsOS4yNyAzNi4zOC05LjI3IDI5LjM2aC0xOS45M0w4Ni41MyA0OHpNODguMjcgODEuNjdoOS4wNGw0LjkyIDQuODItMTcuNDkgNC4zNCAzLjUzLTkuMTdabS05LjUgNDIuMyAyLjA2LTcuNTQtNC4xNS00LjYySDY0LjgybC00LjE0IDQuNjIgMi4wNSA3LjU0Ii8+PHBhdGggZmlsbD0iI0MwQzRDRCIgZD0iTTc4Ljc3IDEyMy45N3YxMi40NUg2Mi43NHYtMTIuNDVoMTYuMDJaIi8+PHBhdGggZmlsbD0iI0U3RUJGNiIgZD0ibTM5Ljc0IDEyMi42NiAyMyAxMy43NnYtMTIuNDZsLTIuMDUtNy41NHptNjIuMDMgMC0yMyAxMy43NnYtMTIuNDZsMi4wNi03LjU0eiIvPjwvc3ZnPjwvc3ZnPg==", }, baseAccount: { id: "baseAccount", name: "Base", connector: baseAccountConnector, icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAAALZJREFUaEPtmjEOhDAMBNc/O14GvOzys3CAKK6eAlmaVGl2Zc+kTOU685vkc9/bnD2prZK5/TZY24z9P+g4F5hNh7/GdoG37WlAA5CATwgCxHENYISwQAMQII5rACOEBRqAAHFcAxghLNAABIjjGsAIYYEGIEAc1wBGCAs0AAHiuAYwQligAQgQxzWAEcICDUCAOK4BjBAWaAACxHENYISwQAMQII6fBjr+VHkW3+u+tfyxMpJaDgYzYxb/ALZVAAAAAElFTkSuQmCC", }, safe: { id: "safe", name: "Safe", connector: safeConnector, icon: "https://explorer-api.walletconnect.com/v3/logo/sm/3913df81-63c2-4413-d60b-8ff83cbed500?projectId=34357d3c125c2bcf2ce2bc3309d98715", }, rainbow: { id: "rainbow", name: "Rainbow", connector: rainbowConnector, icon: "https://explorer-api.walletconnect.com/v3/logo/sm/7a33d7f1-3d12-4b5c-f3ee-5cd83cb1b500?projectId=34357d3c125c2bcf2ce2bc3309d98715", }, trust: { id: "trust", name: "Trust", connector: trustwalletConnector, icon: "https://explorer-api.walletconnect.com/v3/logo/sm/7677b54f-3486-46e2-4e37-bf8747814f00?projectId=34357d3c125c2bcf2ce2bc3309d98715", }, ambire: { id: "ambire", name: "Ambire Wallet", connector: ambireConnector, icon: "https://explorer-api.walletconnect.com/v3/logo/sm/c39b3a16-1a38-4588-f089-cb7aeb584700?projectId=34357d3c125c2bcf2ce2bc3309d98715", }, argent: { id: "argent", name: "Argent", connector: walletConnectConnector, icon: "https://explorer-api.walletconnect.com/v3/logo/sm/215158d2-614b-49c9-410f-77aa661c3900?projectId=34357d3c125c2bcf2ce2bc3309d98715", }, binance: { id: "binance", name: "Binance Wallet", connector: walletConnectConnector, icon: "https://explorer-api.walletconnect.com/v3/logo/sm/ebac7b39-688c-41e3-7912-a4fefba74600?projectId=34357d3c125c2bcf2ce2bc3309d98715", }, okx: { id: "okx", name: "OKX Wallet", connector: okxwalletConnector, icon: "https://explorer-api.walletconnect.com/v3/logo/sm/c55df831-3c52-49fc-d1d1-97a926dc0c00?projectId=34357d3c125c2bcf2ce2bc3309d98715", }, zerion: { id: "zerion", name: "Zerion", connector: zerionConnector, icon: "https://explorer-api.walletconnect.com/v3/logo/sm/73f6f52f-7862-49e7-bb85-ba93ab72cc00?projectId=34357d3c125c2bcf2ce2bc3309d98715", }, phantom: { id: "phantom", name: "Phantom", connector: phantomConnector, icon: "https://explorer-api.walletconnect.com/v3/logo/sm/b6ec7b81-bb4f-427d-e290-7631e6e50d00?projectId=34357d3c125c2bcf2ce2bc3309d98715", }, coinbase: { id: "coinbase", name: "Coinbase Wallet", connector: coinbaseWalletConnector, icon: "data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PScwIDAgMTAyNCAxMDI0JyBmaWxsPSdub25lJyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHN0eWxlPSdoZWlnaHQ6MjhweDt3aWR0aDoyOHB4Jz48cmVjdCB3aWR0aD0nMTAyNCcgaGVpZ2h0PScxMDI0JyBmaWxsPScjMDA1MkZGJyByeD0nMTAwJyByeT0nMTAwJz48L3JlY3Q+PHBhdGggZmlsbC1ydWxlPSdldmVub2RkJyBjbGlwLXJ1bGU9J2V2ZW5vZGQnIGQ9J00xNTIgNTEyQzE1MiA3MTAuODIzIDMxMy4xNzcgODcyIDUxMiA4NzJDNzEwLjgyMyA4NzIgODcyIDcxMC44MjMgODcyIDUxMkM4NzIgMzEzLjE3NyA3MTAuODIzIDE1MiA1MTIgMTUyQzMxMy4xNzcgMTUyIDE1MiAzMTMuMTc3IDE1MiA1MTJaTTQyMCAzOTZDNDA2Ljc0NSAzOTYgMzk2IDQwNi43NDUgMzk2IDQyMFY2MDRDMzk2IDYxNy4yNTUgNDA2Ljc0NSA2MjggNDIwIDYyOEg2MDRDNjE3LjI1NSA2MjggNjI4IDYxNy4yNTUgNjI4IDYwNFY0MjBDNjI4IDQwNi43NDUgNjE3LjI1NSAzOTYgNjA0IDM5Nkg0MjBaJyBmaWxsPSd3aGl0ZSc+PC9wYXRoPjwvc3ZnPg==", }, rabby: { id: "rabby", name: "Rabby", connector: rabbyConnector, icon: "https://explorer-api.walletconnect.com/v3/logo/sm/255e6ba2-8dfd-43ad-e88e-57cbb98f6800?projectId=34357d3c125c2bcf2ce2bc3309d98715", }, privy: { id: "privy", name: "Privy", icon: "https://avatars.githubusercontent.com/u/81824329?s=200&v=4", }, gemini: { id: "gemini", name: "Gemini", connector: geminiConnector, icon: "https://explorer-api.walletconnect.com/v3/logo/sm/56a3fd87-2627-4903-fddd-205224dac500?projectId=34357d3c125c2bcf2ce2bc3309d98715", }, sequence: { id: "sequence", name: "Sequence", connector: sequenceConnector, icon: "https://sequence.app/icon.svg", }, } export const topShownWallets = [ "metamask", "walletconnect", "baseAccount", "rainbow", "phantom", ] export const getWalletIcon = (walletId?: string): string => { if (!walletId) return "" return (WALLET_CONFIGS[walletId]?.icon || "") as string } export const getWalletName = (walletId?: string): string => { if (!walletId) return "" return (WALLET_CONFIGS[walletId]?.name || "") as string } export const wagmiConnectorToWalletId = (wagmiConnector: any): string => { const wagmiConnectorName = ( wagmiConnector?.name || wagmiConnector?.id || "" ).toLowerCase() if (wagmiConnectorName.includes("rabby")) return "rabby" if (wagmiConnectorName.includes("metamask")) return "metamask" if (wagmiConnectorName.includes("walletconnect")) return "walletconnect" if (wagmiConnectorName.includes("coinbase")) return "coinbase" if (wagmiConnectorName.includes("base")) return "baseAccount" if (wagmiConnectorName.includes("rainbow")) return "rainbow" if (wagmiConnectorName.includes("trust")) return "trust" if (wagmiConnectorName.includes("ambire")) return "ambire" if (wagmiConnectorName.includes("argent")) return "argent" if (wagmiConnectorName.includes("okx")) return "okxwallet" if (wagmiConnectorName.includes("privy")) return "privy" if (wagmiConnectorName.includes("gemini")) return "gemini" if (wagmiConnectorName.includes("sequence")) return "sequence" return wagmiConnector.id || "injected" } // Hook to get combined wallets from WALLET_CONFIGS and wagmi connectors export const useWallets = () => { const { connectors } = useConnect() const allWallets = React.useMemo(() => { // Get config wallets that have connectors const configWallets = Object.values(WALLET_CONFIGS) .filter((config) => config.connector) .map((config) => ({ id: config.id, name: config.name, icon: config.icon, connector: config.connector, source: "config" as const, })) // Get wagmi wallets const wagmiWallets = connectors?.map((connector: any) => ({ id: wagmiConnectorToWalletId(connector), name: connector.name || "", icon: getWalletIcon(wagmiConnectorToWalletId(connector)) || connector.icon || "", connector: connector, source: "wagmi" as const, })) || [] // Combine and deduplicate, prioritizing wagmi over config const allWallets: any[] = [] for (const wallet of configWallets) { if (!wallet.connector) { wallet.connector = connectors?.find( (connector: any) => wagmiConnectorToWalletId(connector) === wallet.id, ) if (!wallet.connector) { continue } } allWallets.push({ id: wallet.id, name: wallet.name, icon: wallet.icon, connector: wallet.connector, source: "config" as const, }) } for (const wallet of wagmiWallets) { if ( !allWallets.find((w: any) => w.id === wagmiConnectorToWalletId(wallet)) ) { const configWallet = configWallets.find( (config: any) => config.id === wallet.id, ) allWallets.push({ id: wallet.id, name: configWallet?.name || wallet.name, icon: configWallet?.icon || wallet.icon, connector: wallet.connector, source: "wagmi" as const, }) } } return allWallets }, [connectors]) return { wallets: allWallets, } } // Helper method to find wallet by ID using the hook (for use in components) export const useFindWalletById = (walletId: string) => { const { wallets } = useWallets() return wallets.find((wallet: any) => wallet.id === walletId) || null }