Skip to content

Commit

Permalink
[react, wallets] Add imToken Wallet (#2497)
Browse files Browse the repository at this point in the history
Signed-off-by: Mako Shan <imakoshan@gmail.com>
Signed-off-by: Jonas Daniels <jonas.daniels@outlook.com>
Co-authored-by: xwartz <stddup@gmail.com>
Co-authored-by: Jonas Daniels <jonas.daniels@outlook.com>
  • Loading branch information
3 people committed Mar 20, 2024
1 parent 9c884e2 commit 79c9e13
Show file tree
Hide file tree
Showing 19 changed files with 317 additions and 2 deletions.
7 changes: 7 additions & 0 deletions .changeset/tall-moose-add-imToken.md
@@ -0,0 +1,7 @@
---
"@thirdweb-dev/wallets": patch
"@thirdweb-dev/react": patch
"@thirdweb-dev/react-core": patch
---

Add imToken Wallet
4 changes: 3 additions & 1 deletion packages/react-core/src/core/hooks/wallet-hooks.ts
Expand Up @@ -8,6 +8,7 @@ import type {
CryptoDefiWallet,
EmbeddedWallet,
FrameWallet,
ImTokenWallet,
LocalWallet,
MagicEdenWallet,
MagicLink,
Expand Down Expand Up @@ -41,6 +42,7 @@ export type WalletIdToWalletTypeMap = {
rainbowWallet: RainbowWallet;
blocto: BloctoWallet;
frame: FrameWallet;
imToken: ImTokenWallet;
localWallet: LocalWallet;
magicLink: MagicLink;
paper: PaperWallet;
Expand All @@ -57,7 +59,7 @@ export type WalletIdToWalletTypeMap = {
cryptoDefiWallet: CryptoDefiWallet;
rabby: RabbyWallet;
xdefi: XDEFIWallet;
magicEden: MagicEdenWallet
magicEden: MagicEdenWallet;
};

/**
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/evm/index.ts
Expand Up @@ -111,4 +111,5 @@ export {
CryptoDefiWallet,
RabbyWallet,
Coin98Wallet,
ImTokenWallet,
} from "@thirdweb-dev/wallets";
1 change: 1 addition & 0 deletions packages/react/src/evm/locales/en.ts
Expand Up @@ -171,6 +171,7 @@ export function enDefault(): ThirdwebLocale {
xdefiWallet: extensionAndQRScanScreens("XDEFI"),
rainbowWallet: extensionAndQRScanScreens("Rainbow"),
trustWallet: extensionAndQRScanScreens("Trust"),
imTokenWallet: extensionAndQRScanScreens("imToken"),
zerionWallet: extensionAndQRScanScreens("Zerion"),
coreWallet: extensionAndQRScanScreens("Core"),
oneKeyWallet: extensionAndQRScanScreens("OneKey"),
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/evm/locales/es.ts
Expand Up @@ -176,6 +176,7 @@ export function esDefault(): ThirdwebLocale {
xdefiWallet: extensionAndQRScanScreens("XDEFI"),
rainbowWallet: extensionAndQRScanScreens("Rainbow"),
trustWallet: extensionAndQRScanScreens("Trust"),
imTokenWallet: extensionAndQRScanScreens("imToken"),
zerionWallet: extensionAndQRScanScreens("Zerion"),
oneKeyWallet: extensionAndQRScanScreens("OneKey"),
cryptoDefiWallet: extensionAndQRScanScreens("Crypto Defi"),
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/evm/locales/ja.ts
Expand Up @@ -176,6 +176,7 @@ export function jaDefault(): ThirdwebLocale {
xdefiWallet: extensionAndQRScanScreens("XDEFI"),
rainbowWallet: extensionAndQRScanScreens("Rainbow"),
trustWallet: extensionAndQRScanScreens("Trust"),
imTokenWallet: extensionAndQRScanScreens("imToken"),
zerionWallet: extensionAndQRScanScreens("Zerion"),
oneKeyWallet: extensionAndQRScanScreens("OneKey"),
cryptoDefiWallet: extensionAndQRScanScreens("Crypto Defi"),
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/evm/locales/tl.ts
Expand Up @@ -176,6 +176,7 @@ export function tlDefault(): ThirdwebLocale {
xdefiWallet: extensionAndQRScanScreens("XDEFI"),
rainbowWallet: extensionAndQRScanScreens("Rainbow"),
trustWallet: extensionAndQRScanScreens("Trust"),
imTokenWallet: extensionAndQRScanScreens("imToken"),
zerionWallet: extensionAndQRScanScreens("Zerion"),
coreWallet: extensionAndQRScanScreens("Core"),
oneKeyWallet: extensionAndQRScanScreens("OneKey"),
Expand Down
3 changes: 2 additions & 1 deletion packages/react/src/evm/locales/types.ts
Expand Up @@ -183,6 +183,7 @@ export type ThirdwebLocale = {
getStartedScreen: { instruction: string };
scanScreen: { instruction: string };
};
trustWallet: ExtensionAndQRScreensLocale;
localWallet: {
confirmPasswordLabel: string;
createScreen: {
Expand Down Expand Up @@ -302,7 +303,7 @@ export type ThirdwebLocale = {
title: string;
};
};
trustWallet: ExtensionAndQRScreensLocale;
imTokenWallet: ExtensionAndQRScreensLocale;
walletConnect: { scanInstruction: string };
zerionWallet: ExtensionAndQRScreensLocale;
};
Expand Down
5 changes: 5 additions & 0 deletions packages/react/src/index.ts
Expand Up @@ -107,6 +107,11 @@ export {
type Coin98WalletConfigOptions,
} from "./wallet/wallets/coin98/coin98Wallet";

export {
imTokenWallet,
type ImTokenWalletConfigOptions,
} from "./wallet/wallets/imtoken/imTokenWallet";

// theming
export { darkTheme, lightTheme } from "./design-system/index";
export type { Theme, ThemeOverrides } from "./design-system/index";
Expand Down
3 changes: 3 additions & 0 deletions packages/react/src/wallet/hooks/useInstalledWallets.ts
Expand Up @@ -12,19 +12,22 @@ export function useInstalledWallets() {
let isCoinbaseWalletInstalled = false;
let isZerionWalletInstalled = false;
let isTrustWalletInstalled = false;
let isImTokenInstalled = false;

const window_: Window | undefined = globalThis?.window;
if (assertWindowEthereum(window_)) {
isMetamaskInstalled = !!getInjectedMetamaskProvider();
isCoinbaseWalletInstalled = !!getInjectedCoinbaseProvider();
isZerionWalletInstalled = !!window_.ethereum?.isZerion;
isTrustWalletInstalled = !!window_.ethereum?.isTrust;
isImTokenInstalled = !!window_.ethereum?.isToken;
}

return {
metamask: isMetamaskInstalled,
coinbaseWallet: isCoinbaseWalletInstalled,
trustWallet: isTrustWalletInstalled,
zerionWallet: isZerionWalletInstalled,
imtokenWallet: isImTokenInstalled,
};
}
73 changes: 73 additions & 0 deletions packages/react/src/wallet/wallets/imtoken/imTokenWallet.tsx
@@ -0,0 +1,73 @@
import type {
WalletOptions,
WalletConfig,
ConnectUIProps,
} from "@thirdweb-dev/react-core";
import { ImTokenWallet, assertWindowEthereum } from "@thirdweb-dev/wallets";
import { useTWLocale } from "../../../evm/providers/locale-provider";
import { ExtensionOrWCConnectionUI } from "../_common/ExtensionORWCConnectionUI";

const imTokenWalletUris = {
ios: "https://itunes.apple.com/us/app/imtoken2/id1384798940",
android: "https://play.google.com/store/apps/details?id=im.token.app",
};

export type ImTokenWalletConfigOptions = {
projectId?: string;
recommended?: boolean;
};

export const imTokenWallet = (
options?: ImTokenWalletConfigOptions,
): WalletConfig<ImTokenWallet> => {
return {
id: ImTokenWallet.id,
recommended: options?.recommended,
meta: {
...ImTokenWallet.meta,
iconURL:
"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iODAiIGhlaWdodD0iODAiIHZpZXdCb3g9IjAgMCA4MCA4MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzIyMl80NzgzKSI+CjxtYXNrIGlkPSJtYXNrMF8yMjJfNDc4MyIgc3R5bGU9Im1hc2stdHlwZTpsdW1pbmFuY2UiIG1hc2tVbml0cz0idXNlclNwYWNlT25Vc2UiIHg9IjAiIHk9IjAiIHdpZHRoPSI4MCIgaGVpZ2h0PSI4MCI+CjxwYXRoIGQ9Ik03OS44OTQ4IDBIMC4wNTA3ODEyVjgwSDc5Ljg5NDhWMFoiIGZpbGw9IndoaXRlIi8+CjwvbWFzaz4KPGcgbWFzaz0idXJsKCNtYXNrMF8yMjJfNDc4MykiPgo8cGF0aCBkPSJNNjIuMDI3NSAwSDE4LjA1MDlDOC4xNDYzOSAwIDAuMTE3MTg4IDguMDQ0ODggMC4xMTcxODggMTcuOTY4OFY2Mi4wMzEyQzAuMTE3MTg4IDcxLjk1NTEgOC4xNDYzOSA4MCAxOC4wNTA5IDgwSDYyLjAyNzVDNzEuOTMyIDgwIDc5Ljk2MTIgNzEuOTU1MSA3OS45NjEyIDYyLjAzMTJWMTcuOTY4OEM3OS45NjEyIDguMDQ0ODggNzEuOTMyIDAgNjIuMDI3NSAwWiIgZmlsbD0idXJsKCNwYWludDBfbGluZWFyXzIyMl80NzgzKSIvPgo8cGF0aCBkPSJNNjUuMDk4MSAyNC43MzNDNjYuNzU4NiA0Ny4yNjY3IDUyLjMwMjEgNTcuOTE3MiAzOS4zNDIzIDU5LjA1M0MyNy4yOTM1IDYwLjEwODcgMTUuOTUyIDUyLjY5MDggMTQuOTU3MSA0MS4yOTM2QzE0LjEzNjMgMzEuODc3NiAxOS45NDQ1IDI3Ljg2ODkgMjQuNTA4IDI3LjQ2OTRDMjkuMjAxNSAyNy4wNTcgMzMuMTQ1OCAzMC4zMDAxIDMzLjQ4NzkgMzQuMjI2OUMzMy44MTc1IDM4LjAwMiAzMS40NjY0IDM5LjcyMDUgMjkuODMxMyAzOS44NjM0QzI4LjUzODIgMzkuOTc3IDI2LjkxMTQgMzkuMTkwNSAyNi43NjQ1IDM3LjUwMTZDMjYuNjM4NSAzNi4wNTAzIDI3LjE4ODUgMzUuODUyNiAyNy4wNTQxIDM0LjMxMDlDMjYuODE0OSAzMS41NjYyIDI0LjQyNjEgMzEuMjQ2NiAyMy4xMTgzIDMxLjM2MDFDMjEuNTM1NyAzMS40OTkxIDE4LjY2NDEgMzMuMzQ5OCAxOS4wNjcgMzcuOTZDMTkuNDcyMiA0Mi42MTAxIDIzLjkyMjIgNDYuMjg0NSAyOS43NTU3IDQ1Ljc3MzRDMzYuMDUwOSA0NS4yMjIzIDQwLjQzMzcgNDAuMzExNCA0MC43NjM0IDMzLjQyMzRDNDAuNzYwMyAzMy4wNTg2IDQwLjgzNyAzMi42OTc1IDQwLjk4OCAzMi4zNjU1TDQwLjk5IDMyLjM1NzJDNDEuMDU3OCAzMi4yMTI4IDQxLjEzNzIgMzIuMDc0MiA0MS4yMjcyIDMxLjk0MjhDNDEuMzYxNiAzMS43NDA5IDQxLjUzMzggMzEuNTE4IDQxLjc1NjIgMzEuMjczOUM0MS43NTgzIDMxLjI2NzYgNDEuNzU4MyAzMS4yNjc2IDQxLjc2MjYgMzEuMjY3NkM0MS45MjQxIDMxLjA4NDcgNDIuMTE5NCAzMC44ODcgNDIuMzM5NyAzMC42NzQ1QzQ1LjA4OTcgMjguMDc1IDU0Ljk5MzEgMjEuOTQ0MiA2NC4zNTkyIDIzLjg4NTVDNjQuNTU3MyAyMy45MjggNjQuNzM2MSAyNC4wMzM0IDY0Ljg2OTMgMjQuMTg2MkM2NS4wMDI1IDI0LjMzOTEgNjUuMDgyNiAyNC41MzA4IDY1LjA5ODEgMjQuNzMzWiIgZmlsbD0id2hpdGUiLz4KPC9nPgo8L2c+CjxkZWZzPgo8bGluZWFyR3JhZGllbnQgaWQ9InBhaW50MF9saW5lYXJfMjIyXzQ3ODMiIHgxPSI3My41MDA5IiB5MT0iNS4zMTI1IiB4Mj0iMi44NzI0MSIgeTI9Ijc3LjY3NDciIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KPHN0b3Agc3RvcC1jb2xvcj0iIzExQzREMSIvPgo8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiMwMDYyQUQiLz4KPC9saW5lYXJHcmFkaWVudD4KPGNsaXBQYXRoIGlkPSJjbGlwMF8yMjJfNDc4MyI+CjxyZWN0IHdpZHRoPSI4MCIgaGVpZ2h0PSI4MCIgZmlsbD0id2hpdGUiLz4KPC9jbGlwUGF0aD4KPC9kZWZzPgo8L3N2Zz4=",
},
create: (walletOptions: WalletOptions) => {
const wallet = new ImTokenWallet({
...walletOptions,
projectId: options?.projectId,
qrcode: false,
});

return wallet;
},
connectUI: ConnectUI,
isInstalled: isInstalled,
};
};

function isInstalled() {
if (assertWindowEthereum(globalThis.window)) {
return !!globalThis.window.ethereum.isImToken;
}
return false;
}

function ConnectUI(props: ConnectUIProps<ImTokenWallet>) {
const locale = useTWLocale();
return (
<ExtensionOrWCConnectionUI
connect={props.connect}
connected={props.connected}
createWalletInstance={props.createWalletInstance}
goBack={props.goBack}
meta={props.walletConfig.meta}
setConnectedWallet={(w) => props.setConnectedWallet(w as ImTokenWallet)}
setConnectionStatus={props.setConnectionStatus}
supportedWallets={props.supportedWallets}
walletConnectUris={{
ios: imTokenWalletUris.ios,
android: imTokenWalletUris.android,
other: imTokenWalletUris.android,
}}
walletLocale={locale.wallets.imTokenWallet}
isInstalled={isInstalled}
/>
);
}
7 changes: 7 additions & 0 deletions packages/wallets/evm/connectors/imtoken/package.json
@@ -0,0 +1,7 @@
{
"main": "dist/thirdweb-dev-wallets-evm-connectors-imtoken.cjs.js",
"module": "dist/thirdweb-dev-wallets-evm-connectors-imtoken.esm.js",
"browser": {
"./dist/thirdweb-dev-wallets-evm-connectors-imtoken.esm.js": "./dist/thirdweb-dev-wallets-evm-connectors-imtoken.browser.esm.js"
}
}
7 changes: 7 additions & 0 deletions packages/wallets/evm/wallets/imtoken/package.json
@@ -0,0 +1,7 @@
{
"main": "dist/thirdweb-dev-wallets-evm-wallets-imtoken.cjs.js",
"module": "dist/thirdweb-dev-wallets-evm-wallets-imtoken.esm.js",
"browser": {
"./dist/thirdweb-dev-wallets-evm-wallets-imtoken.esm.js": "./dist/thirdweb-dev-wallets-evm-wallets-imtoken.browser.esm.js"
}
}
14 changes: 14 additions & 0 deletions packages/wallets/package.json
Expand Up @@ -147,6 +147,13 @@
},
"default": "./evm/wallets/gcp-kms/dist/thirdweb-dev-wallets-evm-wallets-gcp-kms.cjs.js"
},
"./evm/wallets/imtoken": {
"module": {
"browser": "./evm/wallets/imtoken/dist/thirdweb-dev-wallets-evm-wallets-imtoken.browser.esm.js",
"default": "./evm/wallets/imtoken/dist/thirdweb-dev-wallets-evm-wallets-imtoken.esm.js"
},
"default": "./evm/wallets/imtoken/dist/thirdweb-dev-wallets-evm-wallets-imtoken.cjs.js"
},
"./evm/wallets/phantom": {
"module": {
"browser": "./evm/wallets/phantom/dist/thirdweb-dev-wallets-evm-wallets-phantom.browser.esm.js",
Expand Down Expand Up @@ -336,6 +343,13 @@
},
"default": "./evm/wallets/embedded-wallet/dist/thirdweb-dev-wallets-evm-wallets-embedded-wallet.cjs.js"
},
"./evm/connectors/imtoken": {
"module": {
"browser": "./evm/connectors/imtoken/dist/thirdweb-dev-wallets-evm-connectors-imtoken.browser.esm.js",
"default": "./evm/connectors/imtoken/dist/thirdweb-dev-wallets-evm-connectors-imtoken.esm.js"
},
"default": "./evm/connectors/imtoken/dist/thirdweb-dev-wallets-evm-connectors-imtoken.cjs.js"
},
"./evm/connectors/phantom": {
"module": {
"browser": "./evm/connectors/phantom/dist/thirdweb-dev-wallets-evm-connectors-phantom.browser.esm.js",
Expand Down
48 changes: 48 additions & 0 deletions packages/wallets/src/evm/connectors/imtoken/index.ts
@@ -0,0 +1,48 @@
import { InjectedConnector, InjectedConnectorOptions } from "../injected";
import { assertWindowEthereum } from "../../utils/assertWindowEthereum";
import { Ethereum } from "../injected/types";
import type { Chain } from "@thirdweb-dev/chains";
import { AsyncStorage } from "../../../core/AsyncStorage";

type ImTokenConnectorConstructorArg = {
chains?: Chain[];
connectorStorage: AsyncStorage;
options?: InjectedConnectorOptions;
};

export class ImTokenConnector extends InjectedConnector {
constructor(arg: ImTokenConnectorConstructorArg) {
const defaultOptions = {
name: "imToken",
getProvider() {
function getReady(ethereum?: Ethereum) {
const isToken = !!ethereum?.isToken;
if (!isToken) {
return;
}
return ethereum;
}

if (typeof window === "undefined") {
return;
}
if (assertWindowEthereum(globalThis.window)) {
if (globalThis.window.ethereum?.providers) {
return globalThis.window.ethereum.providers.find(getReady);
}

return getReady(globalThis.window.ethereum);
}
},
};
const options = {
...defaultOptions,
...arg.options,
};
super({
chains: arg.chains,
options,
connectorStorage: arg.connectorStorage,
});
}
}
2 changes: 2 additions & 0 deletions packages/wallets/src/evm/connectors/injected/types.ts
Expand Up @@ -56,6 +56,8 @@ type InjectedProviderFlags = {
isDefiWallet?: true;
isRabbyWallet?: true;
isCoin98Wallet?: true;
// imToken
isToken?: true;
};
type InjectedProviders = InjectedProviderFlags & {
isMetaMask: true;
Expand Down
1 change: 1 addition & 0 deletions packages/wallets/src/evm/constants/walletIds.ts
Expand Up @@ -5,6 +5,7 @@ export const walletIds = {
coreWallet: "coreWallet",
cryptoDefiWallet: "cryptoDefiWallet",
frame: "frame",
imtoken: "imToken",
localWallet: "localWallet",
magicLink: "magicLink",
metamask: "metamask",
Expand Down
1 change: 1 addition & 0 deletions packages/wallets/src/evm/index.ts
Expand Up @@ -32,6 +32,7 @@ export * from "./wallets/coinbase-wallet";
export * from "./wallets/embedded-wallet";
export * from "./wallets/ethers";
export * from "./wallets/frame";
export * from "./wallets/imtoken";
export * from "./wallets/injected";
export * from "./wallets/local-wallet";
export * from "./wallets/signer";
Expand Down

0 comments on commit 79c9e13

Please sign in to comment.