Skip to content
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/shiny-owls-sit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@thirdweb-dev/react-core": minor
"@thirdweb-dev/wallets": minor
"@thirdweb-dev/react": minor
---

Adding cometh connect biometric AA 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 @@ -17,6 +17,7 @@ import type {
TokenBoundSmartWallet,
TrustWallet,
WalletConnect,
ComethConnect,
walletIds,
} from "@thirdweb-dev/wallets";
import { WalletInstance } from "../types/wallet";
Expand All @@ -40,6 +41,7 @@ type WalletIdToWalletTypeMap = {
walletConnect: WalletConnect;
phantom: PhantomWallet;
walletConnectV1: WalletConnect;
comethConnect: ComethConnect;
okx: OKXWallet;
};

Expand Down
16 changes: 16 additions & 0 deletions packages/react/src/evm/hooks/wallets/useComethConnect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useConnect } from "@thirdweb-dev/react-core";
import { useCallback } from "react";
import { ComethAdditionalOptions } from "@thirdweb-dev/wallets";

export function useComethConnect() {
const connect = useConnect();
return useCallback(
async (options: ComethAdditionalOptions) => {
const { comethConnect } = await import(
"../../../wallet/wallets/comethConnect/comethConnect"
);
return connect(comethConnect(options));
},
[connect],
);
}
2 changes: 2 additions & 0 deletions packages/react/src/evm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export { useMetamask } from "./hooks/wallets/useMetamask";
export { useCoinbaseWallet } from "./hooks/wallets/useCoinbaseWallet";
export { useFrameWallet } from "./hooks/wallets/useFrame";
export { useBloctoWallet } from "./hooks/wallets/useBloctoWallet";
export { useComethConnect } from "./hooks/wallets/useComethConnect";

