diff --git a/.changeset/cuddly-dragons-talk.md b/.changeset/cuddly-dragons-talk.md new file mode 100644 index 00000000..f3a68608 --- /dev/null +++ b/.changeset/cuddly-dragons-talk.md @@ -0,0 +1,5 @@ +--- +'@node-real/walletkit': minor +--- + +Use behavior configuration to control different connection behaviors on different platform diff --git a/examples/nextjs/pages/_app.tsx b/examples/nextjs/pages/_app.tsx index 7984fd53..f8a29a24 100644 --- a/examples/nextjs/pages/_app.tsx +++ b/examples/nextjs/pages/_app.tsx @@ -2,7 +2,20 @@ import '@node-real/walletkit/styles.css'; import '@/styles/globals.css'; import { mainnet } from 'wagmi/chains'; -import { trustWallet, metaMask, walletConnect, defaultEvmConfig } from '@node-real/walletkit/evm'; +import { + trustWallet, + metaMask, + walletConnect, + defaultEvmConfig, + binanceWallet, + bitgetWallet, + codexFieldWallet, + coinbaseWallet, + mathWallet, + okxWallet, + tokenPocket, + uxuyWallet, +} from '@node-real/walletkit/evm'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { WalletKitProvider, @@ -11,7 +24,8 @@ import { WalletKitConfig, } from '@node-real/walletkit'; import { AppProps } from 'next/app'; -import { useAccount, useDisconnect } from 'wagmi'; +import { useAccount, useDisconnect, useSignMessage } from 'wagmi'; +import { useState } from 'react'; const queryClient = new QueryClient(); @@ -23,7 +37,22 @@ const config: WalletKitConfig = { autoConnect: true, initialChainId: 1, walletConnectProjectId: '518ee55b46bc23b5b496b03b1322aa13', - wallets: [metaMask(), trustWallet(), walletConnect()], + wallets: [ + binanceWallet(), + trustWallet(), + walletConnect(), + uxuyWallet(), + codexFieldWallet(), + metaMask(), + + bitgetWallet(), + coinbaseWallet(), + + tokenPocket(), + okxWallet(), + + mathWallet(), + ], chains: [mainnet], }), }; @@ -42,15 +71,31 @@ export default function App({ Component, pageProps }: AppProps) { function ConnectButton() { const { onOpen } = useConnectModal(); + const [signResult, setSignResult] = useState(''); - const { address, isConnected } = useAccount(); + const { address } = useAccount(); const { disconnect } = useDisconnect(); + const { signMessageAsync } = useSignMessage(); - if (isConnected) { + if (address) { return ( <> -
address:{address}
- +
+ +
address:{address}
+
+
+ + +
signed message:{signResult}
+
); } diff --git a/examples/vite/src/App.tsx b/examples/vite/src/App.tsx index 6058a325..34fe4f71 100644 --- a/examples/vite/src/App.tsx +++ b/examples/vite/src/App.tsx @@ -14,7 +14,8 @@ import { } from '@node-real/walletkit/evm'; import { mainnet } from 'viem/chains'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; -import { useAccount, useDisconnect } from 'wagmi'; +import { useAccount, useDisconnect, useSignMessage } from 'wagmi'; +import { useState } from 'react'; const queryClient = new QueryClient(); @@ -44,15 +45,31 @@ export default function App() { function ConnectButton() { const { onOpen } = useConnectModal(); + const [signResult, setSignResult] = useState(''); const { address } = useAccount(); const { disconnect } = useDisconnect(); + const { signMessageAsync } = useSignMessage(); if (address) { return ( <> -
address:{address}
- +
+ +
address:{address}
+
+
+ + +
signed message:{signResult}
+
); } diff --git a/packages/walletkit/__dev__/App.tsx b/packages/walletkit/__dev__/App.tsx index fce3f600..7be3ab25 100644 --- a/packages/walletkit/__dev__/App.tsx +++ b/packages/walletkit/__dev__/App.tsx @@ -1,11 +1,5 @@ import './style.css'; -import { - ConnectModal, - isMobile, - useConnectModal, - WalletKitConfig, - WalletKitProvider, -} from '@/core/index'; +import { ConnectModal, useConnectModal, WalletKitConfig, WalletKitProvider } from '@/core/index'; import VConsole from 'vconsole'; import { binanceWallet, @@ -93,41 +87,6 @@ export default function App() { ); } -export const getIsAndroid = () => { - const ua = navigator.userAgent; - const android = Boolean(ua.match(/Android/i)); - return android; -}; - -export const getHref = (isAndroid: boolean, wc?: string) => { - const appID = 'xoqXxUSMRccLCrZNRebmzj'; - const startPagePath = 'L3BhZ2VzL2Rhc2hib2FyZC1uZXcvaW5kZXg='; - - let qs = `appId=${appID}&startPagePath=${startPagePath}`; - if (wc) { - const startPageQuery = encodeURI( - `wc=${encodeURIComponent(wc)}&isDeepLink=true&id=${+new Date()}`, - ); - qs = `${qs}&startPageQuery=${startPageQuery}`; - } - const host = '//app.binance.com'; - if (isAndroid) { - return `bnc:${host}/mp/app?${qs}`; - } - return `https:${host}/?_dp=${encodeURI(`/mp/app?${qs}`)}`; -}; - -export const openBinanceDeepLink = (wc?: string) => { - const href = getHref(true, wc); - if (!isMobile()) return; - - const a = document.createElement('a'); - a.href = href; - document.body.appendChild(a); - a.click(); - document.body.removeChild(a); -}; - function ConnectButton() { const { onOpen } = useConnectModal(); diff --git a/packages/walletkit/src/core/configs/types.ts b/packages/walletkit/src/core/configs/types.ts index a2bfaf48..d78685ca 100644 --- a/packages/walletkit/src/core/configs/types.ts +++ b/packages/walletkit/src/core/configs/types.ts @@ -1,6 +1,7 @@ import { ColorMode } from '@/core/providers/ThemeProvider/context'; export type WalletType = 'evm' | 'solana' | 'tron'; + export type PlatformType = | 'tg-android' | 'tg-ios' @@ -9,6 +10,16 @@ export type PlatformType = | 'browser-ios' | 'browser-pc'; +export type ConnectType = 'default' | 'sdk' | 'uri' | 'qrcode' | 'walletConnect'; + +export interface BaseBehavior { + platforms: PlatformType[]; + connectType: ConnectType; + isInstalled?: () => boolean | undefined; + getAppLink?: () => string | undefined; + getUri?: (uri: string) => string | undefined; +} + export interface WalletConfig { name: string; logos: { @@ -21,15 +32,13 @@ export interface WalletConfig { spinnerColor?: string; } -export interface BaseWallet extends WalletConfig { +export interface BaseWallet extends WalletConfig { id: string; walletType: WalletType; isDisabled?: boolean; isVisible?: boolean; render?: (props: WalletRenderProps) => React.ReactNode; - showQRCode?: boolean; - isInstalled: () => boolean | undefined; - platforms: PlatformType[]; + behaviors: T[]; } export interface WalletRenderProps { diff --git a/packages/walletkit/src/core/modals/ConnectModal/HomeView/index.tsx b/packages/walletkit/src/core/modals/ConnectModal/HomeView/index.tsx index 32bb66dd..c62b2a52 100644 --- a/packages/walletkit/src/core/modals/ConnectModal/HomeView/index.tsx +++ b/packages/walletkit/src/core/modals/ConnectModal/HomeView/index.tsx @@ -6,23 +6,19 @@ import { GridLayout } from './GridLayout'; import { ListLayout } from './ListLayout'; import { clsDisclaimer } from './styles.css'; import { useWalletKit } from '@/core/providers/WalletKitProvider/context'; -import { isAndroid, isBrowser, isIOS, isPC, isTMA } from '@/core/base/utils/mobile'; import { useMemo } from 'react'; +import { getPlatform } from '@/core/utils/common'; export function HomeView() { const { wallets, options } = useWalletKit(); const { isMobileLayout } = useResponsive(); const visibleWallets = useMemo(() => { + const platform = getPlatform(); const visibleWallets = wallets.filter((wallet) => { const isVisible = wallet.isVisible !== false && - ((isBrowser() && isAndroid() && wallet.platforms.includes('browser-android')) || - (isBrowser() && isIOS() && wallet.platforms.includes('browser-ios')) || - (isBrowser() && isPC() && wallet.platforms.includes('browser-pc')) || - (isTMA() && isAndroid() && wallet.platforms.includes('tg-android')) || - (isTMA() && isIOS() && wallet.platforms.includes('tg-ios')) || - (isTMA() && isPC() && wallet.platforms.includes('tg-pc'))); + !!wallet.behaviors.find((e) => e.platforms.includes(platform)); return isVisible; }); diff --git a/packages/walletkit/src/core/providers/ThemeProvider/index.tsx b/packages/walletkit/src/core/providers/ThemeProvider/index.tsx index 776e954b..f7cbde8d 100644 --- a/packages/walletkit/src/core/providers/ThemeProvider/index.tsx +++ b/packages/walletkit/src/core/providers/ThemeProvider/index.tsx @@ -104,7 +104,7 @@ export function ThemeProvider(props: ThemeProviderProps) { return ( - + {children} ); diff --git a/packages/walletkit/src/core/utils/common.ts b/packages/walletkit/src/core/utils/common.ts index 506be54c..1501485c 100644 --- a/packages/walletkit/src/core/utils/common.ts +++ b/packages/walletkit/src/core/utils/common.ts @@ -1,4 +1,5 @@ -import { isTMA } from '../base/utils/mobile'; +import { isAndroid, isIOS, isPC, isTMA } from '../base/utils/mobile'; +import { PlatformType } from '../configs/types'; export function mergeList(list1: any[] = [], list2: any[] = []) { const result: any[] = [...list1]; @@ -34,3 +35,28 @@ export async function openLink(uri?: string, target = '_self') { const finalTarget = isTMA() ? '_blank' : target; window.open(uri, finalTarget, 'noopener noreferrer'); } + +export function getPlatform(): PlatformType { + if (isTMA()) { + if (isPC()) { + return 'tg-pc'; + } + if (isAndroid()) { + return 'tg-android'; + } + if (isIOS()) { + return 'tg-ios'; + } + } else { + if (isPC()) { + return 'browser-pc'; + } + if (isAndroid()) { + return 'browser-android'; + } + if (isIOS()) { + return 'browser-ios'; + } + } + return 'browser-pc'; +} diff --git a/packages/walletkit/src/evm/components/EvmConnectingView/index.tsx b/packages/walletkit/src/evm/components/EvmConnectingView/index.tsx index e4409f2f..247d8710 100644 --- a/packages/walletkit/src/evm/components/EvmConnectingView/index.tsx +++ b/packages/walletkit/src/evm/components/EvmConnectingView/index.tsx @@ -6,17 +6,19 @@ import { useWalletConnector } from '@/evm/hooks/useWalletConnector'; import { useCallback } from 'react'; import { useConnectingStatus } from '@/evm/hooks/useConnectingStatus'; import { useAccount } from 'wagmi'; +import { getEvmWalletPlatformBehavior } from '@/evm/utils/getEvmWalletPlatformBehavior'; export function EvmConnectingView() { const { selectedWallet } = useWalletKit(); const isConnected = useIsConnected(); const selectedConnector = useWalletConnector(selectedWallet.id); + const behavior = getEvmWalletPlatformBehavior(selectedWallet); const { connect, status, setStatus } = useConnectingStatus(); const { address } = useAccount(); const runConnect = useCallback(() => { - if (!selectedWallet.isInstalled()) return; + if (!behavior?.isInstalled?.()) return; if (selectedConnector) { setStatus(CONNECT_STATUS.CONNECTING); @@ -24,7 +26,7 @@ export function EvmConnectingView() { } else { setStatus(CONNECT_STATUS.UNAVAILABLE); } - }, [connect, selectedConnector, selectedWallet, setStatus]); + }, [behavior, connect, selectedConnector, setStatus]); return ( { + const behavior = getEvmWalletPlatformBehavior(selectedWallet); + + return selectedWallet.id === metaMask().id ? metaMaskUri : wcUri - ? (selectedWallet as EvmWallet).getUri?.(wcUri) + ? behavior?.getUri?.(wcUri) : wcUri; + }, [metaMaskUri, selectedWallet, wcUri]); const onConnect = () => { setStatus(CONNECT_STATUS.CONNECTING); diff --git a/packages/walletkit/src/evm/components/SetEvmWalletClickRef/index.tsx b/packages/walletkit/src/evm/components/SetEvmWalletClickRef/index.tsx index b2269801..4a20f4f0 100644 --- a/packages/walletkit/src/evm/components/SetEvmWalletClickRef/index.tsx +++ b/packages/walletkit/src/evm/components/SetEvmWalletClickRef/index.tsx @@ -7,13 +7,8 @@ import { useWalletKit } from '@/core/providers/WalletKitProvider/context'; import { openLink } from '@/core/utils/common'; import { useEvmConnect } from '@/evm/hooks/useEvmConnect'; import { useWalletConnectModal } from '@/evm/hooks/useWalletConnectModal'; -import { - binanceWallet, - codexFieldWallet, - EvmWallet, - isWalletConnect, - uxuyWallet, -} from '@/evm/wallets'; +import { getEvmWalletPlatformBehavior } from '@/evm/utils/getEvmWalletPlatformBehavior'; +import { EvmWallet } from '@/evm/wallets'; import { useRef } from 'react'; import { useConnectors, useDisconnect } from 'wagmi'; @@ -38,12 +33,13 @@ export function SetEvmWalletClickRef(props: SetEvmWalletClickRefProps) { clickRef.current = (walletId: string, e: React.MouseEvent) => { const wallet = evmConfig!.wallets.find((item) => item.id === walletId)! as EvmWallet; const connector = connectors.find((item) => item.id === walletId)!; + const behavior = getEvmWalletPlatformBehavior(wallet); const pass = options.onClickWallet?.(wallet, e); if (pass === false) return; log('[ClickWallet]', `ethereum:`, typeof window.ethereum); - log('[ClickWallet]', `installed:`, wallet.isInstalled()); + log('[ClickWallet]', `installed:`, behavior?.isInstalled?.()); const jumpTo = (viewRoute: ViewRoutes) => { setSelectedWallet(wallet); @@ -57,38 +53,19 @@ export function SetEvmWalletClickRef(props: SetEvmWalletClickRefProps) { } }; - const jumpToQRCodeView = () => { - jumpTo(ViewRoutes.EVM_QRCODE); - }; - - const jumpToConnectingView = () => { - jumpTo(ViewRoutes.EVM_CONNECTING); - }; - - const jumpToDeepLink = () => { - const deepLink = wallet.getDeepLink(); - if (deepLink) { - openLink(deepLink); - } else { - options.onError?.( - new Error(`The wallet does not support deeplink`), - `The wallet does not support deeplink`, - ); - } - }; - - const jumpToUriConnectingView = () => { - jumpTo(ViewRoutes.EVM_URI_CONNECTING); - }; - disconnect(); clearTimeout(timerRef.current); - const useSDK = [binanceWallet().id].includes(walletId); - const delay = useSDK ? 0 : 300; - const handleJumping = () => { - if (useSDK) { + if (behavior?.connectType === 'walletConnect') { + if (isMobile()) { + wcModal.onOpen(); + } else { + jumpTo(ViewRoutes.EVM_QRCODE); + } + } + + if (behavior?.connectType === 'sdk') { setSelectedWallet(wallet); connect({ connector, @@ -99,45 +76,26 @@ export function SetEvmWalletClickRef(props: SetEvmWalletClickRefProps) { return; } - // 1. TMA - if (isTMA()) { - if ([uxuyWallet().id, codexFieldWallet().id].includes(walletId)) { - jumpToConnectingView(); - return; - } + if (behavior?.connectType === 'qrcode') { + jumpTo(ViewRoutes.EVM_QRCODE); + } + if (behavior?.connectType === 'uri') { + jumpTo(ViewRoutes.EVM_URI_CONNECTING); + } + + if (behavior?.connectType === 'default') { if (isMobile()) { - // 1.1 mobile - if (isWalletConnect(walletId)) { - wcModal.onOpen(); - } else { - jumpToUriConnectingView(); - } - } else { - // 1.2 pc - jumpToQRCodeView(); - } - } else if (isMobile()) { - // 2. mobile - if (wallet.isInstalled()) { - if (isWalletConnect(walletId)) { - wcModal.onOpen(); + if (behavior.isInstalled?.()) { + jumpTo(ViewRoutes.EVM_CONNECTING); } else { - jumpToConnectingView(); + const appLink = behavior.getAppLink?.(); + if (appLink) { + openLink(appLink); + } } } else { - jumpToDeepLink(); - } - } else { - // 3. pc - if (wallet.showQRCode) { - jumpToQRCodeView(); - } else { - if (isWalletConnect(walletId)) { - wcModal.onOpen(); - } else { - jumpToConnectingView(); - } + jumpTo(ViewRoutes.EVM_CONNECTING); } } }; @@ -145,6 +103,7 @@ export function SetEvmWalletClickRef(props: SetEvmWalletClickRefProps) { if (isTMA() && isMobile()) { handleJumping(); } else { + const delay = behavior?.connectType === 'sdk' ? 0 : 300; timerRef.current = setTimeout(handleJumping, delay); } }; diff --git a/packages/walletkit/src/evm/hooks/useConnectingStatus.ts b/packages/walletkit/src/evm/hooks/useConnectingStatus.ts index 8b9f2496..2f9a2d48 100644 --- a/packages/walletkit/src/evm/hooks/useConnectingStatus.ts +++ b/packages/walletkit/src/evm/hooks/useConnectingStatus.ts @@ -5,6 +5,7 @@ import { useEvmConnect } from './useEvmConnect'; import { EventEmitter } from '@/core/utils/eventEmitter'; import { Config } from 'wagmi'; import { ConnectData } from 'wagmi/query'; +import { getEvmWalletPlatformBehavior } from '../utils/getEvmWalletPlatformBehavior'; interface UseConnectingStatusProps { initialStatus?: CONNECT_STATUS; @@ -15,7 +16,9 @@ export function useConnectingStatus(props: UseConnectingStatusProps = {}) { const { selectedWallet, evmConfig, options, action } = useWalletKit(); - const defaultStatus = selectedWallet.isInstalled() + const behavior = getEvmWalletPlatformBehavior(selectedWallet); + + const defaultStatus = behavior?.isInstalled?.() ? CONNECT_STATUS.CONNECTING : CONNECT_STATUS.UNAVAILABLE; diff --git a/packages/walletkit/src/evm/hooks/useEvmConnect.ts b/packages/walletkit/src/evm/hooks/useEvmConnect.ts index 64dc77e9..08dc2df5 100644 --- a/packages/walletkit/src/evm/hooks/useEvmConnect.ts +++ b/packages/walletkit/src/evm/hooks/useEvmConnect.ts @@ -11,7 +11,7 @@ export type UseEvmConnectReturnType = ReturnType; let timer: any; export function useEvmConnect(props?: UseEvmConnectProps): UseEvmConnectReturnType { - const { log, options, evmConfig } = useWalletKit(); + const { log, options, evmConfig, selectedWallet } = useWalletKit(); const connectProps = { chainId: evmConfig?.initialChainId, @@ -33,6 +33,7 @@ export function useEvmConnect(props?: UseEvmConnectProps): UseEvmConnectReturnTy log, handler: options.onError, error, + wallet: selectedWallet, }); } }, 100); diff --git a/packages/walletkit/src/evm/hooks/useEvmSwitchChain.ts b/packages/walletkit/src/evm/hooks/useEvmSwitchChain.ts index 7a1bc83b..09367ce8 100644 --- a/packages/walletkit/src/evm/hooks/useEvmSwitchChain.ts +++ b/packages/walletkit/src/evm/hooks/useEvmSwitchChain.ts @@ -6,7 +6,7 @@ import { evmCommonErrorHandler } from '../utils/evmCommonErrorHandler'; export type UseEvmSwitchChainProps = Parameters[0]; export function useEvmSwitchChain(props?: UseEvmSwitchChainProps) { - const { options, log } = useWalletKit(); + const { options, log, selectedWallet } = useWalletKit(); const result = useSwitchChain({ ...props, @@ -17,6 +17,7 @@ export function useEvmSwitchChain(props?: UseEvmSwitchChainProps) { log, handler: options.onError, error, + wallet: selectedWallet, }); props?.mutation?.onError?.(error, ...params); }, diff --git a/packages/walletkit/src/evm/utils/defaultEvmConfig.ts b/packages/walletkit/src/evm/utils/defaultEvmConfig.ts index 9292bc97..d3611f27 100644 --- a/packages/walletkit/src/evm/utils/defaultEvmConfig.ts +++ b/packages/walletkit/src/evm/utils/defaultEvmConfig.ts @@ -13,6 +13,7 @@ import { setEvmGlobalData } from '../globalData'; import { codexFieldWallet } from '../wallets/codexFieldWallet'; import { ChainDisplayConfig } from '@/evm/chains/types'; import { getChainDisplayConfigs } from '../chains'; +import { getEvmWalletPlatformBehavior } from './getEvmWalletPlatformBehavior'; interface CustomizedEvmConfig extends Omit { @@ -90,17 +91,20 @@ export function defaultEvmConfig(params: CustomizedEvmConfig) { } function getCreateConnectorFns(wallets: EvmWallet[]) { - const fns = wallets.map((w) => { - const fn = w.getCreateConnectorFn(); - - // If we disable a wallet but still let it show up in the list, - // we should clear the cache to prevent `autoConnect` from automatically connecting to the wallet. - if (w.isDisabled && typeof window !== 'undefined') { - localStorage.removeItem(`wagmi.${w.id}.shimDisconnect`); - } - - return fn; - }); + const fns = wallets + .map((w) => { + // If we disable a wallet but still let it show up in the list, + // we should clear the cache to prevent `autoConnect` from automatically connecting to the wallet. + if (w.isDisabled && typeof window !== 'undefined') { + localStorage.removeItem(`wagmi.${w.id}.shimDisconnect`); + } + + const behavior = getEvmWalletPlatformBehavior(w); + if (behavior?.getCreateConnectorFn) { + return behavior.getCreateConnectorFn(); + } + }) + .filter((e) => !!e); createSingletonWalletConnect(wallets, fns); @@ -115,6 +119,8 @@ function createSingletonWalletConnect(wallets: EvmWallet[], fns: CreateConnector return; } - const fn = walletConnect().getCreateConnectorFn(); - fns.push(fn); + const fn = walletConnect().behaviors?.[0]?.getCreateConnectorFn?.(); + if (fn) { + fns.push(fn); + } } diff --git a/packages/walletkit/src/evm/utils/evmCommonErrorHandler.ts b/packages/walletkit/src/evm/utils/evmCommonErrorHandler.ts index 948d5d83..ee9039bb 100644 --- a/packages/walletkit/src/evm/utils/evmCommonErrorHandler.ts +++ b/packages/walletkit/src/evm/utils/evmCommonErrorHandler.ts @@ -1,9 +1,18 @@ import { isIOS, isMobile } from '@/core/base/utils/mobile'; -import { binanceWallet, trustWallet } from '../wallets'; +import { binanceWallet, EvmWallet, trustWallet } from '../wallets'; +import { getEvmWalletPlatformBehavior } from './getEvmWalletPlatformBehavior'; -export function evmCommonErrorHandler(props: { log: any; handler: any; error: any }) { +export function evmCommonErrorHandler(props: { + log: any; + handler: any; + error: any; + wallet: EvmWallet; +}) { const { log, handler, error } = props; + const trustBehavior = getEvmWalletPlatformBehavior(trustWallet()); + const binanceBehavior = getEvmWalletPlatformBehavior(binanceWallet()); + let text = ''; if (error) { @@ -11,7 +20,7 @@ export function evmCommonErrorHandler(props: { log: any; handler: any; error: an switch (error.code) { case 4902: // TODO - if (isIOS() && trustWallet().isInstalled()) { + if (isIOS() && trustBehavior?.isInstalled?.()) { text = 'Not supported chainId'; } break; @@ -26,7 +35,7 @@ export function evmCommonErrorHandler(props: { log: any; handler: any; error: an description = 'Use rejected the request'; } - if (isMobile() && binanceWallet().isInstalled()) { + if (isMobile() && binanceBehavior?.isInstalled?.()) { if ( description?.includes('Request failed: The JSON sent is not a valid Request object.') || description?.includes('Adaptor not found: eip155') diff --git a/packages/walletkit/src/evm/utils/getEvmWalletPlatformBehavior.ts b/packages/walletkit/src/evm/utils/getEvmWalletPlatformBehavior.ts new file mode 100644 index 00000000..6562b760 --- /dev/null +++ b/packages/walletkit/src/evm/utils/getEvmWalletPlatformBehavior.ts @@ -0,0 +1,8 @@ +import { getPlatform } from '@/core/utils/common'; +import { EvmWallet } from '../wallets'; + +export function getEvmWalletPlatformBehavior(wallet: EvmWallet) { + const platform = getPlatform(); + const behavior = wallet.behaviors.find((e) => e.platforms.includes(platform)); + return behavior; +} diff --git a/packages/walletkit/src/evm/wallets/binanceWallet/index.tsx b/packages/walletkit/src/evm/wallets/binanceWallet/index.tsx index 9a7abcc5..ac88d565 100644 --- a/packages/walletkit/src/evm/wallets/binanceWallet/index.tsx +++ b/packages/walletkit/src/evm/wallets/binanceWallet/index.tsx @@ -1,5 +1,4 @@ import { BinanceW3WParameters, getWagmiConnectorV2 } from '@binance/w3w-wagmi-connector-v2'; -import { isInBinance } from '@binance/w3w-utils'; import { isMobile, isTMA } from '@/core/base/utils/mobile'; import { binanceWalletConfig } from '@/core/configs/binanceWallet'; import { EvmWallet } from '../types'; @@ -14,82 +13,84 @@ export interface BinanceWalletOptions extends Partial { export function binanceWallet(props: BinanceWalletOptions = {}): EvmWallet { const { connectorOptions = {}, ...restProps } = props; + const getProvider = () => { + if (typeof window === 'undefined') return; + return getEvmInjectedProvider('isBinance'); + }; + + const isInstalled = () => { + return !!getProvider(); + }; + return { ...binanceWalletConfig, id: 'binanceWeb3Wallet', walletType: 'evm', - showQRCode: false, - platforms: ['tg-android', 'tg-ios', 'tg-pc', 'browser-android', 'browser-ios', 'browser-pc'], - isInstalled() { - return !!getProvider(); - }, - getDeepLink() { - const url = window.location.href; - const base = 'bnc://app.binance.com/mp/app'; - const appId = 'yFK5FCqYprrXDiVFbhyRx7'; - - const startPagePath = window.btoa('/pages/browser/index'); - const startPageQuery = window.btoa(`url=${url}`); - const deeplink = `${base}?appId=${appId}&startPagePath=${startPagePath}&startPageQuery=${startPageQuery}`; - const dp = window.btoa(deeplink); - const http = `https://app.binance.com/en/download?_dp=${dp}`; + behaviors: [ + { + platforms: ['tg-android', 'tg-ios', 'tg-pc', 'browser-pc'], + connectType: 'sdk', + getCreateConnectorFn() { + if (typeof window !== 'undefined' && isMobile() && isTMA()) { + const originalAppendChild = document.body.appendChild; - return http; - }, - getUri(uri) { - const encodedUri = encodeURIComponent(uri); - return `https://app.binance.com/cedefi/wc?uri=${encodedUri}`; - }, - getCreateConnectorFn() { - if (isInBinance()) { - let isReady = false; + document.body.appendChild = function (node, ...params) { + if (node instanceof HTMLAnchorElement && node.href?.startsWith('bnc://')) { + node.href = `https://app.binance.com/en/download?_dp=${window.btoa(node.href)}`; + node.target = '_blank'; - return injected({ - shimDisconnect: true, - target: { - id: this.id, - name: binanceWallet().name, - async provider() { - if (isMobile() && binanceWallet().isInstalled() && !isReady) { - await sleep(3000); + const div = document.createElement('div'); + div.textContent = node.href; + document.body.appendChild(div); } - isReady = true; - return getProvider(); - }, - }, - ...connectorOptions, - }); - } + return originalAppendChild.call(document.body, node, ...params) as any; + }; + } - if (typeof window !== 'undefined') { - const originalAppendChild = document.body.appendChild; + const connector = getWagmiConnectorV2(); + return connector({ + ...connectorOptions, + }); + }, + }, + { + platforms: ['browser-android', 'browser-ios'], + connectType: 'default', + isInstalled, + getAppLink() { + const url = window.location.href; + const base = 'bnc://app.binance.com/mp/app'; + const appId = 'yFK5FCqYprrXDiVFbhyRx7'; - document.body.appendChild = function (node, ...params) { - if (node instanceof HTMLAnchorElement && node.href?.startsWith('bnc://')) { - node.href = `https://app.binance.com/en/download?_dp=${window.btoa(node.href)}`; - node.target = '_blank'; - // node.href = node.href.replace('bnc://', 'https://'); + const startPagePath = window.btoa('/pages/browser/index'); + const startPageQuery = window.btoa(`url=${url}`); + const deeplink = `${base}?appId=${appId}&startPagePath=${startPagePath}&startPageQuery=${startPageQuery}`; + const dp = window.btoa(deeplink); + const http = `https://app.binance.com/en/download?_dp=${dp}`; - // const qs = node.href.replace('bnc://app.binance.com/mp/app?', ''); - // node.href = `https://app.binance.com/?_dp=${encodeURI(`/mp/app?${qs}`)}`; - const div = document.createElement('div'); - div.textContent = node.href; - document.body.appendChild(div); - } - return originalAppendChild.call(document.body, node, ...params) as any; - }; - } + return http; + }, + getCreateConnectorFn() { + let isReady = false; - const connector = getWagmiConnectorV2(); - return connector({ - ...connectorOptions, - }); - }, + return injected({ + shimDisconnect: true, + target: { + id: binanceWallet().id, + name: binanceWallet().name, + async provider() { + if (isMobile() && isInstalled() && !isReady) { + await sleep(3000); + } + isReady = true; + return getProvider(); + }, + }, + ...connectorOptions, + }); + }, + }, + ], ...restProps, }; } - -function getProvider() { - if (typeof window === 'undefined') return; - return getEvmInjectedProvider('isBinance'); -} diff --git a/packages/walletkit/src/evm/wallets/bitgetWallet/index.tsx b/packages/walletkit/src/evm/wallets/bitgetWallet/index.tsx index 62d2f3d3..a9c0636a 100644 --- a/packages/walletkit/src/evm/wallets/bitgetWallet/index.tsx +++ b/packages/walletkit/src/evm/wallets/bitgetWallet/index.tsx @@ -7,43 +7,58 @@ import { isAndroid, isTMA } from '@/core/base/utils/mobile'; export function bitgetWallet(props: InjectedEvmWalletOptions = {}): EvmWallet { const { connectorOptions, ...restProps } = props; + const getUri = (uri: string) => { + let encodedUri = encodeURIComponent(uri); + if (isTMA() && isAndroid()) { + encodedUri = encodeURIComponent(encodedUri); + } + return `https://bkcode.vip/wc?uri=${encodedUri}`; + }; + + const getProvider = () => { + if (typeof window === 'undefined') return; + return getEvmInjectedProvider('isBitEthereum') ?? window.bitkeep?.ethereum; + }; + return { ...bitgetWalletConfig, id: 'bitgetWallet', walletType: 'evm', - showQRCode: false, - platforms: ['tg-android', 'tg-ios', 'tg-pc', 'browser-android', 'browser-ios', 'browser-pc'], - isInstalled() { - return !!getProvider(); - }, - getDeepLink() { - return `https://bkcode.vip?action=dapp&url=${window.location.href}`; - }, - getUri(uri) { - let encodedUri = encodeURIComponent(uri); - if (isTMA() && isAndroid()) { - encodedUri = encodeURIComponent(encodedUri); - } - return `https://bkcode.vip/wc?uri=${encodedUri}`; - }, - getCreateConnectorFn() { - return injected({ - shimDisconnect: true, - target: { - id: bitgetWallet().id, - name: bitgetWallet().name, - async provider() { - return getProvider(); - }, + behaviors: [ + { + platforms: ['tg-android', 'tg-ios'], + connectType: 'uri', + getUri, + }, + { + platforms: ['tg-pc'], + connectType: 'qrcode', + getUri, + }, + { + platforms: ['browser-android', 'browser-ios', 'browser-pc'], + connectType: 'default', + isInstalled() { + return !!getProvider(); }, - ...connectorOptions, - }); - }, + getAppLink() { + return `https://bkcode.vip?action=dapp&url=${window.location.href}`; + }, + getCreateConnectorFn() { + return injected({ + shimDisconnect: true, + target: { + id: bitgetWallet().id, + name: bitgetWallet().name, + async provider() { + return getProvider(); + }, + }, + ...connectorOptions, + }); + }, + }, + ], ...restProps, }; } - -function getProvider() { - if (typeof window === 'undefined') return; - return getEvmInjectedProvider('isBitEthereum') ?? window.bitkeep?.ethereum; -} diff --git a/packages/walletkit/src/evm/wallets/codexFieldWallet/index.tsx b/packages/walletkit/src/evm/wallets/codexFieldWallet/index.tsx index db0b0fb6..d140bc45 100644 --- a/packages/walletkit/src/evm/wallets/codexFieldWallet/index.tsx +++ b/packages/walletkit/src/evm/wallets/codexFieldWallet/index.tsx @@ -5,7 +5,6 @@ import { } from 'codexfield-wallet-connector'; import { getEvmGlobalData } from '@/evm/globalData'; import { codexFieldWalletConfig } from '@/core/configs/codexFieldWallet'; -import { isTMA } from '@/core/base/utils/mobile'; interface CodexFieldWalletOptions extends Partial { connectorOptions?: Partial; @@ -18,29 +17,27 @@ export function codexFieldWallet(props: CodexFieldWalletOptions = {}): EvmWallet ...codexFieldWalletConfig, id: 'codexFieldWallet', walletType: 'evm', - showQRCode: false, - platforms: ['tg-android', 'tg-ios', 'tg-pc'], - isInstalled() { - return isTMA(); - }, - getDeepLink() { - return undefined; - }, - getUri(uri) { - return undefined; - }, - getCreateConnectorFn() { - const { walletConnectProjectId } = getEvmGlobalData(); + behaviors: [ + { + platforms: ['tg-android', 'tg-ios', 'tg-pc'], + connectType: 'default', + isInstalled() { + return true; + }, + getCreateConnectorFn() { + const { walletConnectProjectId } = getEvmGlobalData(); - if (!walletConnectProjectId) { - throw new Error('walletConnectProjectId is required.'); - } + if (!walletConnectProjectId) { + throw new Error('walletConnectProjectId is required.'); + } - return wagmiCodexFieldWallet({ - projectId: walletConnectProjectId, - ...connectorOptions, - }); - }, + return wagmiCodexFieldWallet({ + projectId: walletConnectProjectId, + ...connectorOptions, + }); + }, + }, + ], ...restProps, }; } diff --git a/packages/walletkit/src/evm/wallets/coinbaseWallet/index.tsx b/packages/walletkit/src/evm/wallets/coinbaseWallet/index.tsx index ac6e2c6d..f70f81c2 100644 --- a/packages/walletkit/src/evm/wallets/coinbaseWallet/index.tsx +++ b/packages/walletkit/src/evm/wallets/coinbaseWallet/index.tsx @@ -14,44 +14,45 @@ interface CoinbaseWalletOptions extends Partial { export function coinbaseWallet(props: CoinbaseWalletOptions = {}): EvmWallet { const { connectorOptions, ...restProps } = props; + const getProvider = () => { + if (typeof window === 'undefined') return; + return getEvmInjectedProvider('isCoinbaseWallet') || window.coinbaseWalletExtension; + }; + return { ...coinbaseWalletConfig, id: 'coinbaseWallet', walletType: 'evm', - showQRCode: false, - platforms: ['browser-android', 'browser-ios', 'browser-pc'], - isInstalled() { - if ( - connectorOptions && - 'headlessMode' in connectorOptions && - !connectorOptions.headlessMode - ) { - return true; - } - return !!getProvider(); - }, - getDeepLink() { - return `https://go.cb-w.com/dapp?cb_url=${encodeURIComponent(window.location.href)}`; - }, - getUri() { - return undefined; - }, - getCreateConnectorFn() { - const { metadata } = getEvmGlobalData(); + behaviors: [ + { + platforms: ['browser-android', 'browser-ios', 'browser-pc'], + connectType: 'default', + isInstalled() { + if ( + connectorOptions && + 'headlessMode' in connectorOptions && + !connectorOptions.headlessMode + ) { + return true; + } + return !!getProvider(); + }, + getAppLink() { + return `https://go.cb-w.com/dapp?cb_url=${encodeURIComponent(window.location.href)}`; + }, + getCreateConnectorFn() { + const { metadata } = getEvmGlobalData(); - return wagmiCoinbaseWallet({ - appName: metadata!.name, - headlessMode: true, - overrideIsMetaMask: false, - appLogoUrl: metadata?.icon, - ...connectorOptions, - }); - }, + return wagmiCoinbaseWallet({ + appName: metadata!.name, + headlessMode: true, + overrideIsMetaMask: false, + appLogoUrl: metadata?.icon, + ...connectorOptions, + }); + }, + }, + ], ...restProps, }; } - -function getProvider() { - if (typeof window === 'undefined') return; - return getEvmInjectedProvider('isCoinbaseWallet') || window.coinbaseWalletExtension; -} diff --git a/packages/walletkit/src/evm/wallets/mathWallet/index.tsx b/packages/walletkit/src/evm/wallets/mathWallet/index.tsx index d36c6f1c..a21ebb32 100644 --- a/packages/walletkit/src/evm/wallets/mathWallet/index.tsx +++ b/packages/walletkit/src/evm/wallets/mathWallet/index.tsx @@ -6,41 +6,38 @@ import { getEvmInjectedProvider } from '../utils'; export function mathWallet(props: InjectedEvmWalletOptions = {}): EvmWallet { const { connectorOptions, ...restProps } = props; + const getProvider = () => { + if (typeof window === 'undefined') return; + return getEvmInjectedProvider('isMathWallet'); + }; + return { ...mathWalletConfig, id: 'mathWallet', walletType: 'evm', spinnerColor: undefined, - platforms: ['browser-android', 'browser-ios', 'browser-pc'], - isInstalled() { - return !!getProvider(); - }, - getDeepLink() { - // return `mathwallet://mathwallet.org?action=link&value=${window.location.href}`; - // return `mathwallet://wc?uri=${encodeURIComponent(uri)}`; - return undefined; - }, - getUri(uri) { - return uri; - }, - getCreateConnectorFn() { - return injected({ - shimDisconnect: true, - target: { - id: mathWallet().id, - name: mathWallet().name, - async provider() { - return getProvider(); - }, + behaviors: [ + { + platforms: ['browser-android', 'browser-ios', 'browser-pc'], + connectType: 'default', + isInstalled() { + return !!getProvider(); + }, + getCreateConnectorFn() { + return injected({ + shimDisconnect: true, + target: { + id: mathWallet().id, + name: mathWallet().name, + async provider() { + return getProvider(); + }, + }, + ...connectorOptions, + }); }, - ...connectorOptions, - }); - }, + }, + ], ...restProps, }; } - -function getProvider() { - if (typeof window === 'undefined') return; - return getEvmInjectedProvider('isMathWallet'); -} diff --git a/packages/walletkit/src/evm/wallets/metaMask/index.tsx b/packages/walletkit/src/evm/wallets/metaMask/index.tsx index d08e4b99..cbce4979 100644 --- a/packages/walletkit/src/evm/wallets/metaMask/index.tsx +++ b/packages/walletkit/src/evm/wallets/metaMask/index.tsx @@ -11,33 +11,45 @@ export interface MetaMaskOptions extends Partial { export function metaMask(props: MetaMaskOptions = {}): EvmWallet { const { connectorOptions, ...restProps } = props; + const getCreateConnectorFn = () => { + return metaMaskSDk({ + useDeeplink: false, + headless: true, + openDeeplink(arg) { + openLink(arg); + }, + ...connectorOptions, + }); + }; + return { ...metaMaskConfig, id: 'metaMask', walletType: 'evm', - showQRCode: false, - platforms: ['tg-android', 'tg-ios', 'tg-pc', 'browser-android', 'browser-ios', 'browser-pc'], - isInstalled() { - return hasEvmInjectedProvider('isMetaMask'); - }, - getDeepLink() { - const dappPath = window.location.href.replace(/^https?:\/\//, ''); - return `https://metamask.app.link/dapp/${dappPath}`; - }, - getUri(uri) { - const encodedUri = encodeURIComponent(uri); - return `https://metamask.app.link/wc?uri=${encodedUri}`; - }, - getCreateConnectorFn() { - return metaMaskSDk({ - useDeeplink: false, - headless: true, - openDeeplink(arg) { - openLink(arg); + behaviors: [ + { + platforms: ['tg-android', 'tg-ios'], + connectType: 'uri', + getCreateConnectorFn, + }, + { + platforms: ['tg-pc'], + connectType: 'qrcode', + getCreateConnectorFn, + }, + { + platforms: ['browser-android', 'browser-ios', 'browser-pc'], + connectType: 'default', + isInstalled() { + return hasEvmInjectedProvider('isMetaMask'); + }, + getAppLink() { + const dappPath = window.location.href.replace(/^https?:\/\//, ''); + return `https://metamask.app.link/dapp/${dappPath}`; }, - ...connectorOptions, - }); - }, + getCreateConnectorFn, + }, + ], ...restProps, }; } diff --git a/packages/walletkit/src/evm/wallets/okxWallet/index.tsx b/packages/walletkit/src/evm/wallets/okxWallet/index.tsx index f5f9aa2b..65b3ed9b 100644 --- a/packages/walletkit/src/evm/wallets/okxWallet/index.tsx +++ b/packages/walletkit/src/evm/wallets/okxWallet/index.tsx @@ -6,39 +6,40 @@ import { getEvmInjectedProvider } from '../utils'; export function okxWallet(props: InjectedEvmWalletOptions = {}): EvmWallet { const { connectorOptions, ...restProps } = props; + const getProvider = () => { + if (typeof window === 'undefined') return; + return getEvmInjectedProvider('isOkxWallet') ?? window.okexchain; + }; + return { ...okxWalletConfig, id: 'okxWallet', walletType: 'evm', - showQRCode: false, - platforms: ['browser-android', 'browser-ios', 'browser-pc'], - isInstalled() { - return !!getProvider(); - }, - getDeepLink() { - return `okx://wallet/dapp/details?dappUrl=${window.location.href}`; - }, - getUri(uri) { - return `okex://main/wc?uri=${encodeURIComponent(uri)}`; - }, - getCreateConnectorFn() { - return injected({ - shimDisconnect: true, - target: { - id: okxWallet().id, - name: okxWallet().name, - async provider() { - return getProvider(); - }, + behaviors: [ + { + platforms: ['browser-android', 'browser-ios', 'browser-pc'], + connectType: 'default', + isInstalled() { + return !!getProvider(); + }, + getAppLink() { + return `okx://wallet/dapp/details?dappUrl=${window.location.href}`; }, - ...connectorOptions, - }); - }, + getCreateConnectorFn() { + return injected({ + shimDisconnect: true, + target: { + id: okxWallet().id, + name: okxWallet().name, + async provider() { + return getProvider(); + }, + }, + ...connectorOptions, + }); + }, + }, + ], ...restProps, }; } - -function getProvider() { - if (typeof window === 'undefined') return; - return getEvmInjectedProvider('isOkxWallet') ?? window.okexchain; -} diff --git a/packages/walletkit/src/evm/wallets/safe/index.tsx b/packages/walletkit/src/evm/wallets/safe/index.tsx index db5036e5..311a13c8 100644 --- a/packages/walletkit/src/evm/wallets/safe/index.tsx +++ b/packages/walletkit/src/evm/wallets/safe/index.tsx @@ -13,24 +13,29 @@ export function safe(props: SafeOptions = {}): EvmWallet { ...safeConfig, id: 'safe', walletType: 'evm', - showQRCode: false, - platforms: ['tg-android', 'tg-ios', 'tg-pc', 'browser-android', 'browser-ios', 'browser-pc'], - isInstalled() { - return !(typeof window === 'undefined') && window?.parent !== window; - }, - getDeepLink: () => { - return undefined; - }, - getUri() { - return undefined; - }, - getCreateConnectorFn() { - return wagmiSafe({ - allowedDomains: [/gnosis-safe.io$/, /app.safe.global$/], - debug: false, - ...connectorOptions, - }); - }, + behaviors: [ + { + platforms: [ + 'tg-android', + 'tg-ios', + 'tg-pc', + 'browser-android', + 'browser-ios', + 'browser-pc', + ], + connectType: 'default', + isInstalled() { + return !(typeof window === 'undefined') && window?.parent !== window; + }, + getCreateConnectorFn() { + return wagmiSafe({ + allowedDomains: [/gnosis-safe.io$/, /app.safe.global$/], + debug: false, + ...connectorOptions, + }); + }, + }, + ], ...restProps, }; } diff --git a/packages/walletkit/src/evm/wallets/tokenPocket/index.tsx b/packages/walletkit/src/evm/wallets/tokenPocket/index.tsx index e640b770..78342860 100644 --- a/packages/walletkit/src/evm/wallets/tokenPocket/index.tsx +++ b/packages/walletkit/src/evm/wallets/tokenPocket/index.tsx @@ -6,44 +6,45 @@ import { getEvmInjectedProvider } from '../utils'; export function tokenPocket(props: InjectedEvmWalletOptions = {}): EvmWallet { const { connectorOptions, ...restProps } = props; + const getProvider = () => { + if (typeof window === 'undefined') return; + return ( + getEvmInjectedProvider('isTokenPocket') ?? window.tokenpocket?.ethereum ?? window.tokenpocket + ); + }; + return { ...tokenPocketConfig, id: 'tokenPocket', walletType: 'evm', - showQRCode: false, - platforms: ['browser-android', 'browser-ios', 'browser-pc'], - isInstalled() { - return !!getProvider(); - }, - getDeepLink() { - const params = { - url: window.location.href, - }; - return `tpdapp://open?params=${encodeURIComponent(JSON.stringify(params))}`; - }, - getUri(uri) { - return `tpoutside://wc?uri=${encodeURIComponent(uri)}`; - }, - getCreateConnectorFn() { - return injected({ - shimDisconnect: true, - target: { - id: tokenPocket().id, - name: tokenPocket().name, - async provider() { - return getProvider(); - }, + behaviors: [ + { + platforms: ['browser-android', 'browser-ios', 'browser-pc'], + connectType: 'default', + isInstalled() { + return !!getProvider(); + }, + getAppLink() { + const params = { + url: window.location.href, + }; + return `tpdapp://open?params=${encodeURIComponent(JSON.stringify(params))}`; }, - ...connectorOptions, - }); - }, + getCreateConnectorFn() { + return injected({ + shimDisconnect: true, + target: { + id: tokenPocket().id, + name: tokenPocket().name, + async provider() { + return getProvider(); + }, + }, + ...connectorOptions, + }); + }, + }, + ], ...restProps, }; } - -function getProvider() { - if (typeof window === 'undefined') return; - return ( - getEvmInjectedProvider('isTokenPocket') ?? window.tokenpocket?.ethereum ?? window.tokenpocket - ); -} diff --git a/packages/walletkit/src/evm/wallets/trustWallet/index.tsx b/packages/walletkit/src/evm/wallets/trustWallet/index.tsx index ffd2ec42..16c7957a 100644 --- a/packages/walletkit/src/evm/wallets/trustWallet/index.tsx +++ b/packages/walletkit/src/evm/wallets/trustWallet/index.tsx @@ -8,53 +8,69 @@ import { isAndroid, isTMA } from '@/core/base/utils/mobile'; export function trustWallet(props: InjectedEvmWalletOptions = {}): EvmWallet { const { connectorOptions, ...restProps } = props; + const getUri = (uri: string) => { + let encodedUri = encodeURIComponent(uri); + if (isTMA() && isAndroid()) { + encodedUri = encodeURIComponent(encodedUri); + } + return `https://link.trustwallet.com/wc?uri=${encodedUri}`; + }; + + const getProvider = () => { + if (typeof window === 'undefined') return; + + // binance web3 wallet will inject a trustwallet object with no request on mobile + if (!window?.trustwallet?.request) return; + + return window.trustwallet ?? window.trustWallet ?? getEvmInjectedProvider('isTrust'); + }; + return { ...trustWalletConfig, id: 'trust', walletType: 'evm', - showQRCode: false, - platforms: ['tg-android', 'tg-ios', 'tg-pc', 'browser-android', 'browser-ios', 'browser-pc'], - isInstalled() { - return !!getProvider(); - }, - getDeepLink() { - const encodedUrl = encodeURIComponent(window.location.href); - return `https://link.trustwallet.com/open_url?coin_id=60&url=${encodedUrl}`; - }, - getUri(uri) { - let encodedUri = encodeURIComponent(uri); - if (isTMA() && isAndroid()) { - encodedUri = encodeURIComponent(encodedUri); - } - return `https://link.trustwallet.com/wc?uri=${encodedUri}`; - }, - getCreateConnectorFn() { - let isReady = false; - return injected({ - shimDisconnect: true, - target: { - id: trustWallet().id, - name: trustWallet().name, - async provider() { - if (!isReady) { - await sleep(); - } - isReady = true; - return getProvider(); - }, + behaviors: [ + { + platforms: ['tg-android', 'tg-ios'], + connectType: 'uri', + getUri, + }, + { + platforms: ['tg-pc'], + connectType: 'qrcode', + getUri, + }, + { + platforms: ['browser-android', 'browser-ios', 'browser-pc'], + connectType: 'default', + isInstalled() { + return !!getProvider(); + }, + getAppLink() { + const encodedUrl = encodeURIComponent(window.location.href); + return `https://link.trustwallet.com/open_url?coin_id=60&url=${encodedUrl}`; }, - ...connectorOptions, - }); - }, + + getCreateConnectorFn() { + let isReady = false; + return injected({ + shimDisconnect: true, + target: { + id: trustWallet().id, + name: trustWallet().name, + async provider() { + if (!isReady) { + await sleep(); + } + isReady = true; + return getProvider(); + }, + }, + ...connectorOptions, + }); + }, + }, + ], ...restProps, }; } - -function getProvider() { - if (typeof window === 'undefined') return; - - // binance web3 wallet will inject a trustwallet object with no request on mobile - if (!window?.trustwallet?.request) return; - - return window.trustwallet ?? window.trustWallet ?? getEvmInjectedProvider('isTrust'); -} diff --git a/packages/walletkit/src/evm/wallets/types.ts b/packages/walletkit/src/evm/wallets/types.ts index aadd3784..db5a082c 100644 --- a/packages/walletkit/src/evm/wallets/types.ts +++ b/packages/walletkit/src/evm/wallets/types.ts @@ -1,13 +1,14 @@ import { CreateConnectorFn } from 'wagmi'; import { InjectedParameters } from './injected'; -import { BaseWallet } from '@/core/configs/types'; +import { BaseBehavior, BaseWallet } from '@/core/configs/types'; -export interface EvmWallet extends BaseWallet { - getCreateConnectorFn: () => CreateConnectorFn; - getDeepLink: () => string | undefined; - getUri: (uri: string) => string | undefined; +export interface EvmWalletBehavior extends BaseBehavior { + getCreateConnectorFn?: () => CreateConnectorFn; } +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface EvmWallet extends BaseWallet {} + export interface InjectedEvmWalletOptions extends Partial { connectorOptions?: InjectedParameters; } diff --git a/packages/walletkit/src/evm/wallets/uxuyWallet/index.tsx b/packages/walletkit/src/evm/wallets/uxuyWallet/index.tsx index 85eb336f..35d82fa8 100644 --- a/packages/walletkit/src/evm/wallets/uxuyWallet/index.tsx +++ b/packages/walletkit/src/evm/wallets/uxuyWallet/index.tsx @@ -1,56 +1,50 @@ import { uxuyWalletConfig } from '@/core/configs/uyuxWallet'; import { injected } from '../injected'; import { EvmWallet, InjectedEvmWalletOptions } from '../types'; -import { isTMA } from '@/core/base/utils/mobile'; export function uxuyWallet(props: InjectedEvmWalletOptions = {}): EvmWallet { const { connectorOptions, ...restProps } = props; + const getProvider = async () => { + if (typeof window === 'undefined') return; + + try { + const { WalletTgSdk } = (await import('@uxuycom/web3-tg-sdk')).default; + const { ethereum } = new WalletTgSdk({ + metaData: { + hostname: window.location.hostname, + }, + }); + + return ethereum as any; + } catch (err) { + console.error(err); + } + }; + return { ...uxuyWalletConfig, id: 'uxuyWallet', walletType: 'evm', - showQRCode: false, - platforms: ['tg-android', 'tg-ios', 'tg-pc'], - isInstalled() { - return isTMA(); - }, - getDeepLink() { - return undefined; - }, - getUri(uri) { - return undefined; - }, - getCreateConnectorFn() { - return injected({ - shimDisconnect: true, - target: { - id: uxuyWallet().id, - name: uxuyWallet().name, - async provider() { - return await getProvider(); - }, + behaviors: [ + { + platforms: ['tg-android', 'tg-ios', 'tg-pc'], + connectType: 'default', + getCreateConnectorFn() { + return injected({ + shimDisconnect: true, + target: { + id: uxuyWallet().id, + name: uxuyWallet().name, + async provider() { + return await getProvider(); + }, + }, + ...connectorOptions, + }); }, - ...connectorOptions, - }); - }, + }, + ], ...restProps, }; } - -async function getProvider() { - if (typeof window === 'undefined') return; - - try { - const { WalletTgSdk } = (await import('@uxuycom/web3-tg-sdk')).default; - const { ethereum } = new WalletTgSdk({ - metaData: { - hostname: window.location.hostname, - }, - }); - - return ethereum as any; - } catch (err) { - console.error(err); - } -} diff --git a/packages/walletkit/src/evm/wallets/walletConnect/index.tsx b/packages/walletkit/src/evm/wallets/walletConnect/index.tsx index 4dd58e5a..2fc983a2 100644 --- a/packages/walletkit/src/evm/wallets/walletConnect/index.tsx +++ b/packages/walletkit/src/evm/wallets/walletConnect/index.tsx @@ -14,49 +14,55 @@ export function walletConnect(props: WalletConnectOptions = {}): EvmWallet { ...walletConnectConfig, id: 'walletConnect', walletType: 'evm', - showQRCode: !connectorOptions?.showQrModal, - platforms: ['tg-android', 'tg-ios', 'tg-pc', 'browser-android', 'browser-ios', 'browser-pc'], - isInstalled() { - return true; - }, - getDeepLink() { - return undefined; - }, - getUri(uri) { - return uri; - }, - getCreateConnectorFn() { - const { walletConnectProjectId, metadata } = getEvmGlobalData(); + behaviors: [ + { + platforms: [ + 'tg-android', + 'tg-ios', + 'tg-pc', + 'browser-android', + 'browser-ios', + 'browser-pc', + ], + connectType: 'walletConnect', + getUri(uri) { + return uri; + }, + getCreateConnectorFn() { + const { walletConnectProjectId, metadata } = getEvmGlobalData(); - const hasAllAppData = metadata?.name && metadata.icon && metadata.description && metadata.url; + const hasAllAppData = + metadata?.name && metadata.icon && metadata.description && metadata.url; - if (!walletConnectProjectId) { - throw new Error('walletConnectProjectId is required.'); - } + if (!walletConnectProjectId) { + throw new Error('walletConnectProjectId is required.'); + } - return wagmiWalletConnect({ - // https://github.com/WalletConnect/walletconnect-monorepo/issues/2830 - relayUrl: 'wss://relay.walletconnect.org', - projectId: walletConnectProjectId, - metadata: hasAllAppData - ? { - name: metadata.name, - description: metadata.description!, - url: metadata.url!, - icons: [metadata.icon!], - } - : undefined, - qrModalOptions: { - explorerRecommendedWalletIds: [ - '8a0ee50d1f22f6651afcae7eb4253e52a3310b90af5daef78a8c4929a9bb99d4', - 'c57ca95b47569778a828d19178114f4db188b89b763c899ba0be274e97267d96', - '4622a2b2d6af1c9844944291e5e7351a6aa24cd7b23099efac1b2fd875da31a0', - ], + return wagmiWalletConnect({ + // https://github.com/WalletConnect/walletconnect-monorepo/issues/2830 + relayUrl: 'wss://relay.walletconnect.org', + projectId: walletConnectProjectId, + metadata: hasAllAppData + ? { + name: metadata.name, + description: metadata.description!, + url: metadata.url!, + icons: [metadata.icon!], + } + : undefined, + qrModalOptions: { + explorerRecommendedWalletIds: [ + '8a0ee50d1f22f6651afcae7eb4253e52a3310b90af5daef78a8c4929a9bb99d4', + 'c57ca95b47569778a828d19178114f4db188b89b763c899ba0be274e97267d96', + '4622a2b2d6af1c9844944291e5e7351a6aa24cd7b23099efac1b2fd875da31a0', + ], + }, + ...connectorOptions, + showQrModal: true, + }); }, - ...connectorOptions, - showQrModal: true, - }); - }, + }, + ], ...restProps, }; } diff --git a/packages/walletkit/src/solana/components/SetSolanaWalletClickRef/index.tsx b/packages/walletkit/src/solana/components/SetSolanaWalletClickRef/index.tsx index fc6b1b75..5105e330 100644 --- a/packages/walletkit/src/solana/components/SetSolanaWalletClickRef/index.tsx +++ b/packages/walletkit/src/solana/components/SetSolanaWalletClickRef/index.tsx @@ -5,6 +5,7 @@ import { useRouter } from '@/core/providers/RouteProvider/context'; import { useWalletKit } from '@/core/providers/WalletKitProvider/context'; import { openLink } from '@/core/utils/common'; import { useSolanaConnect } from '@/solana/hooks/useSolanaConnect'; +import { getSolanaWalletPlatformBehavior } from '@/solana/utils/getSolanaWalletPlatformBehavior'; import { SolanaWallet } from '@/solana/wallets'; import { useWallet } from '@solana/wallet-adapter-react'; import { useRef } from 'react'; @@ -27,12 +28,13 @@ export function SetSolanaWalletClickRef(props: SetSolanaWalletClickRefProps) { clickRef.current = (walletId: string, e: React.MouseEvent) => { const wallet = solanaConfig!.wallets.find((item) => item.id === walletId)! as SolanaWallet; + const behavior = getSolanaWalletPlatformBehavior(wallet); const pass = options.onClickWallet?.(wallet, e); if (pass === false) return; log('[ClickWallet]', `wallet:`, wallet); - log('[ClickWallet]', `installed:`, wallet.isInstalled()); + log('[ClickWallet]', `installed:`, behavior?.isInstalled?.()); const jumpTo = (viewRoute: ViewRoutes) => { setSelectedWallet(wallet); @@ -46,28 +48,26 @@ export function SetSolanaWalletClickRef(props: SetSolanaWalletClickRefProps) { } }; - const jumpToConnectingView = () => { - jumpTo(ViewRoutes.SOLANA_CONNECTING); - }; - disconnect(); clearTimeout(timerRef.current); timerRef.current = setTimeout(() => { - if (isMobile()) { - const deeplink = wallet.getDeepLink(); + if (behavior?.connectType === 'default') { + if (isMobile()) { + const appLink = behavior.getAppLink?.(); - if (wallet.isInstalled()) { - jumpToConnectingView(); - } else if (deeplink) { - openLink(deeplink); + if (behavior.isInstalled?.()) { + jumpTo(ViewRoutes.SOLANA_CONNECTING); + } else if (appLink) { + openLink(appLink); + } else { + connect({ + adapterName: wallet.adapterName, + }); + } } else { - connect({ - adapterName: wallet.adapterName, - }); + jumpTo(ViewRoutes.SOLANA_CONNECTING); } - } else { - jumpToConnectingView(); } }, 300); }; diff --git a/packages/walletkit/src/solana/components/SolanaConnectingView/index.tsx b/packages/walletkit/src/solana/components/SolanaConnectingView/index.tsx index 5528641c..9474b7a0 100644 --- a/packages/walletkit/src/solana/components/SolanaConnectingView/index.tsx +++ b/packages/walletkit/src/solana/components/SolanaConnectingView/index.tsx @@ -3,18 +3,23 @@ import { TemplateConnectingView } from '@/core/modals/ConnectModal/TemplateConne import { useWalletKit } from '@/core/providers/WalletKitProvider/context'; import { EventEmitter } from '@/core/utils/eventEmitter'; import { useSolanaConnect } from '@/solana/hooks/useSolanaConnect'; +import { getSolanaWalletPlatformBehavior } from '@/solana/utils/getSolanaWalletPlatformBehavior'; import { solanaCommonErrorHandler } from '@/solana/utils/solanaCommonErrorHandler'; import { SolanaWallet } from '@/solana/wallets'; import { useWallet, WalletProviderProps } from '@solana/wallet-adapter-react'; -import { useCallback, useEffect, useState } from 'react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; type WalletError = Parameters['onError']>[0]; export function SolanaConnectingView() { const { log, selectedWallet, options } = useWalletKit(); + const behavior = useMemo(() => { + return getSolanaWalletPlatformBehavior(selectedWallet as SolanaWallet); + }, [selectedWallet]); + const [status, setStatus] = useState( - selectedWallet.isInstalled() ? CONNECT_STATUS.CONNECTING : CONNECT_STATUS.UNAVAILABLE, + behavior?.isInstalled?.() ? CONNECT_STATUS.CONNECTING : CONNECT_STATUS.UNAVAILABLE, ); const { isConnected, connect } = useSolanaConnect(); @@ -50,13 +55,13 @@ export function SolanaConnectingView() { }, [options.onError, log]); const runConnect = useCallback(async () => { - if (!selectedWallet.isInstalled()) return; + if (!behavior?.isInstalled?.()) return; setStatus(CONNECT_STATUS.CONNECTING); connect({ adapterName: (selectedWallet as SolanaWallet).adapterName, }); - }, [connect, selectedWallet]); + }, [behavior, connect, selectedWallet]); return ( ; export function defaultSolanaConfig(params: CustomizedSolanaConfig) { const { autoConnect = false, - metadata = { name: 'WalletKit' }, - walletConnectProjectId, + // metadata = { name: 'WalletKit' }, + // walletConnectProjectId, rpcUrl, wallets, } = params; setSolanaGlobalData({ - metadata, - walletConnectProjectId, - walletConnectModalIsOpen: false, + // metadata, + // walletConnectProjectId, + // walletConnectModalIsOpen: false, rpcUrl, }); - const adapters = wallets.map((w) => w.getAdapter()) as any; + const adapters = wallets + .map((w) => { + const behavior = getSolanaWalletPlatformBehavior(w); + return behavior?.getAdapter?.(); + }) + .filter((e) => !!e); return { autoConnect, - metadata, - walletConnectProjectId, + // metadata, + // walletConnectProjectId, adapters, rpcUrl, wallets, diff --git a/packages/walletkit/src/solana/utils/getSolanaWalletPlatformBehavior.ts b/packages/walletkit/src/solana/utils/getSolanaWalletPlatformBehavior.ts new file mode 100644 index 00000000..e96ce20c --- /dev/null +++ b/packages/walletkit/src/solana/utils/getSolanaWalletPlatformBehavior.ts @@ -0,0 +1,8 @@ +import { getPlatform } from '@/core/utils/common'; +import { SolanaWallet } from '../wallets'; + +export function getSolanaWalletPlatformBehavior(wallet: SolanaWallet) { + const platform = getPlatform(); + const behavior = wallet.behaviors.find((e) => e.platforms.includes(platform)); + return behavior; +} diff --git a/packages/walletkit/src/solana/wallets/phantomWallet/index.tsx b/packages/walletkit/src/solana/wallets/phantomWallet/index.tsx index 393605a8..0a9ea9d7 100644 --- a/packages/walletkit/src/solana/wallets/phantomWallet/index.tsx +++ b/packages/walletkit/src/solana/wallets/phantomWallet/index.tsx @@ -15,21 +15,25 @@ export function phantomWallet(props: PhantomOptions = {}): SolanaWallet { id: 'solana:phantom', walletType: 'solana', adapterName: 'Phantom', - showQRCode: false, - platforms: ['browser-android', 'browser-ios', 'browser-pc'], - isInstalled() { - return hasSolanaInjectedProvider('isPhantom'); - }, - getDeepLink() { - const encodedUrl = encodeURIComponent(window.location.href); - const encodeDapp = encodeURIComponent(window.origin); - return `https://phantom.app/ul/browse/${encodedUrl}?ref=${encodeDapp}`; - }, - getAdapter() { - return new PhantomWalletAdapter({ - ...adapterOptions, - }); - }, + behaviors: [ + { + platforms: ['browser-android', 'browser-ios', 'browser-pc'], + connectType: 'default', + isInstalled() { + return hasSolanaInjectedProvider('isPhantom'); + }, + getAppLink() { + const encodedUrl = encodeURIComponent(window.location.href); + const encodeDapp = encodeURIComponent(window.origin); + return `https://phantom.app/ul/browse/${encodedUrl}?ref=${encodeDapp}`; + }, + getAdapter() { + return new PhantomWalletAdapter({ + ...adapterOptions, + }); + }, + }, + ], ...restProps, }; } diff --git a/packages/walletkit/src/solana/wallets/trustWallet/index.tsx b/packages/walletkit/src/solana/wallets/trustWallet/index.tsx index 7c1a4baa..39d01d7a 100644 --- a/packages/walletkit/src/solana/wallets/trustWallet/index.tsx +++ b/packages/walletkit/src/solana/wallets/trustWallet/index.tsx @@ -15,26 +15,30 @@ export function trustWallet(props: TrustWalletOptions = {}): SolanaWallet { id: 'solana:trust', walletType: 'solana', adapterName: 'Trust', - showQRCode: false, - platforms: ['browser-android', 'browser-ios', 'browser-pc'], - getDeepLink() { - const encodedUrl = encodeURIComponent(window.location.href); - return `https://link.trustwallet.com/open_url?coin_id=60&url=${encodedUrl}`; - }, - isInstalled() { - if (typeof window === 'undefined') return false; + behaviors: [ + { + platforms: ['browser-android', 'browser-ios', 'browser-pc'], + connectType: 'default', + isInstalled() { + if (typeof window === 'undefined') return false; - return ( - hasSolanaInjectedProvider('isTrust') || - window?.trustwallet?.solana?.isTrust || - window?.trustWallet?.solana?.isTrust - ); - }, - getAdapter() { - return new TrustWalletAdapter({ - ...adapterOptions, - }); - }, + return ( + hasSolanaInjectedProvider('isTrust') || + window?.trustwallet?.solana?.isTrust || + window?.trustWallet?.solana?.isTrust + ); + }, + getAppLink() { + const encodedUrl = encodeURIComponent(window.location.href); + return `https://link.trustwallet.com/open_url?coin_id=60&url=${encodedUrl}`; + }, + getAdapter() { + return new TrustWalletAdapter({ + ...adapterOptions, + }); + }, + }, + ], ...restProps, }; } diff --git a/packages/walletkit/src/solana/wallets/types.ts b/packages/walletkit/src/solana/wallets/types.ts index 27303668..fc461e64 100644 --- a/packages/walletkit/src/solana/wallets/types.ts +++ b/packages/walletkit/src/solana/wallets/types.ts @@ -1,12 +1,14 @@ -import { BaseWallet } from '@/core/configs/types'; +import { BaseBehavior, BaseWallet } from '@/core/configs/types'; import { WalletProviderProps } from '@solana/wallet-adapter-react'; export type Adapter = WalletProviderProps['wallets'][0]; -export interface SolanaWallet extends BaseWallet { +export interface SolanaWalletBehavior extends BaseBehavior { + getAdapter?: () => Adapter; +} + +export interface SolanaWallet extends BaseWallet { adapterName: string; - getDeepLink: () => string | undefined; - getAdapter: () => Adapter; } export interface InjectedSolanaWalletOptions extends Partial { diff --git a/packages/walletkit/src/solana/wallets/walletConnect/index.tsx b/packages/walletkit/src/solana/wallets/walletConnect/index.tsx deleted file mode 100644 index d341af1f..00000000 --- a/packages/walletkit/src/solana/wallets/walletConnect/index.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { - WalletConnectWalletAdapter, - WalletConnectWalletAdapterConfig, -} from '@solana/wallet-adapter-wallets'; -import { SolanaWallet } from '../types'; -import { walletConnectConfig } from '@/core/configs/walletConnect'; -import { getSolanaGlobalData } from '@/solana/globalData'; - -interface WalletConnectOptions extends Partial { - adapterOptions?: Partial; -} - -export function walletConnect(props: WalletConnectOptions = {}): SolanaWallet { - const { adapterOptions, ...restProps } = props; - - return { - ...walletConnectConfig, - id: 'solana:walletConnect', - walletType: 'solana', - adapterName: 'WalletConnect', - showQRCode: true, - platforms: ['tg-android', 'tg-ios', 'tg-pc', 'browser-android', 'browser-ios', 'browser-pc'], - isInstalled() { - return false; - }, - getDeepLink() { - return undefined; - }, - getAdapter() { - const { walletConnectProjectId, metadata, rpcUrl } = getSolanaGlobalData(); - - const hasAllAppData = metadata?.name && metadata.icon && metadata.description && metadata.url; - - if (!walletConnectProjectId) { - throw new Error('walletConnectProjectId is required.'); - } - - return new WalletConnectWalletAdapter({ - network: rpcUrl as any, - options: { - // https://github.com/WalletConnect/walletconnect-monorepo/issues/2830 - relayUrl: 'wss://relay.walletconnect.org', - projectId: walletConnectProjectId, - metadata: hasAllAppData - ? { - name: metadata.name, - description: metadata.description!, - url: metadata.url!, - icons: [metadata.icon!], - } - : undefined, - ...adapterOptions, - }, - }); - }, - ...restProps, - }; -} - -export function isWalletConnect(id: string) { - return id === walletConnect().id; -} diff --git a/packages/walletkit/src/tron/components/SetTronWalletClickRef/index.tsx b/packages/walletkit/src/tron/components/SetTronWalletClickRef/index.tsx index 48cc81ed..07ee8799 100644 --- a/packages/walletkit/src/tron/components/SetTronWalletClickRef/index.tsx +++ b/packages/walletkit/src/tron/components/SetTronWalletClickRef/index.tsx @@ -4,6 +4,7 @@ import { ViewRoutes } from '@/core/providers/RouteProvider'; import { useRouter } from '@/core/providers/RouteProvider/context'; import { useWalletKit } from '@/core/providers/WalletKitProvider/context'; import { useTronConnect } from '@/tron/hooks/useTronConnect'; +import { getTronWalletPlatformBehavior } from '@/tron/utils/getTronWalletPlatformBehavior'; import { TronWallet } from '@/tron/wallets'; import { useWallet } from '@tronweb3/tronwallet-adapter-react-hooks'; import { useRef } from 'react'; @@ -26,12 +27,13 @@ export function SetTronWalletClickRef(props: SetTronWalletClickRefProps) { clickRef.current = (walletId: string, e: React.MouseEvent) => { const wallet = tronConfig!.wallets.find((item) => item.id === walletId)! as TronWallet; + const behavior = getTronWalletPlatformBehavior(wallet); const pass = options.onClickWallet?.(wallet, e); if (pass === false) return; log('[ClickWallet]', `wallet:`, wallet); - log('[ClickWallet]', `installed:`, wallet.isInstalled()); + log('[ClickWallet]', `installed:`, behavior?.isInstalled?.()); const jumpTo = (viewRoute: ViewRoutes) => { setSelectedWallet(wallet); @@ -45,24 +47,22 @@ export function SetTronWalletClickRef(props: SetTronWalletClickRefProps) { } }; - const jumpToConnectingView = () => { - jumpTo(ViewRoutes.TRON_CONNECTING); - }; - disconnect(); clearTimeout(timerRef.current); timerRef.current = setTimeout(() => { - if (isMobile()) { - if (wallet.isInstalled()) { - jumpToConnectingView(); + if (behavior?.connectType === 'default') { + if (isMobile()) { + if (behavior?.isInstalled?.()) { + jumpTo(ViewRoutes.TRON_CONNECTING); + } else { + connect({ + adapterName: wallet.adapterName, + }); + } } else { - connect({ - adapterName: wallet.adapterName, - }); + jumpTo(ViewRoutes.TRON_CONNECTING); } - } else { - jumpToConnectingView(); } }, 300); }; diff --git a/packages/walletkit/src/tron/components/TronConnectingView/index.tsx b/packages/walletkit/src/tron/components/TronConnectingView/index.tsx index 0fc97b06..9f8e6e21 100644 --- a/packages/walletkit/src/tron/components/TronConnectingView/index.tsx +++ b/packages/walletkit/src/tron/components/TronConnectingView/index.tsx @@ -3,6 +3,7 @@ import { TemplateConnectingView } from '@/core/modals/ConnectModal/TemplateConne import { useWalletKit } from '@/core/providers/WalletKitProvider/context'; import { EventEmitter } from '@/core/utils/eventEmitter'; import { useTronConnect } from '@/tron/hooks/useTronConnect'; +import { getTronWalletPlatformBehavior } from '@/tron/utils/getTronWalletPlatformBehavior'; import { tronCommonErrorHandler } from '@/tron/utils/tronCommonErrorHandler'; import { TronWallet } from '@/tron/wallets'; import { useWallet, WalletProviderProps } from '@tronweb3/tronwallet-adapter-react-hooks'; @@ -13,8 +14,10 @@ type WalletError = Parameters['onError']>[0]; export function TronConnectingView() { const { log, selectedWallet, options, tronConfig } = useWalletKit(); + const behavior = getTronWalletPlatformBehavior(selectedWallet as TronWallet); + const [status, setStatus] = useState( - selectedWallet.isInstalled() ? CONNECT_STATUS.CONNECTING : CONNECT_STATUS.UNAVAILABLE, + behavior?.isInstalled?.() ? CONNECT_STATUS.CONNECTING : CONNECT_STATUS.UNAVAILABLE, ); const { connect, isConnected } = useTronConnect(); @@ -47,14 +50,14 @@ export function TronConnectingView() { }, [options.onError, log]); const runConnect = useCallback(async () => { - if (!selectedWallet.isInstalled()) return; + if (!behavior?.isInstalled?.()) return; setStatus(CONNECT_STATUS.CONNECTING); connect({ adapterName: (selectedWallet as TronWallet).adapterName, chainId: tronConfig?.initialChainId, }); - }, [connect, selectedWallet, tronConfig?.initialChainId]); + }, [behavior, connect, selectedWallet, tronConfig?.initialChainId]); return ( w.getAdapter()) as any; + const adapters = wallets + .map((w) => { + const behavior = getTronWalletPlatformBehavior(w); + return behavior?.getAdapter?.(); + }) + .filter((e) => !!e); return { autoConnect, diff --git a/packages/walletkit/src/tron/utils/getTronWalletPlatformBehavior.ts b/packages/walletkit/src/tron/utils/getTronWalletPlatformBehavior.ts new file mode 100644 index 00000000..361a709e --- /dev/null +++ b/packages/walletkit/src/tron/utils/getTronWalletPlatformBehavior.ts @@ -0,0 +1,8 @@ +import { getPlatform } from '@/core/utils/common'; +import { TronWallet } from '../wallets'; + +export function getTronWalletPlatformBehavior(wallet: TronWallet) { + const platform = getPlatform(); + const behavior = wallet.behaviors.find((e) => e.platforms.includes(platform)); + return behavior; +} diff --git a/packages/walletkit/src/tron/wallets/tronLink/index.ts b/packages/walletkit/src/tron/wallets/tronLink/index.ts index 6aedba64..b0ce64df 100644 --- a/packages/walletkit/src/tron/wallets/tronLink/index.ts +++ b/packages/walletkit/src/tron/wallets/tronLink/index.ts @@ -15,18 +15,20 @@ export function tronLink(props: TronLinkOptions = {}): TronWallet { id: 'tron:tronLink', walletType: 'tron', adapterName: 'TronLink', - showQRCode: false, - platforms: ['browser-android', 'browser-ios', 'browser-pc'], - isInstalled() { - if (typeof window === 'undefined') return false; - - return hasTronInjectedProvider('isTronLink'); - }, - getAdapter() { - return new TronLinkAdapter({ - ...adapterOptions, - }); - }, + behaviors: [ + { + platforms: ['browser-android', 'browser-ios', 'browser-pc'], + connectType: 'default', + isInstalled() { + return hasTronInjectedProvider('isTronLink'); + }, + getAdapter() { + return new TronLinkAdapter({ + ...adapterOptions, + }); + }, + }, + ], ...restProps, }; } diff --git a/packages/walletkit/src/tron/wallets/types.ts b/packages/walletkit/src/tron/wallets/types.ts index 35044c7a..46246e1e 100644 --- a/packages/walletkit/src/tron/wallets/types.ts +++ b/packages/walletkit/src/tron/wallets/types.ts @@ -1,9 +1,12 @@ -import { BaseWallet } from '@/core/configs/types'; +import { BaseBehavior, BaseWallet } from '@/core/configs/types'; import { Adapter, BaseAdapterConfig } from '@tronweb3/tronwallet-abstract-adapter'; -export interface TronWallet extends BaseWallet { +export interface TronWalletBehavior extends BaseBehavior { + getAdapter?: () => Adapter; +} + +export interface TronWallet extends BaseWallet { adapterName: string; - getAdapter: () => Adapter; } export interface InjectedTronWalletOptions extends Partial { diff --git a/packages/walletkit/src/typings.d.ts b/packages/walletkit/src/typings.d.ts index ac3ced17..2a6a6925 100644 --- a/packages/walletkit/src/typings.d.ts +++ b/packages/walletkit/src/typings.d.ts @@ -18,3 +18,5 @@ type DeepPartial = T extends object : T; type SVGIconProps = React.SVGProps; + +type ValueOf = T[keyof T];