@metamask/transaction-pay-controller 23.16.1 → 23.17.1
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/CHANGELOG.md +20 -1
- package/dist/strategy/fiat/chomp.cjs +58 -0
- package/dist/strategy/fiat/chomp.cjs.map +1 -0
- package/dist/strategy/fiat/chomp.d.cts +9 -0
- package/dist/strategy/fiat/chomp.d.cts.map +1 -0
- package/dist/strategy/fiat/chomp.d.mts +9 -0
- package/dist/strategy/fiat/chomp.d.mts.map +1 -0
- package/dist/strategy/fiat/chomp.mjs +54 -0
- package/dist/strategy/fiat/chomp.mjs.map +1 -0
- package/dist/strategy/fiat/fiat-direct-musd.cjs +50 -3
- package/dist/strategy/fiat/fiat-direct-musd.cjs.map +1 -1
- package/dist/strategy/fiat/fiat-direct-musd.d.cts +7 -2
- package/dist/strategy/fiat/fiat-direct-musd.d.cts.map +1 -1
- package/dist/strategy/fiat/fiat-direct-musd.d.mts +7 -2
- package/dist/strategy/fiat/fiat-direct-musd.d.mts.map +1 -1
- package/dist/strategy/fiat/fiat-direct-musd.mjs +50 -3
- package/dist/strategy/fiat/fiat-direct-musd.mjs.map +1 -1
- package/dist/strategy/fiat/fiat-submit.cjs +29 -3
- package/dist/strategy/fiat/fiat-submit.cjs.map +1 -1
- package/dist/strategy/fiat/fiat-submit.d.cts.map +1 -1
- package/dist/strategy/fiat/fiat-submit.d.mts.map +1 -1
- package/dist/strategy/fiat/fiat-submit.mjs +29 -3
- package/dist/strategy/fiat/fiat-submit.mjs.map +1 -1
- package/dist/strategy/fiat/utils.cjs +9 -4
- package/dist/strategy/fiat/utils.cjs.map +1 -1
- package/dist/strategy/fiat/utils.d.cts +20 -2
- package/dist/strategy/fiat/utils.d.cts.map +1 -1
- package/dist/strategy/fiat/utils.d.mts +20 -2
- package/dist/strategy/fiat/utils.d.mts.map +1 -1
- package/dist/strategy/fiat/utils.mjs +9 -4
- package/dist/strategy/fiat/utils.mjs.map +1 -1
- package/dist/tests/messenger-mock.d.cts +1 -1
- package/dist/tests/messenger-mock.d.mts +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +2 -2
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +2 -2
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/dist/utils/quotes.cjs +8 -1
- package/dist/utils/quotes.cjs.map +1 -1
- package/dist/utils/quotes.d.cts.map +1 -1
- package/dist/utils/quotes.d.mts.map +1 -1
- package/dist/utils/quotes.mjs +8 -1
- package/dist/utils/quotes.mjs.map +1 -1
- package/dist/utils/transaction.cjs +11 -8
- package/dist/utils/transaction.cjs.map +1 -1
- package/dist/utils/transaction.d.cts +16 -4
- package/dist/utils/transaction.d.cts.map +1 -1
- package/dist/utils/transaction.d.mts +16 -4
- package/dist/utils/transaction.d.mts.map +1 -1
- package/dist/utils/transaction.mjs +11 -8
- package/dist/utils/transaction.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transaction.cjs","sourceRoot":"","sources":["../../src/utils/transaction.ts"],"names":[],"mappings":"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","sourcesContent":["import { Interface } from '@ethersproject/abi';\nimport { abiERC20 } from '@metamask/metamask-eth-abis';\nimport {\n TransactionStatus,\n TransactionType,\n} from '@metamask/transaction-controller';\nimport type { TransactionMeta } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\nimport type { Patch } from 'immer';\nimport { cloneDeep } from 'lodash';\n\nimport { projectLogger } from '../logger';\nimport type {\n TransactionPayControllerMessenger,\n TransactionPayControllerState,\n UpdateTransactionDataCallback,\n} from '../types';\nimport { getAssetsUnifyStateFeature } from './feature-flags';\nimport { rpcRequest } from './provider';\nimport { parseRequiredTokens } from './required-tokens';\nimport { getNativeToken } from './token';\n\nconst log = createModuleLogger(projectLogger, 'transaction');\n\nexport const FINALIZED_STATUSES = [\n TransactionStatus.confirmed,\n TransactionStatus.dropped,\n TransactionStatus.failed,\n];\n\n/**\n * Retrieve transaction metadata by ID.\n *\n * @param transactionId - ID of the transaction to retrieve.\n * @param messenger - Controller messenger.\n * @returns The transaction metadata or undefined if not found.\n */\nexport function getTransaction(\n transactionId: string,\n messenger: TransactionPayControllerMessenger,\n): TransactionMeta | undefined {\n const transactionControllerState = messenger.call(\n 'TransactionController:getState',\n );\n\n return transactionControllerState.transactions.find(\n (tx) => tx.id === transactionId,\n );\n}\n\n/**\n * Subscribe to transaction changes and update the transaction data accordingly.\n *\n * @param messenger - Controller messenger.\n * @param updateTransactionData - Callback to update transaction data.\n * @param removeTransactionData - Callback to remove transaction data.\n */\nexport function subscribeTransactionChanges(\n messenger: TransactionPayControllerMessenger,\n updateTransactionData: UpdateTransactionDataCallback,\n removeTransactionData: (transactionId: string) => void,\n): void {\n messenger.subscribe(\n 'TransactionController:stateChange',\n (\n transactions: TransactionMeta[],\n previousTransactions: TransactionMeta[] | undefined,\n ) => {\n const newTransactions = transactions.filter(\n (tx) => !previousTransactions?.find((prevTx) => prevTx.id === tx.id),\n );\n\n const updatedTransactions = transactions.filter((tx) => {\n const previousTransaction = previousTransactions?.find(\n (prevTx) => prevTx.id === tx.id,\n );\n\n return (\n previousTransaction &&\n previousTransaction?.txParams.data !== tx.txParams.data\n );\n });\n\n const finalizedTransactions = transactions.filter((tx) => {\n const previousTransaction = previousTransactions?.find(\n (prevTx) => prevTx.id === tx.id,\n );\n\n return (\n previousTransaction &&\n !FINALIZED_STATUSES.includes(previousTransaction.status) &&\n FINALIZED_STATUSES.includes(tx.status)\n );\n });\n\n const deletedTransactions = (previousTransactions ?? []).filter(\n (prevTx) => !transactions.find((tx) => tx.id === prevTx.id),\n );\n\n [...finalizedTransactions, ...deletedTransactions].forEach((tx) =>\n onTransactionFinalized(tx, removeTransactionData),\n );\n\n [...newTransactions, ...updatedTransactions].forEach((tx) =>\n onTransactionChange(tx, messenger, updateTransactionData),\n );\n },\n (state) => state.transactions,\n );\n}\n\n/**\n * Subscribe to asset state changes and re-parse required tokens for\n * in-flight transactions whose tokens have not yet resolved.\n *\n * @param messenger - Controller messenger.\n * @param getControllerState - Callback returning the current controller state.\n * @param updateTransactionData - Callback to update transaction data.\n */\nexport function subscribeAssetChanges(\n messenger: TransactionPayControllerMessenger,\n getControllerState: () => TransactionPayControllerState,\n updateTransactionData: UpdateTransactionDataCallback,\n): void {\n const buildHandler =\n (source: string) =>\n (_state: unknown, patches: Patch[] | undefined): void => {\n const { transactionData } = getControllerState();\n\n for (const [transactionId, data] of Object.entries(transactionData)) {\n if (data.tokens.length > 0) {\n continue;\n }\n\n const transaction = getTransaction(transactionId, messenger);\n\n if (!transaction || FINALIZED_STATUSES.includes(transaction.status)) {\n continue;\n }\n\n log('Asset data changed', { transactionId, source, patches });\n\n onTransactionChange(transaction, messenger, updateTransactionData);\n }\n };\n\n if (getAssetsUnifyStateFeature(messenger)) {\n messenger.subscribe(\n 'AssetsController:stateChange',\n buildHandler('AssetsController'),\n );\n return;\n }\n\n messenger.subscribe(\n 'TokensController:stateChange',\n buildHandler('TokensController'),\n );\n messenger.subscribe(\n 'TokenRatesController:stateChange',\n buildHandler('TokenRatesController'),\n );\n messenger.subscribe(\n 'CurrencyRateController:stateChange',\n buildHandler('CurrencyRateController'),\n );\n}\n\n/**\n * Wait for a transaction to be confirmed or fail.\n *\n * @param transactionId - ID of the transaction to wait for.\n * @param messenger - Controller messenger.\n * @returns A promise that resolves when the transaction is confirmed or rejects if it fails.\n */\nexport function waitForTransactionConfirmed(\n transactionId: string,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n const isConfirmed = (tx?: TransactionMeta, fn?: () => void): boolean => {\n log('Checking transaction status', tx?.status, tx?.type);\n\n if (tx?.status === TransactionStatus.confirmed) {\n fn?.();\n resolve();\n return true;\n }\n\n if (\n [TransactionStatus.dropped, TransactionStatus.failed].includes(\n tx?.status as TransactionStatus,\n )\n ) {\n fn?.();\n reject(\n new Error(`Transaction failed - ${tx?.type} - ${tx?.error?.message}`),\n );\n return true;\n }\n\n return false;\n };\n\n const initialState = messenger.call('TransactionController:getState');\n\n const initialTx = initialState.transactions.find(\n (singleTransaction) => singleTransaction.id === transactionId,\n );\n\n if (isConfirmed(initialTx)) {\n return;\n }\n\n const handler = (tx?: TransactionMeta): void => {\n const unsubscribe = (): void =>\n messenger.unsubscribe('TransactionController:stateChange', handler);\n\n isConfirmed(tx, unsubscribe);\n };\n\n messenger.subscribe('TransactionController:stateChange', handler, (state) =>\n state.transactions.find((tx) => tx.id === transactionId),\n );\n });\n}\n\n/**\n * Update a transaction by applying a function to its draft.\n *\n * @param request - Request object.\n * @param request.transactionId - ID of the transaction to update.\n * @param request.messenger - Controller messenger.\n * @param request.note - Note describing the update.\n * @param fn - Function that applies updates to the transaction draft.\n */\nexport function updateTransaction(\n {\n transactionId,\n messenger,\n note,\n }: {\n transactionId: string;\n messenger: TransactionPayControllerMessenger;\n note: string;\n },\n fn: (draft: TransactionMeta) => void,\n): void {\n const transaction = getTransaction(transactionId, messenger as never);\n\n if (!transaction) {\n throw new Error(`Transaction not found: ${transactionId}`);\n }\n\n const newTransaction = cloneDeep(transaction);\n\n fn(newTransaction);\n\n messenger.call(\n 'TransactionController:updateTransaction',\n newTransaction,\n note,\n );\n}\n\n/**\n * Collect all new transactions until `end` is called.\n *\n * @param chainId - The chain ID to filter transactions by.\n * @param from - The address to filter transactions by.\n * @param messenger - The controller messenger.\n * @param onTransaction - Callback called with each matching transaction ID.\n * @returns An object with an `end` method to stop collecting transactions.\n */\nexport function collectTransactionIds(\n chainId: Hex,\n from: Hex,\n messenger: TransactionPayControllerMessenger,\n onTransaction: (transactionId: string) => void,\n): { end: () => void } {\n const listener = (tx: TransactionMeta): void => {\n if (\n tx.chainId !== chainId ||\n tx.txParams.from.toLowerCase() !== from.toLowerCase()\n ) {\n return;\n }\n\n onTransaction(tx.id);\n };\n\n messenger.subscribe(\n 'TransactionController:unapprovedTransactionAdded',\n listener,\n );\n\n const end = (): void => {\n messenger.unsubscribe(\n 'TransactionController:unapprovedTransactionAdded',\n listener,\n );\n };\n\n return { end };\n}\n\n/**\n * Check whether a transaction is a Predict withdrawal.\n *\n * Returns `true` when the transaction's own type is `predictWithdraw`, or\n * when any of its nested transactions has that type.\n *\n * @param transaction - Transaction metadata.\n * @returns `true` when the transaction is a Predict withdrawal.\n */\nexport function isPredictWithdrawTransaction(\n transaction: TransactionMeta,\n): boolean {\n return (\n transaction.type === TransactionType.predictWithdraw ||\n (transaction.nestedTransactions?.some(\n (nt) => nt.type === TransactionType.predictWithdraw,\n ) ??\n false)\n );\n}\n\n/**\n * Handle a transaction change by updating its associated data.\n *\n * @param transaction - Transaction metadata.\n * @param messenger - Controller messenger.\n * @param updateTransactionData - Callback to update transaction data.\n */\nfunction onTransactionChange(\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n updateTransactionData: UpdateTransactionDataCallback,\n): void {\n const tokens = parseRequiredTokens(transaction, messenger);\n\n log('Transaction changed', { transaction, tokens });\n\n updateTransactionData(transaction.id, (data) => {\n data.tokens = tokens;\n });\n}\n\n/**\n * Handle a finalized transaction by removing its associated data.\n *\n * @param transaction - Transaction metadata.\n * @param removeTransactionData - Callback to remove transaction data.\n */\nfunction onTransactionFinalized(\n transaction: TransactionMeta,\n removeTransactionData: (transactionId: string) => void,\n): void {\n log('Transaction finalized', { transaction });\n removeTransactionData(transaction.id);\n}\n\nconst erc20Interface = new Interface(abiERC20);\n\nconst ERC20_TRANSFER_EVENT_TOPIC = erc20Interface.getEventTopic('Transfer');\n\n/**\n * Reads the transferred token amount from a completed on-chain transaction.\n *\n * For native tokens the amount is resolved via `debug_traceTransaction`\n * (internal-call aware), falling back to the top-level `tx.value`.\n * For ERC-20 tokens the amount is decoded from `Transfer` event logs\n * in the transaction receipt.\n *\n * @param options - The options.\n * @param options.messenger - Controller messenger for network access.\n * @param options.txHash - Transaction hash of the completed on-chain transaction.\n * @param options.chainId - Chain ID where the transaction was executed.\n * @param options.tokenAddress - Address of the transferred token.\n * @param options.walletAddress - Recipient wallet address to filter transfers to.\n * @returns The raw (atomic) transferred amount as a decimal string,\n * or `undefined` if the amount cannot be determined.\n */\nexport async function getTransferredAmountFromTxHash({\n messenger,\n txHash,\n chainId,\n tokenAddress,\n walletAddress,\n}: {\n messenger: TransactionPayControllerMessenger;\n txHash: string;\n chainId: Hex;\n tokenAddress: Hex;\n walletAddress: Hex;\n}): Promise<string | undefined> {\n const isNative =\n tokenAddress.toLowerCase() === getNativeToken(chainId).toLowerCase();\n\n if (isNative) {\n return await getNativeTransferAmount(\n messenger,\n chainId,\n txHash,\n walletAddress,\n );\n }\n\n return await getErc20TransferAmount(\n messenger,\n chainId,\n txHash,\n tokenAddress,\n walletAddress,\n );\n}\n\n/**\n * Resolves the native token amount received by a wallet from a transaction.\n *\n * 1. Attempts `debug_traceTransaction` with `callTracer` to walk internal\n * calls and sum all native value transfers targeting `walletAddress`.\n * 2. Falls back to the top-level `tx.value` when the wallet is the direct\n * recipient and the trace RPC is unavailable or errors.\n *\n * @param messenger - Controller messenger.\n * @param chainId - Chain ID where the transaction was executed.\n * @param txHash - Transaction hash.\n * @param walletAddress - Recipient wallet address.\n * @returns Raw amount as a decimal string, or `undefined`.\n */\nasync function getNativeTransferAmount(\n messenger: TransactionPayControllerMessenger,\n chainId: Hex,\n txHash: string,\n walletAddress: Hex,\n): Promise<string | undefined> {\n try {\n const trace = await rpcRequest<CallTrace>({\n messenger,\n chainId,\n method: 'debug_traceTransaction',\n params: [txHash, { tracer: 'callTracer' }],\n });\n\n const amount = sumNativeValueFromTrace(trace, walletAddress);\n if (amount.gt(0)) {\n return amount.toFixed(0);\n }\n } catch {\n // debug_traceTransaction not supported — fall through to tx.value\n }\n\n const tx = await rpcRequest<{ to?: string; value: string } | null>({\n messenger,\n chainId,\n method: 'eth_getTransactionByHash',\n params: [txHash],\n });\n\n if (!tx) {\n return undefined;\n }\n\n if (tx.to?.toLowerCase() !== walletAddress.toLowerCase()) {\n return undefined;\n }\n\n return positiveOrUndefined(new BigNumber(tx.value).toFixed(0));\n}\n\n/**\n * Resolves the ERC-20 token amount received by a wallet from a transaction\n * by decoding `Transfer` event logs from the transaction receipt.\n *\n * @param messenger - Controller messenger.\n * @param chainId - Chain ID where the transaction was executed.\n * @param txHash - Transaction hash.\n * @param tokenAddress - ERC-20 token contract address.\n * @param walletAddress - Recipient wallet address.\n * @returns Raw amount as a decimal string, or `undefined`.\n */\nasync function getErc20TransferAmount(\n messenger: TransactionPayControllerMessenger,\n chainId: Hex,\n txHash: string,\n tokenAddress: Hex,\n walletAddress: Hex,\n): Promise<string | undefined> {\n const receipt = await rpcRequest<{\n logs: { address: string; topics: string[]; data: string }[];\n } | null>({\n messenger,\n chainId,\n method: 'eth_getTransactionReceipt',\n params: [txHash],\n });\n\n if (!receipt) {\n return undefined;\n }\n\n let total = new BigNumber(0);\n\n for (const txLog of receipt.logs) {\n if (txLog.address.toLowerCase() !== tokenAddress.toLowerCase()) {\n continue;\n }\n\n if (!txLog.topics[0] || txLog.topics[0] !== ERC20_TRANSFER_EVENT_TOPIC) {\n continue;\n }\n\n try {\n const parsed = erc20Interface.parseLog(txLog);\n const to = (parsed.args[1] as string).toLowerCase();\n\n if (to !== walletAddress.toLowerCase()) {\n continue;\n }\n\n total = total.plus(parsed.args[2].toString());\n } catch {\n continue;\n }\n }\n\n return positiveOrUndefined(total.toFixed(0));\n}\n\ntype CallTrace = {\n to?: string;\n value?: string;\n calls?: CallTrace[];\n};\n\n/**\n * Recursively walks a `callTracer` result and sums native value\n * transferred to a specific address.\n *\n * @param trace - Call trace node.\n * @param walletAddress - Target address to accumulate value for.\n * @returns Accumulated native value as BigNumber.\n */\nfunction sumNativeValueFromTrace(\n trace: CallTrace,\n walletAddress: Hex,\n): BigNumber {\n let total = new BigNumber(0);\n\n if (\n trace.to?.toLowerCase() === walletAddress.toLowerCase() &&\n trace.value &&\n trace.value !== '0x0'\n ) {\n total = total.plus(new BigNumber(trace.value));\n }\n\n if (trace.calls) {\n for (const child of trace.calls) {\n total = total.plus(sumNativeValueFromTrace(child, walletAddress));\n }\n }\n\n return total;\n}\n\nfunction positiveOrUndefined(amount: string): string | undefined {\n return new BigNumber(amount).gt(0) ? amount : undefined;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"transaction.cjs","sourceRoot":"","sources":["../../src/utils/transaction.ts"],"names":[],"mappings":"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","sourcesContent":["import { Interface } from '@ethersproject/abi';\nimport { abiERC20 } from '@metamask/metamask-eth-abis';\nimport {\n TransactionStatus,\n TransactionType,\n} from '@metamask/transaction-controller';\nimport type { TransactionMeta } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\nimport type { Patch } from 'immer';\nimport { cloneDeep } from 'lodash';\n\nimport { projectLogger } from '../logger';\nimport type {\n TransactionPayControllerMessenger,\n TransactionPayControllerState,\n UpdateTransactionDataCallback,\n} from '../types';\nimport { getAssetsUnifyStateFeature } from './feature-flags';\nimport { rpcRequest } from './provider';\nimport { parseRequiredTokens } from './required-tokens';\nimport { getNativeToken } from './token';\n\nconst log = createModuleLogger(projectLogger, 'transaction');\n\nexport const FINALIZED_STATUSES = [\n TransactionStatus.confirmed,\n TransactionStatus.dropped,\n TransactionStatus.failed,\n];\n\n/**\n * Retrieve transaction metadata by ID.\n *\n * @param transactionId - ID of the transaction to retrieve.\n * @param messenger - Controller messenger.\n * @returns The transaction metadata or undefined if not found.\n */\nexport function getTransaction(\n transactionId: string,\n messenger: TransactionPayControllerMessenger,\n): TransactionMeta | undefined {\n const transactionControllerState = messenger.call(\n 'TransactionController:getState',\n );\n\n return transactionControllerState.transactions.find(\n (tx) => tx.id === transactionId,\n );\n}\n\n/**\n * Subscribe to transaction changes and update the transaction data accordingly.\n *\n * @param messenger - Controller messenger.\n * @param updateTransactionData - Callback to update transaction data.\n * @param removeTransactionData - Callback to remove transaction data.\n */\nexport function subscribeTransactionChanges(\n messenger: TransactionPayControllerMessenger,\n updateTransactionData: UpdateTransactionDataCallback,\n removeTransactionData: (transactionId: string) => void,\n): void {\n messenger.subscribe(\n 'TransactionController:stateChange',\n (\n transactions: TransactionMeta[],\n previousTransactions: TransactionMeta[] | undefined,\n ) => {\n const newTransactions = transactions.filter(\n (tx) => !previousTransactions?.find((prevTx) => prevTx.id === tx.id),\n );\n\n const updatedTransactions = transactions.filter((tx) => {\n const previousTransaction = previousTransactions?.find(\n (prevTx) => prevTx.id === tx.id,\n );\n\n return (\n previousTransaction &&\n previousTransaction?.txParams.data !== tx.txParams.data\n );\n });\n\n const finalizedTransactions = transactions.filter((tx) => {\n const previousTransaction = previousTransactions?.find(\n (prevTx) => prevTx.id === tx.id,\n );\n\n return (\n previousTransaction &&\n !FINALIZED_STATUSES.includes(previousTransaction.status) &&\n FINALIZED_STATUSES.includes(tx.status)\n );\n });\n\n const deletedTransactions = (previousTransactions ?? []).filter(\n (prevTx) => !transactions.find((tx) => tx.id === prevTx.id),\n );\n\n [...finalizedTransactions, ...deletedTransactions].forEach((tx) =>\n onTransactionFinalized(tx, removeTransactionData),\n );\n\n [...newTransactions, ...updatedTransactions].forEach((tx) =>\n onTransactionChange(tx, messenger, updateTransactionData),\n );\n },\n (state) => state.transactions,\n );\n}\n\n/**\n * Subscribe to asset state changes and re-parse required tokens for\n * in-flight transactions whose tokens have not yet resolved.\n *\n * @param messenger - Controller messenger.\n * @param getControllerState - Callback returning the current controller state.\n * @param updateTransactionData - Callback to update transaction data.\n */\nexport function subscribeAssetChanges(\n messenger: TransactionPayControllerMessenger,\n getControllerState: () => TransactionPayControllerState,\n updateTransactionData: UpdateTransactionDataCallback,\n): void {\n const buildHandler =\n (source: string) =>\n (_state: unknown, patches: Patch[] | undefined): void => {\n const { transactionData } = getControllerState();\n\n for (const [transactionId, data] of Object.entries(transactionData)) {\n if (data.tokens.length > 0) {\n continue;\n }\n\n const transaction = getTransaction(transactionId, messenger);\n\n if (!transaction || FINALIZED_STATUSES.includes(transaction.status)) {\n continue;\n }\n\n log('Asset data changed', { transactionId, source, patches });\n\n onTransactionChange(transaction, messenger, updateTransactionData);\n }\n };\n\n if (getAssetsUnifyStateFeature(messenger)) {\n messenger.subscribe(\n 'AssetsController:stateChange',\n buildHandler('AssetsController'),\n );\n return;\n }\n\n messenger.subscribe(\n 'TokensController:stateChange',\n buildHandler('TokensController'),\n );\n messenger.subscribe(\n 'TokenRatesController:stateChange',\n buildHandler('TokenRatesController'),\n );\n messenger.subscribe(\n 'CurrencyRateController:stateChange',\n buildHandler('CurrencyRateController'),\n );\n}\n\n/**\n * Wait for a transaction to be confirmed or fail.\n *\n * @param transactionId - ID of the transaction to wait for.\n * @param messenger - Controller messenger.\n * @returns A promise that resolves when the transaction is confirmed or rejects if it fails.\n */\nexport function waitForTransactionConfirmed(\n transactionId: string,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n const isConfirmed = (tx?: TransactionMeta, fn?: () => void): boolean => {\n log('Checking transaction status', tx?.status, tx?.type);\n\n if (tx?.status === TransactionStatus.confirmed) {\n fn?.();\n resolve();\n return true;\n }\n\n if (\n [TransactionStatus.dropped, TransactionStatus.failed].includes(\n tx?.status as TransactionStatus,\n )\n ) {\n fn?.();\n reject(\n new Error(`Transaction failed - ${tx?.type} - ${tx?.error?.message}`),\n );\n return true;\n }\n\n return false;\n };\n\n const initialState = messenger.call('TransactionController:getState');\n\n const initialTx = initialState.transactions.find(\n (singleTransaction) => singleTransaction.id === transactionId,\n );\n\n if (isConfirmed(initialTx)) {\n return;\n }\n\n const handler = (tx?: TransactionMeta): void => {\n const unsubscribe = (): void =>\n messenger.unsubscribe('TransactionController:stateChange', handler);\n\n isConfirmed(tx, unsubscribe);\n };\n\n messenger.subscribe('TransactionController:stateChange', handler, (state) =>\n state.transactions.find((tx) => tx.id === transactionId),\n );\n });\n}\n\n/**\n * Update a transaction by applying a function to its draft.\n *\n * @param request - Request object.\n * @param request.transactionId - ID of the transaction to update.\n * @param request.messenger - Controller messenger.\n * @param request.note - Note describing the update.\n * @param fn - Function that applies updates to the transaction draft.\n */\nexport function updateTransaction(\n {\n transactionId,\n messenger,\n note,\n }: {\n transactionId: string;\n messenger: TransactionPayControllerMessenger;\n note: string;\n },\n fn: (draft: TransactionMeta) => void,\n): void {\n const transaction = getTransaction(transactionId, messenger as never);\n\n if (!transaction) {\n throw new Error(`Transaction not found: ${transactionId}`);\n }\n\n const newTransaction = cloneDeep(transaction);\n\n fn(newTransaction);\n\n messenger.call(\n 'TransactionController:updateTransaction',\n newTransaction,\n note,\n );\n}\n\n/**\n * Collect all new transactions until `end` is called.\n *\n * @param chainId - The chain ID to filter transactions by.\n * @param from - The address to filter transactions by.\n * @param messenger - The controller messenger.\n * @param onTransaction - Callback called with each matching transaction ID.\n * @returns An object with an `end` method to stop collecting transactions.\n */\nexport function collectTransactionIds(\n chainId: Hex,\n from: Hex,\n messenger: TransactionPayControllerMessenger,\n onTransaction: (transactionId: string) => void,\n): { end: () => void } {\n const listener = (tx: TransactionMeta): void => {\n if (\n tx.chainId !== chainId ||\n tx.txParams.from.toLowerCase() !== from.toLowerCase()\n ) {\n return;\n }\n\n onTransaction(tx.id);\n };\n\n messenger.subscribe(\n 'TransactionController:unapprovedTransactionAdded',\n listener,\n );\n\n const end = (): void => {\n messenger.unsubscribe(\n 'TransactionController:unapprovedTransactionAdded',\n listener,\n );\n };\n\n return { end };\n}\n\n/**\n * Check whether a transaction is a Predict withdrawal.\n *\n * Returns `true` when the transaction's own type is `predictWithdraw`, or\n * when any of its nested transactions has that type.\n *\n * @param transaction - Transaction metadata.\n * @returns `true` when the transaction is a Predict withdrawal.\n */\nexport function isPredictWithdrawTransaction(\n transaction: TransactionMeta,\n): boolean {\n return (\n transaction.type === TransactionType.predictWithdraw ||\n (transaction.nestedTransactions?.some(\n (nt) => nt.type === TransactionType.predictWithdraw,\n ) ??\n false)\n );\n}\n\n/**\n * Handle a transaction change by updating its associated data.\n *\n * @param transaction - Transaction metadata.\n * @param messenger - Controller messenger.\n * @param updateTransactionData - Callback to update transaction data.\n */\nfunction onTransactionChange(\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n updateTransactionData: UpdateTransactionDataCallback,\n): void {\n const tokens = parseRequiredTokens(transaction, messenger);\n\n log('Transaction changed', { transaction, tokens });\n\n updateTransactionData(transaction.id, (data) => {\n data.tokens = tokens;\n });\n}\n\n/**\n * Handle a finalized transaction by removing its associated data.\n *\n * @param transaction - Transaction metadata.\n * @param removeTransactionData - Callback to remove transaction data.\n */\nfunction onTransactionFinalized(\n transaction: TransactionMeta,\n removeTransactionData: (transactionId: string) => void,\n): void {\n log('Transaction finalized', { transaction });\n removeTransactionData(transaction.id);\n}\n\nconst erc20Interface = new Interface(abiERC20);\n\nconst ERC20_TRANSFER_EVENT_TOPIC = erc20Interface.getEventTopic('Transfer');\n\n/**\n * Result from {@link getTransferredAmountFromTxHash}.\n */\nexport type TransferredAmountResult = {\n /** Raw (atomic) transferred amount as a decimal string, or `undefined`. */\n amountRaw: string | undefined;\n /**\n * Block number of the on-chain transaction as a 0x-prefixed hex string.\n * Populated only for ERC-20 tokens (sourced from the receipt); `undefined`\n * for native token transactions.\n */\n blockNumber: Hex | undefined;\n};\n\n/**\n * Reads the transferred token amount from a completed on-chain transaction.\n *\n * For native tokens the amount is resolved via `debug_traceTransaction`\n * (internal-call aware), falling back to the top-level `tx.value`.\n * For ERC-20 tokens the amount is decoded from `Transfer` event logs\n * in the transaction receipt, and the receipt `blockNumber` is also returned.\n *\n * @param options - The options.\n * @param options.messenger - Controller messenger for network access.\n * @param options.txHash - Transaction hash of the completed on-chain transaction.\n * @param options.chainId - Chain ID where the transaction was executed.\n * @param options.tokenAddress - Address of the transferred token.\n * @param options.walletAddress - Recipient wallet address to filter transfers to.\n * @returns The raw transferred amount and, for ERC-20, the receipt block number.\n */\nexport async function getTransferredAmountFromTxHash({\n messenger,\n txHash,\n chainId,\n tokenAddress,\n walletAddress,\n}: {\n messenger: TransactionPayControllerMessenger;\n txHash: string;\n chainId: Hex;\n tokenAddress: Hex;\n walletAddress: Hex;\n}): Promise<TransferredAmountResult> {\n const isNative =\n tokenAddress.toLowerCase() === getNativeToken(chainId).toLowerCase();\n\n if (isNative) {\n const amountRaw = await getNativeTransferAmount(\n messenger,\n chainId,\n txHash,\n walletAddress,\n );\n\n return { amountRaw, blockNumber: undefined };\n }\n\n return await getErc20TransferAmount(\n messenger,\n chainId,\n txHash,\n tokenAddress,\n walletAddress,\n );\n}\n\n/**\n * Resolves the native token amount received by a wallet from a transaction.\n *\n * 1. Attempts `debug_traceTransaction` with `callTracer` to walk internal\n * calls and sum all native value transfers targeting `walletAddress`.\n * 2. Falls back to the top-level `tx.value` when the wallet is the direct\n * recipient and the trace RPC is unavailable or errors.\n *\n * @param messenger - Controller messenger.\n * @param chainId - Chain ID where the transaction was executed.\n * @param txHash - Transaction hash.\n * @param walletAddress - Recipient wallet address.\n * @returns Raw amount as a decimal string, or `undefined`.\n */\nasync function getNativeTransferAmount(\n messenger: TransactionPayControllerMessenger,\n chainId: Hex,\n txHash: string,\n walletAddress: Hex,\n): Promise<string | undefined> {\n try {\n const trace = await rpcRequest<CallTrace>({\n messenger,\n chainId,\n method: 'debug_traceTransaction',\n params: [txHash, { tracer: 'callTracer' }],\n });\n\n const amount = sumNativeValueFromTrace(trace, walletAddress);\n if (amount.gt(0)) {\n return amount.toFixed(0);\n }\n } catch {\n // debug_traceTransaction not supported — fall through to tx.value\n }\n\n const tx = await rpcRequest<{ to?: string; value: string } | null>({\n messenger,\n chainId,\n method: 'eth_getTransactionByHash',\n params: [txHash],\n });\n\n if (!tx) {\n return undefined;\n }\n\n if (tx.to?.toLowerCase() !== walletAddress.toLowerCase()) {\n return undefined;\n }\n\n return positiveOrUndefined(new BigNumber(tx.value).toFixed(0));\n}\n\n/**\n * Resolves the ERC-20 token amount received by a wallet from a transaction\n * by decoding `Transfer` event logs from the transaction receipt. Also\n * returns the receipt `blockNumber` so callers can reuse it without a\n * second network request.\n *\n * @param messenger - Controller messenger.\n * @param chainId - Chain ID where the transaction was executed.\n * @param txHash - Transaction hash.\n * @param tokenAddress - ERC-20 token contract address.\n * @param walletAddress - Recipient wallet address.\n * @returns Raw amount (or `undefined`) and the receipt block number (or `undefined`).\n */\nasync function getErc20TransferAmount(\n messenger: TransactionPayControllerMessenger,\n chainId: Hex,\n txHash: string,\n tokenAddress: Hex,\n walletAddress: Hex,\n): Promise<TransferredAmountResult> {\n const receipt = await rpcRequest<{\n blockNumber: Hex;\n logs: { address: string; topics: string[]; data: string }[];\n } | null>({\n messenger,\n chainId,\n method: 'eth_getTransactionReceipt',\n params: [txHash],\n });\n\n if (!receipt) {\n return { amountRaw: undefined, blockNumber: undefined };\n }\n\n const { blockNumber } = receipt;\n let total = new BigNumber(0);\n\n for (const txLog of receipt.logs) {\n if (txLog.address.toLowerCase() !== tokenAddress.toLowerCase()) {\n continue;\n }\n\n if (!txLog.topics[0] || txLog.topics[0] !== ERC20_TRANSFER_EVENT_TOPIC) {\n continue;\n }\n\n try {\n const parsed = erc20Interface.parseLog(txLog);\n const to = (parsed.args[1] as string).toLowerCase();\n\n if (to !== walletAddress.toLowerCase()) {\n continue;\n }\n\n total = total.plus(parsed.args[2].toString());\n } catch {\n continue;\n }\n }\n\n return { amountRaw: positiveOrUndefined(total.toFixed(0)), blockNumber };\n}\n\ntype CallTrace = {\n to?: string;\n value?: string;\n calls?: CallTrace[];\n};\n\n/**\n * Recursively walks a `callTracer` result and sums native value\n * transferred to a specific address.\n *\n * @param trace - Call trace node.\n * @param walletAddress - Target address to accumulate value for.\n * @returns Accumulated native value as BigNumber.\n */\nfunction sumNativeValueFromTrace(\n trace: CallTrace,\n walletAddress: Hex,\n): BigNumber {\n let total = new BigNumber(0);\n\n if (\n trace.to?.toLowerCase() === walletAddress.toLowerCase() &&\n trace.value &&\n trace.value !== '0x0'\n ) {\n total = total.plus(new BigNumber(trace.value));\n }\n\n if (trace.calls) {\n for (const child of trace.calls) {\n total = total.plus(sumNativeValueFromTrace(child, walletAddress));\n }\n }\n\n return total;\n}\n\nfunction positiveOrUndefined(amount: string): string | undefined {\n return new BigNumber(amount).gt(0) ? amount : undefined;\n}\n"]}
|
|
@@ -72,13 +72,26 @@ export declare function collectTransactionIds(chainId: Hex, from: Hex, messenger
|
|
|
72
72
|
* @returns `true` when the transaction is a Predict withdrawal.
|
|
73
73
|
*/
|
|
74
74
|
export declare function isPredictWithdrawTransaction(transaction: TransactionMeta): boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Result from {@link getTransferredAmountFromTxHash}.
|
|
77
|
+
*/
|
|
78
|
+
export type TransferredAmountResult = {
|
|
79
|
+
/** Raw (atomic) transferred amount as a decimal string, or `undefined`. */
|
|
80
|
+
amountRaw: string | undefined;
|
|
81
|
+
/**
|
|
82
|
+
* Block number of the on-chain transaction as a 0x-prefixed hex string.
|
|
83
|
+
* Populated only for ERC-20 tokens (sourced from the receipt); `undefined`
|
|
84
|
+
* for native token transactions.
|
|
85
|
+
*/
|
|
86
|
+
blockNumber: Hex | undefined;
|
|
87
|
+
};
|
|
75
88
|
/**
|
|
76
89
|
* Reads the transferred token amount from a completed on-chain transaction.
|
|
77
90
|
*
|
|
78
91
|
* For native tokens the amount is resolved via `debug_traceTransaction`
|
|
79
92
|
* (internal-call aware), falling back to the top-level `tx.value`.
|
|
80
93
|
* For ERC-20 tokens the amount is decoded from `Transfer` event logs
|
|
81
|
-
* in the transaction receipt.
|
|
94
|
+
* in the transaction receipt, and the receipt `blockNumber` is also returned.
|
|
82
95
|
*
|
|
83
96
|
* @param options - The options.
|
|
84
97
|
* @param options.messenger - Controller messenger for network access.
|
|
@@ -86,8 +99,7 @@ export declare function isPredictWithdrawTransaction(transaction: TransactionMet
|
|
|
86
99
|
* @param options.chainId - Chain ID where the transaction was executed.
|
|
87
100
|
* @param options.tokenAddress - Address of the transferred token.
|
|
88
101
|
* @param options.walletAddress - Recipient wallet address to filter transfers to.
|
|
89
|
-
* @returns The raw
|
|
90
|
-
* or `undefined` if the amount cannot be determined.
|
|
102
|
+
* @returns The raw transferred amount and, for ERC-20, the receipt block number.
|
|
91
103
|
*/
|
|
92
104
|
export declare function getTransferredAmountFromTxHash({ messenger, txHash, chainId, tokenAddress, walletAddress, }: {
|
|
93
105
|
messenger: TransactionPayControllerMessenger;
|
|
@@ -95,5 +107,5 @@ export declare function getTransferredAmountFromTxHash({ messenger, txHash, chai
|
|
|
95
107
|
chainId: Hex;
|
|
96
108
|
tokenAddress: Hex;
|
|
97
109
|
walletAddress: Hex;
|
|
98
|
-
}): Promise<
|
|
110
|
+
}): Promise<TransferredAmountResult>;
|
|
99
111
|
//# sourceMappingURL=transaction.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transaction.d.cts","sourceRoot":"","sources":["../../src/utils/transaction.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,iBAAiB,EAElB,yCAAyC;AAC1C,OAAO,KAAK,EAAE,eAAe,EAAE,yCAAyC;AACxE,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAO3C,OAAO,KAAK,EACV,iCAAiC,EACjC,6BAA6B,EAC7B,6BAA6B,EAC9B,qBAAiB;AAQlB,eAAO,MAAM,kBAAkB,qBAI9B,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,iCAAiC,GAC3C,eAAe,GAAG,SAAS,CAQ7B;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,SAAS,EAAE,iCAAiC,EAC5C,qBAAqB,EAAE,6BAA6B,EACpD,qBAAqB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,GACrD,IAAI,CAgDN;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,iCAAiC,EAC5C,kBAAkB,EAAE,MAAM,6BAA6B,EACvD,qBAAqB,EAAE,6BAA6B,GACnD,IAAI,CA2CN;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,iCAAiC,GAC3C,OAAO,CAAC,IAAI,CAAC,CA+Cf;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,EACE,aAAa,EACb,SAAS,EACT,IAAI,GACL,EAAE;IACD,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,iCAAiC,CAAC;IAC7C,IAAI,EAAE,MAAM,CAAC;CACd,EACD,EAAE,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,GACnC,IAAI,CAgBN;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,GAAG,EACZ,IAAI,EAAE,GAAG,EACT,SAAS,EAAE,iCAAiC,EAC5C,aAAa,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,GAC7C;IAAE,GAAG,EAAE,MAAM,IAAI,CAAA;CAAE,CAyBrB;AAED;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAC1C,WAAW,EAAE,eAAe,GAC3B,OAAO,CAQT;AAyCD
|
|
1
|
+
{"version":3,"file":"transaction.d.cts","sourceRoot":"","sources":["../../src/utils/transaction.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,iBAAiB,EAElB,yCAAyC;AAC1C,OAAO,KAAK,EAAE,eAAe,EAAE,yCAAyC;AACxE,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAO3C,OAAO,KAAK,EACV,iCAAiC,EACjC,6BAA6B,EAC7B,6BAA6B,EAC9B,qBAAiB;AAQlB,eAAO,MAAM,kBAAkB,qBAI9B,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,iCAAiC,GAC3C,eAAe,GAAG,SAAS,CAQ7B;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,SAAS,EAAE,iCAAiC,EAC5C,qBAAqB,EAAE,6BAA6B,EACpD,qBAAqB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,GACrD,IAAI,CAgDN;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,iCAAiC,EAC5C,kBAAkB,EAAE,MAAM,6BAA6B,EACvD,qBAAqB,EAAE,6BAA6B,GACnD,IAAI,CA2CN;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,iCAAiC,GAC3C,OAAO,CAAC,IAAI,CAAC,CA+Cf;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,EACE,aAAa,EACb,SAAS,EACT,IAAI,GACL,EAAE;IACD,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,iCAAiC,CAAC;IAC7C,IAAI,EAAE,MAAM,CAAC;CACd,EACD,EAAE,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,GACnC,IAAI,CAgBN;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,GAAG,EACZ,IAAI,EAAE,GAAG,EACT,SAAS,EAAE,iCAAiC,EAC5C,aAAa,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,GAC7C;IAAE,GAAG,EAAE,MAAM,IAAI,CAAA;CAAE,CAyBrB;AAED;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAC1C,WAAW,EAAE,eAAe,GAC3B,OAAO,CAQT;AAyCD;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC,2EAA2E;IAC3E,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B;;;;OAIG;IACH,WAAW,EAAE,GAAG,GAAG,SAAS,CAAC;CAC9B,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,8BAA8B,CAAC,EACnD,SAAS,EACT,MAAM,EACN,OAAO,EACP,YAAY,EACZ,aAAa,GACd,EAAE;IACD,SAAS,EAAE,iCAAiC,CAAC;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,GAAG,CAAC;IACb,YAAY,EAAE,GAAG,CAAC;IAClB,aAAa,EAAE,GAAG,CAAC;CACpB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAsBnC"}
|
|
@@ -72,13 +72,26 @@ export declare function collectTransactionIds(chainId: Hex, from: Hex, messenger
|
|
|
72
72
|
* @returns `true` when the transaction is a Predict withdrawal.
|
|
73
73
|
*/
|
|
74
74
|
export declare function isPredictWithdrawTransaction(transaction: TransactionMeta): boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Result from {@link getTransferredAmountFromTxHash}.
|
|
77
|
+
*/
|
|
78
|
+
export type TransferredAmountResult = {
|
|
79
|
+
/** Raw (atomic) transferred amount as a decimal string, or `undefined`. */
|
|
80
|
+
amountRaw: string | undefined;
|
|
81
|
+
/**
|
|
82
|
+
* Block number of the on-chain transaction as a 0x-prefixed hex string.
|
|
83
|
+
* Populated only for ERC-20 tokens (sourced from the receipt); `undefined`
|
|
84
|
+
* for native token transactions.
|
|
85
|
+
*/
|
|
86
|
+
blockNumber: Hex | undefined;
|
|
87
|
+
};
|
|
75
88
|
/**
|
|
76
89
|
* Reads the transferred token amount from a completed on-chain transaction.
|
|
77
90
|
*
|
|
78
91
|
* For native tokens the amount is resolved via `debug_traceTransaction`
|
|
79
92
|
* (internal-call aware), falling back to the top-level `tx.value`.
|
|
80
93
|
* For ERC-20 tokens the amount is decoded from `Transfer` event logs
|
|
81
|
-
* in the transaction receipt.
|
|
94
|
+
* in the transaction receipt, and the receipt `blockNumber` is also returned.
|
|
82
95
|
*
|
|
83
96
|
* @param options - The options.
|
|
84
97
|
* @param options.messenger - Controller messenger for network access.
|
|
@@ -86,8 +99,7 @@ export declare function isPredictWithdrawTransaction(transaction: TransactionMet
|
|
|
86
99
|
* @param options.chainId - Chain ID where the transaction was executed.
|
|
87
100
|
* @param options.tokenAddress - Address of the transferred token.
|
|
88
101
|
* @param options.walletAddress - Recipient wallet address to filter transfers to.
|
|
89
|
-
* @returns The raw
|
|
90
|
-
* or `undefined` if the amount cannot be determined.
|
|
102
|
+
* @returns The raw transferred amount and, for ERC-20, the receipt block number.
|
|
91
103
|
*/
|
|
92
104
|
export declare function getTransferredAmountFromTxHash({ messenger, txHash, chainId, tokenAddress, walletAddress, }: {
|
|
93
105
|
messenger: TransactionPayControllerMessenger;
|
|
@@ -95,5 +107,5 @@ export declare function getTransferredAmountFromTxHash({ messenger, txHash, chai
|
|
|
95
107
|
chainId: Hex;
|
|
96
108
|
tokenAddress: Hex;
|
|
97
109
|
walletAddress: Hex;
|
|
98
|
-
}): Promise<
|
|
110
|
+
}): Promise<TransferredAmountResult>;
|
|
99
111
|
//# sourceMappingURL=transaction.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transaction.d.mts","sourceRoot":"","sources":["../../src/utils/transaction.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,iBAAiB,EAElB,yCAAyC;AAC1C,OAAO,KAAK,EAAE,eAAe,EAAE,yCAAyC;AACxE,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAO3C,OAAO,KAAK,EACV,iCAAiC,EACjC,6BAA6B,EAC7B,6BAA6B,EAC9B,qBAAiB;AAQlB,eAAO,MAAM,kBAAkB,qBAI9B,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,iCAAiC,GAC3C,eAAe,GAAG,SAAS,CAQ7B;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,SAAS,EAAE,iCAAiC,EAC5C,qBAAqB,EAAE,6BAA6B,EACpD,qBAAqB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,GACrD,IAAI,CAgDN;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,iCAAiC,EAC5C,kBAAkB,EAAE,MAAM,6BAA6B,EACvD,qBAAqB,EAAE,6BAA6B,GACnD,IAAI,CA2CN;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,iCAAiC,GAC3C,OAAO,CAAC,IAAI,CAAC,CA+Cf;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,EACE,aAAa,EACb,SAAS,EACT,IAAI,GACL,EAAE;IACD,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,iCAAiC,CAAC;IAC7C,IAAI,EAAE,MAAM,CAAC;CACd,EACD,EAAE,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,GACnC,IAAI,CAgBN;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,GAAG,EACZ,IAAI,EAAE,GAAG,EACT,SAAS,EAAE,iCAAiC,EAC5C,aAAa,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,GAC7C;IAAE,GAAG,EAAE,MAAM,IAAI,CAAA;CAAE,CAyBrB;AAED;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAC1C,WAAW,EAAE,eAAe,GAC3B,OAAO,CAQT;AAyCD
|
|
1
|
+
{"version":3,"file":"transaction.d.mts","sourceRoot":"","sources":["../../src/utils/transaction.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,iBAAiB,EAElB,yCAAyC;AAC1C,OAAO,KAAK,EAAE,eAAe,EAAE,yCAAyC;AACxE,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAO3C,OAAO,KAAK,EACV,iCAAiC,EACjC,6BAA6B,EAC7B,6BAA6B,EAC9B,qBAAiB;AAQlB,eAAO,MAAM,kBAAkB,qBAI9B,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,iCAAiC,GAC3C,eAAe,GAAG,SAAS,CAQ7B;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,SAAS,EAAE,iCAAiC,EAC5C,qBAAqB,EAAE,6BAA6B,EACpD,qBAAqB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,GACrD,IAAI,CAgDN;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,iCAAiC,EAC5C,kBAAkB,EAAE,MAAM,6BAA6B,EACvD,qBAAqB,EAAE,6BAA6B,GACnD,IAAI,CA2CN;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,iCAAiC,GAC3C,OAAO,CAAC,IAAI,CAAC,CA+Cf;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,EACE,aAAa,EACb,SAAS,EACT,IAAI,GACL,EAAE;IACD,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,iCAAiC,CAAC;IAC7C,IAAI,EAAE,MAAM,CAAC;CACd,EACD,EAAE,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,GACnC,IAAI,CAgBN;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,GAAG,EACZ,IAAI,EAAE,GAAG,EACT,SAAS,EAAE,iCAAiC,EAC5C,aAAa,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,GAC7C;IAAE,GAAG,EAAE,MAAM,IAAI,CAAA;CAAE,CAyBrB;AAED;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAC1C,WAAW,EAAE,eAAe,GAC3B,OAAO,CAQT;AAyCD;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC,2EAA2E;IAC3E,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B;;;;OAIG;IACH,WAAW,EAAE,GAAG,GAAG,SAAS,CAAC;CAC9B,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,8BAA8B,CAAC,EACnD,SAAS,EACT,MAAM,EACN,OAAO,EACP,YAAY,EACZ,aAAa,GACd,EAAE;IACD,SAAS,EAAE,iCAAiC,CAAC;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,GAAG,CAAC;IACb,YAAY,EAAE,GAAG,CAAC;IAClB,aAAa,EAAE,GAAG,CAAC;CACpB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAsBnC"}
|
|
@@ -206,7 +206,7 @@ const ERC20_TRANSFER_EVENT_TOPIC = erc20Interface.getEventTopic('Transfer');
|
|
|
206
206
|
* For native tokens the amount is resolved via `debug_traceTransaction`
|
|
207
207
|
* (internal-call aware), falling back to the top-level `tx.value`.
|
|
208
208
|
* For ERC-20 tokens the amount is decoded from `Transfer` event logs
|
|
209
|
-
* in the transaction receipt.
|
|
209
|
+
* in the transaction receipt, and the receipt `blockNumber` is also returned.
|
|
210
210
|
*
|
|
211
211
|
* @param options - The options.
|
|
212
212
|
* @param options.messenger - Controller messenger for network access.
|
|
@@ -214,13 +214,13 @@ const ERC20_TRANSFER_EVENT_TOPIC = erc20Interface.getEventTopic('Transfer');
|
|
|
214
214
|
* @param options.chainId - Chain ID where the transaction was executed.
|
|
215
215
|
* @param options.tokenAddress - Address of the transferred token.
|
|
216
216
|
* @param options.walletAddress - Recipient wallet address to filter transfers to.
|
|
217
|
-
* @returns The raw
|
|
218
|
-
* or `undefined` if the amount cannot be determined.
|
|
217
|
+
* @returns The raw transferred amount and, for ERC-20, the receipt block number.
|
|
219
218
|
*/
|
|
220
219
|
export async function getTransferredAmountFromTxHash({ messenger, txHash, chainId, tokenAddress, walletAddress, }) {
|
|
221
220
|
const isNative = tokenAddress.toLowerCase() === getNativeToken(chainId).toLowerCase();
|
|
222
221
|
if (isNative) {
|
|
223
|
-
|
|
222
|
+
const amountRaw = await getNativeTransferAmount(messenger, chainId, txHash, walletAddress);
|
|
223
|
+
return { amountRaw, blockNumber: undefined };
|
|
224
224
|
}
|
|
225
225
|
return await getErc20TransferAmount(messenger, chainId, txHash, tokenAddress, walletAddress);
|
|
226
226
|
}
|
|
@@ -270,14 +270,16 @@ async function getNativeTransferAmount(messenger, chainId, txHash, walletAddress
|
|
|
270
270
|
}
|
|
271
271
|
/**
|
|
272
272
|
* Resolves the ERC-20 token amount received by a wallet from a transaction
|
|
273
|
-
* by decoding `Transfer` event logs from the transaction receipt.
|
|
273
|
+
* by decoding `Transfer` event logs from the transaction receipt. Also
|
|
274
|
+
* returns the receipt `blockNumber` so callers can reuse it without a
|
|
275
|
+
* second network request.
|
|
274
276
|
*
|
|
275
277
|
* @param messenger - Controller messenger.
|
|
276
278
|
* @param chainId - Chain ID where the transaction was executed.
|
|
277
279
|
* @param txHash - Transaction hash.
|
|
278
280
|
* @param tokenAddress - ERC-20 token contract address.
|
|
279
281
|
* @param walletAddress - Recipient wallet address.
|
|
280
|
-
* @returns Raw amount
|
|
282
|
+
* @returns Raw amount (or `undefined`) and the receipt block number (or `undefined`).
|
|
281
283
|
*/
|
|
282
284
|
async function getErc20TransferAmount(messenger, chainId, txHash, tokenAddress, walletAddress) {
|
|
283
285
|
const receipt = await rpcRequest({
|
|
@@ -287,8 +289,9 @@ async function getErc20TransferAmount(messenger, chainId, txHash, tokenAddress,
|
|
|
287
289
|
params: [txHash],
|
|
288
290
|
});
|
|
289
291
|
if (!receipt) {
|
|
290
|
-
return undefined;
|
|
292
|
+
return { amountRaw: undefined, blockNumber: undefined };
|
|
291
293
|
}
|
|
294
|
+
const { blockNumber } = receipt;
|
|
292
295
|
let total = new BigNumber(0);
|
|
293
296
|
for (const txLog of receipt.logs) {
|
|
294
297
|
if (txLog.address.toLowerCase() !== tokenAddress.toLowerCase()) {
|
|
@@ -309,7 +312,7 @@ async function getErc20TransferAmount(messenger, chainId, txHash, tokenAddress,
|
|
|
309
312
|
continue;
|
|
310
313
|
}
|
|
311
314
|
}
|
|
312
|
-
return positiveOrUndefined(total.toFixed(0));
|
|
315
|
+
return { amountRaw: positiveOrUndefined(total.toFixed(0)), blockNumber };
|
|
313
316
|
}
|
|
314
317
|
/**
|
|
315
318
|
* Recursively walks a `callTracer` result and sums native value
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transaction.mjs","sourceRoot":"","sources":["../../src/utils/transaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,2BAA2B;AAC/C,OAAO,EAAE,QAAQ,EAAE,oCAAoC;AACvD,OAAO,EACL,iBAAiB,EACjB,eAAe,EAChB,yCAAyC;AAG1C,OAAO,EAAE,kBAAkB,EAAE,wBAAwB;AACrD,OAAO,EAAE,SAAS,EAAE,qBAAqB;;;AAIzC,OAAO,EAAE,aAAa,EAAE,sBAAkB;AAM1C,OAAO,EAAE,0BAA0B,EAAE,4BAAwB;AAC7D,OAAO,EAAE,UAAU,EAAE,uBAAmB;AACxC,OAAO,EAAE,mBAAmB,EAAE,8BAA0B;AACxD,OAAO,EAAE,cAAc,EAAE,oBAAgB;AAEzC,MAAM,GAAG,GAAG,kBAAkB,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;AAE7D,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,iBAAiB,CAAC,SAAS;IAC3B,iBAAiB,CAAC,OAAO;IACzB,iBAAiB,CAAC,MAAM;CACzB,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,aAAqB,EACrB,SAA4C;IAE5C,MAAM,0BAA0B,GAAG,SAAS,CAAC,IAAI,CAC/C,gCAAgC,CACjC,CAAC;IAEF,OAAO,0BAA0B,CAAC,YAAY,CAAC,IAAI,CACjD,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,aAAa,CAChC,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,2BAA2B,CACzC,SAA4C,EAC5C,qBAAoD,EACpD,qBAAsD;IAEtD,SAAS,CAAC,SAAS,CACjB,mCAAmC,EACnC,CACE,YAA+B,EAC/B,oBAAmD,EACnD,EAAE;QACF,MAAM,eAAe,GAAG,YAAY,CAAC,MAAM,CACzC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,oBAAoB,EAAE,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CACrE,CAAC;QAEF,MAAM,mBAAmB,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE;YACrD,MAAM,mBAAmB,GAAG,oBAAoB,EAAE,IAAI,CACpD,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAChC,CAAC;YAEF,OAAO,CACL,mBAAmB;gBACnB,mBAAmB,EAAE,QAAQ,CAAC,IAAI,KAAK,EAAE,CAAC,QAAQ,CAAC,IAAI,CACxD,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,MAAM,qBAAqB,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE;YACvD,MAAM,mBAAmB,GAAG,oBAAoB,EAAE,IAAI,CACpD,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAChC,CAAC;YAEF,OAAO,CACL,mBAAmB;gBACnB,CAAC,kBAAkB,CAAC,QAAQ,CAAC,mBAAmB,CAAC,MAAM,CAAC;gBACxD,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,CAAC,CACvC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,MAAM,mBAAmB,GAAG,CAAC,oBAAoB,IAAI,EAAE,CAAC,CAAC,MAAM,CAC7D,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,CAAC,CAC5D,CAAC;QAEF,CAAC,GAAG,qBAAqB,EAAE,GAAG,mBAAmB,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAChE,sBAAsB,CAAC,EAAE,EAAE,qBAAqB,CAAC,CAClD,CAAC;QAEF,CAAC,GAAG,eAAe,EAAE,GAAG,mBAAmB,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAC1D,mBAAmB,CAAC,EAAE,EAAE,SAAS,EAAE,qBAAqB,CAAC,CAC1D,CAAC;IACJ,CAAC,EACD,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,YAAY,CAC9B,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CACnC,SAA4C,EAC5C,kBAAuD,EACvD,qBAAoD;IAEpD,MAAM,YAAY,GAChB,CAAC,MAAc,EAAE,EAAE,CACnB,CAAC,MAAe,EAAE,OAA4B,EAAQ,EAAE;QACtD,MAAM,EAAE,eAAe,EAAE,GAAG,kBAAkB,EAAE,CAAC;QAEjD,KAAK,MAAM,CAAC,aAAa,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC;YACpE,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC3B,SAAS;YACX,CAAC;YAED,MAAM,WAAW,GAAG,cAAc,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;YAE7D,IAAI,CAAC,WAAW,IAAI,kBAAkB,CAAC,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;gBACpE,SAAS;YACX,CAAC;YAED,GAAG,CAAC,oBAAoB,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;YAE9D,mBAAmB,CAAC,WAAW,EAAE,SAAS,EAAE,qBAAqB,CAAC,CAAC;QACrE,CAAC;IACH,CAAC,CAAC;IAEJ,IAAI,0BAA0B,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1C,SAAS,CAAC,SAAS,CACjB,8BAA8B,EAC9B,YAAY,CAAC,kBAAkB,CAAC,CACjC,CAAC;QACF,OAAO;IACT,CAAC;IAED,SAAS,CAAC,SAAS,CACjB,8BAA8B,EAC9B,YAAY,CAAC,kBAAkB,CAAC,CACjC,CAAC;IACF,SAAS,CAAC,SAAS,CACjB,kCAAkC,EAClC,YAAY,CAAC,sBAAsB,CAAC,CACrC,CAAC;IACF,SAAS,CAAC,SAAS,CACjB,oCAAoC,EACpC,YAAY,CAAC,wBAAwB,CAAC,CACvC,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,2BAA2B,CACzC,aAAqB,EACrB,SAA4C;IAE5C,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC3C,MAAM,WAAW,GAAG,CAAC,EAAoB,EAAE,EAAe,EAAW,EAAE;YACrE,GAAG,CAAC,6BAA6B,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;YAEzD,IAAI,EAAE,EAAE,MAAM,KAAK,iBAAiB,CAAC,SAAS,EAAE,CAAC;gBAC/C,EAAE,EAAE,EAAE,CAAC;gBACP,OAAO,EAAE,CAAC;gBACV,OAAO,IAAI,CAAC;YACd,CAAC;YAED,IACE,CAAC,iBAAiB,CAAC,OAAO,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC,QAAQ,CAC5D,EAAE,EAAE,MAA2B,CAChC,EACD,CAAC;gBACD,EAAE,EAAE,EAAE,CAAC;gBACP,MAAM,CACJ,IAAI,KAAK,CAAC,wBAAwB,EAAE,EAAE,IAAI,MAAM,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CACtE,CAAC;gBACF,OAAO,IAAI,CAAC;YACd,CAAC;YAED,OAAO,KAAK,CAAC;QACf,CAAC,CAAC;QAEF,MAAM,YAAY,GAAG,SAAS,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;QAEtE,MAAM,SAAS,GAAG,YAAY,CAAC,YAAY,CAAC,IAAI,CAC9C,CAAC,iBAAiB,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,KAAK,aAAa,CAC9D,CAAC;QAEF,IAAI,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3B,OAAO;QACT,CAAC;QAED,MAAM,OAAO,GAAG,CAAC,EAAoB,EAAQ,EAAE;YAC7C,MAAM,WAAW,GAAG,GAAS,EAAE,CAC7B,SAAS,CAAC,WAAW,CAAC,mCAAmC,EAAE,OAAO,CAAC,CAAC;YAEtE,WAAW,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;QAC/B,CAAC,CAAC;QAEF,SAAS,CAAC,SAAS,CAAC,mCAAmC,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAC1E,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,aAAa,CAAC,CACzD,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAC/B,EACE,aAAa,EACb,SAAS,EACT,IAAI,GAKL,EACD,EAAoC;IAEpC,MAAM,WAAW,GAAG,cAAc,CAAC,aAAa,EAAE,SAAkB,CAAC,CAAC;IAEtE,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,0BAA0B,aAAa,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,cAAc,GAAG,SAAS,CAAC,WAAW,CAAC,CAAC;IAE9C,EAAE,CAAC,cAAc,CAAC,CAAC;IAEnB,SAAS,CAAC,IAAI,CACZ,yCAAyC,EACzC,cAAc,EACd,IAAI,CACL,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CACnC,OAAY,EACZ,IAAS,EACT,SAA4C,EAC5C,aAA8C;IAE9C,MAAM,QAAQ,GAAG,CAAC,EAAmB,EAAQ,EAAE;QAC7C,IACE,EAAE,CAAC,OAAO,KAAK,OAAO;YACtB,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,WAAW,EAAE,EACrD,CAAC;YACD,OAAO;QACT,CAAC;QAED,aAAa,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACvB,CAAC,CAAC;IAEF,SAAS,CAAC,SAAS,CACjB,kDAAkD,EAClD,QAAQ,CACT,CAAC;IAEF,MAAM,GAAG,GAAG,GAAS,EAAE;QACrB,SAAS,CAAC,WAAW,CACnB,kDAAkD,EAClD,QAAQ,CACT,CAAC;IACJ,CAAC,CAAC;IAEF,OAAO,EAAE,GAAG,EAAE,CAAC;AACjB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,4BAA4B,CAC1C,WAA4B;IAE5B,OAAO,CACL,WAAW,CAAC,IAAI,KAAK,eAAe,CAAC,eAAe;QACpD,CAAC,WAAW,CAAC,kBAAkB,EAAE,IAAI,CACnC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,KAAK,eAAe,CAAC,eAAe,CACpD;YACC,KAAK,CAAC,CACT,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,SAAS,mBAAmB,CAC1B,WAA4B,EAC5B,SAA4C,EAC5C,qBAAoD;IAEpD,MAAM,MAAM,GAAG,mBAAmB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IAE3D,GAAG,CAAC,qBAAqB,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC;IAEpD,qBAAqB,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE;QAC7C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,SAAS,sBAAsB,CAC7B,WAA4B,EAC5B,qBAAsD;IAEtD,GAAG,CAAC,uBAAuB,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC;IAC9C,qBAAqB,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,cAAc,GAAG,IAAI,SAAS,CAAC,QAAQ,CAAC,CAAC;AAE/C,MAAM,0BAA0B,GAAG,cAAc,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;AAE5E;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAAC,EACnD,SAAS,EACT,MAAM,EACN,OAAO,EACP,YAAY,EACZ,aAAa,GAOd;IACC,MAAM,QAAQ,GACZ,YAAY,CAAC,WAAW,EAAE,KAAK,cAAc,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;IAEvE,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,MAAM,uBAAuB,CAClC,SAAS,EACT,OAAO,EACP,MAAM,EACN,aAAa,CACd,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,sBAAsB,CACjC,SAAS,EACT,OAAO,EACP,MAAM,EACN,YAAY,EACZ,aAAa,CACd,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,KAAK,UAAU,uBAAuB,CACpC,SAA4C,EAC5C,OAAY,EACZ,MAAc,EACd,aAAkB;IAElB,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,UAAU,CAAY;YACxC,SAAS;YACT,OAAO;YACP,MAAM,EAAE,wBAAwB;YAChC,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;SAC3C,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,uBAAuB,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;QAC7D,IAAI,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjB,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,kEAAkE;IACpE,CAAC;IAED,MAAM,EAAE,GAAG,MAAM,UAAU,CAAwC;QACjE,SAAS;QACT,OAAO;QACP,MAAM,EAAE,0BAA0B;QAClC,MAAM,EAAE,CAAC,MAAM,CAAC;KACjB,CAAC,CAAC;IAEH,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,EAAE,CAAC,EAAE,EAAE,WAAW,EAAE,KAAK,aAAa,CAAC,WAAW,EAAE,EAAE,CAAC;QACzD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,mBAAmB,CAAC,IAAI,SAAS,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;AACjE,CAAC;AAED;;;;;;;;;;GAUG;AACH,KAAK,UAAU,sBAAsB,CACnC,SAA4C,EAC5C,OAAY,EACZ,MAAc,EACd,YAAiB,EACjB,aAAkB;IAElB,MAAM,OAAO,GAAG,MAAM,UAAU,CAEtB;QACR,SAAS;QACT,OAAO;QACP,MAAM,EAAE,2BAA2B;QACnC,MAAM,EAAE,CAAC,MAAM,CAAC;KACjB,CAAC,CAAC;IAEH,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,KAAK,GAAG,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC;IAE7B,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjC,IAAI,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,YAAY,CAAC,WAAW,EAAE,EAAE,CAAC;YAC/D,SAAS;QACX,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,0BAA0B,EAAE,CAAC;YACvE,SAAS;QACX,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,cAAc,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YAC9C,MAAM,EAAE,GAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAY,CAAC,WAAW,EAAE,CAAC;YAEpD,IAAI,EAAE,KAAK,aAAa,CAAC,WAAW,EAAE,EAAE,CAAC;gBACvC,SAAS;YACX,CAAC;YAED,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;QAChD,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;IACH,CAAC;IAED,OAAO,mBAAmB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/C,CAAC;AAQD;;;;;;;GAOG;AACH,SAAS,uBAAuB,CAC9B,KAAgB,EAChB,aAAkB;IAElB,IAAI,KAAK,GAAG,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC;IAE7B,IACE,KAAK,CAAC,EAAE,EAAE,WAAW,EAAE,KAAK,aAAa,CAAC,WAAW,EAAE;QACvD,KAAK,CAAC,KAAK;QACX,KAAK,CAAC,KAAK,KAAK,KAAK,EACrB,CAAC;QACD,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAChB,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAChC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,mBAAmB,CAAC,MAAc;IACzC,OAAO,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AAC1D,CAAC","sourcesContent":["import { Interface } from '@ethersproject/abi';\nimport { abiERC20 } from '@metamask/metamask-eth-abis';\nimport {\n TransactionStatus,\n TransactionType,\n} from '@metamask/transaction-controller';\nimport type { TransactionMeta } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\nimport type { Patch } from 'immer';\nimport { cloneDeep } from 'lodash';\n\nimport { projectLogger } from '../logger';\nimport type {\n TransactionPayControllerMessenger,\n TransactionPayControllerState,\n UpdateTransactionDataCallback,\n} from '../types';\nimport { getAssetsUnifyStateFeature } from './feature-flags';\nimport { rpcRequest } from './provider';\nimport { parseRequiredTokens } from './required-tokens';\nimport { getNativeToken } from './token';\n\nconst log = createModuleLogger(projectLogger, 'transaction');\n\nexport const FINALIZED_STATUSES = [\n TransactionStatus.confirmed,\n TransactionStatus.dropped,\n TransactionStatus.failed,\n];\n\n/**\n * Retrieve transaction metadata by ID.\n *\n * @param transactionId - ID of the transaction to retrieve.\n * @param messenger - Controller messenger.\n * @returns The transaction metadata or undefined if not found.\n */\nexport function getTransaction(\n transactionId: string,\n messenger: TransactionPayControllerMessenger,\n): TransactionMeta | undefined {\n const transactionControllerState = messenger.call(\n 'TransactionController:getState',\n );\n\n return transactionControllerState.transactions.find(\n (tx) => tx.id === transactionId,\n );\n}\n\n/**\n * Subscribe to transaction changes and update the transaction data accordingly.\n *\n * @param messenger - Controller messenger.\n * @param updateTransactionData - Callback to update transaction data.\n * @param removeTransactionData - Callback to remove transaction data.\n */\nexport function subscribeTransactionChanges(\n messenger: TransactionPayControllerMessenger,\n updateTransactionData: UpdateTransactionDataCallback,\n removeTransactionData: (transactionId: string) => void,\n): void {\n messenger.subscribe(\n 'TransactionController:stateChange',\n (\n transactions: TransactionMeta[],\n previousTransactions: TransactionMeta[] | undefined,\n ) => {\n const newTransactions = transactions.filter(\n (tx) => !previousTransactions?.find((prevTx) => prevTx.id === tx.id),\n );\n\n const updatedTransactions = transactions.filter((tx) => {\n const previousTransaction = previousTransactions?.find(\n (prevTx) => prevTx.id === tx.id,\n );\n\n return (\n previousTransaction &&\n previousTransaction?.txParams.data !== tx.txParams.data\n );\n });\n\n const finalizedTransactions = transactions.filter((tx) => {\n const previousTransaction = previousTransactions?.find(\n (prevTx) => prevTx.id === tx.id,\n );\n\n return (\n previousTransaction &&\n !FINALIZED_STATUSES.includes(previousTransaction.status) &&\n FINALIZED_STATUSES.includes(tx.status)\n );\n });\n\n const deletedTransactions = (previousTransactions ?? []).filter(\n (prevTx) => !transactions.find((tx) => tx.id === prevTx.id),\n );\n\n [...finalizedTransactions, ...deletedTransactions].forEach((tx) =>\n onTransactionFinalized(tx, removeTransactionData),\n );\n\n [...newTransactions, ...updatedTransactions].forEach((tx) =>\n onTransactionChange(tx, messenger, updateTransactionData),\n );\n },\n (state) => state.transactions,\n );\n}\n\n/**\n * Subscribe to asset state changes and re-parse required tokens for\n * in-flight transactions whose tokens have not yet resolved.\n *\n * @param messenger - Controller messenger.\n * @param getControllerState - Callback returning the current controller state.\n * @param updateTransactionData - Callback to update transaction data.\n */\nexport function subscribeAssetChanges(\n messenger: TransactionPayControllerMessenger,\n getControllerState: () => TransactionPayControllerState,\n updateTransactionData: UpdateTransactionDataCallback,\n): void {\n const buildHandler =\n (source: string) =>\n (_state: unknown, patches: Patch[] | undefined): void => {\n const { transactionData } = getControllerState();\n\n for (const [transactionId, data] of Object.entries(transactionData)) {\n if (data.tokens.length > 0) {\n continue;\n }\n\n const transaction = getTransaction(transactionId, messenger);\n\n if (!transaction || FINALIZED_STATUSES.includes(transaction.status)) {\n continue;\n }\n\n log('Asset data changed', { transactionId, source, patches });\n\n onTransactionChange(transaction, messenger, updateTransactionData);\n }\n };\n\n if (getAssetsUnifyStateFeature(messenger)) {\n messenger.subscribe(\n 'AssetsController:stateChange',\n buildHandler('AssetsController'),\n );\n return;\n }\n\n messenger.subscribe(\n 'TokensController:stateChange',\n buildHandler('TokensController'),\n );\n messenger.subscribe(\n 'TokenRatesController:stateChange',\n buildHandler('TokenRatesController'),\n );\n messenger.subscribe(\n 'CurrencyRateController:stateChange',\n buildHandler('CurrencyRateController'),\n );\n}\n\n/**\n * Wait for a transaction to be confirmed or fail.\n *\n * @param transactionId - ID of the transaction to wait for.\n * @param messenger - Controller messenger.\n * @returns A promise that resolves when the transaction is confirmed or rejects if it fails.\n */\nexport function waitForTransactionConfirmed(\n transactionId: string,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n const isConfirmed = (tx?: TransactionMeta, fn?: () => void): boolean => {\n log('Checking transaction status', tx?.status, tx?.type);\n\n if (tx?.status === TransactionStatus.confirmed) {\n fn?.();\n resolve();\n return true;\n }\n\n if (\n [TransactionStatus.dropped, TransactionStatus.failed].includes(\n tx?.status as TransactionStatus,\n )\n ) {\n fn?.();\n reject(\n new Error(`Transaction failed - ${tx?.type} - ${tx?.error?.message}`),\n );\n return true;\n }\n\n return false;\n };\n\n const initialState = messenger.call('TransactionController:getState');\n\n const initialTx = initialState.transactions.find(\n (singleTransaction) => singleTransaction.id === transactionId,\n );\n\n if (isConfirmed(initialTx)) {\n return;\n }\n\n const handler = (tx?: TransactionMeta): void => {\n const unsubscribe = (): void =>\n messenger.unsubscribe('TransactionController:stateChange', handler);\n\n isConfirmed(tx, unsubscribe);\n };\n\n messenger.subscribe('TransactionController:stateChange', handler, (state) =>\n state.transactions.find((tx) => tx.id === transactionId),\n );\n });\n}\n\n/**\n * Update a transaction by applying a function to its draft.\n *\n * @param request - Request object.\n * @param request.transactionId - ID of the transaction to update.\n * @param request.messenger - Controller messenger.\n * @param request.note - Note describing the update.\n * @param fn - Function that applies updates to the transaction draft.\n */\nexport function updateTransaction(\n {\n transactionId,\n messenger,\n note,\n }: {\n transactionId: string;\n messenger: TransactionPayControllerMessenger;\n note: string;\n },\n fn: (draft: TransactionMeta) => void,\n): void {\n const transaction = getTransaction(transactionId, messenger as never);\n\n if (!transaction) {\n throw new Error(`Transaction not found: ${transactionId}`);\n }\n\n const newTransaction = cloneDeep(transaction);\n\n fn(newTransaction);\n\n messenger.call(\n 'TransactionController:updateTransaction',\n newTransaction,\n note,\n );\n}\n\n/**\n * Collect all new transactions until `end` is called.\n *\n * @param chainId - The chain ID to filter transactions by.\n * @param from - The address to filter transactions by.\n * @param messenger - The controller messenger.\n * @param onTransaction - Callback called with each matching transaction ID.\n * @returns An object with an `end` method to stop collecting transactions.\n */\nexport function collectTransactionIds(\n chainId: Hex,\n from: Hex,\n messenger: TransactionPayControllerMessenger,\n onTransaction: (transactionId: string) => void,\n): { end: () => void } {\n const listener = (tx: TransactionMeta): void => {\n if (\n tx.chainId !== chainId ||\n tx.txParams.from.toLowerCase() !== from.toLowerCase()\n ) {\n return;\n }\n\n onTransaction(tx.id);\n };\n\n messenger.subscribe(\n 'TransactionController:unapprovedTransactionAdded',\n listener,\n );\n\n const end = (): void => {\n messenger.unsubscribe(\n 'TransactionController:unapprovedTransactionAdded',\n listener,\n );\n };\n\n return { end };\n}\n\n/**\n * Check whether a transaction is a Predict withdrawal.\n *\n * Returns `true` when the transaction's own type is `predictWithdraw`, or\n * when any of its nested transactions has that type.\n *\n * @param transaction - Transaction metadata.\n * @returns `true` when the transaction is a Predict withdrawal.\n */\nexport function isPredictWithdrawTransaction(\n transaction: TransactionMeta,\n): boolean {\n return (\n transaction.type === TransactionType.predictWithdraw ||\n (transaction.nestedTransactions?.some(\n (nt) => nt.type === TransactionType.predictWithdraw,\n ) ??\n false)\n );\n}\n\n/**\n * Handle a transaction change by updating its associated data.\n *\n * @param transaction - Transaction metadata.\n * @param messenger - Controller messenger.\n * @param updateTransactionData - Callback to update transaction data.\n */\nfunction onTransactionChange(\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n updateTransactionData: UpdateTransactionDataCallback,\n): void {\n const tokens = parseRequiredTokens(transaction, messenger);\n\n log('Transaction changed', { transaction, tokens });\n\n updateTransactionData(transaction.id, (data) => {\n data.tokens = tokens;\n });\n}\n\n/**\n * Handle a finalized transaction by removing its associated data.\n *\n * @param transaction - Transaction metadata.\n * @param removeTransactionData - Callback to remove transaction data.\n */\nfunction onTransactionFinalized(\n transaction: TransactionMeta,\n removeTransactionData: (transactionId: string) => void,\n): void {\n log('Transaction finalized', { transaction });\n removeTransactionData(transaction.id);\n}\n\nconst erc20Interface = new Interface(abiERC20);\n\nconst ERC20_TRANSFER_EVENT_TOPIC = erc20Interface.getEventTopic('Transfer');\n\n/**\n * Reads the transferred token amount from a completed on-chain transaction.\n *\n * For native tokens the amount is resolved via `debug_traceTransaction`\n * (internal-call aware), falling back to the top-level `tx.value`.\n * For ERC-20 tokens the amount is decoded from `Transfer` event logs\n * in the transaction receipt.\n *\n * @param options - The options.\n * @param options.messenger - Controller messenger for network access.\n * @param options.txHash - Transaction hash of the completed on-chain transaction.\n * @param options.chainId - Chain ID where the transaction was executed.\n * @param options.tokenAddress - Address of the transferred token.\n * @param options.walletAddress - Recipient wallet address to filter transfers to.\n * @returns The raw (atomic) transferred amount as a decimal string,\n * or `undefined` if the amount cannot be determined.\n */\nexport async function getTransferredAmountFromTxHash({\n messenger,\n txHash,\n chainId,\n tokenAddress,\n walletAddress,\n}: {\n messenger: TransactionPayControllerMessenger;\n txHash: string;\n chainId: Hex;\n tokenAddress: Hex;\n walletAddress: Hex;\n}): Promise<string | undefined> {\n const isNative =\n tokenAddress.toLowerCase() === getNativeToken(chainId).toLowerCase();\n\n if (isNative) {\n return await getNativeTransferAmount(\n messenger,\n chainId,\n txHash,\n walletAddress,\n );\n }\n\n return await getErc20TransferAmount(\n messenger,\n chainId,\n txHash,\n tokenAddress,\n walletAddress,\n );\n}\n\n/**\n * Resolves the native token amount received by a wallet from a transaction.\n *\n * 1. Attempts `debug_traceTransaction` with `callTracer` to walk internal\n * calls and sum all native value transfers targeting `walletAddress`.\n * 2. Falls back to the top-level `tx.value` when the wallet is the direct\n * recipient and the trace RPC is unavailable or errors.\n *\n * @param messenger - Controller messenger.\n * @param chainId - Chain ID where the transaction was executed.\n * @param txHash - Transaction hash.\n * @param walletAddress - Recipient wallet address.\n * @returns Raw amount as a decimal string, or `undefined`.\n */\nasync function getNativeTransferAmount(\n messenger: TransactionPayControllerMessenger,\n chainId: Hex,\n txHash: string,\n walletAddress: Hex,\n): Promise<string | undefined> {\n try {\n const trace = await rpcRequest<CallTrace>({\n messenger,\n chainId,\n method: 'debug_traceTransaction',\n params: [txHash, { tracer: 'callTracer' }],\n });\n\n const amount = sumNativeValueFromTrace(trace, walletAddress);\n if (amount.gt(0)) {\n return amount.toFixed(0);\n }\n } catch {\n // debug_traceTransaction not supported — fall through to tx.value\n }\n\n const tx = await rpcRequest<{ to?: string; value: string } | null>({\n messenger,\n chainId,\n method: 'eth_getTransactionByHash',\n params: [txHash],\n });\n\n if (!tx) {\n return undefined;\n }\n\n if (tx.to?.toLowerCase() !== walletAddress.toLowerCase()) {\n return undefined;\n }\n\n return positiveOrUndefined(new BigNumber(tx.value).toFixed(0));\n}\n\n/**\n * Resolves the ERC-20 token amount received by a wallet from a transaction\n * by decoding `Transfer` event logs from the transaction receipt.\n *\n * @param messenger - Controller messenger.\n * @param chainId - Chain ID where the transaction was executed.\n * @param txHash - Transaction hash.\n * @param tokenAddress - ERC-20 token contract address.\n * @param walletAddress - Recipient wallet address.\n * @returns Raw amount as a decimal string, or `undefined`.\n */\nasync function getErc20TransferAmount(\n messenger: TransactionPayControllerMessenger,\n chainId: Hex,\n txHash: string,\n tokenAddress: Hex,\n walletAddress: Hex,\n): Promise<string | undefined> {\n const receipt = await rpcRequest<{\n logs: { address: string; topics: string[]; data: string }[];\n } | null>({\n messenger,\n chainId,\n method: 'eth_getTransactionReceipt',\n params: [txHash],\n });\n\n if (!receipt) {\n return undefined;\n }\n\n let total = new BigNumber(0);\n\n for (const txLog of receipt.logs) {\n if (txLog.address.toLowerCase() !== tokenAddress.toLowerCase()) {\n continue;\n }\n\n if (!txLog.topics[0] || txLog.topics[0] !== ERC20_TRANSFER_EVENT_TOPIC) {\n continue;\n }\n\n try {\n const parsed = erc20Interface.parseLog(txLog);\n const to = (parsed.args[1] as string).toLowerCase();\n\n if (to !== walletAddress.toLowerCase()) {\n continue;\n }\n\n total = total.plus(parsed.args[2].toString());\n } catch {\n continue;\n }\n }\n\n return positiveOrUndefined(total.toFixed(0));\n}\n\ntype CallTrace = {\n to?: string;\n value?: string;\n calls?: CallTrace[];\n};\n\n/**\n * Recursively walks a `callTracer` result and sums native value\n * transferred to a specific address.\n *\n * @param trace - Call trace node.\n * @param walletAddress - Target address to accumulate value for.\n * @returns Accumulated native value as BigNumber.\n */\nfunction sumNativeValueFromTrace(\n trace: CallTrace,\n walletAddress: Hex,\n): BigNumber {\n let total = new BigNumber(0);\n\n if (\n trace.to?.toLowerCase() === walletAddress.toLowerCase() &&\n trace.value &&\n trace.value !== '0x0'\n ) {\n total = total.plus(new BigNumber(trace.value));\n }\n\n if (trace.calls) {\n for (const child of trace.calls) {\n total = total.plus(sumNativeValueFromTrace(child, walletAddress));\n }\n }\n\n return total;\n}\n\nfunction positiveOrUndefined(amount: string): string | undefined {\n return new BigNumber(amount).gt(0) ? amount : undefined;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"transaction.mjs","sourceRoot":"","sources":["../../src/utils/transaction.ts"],"names":[],"mappings":"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","sourcesContent":["import { Interface } from '@ethersproject/abi';\nimport { abiERC20 } from '@metamask/metamask-eth-abis';\nimport {\n TransactionStatus,\n TransactionType,\n} from '@metamask/transaction-controller';\nimport type { TransactionMeta } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\nimport type { Patch } from 'immer';\nimport { cloneDeep } from 'lodash';\n\nimport { projectLogger } from '../logger';\nimport type {\n TransactionPayControllerMessenger,\n TransactionPayControllerState,\n UpdateTransactionDataCallback,\n} from '../types';\nimport { getAssetsUnifyStateFeature } from './feature-flags';\nimport { rpcRequest } from './provider';\nimport { parseRequiredTokens } from './required-tokens';\nimport { getNativeToken } from './token';\n\nconst log = createModuleLogger(projectLogger, 'transaction');\n\nexport const FINALIZED_STATUSES = [\n TransactionStatus.confirmed,\n TransactionStatus.dropped,\n TransactionStatus.failed,\n];\n\n/**\n * Retrieve transaction metadata by ID.\n *\n * @param transactionId - ID of the transaction to retrieve.\n * @param messenger - Controller messenger.\n * @returns The transaction metadata or undefined if not found.\n */\nexport function getTransaction(\n transactionId: string,\n messenger: TransactionPayControllerMessenger,\n): TransactionMeta | undefined {\n const transactionControllerState = messenger.call(\n 'TransactionController:getState',\n );\n\n return transactionControllerState.transactions.find(\n (tx) => tx.id === transactionId,\n );\n}\n\n/**\n * Subscribe to transaction changes and update the transaction data accordingly.\n *\n * @param messenger - Controller messenger.\n * @param updateTransactionData - Callback to update transaction data.\n * @param removeTransactionData - Callback to remove transaction data.\n */\nexport function subscribeTransactionChanges(\n messenger: TransactionPayControllerMessenger,\n updateTransactionData: UpdateTransactionDataCallback,\n removeTransactionData: (transactionId: string) => void,\n): void {\n messenger.subscribe(\n 'TransactionController:stateChange',\n (\n transactions: TransactionMeta[],\n previousTransactions: TransactionMeta[] | undefined,\n ) => {\n const newTransactions = transactions.filter(\n (tx) => !previousTransactions?.find((prevTx) => prevTx.id === tx.id),\n );\n\n const updatedTransactions = transactions.filter((tx) => {\n const previousTransaction = previousTransactions?.find(\n (prevTx) => prevTx.id === tx.id,\n );\n\n return (\n previousTransaction &&\n previousTransaction?.txParams.data !== tx.txParams.data\n );\n });\n\n const finalizedTransactions = transactions.filter((tx) => {\n const previousTransaction = previousTransactions?.find(\n (prevTx) => prevTx.id === tx.id,\n );\n\n return (\n previousTransaction &&\n !FINALIZED_STATUSES.includes(previousTransaction.status) &&\n FINALIZED_STATUSES.includes(tx.status)\n );\n });\n\n const deletedTransactions = (previousTransactions ?? []).filter(\n (prevTx) => !transactions.find((tx) => tx.id === prevTx.id),\n );\n\n [...finalizedTransactions, ...deletedTransactions].forEach((tx) =>\n onTransactionFinalized(tx, removeTransactionData),\n );\n\n [...newTransactions, ...updatedTransactions].forEach((tx) =>\n onTransactionChange(tx, messenger, updateTransactionData),\n );\n },\n (state) => state.transactions,\n );\n}\n\n/**\n * Subscribe to asset state changes and re-parse required tokens for\n * in-flight transactions whose tokens have not yet resolved.\n *\n * @param messenger - Controller messenger.\n * @param getControllerState - Callback returning the current controller state.\n * @param updateTransactionData - Callback to update transaction data.\n */\nexport function subscribeAssetChanges(\n messenger: TransactionPayControllerMessenger,\n getControllerState: () => TransactionPayControllerState,\n updateTransactionData: UpdateTransactionDataCallback,\n): void {\n const buildHandler =\n (source: string) =>\n (_state: unknown, patches: Patch[] | undefined): void => {\n const { transactionData } = getControllerState();\n\n for (const [transactionId, data] of Object.entries(transactionData)) {\n if (data.tokens.length > 0) {\n continue;\n }\n\n const transaction = getTransaction(transactionId, messenger);\n\n if (!transaction || FINALIZED_STATUSES.includes(transaction.status)) {\n continue;\n }\n\n log('Asset data changed', { transactionId, source, patches });\n\n onTransactionChange(transaction, messenger, updateTransactionData);\n }\n };\n\n if (getAssetsUnifyStateFeature(messenger)) {\n messenger.subscribe(\n 'AssetsController:stateChange',\n buildHandler('AssetsController'),\n );\n return;\n }\n\n messenger.subscribe(\n 'TokensController:stateChange',\n buildHandler('TokensController'),\n );\n messenger.subscribe(\n 'TokenRatesController:stateChange',\n buildHandler('TokenRatesController'),\n );\n messenger.subscribe(\n 'CurrencyRateController:stateChange',\n buildHandler('CurrencyRateController'),\n );\n}\n\n/**\n * Wait for a transaction to be confirmed or fail.\n *\n * @param transactionId - ID of the transaction to wait for.\n * @param messenger - Controller messenger.\n * @returns A promise that resolves when the transaction is confirmed or rejects if it fails.\n */\nexport function waitForTransactionConfirmed(\n transactionId: string,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n const isConfirmed = (tx?: TransactionMeta, fn?: () => void): boolean => {\n log('Checking transaction status', tx?.status, tx?.type);\n\n if (tx?.status === TransactionStatus.confirmed) {\n fn?.();\n resolve();\n return true;\n }\n\n if (\n [TransactionStatus.dropped, TransactionStatus.failed].includes(\n tx?.status as TransactionStatus,\n )\n ) {\n fn?.();\n reject(\n new Error(`Transaction failed - ${tx?.type} - ${tx?.error?.message}`),\n );\n return true;\n }\n\n return false;\n };\n\n const initialState = messenger.call('TransactionController:getState');\n\n const initialTx = initialState.transactions.find(\n (singleTransaction) => singleTransaction.id === transactionId,\n );\n\n if (isConfirmed(initialTx)) {\n return;\n }\n\n const handler = (tx?: TransactionMeta): void => {\n const unsubscribe = (): void =>\n messenger.unsubscribe('TransactionController:stateChange', handler);\n\n isConfirmed(tx, unsubscribe);\n };\n\n messenger.subscribe('TransactionController:stateChange', handler, (state) =>\n state.transactions.find((tx) => tx.id === transactionId),\n );\n });\n}\n\n/**\n * Update a transaction by applying a function to its draft.\n *\n * @param request - Request object.\n * @param request.transactionId - ID of the transaction to update.\n * @param request.messenger - Controller messenger.\n * @param request.note - Note describing the update.\n * @param fn - Function that applies updates to the transaction draft.\n */\nexport function updateTransaction(\n {\n transactionId,\n messenger,\n note,\n }: {\n transactionId: string;\n messenger: TransactionPayControllerMessenger;\n note: string;\n },\n fn: (draft: TransactionMeta) => void,\n): void {\n const transaction = getTransaction(transactionId, messenger as never);\n\n if (!transaction) {\n throw new Error(`Transaction not found: ${transactionId}`);\n }\n\n const newTransaction = cloneDeep(transaction);\n\n fn(newTransaction);\n\n messenger.call(\n 'TransactionController:updateTransaction',\n newTransaction,\n note,\n );\n}\n\n/**\n * Collect all new transactions until `end` is called.\n *\n * @param chainId - The chain ID to filter transactions by.\n * @param from - The address to filter transactions by.\n * @param messenger - The controller messenger.\n * @param onTransaction - Callback called with each matching transaction ID.\n * @returns An object with an `end` method to stop collecting transactions.\n */\nexport function collectTransactionIds(\n chainId: Hex,\n from: Hex,\n messenger: TransactionPayControllerMessenger,\n onTransaction: (transactionId: string) => void,\n): { end: () => void } {\n const listener = (tx: TransactionMeta): void => {\n if (\n tx.chainId !== chainId ||\n tx.txParams.from.toLowerCase() !== from.toLowerCase()\n ) {\n return;\n }\n\n onTransaction(tx.id);\n };\n\n messenger.subscribe(\n 'TransactionController:unapprovedTransactionAdded',\n listener,\n );\n\n const end = (): void => {\n messenger.unsubscribe(\n 'TransactionController:unapprovedTransactionAdded',\n listener,\n );\n };\n\n return { end };\n}\n\n/**\n * Check whether a transaction is a Predict withdrawal.\n *\n * Returns `true` when the transaction's own type is `predictWithdraw`, or\n * when any of its nested transactions has that type.\n *\n * @param transaction - Transaction metadata.\n * @returns `true` when the transaction is a Predict withdrawal.\n */\nexport function isPredictWithdrawTransaction(\n transaction: TransactionMeta,\n): boolean {\n return (\n transaction.type === TransactionType.predictWithdraw ||\n (transaction.nestedTransactions?.some(\n (nt) => nt.type === TransactionType.predictWithdraw,\n ) ??\n false)\n );\n}\n\n/**\n * Handle a transaction change by updating its associated data.\n *\n * @param transaction - Transaction metadata.\n * @param messenger - Controller messenger.\n * @param updateTransactionData - Callback to update transaction data.\n */\nfunction onTransactionChange(\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n updateTransactionData: UpdateTransactionDataCallback,\n): void {\n const tokens = parseRequiredTokens(transaction, messenger);\n\n log('Transaction changed', { transaction, tokens });\n\n updateTransactionData(transaction.id, (data) => {\n data.tokens = tokens;\n });\n}\n\n/**\n * Handle a finalized transaction by removing its associated data.\n *\n * @param transaction - Transaction metadata.\n * @param removeTransactionData - Callback to remove transaction data.\n */\nfunction onTransactionFinalized(\n transaction: TransactionMeta,\n removeTransactionData: (transactionId: string) => void,\n): void {\n log('Transaction finalized', { transaction });\n removeTransactionData(transaction.id);\n}\n\nconst erc20Interface = new Interface(abiERC20);\n\nconst ERC20_TRANSFER_EVENT_TOPIC = erc20Interface.getEventTopic('Transfer');\n\n/**\n * Result from {@link getTransferredAmountFromTxHash}.\n */\nexport type TransferredAmountResult = {\n /** Raw (atomic) transferred amount as a decimal string, or `undefined`. */\n amountRaw: string | undefined;\n /**\n * Block number of the on-chain transaction as a 0x-prefixed hex string.\n * Populated only for ERC-20 tokens (sourced from the receipt); `undefined`\n * for native token transactions.\n */\n blockNumber: Hex | undefined;\n};\n\n/**\n * Reads the transferred token amount from a completed on-chain transaction.\n *\n * For native tokens the amount is resolved via `debug_traceTransaction`\n * (internal-call aware), falling back to the top-level `tx.value`.\n * For ERC-20 tokens the amount is decoded from `Transfer` event logs\n * in the transaction receipt, and the receipt `blockNumber` is also returned.\n *\n * @param options - The options.\n * @param options.messenger - Controller messenger for network access.\n * @param options.txHash - Transaction hash of the completed on-chain transaction.\n * @param options.chainId - Chain ID where the transaction was executed.\n * @param options.tokenAddress - Address of the transferred token.\n * @param options.walletAddress - Recipient wallet address to filter transfers to.\n * @returns The raw transferred amount and, for ERC-20, the receipt block number.\n */\nexport async function getTransferredAmountFromTxHash({\n messenger,\n txHash,\n chainId,\n tokenAddress,\n walletAddress,\n}: {\n messenger: TransactionPayControllerMessenger;\n txHash: string;\n chainId: Hex;\n tokenAddress: Hex;\n walletAddress: Hex;\n}): Promise<TransferredAmountResult> {\n const isNative =\n tokenAddress.toLowerCase() === getNativeToken(chainId).toLowerCase();\n\n if (isNative) {\n const amountRaw = await getNativeTransferAmount(\n messenger,\n chainId,\n txHash,\n walletAddress,\n );\n\n return { amountRaw, blockNumber: undefined };\n }\n\n return await getErc20TransferAmount(\n messenger,\n chainId,\n txHash,\n tokenAddress,\n walletAddress,\n );\n}\n\n/**\n * Resolves the native token amount received by a wallet from a transaction.\n *\n * 1. Attempts `debug_traceTransaction` with `callTracer` to walk internal\n * calls and sum all native value transfers targeting `walletAddress`.\n * 2. Falls back to the top-level `tx.value` when the wallet is the direct\n * recipient and the trace RPC is unavailable or errors.\n *\n * @param messenger - Controller messenger.\n * @param chainId - Chain ID where the transaction was executed.\n * @param txHash - Transaction hash.\n * @param walletAddress - Recipient wallet address.\n * @returns Raw amount as a decimal string, or `undefined`.\n */\nasync function getNativeTransferAmount(\n messenger: TransactionPayControllerMessenger,\n chainId: Hex,\n txHash: string,\n walletAddress: Hex,\n): Promise<string | undefined> {\n try {\n const trace = await rpcRequest<CallTrace>({\n messenger,\n chainId,\n method: 'debug_traceTransaction',\n params: [txHash, { tracer: 'callTracer' }],\n });\n\n const amount = sumNativeValueFromTrace(trace, walletAddress);\n if (amount.gt(0)) {\n return amount.toFixed(0);\n }\n } catch {\n // debug_traceTransaction not supported — fall through to tx.value\n }\n\n const tx = await rpcRequest<{ to?: string; value: string } | null>({\n messenger,\n chainId,\n method: 'eth_getTransactionByHash',\n params: [txHash],\n });\n\n if (!tx) {\n return undefined;\n }\n\n if (tx.to?.toLowerCase() !== walletAddress.toLowerCase()) {\n return undefined;\n }\n\n return positiveOrUndefined(new BigNumber(tx.value).toFixed(0));\n}\n\n/**\n * Resolves the ERC-20 token amount received by a wallet from a transaction\n * by decoding `Transfer` event logs from the transaction receipt. Also\n * returns the receipt `blockNumber` so callers can reuse it without a\n * second network request.\n *\n * @param messenger - Controller messenger.\n * @param chainId - Chain ID where the transaction was executed.\n * @param txHash - Transaction hash.\n * @param tokenAddress - ERC-20 token contract address.\n * @param walletAddress - Recipient wallet address.\n * @returns Raw amount (or `undefined`) and the receipt block number (or `undefined`).\n */\nasync function getErc20TransferAmount(\n messenger: TransactionPayControllerMessenger,\n chainId: Hex,\n txHash: string,\n tokenAddress: Hex,\n walletAddress: Hex,\n): Promise<TransferredAmountResult> {\n const receipt = await rpcRequest<{\n blockNumber: Hex;\n logs: { address: string; topics: string[]; data: string }[];\n } | null>({\n messenger,\n chainId,\n method: 'eth_getTransactionReceipt',\n params: [txHash],\n });\n\n if (!receipt) {\n return { amountRaw: undefined, blockNumber: undefined };\n }\n\n const { blockNumber } = receipt;\n let total = new BigNumber(0);\n\n for (const txLog of receipt.logs) {\n if (txLog.address.toLowerCase() !== tokenAddress.toLowerCase()) {\n continue;\n }\n\n if (!txLog.topics[0] || txLog.topics[0] !== ERC20_TRANSFER_EVENT_TOPIC) {\n continue;\n }\n\n try {\n const parsed = erc20Interface.parseLog(txLog);\n const to = (parsed.args[1] as string).toLowerCase();\n\n if (to !== walletAddress.toLowerCase()) {\n continue;\n }\n\n total = total.plus(parsed.args[2].toString());\n } catch {\n continue;\n }\n }\n\n return { amountRaw: positiveOrUndefined(total.toFixed(0)), blockNumber };\n}\n\ntype CallTrace = {\n to?: string;\n value?: string;\n calls?: CallTrace[];\n};\n\n/**\n * Recursively walks a `callTracer` result and sums native value\n * transferred to a specific address.\n *\n * @param trace - Call trace node.\n * @param walletAddress - Target address to accumulate value for.\n * @returns Accumulated native value as BigNumber.\n */\nfunction sumNativeValueFromTrace(\n trace: CallTrace,\n walletAddress: Hex,\n): BigNumber {\n let total = new BigNumber(0);\n\n if (\n trace.to?.toLowerCase() === walletAddress.toLowerCase() &&\n trace.value &&\n trace.value !== '0x0'\n ) {\n total = total.plus(new BigNumber(trace.value));\n }\n\n if (trace.calls) {\n for (const child of trace.calls) {\n total = total.plus(sumNativeValueFromTrace(child, walletAddress));\n }\n }\n\n return total;\n}\n\nfunction positiveOrUndefined(amount: string): string | undefined {\n return new BigNumber(amount).gt(0) ? amount : undefined;\n}\n"]}
|
package/package.json
CHANGED