export {
usePaperWalletUserEmail,
Expand Down Expand Up @@ -66,5 +67,6 @@ export {
MagicLink,
SignerWallet,
InjectedWallet,
ComethConnect,
setWalletAnalyticsEnabled,
} from "@thirdweb-dev/wallets";
1 change: 1 addition & 0 deletions packages/react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export { defaultWallets } from "./wallet/wallets/defaultWallets";
export { useSmartWallet } from "./evm/hooks/wallets/useSmartWallet";
export { bloctoWallet } from "./wallet/wallets/blocto/bloctoWallet";
export { coinbaseWallet } from "./wallet/wallets/coinbase/coinbaseWallet";
export { comethConnect } from "./wallet/wallets/comethConnect/comethConnect";
export { embeddedWallet } from "./wallet/wallets/embeddedWallet/embeddedWallet";
export { frameWallet } from "./wallet/wallets/frame/frameWallet";
export { localWallet } from "./wallet/wallets/localWallet/localWallet";
Expand Down
103 changes: 103 additions & 0 deletions packages/react/src/wallet/wallets/comethConnect/comethConnect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import {
ConnectUIProps,
useConnect,
type WalletConfig,
} from "@thirdweb-dev/react-core";
import {
ComethConnect,
ComethAdditionalOptions,
walletIds,
} from "@thirdweb-dev/wallets";
import { useRef, useEffect, useState, useCallback } from "react";
import { Spinner } from "../../../components/Spinner";
import { Container } from "../../../components/basic";
import { ExclamationTriangleIcon, ReloadIcon } from "@radix-ui/react-icons";
import { iconSize, spacing } from "../../../design-system";
import { Spacer } from "../../../components/Spacer";
import { Text } from "../../../components/text";
import { Button } from "../../../components/buttons";

export const comethConnect = (
config: Omit<ComethAdditionalOptions, "chain">,
): WalletConfig<ComethConnect> => ({
id: walletIds.comethConnect,
meta: {
name: "Cometh Connect",
iconURL:
"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iODAiIGhlaWdodD0iODAiIHZpZXdCb3g9IjAgMCA4MCA4MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjgwIiBoZWlnaHQ9IjgwIiByeD0iMTIiIGZpbGw9IiMxRDJGNEEiLz4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzUwXzUpIj4KPHBhdGggZD0iTTYzLjUwNzUgMTUuMDM0MkM1Ni44NTI4IDE1LjQ3MjMgNDcuNzQwMSAxOC4yMzQ5IDM5LjkwNDMgMjIuMTg1M0MzNi45NDY2IDIzLjY3NzggMzQuODE3NCAyNC45ODU1IDMyLjgxNDggMjYuNTQzMUMzMi43NzAyIDI2LjU3NzMgMzIuNzMyNiAyNi41OTEgMzIuNzMyNiAyNi41NzA1QzMyLjczMjYgMjYuNTQ2NSAzMi44MDc5IDI2LjE5MzkgMzIuOTAzNyAyNS43ODMxQzMyLjk5NjEgMjUuMzcyNCAzMy4wNzUgMjUuMDE5OCAzMy4wNzUgMjQuOTk5MkMzMy4wNzUgMjQuODkzMSAyOS41Nzk4IDI3LjQwNTggMjcuNzY4OSAyOC44MDkzQzIwLjAzOTIgMzQuODEwMiAxNi4xMjY1IDQwLjQzNDYgMTUuMjA5IDQ2Ljg2NjlDMTUuMDI3NiA0OC4xNDA0IDE0Ljk1MjMgNDkuODg5NiAxNS4wMzEgNTEuMDI2MUMxNS4zNzY4IDU1Ljk0NTMgMTcuNTQ3MSA1OS44OTkyIDIxLjIzMDUgNjIuMzIyOEMyMS44ODA5IDYyLjc1MDggMjIuMjMzNSA2Mi45NDkyIDIyLjkxMTMgNjMuMjc3OUMyNi4wNDcgNjQuNzk0NCAyOS44NTM3IDY1LjI3MDIgMzQuMDg0OCA2NC42ODE0QzM2LjYxMTIgNjQuMzI4OSAzOS4yMjY2IDYzLjU3NTggNDEuMDE2OCA2Mi42ODU3QzQzLjAxMjYgNjEuNjkyOCA0NS4xMzE1IDYwLjI0ODMgNDcuMDU4OSA1OC41NzQ0QzQ3LjYxMzQgNTguMDg4MiA0OS4zMDQ1IDU2LjQwMDYgNDkuNzgzNyA1NS44NTI5QzUxLjAyNjQgNTQuNDI4OSA1Mi4wMjU5IDUzLjA4MzUgNTIuOTEyNiA1MS42NDIyTDUzLjE0NTMgNTEuMjY1N0w1Mi45NjA2IDUxLjQzN0M1Mi43MTQgNTEuNjY5NyA1Mi4zNjgzIDUxLjkwOTMgNTIuMDUzNCA1Mi4wNzM2QzUxLjcwNzYgNTIuMjUxNyA1MS42NTYyIDUyLjI0ODEgNTEuODI3NSA1Mi4wNDI5QzUyLjIwNCA1MS41OTQ0IDUyLjY1MjUgNTAuNzU1NyA1Mi44MDk5IDUwLjIwNzlDNTIuODU3OCA1MC4wNDAyIDUyLjg5MjEgNDkuODk5OCA1Mi44ODUyIDQ5Ljg5M0M1Mi44ODE4IDQ5Ljg4NjIgNTIuNzIxIDQ5Ljk4ODggNTIuNTM2IDUwLjEyMjRDNTAuNDQ3OCA1MS41OTQ0IDQ2LjY5NiA1My40MjI0IDQ0LjIwMzkgNTQuMTc4OUM0My45ODgyIDU0LjI0MzkgNDMuODA2OCA1NC4yOTE5IDQzLjggNTQuMjg1MUM0My43OTMgNTQuMjc4MyA0My44NTgxIDU0LjExMDQgNDMuOTQwMiA1My45MTJDNDQuMTAxMiA1My41MzIgNDQuMzM0IDUyLjg0MDQgNDQuNDE2MSA1Mi40OTgxQzQ0LjUyMjIgNTIuMDY2OCA0NC41NDI3IDUyLjA4MDQgNDQuMjEwNyA1Mi4zNDc1QzQzLjg3ODcgNTIuNjE0NCA0Mi44OTk3IDUzLjI3MTcgNDIuNDcxNyA1My41MTQ3QzQwLjkwNzMgNTQuNDAxNCAzOS4wODk2IDU1LjAwNzMgMzcuMjUxMiA1NS4yNTM5QzM2LjU3MzQgNTUuMzQ2MyAzNS4yMTQ0IDU1LjM4MzggMzQuNTkxNSA1NS4zMjU4QzMyLjc0OTcgNTUuMTU3OSAzMS4yNjQgNTQuNjM0MiAzMC4wNjI1IDUzLjcyN0MyOC41OTczIDUyLjYyNDggMjcuNzIxIDUwLjk4NTEgMjcuNDQwMyA0OC44Mjg0QzI3LjM2ODQgNDguMjkxIDI3LjM2MTUgNDcuMDI3OCAyNy40MjMyIDQ2LjQ1NkMyNy41ODA2IDQ1LjAwODEgMjcuOTIzIDQzLjc4NiAyOC41NDYgNDIuNDMzOEMyOS45NyAzOS4zNTY0IDMyLjk3NTYgMzUuODY4IDM3LjM5NSAzMi4xNzFDNDAuMTY3OSAyOS44NDk5IDQzLjYxODUgMjcuMzUxIDQ2LjkzOSAyNS4yNTk0QzUxLjQ0NzUgMjIuNDE4MSA1Ni41OTI1IDE5Ljc4NTYgNjEuNTA1IDE3LjgwMzZDNjEuODQzOCAxNy42NjY2IDYyLjEzNDggMTcuNTQzNCA2Mi4xNDg0IDE3LjUyOTdDNjIuMTgyOCAxNy40OTg5IDYxLjQ3MDcgMTcuMzc1NyA2MC44NTQ1IDE3LjMwMzhDNjAuNTkxIDE3LjI3MyA2MC4wMDU2IDE3LjIzODcgNTkuNTUzNyAxNy4yMjVMNTguNzMyMSAxNy4yMDQ1TDU4Ljk4ODggMTcuMTEyMUM1OS40MDY1IDE2Ljk2NDkgNjMuOTI4NiAxNS4zNDkxIDY0LjQzMTggMTUuMTY3N0w2NC44OTM5IDE0Ljk5OTlMNjQuNDE0NyAxNS4wMDM0QzY0LjE1MTEgMTUuMDAzNCA2My43NDM4IDE1LjAyMDUgNjMuNTA3NSAxNS4wMzQyWiIgZmlsbD0id2hpdGUiLz4KPC9nPgo8ZGVmcz4KPGNsaXBQYXRoIGlkPSJjbGlwMF81MF81Ij4KPHJlY3Qgd2lkdGg9IjUwIiBoZWlnaHQ9IjUwIiBmaWxsPSJ3aGl0ZSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTUgMTUpIi8+CjwvY2xpcFBhdGg+CjwvZGVmcz4KPC9zdmc+Cg==",
},
create(walletOptions) {
return new ComethConnect({
...walletOptions,
...config,
});
},
connectUI: ComethConnectUI,
isInstalled() {
return false;
},
});

export const ComethConnectUI = ({
connected,
walletConfig,
}: ConnectUIProps<ComethConnect>) => {
const connect = useConnect();
const [status, setStatus] = useState<"loading" | "error">("loading");
const prompted = useRef(false);

const connectWallet = useCallback(async () => {
try {
setStatus("loading");
await connect(walletConfig);
connected();
} catch (e) {
setStatus("error");
console.error(e);
}
}, [connect, connected, walletConfig]);

useEffect(() => {
if (prompted.current) {
return;
}
prompted.current = true;
connectWallet();
}, [connectWallet]);

return (
<Container flex="column" center="y" animate="fadein" fullHeight p="lg">
<Container
expand
center="both"
flex="column"
style={{
minHeight: "250px",
}}
>
{status === "loading" && <Spinner size="xl" color="accentText" />}
{status === "error" && (
<Container color="danger" flex="column" center="x" animate="fadein">
<ExclamationTriangleIcon width={iconSize.xl} height={iconSize.xl} />
<Spacer y="md" />
<Text color="danger">Failed to sign in</Text>
</Container>
)}
</Container>

{status === "error" && (
<Button
fullWidth
variant="accent"
onClick={connectWallet}
style={{
gap: spacing.sm,
}}
>
<ReloadIcon width={iconSize.sm} height={iconSize.sm} />
Try Again
</Button>
)}
</Container>
);
};
2 changes: 1 addition & 1 deletion packages/sdk/src/evm/constants/erc721-features.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import IMintableERC721Abi from "@thirdweb-dev/contracts-js/dist/abis/IMintableER
import MulticallAbi from "@thirdweb-dev/contracts-js/dist/abis/IMulticall.json";
import SignatureMintERC721Abi from "@thirdweb-dev/contracts-js/dist/abis/ISignatureMintERC721.json";
import SignatureMintERC721_V1Abi from "@thirdweb-dev/contracts-js/dist/abis/ISignatureMintERC721_V1.json";
import TieredDropAbi from "@thirdweb-dev/contracts-js/dist/abis/LazyMintWithTier_V1.json";
import TieredDropAbi from "@thirdweb-dev/contracts-js/dist/abis/LazyMintWithTier.json";
import SharedMetadataAbi from "@thirdweb-dev/contracts-js/dist/abis/SharedMetadata.json";
import zora_IDropERC721 from "@thirdweb-dev/contracts-js/dist/abis/zora_IERC721Drop.json";
import ILoyaltyCardAbi from "@thirdweb-dev/contracts-js/dist/abis/ILoyaltyCard.json";
Expand Down
7 changes: 7 additions & 0 deletions packages/wallets/evm/connectors/cometh-connect/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"main": "dist/thirdweb-dev-wallets-evm-connectors-cometh-connect.cjs.js",
"module": "dist/thirdweb-dev-wallets-evm-connectors-cometh-connect.esm.js",
"browser": {
"./dist/thirdweb-dev-wallets-evm-connectors-cometh-connect.esm.js": "./dist/thirdweb-dev-wallets-evm-connectors-cometh-connect.browser.esm.js"
}
}
7 changes: 7 additions & 0 deletions packages/wallets/evm/wallets/cometh-connect/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"main": "dist/thirdweb-dev-wallets-evm-wallets-cometh-connect.cjs.js",
"module": "dist/thirdweb-dev-wallets-evm-wallets-cometh-connect.esm.js",
"browser": {
"./dist/thirdweb-dev-wallets-evm-wallets-cometh-connect.esm.js": "./dist/thirdweb-dev-wallets-evm-wallets-cometh-connect.browser.esm.js"
}
}
15 changes: 15 additions & 0 deletions packages/wallets/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,13 @@
},
"default": "./evm/connectors/trust/dist/thirdweb-dev-wallets-evm-connectors-trust.cjs.js"
},
"./evm/wallets/cometh-connect": {
"module": {
"browser": "./evm/wallets/cometh-connect/dist/thirdweb-dev-wallets-evm-wallets-cometh-connect.browser.esm.js",
"default": "./evm/wallets/cometh-connect/dist/thirdweb-dev-wallets-evm-wallets-cometh-connect.esm.js"
},
"default": "./evm/wallets/cometh-connect/dist/thirdweb-dev-wallets-evm-wallets-cometh-connect.cjs.js"
},
"./evm/wallets/rainbow-wallet": {
"module": {
"browser": "./evm/wallets/rainbow-wallet/dist/thirdweb-dev-wallets-evm-wallets-rainbow-wallet.browser.esm.js",
Expand Down Expand Up @@ -323,6 +330,13 @@
},
"default": "./evm/connectors/smart-wallet/dist/thirdweb-dev-wallets-evm-connectors-smart-wallet.cjs.js"
},
"./evm/connectors/cometh-connect": {
"module": {
"browser": "./evm/connectors/cometh-connect/dist/thirdweb-dev-wallets-evm-connectors-cometh-connect.browser.esm.js",
"default": "./evm/connectors/cometh-connect/dist/thirdweb-dev-wallets-evm-connectors-cometh-connect.esm.js"
},
"default": "./evm/connectors/cometh-connect/dist/thirdweb-dev-wallets-evm-connectors-cometh-connect.cjs.js"
},
"./evm/connectors/wallet-connect": {
"module": {
"browser": "./evm/connectors/wallet-connect/dist/thirdweb-dev-wallets-evm-connectors-wallet-connect.browser.esm.js",
Expand Down Expand Up @@ -403,6 +417,7 @@
"@account-abstraction/contracts": "^0.5.0",
"@account-abstraction/sdk": "^0.5.0",
"@account-abstraction/utils": "^0.5.0",
"@cometh/connect-sdk": "^1.2.0",
"@blocto/sdk": "^0.5.4",
"@coinbase/wallet-sdk": "^3.7.1",
"@google-cloud/kms": "3.0.1",
Expand Down
120 changes: 120 additions & 0 deletions packages/wallets/src/evm/connectors/cometh-connect/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { Connector } from "../../interfaces/connector";
import type { providers, Signer } from "ethers";
import { ethers } from "ethers";

import {
ComethWallet,
ComethProvider,
ComethSigner,
ConnectAdaptor,
AUTHAdapter,
SupportedNetworks,
} from "@cometh/connect-sdk";

import { ComethWalletConfig } from "./types";
import { walletIds } from "../../constants/walletIds";

export class ComethConnector extends Connector {
readonly id = walletIds.comethConnect;
readonly name = "Cometh Connect";
private options: ComethWalletConfig;
private instance?: ComethWallet;
private authAdapter?: AUTHAdapter;
constructor(config: ComethWalletConfig) {
super();
this.options = config;
}

async connect() {
const chainId = ethers.utils.hexlify(this.options.chain.chainId);

if (this._isSupportedNetwork(chainId)) {
this.authAdapter = new ConnectAdaptor({
chainId: chainId,
apiKey: this.options.apiKey,
rpcUrl: this.options.rpcUrl,
});
} else {
throw new Error("This network is not supported");
}

if (!this.authAdapter) {
throw new Error("authAdapter not initialized");
}
this.instance = new ComethWallet({
authAdapter: this.authAdapter,
apiKey: this.options.apiKey,
rpcUrl: this.options.rpcUrl,
});

if (!this.instance) {
throw new Error("Error connecting User");
}

// eslint-disable-next-line no-unused-expressions
this.options?.walletAddress
? await this.instance.connect(this.options.walletAddress)
: await this.instance.connect();

return this.getAddress();
}

_isSupportedNetwork(value: string): value is SupportedNetworks {
return Object.values(SupportedNetworks).includes(value as any);
}

async disconnect(): Promise<void> {
const instance = await this.instance;
if (!instance) {
throw new Error("Error connecting User");
}
await instance.logout();
}

async getProvider(): Promise<providers.Provider> {
if (!this.instance) {
throw new Error("Error connecting User");
}
const provider = await this.instance.getProvider();
if (!provider) {
throw new Error("Provider not found");
}
return provider;
}

public async getSigner(): Promise<Signer> {
if (!this.instance) {
throw new Error("Error connecting User");
}
const instanceProvider = new ComethProvider(this.instance);
return new ComethSigner(this.instance, instanceProvider);
}

async getAddress(): Promise<string> {
if (!this.instance) {
throw new Error("Error connecting User");
}
return await this.instance.getAddress();
}

async isConnected(): Promise<boolean> {
try {
const addr = await this.getAddress();
return !!addr;
} catch (e) {
return false;
}
}

async switchChain(): Promise<void> {
throw new Error("method is not implemented for this adapter");
}

updateChains() {
console.debug("no update chains possible");
}

async setupListeners() {
throw new Error("method is not implemented for this adapter");
}
}
9 changes: 9 additions & 0 deletions packages/wallets/src/evm/connectors/cometh-connect/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Chain } from "@thirdweb-dev/chains";

// eslint-disable-next-line @typescript-eslint/ban-types
export interface ComethWalletConfig {
chain: Chain;
apiKey: string;
walletAddress?: string;
rpcUrl?: string;
}
1 change: 1 addition & 0 deletions packages/wallets/src/evm/constants/walletIds.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export const walletIds = {
blocto: "blocto",
coinbase: "coinbase",
comethConnect: "comethConnect",
frame: "frame",
localWallet: "localWallet",
magicLink: "magicLink",
Expand Down
4 changes: 4 additions & 0 deletions packages/wallets/src/evm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ export type {
} from "./wallets/abstract";

export * from "./wallets/paper-wallet";
export {
ComethConnect,
type ComethAdditionalOptions,
} from "./wallets/cometh-connect";
// just the types
export { AbstractClientWallet } from "./wallets/base";
export type { WalletOptions } from "./wallets/base";
Expand Down
Loading