diff --git a/packages/web/config/generate-cosmos-kit-wallet-list.ts b/packages/web/config/generate-cosmos-kit-wallet-list.ts index 5a2ee99017..b22bc9a446 100644 --- a/packages/web/config/generate-cosmos-kit-wallet-list.ts +++ b/packages/web/config/generate-cosmos-kit-wallet-list.ts @@ -5,6 +5,7 @@ import path from "node:path"; import { cdcwalletExtensionInfo } from "@cosmos-kit/cdcwallet-extension"; import { Wallet as DefaultWallet } from "@cosmos-kit/core"; import { cosmostationExtensionInfo } from "@cosmos-kit/cosmostation-extension"; +import { imTokenWalletInfo } from "@cosmos-kit/imtoken-extension" import { keplrExtensionInfo } from "@cosmos-kit/keplr-extension"; import { keplrMobileInfo } from "@cosmos-kit/keplr-mobile"; import { leapExtensionInfo } from "@cosmos-kit/leap-extension"; @@ -38,6 +39,7 @@ const CosmosKitWalletList: Wallet[] = [ cosmostationExtensionInfo, stationExtensionInfo, cdcwalletExtensionInfo, + imTokenWalletInfo, ]; function isObject(value: any): value is Record { @@ -106,7 +108,7 @@ async function generateCosmosKitWalletList() { ).join(",")}} export const CosmosKitWalletList: Record = ${getStringifiedWallet( registryObject - )} + )} `; const prettierConfig = await prettier.resolveConfig("./"); diff --git a/packages/web/config/wallet-registry.ts b/packages/web/config/wallet-registry.ts index 316f5f4f59..e102a38e42 100644 --- a/packages/web/config/wallet-registry.ts +++ b/packages/web/config/wallet-registry.ts @@ -26,7 +26,7 @@ export const CosmosWalletRegistry: CosmosRegistryWallet[] = [ import("~/integrations/keplr-walletconnect").then( (m) => m.KeplrMobileWallet ), - supportsChain: async (chainId) => { + supportsChain: async (chainId: string) => { const keplrMobileAvailableChains: MainnetChainIds[] = [ "cosmoshub-4", "osmosis-1", @@ -54,9 +54,9 @@ export const CosmosWalletRegistry: CosmosRegistryWallet[] = [ "gitopia", "likecoin-mainnet-2", "akashnet-2", - ]; + ] - return keplrMobileAvailableChains.includes(chainId as MainnetChainIds); + return keplrMobileAvailableChains.includes(chainId as MainnetChainIds) }, stakeUrl: "https://wallet.keplr.app/chains/osmosis?tab=staking", governanceUrl: "https://wallet.keplr.app/chains/osmosis?tab=governance", @@ -78,7 +78,7 @@ export const CosmosWalletRegistry: CosmosRegistryWallet[] = [ logo: "/wallets/leap.svg", lazyInstall: () => import("@cosmos-kit/leap-mobile").then((m) => m.LeapMobileWallet), - supportsChain: async (chainId) => { + supportsChain: async (chainId: string) => { const leapMobileAvailableChains: MainnetChainIds[] = [ "agoric-3", "akashnet-2", @@ -146,8 +146,8 @@ export const CosmosWalletRegistry: CosmosRegistryWallet[] = [ "phoenix-1", "umee-1", "dimension_37-1", - ]; - return leapMobileAvailableChains.includes(chainId as MainnetChainIds); + ] + return leapMobileAvailableChains.includes(chainId as MainnetChainIds) }, stakeUrl: "https://cosmos.leapwallet.io/transact/stake/plain?chain=osmosis", @@ -162,27 +162,27 @@ export const CosmosWalletRegistry: CosmosRegistryWallet[] = [ (m) => m.OkxwalletExtensionWallet ), windowPropertyName: "okxwallet", - async supportsChain(chainId, retryCount = 0) { - if (typeof window === "undefined") return true; + async supportsChain(chainId: string, retryCount = 0) { + if (typeof window === "undefined") return true const okxWallet = (window as any)?.okxwallet?.keplr as { - getKey: (chainId: string) => Promise; - }; + getKey: (chainId: string) => Promise + } - if (!okxWallet) return true; + if (!okxWallet) return true try { - await okxWallet.getKey(chainId); - return true; + await okxWallet.getKey(chainId) + return true } catch (e) { - const error = e as { code: number; message: string }; + const error = e as { code: number; message: string } // Check for chain not supported error if ( error.code === -32603 && error.message.includes("There is no chain info") ) { - return false; + return false } // Retry if the wallet is already processing @@ -199,26 +199,26 @@ export const CosmosWalletRegistry: CosmosRegistryWallet[] = [ */ await new Promise((resolve) => setTimeout(resolve, Math.pow(2, retryCount) * 100) - ); + ) // @ts-ignore - return this.supportsChain(chainId, retryCount + 1); + return this.supportsChain(chainId, retryCount + 1) } - return false; + return false } }, matchError: (error) => { - if (typeof error !== "string") return error; + if (typeof error !== "string") return error if ( error.includes( "Already processing wallet_requestIdentities. Please wait." ) ) { - return new WalletConnectionInProgressError(); + return new WalletConnectionInProgressError() } - return error; + return error }, signOptions: { preferNoSetFee: true, @@ -262,13 +262,13 @@ export const CosmosWalletRegistry: CosmosRegistryWallet[] = [ (m) => m.CdcwalletExtensionWallet ), mobileDisabled: false, - async supportsChain(chainId) { + async supportsChain(chainId: string) { const cdcAvailableChains: MainnetChainIds[] = [ "cosmoshub-4", "osmosis-1", "crypto-org-chain-mainnet-1", - ]; - return cdcAvailableChains.includes(chainId as MainnetChainIds); + ] + return cdcAvailableChains.includes(chainId as MainnetChainIds) }, windowPropertyName: "cdc_wallet", stakeUrl: "https://crypto.com/staking", @@ -281,19 +281,19 @@ export const CosmosWalletRegistry: CosmosRegistryWallet[] = [ lazyInstall: () => import("@cosmos-kit/xdefi-extension").then((m) => m.XDEFIExtensionWallet), windowPropertyName: "xfi", - async supportsChain(chainId) { - if (typeof window === "undefined") return true; + async supportsChain(chainId: string) { + if (typeof window === "undefined") return true const xfiWallet = (window as any)?.xfi?.keplr as { - getKey: (chainId: string) => Promise; - }; + getKey: (chainId: string) => Promise + } - if (!xfiWallet) return true; + if (!xfiWallet) return true return xfiWallet .getKey(chainId) .then(() => true) - .catch(() => false); + .catch(() => false) }, features: [], }, @@ -318,21 +318,34 @@ export const CosmosWalletRegistry: CosmosRegistryWallet[] = [ (m) => m.StationExtensionWallet ), windowPropertyName: "station", - supportsChain: async (chainId) => { - if (typeof window === "undefined") return true; + supportsChain: async (chainId: string) => { + if (typeof window === "undefined") return true const stationWallet = (window as any)?.station?.keplr as { - getChainInfosWithoutEndpoints: () => Promise<{ chainId: string }[]>; - }; + getChainInfosWithoutEndpoints: () => Promise<{ chainId: string }[]> + } - if (!stationWallet) return true; + if (!stationWallet) return true - const chainInfos = await stationWallet.getChainInfosWithoutEndpoints(); - return chainInfos.some((info) => info.chainId === chainId); + const chainInfos = await stationWallet.getChainInfosWithoutEndpoints() + return chainInfos.some((info) => info.chainId === chainId) }, signOptions: { preferNoSetFee: true, }, features: [], }, -]; + { + ...CosmosKitWalletList["imtoken-extension"], + logo: "/wallets/imtoken.svg", + mobileDisabled: false, + windowPropertyName: "cosmos", + features: [], + lazyInstall: () => + import("@cosmos-kit/imtoken-extension").then((m) => m.IMTokenWallet), + async supportsChain(chainId: string) { + const cdcAvailableChains: MainnetChainIds[] = ["cosmoshub-4", "osmosis-1"] + return cdcAvailableChains.includes(chainId as MainnetChainIds) + }, + }, +] diff --git a/packages/web/modals/wallet-select/use-selectable-wallets.ts b/packages/web/modals/wallet-select/use-selectable-wallets.ts index f311b80bdc..6abf51ba6b 100644 --- a/packages/web/modals/wallet-select/use-selectable-wallets.ts +++ b/packages/web/modals/wallet-select/use-selectable-wallets.ts @@ -79,11 +79,11 @@ export const useSelectableWallets = ({ * Therefore, we should only show that compatible extension wallet. * */ if (acc.length > 0 && acc[0].name.endsWith("-extension")) { - return acc; + return acc } - const _window = window as Record; - const mobileWebModeName = "mobile-web"; + const _window = window as Record + const mobileWebModeName = "mobile-web" /** * If on mobile and `leap` is in `window`, it means that the user enters @@ -99,7 +99,23 @@ export const useSelectableWallets = ({ (wallet) => wallet.name === AvailableCosmosWallets.CryptocomWallet ) - .map((wallet) => ({ ...wallet, mobileDisabled: false })); + .map((wallet) => ({ ...wallet, mobileDisabled: false })) + } + + /** + * If on mobile and `imToken` is in `window`, it means that the user enters + * the frontend from imToken's app in app browser. So, there is no need + * to use wallet connect, as it resembles the extension's usage. + */ + if ( + _window?.imToken && + _window?.cosmos?.mode === mobileWebModeName + ) { + return array + .filter( + (wallet) => wallet.name === AvailableCosmosWallets.imToken + ) + .map((wallet) => ({ ...wallet, mobileDisabled: false })) } /** @@ -110,7 +126,7 @@ export const useSelectableWallets = ({ if (_window?.leap && _window?.leap?.mode === mobileWebModeName) { return array .filter((wallet) => wallet.name === AvailableCosmosWallets.Leap) - .map((wallet) => ({ ...wallet, mobileDisabled: false })); + .map((wallet) => ({ ...wallet, mobileDisabled: false })) } /** @@ -123,13 +139,13 @@ export const useSelectableWallets = ({ .filter( (wallet) => wallet.name === AvailableCosmosWallets.Keplr ) - .map((wallet) => ({ ...wallet, mobileDisabled: false })); + .map((wallet) => ({ ...wallet, mobileDisabled: false })) } /** * If user is in a normal mobile browser, show only wallet connect */ - return wallet.name.endsWith("mobile") ? [...acc, wallet] : acc; + return wallet.name.endsWith("mobile") ? [...acc, wallet] : acc } return [...acc, wallet]; diff --git a/packages/web/package.json b/packages/web/package.json index 09875ced4a..f4adbc86f4 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -38,6 +38,7 @@ "@cosmos-kit/keplr": "^2.12.2", "@cosmos-kit/leap": "^2.12.2", "@cosmos-kit/okxwallet": "^2.9.2", + "@cosmos-kit/imtoken": "^1.0.0", "@cosmos-kit/station": "^2.10.2", "@cosmos-kit/trust": "^2.11.2", "@cosmos-kit/xdefi": "^2.10.2", diff --git a/packages/web/public/wallets/imtoken.svg b/packages/web/public/wallets/imtoken.svg new file mode 100644 index 0000000000..c974f392e0 --- /dev/null +++ b/packages/web/public/wallets/imtoken.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + +