Skip to content

Commit

Permalink
feat: [WT-2192] Checkout widgets support for browser wallets via EIP-…
Browse files Browse the repository at this point in the history
…6963 (#1576)
  • Loading branch information
dreamoftrees authored Mar 7, 2024
1 parent 1ef5819 commit 0c44c10
Show file tree
Hide file tree
Showing 17 changed files with 347 additions and 122 deletions.
9 changes: 8 additions & 1 deletion packages/checkout/sdk/src/types/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,13 @@ export type OnRampConfig = {
export type ConnectConfig = {
/** A boolean value for enabling/disabling WalletConnect */
walletConnect: boolean;
/** A configuration for injected wallets */
injected: {
/** List for sorting injected wallets via wallet rdns */
priorityWalletRdns: string[];
/** List for blocking injected wallets via wallet rdns */
blacklistWalletRdns: string[];
}
};

/**
Expand Down Expand Up @@ -236,7 +243,7 @@ export type ChainsTokensConfig = {
* @property {boolean | undefined} blockscout -
*/
export type ChainTokensConfig = {
/** List of allowed tokens for a given chain. */
/** List of allowed tokens for a given chain. */
allowed?: TokenInfo[];
/** Feature flag to enable/disable blockscout integration. */
blockscout?: boolean;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { Box, useConvertSxToEmotionStyles } from '@biom3/react';
import { Box, BoxProps, useConvertSxToEmotionStyles } from '@biom3/react';
import { imageStyles, rawImageStyles } from './RawImageStyles';

export interface RawImageProps {
export type RawImageProps = {
src: string;
alt: string;
sx?: any;
}
} & BoxProps;

export function RawImage({
src,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const rawImageStyles = {
};

export const imageStyles = {
width: '32px',
width: 'auto',
height: '100%',
objectFit: 'contain',
objectPosition: '50% 50%',
Expand Down
17 changes: 17 additions & 0 deletions packages/checkout/widgets-lib/src/lib/animation/listAnimation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export const listVariants = {
hidden: { opacity: 0 },
show: { opacity: 1 },
};

export const listItemVariants = {
hidden: { y: 8, opacity: 0 },
show: (i) => ({
y: 0,
opacity: 1,
transition: {
delay: i * 0.1,
duration: 0.2,
ease: 'easeOut',
},
}),
};
24 changes: 0 additions & 24 deletions packages/checkout/widgets-lib/src/lib/hooks/useAnimation.ts

This file was deleted.

66 changes: 39 additions & 27 deletions packages/checkout/widgets-lib/src/lib/hooks/useInjectedProviders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,40 +12,35 @@ export interface UseInjectedProvidersParams {
checkout: Checkout | null;
}

type ConnectConfig = {
injected: {
priorityWalletRdns: WalletProviderRdns | string[];
blacklistWalletRdns: WalletProviderRdns | string[];
};
};

let passportWeb3Provider: Web3Provider;
const processProviders = (checkout: Checkout | null, injectedProviders: EIP6963ProviderDetail<EIP1193Provider>[]) => {
// Apply wallet providers allowlist
const allowedWalletRdns = [
'com.immutable.passport', // Immutable Passport
'io.metamask', // MetaMask
// 'xyz.frontier.wallet', // Frontier
// 'me.rainbow', // Rainbow
// 'com.coinbase.wallet', // Coinbase Wallet
];
const uniqueRdnsSet = new Set();
const processProviders = (
checkout: Checkout | null,
injectedProviders: EIP6963ProviderDetail<EIP1193Provider>[],
priorityWalletRdns: WalletProviderRdns | string[] = [],
blacklistWalletRdns: WalletProviderRdns | string[] = [],
) => {
// Filter providers
const filteredProviders = injectedProviders
.filter((provider) => {
if (allowedWalletRdns.includes(provider.info.rdns)) {
if (!uniqueRdnsSet.has(provider.info.rdns)) {
uniqueRdnsSet.add(provider.info.rdns);
return true;
}
}

return false;
})
.filter((provider) => !blacklistWalletRdns.includes(provider.info.rdns))
.sort((a, b) => {
// Get the index of the rdns for each provider
const indexA = allowedWalletRdns.indexOf(a.info.rdns);
const indexB = allowedWalletRdns.indexOf(b.info.rdns);
let indexA = priorityWalletRdns.indexOf(a.info.rdns);
if (indexA < 0) indexA = 999;
let indexB = priorityWalletRdns.indexOf(b.info.rdns);
if (indexB < 0) indexB = 999;

// Sort based on the index
return indexA - indexB;
});

// Add passport from checkout config if not from injected providers
if (checkout?.passport
&& allowedWalletRdns.includes(WalletProviderRdns.PASSPORT)
// && priorityWalletRdns.includes(WalletProviderRdns.PASSPORT) TODO: // Uncomment this when config JSON is updated
&& !filteredProviders.some((provider) => provider.info.rdns === WalletProviderRdns.PASSPORT)) {
if (!passportWeb3Provider) {
passportWeb3Provider = new Web3Provider(checkout.passport.connectEvm());
Expand All @@ -57,12 +52,21 @@ const processProviders = (checkout: Checkout | null, injectedProviders: EIP6963P
};

/**
* Hook that supplies a filters and sorted list of EIP-6963 injected providers.
* Hook that supplies a sorted list of EIP-6963 injected providers.
*/
export const useInjectedProviders = ({ checkout }: UseInjectedProvidersParams) => {
let defaultPriorityWalletRdns: WalletProviderRdns | string[] = [];
let defaultBlacklistWalletRdns: WalletProviderRdns | string[] = [];
(async () => {
const connectConfig = await checkout?.config.remote.getConfig('connect') as ConnectConfig;
defaultPriorityWalletRdns = connectConfig.injected?.priorityWalletRdns ?? [];
defaultBlacklistWalletRdns = connectConfig.injected?.blacklistWalletRdns ?? [];
})();
const defaultProviders = processProviders(
checkout,
InjectedProvidersManager.getInstance().getProviders(),
defaultPriorityWalletRdns,
defaultBlacklistWalletRdns,
);
const [providers, setProviders] = useState<EIP6963ProviderDetail[]>(
defaultProviders,
Expand All @@ -76,7 +80,15 @@ export const useInjectedProviders = ({ checkout }: UseInjectedProvidersParams) =
const cancelSubscription = InjectedProvidersManager
.getInstance()
.subscribe(async (injectedProviders: EIP6963ProviderDetail[]) => {
const filteredProviders = processProviders(checkout, injectedProviders);
const connectConfig = await checkout?.config.remote.getConfig('connect') as ConnectConfig;
const priorityWalletRdns = connectConfig.injected?.priorityWalletRdns ?? [];
const blacklistWalletRdns = connectConfig.injected?.blacklistWalletRdns ?? [];
const filteredProviders = processProviders(
checkout,
injectedProviders,
priorityWalletRdns,
blacklistWalletRdns,
);
setProviders(filteredProviders);
});

Expand Down
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 @@ -138,7 +138,7 @@ export class WalletConnectManager {
chains: this.environment === Environment.PRODUCTION ? productionModalChains : testnetModalChains,
explorerRecommendedWalletIds: this.environment === Environment.PRODUCTION
? productionWalletWhitelist : sandboxWalletWhitelist,
explorerExcludedWalletIds: 'ALL',
explorerExcludedWalletIds: undefined, // 'ALL',
themeMode: this.theme,
themeVariables: this.theme === WidgetTheme.DARK ? darkThemeVariables : lightThemeVariables,
});
Expand Down
9 changes: 8 additions & 1 deletion packages/checkout/widgets-lib/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
"body": {
"heading": "Connect a wallet",
"content": "You'll need to connect or create a digital wallet to buy, sell, trade and store your coins and collectibles."
},
"walletSelection": {
"heading": "Choose a wallet"
}
},
"CONNECT_SUCCESS": {
Expand Down Expand Up @@ -543,7 +546,11 @@
},
"walletconnect": {
"heading": "Other wallets",
"description": "Allows you to connect with any blockchain wallet including MetaMask"
"description": "Allows you to connect with any blockchain mobile wallet including MetaMask"
},
"browserwallet": {
"heading": "Browser wallets",
"description": "Digital wallet for accessing blockchain applications and web3"
}
},
"drawers": {
Expand Down
7 changes: 7 additions & 0 deletions packages/checkout/widgets-lib/src/locales/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
"body": {
"heading": "ウォレットを接続する",
"content": "購入、販売、取引、およびコインとコレクティブルを保存するには、デジタルウォレットを接続または作成する必要があります。"
},
"walletSelection": {
"heading": "ウォレットを選択"
}
},
"CONNECT_SUCCESS": {
Expand Down Expand Up @@ -551,6 +554,10 @@
"walletconnect": {
"heading": "その他のウォレット",
"description": "MetaMaskを含む任意のブロックチェーンウォレットに接続できます"
},
"browserwallet": {
"heading": "ブラウザウォレット",
"description": "ブロックチェーンアプリケーションおよびweb3にアクセスするためのデジタルウォレット"
}
},
"drawers": {
Expand Down
7 changes: 7 additions & 0 deletions packages/checkout/widgets-lib/src/locales/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
"body": {
"heading": "지갑 연결",
"content": "구매, 판매, 거래 및 코인과 수집품을 저장하려면 디지털 지갑을 연결하거나 만들어야 합니다."
},
"walletSelection": {
"heading": "지갑 선택"
}
},
"CONNECT_SUCCESS": {
Expand Down Expand Up @@ -544,6 +547,10 @@
"walletconnect": {
"heading": "기타 지갑",
"description": "MetaMask를 포함한 모든 블록체인 지갑에 연결할 수 있습니다"
},
"browserwallet": {
"heading": "브라우저 지갑",
"description": "블록체인 애플리케이션 및 web3에 접근하기 위한 디지털 지갑"
}
},
"drawers": {
Expand Down
7 changes: 7 additions & 0 deletions packages/checkout/widgets-lib/src/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
"body": {
"heading": "连接钱包",
"content": "您需要连接或创建数字钱包以购买、出售、交易和存储您的硬币和收藏品。"
},
"walletSelection": {
"heading": "选择一个钱包"
}
},
"CONNECT_SUCCESS": {
Expand Down Expand Up @@ -544,6 +547,10 @@
"walletconnect": {
"heading": "其他钱包",
"description": "允许您连接到包括MetaMask在内的任何区块链钱包"
},
"browserwallet": {
"heading": "浏览器钱包",
"description": "用于访问区块链应用和web3的数字钱包"
}
},
"drawers": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,18 @@ import { motion } from 'framer-motion';
import { WalletItem } from './WalletItem';
import { walletItemListStyles } from './WalletDrawerStyles';
import { WalletConnectItem } from './WalletConnectItem';
import { useAnimation } from '../../../lib/hooks/useAnimation';
import { useWalletConnect } from '../../../lib/hooks/useWalletConnect';
import { WalletChangeEvent } from './WalletDrawerEvents';
import { EIP1193Provider, EIP6963ProviderDetail, walletConnectProviderInfo } from '../../../lib/provider';
import { listItemVariants, listVariants } from '../../../lib/animation/listAnimation';

interface WalletDrawerProps {
testId: string;
drawerText: {
heading: string;
defaultText?: string;
},
showWalletConnect?: boolean;
showWalletSelectorTarget: boolean;
walletOptions: EIP6963ProviderDetail<EIP1193Provider>[];
showDrawer: boolean;
Expand All @@ -26,14 +27,14 @@ export function WalletDrawer({
testId,
drawerText,
walletOptions,
showWalletConnect = true,
showWalletSelectorTarget,
showDrawer,
setShowDrawer,
onWalletChange,
}: WalletDrawerProps) {
const { isWalletConnectEnabled, openWalletConnectModal } = useWalletConnect();
const [walletItemLoading, setWalletItemLoading] = useState(false);
const { listVariants, listItemVariants } = useAnimation();
const { heading, defaultText } = drawerText;

const handleWalletItemClick = async (providerDetail: EIP6963ProviderDetail<EIP1193Provider>) => {
Expand Down Expand Up @@ -124,7 +125,7 @@ export function WalletDrawer({
)}
/>
))}
{isWalletConnectEnabled && (
{isWalletConnectEnabled && showWalletConnect && (
<motion.div
variants={listItemVariants}
custom={walletOptions.length}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ export const walletItemListStyles = {
flexDirection: 'column',
gap: 'base.spacing.x1',
paddingX: 'base.spacing.x4',
mb: 'base.spacing.x4',
};
Loading

0 comments on commit 0c44c10

Please sign in to comment.