diff --git a/packages/checkout/widgets-lib/src/components/Hero/WalletWarningHero.tsx b/packages/checkout/widgets-lib/src/components/Hero/WalletWarningHero.tsx
new file mode 100644
index 0000000000..9402cedec5
--- /dev/null
+++ b/packages/checkout/widgets-lib/src/components/Hero/WalletWarningHero.tsx
@@ -0,0 +1,174 @@
+/* eslint-disable max-len */
+import { Box } from '@biom3/react';
+
+export function WalletWarningHero() {
+ return (
+
+
+
+ );
+}
diff --git a/packages/checkout/widgets-lib/src/locales/en.json b/packages/checkout/widgets-lib/src/locales/en.json
index 9ce6eaa2a8..12ebc00836 100644
--- a/packages/checkout/widgets-lib/src/locales/en.json
+++ b/packages/checkout/widgets-lib/src/locales/en.json
@@ -7,6 +7,12 @@
},
"walletSelection": {
"heading": "Choose a wallet"
+ },
+ "nonPassportDrawer": {
+ "heading": "Non-Passport users will need IMX for gas.",
+ "body1": "We recommend using Layerswap to bridge funds onto Immutable zkEVM, with refuel switched on so you receive some IMX.",
+ "body2": "Alternatively, pay and play easily with a gas free Immutable Passport.",
+ "buttonText": "Proceed anyway"
}
},
"CONNECT_SUCCESS": {
diff --git a/packages/checkout/widgets-lib/src/locales/ja.json b/packages/checkout/widgets-lib/src/locales/ja.json
index 4edebbaa72..c1e8258e12 100644
--- a/packages/checkout/widgets-lib/src/locales/ja.json
+++ b/packages/checkout/widgets-lib/src/locales/ja.json
@@ -7,7 +7,13 @@
},
"walletSelection": {
"heading": "ウォレットを選択"
- }
+ },
+ "nonPassportDrawer": {
+ "heading": "パスポート未使用者はガス代としてIMXが必要です。",
+ "body1": "資金をImmutable zkEVMにブリッジするには、Layerswapの使用をお勧めします。リファエルをオンにしてIMXを受け取ります。",
+ "body2": "または、ガス無料のImmutable Passportで簡単に支払いとプレイができます。",
+ "buttonText": "それでも進む"
+ }
},
"CONNECT_SUCCESS": {
"status": "接続が安全です",
diff --git a/packages/checkout/widgets-lib/src/locales/ko.json b/packages/checkout/widgets-lib/src/locales/ko.json
index 662e01acf0..b6a61389c3 100644
--- a/packages/checkout/widgets-lib/src/locales/ko.json
+++ b/packages/checkout/widgets-lib/src/locales/ko.json
@@ -7,6 +7,12 @@
},
"walletSelection": {
"heading": "지갑 선택"
+ },
+ "nonPassportDrawer": {
+ "heading": "비 패스포트 사용자는 가스 비용으로 IMX가 필요합니다.",
+ "body1": "자금을 Immutable zkEVM으로 브리징하기 위해 Layerswap을 사용하는 것을 권장합니다. 리퓨엘이 켜져 있으면 IMX를 받을 수 있습니다.",
+ "body2": "또는 가스 비용이 없는 Immutable Passport로 쉽게 결제하고 플레이하세요.",
+ "buttonText": "어쨌든 진행"
}
},
"CONNECT_SUCCESS": {
diff --git a/packages/checkout/widgets-lib/src/locales/zh.json b/packages/checkout/widgets-lib/src/locales/zh.json
index 01633ba3bc..49ff1a9511 100644
--- a/packages/checkout/widgets-lib/src/locales/zh.json
+++ b/packages/checkout/widgets-lib/src/locales/zh.json
@@ -7,6 +7,12 @@
},
"walletSelection": {
"heading": "选择一个钱包"
+ },
+ "nonPassportDrawer": {
+ "heading": "非Passport用户需要IMX来支付燃气费。",
+ "body1": "我们建议使用Layerswap将资金桥接到Immutable zkEVM,并打开加油功能,以便您能收到一些IMX。",
+ "body2": "或者,可以使用免燃气费的Immutable Passport轻松支付和玩游戏。",
+ "buttonText": "继续操作"
}
},
"CONNECT_SUCCESS": {
diff --git a/packages/checkout/widgets-lib/src/widgets/connect/components/NonPassportWarningDrawer.tsx b/packages/checkout/widgets-lib/src/widgets/connect/components/NonPassportWarningDrawer.tsx
new file mode 100644
index 0000000000..568d005446
--- /dev/null
+++ b/packages/checkout/widgets-lib/src/widgets/connect/components/NonPassportWarningDrawer.tsx
@@ -0,0 +1,101 @@
+import {
+ Body,
+ Box,
+ ButtCon,
+ Button,
+ Drawer,
+ Heading,
+ Link,
+} from '@biom3/react';
+import { Trans, useTranslation } from 'react-i18next';
+import { WalletWarningHero } from 'components/Hero/WalletWarningHero';
+
+export function NonPassportWarningDrawer({
+ visible,
+ onCloseDrawer,
+ handleCtaButtonClick,
+}: {
+ visible: boolean;
+ onCloseDrawer: () => void;
+ handleCtaButtonClick: () => void;
+}) {
+ const { t } = useTranslation();
+
+ return (
+
+
+
+
+
+
+ {t('views.CONNECT_WALLET.nonPassportDrawer.heading')}
+
+
+
+ )}
+ />
+ ),
+ }}
+ />
+
+
+ {t('views.CONNECT_WALLET.nonPassportDrawer.body2')}
+
+
+
+
+
+
+
+ );
+}
diff --git a/packages/checkout/widgets-lib/src/widgets/connect/components/WalletList.tsx b/packages/checkout/widgets-lib/src/widgets/connect/components/WalletList.tsx
index f28a2a17ec..34c8eb3839 100644
--- a/packages/checkout/widgets-lib/src/widgets/connect/components/WalletList.tsx
+++ b/packages/checkout/widgets-lib/src/widgets/connect/components/WalletList.tsx
@@ -1,11 +1,18 @@
import { Box } from '@biom3/react';
import {
ChainId,
- CheckoutErrorType, EIP6963ProviderDetail,
- WalletProviderName, WalletProviderRdns,
+ CheckoutErrorType,
+ EIP6963ProviderDetail,
+ WalletProviderName,
+ WalletProviderRdns,
} from '@imtbl/checkout-sdk';
import {
- useCallback, useContext, useEffect, useMemo, useRef, useState,
+ useCallback,
+ useContext,
+ useEffect,
+ useMemo,
+ useRef,
+ useState,
} from 'react';
import { motion } from 'framer-motion';
import { useTranslation } from 'react-i18next';
@@ -31,12 +38,16 @@ import {
isPassportProvider,
} from '../../../lib/provider';
import { addProviderListenersForWidgetRoot, getL1ChainId } from '../../../lib';
-import { listItemVariants, listVariants } from '../../../lib/animation/listAnimation';
+import {
+ listItemVariants,
+ listVariants,
+} from '../../../lib/animation/listAnimation';
import { WalletDrawer } from '../../../components/WalletDrawer/WalletDrawer';
import { WalletChangeEvent } from '../../../components/WalletDrawer/WalletDrawerEvents';
import { WalletConnectItem } from './WalletConnectItem';
import { BrowserWalletItem } from './BrowserWalletItem';
import { identifyUser } from '../../../lib/analytics/identifyUser';
+import { NonPassportWarningDrawer } from './NonPassportWarningDrawer';
export interface WalletListProps {
targetWalletRdns?: string;
@@ -61,43 +72,59 @@ export function WalletList(props: WalletListProps) {
const walletConnectItemRef = useRef(null);
const [showChangedYourMindDrawer, setShowChangedYourMindDrawer] = useState(false);
const [showUnableToConnectDrawer, setShowUnableToConnectDrawer] = useState(false);
+ const [showNonPassportWarning, setShowNonPassportWarning] = useState(false);
const [chosenProviderDetail, setChosenProviderDetail] = useState();
- const filteredProviders = useMemo(() => (
- providers
- .filter((provider) => (!(provider.info.rdns === WalletProviderRdns.PASSPORT)))
- .filter((provider) => (!blocklistWalletRdns.includes(provider.info.rdns)))
- ), [providers]);
+ const filteredProviders = useMemo(
+ () => providers
+ .filter(
+ (provider) => !(provider.info.rdns === WalletProviderRdns.PASSPORT),
+ )
+ .filter(
+ (provider) => !blocklistWalletRdns.includes(provider.info.rdns),
+ ),
+ [providers],
+ );
// Don't allow Passport if targetChainId is L1
- const passportProviderDetail = useMemo(() => (
- targetChainId !== getL1ChainId(checkout!.config)
- && providers
- .filter((provider) => (!blocklistWalletRdns.includes(provider.info.rdns)))
- .find((provider) => provider.info.rdns === WalletProviderRdns.PASSPORT)
- ), [providers, checkout]);
-
- const selectWeb3Provider = useCallback((web3Provider: Web3Provider, providerName: string) => {
- connectDispatch({
- payload: {
- type: ConnectActions.SET_PROVIDER,
- provider: web3Provider,
- },
- });
- connectDispatch({
- payload: {
- type: ConnectActions.SET_WALLET_PROVIDER_NAME,
- walletProviderName: providerName as WalletProviderName,
- },
- });
- }, []);
+ const passportProviderDetail = useMemo(
+ () => targetChainId !== getL1ChainId(checkout!.config)
+ && providers
+ .filter((provider) => !blocklistWalletRdns.includes(provider.info.rdns))
+ .find((provider) => provider.info.rdns === WalletProviderRdns.PASSPORT),
+ [providers, checkout],
+ );
+
+ const selectWeb3Provider = useCallback(
+ (web3Provider: Web3Provider, providerName: string) => {
+ connectDispatch({
+ payload: {
+ type: ConnectActions.SET_PROVIDER,
+ provider: web3Provider,
+ },
+ });
+ connectDispatch({
+ payload: {
+ type: ConnectActions.SET_WALLET_PROVIDER_NAME,
+ walletProviderName: providerName as WalletProviderName,
+ },
+ });
+ },
+ [],
+ );
const handleConnectViewUpdate = async (provider: Web3Provider) => {
const isPassport = isPassportProvider(provider);
- const chainId = await provider.provider.request!({ method: 'eth_chainId', params: [] });
+ const chainId = await provider.provider.request!({
+ method: 'eth_chainId',
+ params: [],
+ });
// eslint-disable-next-line radix
const parsedChainId = parseInt(chainId.toString());
- if (parsedChainId !== targetChainId && !allowedChains?.includes(parsedChainId)) {
+ if (
+ parsedChainId !== targetChainId
+ && !allowedChains?.includes(parsedChainId)
+ ) {
// TODO: What do we do with Passport here as it can't connect to L1
if (isPassport) {
viewDispatch({
@@ -125,50 +152,53 @@ export function WalletList(props: WalletListProps) {
});
};
- const selectProviderDetail = useCallback(async (providerDetail: EIP6963ProviderDetail) => {
- if (!checkout) return;
-
- try {
- const isMetaMask = providerDetail.info.rdns === WalletProviderRdns.METAMASK;
- const web3Provider = new Web3Provider(providerDetail.provider as any);
+ const selectProviderDetail = useCallback(
+ async (providerDetail: EIP6963ProviderDetail) => {
+ if (!checkout) return;
try {
- // TODO: Find a nice way to detect if the wallet supports switching accounts via requestPermissions
- const changeAccount = isMetaMask;
- const connectResult = await checkout.connect({
- provider: web3Provider,
- requestWalletPermissions: changeAccount,
- });
+ const isMetaMask = providerDetail.info.rdns === WalletProviderRdns.METAMASK;
+ const web3Provider = new Web3Provider(providerDetail.provider as any);
- // Set up EIP-1193 provider event listeners for widget root instances
- addProviderListenersForWidgetRoot(connectResult.provider);
- await identifyUser(identify, connectResult.provider);
+ try {
+ // TODO: Find a nice way to detect if the wallet supports switching accounts via requestPermissions
+ const changeAccount = isMetaMask;
+ const connectResult = await checkout.connect({
+ provider: web3Provider,
+ requestWalletPermissions: changeAccount,
+ });
- selectWeb3Provider(
- web3Provider,
- getProviderSlugFromRdns(providerDetail.info.rdns),
- );
- await handleConnectViewUpdate(web3Provider);
- } catch (err: CheckoutErrorType | any) {
- if (err.type === CheckoutErrorType.USER_REJECTED_REQUEST_ERROR) {
- // eslint-disable-next-line no-console
- console.error('Connect rejected', err);
+ // Set up EIP-1193 provider event listeners for widget root instances
+ addProviderListenersForWidgetRoot(connectResult.provider);
+ await identifyUser(identify, connectResult.provider);
+
+ selectWeb3Provider(
+ web3Provider,
+ getProviderSlugFromRdns(providerDetail.info.rdns),
+ );
+ await handleConnectViewUpdate(web3Provider);
+ } catch (err: CheckoutErrorType | any) {
+ if (err.type === CheckoutErrorType.USER_REJECTED_REQUEST_ERROR) {
+ // eslint-disable-next-line no-console
+ console.error('Connect rejected', err);
- setShowChangedYourMindDrawer(true);
- } else {
- // eslint-disable-next-line no-console
- console.error('Connect error', err);
+ setShowChangedYourMindDrawer(true);
+ } else {
+ // eslint-disable-next-line no-console
+ console.error('Connect error', err);
- setShowUnableToConnectDrawer(true);
+ setShowUnableToConnectDrawer(true);
+ }
}
- }
- } catch (err: any) {
- // eslint-disable-next-line no-console
- console.error('Connect unknown error', err);
+ } catch (err: any) {
+ // eslint-disable-next-line no-console
+ console.error('Connect unknown error', err);
- setShowUnableToConnectDrawer(true);
- }
- }, [checkout]);
+ setShowUnableToConnectDrawer(true);
+ }
+ },
+ [checkout],
+ );
const connectCallback = async (ethereumProvider) => {
if (ethereumProvider.connected && ethereumProvider.session) {
@@ -228,6 +258,17 @@ export function WalletList(props: WalletListProps) {
const handleWalletItemClick = useCallback(
async (providerDetail: EIP6963ProviderDetail) => {
+ const isPassport = providerDetail.info.rdns === WalletProviderRdns.PASSPORT;
+ const hasSeenNonPassportWarning = localStorage.getItem(
+ 'hasSeenNonPassportWarning',
+ );
+
+ if (!isPassport && !hasSeenNonPassportWarning) {
+ setChosenProviderDetail(providerDetail);
+ setShowNonPassportWarning(true);
+ return;
+ }
+
setShowChangedYourMindDrawer(false);
setShowUnableToConnectDrawer(false);
setChosenProviderDetail(providerDetail);
@@ -265,13 +306,20 @@ export function WalletList(props: WalletListProps) {
useEffect(() => {
// Auto-trigger wallet connection via rdns
if (targetWalletRdns && targetWalletRdns?.length > 0) {
- if (targetWalletRdns === WalletProviderRdns.PASSPORT && passportProviderDetail) {
+ if (
+ targetWalletRdns === WalletProviderRdns.PASSPORT
+ && passportProviderDetail
+ ) {
handleWalletItemClick(passportProviderDetail);
- } else if (targetWalletRdns === WalletProviderRdns.WALLETCONNECT && walletConnectItemRef.current) {
+ } else if (
+ targetWalletRdns === WalletProviderRdns.WALLETCONNECT
+ && walletConnectItemRef.current
+ ) {
(walletConnectItemRef.current as any).connect();
} else {
- const targetProviderDetail = filteredProviders
- .find((providerDetail) => providerDetail.info.rdns === targetWalletRdns);
+ const targetProviderDetail = filteredProviders.find(
+ (providerDetail) => providerDetail.info.rdns === targetWalletRdns,
+ );
if (targetProviderDetail) {
handleWalletItemClick(targetProviderDetail);
}
@@ -279,16 +327,20 @@ export function WalletList(props: WalletListProps) {
}
}, [filteredProviders, targetWalletRdns]);
+ const handleNonPassportWarningDrawerButtonClick = async () => {
+ if (chosenProviderDetail) {
+ localStorage.setItem('hasSeenNonPassportWarning', 'true');
+ setShowNonPassportWarning(false);
+ await selectProviderDetail(chosenProviderDetail);
+ }
+ };
+
return (
- )}
+ rc={
+
+ }
sx={walletListStyle}
>
{passportProviderDetail && (
@@ -327,17 +379,27 @@ export function WalletList(props: WalletListProps) {
key="browserwallet"
style={{ width: '100%' }}
>
-
+
)}
{isWalletConnectEnabled && (
0 ? 1 : 0)}
+ custom={
+ 0
+ + (passportProviderDetail ? 1 : 0)
+ + (filteredProviders.length > 0 ? 1 : 0)
+ }
key="walletconnect"
style={{ width: '100%' }}
>
-
+
)}
@@ -369,6 +431,12 @@ export function WalletList(props: WalletListProps) {
onCloseDrawer={() => setShowUnableToConnectDrawer(false)}
onTryAgain={() => setShowUnableToConnectDrawer(false)}
/>
+
+ setShowNonPassportWarning(false)}
+ handleCtaButtonClick={handleNonPassportWarningDrawerButtonClick}
+ />
);
}