Skip to content

Commit

Permalink
Add QR connection support in Coinbase wallet
Browse files Browse the repository at this point in the history
  • Loading branch information
MananTank committed Feb 16, 2024
1 parent 1dd462f commit 994f033
Show file tree
Hide file tree
Showing 11 changed files with 542 additions and 60 deletions.
1 change: 1 addition & 0 deletions packages/thirdweb/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@
"!tsconfig.build.json"
],
"dependencies": {
"@coinbase/wallet-sdk": "^3.7.1",
"@emotion/react": "11.11.3",
"@emotion/styled": "11.11.0",
"@noble/hashes": "1.3.3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ import type { DAppMetaData } from "../../wallets/types.js";
export const ThirdwebProviderContext = /* @__PURE__ */ createContext<{
wallets: WalletConfig[];
client: ThirdwebClient;
dappMetadata?: DAppMetaData;
dappMetadata: DAppMetaData;
} | null>(null);
5 changes: 2 additions & 3 deletions packages/thirdweb/src/react/providers/thirdweb-provider.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable better-tree-shaking/no-top-level-side-effects */
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import {
AutoConnect,
Expand All @@ -23,6 +21,7 @@ import {
import { getChainIdFromChain } from "../../chain/index.js";
import type { DAppMetaData } from "../../wallets/types.js";
import { isBaseTransactionOptions } from "../../transaction/index.js";
import { defaultDappMetadata } from "../../wallets/wallet-connect/index.js";

/**
* The ThirdwebProvider is component is a provider component that sets up the React Query client and Wallet Connection Manager.
Expand Down Expand Up @@ -110,7 +109,7 @@ export function ThirdwebProvider(props: ThirdwebProviderProps) {
value={{
wallets: props.wallets || defaultWallets,
client: props.client,
dappMetadata: props.dappMetadata,
dappMetadata: props.dappMetadata || defaultDappMetadata,
}}
>
{props.autoConnect === false ? <NoAutoConnect /> : <AutoConnect />}
Expand Down
2 changes: 1 addition & 1 deletion packages/thirdweb/src/react/types/wallets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export type WalletConfig = {

create: (options: {
client: ThirdwebClient;
dappMetadata?: DAppMetaData;
dappMetadata: DAppMetaData;
}) => Wallet;

/**
Expand Down
148 changes: 129 additions & 19 deletions packages/thirdweb/src/react/wallets/coinbase/coinbaseConfig.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@ import {
injectedCoinbaseProvider,
coinbaseMetadata,
coinbaseWallet,
coinbaseSDKWallet,
CoinbaseSDKWallet,
} from "../../../wallets/index.js";
import type { WalletConfig } from "../../types/wallets.js";
import { useTWLocale } from "../../providers/locale-provider.js";
import type { ConnectUIProps, WalletConfig } from "../../types/wallets.js";
import { GetStartedScreen } from "../shared/GetStartedScreen.js";
import { InjectedConnectUI } from "../shared/InjectedConnectUI.js";
import { ScanScreen } from "../shared/ScanScreen.js";
import { useState, useRef, useEffect } from "react";

/**
* Integrate Coinbase wallet connection into your app.
Expand All @@ -19,29 +25,133 @@ import { InjectedConnectUI } from "../shared/InjectedConnectUI.js";
* @returns WalletConfig object to be passed into `ThirdwebProvider`
*/
export const coinbaseConfig = (): WalletConfig => {
const isInjected = !!injectedCoinbaseProvider();

return {
metadata: coinbaseMetadata,
create() {
return coinbaseWallet();
},
connectUI(props) {
return (
<InjectedConnectUI
{...props}
onGetStarted={() => {
// TODO
}}
// links={{
// extension:
// "https://chrome.google.com/webstore/detail/coinbase-wallet-extension/hnfanknocfeofbddgcijnmhnfnkdnaad",
// android: "https://play.google.com/store/apps/details?id=org.toshi",
// ios: "https://apps.apple.com/us/app/coinbase-wallet-nfts-crypto/id1278383455",
// }}
/>
);
create(createOptions) {
if (isInjected) {
return coinbaseWallet();
} else {
return coinbaseSDKWallet({
appName: createOptions.dappMetadata.name,
});
}
},
connectUI: CoinbaseConnectUI,
isInstalled() {
return !!injectedCoinbaseProvider();
},
};
};

const links = {
chrome:
"https://chrome.google.com/webstore/detail/coinbase-wallet-extension/hnfanknocfeofbddgcijnmhnfnkdnaad",
android: "https://play.google.com/store/apps/details?id=org.toshi",
ios: "https://apps.apple.com/us/app/coinbase-wallet-nfts-crypto/id1278383455",
};

function CoinbaseConnectUI(props: ConnectUIProps) {
const isInjected = !!injectedCoinbaseProvider();
const [screen, setScreen] = useState<"main" | "get-started">("main");
const walletConfig = props.walletConfig;
const locale = useTWLocale().wallets.injectedWallet(
walletConfig.metadata.name,
);

if (screen === "get-started") {
return (
<GetStartedScreen
locale={{
scanToDownload: locale.getStartedScreen.instruction,
}}
walletIconURL={walletConfig.metadata.iconUrl}
walletName={walletConfig.metadata.name}
chromeExtensionLink={links.chrome}
googlePlayStoreLink={links.android}
appleStoreLink={links.ios}
onBack={() => {
setScreen("main");
}}
/>
);
}

if (isInjected) {
return (
<InjectedConnectUI
{...props}
onGetStarted={() => {
setScreen("get-started");
}}
/>
);
}

return (
<CoinbaseSDKWalletConnectUI
connectUIProps={props}
onGetStarted={() => {
setScreen("get-started");
}}
/>
);
}

function CoinbaseSDKWalletConnectUI(props: {
connectUIProps: ConnectUIProps;
onGetStarted: () => void;
}) {
const { connectUIProps, onGetStarted } = props;
const locale = useTWLocale().wallets.injectedWallet(
connectUIProps.walletConfig.metadata.name,
);
const { createInstance, done, chainId } = connectUIProps;
const [qrCodeUri, setQrCodeUri] = useState<string | undefined>(undefined);

const scanStarted = useRef(false);

useEffect(() => {
if (scanStarted.current) {
return;
}

scanStarted.current = true;

(async () => {
const wallet = createInstance() as CoinbaseSDKWallet;

try {
await wallet.connect({
reloadOnDisconnect: false,
chainId,
onUri(uri) {
if (uri) {
setQrCodeUri(uri);
} else {
// show error
}
},
headlessMode: true,
});

done(wallet);
} catch {
// show error
}
})();
}, [chainId, createInstance, done]);

return (
<ScanScreen
qrScanInstruction={locale.scanScreen.instruction}
onBack={connectUIProps.screenConfig.goBack}
onGetStarted={onGetStarted}
qrCodeUri={qrCodeUri}
walletName={connectUIProps.walletConfig.metadata.name}
walletIconURL={connectUIProps.walletConfig.metadata.iconUrl}
getStartedLink={locale.getStartedLink}
/>
);
}
8 changes: 8 additions & 0 deletions packages/thirdweb/src/wallets/coinbase/coinbaseMetadata.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { WalletMetadata } from "../types.js";

export const coinbaseMetadata: WalletMetadata = {
id: "com.coinbase.wallet",
name: "Coinbase Wallet",
iconUrl:
"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDgiIGhlaWdodD0iNDgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4IiByeD0iOCIgZmlsbD0iIzA1NTVGRiIvPgo8ZyBjbGlwLXBhdGg9InVybCgjY2xpcDBfMzMwM184NjM0KSI+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTIuMzMxMiA0SDM1LjY2NzJDNDAuMjcwNCA0IDQ0IDguMDEyOCA0NCAxMi45NjMyVjM1LjAzNjhDNDQgMzkuOTg3MiA0MC4yNzA0IDQ0IDM1LjY2ODggNDRIMTIuMzMxMkM3LjcyOTYgNDQgNCAzOS45ODcyIDQgMzUuMDM2OFYxMi45NjMyQzQgOC4wMTI4IDcuNzI5NiA0IDEyLjMzMTIgNFoiIGZpbGw9IiMwMDUyRkYiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yNC4wMDAzIDkuNzkzNDZDMzEuODQ2NyA5Ljc5MzQ2IDM4LjIwNjcgMTYuMTUzNSAzOC4yMDY3IDIzLjk5OTlDMzguMjA2NyAzMS44NDYzIDMxLjg0NjcgMzguMjA2MyAyNC4wMDAzIDM4LjIwNjNDMTYuMTUzOSAzOC4yMDYzIDkuNzkzOTUgMzEuODQ2MyA5Ljc5Mzk1IDIzLjk5OTlDOS43OTM5NSAxNi4xNTM1IDE2LjE1MzkgOS43OTM0NiAyNC4wMDAzIDkuNzkzNDZaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTIwLjUwMDYgMTkuNDU5SDI3LjQ5NzRDMjguMDczNCAxOS40NTkgMjguNTM5IDE5Ljk2MTQgMjguNTM5IDIwLjU3OVYyNy40MTlDMjguNTM5IDI4LjAzODIgMjguMDcxOCAyOC41MzkgMjcuNDk3NCAyOC41MzlIMjAuNTAwNkMxOS45MjQ2IDI4LjUzOSAxOS40NTkgMjguMDM2NiAxOS40NTkgMjcuNDE5VjIwLjU3OUMxOS40NTkgMTkuOTYxNCAxOS45MjYyIDE5LjQ1OSAyMC41MDA2IDE5LjQ1OVoiIGZpbGw9IiMwMDUyRkYiLz4KPC9nPgo8ZGVmcz4KPGNsaXBQYXRoIGlkPSJjbGlwMF8zMzAzXzg2MzQiPgo8cmVjdCB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIGZpbGw9IndoaXRlIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg0IDQpIi8+CjwvY2xpcFBhdGg+CjwvZGVmcz4KPC9zdmc+Cg==",
};
Loading

0 comments on commit 994f033

Please sign in to comment.