Skip to content

Commit

Permalink
Added the ability to auto connect to a provider based on wallet rdns
Browse files Browse the repository at this point in the history
  • Loading branch information
dreamoftrees committed Apr 29, 2024
1 parent a0b8312 commit 2e54593
Show file tree
Hide file tree
Showing 9 changed files with 107 additions and 31 deletions.
2 changes: 2 additions & 0 deletions packages/checkout/sdk/src/types/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Web3Provider } from '@ethersproject/providers';
export enum WalletProviderName {
PASSPORT = 'passport',
METAMASK = 'metamask',
WALLETCONNECT = 'walletconnect',
}

/**
Expand All @@ -14,6 +15,7 @@ export enum WalletProviderName {
export enum WalletProviderRdns {
PASSPORT = 'com.immutable.passport',
METAMASK = 'io.metamask',
WALLETCONNECT = 'walletconnect',
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ChainId } from '../../../types';
import { ChainId, WalletProviderRdns } from '../../../types';
import { WidgetLanguage } from '../configurations';

export enum ConnectTargetLayer {
Expand All @@ -11,6 +11,8 @@ export type ConnectWidgetParams = {
language?: WidgetLanguage;
/** The target chain to connect to as part of the connection process (defaults to Immutable zkEVM / Immutable zkEVM Testnet) */
targetChainId?: ChainId;
/** The target wallet to establish a connection with */
targetWalletRdns?: string | WalletProviderRdns;
/** List of wallets rdns to exclude from the connect widget */
blocklistWalletRdns?: string[];
};
2 changes: 1 addition & 1 deletion packages/checkout/widgets-lib/src/lib/walletConnect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const walletConnectProviderInfo = {
rdns: 'walletconnect',
// eslint-disable-next-line max-len
icon: 'data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNDggNDgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGc+PHBhdGggZD0iTTEwLjQyMzYgMTQuODY4NkMxNy45NTA3IDcuNTIzNzcgMzAuMTY5NCA3LjUyMzc3IDM3LjY5NjQgMTQuODY4NkwzOC42MDI2IDE1Ljc1OTNDMzguOTgyNiAxNi4xMjQ0IDM4Ljk4MjYgMTYuNzIzMSAzOC42MDI2IDE3LjA4ODFMMzUuNTA0MSAyMC4xMTA4QzM1LjMxNDEgMjAuMzAwNiAzNS4wMDcxIDIwLjMwMDYgMzQuODE3MSAyMC4xMTA4TDMzLjU3NDggMTguODk4OEMyOC4zMTMyIDEzLjc3MzUgMTkuODA2OSAxMy43NzM1IDE0LjU0NTIgMTguODk4OEwxMy4yMTUyIDIwLjE5ODRDMTMuMDI1MiAyMC4zODgyIDEyLjcxODMgMjAuMzg4MiAxMi41MjgzIDIwLjE5ODRMOS40Mjk3OCAxNy4xNzU3QzkuMDQ5NzcgMTYuODEwNyA5LjA0OTc3IDE2LjIxMiA5LjQyOTc4IDE1Ljg0N0wxMC40MjM2IDE0Ljg2ODZaTTQ0LjExMjcgMjEuMTE4M0w0Ni44NzUgMjMuODA1MUM0Ny4yNTUgMjQuMTcwMSA0Ny4yNTUgMjQuNzY4OCA0Ni44NzUgMjUuMTMzOUwzNC40MzcxIDM3LjI2ODJDMzQuMDU3MSAzNy42MzMyIDMzLjQ0MzMgMzcuNjMzMiAzMy4wNzc5IDM3LjI2ODJMMjQuMjUgMjguNjUzQzI0LjE2MjMgMjguNTY1NCAyNC4wMDE2IDI4LjU2NTQgMjMuOTEzOSAyOC42NTNMMTUuMDg2IDM3LjI2ODJDMTQuNzA2IDM3LjYzMzIgMTQuMDkyMiAzNy42MzMyIDEzLjcyNjggMzcuMjY4MkwxLjI0NTAzIDI1LjEzMzlDMC44NjUwMiAyNC43Njg4IDAuODY1MDIgMjQuMTcwMSAxLjI0NTAzIDIzLjgwNTFMNC4wMDczOCAyMS4xMTgzQzQuMzg3MzkgMjAuNzUzMyA1LjAwMTI1IDIwLjc1MzMgNS4zNjY2NCAyMS4xMTgzTDE0LjE5NDUgMjkuNzMzNUMxNC4yODIyIDI5LjgyMTEgMTQuNDQyOSAyOS44MjExIDE0LjUzMDYgMjkuNzMzNUwyMy4zNTg1IDIxLjExODNDMjMuNzM4NSAyMC43NTMzIDI0LjM1MjMgMjAuNzUzMyAyNC43MTc3IDIxLjExODNMMzMuNTQ1NiAyOS43MzM1QzMzLjYzMzMgMjkuODIxMSAzMy43OTQgMjkuODIxMSAzMy44ODE3IDI5LjczMzVMNDIuNzA5NiAyMS4xMTgzQzQzLjExODggMjAuNzUzMyA0My43MzI3IDIwLjc1MzMgNDQuMTEyNyAyMS4xMTgzWiIgZmlsbD0iIzM2OEFGQSI+PC9wYXRoPjwvZz48L3N2Zz4=',
uuid: 'wallet-connect',
uuid: 'walletconnect',
} as EIP6963ProviderInfo;

