Skip to content

[wallet, react] Add Coin98 Wallet #1921

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Nov 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/kind-bears-decide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@thirdweb-dev/react-core": patch
"@thirdweb-dev/wallets": patch
"@thirdweb-dev/react": patch
---

Add Coin98 wallet
2 changes: 2 additions & 0 deletions packages/react-core/src/core/hooks/wallet-hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useWalletContext } from "../providers/thirdweb-wallet-provider";
import invariant from "tiny-invariant";
import type {
BloctoWallet,
Coin98Wallet,
CoinbaseWallet,
CoreWallet,
EmbeddedWallet,
Expand All @@ -26,6 +27,7 @@ export type WalletId = (typeof walletIds)[keyof typeof walletIds];

type WalletIdToWalletTypeMap = {
metamask: MetaMaskWallet;
coin98: Coin98Wallet;
coinbase: CoinbaseWallet;
coreWallet: CoreWallet;
rainbowWallet: RainbowWallet;
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/evm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,5 @@ export {
InjectedWallet,
setWalletAnalyticsEnabled,
CoreWallet,
Coin98Wallet,
} from "@thirdweb-dev/wallets";
1 change: 1 addition & 0 deletions packages/react/src/evm/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ export function enDefault() {
trustWallet: extensionAndQRScanScreens("Trust"),
zerionWallet: extensionAndQRScanScreens("Zerion"),
coreWallet: extensionAndQRScanScreens("Core"),
coin98Wallet: extensionAndQRScanScreens("Coin98"),
paperWallet: {
signIn: "Sign in",
signInWithGoogle: "Sign in with Google",
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/evm/locales/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ export function esDefault(): ThirdwebLocale {
metamaskWallet: extensionAndQRScanScreens("MetaMask"),
okxWallet: extensionAndQRScanScreens("OKX"),
coreWallet: extensionAndQRScanScreens("Core"),
coin98Wallet: extensionAndQRScanScreens("Coin98"),
phantomWallet: extensionAndQRScanScreens("Phantom"),
rainbowWallet: extensionAndQRScanScreens("Rainbow"),
trustWallet: extensionAndQRScanScreens("Trust"),
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/evm/locales/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ export function jaDefault(): ThirdwebLocale {
metamaskWallet: extensionAndQRScanScreens("MetaMask"),
okxWallet: extensionAndQRScanScreens("OKX"),
coreWallet: extensionAndQRScanScreens("Core"),
coin98Wallet: extensionAndQRScanScreens("Coin98"),
phantomWallet: extensionAndQRScanScreens("Phantom"),
rainbowWallet: extensionAndQRScanScreens("Rainbow"),
trustWallet: extensionAndQRScanScreens("Trust"),
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export { walletConnectV1 } from "./wallet/wallets/walletConnectV1";
export { zerionWallet } from "./wallet/wallets/zerion/zerionWallet";
export { okxWallet } from "./wallet/wallets/okx/okxWallet";
export { coreWallet } from "./wallet/wallets/coreWallet/coreWallet";
export { coin98Wallet } from "./wallet/wallets/coin98/coin98Wallet";
export { darkTheme, lightTheme } from "./design-system/index";
export type { Theme, ThemeOverrides } from "./design-system/index";

Expand Down
148 changes: 148 additions & 0 deletions packages/react/src/wallet/wallets/coin98/Coin98ConnectUI.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import { ConnectUIProps, useConnect } from "@thirdweb-dev/react-core";
import { ConnectingScreen } from "../../ConnectWallet/screens/ConnectingScreen";
import { isMobile } from "../../../evm/utils/isMobile";
import { useCallback, useEffect, useRef, useState } from "react";
import { GetStartedScreen } from "../../ConnectWallet/screens/GetStartedScreen";
import type { Coin98Wallet } from "@thirdweb-dev/wallets";
import { wait } from "../../../utils/wait";
import { useTWLocale } from "../../../evm/providers/locale-provider";
import { Coin98Scan } from "./Coin98Scan";
import { WCOpenURI } from "../../ConnectWallet/screens/WCOpenUri";
import { coin98WalletUris } from "./coin98WalletUris";

export const Coin98ConnectUI = (props: ConnectUIProps<Coin98Wallet>) => {
const [screen, setScreen] = useState<
"connecting" | "scanning" | "get-started" | "open-wc-uri"
>("connecting");
const locale = useTWLocale().wallets.coin98Wallet;
const connectingLocale = {
getStartedLink: locale.getStartedLink,
instruction: locale.connectionScreen.instruction,
tryAgain: locale.connectionScreen.retry,
inProgress: locale.connectionScreen.inProgress,
failed: locale.connectionScreen.failed,
};
const { walletConfig, connected } = props;
const connect = useConnect();
const [errorConnecting, setErrorConnecting] = useState(false);

const hideBackButton = props.supportedWallets.length === 1;

const connectToExtension = useCallback(async () => {
try {
connectPrompted.current = true;
setErrorConnecting(false);
setScreen("connecting");
await wait(1000);
await connect(walletConfig);
connected();
} catch (e) {
setErrorConnecting(true);
console.error(e);
}
}, [connected, connect, walletConfig]);

const connectPrompted = useRef(false);
useEffect(() => {
if (connectPrompted.current) {
return;
}

const isInstalled = walletConfig.isInstalled
? walletConfig.isInstalled()
: false;

// if loading
(async () => {
if (isInstalled) {
connectToExtension();
}

// if wallet is not injected
else {
// on mobile, open the Coin98 Mobile via wallet connect
if (isMobile()) {
setScreen("open-wc-uri");
} else {
// on desktop, show the Coin98 app scan qr code
setScreen("scanning");
}
}
})();
}, [connectToExtension, walletConfig]);

if (screen === "connecting") {
return (
<ConnectingScreen
locale={{
getStartedLink: locale.getStartedLink,
instruction: locale.connectionScreen.instruction,
tryAgain: locale.connectionScreen.retry,
inProgress: locale.connectionScreen.inProgress,
failed: locale.connectionScreen.failed,
}}
errorConnecting={errorConnecting}
onGetStarted={() => {
setScreen("get-started");
}}
onRetry={connectToExtension}
hideBackButton={hideBackButton}
onBack={props.goBack}
walletName={walletConfig.meta.name}
walletIconURL={walletConfig.meta.iconURL}
/>
);
}

if (screen === "open-wc-uri") {
return (
<WCOpenURI
locale={connectingLocale}
onRetry={() => {
// NOOP - TODO make onRetry optional
}}
errorConnecting={errorConnecting}
onGetStarted={() => {
setScreen("get-started");
}}
hideBackButton={hideBackButton}
onBack={props.goBack}
onConnected={connected}
walletConfig={walletConfig}
appUriPrefix={coin98WalletUris}
/>
);
}

if (screen === "get-started") {
return (
<GetStartedScreen
locale={{
scanToDownload: locale.getStartedScreen.instruction,
}}
walletIconURL={walletConfig.meta.iconURL}
walletName={walletConfig.meta.name}
chromeExtensionLink={walletConfig.meta.urls?.chrome}
googlePlayStoreLink={walletConfig.meta.urls?.android}
appleStoreLink={walletConfig.meta.urls?.ios}
onBack={props.goBack}
/>
);
}

if (screen === "scanning") {
return (
<Coin98Scan
onBack={props.goBack}
onConnected={props.connected}
onGetStarted={() => {
setScreen("get-started");
}}
hideBackButton={hideBackButton}
walletConfig={walletConfig}
/>
);
}

return null;
};
65 changes: 65 additions & 0 deletions packages/react/src/wallet/wallets/coin98/Coin98Scan.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { ScanScreen } from "../../ConnectWallet/screens/ScanScreen";
import {
useCreateWalletInstance,
useWalletContext,
} from "@thirdweb-dev/react-core";
import { useEffect, useRef, useState } from "react";
import type { Coin98Wallet } from "@thirdweb-dev/wallets";
import type { WalletConfig } from "@thirdweb-dev/react-core";
import { useTWLocale } from "../../../evm/providers/locale-provider";

export const Coin98Scan: React.FC<{
onBack: () => void;
onGetStarted: () => void;
onConnected: () => void;
walletConfig: WalletConfig<Coin98Wallet>;
hideBackButton: boolean;
}> = ({ onBack, onConnected, onGetStarted, walletConfig, hideBackButton }) => {
const locale = useTWLocale().wallets.coin98Wallet;
const createInstance = useCreateWalletInstance();
const [qrCodeUri, setQrCodeUri] = useState<string | undefined>();
const { setConnectedWallet, chainToConnect, setConnectionStatus } =
useWalletContext();

const scanStarted = useRef(false);
useEffect(() => {
if (scanStarted.current) {
return;
}
scanStarted.current = true;

const wallet = createInstance(walletConfig);

setConnectionStatus("connecting");
wallet.connectWithQrCode({
chainId: chainToConnect?.chainId,
onQrCodeUri(uri) {
setQrCodeUri(uri);
},
onConnected() {
setConnectedWallet(wallet);
onConnected();
},
});
}, [
createInstance,
setConnectedWallet,
chainToConnect,
onConnected,
walletConfig,
setConnectionStatus,
]);

return (
<ScanScreen
qrScanInstruction={locale.scanScreen.instruction}
onBack={onBack}
onGetStarted={onGetStarted}
qrCodeUri={qrCodeUri}
walletName={walletConfig.meta.name}
walletIconURL={walletConfig.meta.iconURL}
hideBackButton={hideBackButton}
getStartedLink={locale.getStartedLink}
/>
);
};
52 changes: 52 additions & 0 deletions packages/react/src/wallet/wallets/coin98/coin98Wallet.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import type { WalletOptions, WalletConfig } from "@thirdweb-dev/react-core";
import { Coin98Wallet, getInjectedCoin98Provider } from "@thirdweb-dev/wallets";
import { Coin98ConnectUI } from "./Coin98ConnectUI";

type Coin98WalletOptions = {
/**
* When connecting Coin98 using the QR Code - Wallet Connect connector is used which requires a project id.
* This project id is Your project’s unique identifier for wallet connect that can be obtained at cloud.walletconnect.com.
*
* https://docs.walletconnect.com/2.0/web3modal/options#projectid-required
*/
projectId?: string;

/**
* If true, the wallet will be tagged as "reccomended" in ConnectWallet Modal
*/
recommended?: boolean;
};

export const coin98Wallet = (
options?: Coin98WalletOptions,
): WalletConfig<Coin98Wallet> => {
return {
id: Coin98Wallet.id,
recommended: options?.recommended,
meta: {
name: "Coin98 Wallet",
urls: {
chrome:
"https://chrome.google.com/webstore/detail/coin98-wallet/aeachknmefphepccionboohckonoeemg",
android:
"https://play.google.com/store/apps/details?id=coin98.crypto.finance.media",
ios: "https://apps.apple.com/us/app/coin98-super-wallet/id1561969966",
},
iconURL:
"data:image/png;base64,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",
},
create: (walletOptions: WalletOptions) => {
const wallet = new Coin98Wallet({
...walletOptions,
projectId: options?.projectId,
qrcode: false,
});

return wallet;
},
connectUI: Coin98ConnectUI,
isInstalled() {
return !!getInjectedCoin98Provider();
},
};
};
5 changes: 5 additions & 0 deletions packages/react/src/wallet/wallets/coin98/coin98WalletUris.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const coin98WalletUris = {
ios: "coin98://",
android: "coin98://",
other: "coin98://",
};
7 changes: 7 additions & 0 deletions packages/wallets/evm/connectors/coin98/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"main": "dist/thirdweb-dev-wallets-evm-connectors-coin98.cjs.js",
"module": "dist/thirdweb-dev-wallets-evm-connectors-coin98.esm.js",
"browser": {
"./dist/thirdweb-dev-wallets-evm-connectors-coin98.esm.js": "./dist/thirdweb-dev-wallets-evm-connectors-coin98.browser.esm.js"
}
}
7 changes: 7 additions & 0 deletions packages/wallets/evm/wallets/coin98/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"main": "dist/thirdweb-dev-wallets-evm-wallets-coin98.cjs.js",
"module": "dist/thirdweb-dev-wallets-evm-wallets-coin98.esm.js",
"browser": {
"./dist/thirdweb-dev-wallets-evm-wallets-coin98.esm.js": "./dist/thirdweb-dev-wallets-evm-wallets-coin98.browser.esm.js"
}
}
14 changes: 14 additions & 0 deletions packages/wallets/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,13 @@
},
"default": "./evm/wallets/blocto/dist/thirdweb-dev-wallets-evm-wallets-blocto.cjs.js"
},
"./evm/wallets/coin98": {
"module": {
"browser": "./evm/wallets/coin98/dist/thirdweb-dev-wallets-evm-wallets-coin98.browser.esm.js",
"default": "./evm/wallets/coin98/dist/thirdweb-dev-wallets-evm-wallets-coin98.esm.js"
},
"default": "./evm/wallets/coin98/dist/thirdweb-dev-wallets-evm-wallets-coin98.cjs.js"
},
"./evm/wallets/engine": {
"module": {
"browser": "./evm/wallets/engine/dist/thirdweb-dev-wallets-evm-wallets-engine.browser.esm.js",
Expand Down Expand Up @@ -245,6 +252,13 @@
},
"default": "./evm/connectors/blocto/dist/thirdweb-dev-wallets-evm-connectors-blocto.cjs.js"
},
"./evm/connectors/coin98": {
"module": {
"browser": "./evm/connectors/coin98/dist/thirdweb-dev-wallets-evm-connectors-coin98.browser.esm.js",
"default": "./evm/connectors/coin98/dist/thirdweb-dev-wallets-evm-connectors-coin98.esm.js"
},
"default": "./evm/connectors/coin98/dist/thirdweb-dev-wallets-evm-connectors-coin98.cjs.js"
},
"./evm/connectors/signer": {
"module": {
"browser": "./evm/connectors/signer/dist/thirdweb-dev-wallets-evm-connectors-signer.browser.esm.js",
Expand Down
Loading