@imtbl/checkout-widgets 2.24.4 → 2.24.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/{AddTokensWidget-DuUFROT3.js → AddTokensWidget-DtKOUsGu.js} +3 -3
- package/dist/browser/{BridgeWidget-hq-FrbN3.js → BridgeWidget-BEyIilgs.js} +7 -7
- package/dist/browser/{CommerceWidget-DWiMfCWY.js → CommerceWidget-lHiaZb79.js} +13 -13
- package/dist/browser/{FeesBreakdown-qdVxOL0i.js → FeesBreakdown-CGoQZNw_.js} +1 -1
- package/dist/browser/{OnRampWidget-Bdiw7ATC.js → OnRampWidget-XiCeV2Y1.js} +3 -3
- package/dist/browser/{SaleWidget-hjvQ_UrC.js → SaleWidget-wg7122ny.js} +10 -10
- package/dist/browser/{SpendingCapHero-B1igTsUC.js → SpendingCapHero-50L-8e0O.js} +1 -1
- package/dist/browser/{SwapWidget-DhwWytog.js → SwapWidget-DyRGb56t.js} +7 -8
- package/dist/browser/{TokenImage-CGWnVL_Z.js → TokenImage-BSEcsGPt.js} +1 -1
- package/dist/browser/{TopUpView-BZxdHU6y.js → TopUpView-BruGxwia.js} +1 -1
- package/dist/browser/{WalletApproveHero-Btpgg9el.js → WalletApproveHero-BNeRqb6c.js} +46 -20
- package/dist/browser/{WalletWidget-C07lsS9H.js → WalletWidget-Qucp_iny.js} +3 -3
- package/dist/browser/{auto-track-DIuUVS9U.js → auto-track-YBHEPAZ3.js} +1 -1
- package/dist/browser/{index-BI3HRAbF.js → index-B_AfOz3m.js} +1 -1
- package/dist/browser/{index-CX_Q0bB9.js → index-BuHtApNC.js} +1 -1
- package/dist/browser/{index-BViG2No5.js → index-C1C2zjQB.js} +1 -1
- package/dist/browser/{index-fALsJci7.js → index-CZghGU-d.js} +54 -27
- package/dist/browser/{index-DHwKjlaG.js → index-DRpwE8WW.js} +1 -1
- package/dist/browser/{index-MXd6hJdY.js → index-Do4ES1-4.js} +2 -2
- package/dist/browser/{index-DAKBWys4.js → index-DqtCQcyE.js} +1 -1
- package/dist/browser/{index-BQfU8gia.js → index-DtCucxzi.js} +1 -1
- package/dist/browser/index.js +1 -1
- package/dist/browser/{index.umd-BcJ3xskH.js → index.umd-CjyGntCd.js} +1 -1
- package/dist/browser/{useInterval-CqSdWQaT.js → useInterval-C-BIKYov.js} +1 -1
- package/dist/types/lib/chains.d.ts +15 -0
- package/package.json +7 -7
- package/src/components/NetworkSwitchDrawer/NetworkSwitchDrawer.tsx +50 -30
- package/src/lib/chains.test.ts +42 -1
- package/src/lib/chains.ts +21 -0
- package/src/locales/en.json +8 -1
- package/src/widgets/bridge/components/BridgeReviewSummary.tsx +2 -1
- package/src/widgets/connect/components/WalletList.tsx +3 -3
- package/src/widgets/connect/views/ReadyToConnect.tsx +3 -3
- package/src/widgets/connect/views/SwitchNetworkZkEVM.tsx +3 -3
- package/src/widgets/swap/components/SwapForm.tsx +2 -2
package/src/lib/chains.test.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { ChainId, ChainName, ChainSlug } from '@imtbl/checkout-sdk';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
getChainIdBySlug, getChainNameById, getChainSlugById, parseChainId,
|
|
4
|
+
} from './chains';
|
|
3
5
|
|
|
4
6
|
describe('getChainNameById', () => {
|
|
5
7
|
const tests = [
|
|
@@ -48,3 +50,42 @@ describe('getChainIdBySlug', () => {
|
|
|
48
50
|
});
|
|
49
51
|
});
|
|
50
52
|
});
|
|
53
|
+
|
|
54
|
+
describe('parseChainId', () => {
|
|
55
|
+
// Regression: a lint autofix once rewrote `parseInt(chainId)` to
|
|
56
|
+
// `parseInt(chainId, 10)`, which returns 0 for the hex values EIP-695
|
|
57
|
+
// mandates. Every chain then read as "wrong network" and the bridge became
|
|
58
|
+
// unusable. These cases pin the hex handling down.
|
|
59
|
+
const hexCases = [
|
|
60
|
+
{ value: '0x343b', expected: ChainId.IMTBL_ZKEVM_MAINNET },
|
|
61
|
+
{ value: '0x34a1', expected: ChainId.IMTBL_ZKEVM_TESTNET },
|
|
62
|
+
{ value: '0x1', expected: ChainId.ETHEREUM },
|
|
63
|
+
{ value: '0xaa36a7', expected: ChainId.SEPOLIA },
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
hexCases.forEach(({ value, expected }) => {
|
|
67
|
+
it(`should parse hex ${value} as ${expected}`, () => {
|
|
68
|
+
expect(parseChainId(value)).toEqual(expected);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('should parse a decimal string', () => {
|
|
73
|
+
expect(parseChainId('13371')).toEqual(ChainId.IMTBL_ZKEVM_MAINNET);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should pass through a number', () => {
|
|
77
|
+
expect(parseChainId(13371)).toEqual(ChainId.IMTBL_ZKEVM_MAINNET);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('should parse a bigint', () => {
|
|
81
|
+
expect(parseChainId(BigInt(13371))).toEqual(ChainId.IMTBL_ZKEVM_MAINNET);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const invalidCases = [null, undefined, '', 'not-a-chain', '0x', 0, -1, 1.5];
|
|
85
|
+
|
|
86
|
+
invalidCases.forEach((value) => {
|
|
87
|
+
it(`should return null for ${JSON.stringify(value)}`, () => {
|
|
88
|
+
expect(parseChainId(value)).toBeNull();
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
});
|
package/src/lib/chains.ts
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
import { ChainId, ChainName, ChainSlug } from '@imtbl/checkout-sdk';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Parse a chain id as returned by an EIP-1193 provider (e.g. `eth_chainId`).
|
|
5
|
+
*
|
|
6
|
+
* EIP-695 specifies a hex-encoded quantity such as `0x343b`, but providers are
|
|
7
|
+
* inconsistent and may return a decimal string or a number instead. `Number()`
|
|
8
|
+
* handles all three.
|
|
9
|
+
*
|
|
10
|
+
* Do NOT reach for `parseInt(value, 10)` here: it silently returns 0 for hex
|
|
11
|
+
* input, which reads as "wrong network" for every chain. Use this helper so the
|
|
12
|
+
* radix decision lives in one tested place rather than at each call site.
|
|
13
|
+
*
|
|
14
|
+
* Returns `null` when the value cannot be parsed, so callers can tell an
|
|
15
|
+
* unknown chain apart from a legitimately parsed id.
|
|
16
|
+
*/
|
|
17
|
+
export function parseChainId(chainId: unknown): ChainId | null {
|
|
18
|
+
if (chainId === null || chainId === undefined || chainId === '') return null;
|
|
19
|
+
const parsed = Number(chainId);
|
|
20
|
+
if (!Number.isInteger(parsed) || parsed <= 0) return null;
|
|
21
|
+
return parsed as ChainId;
|
|
22
|
+
}
|
|
23
|
+
|
|
3
24
|
export function getChainNameById(chainId: ChainId): ChainName {
|
|
4
25
|
switch (chainId) {
|
|
5
26
|
case ChainId.ETHEREUM: return ChainName.ETHEREUM;
|
package/src/locales/en.json
CHANGED
|
@@ -1237,7 +1237,14 @@
|
|
|
1237
1237
|
"controlledSwitch": {
|
|
1238
1238
|
"body": "You'll need to switch to the {{chain}} network to proceed"
|
|
1239
1239
|
},
|
|
1240
|
-
"
|
|
1240
|
+
"unsupportedSwitch": {
|
|
1241
|
+
"body": "Your {{wallet}} can't switch networks. Go back and choose a different wallet to use the {{chain}} network."
|
|
1242
|
+
},
|
|
1243
|
+
"switchFailed": {
|
|
1244
|
+
"body": "We couldn't switch to the {{chain}} network. Check your {{wallet}} and try again."
|
|
1245
|
+
},
|
|
1246
|
+
"switchButton": "Switch to {{chain}}",
|
|
1247
|
+
"retryButton": "Try again"
|
|
1241
1248
|
},
|
|
1242
1249
|
"walletConnectionError": {
|
|
1243
1250
|
"unableToConnect": {
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
isWalletConnectProvider,
|
|
23
23
|
} from '../../../lib/provider';
|
|
24
24
|
import { calculateCryptoToFiat, getChainImage, isNativeToken } from '../../../lib/utils';
|
|
25
|
+
import { parseChainId } from '../../../lib/chains';
|
|
25
26
|
import {
|
|
26
27
|
DEFAULT_QUOTE_REFRESH_INTERVAL,
|
|
27
28
|
DEFAULT_TOKEN_DECIMALS,
|
|
@@ -391,7 +392,7 @@ export function BridgeReviewSummary() {
|
|
|
391
392
|
return;
|
|
392
393
|
}
|
|
393
394
|
const currentChainId = await provider.send('eth_chainId', []);
|
|
394
|
-
const parsedChainId =
|
|
395
|
+
const parsedChainId = parseChainId(currentChainId);
|
|
395
396
|
if (parsedChainId !== from?.network) {
|
|
396
397
|
setShowSwitchNetworkDrawer(true);
|
|
397
398
|
return;
|
|
@@ -51,6 +51,7 @@ import { BrowserWalletItem } from './BrowserWalletItem';
|
|
|
51
51
|
import { identifyUser } from '../../../lib/analytics/identifyUser';
|
|
52
52
|
import { NonPassportWarningDrawer } from './NonPassportWarningDrawer';
|
|
53
53
|
import { removeSpace } from '../../../lib/utils';
|
|
54
|
+
import { parseChainId } from '../../../lib/chains';
|
|
54
55
|
|
|
55
56
|
export interface WalletListProps {
|
|
56
57
|
targetWalletRdns?: string;
|
|
@@ -136,11 +137,10 @@ export function WalletList(props: WalletListProps) {
|
|
|
136
137
|
const handleConnectViewUpdate = async (provider: WrappedBrowserProvider) => {
|
|
137
138
|
const isPassport = isPassportProvider(provider);
|
|
138
139
|
const chainId = await provider.send!('eth_chainId', []);
|
|
139
|
-
|
|
140
|
-
const parsedChainId = parseInt(chainId.toString());
|
|
140
|
+
const parsedChainId = parseChainId(chainId);
|
|
141
141
|
if (
|
|
142
142
|
parsedChainId !== targetChainId
|
|
143
|
-
&& !allowedChains?.includes(parsedChainId)
|
|
143
|
+
&& !(parsedChainId && allowedChains?.includes(parsedChainId))
|
|
144
144
|
) {
|
|
145
145
|
// TODO: What do we do with Passport here as it can't connect to L1
|
|
146
146
|
if (isPassport) {
|
|
@@ -20,6 +20,7 @@ import { ViewContext, ViewActions } from '../../../context/view-context/ViewCont
|
|
|
20
20
|
import { isMetaMaskProvider, isPassportProvider } from '../../../lib/provider';
|
|
21
21
|
import { UserJourney, useAnalytics } from '../../../context/analytics-provider/SegmentAnalyticsProvider';
|
|
22
22
|
import { identifyUser } from '../../../lib/analytics/identifyUser';
|
|
23
|
+
import { parseChainId } from '../../../lib/chains';
|
|
23
24
|
|
|
24
25
|
export interface ReadyToConnectProps {
|
|
25
26
|
targetChainId: ChainId;
|
|
@@ -89,9 +90,8 @@ export function ReadyToConnect({ targetChainId, allowedChains }: ReadyToConnectP
|
|
|
89
90
|
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
90
91
|
const handleConnectViewUpdate = async (provider: WrappedBrowserProvider) => {
|
|
91
92
|
const chainId = await provider.send!('eth_chainId', []);
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if (parsedChainId !== targetChainId && !allowedChains?.includes(parsedChainId)) {
|
|
93
|
+
const parsedChainId = parseChainId(chainId);
|
|
94
|
+
if (parsedChainId !== targetChainId && !(parsedChainId && allowedChains?.includes(parsedChainId))) {
|
|
95
95
|
// TODO: What do we do with Passport here as it can't connect to L1
|
|
96
96
|
if (isPassport) {
|
|
97
97
|
viewDispatch({
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
} from 'react';
|
|
4
4
|
import { useTranslation } from 'react-i18next';
|
|
5
5
|
import { isWalletConnectProvider } from '../../../lib/provider';
|
|
6
|
+
import { parseChainId } from '../../../lib/chains';
|
|
6
7
|
import { SimpleTextBody } from '../../../components/Body/SimpleTextBody';
|
|
7
8
|
import { FooterButton } from '../../../components/Footer/FooterButton';
|
|
8
9
|
import { HeaderNavigation } from '../../../components/Header/HeaderNavigation';
|
|
@@ -34,8 +35,7 @@ export function SwitchNetworkZkEVM() {
|
|
|
34
35
|
|
|
35
36
|
const checkCorrectNetwork = async () => {
|
|
36
37
|
const currentChainId = await provider.send('eth_chainId', []);
|
|
37
|
-
|
|
38
|
-
const parsedChainId = Number(currentChainId.toString());
|
|
38
|
+
const parsedChainId = parseChainId(currentChainId);
|
|
39
39
|
if (parsedChainId === checkout.config.l2ChainId) {
|
|
40
40
|
connectDispatch({
|
|
41
41
|
payload: {
|
|
@@ -76,7 +76,7 @@ export function SwitchNetworkZkEVM() {
|
|
|
76
76
|
if (!provider.send) return;
|
|
77
77
|
|
|
78
78
|
const currentChainId = await provider.send('eth_chainId', []) as `0x${string}`;
|
|
79
|
-
const parsedChainId =
|
|
79
|
+
const parsedChainId = parseChainId(currentChainId);
|
|
80
80
|
|
|
81
81
|
if (parsedChainId === checkout.config.l2ChainId) {
|
|
82
82
|
connectDispatch({
|
|
@@ -47,6 +47,7 @@ import { ConnectLoaderContext } from '../../../context/connect-loader-context/Co
|
|
|
47
47
|
import useDebounce from '../../../lib/hooks/useDebounce';
|
|
48
48
|
import { CancellablePromise } from '../../../lib/async/cancellablePromise';
|
|
49
49
|
import { isPassportProvider } from '../../../lib/provider';
|
|
50
|
+
import { parseChainId } from '../../../lib/chains';
|
|
50
51
|
import { formatSwapFees } from '../functions/swapFees';
|
|
51
52
|
import { processGasFree } from '../functions/processGasFree';
|
|
52
53
|
import { processSecondaryFees } from '../functions/processSecondaryFees';
|
|
@@ -885,8 +886,7 @@ export function SwapForm({
|
|
|
885
886
|
try {
|
|
886
887
|
// check for switch network here
|
|
887
888
|
const currentChainId = await (provider.provider as any).send('eth_chainId', []);
|
|
888
|
-
|
|
889
|
-
const parsedChainId = parseInt(currentChainId.toString());
|
|
889
|
+
const parsedChainId = parseChainId(currentChainId);
|
|
890
890
|
if (parsedChainId !== checkout.config.l2ChainId) {
|
|
891
891
|
setShowNetworkSwitchDrawer(true);
|
|
892
892
|
return;
|