From ad1d93f37398996014888e63c9eac7b981dc8059 Mon Sep 17 00:00:00 2001 From: Ignacio Santise <25931366+ignaciosantise@users.noreply.github.com> Date: Thu, 2 Jul 2026 17:24:25 -0300 Subject: [PATCH 1/4] feat(rn_cli_wallet): migrate ethers v5 -> v6 Upgrade `ethers` 5.8.0 -> ^6.13.5, decoupled from the previously-reverted secure-enclave work (MMKV plaintext storage kept as-is). - EIP155Lib: HDNodeWallet.fromPhrase / signTypedData / JsonRpcProvider, Wallet | HDNodeWallet typing. Public `_signTypedData` wrapper name kept. - PaymentTransactionUtil: BigNumber -> native bigint; StaticJsonRpcProvider -> JsonRpcProvider + `staticNetwork`; getBlock() null guards. - Named v6 imports across EIP155WalletUtil (Mnemonic.isValidMnemonic), HelperUtil, ERC20BalanceService, EIP155RequestHandlerUtil, PaymentStore. - SettingsStore: wrap wallet setters in valtio ref() (v6's private #signingKey breaks under the proxy and corrupts the shared wallet map). - Drop @ethersproject/pbkdf2 yarn patch + resolutions (v6 has no @ethersproject); keep bip39 patch for non-EVM seed derivation; update quick-crypto web shim comment. - Drive-bys from the original commit: reject eth_sign for security; add handleRedirect to the Canton/Tron sign modals. - Add SettingsStore regression test for the ethers v6 + valtio ref() fix. Co-Authored-By: Claude Opus 4.8 --- ...sproject-pbkdf2-npm-5.8.0-b720e81bcc.patch | Bin 10515 -> 0 bytes .../__tests__/SettingsStore.test.ts | 51 ++ wallets/rn_cli_wallet/package.json | 4 +- wallets/rn_cli_wallet/src/lib/EIP155Lib.ts | 25 +- .../src/modals/SessionSignCantonModal.tsx | 7 +- .../src/modals/SessionSignTronModal.tsx | 7 +- .../src/services/ERC20BalanceService.ts | 6 +- .../src/shims/quick-crypto.web.ts | 10 +- .../rn_cli_wallet/src/store/PaymentStore.ts | 4 +- .../rn_cli_wallet/src/store/SettingsStore.ts | 17 +- .../src/utils/EIP155RequestHandlerUtil.ts | 18 +- .../src/utils/EIP155WalletUtil.ts | 4 +- wallets/rn_cli_wallet/src/utils/HelperUtil.ts | 10 +- .../src/utils/PaymentTransactionUtil.ts | 116 ++-- wallets/rn_cli_wallet/yarn.lock | 577 +----------------- 15 files changed, 206 insertions(+), 650 deletions(-) delete mode 100644 wallets/rn_cli_wallet/.yarn/patches/@ethersproject-pbkdf2-npm-5.8.0-b720e81bcc.patch create mode 100644 wallets/rn_cli_wallet/__tests__/SettingsStore.test.ts diff --git a/wallets/rn_cli_wallet/.yarn/patches/@ethersproject-pbkdf2-npm-5.8.0-b720e81bcc.patch b/wallets/rn_cli_wallet/.yarn/patches/@ethersproject-pbkdf2-npm-5.8.0-b720e81bcc.patch deleted file mode 100644 index a5d5c5e874dc68985cedbc5ab91f5578bac95f49..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10515 zcmeHMUvJws5SP~iE4-IJ?(voZg*@B(XIYk;rgMuF*pPNB7W=8|GD)OjC9>s7auTEH zM;rE$_7!#~O1Av3O@U?u1`(Di9`DHG?~c3^$O7MocKbX?!BLgt)3ehwiaEHe_xhAy zgCB$(CK2PHYno-6^g14Jnq<_qv+qbZyV@bOo$MuLPtJk^Zue0Ics*n+m>X-xF9v z-X7$2{)tf&!uX#FV=aVh`DaE=41n}(0IahCur9t)YB)HRnixQ;<+IoF@041m0rmqj zVW|zWs`{%Cs1Vpd;GSqdq%7bCKE)o}V5^!H0u=)PYXoZdk57-E;}Y}ey0ut}wt&y? z_z=(PsK8bxgnwB`#yShh*r1U7H9lEEI?xN&gS@Vi0s^8c6$1Yu0`*_vrwH)UA`GS+ zoD}$!LF8vw7@?g#@{b>rwd;cv<2b;PGX7-j7$0OOhK$>vPrWpVrXVJkXHJq_M=@(b z;)H1nf|SP&G2kLD`6A@g7L1)_{46|=;vgMQ8t|^(1}udnDk*ENLS@B?V`mZgi^g(j zQj!E{g1yYtSuhd;* zg76T6W^)NBVWg_L64wYeAN@E@JI3=Daw0#;IEu?tav;Kb5{m68@sFpjTj@V@O5Z|9O9qefbYsXhPd7fhoo0k z9pSpsdxwSNW*V#*hMCWg$`dUe_5x?q58(oyl+FfhZ#Zr~4>Etqf}@?rBiYYrywRH7 zXz=A?E>S=25H4{s1OdL`GFCVcFO}h&%eU|wniT7jol20BzcF;e*HMB);(pt01Y*N; zMz9FmZ<2S6p- z)o&q*=CQ|LIkQP$tgolTr_bClhre?O3PfDF-)nz1QzponFUgtizoy zcP+DT^q6Bhy{^{nTOHG2uA(4;Sv^xTE!%ck&$2q2-R*iDi^iGfaog23-*UH7j*WSj z>Ba^ ({ + MMKV: class { + getString() { + return undefined; + } + set() {} + delete() {} + getAllKeys() { + return []; + } + }, +})); + +import EIP155Lib from '../src/lib/EIP155Lib'; +import SettingsStore from '../src/store/SettingsStore'; + +const TYPED_DATA = { + domain: { + name: 'Test', + version: '1', + chainId: 1, + verifyingContract: '0x0000000000000000000000000000000000000001', + }, + types: { Msg: [{ name: 'value', type: 'string' }] }, + message: { value: 'hello' }, +}; + +describe('SettingsStore wallet storage (ethers v6 + valtio)', () => { + it('keeps the EVM wallet usable for signing after setWallet()', async () => { + const lib = EIP155Lib.init({}); + + // Mirrors useInitializeWalletKit: the same instance lives in the + // eip155Wallets map AND is stored in SettingsStore. + SettingsStore.setWallet(lib); + + // PaymentStore signs using the instance from the raw map. Without ref() + // this throws "Cannot read private member #signingKey". + const signature = await lib._signTypedData( + TYPED_DATA.domain, + TYPED_DATA.types, + TYPED_DATA.message, + ); + + expect(signature).toMatch(/^0x[0-9a-fA-F]+$/); + }); +}); diff --git a/wallets/rn_cli_wallet/package.json b/wallets/rn_cli_wallet/package.json index 3af7cca8e..719f2c132 100644 --- a/wallets/rn_cli_wallet/package.json +++ b/wallets/rn_cli_wallet/package.json @@ -58,7 +58,7 @@ "crc-32": "1.2.2", "dayjs": "1.11.21", "ed25519-hd-key": "1.3.0", - "ethers": "5.8.0", + "ethers": "^6.13.5", "expo": "56.0.12", "expo-application": "~56.0.3", "expo-clipboard": "~56.0.4", @@ -153,8 +153,6 @@ "joi": "17.13.4", "uuid": "11.1.1", "@ton/crypto-primitives@2.1.0": "patch:@ton/crypto-primitives@npm%3A2.1.0#./.yarn/patches/@ton-crypto-primitives-npm-2.1.0-3d1ea62176.patch", - "@ethersproject/pbkdf2@5.8.0": "patch:@ethersproject/pbkdf2@npm%3A5.8.0#./.yarn/patches/@ethersproject-pbkdf2-npm-5.8.0-b720e81bcc.patch", - "@ethersproject/pbkdf2@^5.8.0": "patch:@ethersproject/pbkdf2@npm%3A5.8.0#./.yarn/patches/@ethersproject-pbkdf2-npm-5.8.0-b720e81bcc.patch", "bip39@3.1.0": "patch:bip39@npm%3A3.1.0#./.yarn/patches/bip39-npm-3.1.0-03958ed434.patch", "glob": "10.5.0", "valibot": "1.2.0", diff --git a/wallets/rn_cli_wallet/src/lib/EIP155Lib.ts b/wallets/rn_cli_wallet/src/lib/EIP155Lib.ts index f5b2e884f..f4ca434d0 100644 --- a/wallets/rn_cli_wallet/src/lib/EIP155Lib.ts +++ b/wallets/rn_cli_wallet/src/lib/EIP155Lib.ts @@ -1,4 +1,9 @@ -import { providers, Wallet } from 'ethers'; +import { + HDNodeWallet, + JsonRpcProvider, + TransactionRequest, + Wallet, +} from 'ethers'; /** * Types @@ -12,19 +17,19 @@ interface IInitArgs { * Library */ export default class EIP155Lib { - wallet: Wallet; + wallet: Wallet | HDNodeWallet; - constructor(wallet: Wallet) { + constructor(wallet: Wallet | HDNodeWallet) { this.wallet = wallet; } static init({ mnemonic, privateKey }: IInitArgs) { - let wallet: Wallet; + let wallet: Wallet | HDNodeWallet; if (privateKey) { wallet = new Wallet(privateKey); } else if (mnemonic) { - wallet = Wallet.fromMnemonic(mnemonic); + wallet = HDNodeWallet.fromPhrase(mnemonic); } else { wallet = Wallet.createRandom(); } @@ -33,7 +38,7 @@ export default class EIP155Lib { } getMnemonic() { - return this.wallet.mnemonic?.phrase ?? ''; + return 'mnemonic' in this.wallet ? this.wallet.mnemonic?.phrase ?? '' : ''; } getPrivateKey() { @@ -41,7 +46,7 @@ export default class EIP155Lib { } hasMnemonic() { - return !!this.wallet.mnemonic?.phrase; + return 'mnemonic' in this.wallet && !!this.wallet.mnemonic?.phrase; } getAddress() { @@ -53,14 +58,14 @@ export default class EIP155Lib { } _signTypedData(domain: any, types: any, data: any) { - return this.wallet._signTypedData(domain, types, data); + return this.wallet.signTypedData(domain, types, data); } - connect(provider: providers.JsonRpcProvider) { + connect(provider: JsonRpcProvider) { return this.wallet.connect(provider); } - signTransaction(transaction: providers.TransactionRequest) { + signTransaction(transaction: TransactionRequest) { return this.wallet.signTransaction(transaction); } } diff --git a/wallets/rn_cli_wallet/src/modals/SessionSignCantonModal.tsx b/wallets/rn_cli_wallet/src/modals/SessionSignCantonModal.tsx index 20bdb2d36..1bbecc385 100644 --- a/wallets/rn_cli_wallet/src/modals/SessionSignCantonModal.tsx +++ b/wallets/rn_cli_wallet/src/modals/SessionSignCantonModal.tsx @@ -7,6 +7,7 @@ import { rejectCantonRequest, } from '@/utils/CantonRequestHandlerUtil'; import { walletKit } from '@/utils/WalletKitUtil'; +import { handleRedirect } from '@/utils/LinkingUtils'; import { RequestModal } from './RequestModal'; import { useCallback, useState } from 'react'; import { StyleSheet, View } from 'react-native'; @@ -44,6 +45,10 @@ export default function SessionSignCantonModal() { response, }); haptics.requestResponse(); + handleRedirect({ + peerRedirect: requestSession?.peer?.metadata?.redirect, + isLinkMode, + }); } catch (e) { // Respond with JSON-RPC error so the dapp doesn't hang try { @@ -68,7 +73,7 @@ export default function SessionSignCantonModal() { setIsLoadingApprove(false); ModalStore.close(); } - }, [requestEvent, topic]); + }, [requestEvent, topic, requestSession, isLinkMode]); const onReject = useCallback(async () => { if (!requestEvent) { diff --git a/wallets/rn_cli_wallet/src/modals/SessionSignTronModal.tsx b/wallets/rn_cli_wallet/src/modals/SessionSignTronModal.tsx index 764a7f305..d70948027 100644 --- a/wallets/rn_cli_wallet/src/modals/SessionSignTronModal.tsx +++ b/wallets/rn_cli_wallet/src/modals/SessionSignTronModal.tsx @@ -9,6 +9,7 @@ import { rejectTronRequest, } from '@/utils/TronRequestHandlerUtil'; import { walletKit } from '@/utils/WalletKitUtil'; +import { handleRedirect } from '@/utils/LinkingUtils'; import { RequestModal } from './RequestModal'; import { useCallback, useState } from 'react'; import { StyleSheet, View } from 'react-native'; @@ -54,6 +55,10 @@ export default function SessionSignTronModal() { response, }); haptics.requestResponse(); + handleRedirect({ + peerRedirect: requestSession?.peer?.metadata?.redirect, + isLinkMode, + }); } } catch (e) { LogStore.error((e as Error).message, 'SessionSignTronModal', 'onApprove'); @@ -65,7 +70,7 @@ export default function SessionSignTronModal() { setIsLoadingApprove(false); ModalStore.close(); } - }, [requestEvent, topic]); + }, [requestEvent, topic, requestSession, isLinkMode]); // Handle reject action const onReject = useCallback(async () => { diff --git a/wallets/rn_cli_wallet/src/services/ERC20BalanceService.ts b/wallets/rn_cli_wallet/src/services/ERC20BalanceService.ts index 96bfbed12..d983e460e 100644 --- a/wallets/rn_cli_wallet/src/services/ERC20BalanceService.ts +++ b/wallets/rn_cli_wallet/src/services/ERC20BalanceService.ts @@ -1,4 +1,4 @@ -import { Contract, providers, utils } from 'ethers'; +import { Contract, JsonRpcProvider, formatUnits } from 'ethers'; import { ENV } from '@/utils/env'; import { TokenBalance } from '@/utils/BalanceTypes'; import LogStore, { serializeError } from '@/store/LogStore'; @@ -58,14 +58,14 @@ async function fetchSingleERC20Balance( } try { - const provider = new providers.JsonRpcProvider(rpcUrl); + const provider = new JsonRpcProvider(rpcUrl); const contract = new Contract( token.address, ERC20_BALANCE_OF_ABI, provider, ); const rawBalance = await contract.balanceOf(walletAddress); - const numeric = utils.formatUnits(rawBalance, token.decimals); + const numeric = formatUnits(rawBalance, token.decimals); return { name: token.name, diff --git a/wallets/rn_cli_wallet/src/shims/quick-crypto.web.ts b/wallets/rn_cli_wallet/src/shims/quick-crypto.web.ts index f3e460a1a..81b6ef478 100644 --- a/wallets/rn_cli_wallet/src/shims/quick-crypto.web.ts +++ b/wallets/rn_cli_wallet/src/shims/quick-crypto.web.ts @@ -25,11 +25,11 @@ export function getRandomValues(array: T): T { export const subtle = webCrypto?.subtle; // Node's `crypto.pbkdf2Sync`, implemented in pure JS via @noble/hashes. The -// `@ethersproject/pbkdf2` patch aliases its `pbkdf2` export to -// `crypto.pbkdf2Sync` (the fast native path via quick-crypto on device); on web -// we provide it here so ethers' `Wallet.fromMnemonic` (mnemonic -> seed -// derivation) works instead of throwing -// "_ethersprojectPbkdf.pbkdf2 is not a function". +// `bip39` patch aliases its seed derivation (`mnemonicToSeedSync`) to +// `crypto.pbkdf2Sync` — the fast native path via quick-crypto on device; on web +// we provide it here so bip39-based mnemonic -> seed derivation (Solana, Sui, +// Ton) works instead of throwing "pbkdf2 is not a function". (ethers v6 derives +// its own seed via @noble/hashes and no longer routes through `crypto`.) type Hashish = typeof sha512; const HASHES: Record = {sha512, sha256, sha1}; diff --git a/wallets/rn_cli_wallet/src/store/PaymentStore.ts b/wallets/rn_cli_wallet/src/store/PaymentStore.ts index 2852a5b04..6eb62f2e7 100644 --- a/wallets/rn_cli_wallet/src/store/PaymentStore.ts +++ b/wallets/rn_cli_wallet/src/store/PaymentStore.ts @@ -6,7 +6,7 @@ import type { PaymentOptionsResponse, PaymentOption, } from '@walletconnect/pay'; -import { providers } from 'ethers'; +import type { TransactionRequest } from 'ethers'; import { Platform } from 'react-native'; import { ENV } from '@/utils/env'; @@ -620,7 +620,7 @@ const PaymentStore = { const tx = await sendTransactionWithFreshFees({ chainId, - baseTx: { ...(txPayload as providers.TransactionRequest) }, + baseTx: { ...(txPayload as TransactionRequest) }, wallet: evmWallet, logContext: 'approvePayment', }); diff --git a/wallets/rn_cli_wallet/src/store/SettingsStore.ts b/wallets/rn_cli_wallet/src/store/SettingsStore.ts index 33cf03156..b90b88696 100644 --- a/wallets/rn_cli_wallet/src/store/SettingsStore.ts +++ b/wallets/rn_cli_wallet/src/store/SettingsStore.ts @@ -1,4 +1,4 @@ -import { proxy } from 'valtio'; +import { proxy, ref } from 'valtio'; import { Appearance } from 'react-native'; import { Verify, SessionTypes } from '@walletconnect/types'; @@ -99,7 +99,10 @@ const SettingsStore = { }, setWallet(wallet: EIP155Lib) { - state.wallet = wallet; + // ref() keeps the wallet out of valtio's proxy: ethers v6's private + // #signingKey throws through a Proxy and valtio would corrupt the shared + // eip155Wallets instance. + state.wallet = ref(wallet); }, setActiveChainId(value: string) { @@ -146,7 +149,7 @@ const SettingsStore = { }, setSuiWallet(suiWallet: SuiLib) { - state.suiWallet = suiWallet; + state.suiWallet = ref(suiWallet); }, setTonAddress(tonAddress: string) { @@ -154,7 +157,7 @@ const SettingsStore = { }, setTonWallet(tonWallet: TonLib) { - state.tonWallet = tonWallet; + state.tonWallet = ref(tonWallet); }, setTronAddress(tronAddress: string) { @@ -162,7 +165,7 @@ const SettingsStore = { }, setTronWallet(tronWallet: TronLib) { - state.tronWallet = tronWallet; + state.tronWallet = ref(tronWallet); }, setCantonAddress(cantonAddress: string) { @@ -170,7 +173,7 @@ const SettingsStore = { }, setCantonWallet(cantonWallet: CantonLib) { - state.cantonWallet = cantonWallet; + state.cantonWallet = ref(cantonWallet); }, setSolanaAddress(solanaAddress: string) { @@ -178,7 +181,7 @@ const SettingsStore = { }, setSolanaWallet(solanaWallet: SolanaLib) { - state.solanaWallet = solanaWallet; + state.solanaWallet = ref(solanaWallet); }, setThemeMode(value: 'light' | 'dark') { diff --git a/wallets/rn_cli_wallet/src/utils/EIP155RequestHandlerUtil.ts b/wallets/rn_cli_wallet/src/utils/EIP155RequestHandlerUtil.ts index ad0d14d65..4838e2242 100644 --- a/wallets/rn_cli_wallet/src/utils/EIP155RequestHandlerUtil.ts +++ b/wallets/rn_cli_wallet/src/utils/EIP155RequestHandlerUtil.ts @@ -1,4 +1,4 @@ -import { providers } from 'ethers'; +import { JsonRpcProvider } from 'ethers'; import { formatJsonRpcError, formatJsonRpcResult } from '@json-rpc-tools/utils'; import { SignClientTypes } from '@walletconnect/types'; import { getSdkError } from '@walletconnect/utils'; @@ -23,8 +23,20 @@ export async function approveEIP155Request(requestEvent: RequestEventArgs) { eip155Wallets[getWalletAddressFromParams(eip155Addresses, params)]; switch (request.method) { - case EIP155_SIGNING_METHODS.PERSONAL_SIGN: + // eth_sign signs arbitrary opaque bytes (no message prefix) — a phishing + // vector — so reject it and steer dApps to personal_sign. case EIP155_SIGNING_METHODS.ETH_SIGN: + LogStore.warn( + 'Rejected eth_sign request (disabled for security)', + 'EIP155RequestHandler', + 'ethSign', + ); + return formatJsonRpcError( + id, + 'eth_sign is disabled for security reasons. Use personal_sign instead.', + ); + + case EIP155_SIGNING_METHODS.PERSONAL_SIGN: try { const message = getSignParamsMessage(request.params); @@ -63,7 +75,7 @@ export async function approveEIP155Request(requestEvent: RequestEventArgs) { case EIP155_SIGNING_METHODS.ETH_SEND_TRANSACTION: try { const chainData = PresetsUtil.getChainDataById(chainId); - const provider = new providers.JsonRpcProvider(chainData?.rpcUrl); + const provider = new JsonRpcProvider(chainData?.rpcUrl); const sendTransaction = request.params[0]; const connectedWallet = wallet.connect(provider); const { hash } = await connectedWallet.sendTransaction(sendTransaction); diff --git a/wallets/rn_cli_wallet/src/utils/EIP155WalletUtil.ts b/wallets/rn_cli_wallet/src/utils/EIP155WalletUtil.ts index 0ecb03145..e59bc80f2 100644 --- a/wallets/rn_cli_wallet/src/utils/EIP155WalletUtil.ts +++ b/wallets/rn_cli_wallet/src/utils/EIP155WalletUtil.ts @@ -1,4 +1,4 @@ -import { utils } from 'ethers'; +import { Mnemonic } from 'ethers'; import { ENV } from './env'; @@ -68,7 +68,7 @@ export function loadEIP155Wallet(input: string): { `Mnemonic must be 12, 15, 18, 21, or 24 words (got ${words.length})`, ); } - if (!utils.isValidMnemonic(trimmedInput)) { + if (!Mnemonic.isValidMnemonic(trimmedInput)) { throw new Error('Invalid mnemonic phrase'); } } diff --git a/wallets/rn_cli_wallet/src/utils/HelperUtil.ts b/wallets/rn_cli_wallet/src/utils/HelperUtil.ts index eb7b6eb05..6597c5ce6 100644 --- a/wallets/rn_cli_wallet/src/utils/HelperUtil.ts +++ b/wallets/rn_cli_wallet/src/utils/HelperUtil.ts @@ -1,4 +1,4 @@ -import { utils } from 'ethers'; +import { isAddress, isHexString, toUtf8String } from 'ethers'; import { ProposalTypes } from '@walletconnect/types'; import { PresetsUtil } from './PresetsUtil'; @@ -26,8 +26,8 @@ export function truncate(value: string, length: number) { * Converts hex to utf8 string if it is valid bytes */ export function convertHexToUtf8(value: string) { - if (utils.isHexString(value)) { - return utils.toUtf8String(value); + if (isHexString(value)) { + return toUtf8String(value); } return value; @@ -39,7 +39,7 @@ export function convertHexToUtf8(value: string) { * If it is a hex string, it gets converted to utf8 string */ export function getSignParamsMessage(params: string[]) { - const message = params.filter(p => !utils.isAddress(p))[0]; + const message = params.filter(p => !isAddress(p))[0]; return convertHexToUtf8(message); } @@ -50,7 +50,7 @@ export function getSignParamsMessage(params: string[]) { * If data is a string convert it to object */ export function getSignTypedDataParamsData(params: string[]) { - const data = params.filter(p => !utils.isAddress(p))[0]; + const data = params.filter(p => !isAddress(p))[0]; if (typeof data === 'string') { return JSON.parse(data); diff --git a/wallets/rn_cli_wallet/src/utils/PaymentTransactionUtil.ts b/wallets/rn_cli_wallet/src/utils/PaymentTransactionUtil.ts index 180f72b13..92b1024ac 100644 --- a/wallets/rn_cli_wallet/src/utils/PaymentTransactionUtil.ts +++ b/wallets/rn_cli_wallet/src/utils/PaymentTransactionUtil.ts @@ -1,11 +1,18 @@ import type { Action } from '@walletconnect/pay'; -import { BigNumber, providers, utils } from 'ethers'; +import { JsonRpcProvider, Network, formatEther } from 'ethers'; +import type { + Block, + FeeData, + JsonRpcSigner, + TransactionRequest, + TransactionResponse, +} from 'ethers'; import { ENV } from './env'; import LogStore, { serializeError } from '@/store/LogStore'; import { PresetsUtil } from '@/utils/PresetsUtil'; -const POLYGON_MIN_PRIORITY_FEE_WEI = BigNumber.from('30000000000'); // 30 gwei +const POLYGON_MIN_PRIORITY_FEE_WEI = 30000000000n; // 30 gwei const WALLETCONNECT_RPC_BASE_URL = 'https://rpc.walletconnect.org/v1/'; const WALLETCONNECT_FUNGIBLE_PRICE_URL = 'https://rpc.walletconnect.org/v1/fungible/price'; @@ -72,12 +79,12 @@ export type TransactionFeeEstimate = { }; export type TransactionWallet = { - connect: (provider: providers.JsonRpcProvider) => - | providers.JsonRpcSigner + connect: (provider: JsonRpcProvider) => + | JsonRpcSigner | { sendTransaction: ( - tx: providers.TransactionRequest, - ) => Promise; + tx: TransactionRequest, + ) => Promise; }; }; @@ -109,19 +116,19 @@ function getWalletConnectRpcUrl(chainId: string): string | null { )}&projectId=${encodeURIComponent(projectId)}`; } -function getHighestBigNumber( - values: Array, -): BigNumber | null { - return values.reduce((max, v) => { - if (!v) return max; - return !max || v.gt(max) ? v : max; +function getHighestBigInt( + values: Array, +): bigint | null { + return values.reduce((max, v) => { + if (v == null) return max; + return max == null || v > max ? v : max; }, null); } -function toBigNumber(value: unknown): BigNumber | null { +function toBigInt(value: unknown): bigint | null { if (value == null) return null; try { - return BigNumber.from(value as string | number); + return BigInt(value as string | number | bigint); } catch { return null; } @@ -229,9 +236,7 @@ async function fetchNativeTokenPrice({ }); } -export function createPayRpcProvider( - chainId: string, -): providers.StaticJsonRpcProvider { +export function createPayRpcProvider(chainId: string): JsonRpcProvider { const chainData = PresetsUtil.getChainDataById(chainId); if (!chainData) { throw new Error(`Missing chain metadata for ${chainId}`); @@ -245,14 +250,15 @@ export function createPayRpcProvider( } const parsedChainId = Number(chainData.chainId); + // staticNetwork skips the initial eth_chainId detection round-trip. const network = Number.isFinite(parsedChainId) && parsedChainId > 0 - ? { chainId: parsedChainId, name: chainData.name || chainId } + ? new Network(chainData.name || chainId, parsedChainId) : undefined; return network - ? new providers.StaticJsonRpcProvider(rpcUrl, network) - : new providers.StaticJsonRpcProvider(rpcUrl); + ? new JsonRpcProvider(rpcUrl, network, { staticNetwork: network }) + : new JsonRpcProvider(rpcUrl); } export function buildFreshTxRequest({ @@ -262,28 +268,28 @@ export function buildFreshTxRequest({ latestBlock, }: { chainId: string; - baseTx: providers.TransactionRequest; - feeData: providers.FeeData; - latestBlock: providers.Block; -}): providers.TransactionRequest { + baseTx: TransactionRequest; + feeData: FeeData; + latestBlock: Block; +}): TransactionRequest { const chainFloor = chainId === 'eip155:137' ? POLYGON_MIN_PRIORITY_FEE_WEI : null; - const priorityFee = getHighestBigNumber([ + const priorityFee = getHighestBigInt([ chainFloor, feeData.maxPriorityFeePerGas || null, ]); const maxFee = priorityFee - ? getHighestBigNumber([ + ? getHighestBigInt([ latestBlock.baseFeePerGas - ? latestBlock.baseFeePerGas.mul(2).add(priorityFee) + ? latestBlock.baseFeePerGas * 2n + priorityFee : null, feeData.maxFeePerGas || null, priorityFee, ]) : null; - const request: providers.TransactionRequest = { ...baseTx }; + const request: TransactionRequest = { ...baseTx }; if (priorityFee) { request.maxPriorityFeePerGas = priorityFee; @@ -302,7 +308,7 @@ export function buildFreshTxRequest({ !request.maxFeePerGas && feeData.gasPrice ) { - const gasPrice = getHighestBigNumber([feeData.gasPrice, chainFloor]); + const gasPrice = getHighestBigInt([feeData.gasPrice, chainFloor]); if (gasPrice) { request.gasPrice = gasPrice; } @@ -313,10 +319,10 @@ export function buildFreshTxRequest({ return request; } -function serializeTxRequestForLog(tx: providers.TransactionRequest) { +function serializeTxRequestForLog(tx: TransactionRequest) { const asString = (value: unknown): string | number | null => { if (value == null) return null; - if (BigNumber.isBigNumber(value)) return value.toString(); + if (typeof value === 'bigint') return value.toString(); if (typeof value === 'number' || typeof value === 'string') return value; if (typeof value === 'object' && value && 'toString' in value) { try { @@ -349,14 +355,14 @@ function formatNativeGasEstimate({ totalFeeWei, chainId, }: { - totalFeeWei: BigNumber; + totalFeeWei: bigint; chainId: string; }): string { const symbol = NATIVE_SYMBOL_BY_CHAIN_ID[chainId] || 'ETH'; - const feeValue = Number(utils.formatEther(totalFeeWei)); + const feeValue = Number(formatEther(totalFeeWei)); if (!Number.isFinite(feeValue) || feeValue <= 0) { - return `~${utils.formatEther(totalFeeWei)} ${symbol}`; + return `~${formatEther(totalFeeWei)} ${symbol}`; } if (feeValue >= 0.01) { @@ -391,13 +397,13 @@ function buildGasEstimate({ chainId, nativeTokenPrice, }: { - totalFeeWei: BigNumber; + totalFeeWei: bigint; chainId: string; nativeTokenPrice: { price: number; currency: string } | null; }): TransactionFeeEstimate { const nativeSymbol = NATIVE_SYMBOL_BY_CHAIN_ID[chainId] || 'ETH'; const nativeDisplay = formatNativeGasEstimate({ totalFeeWei, chainId }); - const nativeValue = Number(utils.formatEther(totalFeeWei)); + const nativeValue = Number(formatEther(totalFeeWei)); const fiatCurrency = nativeTokenPrice?.currency ?? null; const fiatValue = nativeTokenPrice && Number.isFinite(nativeValue) && nativeValue > 0 @@ -454,15 +460,15 @@ export async function estimateTransactionFee( return null; } - let provider: providers.StaticJsonRpcProvider; + let provider: JsonRpcProvider; try { provider = createPayRpcProvider(walletRpc.chainId); } catch { return null; } - const baseTx: providers.TransactionRequest = { - ...(parsedParams[0] as providers.TransactionRequest), + const baseTx: TransactionRequest = { + ...(parsedParams[0] as TransactionRequest), }; const [gasLimit, feeData, latestBlock] = await Promise.all([ @@ -483,6 +489,10 @@ export async function estimateTransactionFee( ), ]); + if (!latestBlock) { + return null; + } + const txWithFreshFees = buildFreshTxRequest({ chainId: walletRpc.chainId, baseTx, @@ -490,17 +500,17 @@ export async function estimateTransactionFee( latestBlock, }); - const feePerGas = toBigNumber( + const feePerGas = toBigInt( txWithFreshFees.maxFeePerGas ?? txWithFreshFees.gasPrice ?? feeData.maxFeePerGas ?? feeData.gasPrice, ); - if (!feePerGas) { + if (feePerGas == null) { return null; } - const totalFeeWei = gasLimit.mul(feePerGas); + const totalFeeWei = gasLimit * feePerGas; const nativeTokenPrice = await fetchNativeTokenPrice({ chainId: walletRpc.chainId, currency: options.currency, @@ -520,25 +530,27 @@ export async function sendTransactionWithFreshFees({ logContext, }: { chainId: string; - baseTx: providers.TransactionRequest; + baseTx: TransactionRequest; wallet: TransactionWallet; logContext: string; -}): Promise { +}): Promise { const provider = createPayRpcProvider(chainId); const connectedWallet = wallet.connect(provider); - let txRequest: providers.TransactionRequest = { ...baseTx }; + let txRequest: TransactionRequest = { ...baseTx }; try { const [feeData, latestBlock] = await Promise.all([ provider.getFeeData(), provider.getBlock('latest'), ]); - txRequest = buildFreshTxRequest({ - chainId, - baseTx, - feeData, - latestBlock, - }); + if (latestBlock) { + txRequest = buildFreshTxRequest({ + chainId, + baseTx, + feeData, + latestBlock, + }); + } } catch (error) { LogStore.warn( 'Failed to fetch initial fee data', @@ -571,7 +583,7 @@ export async function sendTransactionWithFreshFees({ } export async function waitForTransactionConfirmation( - tx: providers.TransactionResponse, + tx: TransactionResponse, timeoutMs: number = TX_CONFIRMATION_TIMEOUT_MS, ) { let timeoutId: ReturnType | null = null; diff --git a/wallets/rn_cli_wallet/yarn.lock b/wallets/rn_cli_wallet/yarn.lock index e85eb13e2..30e859f0b 100644 --- a/wallets/rn_cli_wallet/yarn.lock +++ b/wallets/rn_cli_wallet/yarn.lock @@ -37,7 +37,7 @@ __metadata: languageName: node linkType: hard -"@adraffy/ens-normalize@npm:^1.11.0": +"@adraffy/ens-normalize@npm:1.11.1, @adraffy/ens-normalize@npm:^1.11.0": version: 1.11.1 resolution: "@adraffy/ens-normalize@npm:1.11.1" checksum: e8b17fcc730ccc45a956e1fbb09edfe42be41c291079512082e9964f8ef4287e67913183cdd02fff71d2e215340d5b98a9bbbd9be32c5d36fad4ba2c1ec33ff2 @@ -2141,418 +2141,6 @@ __metadata: languageName: node linkType: hard -"@ethersproject/abi@npm:5.8.0, @ethersproject/abi@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/abi@npm:5.8.0" - dependencies: - "@ethersproject/address": ^5.8.0 - "@ethersproject/bignumber": ^5.8.0 - "@ethersproject/bytes": ^5.8.0 - "@ethersproject/constants": ^5.8.0 - "@ethersproject/hash": ^5.8.0 - "@ethersproject/keccak256": ^5.8.0 - "@ethersproject/logger": ^5.8.0 - "@ethersproject/properties": ^5.8.0 - "@ethersproject/strings": ^5.8.0 - checksum: cdab990d520fdbfd63d4a8829e78a2d2d2cc110dc3461895bd9014a49d3a9028c2005a11e2569c3fd620cb7780dcb5c71402630a8082a9ca5f85d4f8700d4549 - languageName: node - linkType: hard - -"@ethersproject/abstract-provider@npm:5.8.0, @ethersproject/abstract-provider@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/abstract-provider@npm:5.8.0" - dependencies: - "@ethersproject/bignumber": ^5.8.0 - "@ethersproject/bytes": ^5.8.0 - "@ethersproject/logger": ^5.8.0 - "@ethersproject/networks": ^5.8.0 - "@ethersproject/properties": ^5.8.0 - "@ethersproject/transactions": ^5.8.0 - "@ethersproject/web": ^5.8.0 - checksum: 4fd00d770552af53be297c676f31d938f5dc44d73c24970036a11237a53f114cc1c551fd95937b9eca790f77087da1ed3ec54f97071df088d5861f575fd4f9be - languageName: node - linkType: hard - -"@ethersproject/abstract-signer@npm:5.8.0, @ethersproject/abstract-signer@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/abstract-signer@npm:5.8.0" - dependencies: - "@ethersproject/abstract-provider": ^5.8.0 - "@ethersproject/bignumber": ^5.8.0 - "@ethersproject/bytes": ^5.8.0 - "@ethersproject/logger": ^5.8.0 - "@ethersproject/properties": ^5.8.0 - checksum: 3f7a98caf7c01e58da45d879c08449d1443bced36ac81938789c90d8f9ff86a1993655bae9805fc7b31a723b7bd7b4f1f768a9ec65dff032d0ebdc93133c14f3 - languageName: node - linkType: hard - -"@ethersproject/address@npm:5.8.0, @ethersproject/address@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/address@npm:5.8.0" - dependencies: - "@ethersproject/bignumber": ^5.8.0 - "@ethersproject/bytes": ^5.8.0 - "@ethersproject/keccak256": ^5.8.0 - "@ethersproject/logger": ^5.8.0 - "@ethersproject/rlp": ^5.8.0 - checksum: fa48e16403b656207f996ee7796f0978a146682f10f345b75aa382caa4a70fbfdc6ff585e9955e4779f4f15a31628929b665d288b895cea5df206c070266aea1 - languageName: node - linkType: hard - -"@ethersproject/base64@npm:5.8.0, @ethersproject/base64@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/base64@npm:5.8.0" - dependencies: - "@ethersproject/bytes": ^5.8.0 - checksum: f0c2136c99b2fd2f93b7e110958eacc5990e88274b1f38eb73d8eaa31bdead75fc0c4608dac23cb5718ae455b965de9dc5023446b96de62ef1fa945cbf212096 - languageName: node - linkType: hard - -"@ethersproject/basex@npm:5.8.0, @ethersproject/basex@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/basex@npm:5.8.0" - dependencies: - "@ethersproject/bytes": ^5.8.0 - "@ethersproject/properties": ^5.8.0 - checksum: 7b502b91011d3aac9bf38d77aad113632440a1eab6a966ffbe2c23f9e3758a4dcb2a4189ab2948d6996250d0cb716d7445e7e2103d03b94097a77c0e128f9ab7 - languageName: node - linkType: hard - -"@ethersproject/bignumber@npm:5.8.0, @ethersproject/bignumber@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/bignumber@npm:5.8.0" - dependencies: - "@ethersproject/bytes": ^5.8.0 - "@ethersproject/logger": ^5.8.0 - bn.js: ^5.2.1 - checksum: c87017f466b32d482e4b39370016cfc3edafc2feb89377011c54cd2e7dd011072ef4f275df59cd9fe080a187066082c1808b2682d97547c4fb9e6912331200c3 - languageName: node - linkType: hard - -"@ethersproject/bytes@npm:5.8.0, @ethersproject/bytes@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/bytes@npm:5.8.0" - dependencies: - "@ethersproject/logger": ^5.8.0 - checksum: 507e8ef1f1559590b4e78e3392a2b16090e96fb1091e0b08d3a8491df65976b313c29cdb412594454f68f9f04d5f77ea5a400b489d80a3e46a608156ef31b251 - languageName: node - linkType: hard - -"@ethersproject/constants@npm:5.8.0, @ethersproject/constants@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/constants@npm:5.8.0" - dependencies: - "@ethersproject/bignumber": ^5.8.0 - checksum: 74830c44f4315a1058b905c73be7a9bb92850e45213cb28a957447b8a100f22a514f4500b0ea5ac7a995427cecef9918af39ae4e0e0ecf77aa4835b1ea5c3432 - languageName: node - linkType: hard - -"@ethersproject/contracts@npm:5.8.0": - version: 5.8.0 - resolution: "@ethersproject/contracts@npm:5.8.0" - dependencies: - "@ethersproject/abi": ^5.8.0 - "@ethersproject/abstract-provider": ^5.8.0 - "@ethersproject/abstract-signer": ^5.8.0 - "@ethersproject/address": ^5.8.0 - "@ethersproject/bignumber": ^5.8.0 - "@ethersproject/bytes": ^5.8.0 - "@ethersproject/constants": ^5.8.0 - "@ethersproject/logger": ^5.8.0 - "@ethersproject/properties": ^5.8.0 - "@ethersproject/transactions": ^5.8.0 - checksum: cb181012bd55cc19c08f136e56e28e922f1ca66af66747a1b3f58a2aea5b3332bc7ecfe2d23fa14245e7fd45a4fdc4f3427a345c2e9873a9792838cdfe4c62d5 - languageName: node - linkType: hard - -"@ethersproject/hash@npm:5.8.0, @ethersproject/hash@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/hash@npm:5.8.0" - dependencies: - "@ethersproject/abstract-signer": ^5.8.0 - "@ethersproject/address": ^5.8.0 - "@ethersproject/base64": ^5.8.0 - "@ethersproject/bignumber": ^5.8.0 - "@ethersproject/bytes": ^5.8.0 - "@ethersproject/keccak256": ^5.8.0 - "@ethersproject/logger": ^5.8.0 - "@ethersproject/properties": ^5.8.0 - "@ethersproject/strings": ^5.8.0 - checksum: e1feb47a98c631548b0f98ef0b1eb1b964bc643d5dea12a0eeb533165004cfcfe6f1d2bb32f31941f0b91e6a82212ad5c8577d6d465fba62c38fc0c410941feb - languageName: node - linkType: hard - -"@ethersproject/hdnode@npm:5.8.0, @ethersproject/hdnode@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/hdnode@npm:5.8.0" - dependencies: - "@ethersproject/abstract-signer": ^5.8.0 - "@ethersproject/basex": ^5.8.0 - "@ethersproject/bignumber": ^5.8.0 - "@ethersproject/bytes": ^5.8.0 - "@ethersproject/logger": ^5.8.0 - "@ethersproject/pbkdf2": ^5.8.0 - "@ethersproject/properties": ^5.8.0 - "@ethersproject/sha2": ^5.8.0 - "@ethersproject/signing-key": ^5.8.0 - "@ethersproject/strings": ^5.8.0 - "@ethersproject/transactions": ^5.8.0 - "@ethersproject/wordlists": ^5.8.0 - checksum: 72cc6bd218dbe3565b915f3fd8654562003b1b160a5ace8c8959e319333712a0951887641f6888ef91017a39bb804204fc09fb7e5064e3acf76ad701c2ff1266 - languageName: node - linkType: hard - -"@ethersproject/json-wallets@npm:5.8.0, @ethersproject/json-wallets@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/json-wallets@npm:5.8.0" - dependencies: - "@ethersproject/abstract-signer": ^5.8.0 - "@ethersproject/address": ^5.8.0 - "@ethersproject/bytes": ^5.8.0 - "@ethersproject/hdnode": ^5.8.0 - "@ethersproject/keccak256": ^5.8.0 - "@ethersproject/logger": ^5.8.0 - "@ethersproject/pbkdf2": ^5.8.0 - "@ethersproject/properties": ^5.8.0 - "@ethersproject/random": ^5.8.0 - "@ethersproject/strings": ^5.8.0 - "@ethersproject/transactions": ^5.8.0 - aes-js: 3.0.0 - scrypt-js: 3.0.1 - checksum: 8e0f8529f683d0a3fab1c76173bfccf7fc03a27e291344c86797815872722770be787e91f8fa83c37b0abfc47d5f2a2d0eca0ab862effb5539ad545e317f8d83 - languageName: node - linkType: hard - -"@ethersproject/keccak256@npm:5.8.0, @ethersproject/keccak256@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/keccak256@npm:5.8.0" - dependencies: - "@ethersproject/bytes": ^5.8.0 - js-sha3: 0.8.0 - checksum: af3621d2b18af6c8f5181dacad91e1f6da4e8a6065668b20e4c24684bdb130b31e45e0d4dbaed86d4f1314d01358aa119f05be541b696e455424c47849d81913 - languageName: node - linkType: hard - -"@ethersproject/logger@npm:5.8.0, @ethersproject/logger@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/logger@npm:5.8.0" - checksum: 6249885a7fd4a5806e4c8700b76ffcc8f1ff00d71f31aa717716a89fa6b391de19fbb0cb5ae2560b9f57ec0c2e8e0a11ebc2099124c73d3b42bc58e3eedc41d1 - languageName: node - linkType: hard - -"@ethersproject/networks@npm:5.8.0, @ethersproject/networks@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/networks@npm:5.8.0" - dependencies: - "@ethersproject/logger": ^5.8.0 - checksum: b1d43fdab13e32be74b5547968c7e54786915a1c3543025c628f634872038750171bef15db0cf42a27e568175b185ac9c185a9aae8f93839452942c5a867c908 - languageName: node - linkType: hard - -"@ethersproject/pbkdf2@npm:5.8.0": - version: 5.8.0 - resolution: "@ethersproject/pbkdf2@npm:5.8.0" - dependencies: - "@ethersproject/bytes": ^5.8.0 - "@ethersproject/sha2": ^5.8.0 - checksum: 79e06ec6063e745a714c7c3f8ecfb7a8d2db2d19d45ad0e84e59526f685a2704f06e8c8fbfaf3aca85d15037bead7376d704529aac783985e1ff7b90c2d6e714 - languageName: node - linkType: hard - -"@ethersproject/pbkdf2@patch:@ethersproject/pbkdf2@npm%3A5.8.0#./.yarn/patches/@ethersproject-pbkdf2-npm-5.8.0-b720e81bcc.patch::locator=RNWeb3Wallet%40workspace%3A.": - version: 5.8.0 - resolution: "@ethersproject/pbkdf2@patch:@ethersproject/pbkdf2@npm%3A5.8.0#./.yarn/patches/@ethersproject-pbkdf2-npm-5.8.0-b720e81bcc.patch::version=5.8.0&hash=3a7e9c&locator=RNWeb3Wallet%40workspace%3A." - dependencies: - "@ethersproject/bytes": ^5.8.0 - "@ethersproject/sha2": ^5.8.0 - checksum: a44c5d0c23b3d72a20a54697dcc1e43a56f95cc458b2bb34b2e20d69ad4a831a466462268e6478641ab20619bbe7f82847813e94c60b18d05aea5c2a9335ce7e - languageName: node - linkType: hard - -"@ethersproject/properties@npm:5.8.0, @ethersproject/properties@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/properties@npm:5.8.0" - dependencies: - "@ethersproject/logger": ^5.8.0 - checksum: 2bb0369a3c25a7c1999e990f73a9db149a5e514af253e3945c7728eaea5d864144da6a81661c0c414b97be75db7fb15c34f719169a3adb09e585a3286ea78b9c - languageName: node - linkType: hard - -"@ethersproject/providers@npm:5.8.0": - version: 5.8.0 - resolution: "@ethersproject/providers@npm:5.8.0" - dependencies: - "@ethersproject/abstract-provider": ^5.8.0 - "@ethersproject/abstract-signer": ^5.8.0 - "@ethersproject/address": ^5.8.0 - "@ethersproject/base64": ^5.8.0 - "@ethersproject/basex": ^5.8.0 - "@ethersproject/bignumber": ^5.8.0 - "@ethersproject/bytes": ^5.8.0 - "@ethersproject/constants": ^5.8.0 - "@ethersproject/hash": ^5.8.0 - "@ethersproject/logger": ^5.8.0 - "@ethersproject/networks": ^5.8.0 - "@ethersproject/properties": ^5.8.0 - "@ethersproject/random": ^5.8.0 - "@ethersproject/rlp": ^5.8.0 - "@ethersproject/sha2": ^5.8.0 - "@ethersproject/strings": ^5.8.0 - "@ethersproject/transactions": ^5.8.0 - "@ethersproject/web": ^5.8.0 - bech32: 1.1.4 - ws: 8.18.0 - checksum: 2970ee03fe61bc941555b57075d4a12fbb6342ee56181ad75250a75e9418403e85821bbea1b6e17b25ef35e9eaa1c2b2c564dad7d20af2c1f28ba6db9d0c7ce3 - languageName: node - linkType: hard - -"@ethersproject/random@npm:5.8.0, @ethersproject/random@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/random@npm:5.8.0" - dependencies: - "@ethersproject/bytes": ^5.8.0 - "@ethersproject/logger": ^5.8.0 - checksum: c3bec10516b433eca7ddbd5d97cf2c24153f8fb9615225ea2e3b7fab95a6d6434ab8af55ce55527c3aeb00546ee4363a43aecdc0b5a9970a207ab1551783ddef - languageName: node - linkType: hard - -"@ethersproject/rlp@npm:5.8.0, @ethersproject/rlp@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/rlp@npm:5.8.0" - dependencies: - "@ethersproject/bytes": ^5.8.0 - "@ethersproject/logger": ^5.8.0 - checksum: 9d6f646072b3dd61de993210447d35744a851d24d4fe6262856e372f47a1e9d90976031a9fa28c503b1a4f39dd5ab7c20fc9b651b10507a09b40a33cb04a19f1 - languageName: node - linkType: hard - -"@ethersproject/sha2@npm:5.8.0, @ethersproject/sha2@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/sha2@npm:5.8.0" - dependencies: - "@ethersproject/bytes": ^5.8.0 - "@ethersproject/logger": ^5.8.0 - hash.js: 1.1.7 - checksum: ef8916e3033502476fba9358ba1993722ac3bb99e756d5681e4effa3dfa0f0bf0c29d3fa338662830660b45dd359cccb06ba40bc7b62cfd44f4a177b25829404 - languageName: node - linkType: hard - -"@ethersproject/signing-key@npm:5.8.0, @ethersproject/signing-key@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/signing-key@npm:5.8.0" - dependencies: - "@ethersproject/bytes": ^5.8.0 - "@ethersproject/logger": ^5.8.0 - "@ethersproject/properties": ^5.8.0 - bn.js: ^5.2.1 - elliptic: 6.6.1 - hash.js: 1.1.7 - checksum: 8c07741bc8275568130d97da5d37535c813c842240d0b3409d5e057321595eaf65660c207abdee62e2d7ba225d9b82f0b711ac0324c8c9ceb09a815b231b9f55 - languageName: node - linkType: hard - -"@ethersproject/solidity@npm:5.8.0": - version: 5.8.0 - resolution: "@ethersproject/solidity@npm:5.8.0" - dependencies: - "@ethersproject/bignumber": ^5.8.0 - "@ethersproject/bytes": ^5.8.0 - "@ethersproject/keccak256": ^5.8.0 - "@ethersproject/logger": ^5.8.0 - "@ethersproject/sha2": ^5.8.0 - "@ethersproject/strings": ^5.8.0 - checksum: 305166f3f8e8c2f5ad7b0b03ab96d52082fc79b5136601175e1c76d7abd8fd8e3e4b56569dea745dfa2b7fcbfd180c5d824b03fea7e08dd53d515738a35e51dd - languageName: node - linkType: hard - -"@ethersproject/strings@npm:5.8.0, @ethersproject/strings@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/strings@npm:5.8.0" - dependencies: - "@ethersproject/bytes": ^5.8.0 - "@ethersproject/constants": ^5.8.0 - "@ethersproject/logger": ^5.8.0 - checksum: 997396cf1b183ae66ebfd97b9f98fd50415489f9246875e7769e57270ffa1bffbb62f01430eaac3a0c9cb284e122040949efe632a0221012ee47de252a44a483 - languageName: node - linkType: hard - -"@ethersproject/transactions@npm:5.8.0, @ethersproject/transactions@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/transactions@npm:5.8.0" - dependencies: - "@ethersproject/address": ^5.8.0 - "@ethersproject/bignumber": ^5.8.0 - "@ethersproject/bytes": ^5.8.0 - "@ethersproject/constants": ^5.8.0 - "@ethersproject/keccak256": ^5.8.0 - "@ethersproject/logger": ^5.8.0 - "@ethersproject/properties": ^5.8.0 - "@ethersproject/rlp": ^5.8.0 - "@ethersproject/signing-key": ^5.8.0 - checksum: e867516ccc692c3642bfbd34eab6d2acecabb3b964d8e1cced8e450ec4fa490bcf2513efb6252637bc3157ecd5e0250dadd1a08d3ec3150c14478b9ec7715570 - languageName: node - linkType: hard - -"@ethersproject/units@npm:5.8.0": - version: 5.8.0 - resolution: "@ethersproject/units@npm:5.8.0" - dependencies: - "@ethersproject/bignumber": ^5.8.0 - "@ethersproject/constants": ^5.8.0 - "@ethersproject/logger": ^5.8.0 - checksum: cc7180c85f695449c20572602971145346fc5c169ee32f23d79ac31cc8c9c66a2049e3ac852b940ddccbe39ab1db3b81e3e093b604d9ab7ab27639ecb933b270 - languageName: node - linkType: hard - -"@ethersproject/wallet@npm:5.8.0": - version: 5.8.0 - resolution: "@ethersproject/wallet@npm:5.8.0" - dependencies: - "@ethersproject/abstract-provider": ^5.8.0 - "@ethersproject/abstract-signer": ^5.8.0 - "@ethersproject/address": ^5.8.0 - "@ethersproject/bignumber": ^5.8.0 - "@ethersproject/bytes": ^5.8.0 - "@ethersproject/hash": ^5.8.0 - "@ethersproject/hdnode": ^5.8.0 - "@ethersproject/json-wallets": ^5.8.0 - "@ethersproject/keccak256": ^5.8.0 - "@ethersproject/logger": ^5.8.0 - "@ethersproject/properties": ^5.8.0 - "@ethersproject/random": ^5.8.0 - "@ethersproject/signing-key": ^5.8.0 - "@ethersproject/transactions": ^5.8.0 - "@ethersproject/wordlists": ^5.8.0 - checksum: d2921c3212c30a49048e0cba7a8287e0d53a5346ad5a15d46d9932991dc54e541a3da063c47addc1347a4b65142d7239f7056c8716d6f85c8ec4a1bf6b5d2f69 - languageName: node - linkType: hard - -"@ethersproject/web@npm:5.8.0, @ethersproject/web@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/web@npm:5.8.0" - dependencies: - "@ethersproject/base64": ^5.8.0 - "@ethersproject/bytes": ^5.8.0 - "@ethersproject/logger": ^5.8.0 - "@ethersproject/properties": ^5.8.0 - "@ethersproject/strings": ^5.8.0 - checksum: d8ca89bde8777ed1eec81527f8a989b939b4625b2f6c275eea90031637a802ad68bf46911fdd43c5e84ea2962b8a3cb4801ab51f5393ae401a163c17c774123f - languageName: node - linkType: hard - -"@ethersproject/wordlists@npm:5.8.0, @ethersproject/wordlists@npm:^5.8.0": - version: 5.8.0 - resolution: "@ethersproject/wordlists@npm:5.8.0" - dependencies: - "@ethersproject/bytes": ^5.8.0 - "@ethersproject/hash": ^5.8.0 - "@ethersproject/logger": ^5.8.0 - "@ethersproject/properties": ^5.8.0 - "@ethersproject/strings": ^5.8.0 - checksum: ba24300927a3c9cb85ae8ace84a6be73f3c43aac6eab7a3abe58a7dfd3b168caf3f01a4528efa8193e269dd3d5efe9d4533bdf3b29d5c55743edcb2e864d25d9 - languageName: node - linkType: hard - "@expo/cli@npm:^56.1.16": version: 56.1.16 resolution: "@expo/cli@npm:56.1.16" @@ -5641,7 +5229,7 @@ __metadata: ed25519-hd-key: 1.3.0 eslint: ^8.19.0 eslint-plugin-ft-flow: ^2.0.1 - ethers: 5.8.0 + ethers: ^6.13.5 expo: 56.0.12 expo-application: ~56.0.3 expo-clipboard: ~56.0.4 @@ -5787,13 +5375,6 @@ __metadata: languageName: node linkType: hard -"aes-js@npm:3.0.0": - version: 3.0.0 - resolution: "aes-js@npm:3.0.0" - checksum: 251e26d533cd1a915b44896b17d5ed68c24a02484cfdd2e74ec700a309267db96651ea4eb657bf20aac32a3baa61f6e34edf8e2fec2de440a655da9942d334b8 - languageName: node - linkType: hard - "aes-js@npm:4.0.0-beta.5": version: 4.0.0-beta.5 resolution: "aes-js@npm:4.0.0-beta.5" @@ -6418,13 +5999,6 @@ __metadata: languageName: node linkType: hard -"bech32@npm:1.1.4": - version: 1.1.4 - resolution: "bech32@npm:1.1.4" - checksum: 0e98db619191548390d6f09ff68b0253ba7ae6a55db93dfdbb070ba234c1fd3308c0606fbcc95fad50437227b10011e2698b89f0181f6e7f845c499bd14d0f4b - languageName: node - linkType: hard - "big-integer@npm:1.6.x": version: 1.6.52 resolution: "big-integer@npm:1.6.52" @@ -6562,13 +6136,6 @@ __metadata: languageName: node linkType: hard -"brorand@npm:^1.1.0": - version: 1.1.0 - resolution: "brorand@npm:1.1.0" - checksum: 8a05c9f3c4b46572dec6ef71012b1946db6cae8c7bb60ccd4b7dd5a84655db49fe043ecc6272e7ef1f69dc53d6730b9e2a3a03a8310509a3d797a618cbee52be - languageName: node - linkType: hard - "brotli@npm:1.3.3": version: 1.3.3 resolution: "brotli@npm:1.3.3" @@ -7756,21 +7323,6 @@ __metadata: languageName: node linkType: hard -"elliptic@npm:6.6.1": - version: 6.6.1 - resolution: "elliptic@npm:6.6.1" - dependencies: - bn.js: ^4.11.9 - brorand: ^1.1.0 - hash.js: ^1.0.0 - hmac-drbg: ^1.0.1 - inherits: ^2.0.4 - minimalistic-assert: ^1.0.1 - minimalistic-crypto-utils: ^1.0.1 - checksum: 27b14a52f68bbbc0720da259f712cb73e953f6d2047958cd02fb0d0ade2e83849dc39fb4af630889c67df8817e24237428cf59c4f4c07700f755b401149a7375 - languageName: node - linkType: hard - "emittery@npm:^0.13.1": version: 0.13.1 resolution: "emittery@npm:0.13.1" @@ -8394,44 +7946,6 @@ __metadata: languageName: node linkType: hard -"ethers@npm:5.8.0": - version: 5.8.0 - resolution: "ethers@npm:5.8.0" - dependencies: - "@ethersproject/abi": 5.8.0 - "@ethersproject/abstract-provider": 5.8.0 - "@ethersproject/abstract-signer": 5.8.0 - "@ethersproject/address": 5.8.0 - "@ethersproject/base64": 5.8.0 - "@ethersproject/basex": 5.8.0 - "@ethersproject/bignumber": 5.8.0 - "@ethersproject/bytes": 5.8.0 - "@ethersproject/constants": 5.8.0 - "@ethersproject/contracts": 5.8.0 - "@ethersproject/hash": 5.8.0 - "@ethersproject/hdnode": 5.8.0 - "@ethersproject/json-wallets": 5.8.0 - "@ethersproject/keccak256": 5.8.0 - "@ethersproject/logger": 5.8.0 - "@ethersproject/networks": 5.8.0 - "@ethersproject/pbkdf2": 5.8.0 - "@ethersproject/properties": 5.8.0 - "@ethersproject/providers": 5.8.0 - "@ethersproject/random": 5.8.0 - "@ethersproject/rlp": 5.8.0 - "@ethersproject/sha2": 5.8.0 - "@ethersproject/signing-key": 5.8.0 - "@ethersproject/solidity": 5.8.0 - "@ethersproject/strings": 5.8.0 - "@ethersproject/transactions": 5.8.0 - "@ethersproject/units": 5.8.0 - "@ethersproject/wallet": 5.8.0 - "@ethersproject/web": 5.8.0 - "@ethersproject/wordlists": 5.8.0 - checksum: fb107bf28dc3aedde4729f9553be066c699e0636346c095b4deeb5349a0c0c8538f48a58b5c8cbefced008706919739c5f7b8f4dd506bb471a31edee18cda228 - languageName: node - linkType: hard - "ethers@npm:6.13.5": version: 6.13.5 resolution: "ethers@npm:6.13.5" @@ -8447,6 +7961,21 @@ __metadata: languageName: node linkType: hard +"ethers@npm:^6.13.5": + version: 6.17.0 + resolution: "ethers@npm:6.17.0" + dependencies: + "@adraffy/ens-normalize": 1.11.1 + "@noble/curves": 1.2.0 + "@noble/hashes": 1.3.2 + "@types/node": 22.7.5 + aes-js: 4.0.0-beta.5 + tslib: 2.7.0 + ws: 8.21.0 + checksum: 0ba314af2ae25622c60886caf83d825ce543262685961667d166b825c9dbfc66f905e0d7a2e3d8d4ccfa58b6ac20326e7f9a897b5580879efa758a50067ad082 + languageName: node + linkType: hard + "event-target-shim@npm:^5.0.0": version: 5.0.1 resolution: "event-target-shim@npm:5.0.1" @@ -9412,16 +8941,6 @@ __metadata: languageName: node linkType: hard -"hash.js@npm:1.1.7, hash.js@npm:^1.0.0, hash.js@npm:^1.0.3": - version: 1.1.7 - resolution: "hash.js@npm:1.1.7" - dependencies: - inherits: ^2.0.3 - minimalistic-assert: ^1.0.1 - checksum: e350096e659c62422b85fa508e4b3669017311aa4c49b74f19f8e1bc7f3a54a584fdfd45326d4964d6011f2b2d882e38bea775a96046f2a61b7779a979629d8f - languageName: node - linkType: hard - "hasown@npm:^2.0.2": version: 2.0.2 resolution: "hasown@npm:2.0.2" @@ -9504,17 +9023,6 @@ __metadata: languageName: node linkType: hard -"hmac-drbg@npm:^1.0.1": - version: 1.0.1 - resolution: "hmac-drbg@npm:1.0.1" - dependencies: - hash.js: ^1.0.3 - minimalistic-assert: ^1.0.0 - minimalistic-crypto-utils: ^1.0.1 - checksum: bd30b6a68d7f22d63f10e1888aee497d7c2c5c0bb469e66bbdac99f143904d1dfe95f8131f95b3e86c86dd239963c9d972fcbe147e7cffa00e55d18585c43fe0 - languageName: node - linkType: hard - "hoist-non-react-statics@npm:^3.3.0": version: 3.3.2 resolution: "hoist-non-react-statics@npm:3.3.2" @@ -10812,13 +10320,6 @@ __metadata: languageName: node linkType: hard -"js-sha3@npm:0.8.0": - version: 0.8.0 - resolution: "js-sha3@npm:0.8.0" - checksum: 75df77c1fc266973f06cce8309ce010e9e9f07ec35ab12022ed29b7f0d9c8757f5a73e1b35aa24840dced0dea7059085aa143d817aea9e188e2a80d569d9adce - languageName: node - linkType: hard - "js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": version: 4.0.0 resolution: "js-tokens@npm:4.0.0" @@ -11733,20 +11234,6 @@ __metadata: languageName: node linkType: hard -"minimalistic-assert@npm:^1.0.0, minimalistic-assert@npm:^1.0.1": - version: 1.0.1 - resolution: "minimalistic-assert@npm:1.0.1" - checksum: cc7974a9268fbf130fb055aff76700d7e2d8be5f761fb5c60318d0ed010d839ab3661a533ad29a5d37653133385204c503bfac995aaa4236f4e847461ea32ba7 - languageName: node - linkType: hard - -"minimalistic-crypto-utils@npm:^1.0.1": - version: 1.0.1 - resolution: "minimalistic-crypto-utils@npm:1.0.1" - checksum: 6e8a0422b30039406efd4c440829ea8f988845db02a3299f372fceba56ffa94994a9c0f2fd70c17f9969eedfbd72f34b5070ead9656a34d3f71c0bd72583a0ed - languageName: node - linkType: hard - "minimatch@npm:5.1.8": version: 5.1.8 resolution: "minimatch@npm:5.1.8" @@ -13896,13 +13383,6 @@ __metadata: languageName: node linkType: hard -"scrypt-js@npm:3.0.1": - version: 3.0.1 - resolution: "scrypt-js@npm:3.0.1" - checksum: b7c7d1a68d6ca946f2fbb0778e0c4ec63c65501b54023b2af7d7e9f48fdb6c6580d6f7675cd53bda5944c5ebc057560d5a6365079752546865defb3b79dea454 - languageName: node - linkType: hard - "semver@npm:7.7.1": version: 7.7.1 resolution: "semver@npm:7.7.1" @@ -15808,9 +15288,9 @@ __metadata: languageName: node linkType: hard -"ws@npm:8.18.0": - version: 8.18.0 - resolution: "ws@npm:8.18.0" +"ws@npm:8.21.0, ws@npm:^8.11.0, ws@npm:^8.12.1, ws@npm:^8.5.0": + version: 8.21.0 + resolution: "ws@npm:8.21.0" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ">=5.0.2" @@ -15819,7 +15299,7 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: 91d4d35bc99ff6df483bdf029b9ea4bfd7af1f16fc91231a96777a63d263e1eabf486e13a2353970efc534f9faa43bdbf9ee76525af22f4752cbc5ebda333975 + checksum: 83ff89ae011bc5c3c5605a45a0d50e12589143c7500ca4de83a8d43b3cd26e71f422cb3206fd1a9e6d541d666eeb66255c30d095d62d413b3c7afe5d2c5cb928 languageName: node linkType: hard @@ -15847,21 +15327,6 @@ __metadata: languageName: node linkType: hard -"ws@npm:^8.11.0, ws@npm:^8.12.1, ws@npm:^8.5.0": - version: 8.21.0 - resolution: "ws@npm:8.21.0" - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ">=5.0.2" - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: 83ff89ae011bc5c3c5605a45a0d50e12589143c7500ca4de83a8d43b3cd26e71f422cb3206fd1a9e6d541d666eeb66255c30d095d62d413b3c7afe5d2c5cb928 - languageName: node - linkType: hard - "xcode@npm:^3.0.1": version: 3.0.1 resolution: "xcode@npm:3.0.1" From ea0098301ee794e337c407e633459244d01500fa Mon Sep 17 00:00:00 2001 From: Ignacio Santise <25931366+ignaciosantise@users.noreply.github.com> Date: Fri, 3 Jul 2026 10:51:35 -0300 Subject: [PATCH 2/4] chore(rn_cli_wallet): pin ethers to 6.13.5 Co-Authored-By: Claude Opus 4.8 --- wallets/rn_cli_wallet/package.json | 2 +- wallets/rn_cli_wallet/yarn.lock | 49 +++++++++++------------------- 2 files changed, 18 insertions(+), 33 deletions(-) diff --git a/wallets/rn_cli_wallet/package.json b/wallets/rn_cli_wallet/package.json index 719f2c132..8b1cbefd7 100644 --- a/wallets/rn_cli_wallet/package.json +++ b/wallets/rn_cli_wallet/package.json @@ -58,7 +58,7 @@ "crc-32": "1.2.2", "dayjs": "1.11.21", "ed25519-hd-key": "1.3.0", - "ethers": "^6.13.5", + "ethers": "6.13.5", "expo": "56.0.12", "expo-application": "~56.0.3", "expo-clipboard": "~56.0.4", diff --git a/wallets/rn_cli_wallet/yarn.lock b/wallets/rn_cli_wallet/yarn.lock index 30e859f0b..0d31062d7 100644 --- a/wallets/rn_cli_wallet/yarn.lock +++ b/wallets/rn_cli_wallet/yarn.lock @@ -37,7 +37,7 @@ __metadata: languageName: node linkType: hard -"@adraffy/ens-normalize@npm:1.11.1, @adraffy/ens-normalize@npm:^1.11.0": +"@adraffy/ens-normalize@npm:^1.11.0": version: 1.11.1 resolution: "@adraffy/ens-normalize@npm:1.11.1" checksum: e8b17fcc730ccc45a956e1fbb09edfe42be41c291079512082e9964f8ef4287e67913183cdd02fff71d2e215340d5b98a9bbbd9be32c5d36fad4ba2c1ec33ff2 @@ -5229,7 +5229,7 @@ __metadata: ed25519-hd-key: 1.3.0 eslint: ^8.19.0 eslint-plugin-ft-flow: ^2.0.1 - ethers: ^6.13.5 + ethers: 6.13.5 expo: 56.0.12 expo-application: ~56.0.3 expo-clipboard: ~56.0.4 @@ -7961,21 +7961,6 @@ __metadata: languageName: node linkType: hard -"ethers@npm:^6.13.5": - version: 6.17.0 - resolution: "ethers@npm:6.17.0" - dependencies: - "@adraffy/ens-normalize": 1.11.1 - "@noble/curves": 1.2.0 - "@noble/hashes": 1.3.2 - "@types/node": 22.7.5 - aes-js: 4.0.0-beta.5 - tslib: 2.7.0 - ws: 8.21.0 - checksum: 0ba314af2ae25622c60886caf83d825ce543262685961667d166b825c9dbfc66f905e0d7a2e3d8d4ccfa58b6ac20326e7f9a897b5580879efa758a50067ad082 - languageName: node - linkType: hard - "event-target-shim@npm:^5.0.0": version: 5.0.1 resolution: "event-target-shim@npm:5.0.1" @@ -15288,21 +15273,6 @@ __metadata: languageName: node linkType: hard -"ws@npm:8.21.0, ws@npm:^8.11.0, ws@npm:^8.12.1, ws@npm:^8.5.0": - version: 8.21.0 - resolution: "ws@npm:8.21.0" - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ">=5.0.2" - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: 83ff89ae011bc5c3c5605a45a0d50e12589143c7500ca4de83a8d43b3cd26e71f422cb3206fd1a9e6d541d666eeb66255c30d095d62d413b3c7afe5d2c5cb928 - languageName: node - linkType: hard - "ws@npm:^6.2.3": version: 6.2.4 resolution: "ws@npm:6.2.4" @@ -15327,6 +15297,21 @@ __metadata: languageName: node linkType: hard +"ws@npm:^8.11.0, ws@npm:^8.12.1, ws@npm:^8.5.0": + version: 8.21.0 + resolution: "ws@npm:8.21.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 83ff89ae011bc5c3c5605a45a0d50e12589143c7500ca4de83a8d43b3cd26e71f422cb3206fd1a9e6d541d666eeb66255c30d095d62d413b3c7afe5d2c5cb928 + languageName: node + linkType: hard + "xcode@npm:^3.0.1": version: 3.0.1 resolution: "xcode@npm:3.0.1" From 9fcfaf20158a11ba4a3087468b80f8a728a579d4 Mon Sep 17 00:00:00 2001 From: Ignacio Santise <25931366+ignaciosantise@users.noreply.github.com> Date: Fri, 3 Jul 2026 14:36:41 -0300 Subject: [PATCH 3/4] fix(rn_cli_wallet): use ?? for v6 bigint fee fields; update AGENTS.md ethers version Address PR review: - buildFreshTxRequest: `|| null` coerced a valid `0n` fee to null (bigint is falsy in v6, unlike v5 BigNumber) and dropped EIP-1559 fields on chains returning maxPriorityFeePerGas/maxFeePerGas = 0n. Use `?? null`. - AGENTS.md: ethers 5.8.0 -> 6.13.5. Co-Authored-By: Claude Opus 4.8 --- wallets/rn_cli_wallet/AGENTS.md | 2 +- wallets/rn_cli_wallet/src/utils/PaymentTransactionUtil.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/wallets/rn_cli_wallet/AGENTS.md b/wallets/rn_cli_wallet/AGENTS.md index baa7eb37d..66e51f45f 100644 --- a/wallets/rn_cli_wallet/AGENTS.md +++ b/wallets/rn_cli_wallet/AGENTS.md @@ -26,7 +26,7 @@ This is a production-ready reference implementation for developers building wall - **@walletconnect/pay**: WalletConnect Pay integration ### Blockchain Libraries -- **ethers** (5.8.0): Ethereum/EVM interactions +- **ethers** (6.13.5): Ethereum/EVM interactions - **@mysten/sui**: Sui blockchain support - **@ton/core**, **@ton/crypto**, **@ton/ton**: TON blockchain - **tronweb**: Tron blockchain diff --git a/wallets/rn_cli_wallet/src/utils/PaymentTransactionUtil.ts b/wallets/rn_cli_wallet/src/utils/PaymentTransactionUtil.ts index 92b1024ac..f5a227a25 100644 --- a/wallets/rn_cli_wallet/src/utils/PaymentTransactionUtil.ts +++ b/wallets/rn_cli_wallet/src/utils/PaymentTransactionUtil.ts @@ -276,7 +276,7 @@ export function buildFreshTxRequest({ chainId === 'eip155:137' ? POLYGON_MIN_PRIORITY_FEE_WEI : null; const priorityFee = getHighestBigInt([ chainFloor, - feeData.maxPriorityFeePerGas || null, + feeData.maxPriorityFeePerGas ?? null, ]); const maxFee = priorityFee @@ -284,7 +284,7 @@ export function buildFreshTxRequest({ latestBlock.baseFeePerGas ? latestBlock.baseFeePerGas * 2n + priorityFee : null, - feeData.maxFeePerGas || null, + feeData.maxFeePerGas ?? null, priorityFee, ]) : null; From 9c081f87493aea8ab1d73ee415a87e95c4ca7619 Mon Sep 17 00:00:00 2001 From: Ignacio Santise <25931366+ignaciosantise@users.noreply.github.com> Date: Mon, 6 Jul 2026 09:49:22 -0300 Subject: [PATCH 4/4] fix(rn_cli_wallet): use explicit null checks for bigint fees in buildFreshTxRequest Address Copilot review: 0n is falsy in JS, so truthy checks on ethers v6 bigint fee fields dropped valid zero values (e.g. maxPriorityFeePerGas=0n on L2s without miner tips). Replace truthy checks with != null / == null for priorityFee, maxFee, baseFeePerGas and the gasPrice fallback branch. Co-Authored-By: Claude Opus 4.8 --- .../src/utils/PaymentTransactionUtil.ts | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/wallets/rn_cli_wallet/src/utils/PaymentTransactionUtil.ts b/wallets/rn_cli_wallet/src/utils/PaymentTransactionUtil.ts index f5a227a25..e3bebb265 100644 --- a/wallets/rn_cli_wallet/src/utils/PaymentTransactionUtil.ts +++ b/wallets/rn_cli_wallet/src/utils/PaymentTransactionUtil.ts @@ -279,37 +279,38 @@ export function buildFreshTxRequest({ feeData.maxPriorityFeePerGas ?? null, ]); - const maxFee = priorityFee - ? getHighestBigInt([ - latestBlock.baseFeePerGas - ? latestBlock.baseFeePerGas * 2n + priorityFee - : null, - feeData.maxFeePerGas ?? null, - priorityFee, - ]) - : null; + const maxFee = + priorityFee != null + ? getHighestBigInt([ + latestBlock.baseFeePerGas != null + ? latestBlock.baseFeePerGas * 2n + priorityFee + : null, + feeData.maxFeePerGas ?? null, + priorityFee, + ]) + : null; const request: TransactionRequest = { ...baseTx }; - if (priorityFee) { + if (priorityFee != null) { request.maxPriorityFeePerGas = priorityFee; } else { delete request.maxPriorityFeePerGas; } - if (maxFee) { + if (maxFee != null) { request.maxFeePerGas = maxFee; } else { delete request.maxFeePerGas; } if ( - !request.maxPriorityFeePerGas && - !request.maxFeePerGas && - feeData.gasPrice + request.maxPriorityFeePerGas == null && + request.maxFeePerGas == null && + feeData.gasPrice != null ) { const gasPrice = getHighestBigInt([feeData.gasPrice, chainFloor]); - if (gasPrice) { + if (gasPrice != null) { request.gasPrice = gasPrice; } } else {