@metamask/transaction-pay-controller 16.1.1 → 16.2.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"relay-submit.cjs","sourceRoot":"","sources":["../../../src/strategy/relay/relay-submit.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ORIGIN_METAMASK,\n successfulFetch,\n toHex,\n} from '@metamask/controller-utils';\nimport { TransactionType } from '@metamask/transaction-controller';\nimport type { TransactionParams } from '@metamask/transaction-controller';\nimport type {\n AuthorizationList,\n TransactionMeta,\n} from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport {\n RELAY_DEPOSIT_TYPES,\n RELAY_POLLING_INTERVAL,\n RELAY_STATUS_URL,\n} from './constants';\nimport type { RelayQuote, RelayStatusResponse } from './types';\nimport { projectLogger } from '../../logger';\nimport type {\n PayStrategyExecuteRequest,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types';\nimport { getFeatureFlags } from '../../utils/feature-flags';\nimport { getLiveTokenBalance } from '../../utils/token';\nimport {\n collectTransactionIds,\n getTransaction,\n updateTransaction,\n waitForTransactionConfirmed,\n} from '../../utils/transaction';\n\nconst FALLBACK_HASH = '0x0' as Hex;\n\nconst log = createModuleLogger(projectLogger, 'relay-strategy');\n\n/**\n * Submits Relay quotes.\n *\n * @param request - Request object.\n * @returns An object containing the transaction hash if available.\n */\nexport async function submitRelayQuotes(\n request: PayStrategyExecuteRequest<RelayQuote>,\n): Promise<{ transactionHash?: Hex }> {\n log('Executing quotes', request);\n\n const { quotes, messenger, transaction } = request;\n\n let transactionHash: Hex | undefined;\n\n for (const quote of quotes) {\n ({ transactionHash } = await executeSingleQuote(\n quote,\n messenger,\n transaction,\n ));\n }\n\n return { transactionHash };\n}\n\n/**\n * Executes a single Relay quote.\n *\n * @param quote - Relay quote to execute.\n * @param messenger - Controller messenger.\n * @param transaction - Original transaction meta.\n * @returns An object containing the transaction hash if available.\n */\nasync function executeSingleQuote(\n quote: TransactionPayQuote<RelayQuote>,\n messenger: TransactionPayControllerMessenger,\n transaction: TransactionMeta,\n): Promise<{ transactionHash?: Hex }> {\n log('Executing single quote', quote);\n\n updateTransaction(\n {\n transactionId: transaction.id,\n messenger,\n note: 'Remove nonce from skipped transaction',\n },\n (tx) => {\n tx.txParams.nonce = undefined;\n },\n );\n\n await submitTransactions(quote, transaction, messenger);\n\n const targetHash = await waitForRelayCompletion(quote.original);\n\n log('Relay request completed', targetHash);\n\n updateTransaction(\n {\n transactionId: transaction.id,\n messenger,\n note: 'Intent complete after Relay completion',\n },\n (tx) => {\n tx.isIntentComplete = true;\n },\n );\n\n return { transactionHash: targetHash };\n}\n\n/**\n * Wait for a Relay request to complete.\n *\n * @param quote - Relay quote associated with the request.\n * @returns A promise that resolves when the Relay request is complete.\n */\nasync function waitForRelayCompletion(quote: RelayQuote): Promise<Hex> {\n const isSameChain =\n quote.details.currencyIn.currency.chainId ===\n quote.details.currencyOut.currency.chainId;\n\n const isSingleDepositStep =\n quote.steps.length === 1 && quote.steps[0].id === 'deposit';\n\n if (isSameChain && !isSingleDepositStep) {\n log('Skipping polling as same chain');\n return FALLBACK_HASH;\n }\n\n const { requestId } = quote.steps[0];\n const url = `${RELAY_STATUS_URL}?requestId=${requestId}`;\n\n while (true) {\n const response = await successfulFetch(url, { method: 'GET' });\n const status = (await response.json()) as RelayStatusResponse;\n\n log('Polled status', status.status, status);\n\n if (status.status === 'success') {\n const targetHash = status.txHashes?.slice(-1)[0] as Hex;\n return targetHash ?? FALLBACK_HASH;\n }\n\n if (['failure', 'refund', 'refunded'].includes(status.status)) {\n throw new Error(`Relay request failed with status: ${status.status}`);\n }\n\n await new Promise((resolve) => setTimeout(resolve, RELAY_POLLING_INTERVAL));\n }\n}\n\n/**\n * Normalize the parameters from a relay quote step to match TransactionParams.\n *\n * @param params - Parameters from a relay quote step.\n * @param messenger - Controller messenger.\n * @returns Normalized transaction parameters.\n */\nfunction normalizeParams(\n params: RelayQuote['steps'][0]['items'][0]['data'],\n messenger: TransactionPayControllerMessenger,\n): TransactionParams {\n const featureFlags = getFeatureFlags(messenger);\n\n return {\n data: params.data,\n from: params.from,\n gas: toHex(params.gas ?? featureFlags.relayFallbackGas.max),\n maxFeePerGas: toHex(params.maxFeePerGas),\n maxPriorityFeePerGas: toHex(params.maxPriorityFeePerGas),\n to: params.to,\n value: toHex(params.value ?? '0'),\n };\n}\n\n/**\n * Validate the source token balance is sufficient for the relay deposit.\n *\n * Reads the live balance from TokenBalancesController and compares it against\n * the quote's required source amount to prevent submitting transactions that\n * will revert on-chain due to insufficient balance.\n *\n * @param quote - Relay quote containing the required source amount.\n * @param messenger - Controller messenger.\n */\nasync function validateSourceBalance(\n quote: TransactionPayQuote<RelayQuote>,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n const { from, sourceChainId, sourceTokenAddress } = quote.request;\n\n let currentBalance: string;\n\n try {\n currentBalance = await getLiveTokenBalance(\n messenger,\n from,\n sourceChainId,\n sourceTokenAddress,\n );\n } catch (error) {\n throw new Error(\n `Cannot validate payment token balance - ${(error as Error).message}`,\n );\n }\n\n const requiredAmount = new BigNumber(quote.sourceAmount.raw);\n const balance = new BigNumber(currentBalance);\n\n log('Validating source balance', {\n from,\n sourceChainId,\n sourceTokenAddress,\n currentBalance,\n requiredAmount: requiredAmount.toString(10),\n });\n\n if (balance.isLessThan(requiredAmount)) {\n throw new Error(\n `Insufficient source token balance for relay deposit. ` +\n `Required: ${requiredAmount.toString(10)}, ` +\n `Available: ${balance.toString(10)}`,\n );\n }\n}\n\n/**\n * Submit transactions for a relay quote.\n *\n * @param quote - Relay quote.\n * @param transaction - Original transaction meta.\n * @param messenger - Controller messenger.\n * @returns Hash of the last submitted transaction.\n */\nasync function submitTransactions(\n quote: TransactionPayQuote<RelayQuote>,\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n): Promise<Hex> {\n const { steps } = quote.original;\n const params = steps.flatMap((step) => step.items).map((item) => item.data);\n const invalidKind = steps.find((step) => step.kind !== 'transaction')?.kind;\n\n if (invalidKind) {\n throw new Error(`Unsupported step kind: ${invalidKind}`);\n }\n\n await validateSourceBalance(quote, messenger);\n\n const normalizedParams = params.map((singleParams) =>\n normalizeParams(singleParams, messenger),\n );\n\n // For post-quote flows, prepend the original transaction so it gets\n // included in the batch alongside the relay deposit(s).\n // This always results in multiple params, so it takes the batch path.\n const { isPostQuote } = quote.request;\n\n const allParams =\n isPostQuote && transaction.txParams.to\n ? [\n {\n data: transaction.txParams.data as Hex | undefined,\n from: transaction.txParams.from,\n to: transaction.txParams.to,\n value: transaction.txParams.value as Hex | undefined,\n } as TransactionParams,\n ...normalizedParams,\n ]\n : normalizedParams;\n\n const transactionIds: string[] = [];\n const { from, sourceChainId, sourceTokenAddress } = quote.request;\n\n const networkClientId = messenger.call(\n 'NetworkController:findNetworkClientIdByChainId',\n sourceChainId,\n );\n\n log('Adding transactions', {\n normalizedParams: allParams,\n sourceChainId,\n from,\n networkClientId,\n });\n\n const { end } = collectTransactionIds(\n sourceChainId,\n from,\n messenger,\n (transactionId) => {\n transactionIds.push(transactionId);\n\n updateTransaction(\n {\n transactionId: transaction.id,\n messenger,\n note: 'Add required transaction ID from Relay submission',\n },\n (tx) => {\n tx.requiredTransactionIds ??= [];\n tx.requiredTransactionIds.push(transactionId);\n },\n );\n },\n );\n\n let result: { result: Promise<string> } | undefined;\n\n const gasFeeToken = quote.fees.isSourceGasFeeToken\n ? sourceTokenAddress\n : undefined;\n\n const isSameChain =\n quote.original.details.currencyIn.currency.chainId ===\n quote.original.details.currencyOut.currency.chainId;\n\n const authorizationList: AuthorizationList | undefined =\n isSameChain && quote.original.request.authorizationList?.length\n ? quote.original.request.authorizationList.map((a) => ({\n address: a.address,\n chainId: toHex(a.chainId),\n }))\n : undefined;\n\n const { gasLimits } = quote.original.metamask;\n\n if (allParams.length === 1) {\n const transactionParams = {\n ...allParams[0],\n authorizationList,\n gas: toHex(gasLimits[0]),\n };\n\n result = await messenger.call(\n 'TransactionController:addTransaction',\n transactionParams,\n {\n gasFeeToken,\n networkClientId,\n origin: ORIGIN_METAMASK,\n requireApproval: false,\n type: getRelayDepositType(transaction.type),\n },\n );\n } else {\n const gasLimit7702 =\n gasLimits.length === 1 && allParams.length > 1\n ? toHex(gasLimits[0])\n : undefined;\n\n const transactions = allParams.map((singleParams, index) => {\n const gasLimit = gasLimits[index];\n const gas =\n gasLimit === undefined || gasLimit7702 ? undefined : toHex(gasLimit);\n\n return {\n params: {\n data: singleParams.data as Hex,\n gas,\n maxFeePerGas: singleParams.maxFeePerGas as Hex,\n maxPriorityFeePerGas: singleParams.maxPriorityFeePerGas as Hex,\n to: singleParams.to as Hex,\n value: singleParams.value as Hex,\n },\n type: getTransactionType(\n isPostQuote,\n index,\n transaction.type,\n normalizedParams.length,\n ),\n };\n });\n\n await messenger.call('TransactionController:addTransactionBatch', {\n from,\n disable7702: !gasLimit7702,\n disableHook: Boolean(gasLimit7702),\n disableSequential: Boolean(gasLimit7702),\n gasFeeToken,\n gasLimit7702,\n networkClientId,\n origin: ORIGIN_METAMASK,\n overwriteUpgrade: true,\n requireApproval: false,\n transactions,\n });\n }\n\n end();\n\n log('Added transactions', transactionIds);\n\n if (result) {\n const txHash = await result.result;\n log('Submitted transaction', txHash);\n }\n\n await Promise.all(\n transactionIds.map((txId) => waitForTransactionConfirmed(txId, messenger)),\n );\n\n log('All transactions confirmed', transactionIds);\n\n const hash = getTransaction(transactionIds.slice(-1)[0], messenger)?.hash;\n\n return hash as Hex;\n}\n\n/**\n * Determine the transaction type for a given index in the batch.\n *\n * @param isPostQuote - Whether this is a post-quote flow.\n * @param index - Index of the transaction in the batch.\n * @param originalType - Type of the original transaction (used for post-quote index 0).\n * @param relayParamCount - Number of relay-only params (excludes prepended original tx).\n * @returns The transaction type.\n */\nfunction getTransactionType(\n isPostQuote: boolean | undefined,\n index: number,\n originalType: TransactionMeta['type'],\n relayParamCount: number,\n): TransactionMeta['type'] {\n // Post-quote index 0 is the original transaction\n if (isPostQuote && index === 0) {\n return originalType;\n }\n\n // Adjust index for post-quote flows where original tx is prepended\n const relayIndex = isPostQuote ? index - 1 : index;\n\n const depositType = getRelayDepositType(originalType);\n\n // Single relay step is always a deposit (no approval needed)\n if (relayParamCount === 1) {\n return depositType;\n }\n\n return relayIndex === 0 ? TransactionType.tokenMethodApprove : depositType;\n}\n\n/**\n * Get the relay deposit transaction type based on the parent transaction type.\n *\n * @param originalType - Type of the parent transaction.\n * @returns The mapped relay deposit type, or `relayDeposit` as a fallback.\n */\nfunction getRelayDepositType(\n originalType: TransactionMeta['type'],\n): TransactionType {\n return (\n (originalType && RELAY_DEPOSIT_TYPES[originalType]) ??\n TransactionType.relayDeposit\n );\n}\n"]}
1
+ {"version":3,"file":"relay-submit.cjs","sourceRoot":"","sources":["../../../src/strategy/relay/relay-submit.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ORIGIN_METAMASK,\n successfulFetch,\n toHex,\n} from '@metamask/controller-utils';\nimport { TransactionType } from '@metamask/transaction-controller';\nimport type { TransactionParams } from '@metamask/transaction-controller';\nimport type {\n AuthorizationList,\n TransactionMeta,\n} from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport {\n RELAY_DEPOSIT_TYPES,\n RELAY_POLLING_INTERVAL,\n RELAY_STATUS_URL,\n} from './constants';\nimport type { RelayQuote, RelayStatusResponse } from './types';\nimport { projectLogger } from '../../logger';\nimport type {\n PayStrategyExecuteRequest,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types';\nimport { getFeatureFlags } from '../../utils/feature-flags';\nimport {\n getLiveTokenBalance,\n normalizeTokenAddress,\n TokenAddressTarget,\n} from '../../utils/token';\nimport {\n collectTransactionIds,\n getTransaction,\n updateTransaction,\n waitForTransactionConfirmed,\n} from '../../utils/transaction';\n\nconst FALLBACK_HASH = '0x0' as Hex;\n\nconst log = createModuleLogger(projectLogger, 'relay-strategy');\n\n/**\n * Submits Relay quotes.\n *\n * @param request - Request object.\n * @returns An object containing the transaction hash if available.\n */\nexport async function submitRelayQuotes(\n request: PayStrategyExecuteRequest<RelayQuote>,\n): Promise<{ transactionHash?: Hex }> {\n log('Executing quotes', request);\n\n const { quotes, messenger, transaction } = request;\n\n let transactionHash: Hex | undefined;\n\n for (const quote of quotes) {\n ({ transactionHash } = await executeSingleQuote(\n quote,\n messenger,\n transaction,\n ));\n }\n\n return { transactionHash };\n}\n\n/**\n * Executes a single Relay quote.\n *\n * @param quote - Relay quote to execute.\n * @param messenger - Controller messenger.\n * @param transaction - Original transaction meta.\n * @returns An object containing the transaction hash if available.\n */\nasync function executeSingleQuote(\n quote: TransactionPayQuote<RelayQuote>,\n messenger: TransactionPayControllerMessenger,\n transaction: TransactionMeta,\n): Promise<{ transactionHash?: Hex }> {\n log('Executing single quote', quote);\n\n updateTransaction(\n {\n transactionId: transaction.id,\n messenger,\n note: 'Remove nonce from skipped transaction',\n },\n (tx) => {\n tx.txParams.nonce = undefined;\n },\n );\n\n await submitTransactions(quote, transaction, messenger);\n\n const targetHash = await waitForRelayCompletion(quote.original);\n\n log('Relay request completed', targetHash);\n\n updateTransaction(\n {\n transactionId: transaction.id,\n messenger,\n note: 'Intent complete after Relay completion',\n },\n (tx) => {\n tx.isIntentComplete = true;\n },\n );\n\n return { transactionHash: targetHash };\n}\n\n/**\n * Wait for a Relay request to complete.\n *\n * @param quote - Relay quote associated with the request.\n * @returns A promise that resolves when the Relay request is complete.\n */\nasync function waitForRelayCompletion(quote: RelayQuote): Promise<Hex> {\n const isSameChain =\n quote.details.currencyIn.currency.chainId ===\n quote.details.currencyOut.currency.chainId;\n\n const isSingleDepositStep =\n quote.steps.length === 1 && quote.steps[0].id === 'deposit';\n\n if (isSameChain && !isSingleDepositStep) {\n log('Skipping polling as same chain');\n return FALLBACK_HASH;\n }\n\n const { requestId } = quote.steps[0];\n const url = `${RELAY_STATUS_URL}?requestId=${requestId}`;\n\n while (true) {\n const response = await successfulFetch(url, { method: 'GET' });\n const status = (await response.json()) as RelayStatusResponse;\n\n log('Polled status', status.status, status);\n\n if (status.status === 'success') {\n const targetHash = status.txHashes?.slice(-1)[0] as Hex;\n return targetHash ?? FALLBACK_HASH;\n }\n\n if (['failure', 'refund', 'refunded'].includes(status.status)) {\n throw new Error(`Relay request failed with status: ${status.status}`);\n }\n\n await new Promise((resolve) => setTimeout(resolve, RELAY_POLLING_INTERVAL));\n }\n}\n\n/**\n * Normalize the parameters from a relay quote step to match TransactionParams.\n *\n * @param params - Parameters from a relay quote step.\n * @param messenger - Controller messenger.\n * @returns Normalized transaction parameters.\n */\nfunction normalizeParams(\n params: RelayQuote['steps'][0]['items'][0]['data'],\n messenger: TransactionPayControllerMessenger,\n): TransactionParams {\n const featureFlags = getFeatureFlags(messenger);\n\n return {\n data: params.data,\n from: params.from,\n gas: toHex(params.gas ?? featureFlags.relayFallbackGas.max),\n maxFeePerGas: toHex(params.maxFeePerGas),\n maxPriorityFeePerGas: toHex(params.maxPriorityFeePerGas),\n to: params.to,\n value: toHex(params.value ?? '0'),\n };\n}\n\n/**\n * Validate the source token balance is sufficient for the relay deposit.\n *\n * Reads the live balance from TokenBalancesController and compares it against\n * the quote's required source amount to prevent submitting transactions that\n * will revert on-chain due to insufficient balance.\n *\n * @param quote - Relay quote containing the required source amount.\n * @param messenger - Controller messenger.\n */\nasync function validateSourceBalance(\n quote: TransactionPayQuote<RelayQuote>,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n const { from, sourceChainId, sourceTokenAddress } = quote.request;\n\n const normalizedSourceTokenAddress = normalizeTokenAddress(\n sourceTokenAddress,\n sourceChainId,\n TokenAddressTarget.MetaMask,\n );\n\n let currentBalance: string;\n\n try {\n currentBalance = await getLiveTokenBalance(\n messenger,\n from,\n sourceChainId,\n normalizedSourceTokenAddress,\n );\n } catch (error) {\n throw new Error(\n `Cannot validate payment token balance - ${(error as Error).message}`,\n );\n }\n\n const requiredAmount = new BigNumber(quote.sourceAmount.raw);\n const balance = new BigNumber(currentBalance);\n\n log('Validating source balance', {\n from,\n sourceChainId,\n sourceTokenAddress,\n currentBalance,\n requiredAmount: requiredAmount.toString(10),\n });\n\n if (balance.isLessThan(requiredAmount)) {\n throw new Error(\n `Insufficient source token balance for relay deposit. ` +\n `Required: ${requiredAmount.toString(10)}, ` +\n `Available: ${balance.toString(10)}`,\n );\n }\n}\n\n/**\n * Submit transactions for a relay quote.\n *\n * @param quote - Relay quote.\n * @param transaction - Original transaction meta.\n * @param messenger - Controller messenger.\n * @returns Hash of the last submitted transaction.\n */\nasync function submitTransactions(\n quote: TransactionPayQuote<RelayQuote>,\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n): Promise<Hex> {\n const { steps } = quote.original;\n const params = steps.flatMap((step) => step.items).map((item) => item.data);\n const invalidKind = steps.find((step) => step.kind !== 'transaction')?.kind;\n\n if (invalidKind) {\n throw new Error(`Unsupported step kind: ${invalidKind}`);\n }\n\n await validateSourceBalance(quote, messenger);\n\n const normalizedParams = params.map((singleParams) =>\n normalizeParams(singleParams, messenger),\n );\n\n // For post-quote flows, prepend the original transaction so it gets\n // included in the batch alongside the relay deposit(s).\n // This always results in multiple params, so it takes the batch path.\n const { isPostQuote } = quote.request;\n\n const allParams =\n isPostQuote && transaction.txParams.to\n ? [\n {\n data: transaction.txParams.data as Hex | undefined,\n from: transaction.txParams.from,\n to: transaction.txParams.to,\n value: transaction.txParams.value as Hex | undefined,\n } as TransactionParams,\n ...normalizedParams,\n ]\n : normalizedParams;\n\n const transactionIds: string[] = [];\n const { from, sourceChainId, sourceTokenAddress } = quote.request;\n\n const networkClientId = messenger.call(\n 'NetworkController:findNetworkClientIdByChainId',\n sourceChainId,\n );\n\n log('Adding transactions', {\n normalizedParams: allParams,\n sourceChainId,\n from,\n networkClientId,\n });\n\n const { end } = collectTransactionIds(\n sourceChainId,\n from,\n messenger,\n (transactionId) => {\n transactionIds.push(transactionId);\n\n updateTransaction(\n {\n transactionId: transaction.id,\n messenger,\n note: 'Add required transaction ID from Relay submission',\n },\n (tx) => {\n tx.requiredTransactionIds ??= [];\n tx.requiredTransactionIds.push(transactionId);\n },\n );\n },\n );\n\n let result: { result: Promise<string> } | undefined;\n\n const gasFeeToken = quote.fees.isSourceGasFeeToken\n ? sourceTokenAddress\n : undefined;\n\n const isSameChain =\n quote.original.details.currencyIn.currency.chainId ===\n quote.original.details.currencyOut.currency.chainId;\n\n const authorizationList: AuthorizationList | undefined =\n isSameChain && quote.original.request.authorizationList?.length\n ? quote.original.request.authorizationList.map((a) => ({\n address: a.address,\n chainId: toHex(a.chainId),\n }))\n : undefined;\n\n const { gasLimits } = quote.original.metamask;\n\n if (allParams.length === 1) {\n const transactionParams = {\n ...allParams[0],\n authorizationList,\n gas: toHex(gasLimits[0]),\n };\n\n result = await messenger.call(\n 'TransactionController:addTransaction',\n transactionParams,\n {\n gasFeeToken,\n networkClientId,\n origin: ORIGIN_METAMASK,\n requireApproval: false,\n type: getRelayDepositType(transaction.type),\n },\n );\n } else {\n const gasLimit7702 =\n gasLimits.length === 1 && allParams.length > 1\n ? toHex(gasLimits[0])\n : undefined;\n\n const transactions = allParams.map((singleParams, index) => {\n const gasLimit = gasLimits[index];\n const gas =\n gasLimit === undefined || gasLimit7702 ? undefined : toHex(gasLimit);\n\n return {\n params: {\n data: singleParams.data as Hex,\n gas,\n maxFeePerGas: singleParams.maxFeePerGas as Hex,\n maxPriorityFeePerGas: singleParams.maxPriorityFeePerGas as Hex,\n to: singleParams.to as Hex,\n value: singleParams.value as Hex,\n },\n type: getTransactionType(\n isPostQuote,\n index,\n transaction.type,\n normalizedParams.length,\n ),\n };\n });\n\n await messenger.call('TransactionController:addTransactionBatch', {\n from,\n disable7702: !gasLimit7702,\n disableHook: Boolean(gasLimit7702),\n disableSequential: Boolean(gasLimit7702),\n gasFeeToken,\n gasLimit7702,\n networkClientId,\n origin: ORIGIN_METAMASK,\n overwriteUpgrade: true,\n requireApproval: false,\n transactions,\n });\n }\n\n end();\n\n log('Added transactions', transactionIds);\n\n if (result) {\n const txHash = await result.result;\n log('Submitted transaction', txHash);\n }\n\n await Promise.all(\n transactionIds.map((txId) => waitForTransactionConfirmed(txId, messenger)),\n );\n\n log('All transactions confirmed', transactionIds);\n\n const hash = getTransaction(transactionIds.slice(-1)[0], messenger)?.hash;\n\n return hash as Hex;\n}\n\n/**\n * Determine the transaction type for a given index in the batch.\n *\n * @param isPostQuote - Whether this is a post-quote flow.\n * @param index - Index of the transaction in the batch.\n * @param originalType - Type of the original transaction (used for post-quote index 0).\n * @param relayParamCount - Number of relay-only params (excludes prepended original tx).\n * @returns The transaction type.\n */\nfunction getTransactionType(\n isPostQuote: boolean | undefined,\n index: number,\n originalType: TransactionMeta['type'],\n relayParamCount: number,\n): TransactionMeta['type'] {\n // Post-quote index 0 is the original transaction\n if (isPostQuote && index === 0) {\n return originalType;\n }\n\n // Adjust index for post-quote flows where original tx is prepended\n const relayIndex = isPostQuote ? index - 1 : index;\n\n const depositType = getRelayDepositType(originalType);\n\n // Single relay step is always a deposit (no approval needed)\n if (relayParamCount === 1) {\n return depositType;\n }\n\n return relayIndex === 0 ? TransactionType.tokenMethodApprove : depositType;\n}\n\n/**\n * Get the relay deposit transaction type based on the parent transaction type.\n *\n * @param originalType - Type of the parent transaction.\n * @returns The mapped relay deposit type, or `relayDeposit` as a fallback.\n */\nfunction getRelayDepositType(\n originalType: TransactionMeta['type'],\n): TransactionType {\n return (\n (originalType && RELAY_DEPOSIT_TYPES[originalType]) ??\n TransactionType.relayDeposit\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"relay-submit.d.cts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-submit.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAS3C,OAAO,KAAK,EAAE,UAAU,EAAuB,oBAAgB;AAE/D,OAAO,KAAK,EACV,yBAAyB,EAG1B,wBAAoB;AAcrB;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,yBAAyB,CAAC,UAAU,CAAC,GAC7C,OAAO,CAAC;IAAE,eAAe,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC,CAgBpC"}
1
+ {"version":3,"file":"relay-submit.d.cts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-submit.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAS3C,OAAO,KAAK,EAAE,UAAU,EAAuB,oBAAgB;AAE/D,OAAO,KAAK,EACV,yBAAyB,EAG1B,wBAAoB;AAkBrB;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,yBAAyB,CAAC,UAAU,CAAC,GAC7C,OAAO,CAAC;IAAE,eAAe,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC,CAgBpC"}
@@ -1 +1 @@
1
- {"version":3,"file":"relay-submit.d.mts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-submit.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAS3C,OAAO,KAAK,EAAE,UAAU,EAAuB,oBAAgB;AAE/D,OAAO,KAAK,EACV,yBAAyB,EAG1B,wBAAoB;AAcrB;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,yBAAyB,CAAC,UAAU,CAAC,GAC7C,OAAO,CAAC;IAAE,eAAe,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC,CAgBpC"}
1
+ {"version":3,"file":"relay-submit.d.mts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-submit.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAS3C,OAAO,KAAK,EAAE,UAAU,EAAuB,oBAAgB;AAE/D,OAAO,KAAK,EACV,yBAAyB,EAG1B,wBAAoB;AAkBrB;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,yBAAyB,CAAC,UAAU,CAAC,GAC7C,OAAO,CAAC;IAAE,eAAe,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC,CAgBpC"}
@@ -5,7 +5,7 @@ import { BigNumber } from "bignumber.js";
5
5
  import { RELAY_DEPOSIT_TYPES, RELAY_POLLING_INTERVAL, RELAY_STATUS_URL } from "./constants.mjs";
6
6
  import { projectLogger } from "../../logger.mjs";
7
7
  import { getFeatureFlags } from "../../utils/feature-flags.mjs";
8
- import { getLiveTokenBalance } from "../../utils/token.mjs";
8
+ import { getLiveTokenBalance, normalizeTokenAddress, TokenAddressTarget } from "../../utils/token.mjs";
9
9
  import { collectTransactionIds, getTransaction, updateTransaction, waitForTransactionConfirmed } from "../../utils/transaction.mjs";
10
10
  const FALLBACK_HASH = '0x0';
11
11
  const log = createModuleLogger(projectLogger, 'relay-strategy');
@@ -114,9 +114,10 @@ function normalizeParams(params, messenger) {
114
114
  */
115
115
  async function validateSourceBalance(quote, messenger) {
116
116
  const { from, sourceChainId, sourceTokenAddress } = quote.request;
117
+ const normalizedSourceTokenAddress = normalizeTokenAddress(sourceTokenAddress, sourceChainId, TokenAddressTarget.MetaMask);
117
118
  let currentBalance;
118
119
  try {
119
- currentBalance = await getLiveTokenBalance(messenger, from, sourceChainId, sourceTokenAddress);
120
+ currentBalance = await getLiveTokenBalance(messenger, from, sourceChainId, normalizedSourceTokenAddress);
120
121
  }
121
122
  catch (error) {
122
123
  throw new Error(`Cannot validate payment token balance - ${error.message}`);
@@ -1 +1 @@
1
- {"version":3,"file":"relay-submit.mjs","sourceRoot":"","sources":["../../../src/strategy/relay/relay-submit.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ORIGIN_METAMASK,\n successfulFetch,\n toHex,\n} from '@metamask/controller-utils';\nimport { TransactionType } from '@metamask/transaction-controller';\nimport type { TransactionParams } from '@metamask/transaction-controller';\nimport type {\n AuthorizationList,\n TransactionMeta,\n} from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport {\n RELAY_DEPOSIT_TYPES,\n RELAY_POLLING_INTERVAL,\n RELAY_STATUS_URL,\n} from './constants';\nimport type { RelayQuote, RelayStatusResponse } from './types';\nimport { projectLogger } from '../../logger';\nimport type {\n PayStrategyExecuteRequest,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types';\nimport { getFeatureFlags } from '../../utils/feature-flags';\nimport { getLiveTokenBalance } from '../../utils/token';\nimport {\n collectTransactionIds,\n getTransaction,\n updateTransaction,\n waitForTransactionConfirmed,\n} from '../../utils/transaction';\n\nconst FALLBACK_HASH = '0x0' as Hex;\n\nconst log = createModuleLogger(projectLogger, 'relay-strategy');\n\n/**\n * Submits Relay quotes.\n *\n * @param request - Request object.\n * @returns An object containing the transaction hash if available.\n */\nexport async function submitRelayQuotes(\n request: PayStrategyExecuteRequest<RelayQuote>,\n): Promise<{ transactionHash?: Hex }> {\n log('Executing quotes', request);\n\n const { quotes, messenger, transaction } = request;\n\n let transactionHash: Hex | undefined;\n\n for (const quote of quotes) {\n ({ transactionHash } = await executeSingleQuote(\n quote,\n messenger,\n transaction,\n ));\n }\n\n return { transactionHash };\n}\n\n/**\n * Executes a single Relay quote.\n *\n * @param quote - Relay quote to execute.\n * @param messenger - Controller messenger.\n * @param transaction - Original transaction meta.\n * @returns An object containing the transaction hash if available.\n */\nasync function executeSingleQuote(\n quote: TransactionPayQuote<RelayQuote>,\n messenger: TransactionPayControllerMessenger,\n transaction: TransactionMeta,\n): Promise<{ transactionHash?: Hex }> {\n log('Executing single quote', quote);\n\n updateTransaction(\n {\n transactionId: transaction.id,\n messenger,\n note: 'Remove nonce from skipped transaction',\n },\n (tx) => {\n tx.txParams.nonce = undefined;\n },\n );\n\n await submitTransactions(quote, transaction, messenger);\n\n const targetHash = await waitForRelayCompletion(quote.original);\n\n log('Relay request completed', targetHash);\n\n updateTransaction(\n {\n transactionId: transaction.id,\n messenger,\n note: 'Intent complete after Relay completion',\n },\n (tx) => {\n tx.isIntentComplete = true;\n },\n );\n\n return { transactionHash: targetHash };\n}\n\n/**\n * Wait for a Relay request to complete.\n *\n * @param quote - Relay quote associated with the request.\n * @returns A promise that resolves when the Relay request is complete.\n */\nasync function waitForRelayCompletion(quote: RelayQuote): Promise<Hex> {\n const isSameChain =\n quote.details.currencyIn.currency.chainId ===\n quote.details.currencyOut.currency.chainId;\n\n const isSingleDepositStep =\n quote.steps.length === 1 && quote.steps[0].id === 'deposit';\n\n if (isSameChain && !isSingleDepositStep) {\n log('Skipping polling as same chain');\n return FALLBACK_HASH;\n }\n\n const { requestId } = quote.steps[0];\n const url = `${RELAY_STATUS_URL}?requestId=${requestId}`;\n\n while (true) {\n const response = await successfulFetch(url, { method: 'GET' });\n const status = (await response.json()) as RelayStatusResponse;\n\n log('Polled status', status.status, status);\n\n if (status.status === 'success') {\n const targetHash = status.txHashes?.slice(-1)[0] as Hex;\n return targetHash ?? FALLBACK_HASH;\n }\n\n if (['failure', 'refund', 'refunded'].includes(status.status)) {\n throw new Error(`Relay request failed with status: ${status.status}`);\n }\n\n await new Promise((resolve) => setTimeout(resolve, RELAY_POLLING_INTERVAL));\n }\n}\n\n/**\n * Normalize the parameters from a relay quote step to match TransactionParams.\n *\n * @param params - Parameters from a relay quote step.\n * @param messenger - Controller messenger.\n * @returns Normalized transaction parameters.\n */\nfunction normalizeParams(\n params: RelayQuote['steps'][0]['items'][0]['data'],\n messenger: TransactionPayControllerMessenger,\n): TransactionParams {\n const featureFlags = getFeatureFlags(messenger);\n\n return {\n data: params.data,\n from: params.from,\n gas: toHex(params.gas ?? featureFlags.relayFallbackGas.max),\n maxFeePerGas: toHex(params.maxFeePerGas),\n maxPriorityFeePerGas: toHex(params.maxPriorityFeePerGas),\n to: params.to,\n value: toHex(params.value ?? '0'),\n };\n}\n\n/**\n * Validate the source token balance is sufficient for the relay deposit.\n *\n * Reads the live balance from TokenBalancesController and compares it against\n * the quote's required source amount to prevent submitting transactions that\n * will revert on-chain due to insufficient balance.\n *\n * @param quote - Relay quote containing the required source amount.\n * @param messenger - Controller messenger.\n */\nasync function validateSourceBalance(\n quote: TransactionPayQuote<RelayQuote>,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n const { from, sourceChainId, sourceTokenAddress } = quote.request;\n\n let currentBalance: string;\n\n try {\n currentBalance = await getLiveTokenBalance(\n messenger,\n from,\n sourceChainId,\n sourceTokenAddress,\n );\n } catch (error) {\n throw new Error(\n `Cannot validate payment token balance - ${(error as Error).message}`,\n );\n }\n\n const requiredAmount = new BigNumber(quote.sourceAmount.raw);\n const balance = new BigNumber(currentBalance);\n\n log('Validating source balance', {\n from,\n sourceChainId,\n sourceTokenAddress,\n currentBalance,\n requiredAmount: requiredAmount.toString(10),\n });\n\n if (balance.isLessThan(requiredAmount)) {\n throw new Error(\n `Insufficient source token balance for relay deposit. ` +\n `Required: ${requiredAmount.toString(10)}, ` +\n `Available: ${balance.toString(10)}`,\n );\n }\n}\n\n/**\n * Submit transactions for a relay quote.\n *\n * @param quote - Relay quote.\n * @param transaction - Original transaction meta.\n * @param messenger - Controller messenger.\n * @returns Hash of the last submitted transaction.\n */\nasync function submitTransactions(\n quote: TransactionPayQuote<RelayQuote>,\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n): Promise<Hex> {\n const { steps } = quote.original;\n const params = steps.flatMap((step) => step.items).map((item) => item.data);\n const invalidKind = steps.find((step) => step.kind !== 'transaction')?.kind;\n\n if (invalidKind) {\n throw new Error(`Unsupported step kind: ${invalidKind}`);\n }\n\n await validateSourceBalance(quote, messenger);\n\n const normalizedParams = params.map((singleParams) =>\n normalizeParams(singleParams, messenger),\n );\n\n // For post-quote flows, prepend the original transaction so it gets\n // included in the batch alongside the relay deposit(s).\n // This always results in multiple params, so it takes the batch path.\n const { isPostQuote } = quote.request;\n\n const allParams =\n isPostQuote && transaction.txParams.to\n ? [\n {\n data: transaction.txParams.data as Hex | undefined,\n from: transaction.txParams.from,\n to: transaction.txParams.to,\n value: transaction.txParams.value as Hex | undefined,\n } as TransactionParams,\n ...normalizedParams,\n ]\n : normalizedParams;\n\n const transactionIds: string[] = [];\n const { from, sourceChainId, sourceTokenAddress } = quote.request;\n\n const networkClientId = messenger.call(\n 'NetworkController:findNetworkClientIdByChainId',\n sourceChainId,\n );\n\n log('Adding transactions', {\n normalizedParams: allParams,\n sourceChainId,\n from,\n networkClientId,\n });\n\n const { end } = collectTransactionIds(\n sourceChainId,\n from,\n messenger,\n (transactionId) => {\n transactionIds.push(transactionId);\n\n updateTransaction(\n {\n transactionId: transaction.id,\n messenger,\n note: 'Add required transaction ID from Relay submission',\n },\n (tx) => {\n tx.requiredTransactionIds ??= [];\n tx.requiredTransactionIds.push(transactionId);\n },\n );\n },\n );\n\n let result: { result: Promise<string> } | undefined;\n\n const gasFeeToken = quote.fees.isSourceGasFeeToken\n ? sourceTokenAddress\n : undefined;\n\n const isSameChain =\n quote.original.details.currencyIn.currency.chainId ===\n quote.original.details.currencyOut.currency.chainId;\n\n const authorizationList: AuthorizationList | undefined =\n isSameChain && quote.original.request.authorizationList?.length\n ? quote.original.request.authorizationList.map((a) => ({\n address: a.address,\n chainId: toHex(a.chainId),\n }))\n : undefined;\n\n const { gasLimits } = quote.original.metamask;\n\n if (allParams.length === 1) {\n const transactionParams = {\n ...allParams[0],\n authorizationList,\n gas: toHex(gasLimits[0]),\n };\n\n result = await messenger.call(\n 'TransactionController:addTransaction',\n transactionParams,\n {\n gasFeeToken,\n networkClientId,\n origin: ORIGIN_METAMASK,\n requireApproval: false,\n type: getRelayDepositType(transaction.type),\n },\n );\n } else {\n const gasLimit7702 =\n gasLimits.length === 1 && allParams.length > 1\n ? toHex(gasLimits[0])\n : undefined;\n\n const transactions = allParams.map((singleParams, index) => {\n const gasLimit = gasLimits[index];\n const gas =\n gasLimit === undefined || gasLimit7702 ? undefined : toHex(gasLimit);\n\n return {\n params: {\n data: singleParams.data as Hex,\n gas,\n maxFeePerGas: singleParams.maxFeePerGas as Hex,\n maxPriorityFeePerGas: singleParams.maxPriorityFeePerGas as Hex,\n to: singleParams.to as Hex,\n value: singleParams.value as Hex,\n },\n type: getTransactionType(\n isPostQuote,\n index,\n transaction.type,\n normalizedParams.length,\n ),\n };\n });\n\n await messenger.call('TransactionController:addTransactionBatch', {\n from,\n disable7702: !gasLimit7702,\n disableHook: Boolean(gasLimit7702),\n disableSequential: Boolean(gasLimit7702),\n gasFeeToken,\n gasLimit7702,\n networkClientId,\n origin: ORIGIN_METAMASK,\n overwriteUpgrade: true,\n requireApproval: false,\n transactions,\n });\n }\n\n end();\n\n log('Added transactions', transactionIds);\n\n if (result) {\n const txHash = await result.result;\n log('Submitted transaction', txHash);\n }\n\n await Promise.all(\n transactionIds.map((txId) => waitForTransactionConfirmed(txId, messenger)),\n );\n\n log('All transactions confirmed', transactionIds);\n\n const hash = getTransaction(transactionIds.slice(-1)[0], messenger)?.hash;\n\n return hash as Hex;\n}\n\n/**\n * Determine the transaction type for a given index in the batch.\n *\n * @param isPostQuote - Whether this is a post-quote flow.\n * @param index - Index of the transaction in the batch.\n * @param originalType - Type of the original transaction (used for post-quote index 0).\n * @param relayParamCount - Number of relay-only params (excludes prepended original tx).\n * @returns The transaction type.\n */\nfunction getTransactionType(\n isPostQuote: boolean | undefined,\n index: number,\n originalType: TransactionMeta['type'],\n relayParamCount: number,\n): TransactionMeta['type'] {\n // Post-quote index 0 is the original transaction\n if (isPostQuote && index === 0) {\n return originalType;\n }\n\n // Adjust index for post-quote flows where original tx is prepended\n const relayIndex = isPostQuote ? index - 1 : index;\n\n const depositType = getRelayDepositType(originalType);\n\n // Single relay step is always a deposit (no approval needed)\n if (relayParamCount === 1) {\n return depositType;\n }\n\n return relayIndex === 0 ? TransactionType.tokenMethodApprove : depositType;\n}\n\n/**\n * Get the relay deposit transaction type based on the parent transaction type.\n *\n * @param originalType - Type of the parent transaction.\n * @returns The mapped relay deposit type, or `relayDeposit` as a fallback.\n */\nfunction getRelayDepositType(\n originalType: TransactionMeta['type'],\n): TransactionType {\n return (\n (originalType && RELAY_DEPOSIT_TYPES[originalType]) ??\n TransactionType.relayDeposit\n );\n}\n"]}
1
+ {"version":3,"file":"relay-submit.mjs","sourceRoot":"","sources":["../../../src/strategy/relay/relay-submit.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ORIGIN_METAMASK,\n successfulFetch,\n toHex,\n} from '@metamask/controller-utils';\nimport { TransactionType } from '@metamask/transaction-controller';\nimport type { TransactionParams } from '@metamask/transaction-controller';\nimport type {\n AuthorizationList,\n TransactionMeta,\n} from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport {\n RELAY_DEPOSIT_TYPES,\n RELAY_POLLING_INTERVAL,\n RELAY_STATUS_URL,\n} from './constants';\nimport type { RelayQuote, RelayStatusResponse } from './types';\nimport { projectLogger } from '../../logger';\nimport type {\n PayStrategyExecuteRequest,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types';\nimport { getFeatureFlags } from '../../utils/feature-flags';\nimport {\n getLiveTokenBalance,\n normalizeTokenAddress,\n TokenAddressTarget,\n} from '../../utils/token';\nimport {\n collectTransactionIds,\n getTransaction,\n updateTransaction,\n waitForTransactionConfirmed,\n} from '../../utils/transaction';\n\nconst FALLBACK_HASH = '0x0' as Hex;\n\nconst log = createModuleLogger(projectLogger, 'relay-strategy');\n\n/**\n * Submits Relay quotes.\n *\n * @param request - Request object.\n * @returns An object containing the transaction hash if available.\n */\nexport async function submitRelayQuotes(\n request: PayStrategyExecuteRequest<RelayQuote>,\n): Promise<{ transactionHash?: Hex }> {\n log('Executing quotes', request);\n\n const { quotes, messenger, transaction } = request;\n\n let transactionHash: Hex | undefined;\n\n for (const quote of quotes) {\n ({ transactionHash } = await executeSingleQuote(\n quote,\n messenger,\n transaction,\n ));\n }\n\n return { transactionHash };\n}\n\n/**\n * Executes a single Relay quote.\n *\n * @param quote - Relay quote to execute.\n * @param messenger - Controller messenger.\n * @param transaction - Original transaction meta.\n * @returns An object containing the transaction hash if available.\n */\nasync function executeSingleQuote(\n quote: TransactionPayQuote<RelayQuote>,\n messenger: TransactionPayControllerMessenger,\n transaction: TransactionMeta,\n): Promise<{ transactionHash?: Hex }> {\n log('Executing single quote', quote);\n\n updateTransaction(\n {\n transactionId: transaction.id,\n messenger,\n note: 'Remove nonce from skipped transaction',\n },\n (tx) => {\n tx.txParams.nonce = undefined;\n },\n );\n\n await submitTransactions(quote, transaction, messenger);\n\n const targetHash = await waitForRelayCompletion(quote.original);\n\n log('Relay request completed', targetHash);\n\n updateTransaction(\n {\n transactionId: transaction.id,\n messenger,\n note: 'Intent complete after Relay completion',\n },\n (tx) => {\n tx.isIntentComplete = true;\n },\n );\n\n return { transactionHash: targetHash };\n}\n\n/**\n * Wait for a Relay request to complete.\n *\n * @param quote - Relay quote associated with the request.\n * @returns A promise that resolves when the Relay request is complete.\n */\nasync function waitForRelayCompletion(quote: RelayQuote): Promise<Hex> {\n const isSameChain =\n quote.details.currencyIn.currency.chainId ===\n quote.details.currencyOut.currency.chainId;\n\n const isSingleDepositStep =\n quote.steps.length === 1 && quote.steps[0].id === 'deposit';\n\n if (isSameChain && !isSingleDepositStep) {\n log('Skipping polling as same chain');\n return FALLBACK_HASH;\n }\n\n const { requestId } = quote.steps[0];\n const url = `${RELAY_STATUS_URL}?requestId=${requestId}`;\n\n while (true) {\n const response = await successfulFetch(url, { method: 'GET' });\n const status = (await response.json()) as RelayStatusResponse;\n\n log('Polled status', status.status, status);\n\n if (status.status === 'success') {\n const targetHash = status.txHashes?.slice(-1)[0] as Hex;\n return targetHash ?? FALLBACK_HASH;\n }\n\n if (['failure', 'refund', 'refunded'].includes(status.status)) {\n throw new Error(`Relay request failed with status: ${status.status}`);\n }\n\n await new Promise((resolve) => setTimeout(resolve, RELAY_POLLING_INTERVAL));\n }\n}\n\n/**\n * Normalize the parameters from a relay quote step to match TransactionParams.\n *\n * @param params - Parameters from a relay quote step.\n * @param messenger - Controller messenger.\n * @returns Normalized transaction parameters.\n */\nfunction normalizeParams(\n params: RelayQuote['steps'][0]['items'][0]['data'],\n messenger: TransactionPayControllerMessenger,\n): TransactionParams {\n const featureFlags = getFeatureFlags(messenger);\n\n return {\n data: params.data,\n from: params.from,\n gas: toHex(params.gas ?? featureFlags.relayFallbackGas.max),\n maxFeePerGas: toHex(params.maxFeePerGas),\n maxPriorityFeePerGas: toHex(params.maxPriorityFeePerGas),\n to: params.to,\n value: toHex(params.value ?? '0'),\n };\n}\n\n/**\n * Validate the source token balance is sufficient for the relay deposit.\n *\n * Reads the live balance from TokenBalancesController and compares it against\n * the quote's required source amount to prevent submitting transactions that\n * will revert on-chain due to insufficient balance.\n *\n * @param quote - Relay quote containing the required source amount.\n * @param messenger - Controller messenger.\n */\nasync function validateSourceBalance(\n quote: TransactionPayQuote<RelayQuote>,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n const { from, sourceChainId, sourceTokenAddress } = quote.request;\n\n const normalizedSourceTokenAddress = normalizeTokenAddress(\n sourceTokenAddress,\n sourceChainId,\n TokenAddressTarget.MetaMask,\n );\n\n let currentBalance: string;\n\n try {\n currentBalance = await getLiveTokenBalance(\n messenger,\n from,\n sourceChainId,\n normalizedSourceTokenAddress,\n );\n } catch (error) {\n throw new Error(\n `Cannot validate payment token balance - ${(error as Error).message}`,\n );\n }\n\n const requiredAmount = new BigNumber(quote.sourceAmount.raw);\n const balance = new BigNumber(currentBalance);\n\n log('Validating source balance', {\n from,\n sourceChainId,\n sourceTokenAddress,\n currentBalance,\n requiredAmount: requiredAmount.toString(10),\n });\n\n if (balance.isLessThan(requiredAmount)) {\n throw new Error(\n `Insufficient source token balance for relay deposit. ` +\n `Required: ${requiredAmount.toString(10)}, ` +\n `Available: ${balance.toString(10)}`,\n );\n }\n}\n\n/**\n * Submit transactions for a relay quote.\n *\n * @param quote - Relay quote.\n * @param transaction - Original transaction meta.\n * @param messenger - Controller messenger.\n * @returns Hash of the last submitted transaction.\n */\nasync function submitTransactions(\n quote: TransactionPayQuote<RelayQuote>,\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n): Promise<Hex> {\n const { steps } = quote.original;\n const params = steps.flatMap((step) => step.items).map((item) => item.data);\n const invalidKind = steps.find((step) => step.kind !== 'transaction')?.kind;\n\n if (invalidKind) {\n throw new Error(`Unsupported step kind: ${invalidKind}`);\n }\n\n await validateSourceBalance(quote, messenger);\n\n const normalizedParams = params.map((singleParams) =>\n normalizeParams(singleParams, messenger),\n );\n\n // For post-quote flows, prepend the original transaction so it gets\n // included in the batch alongside the relay deposit(s).\n // This always results in multiple params, so it takes the batch path.\n const { isPostQuote } = quote.request;\n\n const allParams =\n isPostQuote && transaction.txParams.to\n ? [\n {\n data: transaction.txParams.data as Hex | undefined,\n from: transaction.txParams.from,\n to: transaction.txParams.to,\n value: transaction.txParams.value as Hex | undefined,\n } as TransactionParams,\n ...normalizedParams,\n ]\n : normalizedParams;\n\n const transactionIds: string[] = [];\n const { from, sourceChainId, sourceTokenAddress } = quote.request;\n\n const networkClientId = messenger.call(\n 'NetworkController:findNetworkClientIdByChainId',\n sourceChainId,\n );\n\n log('Adding transactions', {\n normalizedParams: allParams,\n sourceChainId,\n from,\n networkClientId,\n });\n\n const { end } = collectTransactionIds(\n sourceChainId,\n from,\n messenger,\n (transactionId) => {\n transactionIds.push(transactionId);\n\n updateTransaction(\n {\n transactionId: transaction.id,\n messenger,\n note: 'Add required transaction ID from Relay submission',\n },\n (tx) => {\n tx.requiredTransactionIds ??= [];\n tx.requiredTransactionIds.push(transactionId);\n },\n );\n },\n );\n\n let result: { result: Promise<string> } | undefined;\n\n const gasFeeToken = quote.fees.isSourceGasFeeToken\n ? sourceTokenAddress\n : undefined;\n\n const isSameChain =\n quote.original.details.currencyIn.currency.chainId ===\n quote.original.details.currencyOut.currency.chainId;\n\n const authorizationList: AuthorizationList | undefined =\n isSameChain && quote.original.request.authorizationList?.length\n ? quote.original.request.authorizationList.map((a) => ({\n address: a.address,\n chainId: toHex(a.chainId),\n }))\n : undefined;\n\n const { gasLimits } = quote.original.metamask;\n\n if (allParams.length === 1) {\n const transactionParams = {\n ...allParams[0],\n authorizationList,\n gas: toHex(gasLimits[0]),\n };\n\n result = await messenger.call(\n 'TransactionController:addTransaction',\n transactionParams,\n {\n gasFeeToken,\n networkClientId,\n origin: ORIGIN_METAMASK,\n requireApproval: false,\n type: getRelayDepositType(transaction.type),\n },\n );\n } else {\n const gasLimit7702 =\n gasLimits.length === 1 && allParams.length > 1\n ? toHex(gasLimits[0])\n : undefined;\n\n const transactions = allParams.map((singleParams, index) => {\n const gasLimit = gasLimits[index];\n const gas =\n gasLimit === undefined || gasLimit7702 ? undefined : toHex(gasLimit);\n\n return {\n params: {\n data: singleParams.data as Hex,\n gas,\n maxFeePerGas: singleParams.maxFeePerGas as Hex,\n maxPriorityFeePerGas: singleParams.maxPriorityFeePerGas as Hex,\n to: singleParams.to as Hex,\n value: singleParams.value as Hex,\n },\n type: getTransactionType(\n isPostQuote,\n index,\n transaction.type,\n normalizedParams.length,\n ),\n };\n });\n\n await messenger.call('TransactionController:addTransactionBatch', {\n from,\n disable7702: !gasLimit7702,\n disableHook: Boolean(gasLimit7702),\n disableSequential: Boolean(gasLimit7702),\n gasFeeToken,\n gasLimit7702,\n networkClientId,\n origin: ORIGIN_METAMASK,\n overwriteUpgrade: true,\n requireApproval: false,\n transactions,\n });\n }\n\n end();\n\n log('Added transactions', transactionIds);\n\n if (result) {\n const txHash = await result.result;\n log('Submitted transaction', txHash);\n }\n\n await Promise.all(\n transactionIds.map((txId) => waitForTransactionConfirmed(txId, messenger)),\n );\n\n log('All transactions confirmed', transactionIds);\n\n const hash = getTransaction(transactionIds.slice(-1)[0], messenger)?.hash;\n\n return hash as Hex;\n}\n\n/**\n * Determine the transaction type for a given index in the batch.\n *\n * @param isPostQuote - Whether this is a post-quote flow.\n * @param index - Index of the transaction in the batch.\n * @param originalType - Type of the original transaction (used for post-quote index 0).\n * @param relayParamCount - Number of relay-only params (excludes prepended original tx).\n * @returns The transaction type.\n */\nfunction getTransactionType(\n isPostQuote: boolean | undefined,\n index: number,\n originalType: TransactionMeta['type'],\n relayParamCount: number,\n): TransactionMeta['type'] {\n // Post-quote index 0 is the original transaction\n if (isPostQuote && index === 0) {\n return originalType;\n }\n\n // Adjust index for post-quote flows where original tx is prepended\n const relayIndex = isPostQuote ? index - 1 : index;\n\n const depositType = getRelayDepositType(originalType);\n\n // Single relay step is always a deposit (no approval needed)\n if (relayParamCount === 1) {\n return depositType;\n }\n\n return relayIndex === 0 ? TransactionType.tokenMethodApprove : depositType;\n}\n\n/**\n * Get the relay deposit transaction type based on the parent transaction type.\n *\n * @param originalType - Type of the parent transaction.\n * @returns The mapped relay deposit type, or `relayDeposit` as a fallback.\n */\nfunction getRelayDepositType(\n originalType: TransactionMeta['type'],\n): TransactionType {\n return (\n (originalType && RELAY_DEPOSIT_TYPES[originalType]) ??\n TransactionType.relayDeposit\n );\n}\n"]}
@@ -203,8 +203,16 @@ export declare function getMessengerMock({ skipRegister, }?: {
203
203
  buyAmount?: string | undefined;
204
204
  from?: string | undefined;
205
205
  };
206
+ typedData: {
207
+ types: Record<string, {
208
+ name: string;
209
+ type: string;
210
+ }[]>;
211
+ primaryType: string;
212
+ domain: Record<string, any>;
213
+ message: Record<string, any>;
214
+ };
206
215
  settlementContract?: string | undefined;
207
- relayer?: string | undefined;
208
216
  } | undefined;
209
217
  gasSponsored?: boolean | undefined;
210
218
  };
@@ -1 +1 @@
1
- {"version":3,"file":"messenger-mock.d.cts","sourceRoot":"","sources":["../../src/tests/messenger-mock.ts"],"names":[],"mappings":";AAwBA,OAAO,KAAK,EAAE,iCAAiC,EAAE,qBAAW;AAY5D;;;;;;GAMG;AAEH,wBAAgB,gBAAgB,CAAC,EAC/B,YAAY,GACb,GAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmOjC"}
1
+ {"version":3,"file":"messenger-mock.d.cts","sourceRoot":"","sources":["../../src/tests/messenger-mock.ts"],"names":[],"mappings":";AAwBA,OAAO,KAAK,EAAE,iCAAiC,EAAE,qBAAW;AAY5D;;;;;;GAMG;AAEH,wBAAgB,gBAAgB,CAAC,EAC/B,YAAY,GACb,GAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmOjC"}
@@ -203,8 +203,16 @@ export declare function getMessengerMock({ skipRegister, }?: {
203
203
  buyAmount?: string | undefined;
204
204
  from?: string | undefined;
205
205
  };
206
+ typedData: {
207
+ types: Record<string, {
208
+ name: string;
209
+ type: string;
210
+ }[]>;
211
+ primaryType: string;
212
+ domain: Record<string, any>;
213
+ message: Record<string, any>;
214
+ };
206
215
  settlementContract?: string | undefined;
207
- relayer?: string | undefined;
208
216
  } | undefined;
209
217
  gasSponsored?: boolean | undefined;
210
218
  };
@@ -1 +1 @@
1
- {"version":3,"file":"messenger-mock.d.mts","sourceRoot":"","sources":["../../src/tests/messenger-mock.ts"],"names":[],"mappings":";AAwBA,OAAO,KAAK,EAAE,iCAAiC,EAAE,qBAAW;AAY5D;;;;;;GAMG;AAEH,wBAAgB,gBAAgB,CAAC,EAC/B,YAAY,GACb,GAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmOjC"}
1
+ {"version":3,"file":"messenger-mock.d.mts","sourceRoot":"","sources":["../../src/tests/messenger-mock.ts"],"names":[],"mappings":";AAwBA,OAAO,KAAK,EAAE,iCAAiC,EAAE,qBAAW;AAY5D;;;;;;GAMG;AAEH,wBAAgB,gBAAgB,CAAC,EAC/B,YAAY,GACb,GAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmOjC"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getLiveTokenBalance = exports.getNativeToken = exports.computeTokenAmounts = exports.getTokenFiatRate = exports.getTokenInfo = exports.getAllTokenBalances = exports.getTokenBalance = exports.isSameToken = void 0;
3
+ exports.normalizeTokenAddress = exports.TokenAddressTarget = exports.getLiveTokenBalance = exports.getNativeToken = exports.computeTokenAmounts = exports.getTokenFiatRate = exports.getTokenInfo = exports.getAllTokenBalances = exports.getTokenBalance = exports.isSameToken = void 0;
4
4
  const contracts_1 = require("@ethersproject/contracts");
5
5
  const providers_1 = require("@ethersproject/providers");
6
6
  const controller_utils_1 = require("@metamask/controller-utils");
@@ -219,4 +219,39 @@ function getTicker(chainId, messenger) {
219
219
  return undefined;
220
220
  }
221
221
  }
222
+ var TokenAddressTarget;
223
+ (function (TokenAddressTarget) {
224
+ TokenAddressTarget["Relay"] = "relay";
225
+ TokenAddressTarget["MetaMask"] = "metamask";
226
+ })(TokenAddressTarget || (exports.TokenAddressTarget = TokenAddressTarget = {}));
227
+ /**
228
+ * Normalize token address formats between MetaMask and Relay for Polygon native
229
+ * token handling.
230
+ *
231
+ * MetaMask uses Polygon's native token contract-like address (`0x...1010`),
232
+ * while Relay expects the zero address for native tokens.
233
+ *
234
+ * @param tokenAddress - Token address to normalize.
235
+ * @param chainId - Chain ID for the token.
236
+ * @param target - Optional target system format.
237
+ * @returns Normalized token address for the target system, or the original
238
+ * address if no target is provided.
239
+ */
240
+ function normalizeTokenAddress(tokenAddress, chainId, target) {
241
+ if (chainId !== constants_1.CHAIN_ID_POLYGON) {
242
+ return tokenAddress;
243
+ }
244
+ const nativeTokenAddress = getNativeToken(chainId).toLowerCase();
245
+ const normalizedTokenAddress = tokenAddress.toLowerCase();
246
+ if (target === TokenAddressTarget.Relay &&
247
+ normalizedTokenAddress === nativeTokenAddress) {
248
+ return constants_1.NATIVE_TOKEN_ADDRESS;
249
+ }
250
+ if (target === TokenAddressTarget.MetaMask &&
251
+ normalizedTokenAddress === constants_1.NATIVE_TOKEN_ADDRESS.toLowerCase()) {
252
+ return nativeTokenAddress;
253
+ }
254
+ return tokenAddress;
255
+ }
256
+ exports.normalizeTokenAddress = normalizeTokenAddress;
222
257
  //# sourceMappingURL=token.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"token.cjs","sourceRoot":"","sources":["../../src/utils/token.ts"],"names":[],"mappings":"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","sourcesContent":["import { Contract } from '@ethersproject/contracts';\nimport { Web3Provider } from '@ethersproject/providers';\nimport { toChecksumHexAddress } from '@metamask/controller-utils';\nimport { abiERC20 } from '@metamask/metamask-eth-abis';\nimport type { Hex } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\nimport { uniq } from 'lodash';\n\nimport { NATIVE_TOKEN_ADDRESS, STABLECOINS } from '../constants';\nimport type { FiatRates, TransactionPayControllerMessenger } from '../types';\n\n/**\n * Check if two tokens are the same (same address and chain).\n *\n * @param token1 - First token identifier.\n * @param token1.address - Token address.\n * @param token1.chainId - Token chain ID.\n * @param token2 - Second token identifier.\n * @param token2.address - Token address.\n * @param token2.chainId - Token chain ID.\n * @returns True if tokens are the same, false otherwise.\n */\nexport function isSameToken(\n token1: { address: Hex; chainId: Hex },\n token2: { address: Hex; chainId: Hex },\n): boolean {\n return (\n token1.address.toLowerCase() === token2.address.toLowerCase() &&\n token1.chainId === token2.chainId\n );\n}\n\n/**\n * Get the token balance for a specific account and token.\n *\n * @param messenger - Controller messenger.\n * @param account - Address of the account.\n * @param chainId - Id of the chain.\n * @param tokenAddress - Address of the token contract.\n * @returns Raw token balance as a decimal string.\n */\nexport function getTokenBalance(\n messenger: TransactionPayControllerMessenger,\n account: Hex,\n chainId: Hex,\n tokenAddress: Hex,\n): string {\n const tokenBalanceControllerState = messenger.call(\n 'TokenBalancesController:getState',\n );\n\n const normalizedAccount = account.toLowerCase() as Hex;\n const normalizedTokenAddress = toChecksumHexAddress(tokenAddress) as Hex;\n const isNative = normalizedTokenAddress === getNativeToken(chainId);\n\n const balanceHex =\n tokenBalanceControllerState.tokenBalances?.[normalizedAccount]?.[chainId]?.[\n normalizedTokenAddress\n ];\n\n if (!isNative && balanceHex === undefined) {\n return '0';\n }\n\n if (!isNative && balanceHex) {\n return new BigNumber(balanceHex, 16).toString(10);\n }\n\n const accountTrackerControllerState = messenger.call(\n 'AccountTrackerController:getState',\n );\n\n const chainAccounts =\n accountTrackerControllerState.accountsByChainId?.[chainId];\n\n const checksumAccount = toChecksumHexAddress(normalizedAccount) as Hex;\n const nativeBalanceHex = chainAccounts?.[checksumAccount]?.balance as Hex;\n\n return new BigNumber(nativeBalanceHex ?? '0x0', 16).toString(10);\n}\n\n/**\n * Get the token balance for a specific account and token.\n *\n * @param messenger - Controller messenger.\n * @param account - Address of the account.\n * @returns The token balance as a BigNumber.\n */\nexport function getAllTokenBalances(\n messenger: TransactionPayControllerMessenger,\n account: Hex,\n): {\n balance: string;\n chainId: Hex;\n tokenAddress: Hex;\n}[] {\n const tokenBalanceControllerState = messenger.call(\n 'TokenBalancesController:getState',\n );\n\n const accountTrackerControllerState = messenger.call(\n 'AccountTrackerController:getState',\n );\n\n const nativeChainIds = Object.keys(\n accountTrackerControllerState.accountsByChainId,\n ) as Hex[];\n\n const normalizedAccount = account.toLowerCase() as Hex;\n\n const balancesByTokenByChain =\n tokenBalanceControllerState.tokenBalances?.[normalizedAccount];\n\n const tokenChainIds = Object.keys(balancesByTokenByChain) as Hex[];\n const chainIds = uniq([...tokenChainIds, ...nativeChainIds]);\n\n return chainIds.flatMap((chainId) => {\n const tokenAddresses = [\n ...(Object.keys(balancesByTokenByChain[chainId] ?? {}) as Hex[]),\n getNativeToken(chainId),\n ];\n\n return tokenAddresses.map((tokenAddress) => ({\n chainId,\n tokenAddress,\n balance: getTokenBalance(messenger, account, chainId, tokenAddress),\n }));\n });\n}\n\n/**\n * Get the token decimals for a specific token.\n *\n * @param messenger - Controller messenger.\n * @param tokenAddress - Address of the token contract.\n * @param chainId - Id of the chain.\n * @returns The token decimals or undefined if the token is not found.\n */\nexport function getTokenInfo(\n messenger: TransactionPayControllerMessenger,\n tokenAddress: Hex,\n chainId: Hex,\n): { decimals: number; symbol: string } | undefined {\n const controllerState = messenger.call('TokensController:getState');\n const normalizedTokenAddress = tokenAddress.toLowerCase() as Hex;\n\n const isNative =\n normalizedTokenAddress === getNativeToken(chainId).toLowerCase();\n\n const token = Object.values(controllerState.allTokens?.[chainId] ?? {})\n .flat()\n .find(\n (singleToken) =>\n singleToken.address.toLowerCase() === normalizedTokenAddress,\n );\n\n if (!token && !isNative) {\n return undefined;\n }\n\n if (token && !isNative) {\n return { decimals: Number(token.decimals), symbol: token.symbol };\n }\n\n const ticker = getTicker(chainId, messenger);\n\n if (!ticker) {\n return undefined;\n }\n\n return { decimals: 18, symbol: ticker };\n}\n\n/**\n * Calculate fiat rates for a specific token.\n *\n * @param messenger - Controller messenger.\n * @param tokenAddress - Address of the token contract.\n * @param chainId - Id of the chain.\n * @returns An object containing the USD and fiat rates, or undefined if rates are not available.\n */\nexport function getTokenFiatRate(\n messenger: TransactionPayControllerMessenger,\n tokenAddress: Hex,\n chainId: Hex,\n): FiatRates | undefined {\n const ticker = getTicker(chainId, messenger);\n\n if (!ticker) {\n return undefined;\n }\n\n const rateControllerState = messenger.call('TokenRatesController:getState');\n\n const currencyRateControllerState = messenger.call(\n 'CurrencyRateController:getState',\n );\n\n const normalizedTokenAddress = toChecksumHexAddress(tokenAddress) as Hex;\n const isNative = normalizedTokenAddress === getNativeToken(chainId);\n\n const tokenToNativeRate =\n rateControllerState.marketData?.[chainId]?.[normalizedTokenAddress]?.price;\n\n if (tokenToNativeRate === undefined && !isNative) {\n return undefined;\n }\n\n const {\n conversionRate: nativeToFiatRate,\n usdConversionRate: nativeToUsdRate,\n } = currencyRateControllerState.currencyRates?.[ticker] ?? {\n conversionRate: null,\n usdConversionRate: null,\n };\n\n if (nativeToFiatRate === null || nativeToUsdRate === null) {\n return undefined;\n }\n const isStablecoin = STABLECOINS[chainId]?.includes(\n tokenAddress.toLowerCase() as Hex,\n );\n\n const usdRate = isStablecoin\n ? '1'\n : new BigNumber(tokenToNativeRate ?? 1)\n .multipliedBy(nativeToUsdRate)\n .toString(10);\n\n const fiatRate = new BigNumber(tokenToNativeRate ?? 1)\n .multipliedBy(nativeToFiatRate)\n .toString(10);\n\n return { usdRate, fiatRate };\n}\n\n/**\n * Calculate the human-readable, raw, USD, and fiat representations of a token amount.\n *\n * @param rawInput - Raw token amount (decimal string, hex, or BigNumber).\n * @param decimals - Number of decimals for the token.\n * @param fiatRates - Fiat rates for the token.\n * @returns Object containing the amount in raw, human-readable, USD, and fiat formats.\n */\nexport function computeTokenAmounts(\n rawInput: BigNumber.Value,\n decimals: number,\n fiatRates: FiatRates,\n): {\n raw: string;\n human: string;\n usd: string;\n fiat: string;\n} {\n const rawValue = new BigNumber(rawInput);\n const humanValue = rawValue.shiftedBy(-decimals);\n\n return {\n raw: rawValue.toFixed(0),\n human: humanValue.toString(10),\n usd: humanValue.multipliedBy(fiatRates.usdRate).toString(10),\n fiat: humanValue.multipliedBy(fiatRates.fiatRate).toString(10),\n };\n}\n\n/**\n * Get the native token address for a given chain ID.\n *\n * @param chainId - Chain ID.\n * @returns - Native token address for the given chain ID.\n */\nexport function getNativeToken(chainId: Hex): Hex {\n switch (chainId) {\n case '0x89':\n return '0x0000000000000000000000000000000000001010';\n default:\n return NATIVE_TOKEN_ADDRESS;\n }\n}\n\n/**\n * Get the live on-chain token balance via an RPC `eth_call` to the ERC-20\n * `balanceOf` function, or `eth_getBalance` for native tokens.\n *\n * Unlike {@link getTokenBalance}, this bypasses the cached state in\n * `TokenBalancesController` and reads directly from the chain.\n *\n * @param messenger - Controller messenger.\n * @param account - Address of the account.\n * @param chainId - Chain ID.\n * @param tokenAddress - Address of the token contract.\n * @returns Raw token balance as a decimal string.\n */\nexport async function getLiveTokenBalance(\n messenger: TransactionPayControllerMessenger,\n account: Hex,\n chainId: Hex,\n tokenAddress: Hex,\n): Promise<string> {\n const networkClientId = messenger.call(\n 'NetworkController:findNetworkClientIdByChainId',\n chainId,\n );\n\n const { provider } = messenger.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n\n const ethersProvider = new Web3Provider(provider);\n const isNative =\n tokenAddress.toLowerCase() === getNativeToken(chainId).toLowerCase();\n\n if (isNative) {\n const balance = await ethersProvider.getBalance(account);\n return balance.toString();\n }\n\n const contract = new Contract(tokenAddress, abiERC20, ethersProvider);\n const balance = await contract.balanceOf(account);\n return balance.toString();\n}\n\nfunction getTicker(\n chainId: Hex,\n messenger: TransactionPayControllerMessenger,\n): string | undefined {\n try {\n const networkClientId = messenger.call(\n 'NetworkController:findNetworkClientIdByChainId',\n chainId,\n );\n\n const networkConfiguration = messenger.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n\n return networkConfiguration.configuration.ticker;\n } catch {\n return undefined;\n }\n}\n"]}
1
+ {"version":3,"file":"token.cjs","sourceRoot":"","sources":["../../src/utils/token.ts"],"names":[],"mappings":"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","sourcesContent":["import { Contract } from '@ethersproject/contracts';\nimport { Web3Provider } from '@ethersproject/providers';\nimport { toChecksumHexAddress } from '@metamask/controller-utils';\nimport { abiERC20 } from '@metamask/metamask-eth-abis';\nimport type { Hex } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\nimport { uniq } from 'lodash';\n\nimport {\n CHAIN_ID_POLYGON,\n NATIVE_TOKEN_ADDRESS,\n STABLECOINS,\n} from '../constants';\nimport type { FiatRates, TransactionPayControllerMessenger } from '../types';\n\n/**\n * Check if two tokens are the same (same address and chain).\n *\n * @param token1 - First token identifier.\n * @param token1.address - Token address.\n * @param token1.chainId - Token chain ID.\n * @param token2 - Second token identifier.\n * @param token2.address - Token address.\n * @param token2.chainId - Token chain ID.\n * @returns True if tokens are the same, false otherwise.\n */\nexport function isSameToken(\n token1: { address: Hex; chainId: Hex },\n token2: { address: Hex; chainId: Hex },\n): boolean {\n return (\n token1.address.toLowerCase() === token2.address.toLowerCase() &&\n token1.chainId === token2.chainId\n );\n}\n\n/**\n * Get the token balance for a specific account and token.\n *\n * @param messenger - Controller messenger.\n * @param account - Address of the account.\n * @param chainId - Id of the chain.\n * @param tokenAddress - Address of the token contract.\n * @returns Raw token balance as a decimal string.\n */\nexport function getTokenBalance(\n messenger: TransactionPayControllerMessenger,\n account: Hex,\n chainId: Hex,\n tokenAddress: Hex,\n): string {\n const tokenBalanceControllerState = messenger.call(\n 'TokenBalancesController:getState',\n );\n\n const normalizedAccount = account.toLowerCase() as Hex;\n const normalizedTokenAddress = toChecksumHexAddress(tokenAddress) as Hex;\n const isNative = normalizedTokenAddress === getNativeToken(chainId);\n\n const balanceHex =\n tokenBalanceControllerState.tokenBalances?.[normalizedAccount]?.[chainId]?.[\n normalizedTokenAddress\n ];\n\n if (!isNative && balanceHex === undefined) {\n return '0';\n }\n\n if (!isNative && balanceHex) {\n return new BigNumber(balanceHex, 16).toString(10);\n }\n\n const accountTrackerControllerState = messenger.call(\n 'AccountTrackerController:getState',\n );\n\n const chainAccounts =\n accountTrackerControllerState.accountsByChainId?.[chainId];\n\n const checksumAccount = toChecksumHexAddress(normalizedAccount) as Hex;\n const nativeBalanceHex = chainAccounts?.[checksumAccount]?.balance as Hex;\n\n return new BigNumber(nativeBalanceHex ?? '0x0', 16).toString(10);\n}\n\n/**\n * Get the token balance for a specific account and token.\n *\n * @param messenger - Controller messenger.\n * @param account - Address of the account.\n * @returns The token balance as a BigNumber.\n */\nexport function getAllTokenBalances(\n messenger: TransactionPayControllerMessenger,\n account: Hex,\n): {\n balance: string;\n chainId: Hex;\n tokenAddress: Hex;\n}[] {\n const tokenBalanceControllerState = messenger.call(\n 'TokenBalancesController:getState',\n );\n\n const accountTrackerControllerState = messenger.call(\n 'AccountTrackerController:getState',\n );\n\n const nativeChainIds = Object.keys(\n accountTrackerControllerState.accountsByChainId,\n ) as Hex[];\n\n const normalizedAccount = account.toLowerCase() as Hex;\n\n const balancesByTokenByChain =\n tokenBalanceControllerState.tokenBalances?.[normalizedAccount];\n\n const tokenChainIds = Object.keys(balancesByTokenByChain) as Hex[];\n const chainIds = uniq([...tokenChainIds, ...nativeChainIds]);\n\n return chainIds.flatMap((chainId) => {\n const tokenAddresses = [\n ...(Object.keys(balancesByTokenByChain[chainId] ?? {}) as Hex[]),\n getNativeToken(chainId),\n ];\n\n return tokenAddresses.map((tokenAddress) => ({\n chainId,\n tokenAddress,\n balance: getTokenBalance(messenger, account, chainId, tokenAddress),\n }));\n });\n}\n\n/**\n * Get the token decimals for a specific token.\n *\n * @param messenger - Controller messenger.\n * @param tokenAddress - Address of the token contract.\n * @param chainId - Id of the chain.\n * @returns The token decimals or undefined if the token is not found.\n */\nexport function getTokenInfo(\n messenger: TransactionPayControllerMessenger,\n tokenAddress: Hex,\n chainId: Hex,\n): { decimals: number; symbol: string } | undefined {\n const controllerState = messenger.call('TokensController:getState');\n const normalizedTokenAddress = tokenAddress.toLowerCase() as Hex;\n\n const isNative =\n normalizedTokenAddress === getNativeToken(chainId).toLowerCase();\n\n const token = Object.values(controllerState.allTokens?.[chainId] ?? {})\n .flat()\n .find(\n (singleToken) =>\n singleToken.address.toLowerCase() === normalizedTokenAddress,\n );\n\n if (!token && !isNative) {\n return undefined;\n }\n\n if (token && !isNative) {\n return { decimals: Number(token.decimals), symbol: token.symbol };\n }\n\n const ticker = getTicker(chainId, messenger);\n\n if (!ticker) {\n return undefined;\n }\n\n return { decimals: 18, symbol: ticker };\n}\n\n/**\n * Calculate fiat rates for a specific token.\n *\n * @param messenger - Controller messenger.\n * @param tokenAddress - Address of the token contract.\n * @param chainId - Id of the chain.\n * @returns An object containing the USD and fiat rates, or undefined if rates are not available.\n */\nexport function getTokenFiatRate(\n messenger: TransactionPayControllerMessenger,\n tokenAddress: Hex,\n chainId: Hex,\n): FiatRates | undefined {\n const ticker = getTicker(chainId, messenger);\n\n if (!ticker) {\n return undefined;\n }\n\n const rateControllerState = messenger.call('TokenRatesController:getState');\n\n const currencyRateControllerState = messenger.call(\n 'CurrencyRateController:getState',\n );\n\n const normalizedTokenAddress = toChecksumHexAddress(tokenAddress) as Hex;\n const isNative = normalizedTokenAddress === getNativeToken(chainId);\n\n const tokenToNativeRate =\n rateControllerState.marketData?.[chainId]?.[normalizedTokenAddress]?.price;\n\n if (tokenToNativeRate === undefined && !isNative) {\n return undefined;\n }\n\n const {\n conversionRate: nativeToFiatRate,\n usdConversionRate: nativeToUsdRate,\n } = currencyRateControllerState.currencyRates?.[ticker] ?? {\n conversionRate: null,\n usdConversionRate: null,\n };\n\n if (nativeToFiatRate === null || nativeToUsdRate === null) {\n return undefined;\n }\n const isStablecoin = STABLECOINS[chainId]?.includes(\n tokenAddress.toLowerCase() as Hex,\n );\n\n const usdRate = isStablecoin\n ? '1'\n : new BigNumber(tokenToNativeRate ?? 1)\n .multipliedBy(nativeToUsdRate)\n .toString(10);\n\n const fiatRate = new BigNumber(tokenToNativeRate ?? 1)\n .multipliedBy(nativeToFiatRate)\n .toString(10);\n\n return { usdRate, fiatRate };\n}\n\n/**\n * Calculate the human-readable, raw, USD, and fiat representations of a token amount.\n *\n * @param rawInput - Raw token amount (decimal string, hex, or BigNumber).\n * @param decimals - Number of decimals for the token.\n * @param fiatRates - Fiat rates for the token.\n * @returns Object containing the amount in raw, human-readable, USD, and fiat formats.\n */\nexport function computeTokenAmounts(\n rawInput: BigNumber.Value,\n decimals: number,\n fiatRates: FiatRates,\n): {\n raw: string;\n human: string;\n usd: string;\n fiat: string;\n} {\n const rawValue = new BigNumber(rawInput);\n const humanValue = rawValue.shiftedBy(-decimals);\n\n return {\n raw: rawValue.toFixed(0),\n human: humanValue.toString(10),\n usd: humanValue.multipliedBy(fiatRates.usdRate).toString(10),\n fiat: humanValue.multipliedBy(fiatRates.fiatRate).toString(10),\n };\n}\n\n/**\n * Get the native token address for a given chain ID.\n *\n * @param chainId - Chain ID.\n * @returns - Native token address for the given chain ID.\n */\nexport function getNativeToken(chainId: Hex): Hex {\n switch (chainId) {\n case '0x89':\n return '0x0000000000000000000000000000000000001010';\n default:\n return NATIVE_TOKEN_ADDRESS;\n }\n}\n\n/**\n * Get the live on-chain token balance via an RPC `eth_call` to the ERC-20\n * `balanceOf` function, or `eth_getBalance` for native tokens.\n *\n * Unlike {@link getTokenBalance}, this bypasses the cached state in\n * `TokenBalancesController` and reads directly from the chain.\n *\n * @param messenger - Controller messenger.\n * @param account - Address of the account.\n * @param chainId - Chain ID.\n * @param tokenAddress - Address of the token contract.\n * @returns Raw token balance as a decimal string.\n */\nexport async function getLiveTokenBalance(\n messenger: TransactionPayControllerMessenger,\n account: Hex,\n chainId: Hex,\n tokenAddress: Hex,\n): Promise<string> {\n const networkClientId = messenger.call(\n 'NetworkController:findNetworkClientIdByChainId',\n chainId,\n );\n\n const { provider } = messenger.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n\n const ethersProvider = new Web3Provider(provider);\n const isNative =\n tokenAddress.toLowerCase() === getNativeToken(chainId).toLowerCase();\n\n if (isNative) {\n const balance = await ethersProvider.getBalance(account);\n return balance.toString();\n }\n\n const contract = new Contract(tokenAddress, abiERC20, ethersProvider);\n const balance = await contract.balanceOf(account);\n return balance.toString();\n}\n\nfunction getTicker(\n chainId: Hex,\n messenger: TransactionPayControllerMessenger,\n): string | undefined {\n try {\n const networkClientId = messenger.call(\n 'NetworkController:findNetworkClientIdByChainId',\n chainId,\n );\n\n const networkConfiguration = messenger.call(\n 'NetworkController:getNetworkClientById',\n networkClientId,\n );\n\n return networkConfiguration.configuration.ticker;\n } catch {\n return undefined;\n }\n}\n\nexport enum TokenAddressTarget {\n Relay = 'relay',\n MetaMask = 'metamask',\n}\n\n/**\n * Normalize token address formats between MetaMask and Relay for Polygon native\n * token handling.\n *\n * MetaMask uses Polygon's native token contract-like address (`0x...1010`),\n * while Relay expects the zero address for native tokens.\n *\n * @param tokenAddress - Token address to normalize.\n * @param chainId - Chain ID for the token.\n * @param target - Optional target system format.\n * @returns Normalized token address for the target system, or the original\n * address if no target is provided.\n */\nexport function normalizeTokenAddress(\n tokenAddress: Hex,\n chainId: Hex,\n target?: TokenAddressTarget,\n): Hex {\n if (chainId !== CHAIN_ID_POLYGON) {\n return tokenAddress;\n }\n\n const nativeTokenAddress = getNativeToken(chainId).toLowerCase() as Hex;\n const normalizedTokenAddress = tokenAddress.toLowerCase();\n\n if (\n target === TokenAddressTarget.Relay &&\n normalizedTokenAddress === nativeTokenAddress\n ) {\n return NATIVE_TOKEN_ADDRESS;\n }\n\n if (\n target === TokenAddressTarget.MetaMask &&\n normalizedTokenAddress === NATIVE_TOKEN_ADDRESS.toLowerCase()\n ) {\n return nativeTokenAddress;\n }\n\n return tokenAddress;\n}\n"]}
@@ -97,4 +97,22 @@ export declare function getNativeToken(chainId: Hex): Hex;
97
97
  * @returns Raw token balance as a decimal string.
98
98
  */
99
99
  export declare function getLiveTokenBalance(messenger: TransactionPayControllerMessenger, account: Hex, chainId: Hex, tokenAddress: Hex): Promise<string>;
100
+ export declare enum TokenAddressTarget {
101
+ Relay = "relay",
102
+ MetaMask = "metamask"
103
+ }
104
+ /**
105
+ * Normalize token address formats between MetaMask and Relay for Polygon native
106
+ * token handling.
107
+ *
108
+ * MetaMask uses Polygon's native token contract-like address (`0x...1010`),
109
+ * while Relay expects the zero address for native tokens.
110
+ *
111
+ * @param tokenAddress - Token address to normalize.
112
+ * @param chainId - Chain ID for the token.
113
+ * @param target - Optional target system format.
114
+ * @returns Normalized token address for the target system, or the original
115
+ * address if no target is provided.
116
+ */
117
+ export declare function normalizeTokenAddress(tokenAddress: Hex, chainId: Hex, target?: TokenAddressTarget): Hex;
100
118
  //# sourceMappingURL=token.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"token.d.cts","sourceRoot":"","sources":["../../src/utils/token.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAC3C,OAAO,EAAE,SAAS,EAAE,qBAAqB;AAIzC,OAAO,KAAK,EAAE,SAAS,EAAE,iCAAiC,EAAE,qBAAiB;AAE7E;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE;IAAE,OAAO,EAAE,GAAG,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,EACtC,MAAM,EAAE;IAAE,OAAO,EAAE,GAAG,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,GACrC,OAAO,CAKT;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,iCAAiC,EAC5C,OAAO,EAAE,GAAG,EACZ,OAAO,EAAE,GAAG,EACZ,YAAY,EAAE,GAAG,GAChB,MAAM,CAiCR;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,iCAAiC,EAC5C,OAAO,EAAE,GAAG,GACX;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,GAAG,CAAC;IACb,YAAY,EAAE,GAAG,CAAC;CACnB,EAAE,CAiCF;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,iCAAiC,EAC5C,YAAY,EAAE,GAAG,EACjB,OAAO,EAAE,GAAG,GACX;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CA6BlD;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,iCAAiC,EAC5C,YAAY,EAAE,GAAG,EACjB,OAAO,EAAE,GAAG,GACX,SAAS,GAAG,SAAS,CAiDvB;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,SAAS,CAAC,KAAK,EACzB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,SAAS,GACnB;IACD,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd,CAUA;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,GAAG,GAAG,GAAG,CAOhD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,iCAAiC,EAC5C,OAAO,EAAE,GAAG,EACZ,OAAO,EAAE,GAAG,EACZ,YAAY,EAAE,GAAG,GAChB,OAAO,CAAC,MAAM,CAAC,CAuBjB"}
1
+ {"version":3,"file":"token.d.cts","sourceRoot":"","sources":["../../src/utils/token.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAC3C,OAAO,EAAE,SAAS,EAAE,qBAAqB;AAQzC,OAAO,KAAK,EAAE,SAAS,EAAE,iCAAiC,EAAE,qBAAiB;AAE7E;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE;IAAE,OAAO,EAAE,GAAG,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,EACtC,MAAM,EAAE;IAAE,OAAO,EAAE,GAAG,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,GACrC,OAAO,CAKT;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,iCAAiC,EAC5C,OAAO,EAAE,GAAG,EACZ,OAAO,EAAE,GAAG,EACZ,YAAY,EAAE,GAAG,GAChB,MAAM,CAiCR;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,iCAAiC,EAC5C,OAAO,EAAE,GAAG,GACX;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,GAAG,CAAC;IACb,YAAY,EAAE,GAAG,CAAC;CACnB,EAAE,CAiCF;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,iCAAiC,EAC5C,YAAY,EAAE,GAAG,EACjB,OAAO,EAAE,GAAG,GACX;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CA6BlD;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,iCAAiC,EAC5C,YAAY,EAAE,GAAG,EACjB,OAAO,EAAE,GAAG,GACX,SAAS,GAAG,SAAS,CAiDvB;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,SAAS,CAAC,KAAK,EACzB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,SAAS,GACnB;IACD,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd,CAUA;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,GAAG,GAAG,GAAG,CAOhD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,iCAAiC,EAC5C,OAAO,EAAE,GAAG,EACZ,OAAO,EAAE,GAAG,EACZ,YAAY,EAAE,GAAG,GAChB,OAAO,CAAC,MAAM,CAAC,CAuBjB;AAuBD,oBAAY,kBAAkB;IAC5B,KAAK,UAAU;IACf,QAAQ,aAAa;CACtB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,GAAG,EACjB,OAAO,EAAE,GAAG,EACZ,MAAM,CAAC,EAAE,kBAAkB,GAC1B,GAAG,CAuBL"}
@@ -97,4 +97,22 @@ export declare function getNativeToken(chainId: Hex): Hex;
97
97
  * @returns Raw token balance as a decimal string.
98
98
  */
99
99
  export declare function getLiveTokenBalance(messenger: TransactionPayControllerMessenger, account: Hex, chainId: Hex, tokenAddress: Hex): Promise<string>;
100
+ export declare enum TokenAddressTarget {
101
+ Relay = "relay",
102
+ MetaMask = "metamask"
103
+ }
104
+ /**
105
+ * Normalize token address formats between MetaMask and Relay for Polygon native
106
+ * token handling.
107
+ *
108
+ * MetaMask uses Polygon's native token contract-like address (`0x...1010`),
109
+ * while Relay expects the zero address for native tokens.
110
+ *
111
+ * @param tokenAddress - Token address to normalize.
112
+ * @param chainId - Chain ID for the token.
113
+ * @param target - Optional target system format.
114
+ * @returns Normalized token address for the target system, or the original
115
+ * address if no target is provided.
116
+ */
117
+ export declare function normalizeTokenAddress(tokenAddress: Hex, chainId: Hex, target?: TokenAddressTarget): Hex;
100
118
  //# sourceMappingURL=token.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"token.d.mts","sourceRoot":"","sources":["../../src/utils/token.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAC3C,OAAO,EAAE,SAAS,EAAE,qBAAqB;AAIzC,OAAO,KAAK,EAAE,SAAS,EAAE,iCAAiC,EAAE,qBAAiB;AAE7E;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE;IAAE,OAAO,EAAE,GAAG,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,EACtC,MAAM,EAAE;IAAE,OAAO,EAAE,GAAG,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,GACrC,OAAO,CAKT;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,iCAAiC,EAC5C,OAAO,EAAE,GAAG,EACZ,OAAO,EAAE,GAAG,EACZ,YAAY,EAAE,GAAG,GAChB,MAAM,CAiCR;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,iCAAiC,EAC5C,OAAO,EAAE,GAAG,GACX;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,GAAG,CAAC;IACb,YAAY,EAAE,GAAG,CAAC;CACnB,EAAE,CAiCF;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,iCAAiC,EAC5C,YAAY,EAAE,GAAG,EACjB,OAAO,EAAE,GAAG,GACX;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CA6BlD;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,iCAAiC,EAC5C,YAAY,EAAE,GAAG,EACjB,OAAO,EAAE,GAAG,GACX,SAAS,GAAG,SAAS,CAiDvB;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,SAAS,CAAC,KAAK,EACzB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,SAAS,GACnB;IACD,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd,CAUA;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,GAAG,GAAG,GAAG,CAOhD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,iCAAiC,EAC5C,OAAO,EAAE,GAAG,EACZ,OAAO,EAAE,GAAG,EACZ,YAAY,EAAE,GAAG,GAChB,OAAO,CAAC,MAAM,CAAC,CAuBjB"}
1
+ {"version":3,"file":"token.d.mts","sourceRoot":"","sources":["../../src/utils/token.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAC3C,OAAO,EAAE,SAAS,EAAE,qBAAqB;AAQzC,OAAO,KAAK,EAAE,SAAS,EAAE,iCAAiC,EAAE,qBAAiB;AAE7E;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE;IAAE,OAAO,EAAE,GAAG,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,EACtC,MAAM,EAAE;IAAE,OAAO,EAAE,GAAG,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,GACrC,OAAO,CAKT;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,iCAAiC,EAC5C,OAAO,EAAE,GAAG,EACZ,OAAO,EAAE,GAAG,EACZ,YAAY,EAAE,GAAG,GAChB,MAAM,CAiCR;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,iCAAiC,EAC5C,OAAO,EAAE,GAAG,GACX;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,GAAG,CAAC;IACb,YAAY,EAAE,GAAG,CAAC;CACnB,EAAE,CAiCF;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,iCAAiC,EAC5C,YAAY,EAAE,GAAG,EACjB,OAAO,EAAE,GAAG,GACX;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CA6BlD;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,iCAAiC,EAC5C,YAAY,EAAE,GAAG,EACjB,OAAO,EAAE,GAAG,GACX,SAAS,GAAG,SAAS,CAiDvB;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,SAAS,CAAC,KAAK,EACzB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,SAAS,GACnB;IACD,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd,CAUA;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,GAAG,GAAG,GAAG,CAOhD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,iCAAiC,EAC5C,OAAO,EAAE,GAAG,EACZ,OAAO,EAAE,GAAG,EACZ,YAAY,EAAE,GAAG,GAChB,OAAO,CAAC,MAAM,CAAC,CAuBjB;AAuBD,oBAAY,kBAAkB;IAC5B,KAAK,UAAU;IACf,QAAQ,aAAa;CACtB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,GAAG,EACjB,OAAO,EAAE,GAAG,EACZ,MAAM,CAAC,EAAE,kBAAkB,GAC1B,GAAG,CAuBL"}
@@ -5,7 +5,7 @@ import { abiERC20 } from "@metamask/metamask-eth-abis";
5
5
  import { BigNumber } from "bignumber.js";
6
6
  import $lodash from "lodash";
7
7
  const { uniq } = $lodash;
8
- import { NATIVE_TOKEN_ADDRESS, STABLECOINS } from "../constants.mjs";
8
+ import { CHAIN_ID_POLYGON, NATIVE_TOKEN_ADDRESS, STABLECOINS } from "../constants.mjs";
9
9
  /**
10
10
  * Check if two tokens are the same (same address and chain).
11
11
  *
@@ -209,4 +209,38 @@ function getTicker(chainId, messenger) {
209
209
  return undefined;
210
210
  }
211
211
  }
212
+ export var TokenAddressTarget;
213
+ (function (TokenAddressTarget) {
214
+ TokenAddressTarget["Relay"] = "relay";
215
+ TokenAddressTarget["MetaMask"] = "metamask";
216
+ })(TokenAddressTarget || (TokenAddressTarget = {}));
217
+ /**
218
+ * Normalize token address formats between MetaMask and Relay for Polygon native
219
+ * token handling.
220
+ *
221
+ * MetaMask uses Polygon's native token contract-like address (`0x...1010`),
222
+ * while Relay expects the zero address for native tokens.
223
+ *
224
+ * @param tokenAddress - Token address to normalize.
225
+ * @param chainId - Chain ID for the token.
226
+ * @param target - Optional target system format.
227
+ * @returns Normalized token address for the target system, or the original
228
+ * address if no target is provided.
229
+ */
230
+ export function normalizeTokenAddress(tokenAddress, chainId, target) {
231
+ if (chainId !== CHAIN_ID_POLYGON) {
232
+ return tokenAddress;
233
+ }
234
+ const nativeTokenAddress = getNativeToken(chainId).toLowerCase();
235
+ const normalizedTokenAddress = tokenAddress.toLowerCase();
236
+ if (target === TokenAddressTarget.Relay &&
237
+ normalizedTokenAddress === nativeTokenAddress) {
238
+ return NATIVE_TOKEN_ADDRESS;
239
+ }
240
+ if (target === TokenAddressTarget.MetaMask &&
241
+ normalizedTokenAddress === NATIVE_TOKEN_ADDRESS.toLowerCase()) {
242
+ return nativeTokenAddress;
243
+ }
244
+ return tokenAddress;
245
+ }
212
246
  //# sourceMappingURL=token.mjs.map