export type WalletConnectConfiguration = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export default function ConnectWidget({
sendCloseEventOverride,
web3Provider,
checkout,
targetWalletRdns,
targetChainId,
allowedChains,
blocklistWalletRdns,
Expand Down Expand Up @@ -206,6 +207,7 @@ export default function ConnectWidget({
)}
{view.type === ConnectWidgetViews.CONNECT_WALLET && (
<ConnectWallet
targetWalletRdns={targetWalletRdns}
targetChainId={targetChain}
allowedChains={allowedChains ?? [targetChain]}
blocklistWalletRdns={blocklistWalletRdns}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export class Connect extends Base<WidgetType.CONNECT> {
<ConnectWidget
config={this.strongConfig()}
checkout={this.checkout}
targetWalletRdns={this.parameters.targetWalletRdns}
targetChainId={this.parameters.targetChainId}
blocklistWalletRdns={this.parameters.blocklistWalletRdns}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,37 +1,43 @@
import { useTranslation } from 'react-i18next';
import { MenuItem } from '@biom3/react';
import { useState } from 'react';
import { forwardRef, useImperativeHandle, useState } from 'react';
import { useWalletConnect } from '../../../lib/hooks/useWalletConnect';

export type WalletConnectItemProps = {
onConnect: () => void;
loading?: boolean;
};

export function WalletConnectItem({
export const WalletConnectItem = forwardRef(({
onConnect,
loading = false,
}: WalletConnectItemProps) {
}: WalletConnectItemProps, ref) => {
const { t } = useTranslation();
const { walletConnectBusy } = useWalletConnect();
const [busy, setBusy] = useState(false);

const connect = async () => {
if (loading) return;
setBusy(true);
// let the parent handle errors
try {
await onConnect();
} finally {
setBusy(false);
}
};

useImperativeHandle(ref, () => ({
connect,
}));

return (
<MenuItem
testId="wallet-list-walletconnect"
size="medium"
emphasized
disabled={walletConnectBusy}
onClick={async () => {
if (loading) return;
setBusy(true);
// let the parent handle errors
try {
await onConnect();
} finally {
setBusy(false);
}
}}
onClick={connect}
sx={{ marginBottom: 'base.spacing.x1' }}
>
<MenuItem.FramedLogo
Expand All @@ -53,4 +59,4 @@ export function WalletConnectItem({
))}
</MenuItem>
);
}
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
WalletProviderName, WalletProviderRdns,
} from '@imtbl/checkout-sdk';
import {
useCallback, useContext, useMemo, useState,
useCallback, useContext, useEffect, useMemo, useRef, useState,
} from 'react';
import { motion } from 'framer-motion';
import { useTranslation } from 'react-i18next';
Expand Down Expand Up @@ -39,14 +39,15 @@ import { BrowserWalletItem } from './BrowserWalletItem';
import { identifyUser } from '../../../lib/analytics/identifyUser';

export interface WalletListProps {
targetWalletRdns?: string;
targetChainId: ChainId;
allowedChains: ChainId[];
blocklistWalletRdns?: string[];
}

export function WalletList(props: WalletListProps) {
const { t } = useTranslation();
const { targetChainId, allowedChains } = props;
const { targetWalletRdns, targetChainId, allowedChains } = props;
const blocklistWalletRdns = props?.blocklistWalletRdns || [];
const {
connectDispatch,
Expand All @@ -57,7 +58,7 @@ export function WalletList(props: WalletListProps) {
const { providers } = useInjectedProviders({ checkout });
const [showWalletDrawer, setShowWalletDrawer] = useState(false);
const { isWalletConnectEnabled, openWalletConnectModal } = useWalletConnect();

const walletConnectItemRef = useRef(null);
const [showChangedYourMindDrawer, setShowChangedYourMindDrawer] = useState(false);
const [showUnableToConnectDrawer, setShowUnableToConnectDrawer] = useState(false);
const [chosenProviderDetail, setChosenProviderDetail] = useState<EIP6963ProviderDetail>();
Expand Down Expand Up @@ -261,6 +262,23 @@ export function WalletList(props: WalletListProps) {
setShowWalletDrawer(true);
}, [track]);

useEffect(() => {
// Auto-trigger wallet connection via rdns
if (targetWalletRdns && targetWalletRdns?.length > 0) {
if (targetWalletRdns === WalletProviderRdns.PASSPORT && passportProviderDetail) {
handleWalletItemClick(passportProviderDetail);
} if (targetWalletRdns === WalletProviderRdns.WALLETCONNECT && walletConnectItemRef.current) {
(walletConnectItemRef.current as any).connect();
} else {
const targetProviderDetail = filteredProviders
.find((providerDetail) => providerDetail.info.rdns === targetWalletRdns);
if (targetProviderDetail) {
handleWalletItemClick(targetProviderDetail);
}
}
}
}, [filteredProviders, targetWalletRdns]);

return (
<Box
testId="wallet-list"
Expand Down Expand Up @@ -319,7 +337,7 @@ export function WalletList(props: WalletListProps) {
key="walletconnect"
style={{ width: '100%' }}
>
<WalletConnectItem onConnect={handleWalletConnectConnection} />
<WalletConnectItem ref={walletConnectItemRef} onConnect={handleWalletConnectConnection} />
</motion.div>
)}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,18 @@ import { ConnectContext } from '../context/ConnectContext';
import { UserJourney, useAnalytics } from '../../../context/analytics-provider/SegmentAnalyticsProvider';

export interface ConnectWalletProps {
targetWalletRdns?: string,
targetChainId: ChainId;
allowedChains: ChainId[];
blocklistWalletRdns?: string[];
}

export function ConnectWallet({ targetChainId, allowedChains, blocklistWalletRdns }: ConnectWalletProps) {
export function ConnectWallet({
targetWalletRdns,
targetChainId,
allowedChains,
blocklistWalletRdns,
}: ConnectWalletProps) {
const { t } = useTranslation();
const {
connectState: { sendCloseEvent },
Expand Down Expand Up @@ -69,6 +75,7 @@ export function ConnectWallet({ targetChainId, allowedChains, blocklistWalletRdn
</Box>
<Box sx={{ paddingX: 'base.spacing.x2' }}>
<WalletList
targetWalletRdns={targetWalletRdns}
targetChainId={targetChainId}
allowedChains={allowedChains}
blocklistWalletRdns={blocklistWalletRdns}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import { useEffect, useMemo, useRef, useState } from 'react';

import {
Checkout,
WidgetType,
WidgetTheme,
ConnectEventType
} from '@imtbl/checkout-sdk';
import { useCallback, useEffect, useMemo, useState } from 'react';

import { Checkout, ConnectEventType, WalletProviderRdns, WidgetTheme, WidgetType } from '@imtbl/checkout-sdk';
import { Environment } from '@imtbl/config';
import { WidgetsFactory } from '@imtbl/checkout-widgets';

Expand All @@ -21,7 +16,18 @@ function ConnectUI() {

useEffect(() => {
(async () => {
setFactory(new WidgetsFactory(checkout, {theme: WidgetTheme.DARK}));
setFactory(new WidgetsFactory(checkout, {
theme: WidgetTheme.DARK,
walletConnect: {
projectId: '938b553484e344b1e0b4bb80edf8c362',
metadata: {
name: 'Checkout Marketplace',
description: 'Checkout Marketplace',
url: 'http://localhost:3000/marketplace-orchestrator',
icons: []
}
}
}));
})()
}, [checkout]);

Expand All @@ -34,7 +40,35 @@ function ConnectUI() {
connect.addListener(ConnectEventType.CLOSE_WIDGET, (data: any) => {
connect.unmount();
})
}, [connect])
}, [connect]);

const connectWC = useCallback(async () => {
if(!connect && !provider) return;
connect!.mount(CONNECT_TARGET_ID, {
targetWalletRdns: WalletProviderRdns.WALLETCONNECT,
});
}, [connect, provider, checkout]);

const connectMetaMask = useCallback(async () => {
if(!connect && !provider) return;
connect!.mount(CONNECT_TARGET_ID, {
targetWalletRdns: WalletProviderRdns.METAMASK,
});
}, [connect, provider, checkout]);

const connectPassport = useCallback(async () => {
if(!connect && !provider) return;
connect!.mount(CONNECT_TARGET_ID, {
targetWalletRdns: WalletProviderRdns.PASSPORT,
});
}, [connect, provider, checkout]);

const connectCoinbase = useCallback(async () => {
if(!connect && !provider) return;
connect!.mount(CONNECT_TARGET_ID, {
targetWalletRdns: 'com.coinbase.wallet'
});
}, [connect, provider, checkout]);

return (
<div>
Expand All @@ -46,6 +80,10 @@ function ConnectUI() {
<button onClick={() => connect?.update({ config: { language: 'ja'}})}>JA</button>
<button onClick={() => connect?.update({ config: { language: 'ko'}})}>KO</button>
<button onClick={() => connect?.update({ config: { language: 'zh'}})}>ZH</button>
<button onClick={() => connectMetaMask()}>Connect MetaMask</button>
<button onClick={() => connectWC()}>Connect WC</button>
<button onClick={() => connectPassport()}>Connect Passport</button>
<button onClick={() => connectCoinbase()}>Connect Coinbase</button>
</div>
);
}
Expand Down

0 comments on commit 2e54593

Please sign in to comment.