@metamask-previews/transaction-pay-controller 26.3.0-preview-e81fe8853 → 26.4.0-preview-3c77cf4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -1
- package/dist/strategy/relay/polymarket/withdraw.cjs +96 -17
- package/dist/strategy/relay/polymarket/withdraw.cjs.map +1 -1
- package/dist/strategy/relay/polymarket/withdraw.d.cts +39 -0
- package/dist/strategy/relay/polymarket/withdraw.d.cts.map +1 -1
- package/dist/strategy/relay/polymarket/withdraw.d.mts +39 -0
- package/dist/strategy/relay/polymarket/withdraw.d.mts.map +1 -1
- package/dist/strategy/relay/polymarket/withdraw.mjs +92 -16
- package/dist/strategy/relay/polymarket/withdraw.mjs.map +1 -1
- package/dist/strategy/relay/relay-quotes.cjs +3 -7
- package/dist/strategy/relay/relay-quotes.cjs.map +1 -1
- package/dist/strategy/relay/relay-quotes.d.cts.map +1 -1
- package/dist/strategy/relay/relay-quotes.d.mts.map +1 -1
- package/dist/strategy/relay/relay-quotes.mjs +4 -8
- package/dist/strategy/relay/relay-quotes.mjs.map +1 -1
- package/dist/strategy/relay/relay-validation.cjs +42 -19
- package/dist/strategy/relay/relay-validation.cjs.map +1 -1
- package/dist/strategy/relay/relay-validation.d.cts.map +1 -1
- package/dist/strategy/relay/relay-validation.d.mts.map +1 -1
- package/dist/strategy/relay/relay-validation.mjs +42 -19
- package/dist/strategy/relay/relay-validation.mjs.map +1 -1
- package/dist/utils/feature-flags.cjs +22 -3
- package/dist/utils/feature-flags.cjs.map +1 -1
- package/dist/utils/feature-flags.d.cts +15 -3
- package/dist/utils/feature-flags.d.cts.map +1 -1
- package/dist/utils/feature-flags.d.mts +15 -3
- package/dist/utils/feature-flags.d.mts.map +1 -1
- package/dist/utils/feature-flags.mjs +22 -3
- package/dist/utils/feature-flags.mjs.map +1 -1
- package/dist/utils/validation.cjs +33 -17
- package/dist/utils/validation.cjs.map +1 -1
- package/dist/utils/validation.d.cts.map +1 -1
- package/dist/utils/validation.d.mts.map +1 -1
- package/dist/utils/validation.mjs +32 -16
- package/dist/utils/validation.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-flags.mjs","sourceRoot":"","sources":["../../src/utils/feature-flags.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TransactionType } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\nimport { uniq } from 'lodash';\n\nimport {\n isTransactionPayStrategy,\n STABLECOINS,\n TransactionPayStrategy,\n} from '../constants.js';\nimport { projectLogger } from '../logger.js';\nimport type { TransactionPayFiatAsset } from '../strategy/fiat/constants.js';\nimport {\n ETH_MAINNET_FIAT_ASSET,\n FIAT_ASSET_ID_BY_TX_TYPE,\n FIAT_ENABLED_TYPES,\n} from '../strategy/fiat/constants.js';\nimport {\n RELAY_EXECUTE_URL,\n RELAY_POLLING_INTERVAL,\n RELAY_QUOTE_URL,\n} from '../strategy/relay/constants.js';\nimport {\n SERVER_POLLING_INTERVAL,\n SERVER_URL_BASE,\n} from '../strategy/server/constants.js';\nimport type { TransactionPayControllerMessenger } from '../types.js';\n\nconst log = createModuleLogger(projectLogger, 'feature-flags');\n\ntype StrategyOrder = TransactionPayStrategy[];\n\nexport const DEFAULT_FEE_RESERVE_MULTIPLIER = 1.2;\nexport const DEFAULT_MAX_RATE_DRIFT_PERCENT = 10;\nexport const DEFAULT_ORDER_POLL_INTERVAL_MS = 1000;\nexport const DEFAULT_ORDER_POLL_TIMEOUT_MS = 10 * 60 * 1000;\n\nexport const DEFAULT_GAS_BUFFER = 1.0;\nexport const DEFAULT_FALLBACK_GAS_ESTIMATE = 900000;\nexport const DEFAULT_FALLBACK_GAS_MAX = 1500000;\nexport const DEFAULT_RELAY_EXECUTE_URL = RELAY_EXECUTE_URL;\nexport const DEFAULT_RELAY_QUOTE_URL = RELAY_QUOTE_URL;\nexport const DEFAULT_RELAY_ORIGIN_GAS_OVERHEAD = '300000';\nexport const DEFAULT_SLIPPAGE = 0.005;\nexport const DEFAULT_HYPERLIQUID_ACTIVATION_FEE_USD = 1;\nexport const DEFAULT_ACROSS_API_BASE = 'https://app.across.to/api';\nexport const DEFAULT_SERVER_BASE_URL = SERVER_URL_BASE;\nexport const DEFAULT_STRATEGY_ORDER: StrategyOrder = [\n TransactionPayStrategy.Server,\n TransactionPayStrategy.Relay,\n TransactionPayStrategy.Across,\n];\n\ntype FeatureFlagsRaw = {\n gasBuffer?: {\n default?: number;\n perChainConfig?: Record<\n Hex,\n {\n name?: string;\n buffer?: number;\n }\n >;\n };\n relayDisabledGasStationChains?: Hex[];\n relayExecuteUrl?: string;\n relayFallbackGas?: {\n estimate?: number;\n max?: number;\n };\n relayQuoteUrl?: string;\n slippage?: number;\n slippageTokens?: Record<Hex, Record<Hex, number>>;\n strategyOrder?: string[];\n strategyOverrides?: StrategyOverridesRaw;\n payStrategies?: PayStrategiesConfigRaw;\n};\n\ntype StrategyOverrideRaw = {\n default?: unknown;\n chains?: Record<string, unknown>;\n tokens?: Record<string, Record<string, unknown>>;\n};\n\ntype StrategyOverridesRaw = {\n default?: StrategyOverrideRaw;\n transactionTypes?: Record<string, StrategyOverrideRaw>;\n};\n\ntype StrategyOverride = {\n chains: Record<Hex, TransactionPayStrategy[]>;\n default?: TransactionPayStrategy[];\n tokens: Record<Hex, Record<Hex, TransactionPayStrategy[]>>;\n};\n\ntype StrategyOverrides = {\n default?: StrategyOverride;\n transactionTypes: Record<string, StrategyOverride>;\n};\n\ntype FiatFlags = {\n assetPerTransactionType?: Partial<\n Record<TransactionType, TransactionPayFiatAsset>\n >;\n directMoneyMusdEnabled?: boolean;\n enabledTransactionTypes: TransactionType[];\n feeReserveMultiplier?: number;\n maxRateDriftPercent?: number;\n orderPollIntervalMs?: number;\n orderPollTimeoutMs?: number;\n vaultDisabled?: boolean;\n};\n\ntype HyperliquidActivationFeeFlag = {\n enabled?: boolean;\n amountUsd?: number;\n};\n\ntype PostQuoteConfig = {\n hyperliquidActivationFee?: HyperliquidActivationFeeFlag;\n};\n\ntype PostQuoteFeatureFlags = {\n default?: PostQuoteConfig;\n overrides?: Record<string, PostQuoteConfig>;\n};\n\nexport type HyperliquidActivationFeeConfig = {\n enabled: boolean;\n amountUsd: number;\n};\n\ntype StrategyRoutingConfig = {\n payStrategies: {\n across: {\n enabled: boolean;\n };\n server: {\n enabled: boolean;\n };\n relay: {\n enabled: boolean;\n };\n };\n strategyOverrides: StrategyOverrides;\n strategyOrder: TransactionPayStrategy[];\n};\n\nexport type FeatureFlags = {\n relayDisabledGasStationChains: Hex[];\n relayExecuteUrl: string;\n relayFallbackGas: {\n estimate: number;\n max: number;\n };\n relayQuoteUrl: string;\n slippage: number;\n};\n\nexport type AcrossConfigRaw = {\n apiBase?: string;\n enabled?: boolean;\n fallbackGas?: {\n estimate?: number;\n max?: number;\n };\n};\n\nexport type AcrossConfig = {\n apiBase: string;\n enabled: boolean;\n fallbackGas: {\n estimate: number;\n max: number;\n };\n};\n\nexport type PayStrategiesConfigRaw = {\n across?: AcrossConfigRaw;\n relay?: {\n enabled?: boolean;\n originGasOverhead?: string;\n pollingInterval?: number;\n pollingTimeout?: number;\n };\n};\n\ntype FeatureFlagsExtendedRaw = {\n excludeChainIdsFromInfura?: Hex[];\n payStrategies?: {\n relay?: {\n gaslessEnabled?: boolean;\n validationEnabled?: boolean;\n };\n server?: {\n enabled?: boolean;\n baseUrl?: string;\n pollingInterval?: number;\n pollingTimeout?: number;\n };\n };\n};\n\ntype EIP7702FeatureFlag = {\n contracts?: Record<Hex, { address: Hex; signature: Hex }[]>;\n supportedChains?: Hex[];\n};\n\nexport type PayStrategiesConfig = {\n across: AcrossConfig;\n server: {\n enabled: boolean;\n baseUrl: string;\n pollingInterval: number;\n pollingTimeout?: number;\n };\n relay: {\n enabled: boolean;\n };\n};\n\nfunction normalizeHex(value: string | undefined): Hex | undefined {\n return value?.toLowerCase() as Hex | undefined;\n}\n\nfunction normalizeStrategy(\n strategy: unknown,\n): TransactionPayStrategy | undefined {\n if (typeof strategy !== 'string') {\n return undefined;\n }\n\n const normalizedStrategy = strategy.toLowerCase() as TransactionPayStrategy;\n\n return isTransactionPayStrategy(normalizedStrategy)\n ? normalizedStrategy\n : undefined;\n}\n\nfunction normalizeStrategyList(strategies: unknown): TransactionPayStrategy[] {\n if (!Array.isArray(strategies)) {\n return [];\n }\n\n return uniq(\n strategies\n .map((strategy) => normalizeStrategy(strategy))\n .filter(\n (strategy): strategy is TransactionPayStrategy =>\n strategy !== undefined,\n ),\n );\n}\n\nfunction normalizeStrategyOverride(\n override: StrategyOverrideRaw | undefined,\n): StrategyOverride {\n const chains = Object.entries(override?.chains ?? {}).reduce<\n Record<Hex, TransactionPayStrategy[]>\n >((result, [chainId, strategies]) => {\n const normalizedStrategies = normalizeStrategyList(strategies);\n\n if (normalizedStrategies.length) {\n result[normalizeHex(chainId) as Hex] = normalizedStrategies;\n }\n\n return result;\n }, {});\n\n const tokens = Object.entries(override?.tokens ?? {}).reduce<\n Record<Hex, Record<Hex, TransactionPayStrategy[]>>\n >((result, [chainId, tokenOverrides]) => {\n const normalizedTokenOverrides = Object.entries(\n tokenOverrides ?? {},\n ).reduce<Record<Hex, TransactionPayStrategy[]>>(\n (tokenResult, [tokenAddress, strategies]) => {\n const normalizedStrategies = normalizeStrategyList(strategies);\n\n if (normalizedStrategies.length) {\n tokenResult[normalizeHex(tokenAddress) as Hex] = normalizedStrategies;\n }\n\n return tokenResult;\n },\n {},\n );\n\n if (Object.keys(normalizedTokenOverrides).length) {\n result[normalizeHex(chainId) as Hex] = normalizedTokenOverrides;\n }\n\n return result;\n }, {});\n\n const defaultStrategies = normalizeStrategyList(override?.default);\n\n return {\n chains,\n default: defaultStrategies.length ? defaultStrategies : undefined,\n tokens,\n };\n}\n\nfunction normalizeStrategyRoutingConfig(\n featureFlags: FeatureFlagsRaw,\n extendedFeatureFlags: FeatureFlagsExtendedRaw,\n): StrategyRoutingConfig {\n const strategyOrder = normalizeStrategyList(featureFlags.strategyOrder);\n\n return {\n payStrategies: {\n across: {\n enabled: featureFlags.payStrategies?.across?.enabled ?? false,\n },\n server: {\n enabled: extendedFeatureFlags.payStrategies?.server?.enabled ?? false,\n },\n relay: {\n enabled: featureFlags.payStrategies?.relay?.enabled ?? true,\n },\n },\n strategyOverrides: {\n default: featureFlags.strategyOverrides?.default\n ? normalizeStrategyOverride(featureFlags.strategyOverrides.default)\n : undefined,\n transactionTypes: Object.entries(\n featureFlags.strategyOverrides?.transactionTypes ?? {},\n ).reduce<Record<string, StrategyOverride>>((result, [type, override]) => {\n result[type] = normalizeStrategyOverride(override);\n return result;\n }, {}),\n },\n strategyOrder:\n strategyOrder.length > 0 ? strategyOrder : [...DEFAULT_STRATEGY_ORDER],\n };\n}\n\nfunction getStrategyRoutingConfig(\n messenger: TransactionPayControllerMessenger,\n): StrategyRoutingConfig {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const featureFlags = state.remoteFeatureFlags?.confirmations_pay as\n | FeatureFlagsRaw\n | undefined;\n const extendedFeatureFlags =\n (state.remoteFeatureFlags?.confirmations_pay_extended as\n | FeatureFlagsExtendedRaw\n | undefined) ?? {};\n\n return normalizeStrategyRoutingConfig(\n featureFlags ?? {},\n extendedFeatureFlags,\n );\n}\n\nfunction filterEnabledStrategies(\n strategies: readonly TransactionPayStrategy[],\n routingConfig: StrategyRoutingConfig,\n): TransactionPayStrategy[] {\n return strategies.filter((strategy) => {\n if (strategy === TransactionPayStrategy.Across) {\n return routingConfig.payStrategies.across.enabled;\n }\n\n if (strategy === TransactionPayStrategy.Relay) {\n return routingConfig.payStrategies.relay.enabled;\n }\n\n if (strategy === TransactionPayStrategy.Server) {\n return routingConfig.payStrategies.server.enabled;\n }\n\n return true;\n });\n}\n\nfunction getTokenOverrideStrategies(\n override: StrategyOverride | undefined,\n normalizedChainId: Hex | undefined,\n normalizedTokenAddress: Hex | undefined,\n): readonly TransactionPayStrategy[] | undefined {\n if (!override || !normalizedChainId || !normalizedTokenAddress) {\n return undefined;\n }\n\n return override.tokens[normalizedChainId]?.[normalizedTokenAddress];\n}\n\nfunction getChainOverrideStrategies(\n override: StrategyOverride | undefined,\n normalizedChainId: Hex | undefined,\n): readonly TransactionPayStrategy[] | undefined {\n if (!override || !normalizedChainId) {\n return undefined;\n }\n\n return override.chains[normalizedChainId];\n}\n\nfunction getDefaultOverrideStrategies(\n override: StrategyOverride | undefined,\n): readonly TransactionPayStrategy[] | undefined {\n return override?.default;\n}\n\n/**\n * Get ordered list of strategies to try for a route.\n *\n * @param messenger - Controller messenger.\n * @param chainId - Optional chain ID used to match route overrides.\n * @param tokenAddress - Optional token address used to match route overrides.\n * @param transactionType - Optional transaction type used to match route\n * overrides.\n * @param fiatPaymentMethodId - Optional fiat payment method ID used to match route overrides.\n * @returns Ordered strategy list.\n */\nexport function getStrategyOrder(\n messenger: TransactionPayControllerMessenger,\n chainId?: Hex,\n tokenAddress?: Hex,\n transactionType?: string,\n fiatPaymentMethodId?: string,\n): StrategyOrder {\n // If fiat payment method is selected, use Fiat strategy only\n if (fiatPaymentMethodId) {\n return [TransactionPayStrategy.Fiat];\n }\n\n const routingConfig = getStrategyRoutingConfig(messenger);\n const normalizedChainId = normalizeHex(chainId);\n const normalizedTokenAddress = normalizeHex(tokenAddress);\n const transactionTypeOverride = transactionType\n ? routingConfig.strategyOverrides.transactionTypes[transactionType]\n : undefined;\n\n const candidates: (readonly TransactionPayStrategy[] | undefined)[] = [\n getTokenOverrideStrategies(\n transactionTypeOverride,\n normalizedChainId,\n normalizedTokenAddress,\n ),\n getChainOverrideStrategies(transactionTypeOverride, normalizedChainId),\n getTokenOverrideStrategies(\n routingConfig.strategyOverrides.default,\n normalizedChainId,\n normalizedTokenAddress,\n ),\n getChainOverrideStrategies(\n routingConfig.strategyOverrides.default,\n normalizedChainId,\n ),\n getDefaultOverrideStrategies(transactionTypeOverride),\n getDefaultOverrideStrategies(routingConfig.strategyOverrides.default),\n ];\n\n // Overrides are authoritative. Once a route matches a specific override\n // scope, disabled strategies do not inherit candidates from lower-precedence\n // scopes.\n for (const strategies of candidates) {\n if (strategies) {\n return filterEnabledStrategies(strategies, routingConfig);\n }\n }\n\n return filterEnabledStrategies(routingConfig.strategyOrder, routingConfig);\n}\n\n/**\n * Get the preferred strategy for a route.\n *\n * @param messenger - Controller messenger.\n * @param chainId - Optional chain ID used to match route overrides.\n * @param tokenAddress - Optional token address used to match route overrides.\n * @param transactionType - Optional transaction type used to match route\n * overrides.\n * @returns The preferred strategy, if any.\n */\nexport function getStrategy(\n messenger: TransactionPayControllerMessenger,\n chainId?: Hex,\n tokenAddress?: Hex,\n transactionType?: string,\n): TransactionPayStrategy | undefined {\n return getStrategyOrder(messenger, chainId, tokenAddress, transactionType)[0];\n}\n\n/**\n * Get feature flags related to the controller.\n *\n * @param messenger - Controller messenger.\n * @returns Feature flags.\n */\nexport function getFeatureFlags(\n messenger: TransactionPayControllerMessenger,\n): FeatureFlags {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const featureFlags =\n (state.remoteFeatureFlags?.confirmations_pay as\n | FeatureFlagsRaw\n | undefined) ?? {};\n\n const estimate = new BigNumber(\n featureFlags.relayFallbackGas?.estimate ?? DEFAULT_FALLBACK_GAS_ESTIMATE,\n ).toNumber();\n\n const max = new BigNumber(\n featureFlags.relayFallbackGas?.max ?? DEFAULT_FALLBACK_GAS_MAX,\n ).toNumber();\n\n const relayExecuteUrl =\n featureFlags.relayExecuteUrl ?? DEFAULT_RELAY_EXECUTE_URL;\n\n const relayQuoteUrl = featureFlags.relayQuoteUrl ?? DEFAULT_RELAY_QUOTE_URL;\n\n const relayDisabledGasStationChains =\n featureFlags.relayDisabledGasStationChains ?? [];\n\n const slippage = featureFlags.slippage ?? DEFAULT_SLIPPAGE;\n\n const result: FeatureFlags = {\n relayDisabledGasStationChains,\n relayExecuteUrl,\n relayFallbackGas: {\n estimate,\n max,\n },\n relayQuoteUrl,\n slippage,\n };\n\n log('Feature flags:', { raw: featureFlags, result });\n\n return result;\n}\n\n/**\n * Get the stablecoins map from the `stableTokens` feature flag.\n * Falls back to the hardcoded {@link STABLECOINS} constant when the flag is\n * absent or not a valid object.\n *\n * @param messenger - Controller messenger.\n * @returns Stablecoins keyed by chain ID.\n */\nexport function getStablecoins(\n messenger: TransactionPayControllerMessenger,\n): Record<Hex, Hex[]> {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const flag = state.remoteFeatureFlags?.stableTokens;\n\n if (flag && typeof flag === 'object' && !Array.isArray(flag)) {\n const raw = flag as Record<string, string[]>;\n return Object.entries(raw).reduce<Record<Hex, Hex[]>>(\n (acc, [chainId, addresses]) => {\n if (Array.isArray(addresses)) {\n acc[chainId.toLowerCase() as Hex] = addresses.map(\n (a) => a.toLowerCase() as Hex,\n );\n }\n return acc;\n },\n {},\n );\n }\n\n return STABLECOINS;\n}\n\n/**\n * Get Pay Strategies configuration.\n *\n * @param messenger - Controller messenger.\n * @returns Pay Strategies configuration.\n */\nexport function getPayStrategiesConfig(\n messenger: TransactionPayControllerMessenger,\n): PayStrategiesConfig {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const featureFlags =\n (state.remoteFeatureFlags?.confirmations_pay as\n | FeatureFlagsRaw\n | undefined) ?? {};\n const extendedFeatureFlags =\n (state.remoteFeatureFlags?.confirmations_pay_extended as\n | FeatureFlagsExtendedRaw\n | undefined) ?? {};\n const payStrategies = featureFlags.payStrategies ?? {};\n const extendedPayStrategies = extendedFeatureFlags.payStrategies ?? {};\n\n const acrossRaw = payStrategies.across ?? {};\n const serverRaw = extendedPayStrategies.server ?? {};\n const relayRaw = payStrategies.relay ?? {};\n\n const across = {\n apiBase: acrossRaw.apiBase ?? DEFAULT_ACROSS_API_BASE,\n enabled: acrossRaw.enabled ?? false,\n fallbackGas: {\n estimate:\n acrossRaw.fallbackGas?.estimate ?? DEFAULT_FALLBACK_GAS_ESTIMATE,\n max: acrossRaw.fallbackGas?.max ?? DEFAULT_FALLBACK_GAS_MAX,\n },\n };\n\n const server = {\n enabled: serverRaw.enabled ?? false,\n baseUrl: serverRaw.baseUrl ?? DEFAULT_SERVER_BASE_URL,\n pollingInterval: serverRaw.pollingInterval ?? SERVER_POLLING_INTERVAL,\n pollingTimeout: serverRaw.pollingTimeout,\n };\n\n const relay = {\n enabled: relayRaw.enabled ?? true,\n };\n\n return {\n across,\n server,\n relay,\n };\n}\n\n/**\n * Whether the Relay /execute gasless flow is enabled.\n *\n * @param messenger - Controller messenger.\n * @returns True if the execute flow is enabled.\n */\nexport function isRelayExecuteEnabled(\n messenger: TransactionPayControllerMessenger,\n): boolean {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const featureFlags =\n (state.remoteFeatureFlags?.confirmations_pay_extended as\n | FeatureFlagsExtendedRaw\n | undefined) ?? {};\n return featureFlags.payStrategies?.relay?.gaslessEnabled ?? false;\n}\n\n/**\n * Whether Relay quote validation is enabled.\n *\n * Acts as an emergency kill switch: when disabled (default), Relay quotes are\n * surfaced without being simulated/validated.\n *\n * @param messenger - Controller messenger.\n * @returns True if Relay quote validation is enabled.\n */\nexport function isRelayValidationEnabled(\n messenger: TransactionPayControllerMessenger,\n): boolean {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const featureFlags =\n (state.remoteFeatureFlags?.confirmations_pay_extended as\n | FeatureFlagsExtendedRaw\n | undefined) ?? {};\n return featureFlags.payStrategies?.relay?.validationEnabled ?? false;\n}\n\n/**\n * Whether a chain is excluded from preferring Infura for balance queries.\n *\n * When a chain ID appears in the `confirmations_pay_extended.excludeChainIdsFromInfura`\n * feature flag array, the Infura RPC endpoint should not be forced for that chain.\n *\n * @param messenger - Controller messenger.\n * @param chainId - Chain ID to check.\n * @returns True if the chain should skip the Infura preference.\n */\nexport function isChainExcludedFromInfura(\n messenger: TransactionPayControllerMessenger,\n chainId: Hex,\n): boolean {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const featureFlags =\n (state.remoteFeatureFlags?.confirmations_pay_extended as\n | FeatureFlagsExtendedRaw\n | undefined) ?? {};\n\n const excludedChains = featureFlags.excludeChainIdsFromInfura ?? [];\n\n return excludedChains.some(\n (excluded) => excluded.toLowerCase() === chainId.toLowerCase(),\n );\n}\n\n/**\n * Get the origin gas overhead to include in Relay quote requests\n * for EIP-7702 chains.\n *\n * @param messenger - Controller messenger.\n * @returns Origin gas overhead as a decimal string.\n */\nexport function getRelayOriginGasOverhead(\n messenger: TransactionPayControllerMessenger,\n): string {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const featureFlags =\n (state.remoteFeatureFlags?.confirmations_pay as\n | FeatureFlagsRaw\n | undefined) ?? {};\n return (\n featureFlags.payStrategies?.relay?.originGasOverhead ??\n DEFAULT_RELAY_ORIGIN_GAS_OVERHEAD\n );\n}\n\n/**\n * Get the relay status polling interval in milliseconds.\n * Falls back to the constant default when not configured.\n *\n * @param messenger - Controller messenger.\n * @returns Polling interval in milliseconds.\n */\nexport function getRelayPollingInterval(\n messenger: TransactionPayControllerMessenger,\n): number {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const featureFlags =\n (state.remoteFeatureFlags?.confirmations_pay as\n | FeatureFlagsRaw\n | undefined) ?? {};\n return (\n featureFlags.payStrategies?.relay?.pollingInterval ?? RELAY_POLLING_INTERVAL\n );\n}\n\n/**\n * Get the relay status polling timeout in milliseconds.\n * Returns 0 or undefined to indicate no timeout.\n *\n * @param messenger - Controller messenger.\n * @returns Polling timeout in milliseconds, or undefined when not configured.\n */\nexport function getRelayPollingTimeout(\n messenger: TransactionPayControllerMessenger,\n): number | undefined {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const featureFlags =\n (state.remoteFeatureFlags?.confirmations_pay as\n | FeatureFlagsRaw\n | undefined) ?? {};\n return featureFlags.payStrategies?.relay?.pollingTimeout;\n}\n\n/**\n * Get the server strategy status polling interval in milliseconds.\n *\n * @param messenger - Controller messenger.\n * @returns Polling interval in milliseconds.\n */\nexport function getServerPollingInterval(\n messenger: TransactionPayControllerMessenger,\n): number {\n return getPayStrategiesConfig(messenger).server.pollingInterval;\n}\n\n/**\n * Get the server strategy status polling timeout in milliseconds.\n *\n * @param messenger - Controller messenger.\n * @returns Polling timeout in milliseconds, or undefined when not configured.\n */\nexport function getServerPollingTimeout(\n messenger: TransactionPayControllerMessenger,\n): number | undefined {\n return getPayStrategiesConfig(messenger).server.pollingTimeout;\n}\n\n/**\n * Get fallback gas limits for quote/submit flows.\n *\n * @param messenger - Controller messenger.\n * @returns Fallback gas limits.\n */\nexport function getFallbackGas(\n messenger: TransactionPayControllerMessenger,\n): FeatureFlags['relayFallbackGas'] {\n return getFeatureFlags(messenger).relayFallbackGas;\n}\n\n/**\n * Get the gas buffer value for a specific chain ID.\n *\n * @param messenger - Controller messenger.\n * @param chainId - Chain ID to get gas buffer for.\n * @returns Gas buffer value.\n */\nexport function getGasBuffer(\n messenger: TransactionPayControllerMessenger,\n chainId: Hex,\n): number {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const featureFlags =\n (state.remoteFeatureFlags?.confirmations_pay as\n | FeatureFlagsRaw\n | undefined) ?? {};\n\n return (\n featureFlags.gasBuffer?.perChainConfig?.[chainId]?.buffer ??\n featureFlags.gasBuffer?.default ??\n DEFAULT_GAS_BUFFER\n );\n}\n\n/**\n * Get the slippage value for a specific chain ID and token address.\n * Falls back to the general slippage feature flag, then the static default.\n *\n * @param messenger - Controller messenger.\n * @param chainId - Chain ID to get slippage for.\n * @param tokenAddress - Token address to get slippage for.\n * @returns Slippage value as a decimal (e.g., 0.005 for 0.5%).\n */\nexport function getSlippage(\n messenger: TransactionPayControllerMessenger,\n chainId: Hex,\n tokenAddress: Hex,\n): number {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const featureFlags =\n (state.remoteFeatureFlags?.confirmations_pay as\n | FeatureFlagsRaw\n | undefined) ?? {};\n const { slippageTokens } = featureFlags;\n\n const tokenMap = getCaseInsensitive(slippageTokens, chainId);\n const tokenSlippage = getCaseInsensitive(tokenMap, tokenAddress);\n\n if (tokenSlippage !== undefined) {\n log('Using token-specific slippage', {\n chainId,\n tokenAddress,\n slippage: tokenSlippage,\n });\n return tokenSlippage;\n }\n\n const slippage = featureFlags.slippage ?? DEFAULT_SLIPPAGE;\n log('Using default slippage', { chainId, tokenAddress, slippage });\n return slippage;\n}\n\n/**\n * Get the AssetsUnifyState feature flag state.\n *\n * @param messenger - Controller messenger.\n * @returns True if the assets unify state feature is enabled, false otherwise.\n */\nexport function getAssetsUnifyStateFeature(\n messenger: TransactionPayControllerMessenger,\n): boolean {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const assetsUnifyState = state.remoteFeatureFlags.assetsUnifyState as\n | {\n enabled: boolean;\n featureVersion: string | null;\n }\n | undefined;\n\n const AssetsUnifyStateFeatureVersion = '1';\n\n return (\n Boolean(assetsUnifyState?.enabled) &&\n assetsUnifyState?.featureVersion === AssetsUnifyStateFeatureVersion\n );\n}\n\n/**\n * Get a value from a record using a case-insensitive key lookup.\n *\n * @param record - The record to search.\n * @param key - The key to look up (case-insensitive).\n * @returns The value if found, undefined otherwise.\n */\nfunction getCaseInsensitive<Value>(\n record: Record<string, Value> | undefined,\n key: string,\n): Value | undefined {\n if (!record) {\n return undefined;\n }\n\n const normalizedKey = key.toLowerCase();\n const entry = Object.entries(record).find(\n ([k]) => k.toLowerCase() === normalizedKey,\n );\n\n return entry?.[1];\n}\n\n/**\n * Get the fiat asset for a specific transaction type.\n *\n * Resolution order:\n * 1. Feature flag override (`confirmations_pay_fiat.assetPerTransactionType`)\n * 2. Hardcoded constant (`FIAT_ASSET_ID_BY_TX_TYPE`)\n * 3. ETH mainnet fallback\n *\n * @param messenger - Controller messenger.\n * @param transactionType - Transaction type to look up.\n * @returns The fiat asset for the given transaction type.\n */\nexport function getFiatAssetPerTransactionType(\n messenger: TransactionPayControllerMessenger,\n transactionType?: TransactionType,\n): TransactionPayFiatAsset {\n if (!transactionType) {\n return ETH_MAINNET_FIAT_ASSET;\n }\n\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const fiatFlags = state.remoteFeatureFlags?.confirmations_pay_fiat as\n | FiatFlags\n | undefined;\n\n return (\n fiatFlags?.assetPerTransactionType?.[transactionType] ??\n FIAT_ASSET_ID_BY_TX_TYPE[transactionType] ??\n ETH_MAINNET_FIAT_ASSET\n );\n}\n\n/**\n * Get the enabled fiat transaction types.\n *\n * @param messenger - Controller messenger.\n * @returns The enabled fiat transaction types.\n */\nexport function getFiatEnabledTypes(\n messenger: TransactionPayControllerMessenger,\n): TransactionType[] {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const fiatFlags = state.remoteFeatureFlags?.confirmations_pay_fiat as\n | FiatFlags\n | undefined;\n\n return fiatFlags?.enabledTransactionTypes ?? FIAT_ENABLED_TYPES;\n}\n\n/**\n * Returns the fee reserve multiplier for fiat three-phase submit.\n *\n * Controls how much of the original relay fee is reserved from the discovery\n * quote source amount to prevent EXACT_OUTPUT cost overruns.\n *\n * @param messenger - Controller messenger.\n * @returns The fee reserve multiplier.\n */\nexport function getFiatFeeReserveMultiplier(\n messenger: TransactionPayControllerMessenger,\n): number {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const fiatFlags = state.remoteFeatureFlags?.confirmations_pay_fiat as\n | FiatFlags\n | undefined;\n\n const multiplier = fiatFlags?.feeReserveMultiplier;\n\n return typeof multiplier === 'number' && multiplier > 0\n ? multiplier\n : DEFAULT_FEE_RESERVE_MULTIPLIER;\n}\n\n/**\n * Returns the maximum allowed relay rate drift percentage for fiat submit.\n *\n * Controls how much the relay exchange rate can drift between the original\n * quoting phase and the post-settlement discovery quote before failing.\n * Defaults to 10%.\n *\n * @param messenger - Controller messenger.\n * @returns The maximum rate drift percentage.\n */\nexport function getFiatMaxRateDriftPercent(\n messenger: TransactionPayControllerMessenger,\n): number {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const fiatFlags = state.remoteFeatureFlags?.confirmations_pay_fiat as\n | FiatFlags\n | undefined;\n\n const maxDrift = fiatFlags?.maxRateDriftPercent;\n\n return typeof maxDrift === 'number' && maxDrift > 0\n ? maxDrift\n : DEFAULT_MAX_RATE_DRIFT_PERCENT;\n}\n\nexport function getDirectMoneyMusdEnabled(\n messenger: TransactionPayControllerMessenger,\n): boolean {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const fiatFlags = state.remoteFeatureFlags?.confirmations_pay_fiat as\n | FiatFlags\n | undefined;\n return fiatFlags?.directMoneyMusdEnabled === true;\n}\n\nexport function getFiatVaultDisabled(\n messenger: TransactionPayControllerMessenger,\n): boolean {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const fiatFlags = state.remoteFeatureFlags?.confirmations_pay_fiat as\n | FiatFlags\n | undefined;\n return fiatFlags?.vaultDisabled === true;\n}\n\n/**\n * Returns the fiat order poll interval in milliseconds.\n *\n * Controls how frequently the fiat order status is polled during\n * the on-ramp completion wait loop. Defaults to 1 000 ms.\n *\n * @param messenger - Controller messenger.\n * @returns The poll interval in milliseconds.\n */\nexport function getFiatOrderPollIntervalMs(\n messenger: TransactionPayControllerMessenger,\n): number {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const fiatFlags = state.remoteFeatureFlags?.confirmations_pay_fiat as\n | FiatFlags\n | undefined;\n\n const interval = fiatFlags?.orderPollIntervalMs;\n\n return typeof interval === 'number' && interval > 0\n ? interval\n : DEFAULT_ORDER_POLL_INTERVAL_MS;\n}\n\n/**\n * Returns the fiat order poll timeout in milliseconds.\n *\n * Controls how long the fiat order polling loop waits for a terminal\n * status before timing out. Defaults to 600 000 ms (10 minutes).\n *\n * @param messenger - Controller messenger.\n * @returns The poll timeout in milliseconds.\n */\nexport function getFiatOrderPollTimeoutMs(\n messenger: TransactionPayControllerMessenger,\n): number {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const fiatFlags = state.remoteFeatureFlags?.confirmations_pay_fiat as\n | FiatFlags\n | undefined;\n\n const timeout = fiatFlags?.orderPollTimeoutMs;\n\n return typeof timeout === 'number' && timeout > 0\n ? timeout\n : DEFAULT_ORDER_POLL_TIMEOUT_MS;\n}\n\n/**\n * Get the HyperLiquid activation-fee configuration from the\n * `confirmations_pay_post_quote` feature flag for a transaction type.\n *\n * Resolves the transaction type's\n * `overrides.<transactionType>.hyperliquidActivationFee`, falling back to\n * `default.hyperliquidActivationFee`.\n *\n * When enabled, an unactivated HyperCore account withdrawing via Pay has the\n * one-time activation fee reserved from the amount sent to HyperLiquid (so the\n * `sendAsset` step retains enough balance) and surfaced as part of the\n * provider fee. Defaults to disabled with a $1 fee.\n *\n * @param messenger - Controller messenger.\n * @param transactionType - Parent transaction type used to resolve overrides.\n * @returns The activation-fee configuration.\n */\nexport function getHyperliquidActivationFeeConfig(\n messenger: TransactionPayControllerMessenger,\n transactionType?: string,\n): HyperliquidActivationFeeConfig {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const featureFlags = state.remoteFeatureFlags\n ?.confirmations_pay_post_quote as PostQuoteFeatureFlags | undefined;\n\n const override = transactionType\n ? featureFlags?.overrides?.[transactionType]\n : undefined;\n const config =\n override?.hyperliquidActivationFee ??\n featureFlags?.default?.hyperliquidActivationFee;\n\n const { amountUsd } = config ?? {};\n\n return {\n enabled: config?.enabled ?? false,\n amountUsd:\n typeof amountUsd === 'number' && amountUsd > 0\n ? amountUsd\n : DEFAULT_HYPERLIQUID_ACTIVATION_FEE_USD,\n };\n}\n\n/**\n * Checks if a chain supports EIP-7702.\n *\n * @param messenger - Controller messenger.\n * @param chainId - Chain ID to check.\n * @returns Whether the chain supports EIP-7702.\n */\nexport function isEIP7702Chain(\n messenger: TransactionPayControllerMessenger,\n chainId: Hex,\n): boolean {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const eip7702Flags = state.remoteFeatureFlags.confirmations_eip_7702 as\n | EIP7702FeatureFlag\n | undefined;\n\n const supportedChains = eip7702Flags?.supportedChains ?? [];\n\n return supportedChains.some(\n (supported) => supported.toLowerCase() === chainId.toLowerCase(),\n );\n}\n\n/**\n * Get the EIP-7702 upgrade contract address for a chain from the\n * `confirmations_eip_7702.contracts` feature flag, if any.\n *\n * @param messenger - Controller messenger.\n * @param chainId - Chain ID to resolve the upgrade contract for.\n * @returns The upgrade contract address, or `undefined` when none is set.\n */\nexport function getEIP7702UpgradeContractAddress(\n messenger: TransactionPayControllerMessenger,\n chainId: Hex,\n): Hex | undefined {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const eip7702Flags = state.remoteFeatureFlags.confirmations_eip_7702 as\n | EIP7702FeatureFlag\n | undefined;\n\n const contracts = getCaseInsensitive(eip7702Flags?.contracts, chainId);\n\n return contracts?.[0]?.address;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"feature-flags.mjs","sourceRoot":"","sources":["../../src/utils/feature-flags.ts"],"names":[],"mappings":"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","sourcesContent":["import { hasTransactionType } from '@metamask/transaction-controller';\nimport type {\n TransactionMeta,\n TransactionType,\n} from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\nimport { uniq } from 'lodash';\n\nimport {\n isTransactionPayStrategy,\n STABLECOINS,\n TransactionPayStrategy,\n} from '../constants.js';\nimport { projectLogger } from '../logger.js';\nimport type { TransactionPayFiatAsset } from '../strategy/fiat/constants.js';\nimport {\n ETH_MAINNET_FIAT_ASSET,\n FIAT_ASSET_ID_BY_TX_TYPE,\n FIAT_ENABLED_TYPES,\n} from '../strategy/fiat/constants.js';\nimport {\n RELAY_EXECUTE_URL,\n RELAY_POLLING_INTERVAL,\n RELAY_QUOTE_URL,\n} from '../strategy/relay/constants.js';\nimport {\n SERVER_POLLING_INTERVAL,\n SERVER_URL_BASE,\n} from '../strategy/server/constants.js';\nimport type { TransactionPayControllerMessenger } from '../types.js';\n\nconst log = createModuleLogger(projectLogger, 'feature-flags');\n\ntype StrategyOrder = TransactionPayStrategy[];\n\nexport const DEFAULT_FEE_RESERVE_MULTIPLIER = 1.2;\nexport const DEFAULT_MAX_RATE_DRIFT_PERCENT = 10;\nexport const DEFAULT_ORDER_POLL_INTERVAL_MS = 1000;\nexport const DEFAULT_ORDER_POLL_TIMEOUT_MS = 10 * 60 * 1000;\n\nexport const DEFAULT_GAS_BUFFER = 1.0;\nexport const DEFAULT_FALLBACK_GAS_ESTIMATE = 900000;\nexport const DEFAULT_FALLBACK_GAS_MAX = 1500000;\nexport const DEFAULT_RELAY_EXECUTE_URL = RELAY_EXECUTE_URL;\nexport const DEFAULT_RELAY_QUOTE_URL = RELAY_QUOTE_URL;\nexport const DEFAULT_RELAY_ORIGIN_GAS_OVERHEAD = '300000';\nexport const DEFAULT_SLIPPAGE = 0.005;\nexport const DEFAULT_HYPERLIQUID_ACTIVATION_FEE_USD = 1;\nexport const DEFAULT_ACROSS_API_BASE = 'https://app.across.to/api';\nexport const DEFAULT_SERVER_BASE_URL = SERVER_URL_BASE;\nexport const DEFAULT_STRATEGY_ORDER: StrategyOrder = [\n TransactionPayStrategy.Server,\n TransactionPayStrategy.Relay,\n TransactionPayStrategy.Across,\n];\n\ntype FeatureFlagsRaw = {\n gasBuffer?: {\n default?: number;\n perChainConfig?: Record<\n Hex,\n {\n name?: string;\n buffer?: number;\n }\n >;\n };\n relayDisabledGasStationChains?: Hex[];\n relayExecuteUrl?: string;\n relayFallbackGas?: {\n estimate?: number;\n max?: number;\n };\n relayQuoteUrl?: string;\n slippage?: number;\n slippageTokens?: Record<Hex, Record<Hex, number>>;\n strategyOrder?: string[];\n strategyOverrides?: StrategyOverridesRaw;\n payStrategies?: PayStrategiesConfigRaw;\n};\n\ntype StrategyOverrideRaw = {\n default?: unknown;\n chains?: Record<string, unknown>;\n tokens?: Record<string, Record<string, unknown>>;\n};\n\ntype StrategyOverridesRaw = {\n default?: StrategyOverrideRaw;\n transactionTypes?: Record<string, StrategyOverrideRaw>;\n};\n\ntype StrategyOverride = {\n chains: Record<Hex, TransactionPayStrategy[]>;\n default?: TransactionPayStrategy[];\n tokens: Record<Hex, Record<Hex, TransactionPayStrategy[]>>;\n};\n\ntype StrategyOverrides = {\n default?: StrategyOverride;\n transactionTypes: Record<string, StrategyOverride>;\n};\n\ntype FiatFlags = {\n assetPerTransactionType?: Partial<\n Record<TransactionType, TransactionPayFiatAsset>\n >;\n directMoneyMusdEnabled?: boolean;\n enabledTransactionTypes: TransactionType[];\n feeReserveMultiplier?: number;\n maxRateDriftPercent?: number;\n orderPollIntervalMs?: number;\n orderPollTimeoutMs?: number;\n vaultDisabled?: boolean;\n};\n\ntype HyperliquidActivationFeeFlag = {\n enabled?: boolean;\n amountUsd?: number;\n};\n\ntype PostQuoteConfig = {\n hyperliquidActivationFee?: HyperliquidActivationFeeFlag;\n};\n\ntype PostQuoteFeatureFlags = {\n default?: PostQuoteConfig;\n overrides?: Record<string, PostQuoteConfig>;\n};\n\nexport type HyperliquidActivationFeeConfig = {\n enabled: boolean;\n amountUsd: number;\n};\n\ntype StrategyRoutingConfig = {\n payStrategies: {\n across: {\n enabled: boolean;\n };\n server: {\n enabled: boolean;\n };\n relay: {\n enabled: boolean;\n };\n };\n strategyOverrides: StrategyOverrides;\n strategyOrder: TransactionPayStrategy[];\n};\n\nexport type FeatureFlags = {\n relayDisabledGasStationChains: Hex[];\n relayExecuteUrl: string;\n relayFallbackGas: {\n estimate: number;\n max: number;\n };\n relayQuoteUrl: string;\n slippage: number;\n};\n\nexport type AcrossConfigRaw = {\n apiBase?: string;\n enabled?: boolean;\n fallbackGas?: {\n estimate?: number;\n max?: number;\n };\n};\n\nexport type AcrossConfig = {\n apiBase: string;\n enabled: boolean;\n fallbackGas: {\n estimate: number;\n max: number;\n };\n};\n\nexport type PayStrategiesConfigRaw = {\n across?: AcrossConfigRaw;\n relay?: {\n enabled?: boolean;\n originGasOverhead?: string;\n pollingInterval?: number;\n pollingTimeout?: number;\n };\n};\n\nexport type RelayValidationEnabledConfig = {\n default?: boolean;\n transactionTypes?: Partial<Record<TransactionType, boolean>>;\n};\n\ntype FeatureFlagsExtendedRaw = {\n excludeChainIdsFromInfura?: Hex[];\n payStrategies?: {\n relay?: {\n gaslessEnabled?: boolean;\n validationEnabled?: RelayValidationEnabledConfig;\n };\n server?: {\n enabled?: boolean;\n baseUrl?: string;\n pollingInterval?: number;\n pollingTimeout?: number;\n };\n };\n};\n\ntype EIP7702FeatureFlag = {\n contracts?: Record<Hex, { address: Hex; signature: Hex }[]>;\n supportedChains?: Hex[];\n};\n\nexport type PayStrategiesConfig = {\n across: AcrossConfig;\n server: {\n enabled: boolean;\n baseUrl: string;\n pollingInterval: number;\n pollingTimeout?: number;\n };\n relay: {\n enabled: boolean;\n };\n};\n\nfunction normalizeHex(value: string | undefined): Hex | undefined {\n return value?.toLowerCase() as Hex | undefined;\n}\n\nfunction normalizeStrategy(\n strategy: unknown,\n): TransactionPayStrategy | undefined {\n if (typeof strategy !== 'string') {\n return undefined;\n }\n\n const normalizedStrategy = strategy.toLowerCase() as TransactionPayStrategy;\n\n return isTransactionPayStrategy(normalizedStrategy)\n ? normalizedStrategy\n : undefined;\n}\n\nfunction normalizeStrategyList(strategies: unknown): TransactionPayStrategy[] {\n if (!Array.isArray(strategies)) {\n return [];\n }\n\n return uniq(\n strategies\n .map((strategy) => normalizeStrategy(strategy))\n .filter(\n (strategy): strategy is TransactionPayStrategy =>\n strategy !== undefined,\n ),\n );\n}\n\nfunction normalizeStrategyOverride(\n override: StrategyOverrideRaw | undefined,\n): StrategyOverride {\n const chains = Object.entries(override?.chains ?? {}).reduce<\n Record<Hex, TransactionPayStrategy[]>\n >((result, [chainId, strategies]) => {\n const normalizedStrategies = normalizeStrategyList(strategies);\n\n if (normalizedStrategies.length) {\n result[normalizeHex(chainId) as Hex] = normalizedStrategies;\n }\n\n return result;\n }, {});\n\n const tokens = Object.entries(override?.tokens ?? {}).reduce<\n Record<Hex, Record<Hex, TransactionPayStrategy[]>>\n >((result, [chainId, tokenOverrides]) => {\n const normalizedTokenOverrides = Object.entries(\n tokenOverrides ?? {},\n ).reduce<Record<Hex, TransactionPayStrategy[]>>(\n (tokenResult, [tokenAddress, strategies]) => {\n const normalizedStrategies = normalizeStrategyList(strategies);\n\n if (normalizedStrategies.length) {\n tokenResult[normalizeHex(tokenAddress) as Hex] = normalizedStrategies;\n }\n\n return tokenResult;\n },\n {},\n );\n\n if (Object.keys(normalizedTokenOverrides).length) {\n result[normalizeHex(chainId) as Hex] = normalizedTokenOverrides;\n }\n\n return result;\n }, {});\n\n const defaultStrategies = normalizeStrategyList(override?.default);\n\n return {\n chains,\n default: defaultStrategies.length ? defaultStrategies : undefined,\n tokens,\n };\n}\n\nfunction normalizeStrategyRoutingConfig(\n featureFlags: FeatureFlagsRaw,\n extendedFeatureFlags: FeatureFlagsExtendedRaw,\n): StrategyRoutingConfig {\n const strategyOrder = normalizeStrategyList(featureFlags.strategyOrder);\n\n return {\n payStrategies: {\n across: {\n enabled: featureFlags.payStrategies?.across?.enabled ?? false,\n },\n server: {\n enabled: extendedFeatureFlags.payStrategies?.server?.enabled ?? false,\n },\n relay: {\n enabled: featureFlags.payStrategies?.relay?.enabled ?? true,\n },\n },\n strategyOverrides: {\n default: featureFlags.strategyOverrides?.default\n ? normalizeStrategyOverride(featureFlags.strategyOverrides.default)\n : undefined,\n transactionTypes: Object.entries(\n featureFlags.strategyOverrides?.transactionTypes ?? {},\n ).reduce<Record<string, StrategyOverride>>((result, [type, override]) => {\n result[type] = normalizeStrategyOverride(override);\n return result;\n }, {}),\n },\n strategyOrder:\n strategyOrder.length > 0 ? strategyOrder : [...DEFAULT_STRATEGY_ORDER],\n };\n}\n\nfunction getStrategyRoutingConfig(\n messenger: TransactionPayControllerMessenger,\n): StrategyRoutingConfig {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const featureFlags = state.remoteFeatureFlags?.confirmations_pay as\n | FeatureFlagsRaw\n | undefined;\n const extendedFeatureFlags =\n (state.remoteFeatureFlags?.confirmations_pay_extended as\n | FeatureFlagsExtendedRaw\n | undefined) ?? {};\n\n return normalizeStrategyRoutingConfig(\n featureFlags ?? {},\n extendedFeatureFlags,\n );\n}\n\nfunction filterEnabledStrategies(\n strategies: readonly TransactionPayStrategy[],\n routingConfig: StrategyRoutingConfig,\n): TransactionPayStrategy[] {\n return strategies.filter((strategy) => {\n if (strategy === TransactionPayStrategy.Across) {\n return routingConfig.payStrategies.across.enabled;\n }\n\n if (strategy === TransactionPayStrategy.Relay) {\n return routingConfig.payStrategies.relay.enabled;\n }\n\n if (strategy === TransactionPayStrategy.Server) {\n return routingConfig.payStrategies.server.enabled;\n }\n\n return true;\n });\n}\n\nfunction getTokenOverrideStrategies(\n override: StrategyOverride | undefined,\n normalizedChainId: Hex | undefined,\n normalizedTokenAddress: Hex | undefined,\n): readonly TransactionPayStrategy[] | undefined {\n if (!override || !normalizedChainId || !normalizedTokenAddress) {\n return undefined;\n }\n\n return override.tokens[normalizedChainId]?.[normalizedTokenAddress];\n}\n\nfunction getChainOverrideStrategies(\n override: StrategyOverride | undefined,\n normalizedChainId: Hex | undefined,\n): readonly TransactionPayStrategy[] | undefined {\n if (!override || !normalizedChainId) {\n return undefined;\n }\n\n return override.chains[normalizedChainId];\n}\n\nfunction getDefaultOverrideStrategies(\n override: StrategyOverride | undefined,\n): readonly TransactionPayStrategy[] | undefined {\n return override?.default;\n}\n\n/**\n * Get ordered list of strategies to try for a route.\n *\n * @param messenger - Controller messenger.\n * @param chainId - Optional chain ID used to match route overrides.\n * @param tokenAddress - Optional token address used to match route overrides.\n * @param transactionType - Optional transaction type used to match route\n * overrides.\n * @param fiatPaymentMethodId - Optional fiat payment method ID used to match route overrides.\n * @returns Ordered strategy list.\n */\nexport function getStrategyOrder(\n messenger: TransactionPayControllerMessenger,\n chainId?: Hex,\n tokenAddress?: Hex,\n transactionType?: string,\n fiatPaymentMethodId?: string,\n): StrategyOrder {\n // If fiat payment method is selected, use Fiat strategy only\n if (fiatPaymentMethodId) {\n return [TransactionPayStrategy.Fiat];\n }\n\n const routingConfig = getStrategyRoutingConfig(messenger);\n const normalizedChainId = normalizeHex(chainId);\n const normalizedTokenAddress = normalizeHex(tokenAddress);\n const transactionTypeOverride = transactionType\n ? routingConfig.strategyOverrides.transactionTypes[transactionType]\n : undefined;\n\n const candidates: (readonly TransactionPayStrategy[] | undefined)[] = [\n getTokenOverrideStrategies(\n transactionTypeOverride,\n normalizedChainId,\n normalizedTokenAddress,\n ),\n getChainOverrideStrategies(transactionTypeOverride, normalizedChainId),\n getTokenOverrideStrategies(\n routingConfig.strategyOverrides.default,\n normalizedChainId,\n normalizedTokenAddress,\n ),\n getChainOverrideStrategies(\n routingConfig.strategyOverrides.default,\n normalizedChainId,\n ),\n getDefaultOverrideStrategies(transactionTypeOverride),\n getDefaultOverrideStrategies(routingConfig.strategyOverrides.default),\n ];\n\n // Overrides are authoritative. Once a route matches a specific override\n // scope, disabled strategies do not inherit candidates from lower-precedence\n // scopes.\n for (const strategies of candidates) {\n if (strategies) {\n return filterEnabledStrategies(strategies, routingConfig);\n }\n }\n\n return filterEnabledStrategies(routingConfig.strategyOrder, routingConfig);\n}\n\n/**\n * Get the preferred strategy for a route.\n *\n * @param messenger - Controller messenger.\n * @param chainId - Optional chain ID used to match route overrides.\n * @param tokenAddress - Optional token address used to match route overrides.\n * @param transactionType - Optional transaction type used to match route\n * overrides.\n * @returns The preferred strategy, if any.\n */\nexport function getStrategy(\n messenger: TransactionPayControllerMessenger,\n chainId?: Hex,\n tokenAddress?: Hex,\n transactionType?: string,\n): TransactionPayStrategy | undefined {\n return getStrategyOrder(messenger, chainId, tokenAddress, transactionType)[0];\n}\n\n/**\n * Get feature flags related to the controller.\n *\n * @param messenger - Controller messenger.\n * @returns Feature flags.\n */\nexport function getFeatureFlags(\n messenger: TransactionPayControllerMessenger,\n): FeatureFlags {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const featureFlags =\n (state.remoteFeatureFlags?.confirmations_pay as\n | FeatureFlagsRaw\n | undefined) ?? {};\n\n const estimate = new BigNumber(\n featureFlags.relayFallbackGas?.estimate ?? DEFAULT_FALLBACK_GAS_ESTIMATE,\n ).toNumber();\n\n const max = new BigNumber(\n featureFlags.relayFallbackGas?.max ?? DEFAULT_FALLBACK_GAS_MAX,\n ).toNumber();\n\n const relayExecuteUrl =\n featureFlags.relayExecuteUrl ?? DEFAULT_RELAY_EXECUTE_URL;\n\n const relayQuoteUrl = featureFlags.relayQuoteUrl ?? DEFAULT_RELAY_QUOTE_URL;\n\n const relayDisabledGasStationChains =\n featureFlags.relayDisabledGasStationChains ?? [];\n\n const slippage = featureFlags.slippage ?? DEFAULT_SLIPPAGE;\n\n const result: FeatureFlags = {\n relayDisabledGasStationChains,\n relayExecuteUrl,\n relayFallbackGas: {\n estimate,\n max,\n },\n relayQuoteUrl,\n slippage,\n };\n\n log('Feature flags:', { raw: featureFlags, result });\n\n return result;\n}\n\n/**\n * Get the stablecoins map from the `stableTokens` feature flag.\n * Falls back to the hardcoded {@link STABLECOINS} constant when the flag is\n * absent or not a valid object.\n *\n * @param messenger - Controller messenger.\n * @returns Stablecoins keyed by chain ID.\n */\nexport function getStablecoins(\n messenger: TransactionPayControllerMessenger,\n): Record<Hex, Hex[]> {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const flag = state.remoteFeatureFlags?.stableTokens;\n\n if (flag && typeof flag === 'object' && !Array.isArray(flag)) {\n const raw = flag as Record<string, string[]>;\n return Object.entries(raw).reduce<Record<Hex, Hex[]>>(\n (acc, [chainId, addresses]) => {\n if (Array.isArray(addresses)) {\n acc[chainId.toLowerCase() as Hex] = addresses.map(\n (a) => a.toLowerCase() as Hex,\n );\n }\n return acc;\n },\n {},\n );\n }\n\n return STABLECOINS;\n}\n\n/**\n * Get Pay Strategies configuration.\n *\n * @param messenger - Controller messenger.\n * @returns Pay Strategies configuration.\n */\nexport function getPayStrategiesConfig(\n messenger: TransactionPayControllerMessenger,\n): PayStrategiesConfig {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const featureFlags =\n (state.remoteFeatureFlags?.confirmations_pay as\n | FeatureFlagsRaw\n | undefined) ?? {};\n const extendedFeatureFlags =\n (state.remoteFeatureFlags?.confirmations_pay_extended as\n | FeatureFlagsExtendedRaw\n | undefined) ?? {};\n const payStrategies = featureFlags.payStrategies ?? {};\n const extendedPayStrategies = extendedFeatureFlags.payStrategies ?? {};\n\n const acrossRaw = payStrategies.across ?? {};\n const serverRaw = extendedPayStrategies.server ?? {};\n const relayRaw = payStrategies.relay ?? {};\n\n const across = {\n apiBase: acrossRaw.apiBase ?? DEFAULT_ACROSS_API_BASE,\n enabled: acrossRaw.enabled ?? false,\n fallbackGas: {\n estimate:\n acrossRaw.fallbackGas?.estimate ?? DEFAULT_FALLBACK_GAS_ESTIMATE,\n max: acrossRaw.fallbackGas?.max ?? DEFAULT_FALLBACK_GAS_MAX,\n },\n };\n\n const server = {\n enabled: serverRaw.enabled ?? false,\n baseUrl: serverRaw.baseUrl ?? DEFAULT_SERVER_BASE_URL,\n pollingInterval: serverRaw.pollingInterval ?? SERVER_POLLING_INTERVAL,\n pollingTimeout: serverRaw.pollingTimeout,\n };\n\n const relay = {\n enabled: relayRaw.enabled ?? true,\n };\n\n return {\n across,\n server,\n relay,\n };\n}\n\n/**\n * Whether the Relay /execute gasless flow is enabled.\n *\n * @param messenger - Controller messenger.\n * @returns True if the execute flow is enabled.\n */\nexport function isRelayExecuteEnabled(\n messenger: TransactionPayControllerMessenger,\n): boolean {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const featureFlags =\n (state.remoteFeatureFlags?.confirmations_pay_extended as\n | FeatureFlagsExtendedRaw\n | undefined) ?? {};\n return featureFlags.payStrategies?.relay?.gaslessEnabled ?? false;\n}\n\n/**\n * Whether Relay quote validation is enabled for a given transaction.\n *\n * Acts as an emergency kill switch: when disabled (default), Relay quotes are\n * surfaced without being simulated/validated.\n *\n * Configured via the `payStrategies.relay.validationEnabled` flag, an object\n * `{ default?: boolean; transactionTypes?: { [type]?: boolean } }`:\n * `default` is the base toggle applied to all transactions (omitted = `false`);\n * a matching `transactionTypes[type]` entry overrides `default` when the\n * transaction, or any of its nested transactions, has that type.\n *\n * @param messenger - Controller messenger.\n * @param transaction - Transaction being validated. Its top-level and nested\n * types are matched against the `transactionTypes` overrides.\n * @returns True if Relay quote validation is enabled.\n */\nexport function isRelayValidationEnabled(\n messenger: TransactionPayControllerMessenger,\n transaction?: TransactionMeta,\n): boolean {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const featureFlags =\n (state.remoteFeatureFlags?.confirmations_pay_extended as\n | FeatureFlagsExtendedRaw\n | undefined) ?? {};\n\n const validationEnabled =\n featureFlags.payStrategies?.relay?.validationEnabled;\n\n const transactionTypes = validationEnabled?.transactionTypes ?? {};\n\n // A per-type override wins over the global `default` toggle. An override\n // matches when the transaction, or any nested transaction, has that type.\n for (const [type, enabled] of Object.entries(transactionTypes)) {\n if (hasTransactionType(transaction, [type as TransactionType])) {\n return enabled;\n }\n }\n\n // `?? false`: `default` is optional, so an omitted config disables validation.\n return validationEnabled?.default ?? false;\n}\n\n/**\n * Whether a chain is excluded from preferring Infura for balance queries.\n *\n * When a chain ID appears in the `confirmations_pay_extended.excludeChainIdsFromInfura`\n * feature flag array, the Infura RPC endpoint should not be forced for that chain.\n *\n * @param messenger - Controller messenger.\n * @param chainId - Chain ID to check.\n * @returns True if the chain should skip the Infura preference.\n */\nexport function isChainExcludedFromInfura(\n messenger: TransactionPayControllerMessenger,\n chainId: Hex,\n): boolean {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const featureFlags =\n (state.remoteFeatureFlags?.confirmations_pay_extended as\n | FeatureFlagsExtendedRaw\n | undefined) ?? {};\n\n const excludedChains = featureFlags.excludeChainIdsFromInfura ?? [];\n\n return excludedChains.some(\n (excluded) => excluded.toLowerCase() === chainId.toLowerCase(),\n );\n}\n\n/**\n * Get the origin gas overhead to include in Relay quote requests\n * for EIP-7702 chains.\n *\n * @param messenger - Controller messenger.\n * @returns Origin gas overhead as a decimal string.\n */\nexport function getRelayOriginGasOverhead(\n messenger: TransactionPayControllerMessenger,\n): string {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const featureFlags =\n (state.remoteFeatureFlags?.confirmations_pay as\n | FeatureFlagsRaw\n | undefined) ?? {};\n return (\n featureFlags.payStrategies?.relay?.originGasOverhead ??\n DEFAULT_RELAY_ORIGIN_GAS_OVERHEAD\n );\n}\n\n/**\n * Get the relay status polling interval in milliseconds.\n * Falls back to the constant default when not configured.\n *\n * @param messenger - Controller messenger.\n * @returns Polling interval in milliseconds.\n */\nexport function getRelayPollingInterval(\n messenger: TransactionPayControllerMessenger,\n): number {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const featureFlags =\n (state.remoteFeatureFlags?.confirmations_pay as\n | FeatureFlagsRaw\n | undefined) ?? {};\n return (\n featureFlags.payStrategies?.relay?.pollingInterval ?? RELAY_POLLING_INTERVAL\n );\n}\n\n/**\n * Get the relay status polling timeout in milliseconds.\n * Returns 0 or undefined to indicate no timeout.\n *\n * @param messenger - Controller messenger.\n * @returns Polling timeout in milliseconds, or undefined when not configured.\n */\nexport function getRelayPollingTimeout(\n messenger: TransactionPayControllerMessenger,\n): number | undefined {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const featureFlags =\n (state.remoteFeatureFlags?.confirmations_pay as\n | FeatureFlagsRaw\n | undefined) ?? {};\n return featureFlags.payStrategies?.relay?.pollingTimeout;\n}\n\n/**\n * Get the server strategy status polling interval in milliseconds.\n *\n * @param messenger - Controller messenger.\n * @returns Polling interval in milliseconds.\n */\nexport function getServerPollingInterval(\n messenger: TransactionPayControllerMessenger,\n): number {\n return getPayStrategiesConfig(messenger).server.pollingInterval;\n}\n\n/**\n * Get the server strategy status polling timeout in milliseconds.\n *\n * @param messenger - Controller messenger.\n * @returns Polling timeout in milliseconds, or undefined when not configured.\n */\nexport function getServerPollingTimeout(\n messenger: TransactionPayControllerMessenger,\n): number | undefined {\n return getPayStrategiesConfig(messenger).server.pollingTimeout;\n}\n\n/**\n * Get fallback gas limits for quote/submit flows.\n *\n * @param messenger - Controller messenger.\n * @returns Fallback gas limits.\n */\nexport function getFallbackGas(\n messenger: TransactionPayControllerMessenger,\n): FeatureFlags['relayFallbackGas'] {\n return getFeatureFlags(messenger).relayFallbackGas;\n}\n\n/**\n * Get the gas buffer value for a specific chain ID.\n *\n * @param messenger - Controller messenger.\n * @param chainId - Chain ID to get gas buffer for.\n * @returns Gas buffer value.\n */\nexport function getGasBuffer(\n messenger: TransactionPayControllerMessenger,\n chainId: Hex,\n): number {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const featureFlags =\n (state.remoteFeatureFlags?.confirmations_pay as\n | FeatureFlagsRaw\n | undefined) ?? {};\n\n return (\n featureFlags.gasBuffer?.perChainConfig?.[chainId]?.buffer ??\n featureFlags.gasBuffer?.default ??\n DEFAULT_GAS_BUFFER\n );\n}\n\n/**\n * Get the slippage value for a specific chain ID and token address.\n * Falls back to the general slippage feature flag, then the static default.\n *\n * @param messenger - Controller messenger.\n * @param chainId - Chain ID to get slippage for.\n * @param tokenAddress - Token address to get slippage for.\n * @returns Slippage value as a decimal (e.g., 0.005 for 0.5%).\n */\nexport function getSlippage(\n messenger: TransactionPayControllerMessenger,\n chainId: Hex,\n tokenAddress: Hex,\n): number {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const featureFlags =\n (state.remoteFeatureFlags?.confirmations_pay as\n | FeatureFlagsRaw\n | undefined) ?? {};\n const { slippageTokens } = featureFlags;\n\n const tokenMap = getCaseInsensitive(slippageTokens, chainId);\n const tokenSlippage = getCaseInsensitive(tokenMap, tokenAddress);\n\n if (tokenSlippage !== undefined) {\n log('Using token-specific slippage', {\n chainId,\n tokenAddress,\n slippage: tokenSlippage,\n });\n return tokenSlippage;\n }\n\n const slippage = featureFlags.slippage ?? DEFAULT_SLIPPAGE;\n log('Using default slippage', { chainId, tokenAddress, slippage });\n return slippage;\n}\n\n/**\n * Get the AssetsUnifyState feature flag state.\n *\n * @param messenger - Controller messenger.\n * @returns True if the assets unify state feature is enabled, false otherwise.\n */\nexport function getAssetsUnifyStateFeature(\n messenger: TransactionPayControllerMessenger,\n): boolean {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const assetsUnifyState = state.remoteFeatureFlags.assetsUnifyState as\n | {\n enabled: boolean;\n featureVersion: string | null;\n }\n | undefined;\n\n const AssetsUnifyStateFeatureVersion = '1';\n\n return (\n Boolean(assetsUnifyState?.enabled) &&\n assetsUnifyState?.featureVersion === AssetsUnifyStateFeatureVersion\n );\n}\n\n/**\n * Get a value from a record using a case-insensitive key lookup.\n *\n * @param record - The record to search.\n * @param key - The key to look up (case-insensitive).\n * @returns The value if found, undefined otherwise.\n */\nfunction getCaseInsensitive<Value>(\n record: Record<string, Value> | undefined,\n key: string,\n): Value | undefined {\n if (!record) {\n return undefined;\n }\n\n const normalizedKey = key.toLowerCase();\n const entry = Object.entries(record).find(\n ([k]) => k.toLowerCase() === normalizedKey,\n );\n\n return entry?.[1];\n}\n\n/**\n * Get the fiat asset for a specific transaction type.\n *\n * Resolution order:\n * 1. Feature flag override (`confirmations_pay_fiat.assetPerTransactionType`)\n * 2. Hardcoded constant (`FIAT_ASSET_ID_BY_TX_TYPE`)\n * 3. ETH mainnet fallback\n *\n * @param messenger - Controller messenger.\n * @param transactionType - Transaction type to look up.\n * @returns The fiat asset for the given transaction type.\n */\nexport function getFiatAssetPerTransactionType(\n messenger: TransactionPayControllerMessenger,\n transactionType?: TransactionType,\n): TransactionPayFiatAsset {\n if (!transactionType) {\n return ETH_MAINNET_FIAT_ASSET;\n }\n\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const fiatFlags = state.remoteFeatureFlags?.confirmations_pay_fiat as\n | FiatFlags\n | undefined;\n\n return (\n fiatFlags?.assetPerTransactionType?.[transactionType] ??\n FIAT_ASSET_ID_BY_TX_TYPE[transactionType] ??\n ETH_MAINNET_FIAT_ASSET\n );\n}\n\n/**\n * Get the enabled fiat transaction types.\n *\n * @param messenger - Controller messenger.\n * @returns The enabled fiat transaction types.\n */\nexport function getFiatEnabledTypes(\n messenger: TransactionPayControllerMessenger,\n): TransactionType[] {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const fiatFlags = state.remoteFeatureFlags?.confirmations_pay_fiat as\n | FiatFlags\n | undefined;\n\n return fiatFlags?.enabledTransactionTypes ?? FIAT_ENABLED_TYPES;\n}\n\n/**\n * Returns the fee reserve multiplier for fiat three-phase submit.\n *\n * Controls how much of the original relay fee is reserved from the discovery\n * quote source amount to prevent EXACT_OUTPUT cost overruns.\n *\n * @param messenger - Controller messenger.\n * @returns The fee reserve multiplier.\n */\nexport function getFiatFeeReserveMultiplier(\n messenger: TransactionPayControllerMessenger,\n): number {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const fiatFlags = state.remoteFeatureFlags?.confirmations_pay_fiat as\n | FiatFlags\n | undefined;\n\n const multiplier = fiatFlags?.feeReserveMultiplier;\n\n return typeof multiplier === 'number' && multiplier > 0\n ? multiplier\n : DEFAULT_FEE_RESERVE_MULTIPLIER;\n}\n\n/**\n * Returns the maximum allowed relay rate drift percentage for fiat submit.\n *\n * Controls how much the relay exchange rate can drift between the original\n * quoting phase and the post-settlement discovery quote before failing.\n * Defaults to 10%.\n *\n * @param messenger - Controller messenger.\n * @returns The maximum rate drift percentage.\n */\nexport function getFiatMaxRateDriftPercent(\n messenger: TransactionPayControllerMessenger,\n): number {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const fiatFlags = state.remoteFeatureFlags?.confirmations_pay_fiat as\n | FiatFlags\n | undefined;\n\n const maxDrift = fiatFlags?.maxRateDriftPercent;\n\n return typeof maxDrift === 'number' && maxDrift > 0\n ? maxDrift\n : DEFAULT_MAX_RATE_DRIFT_PERCENT;\n}\n\nexport function getDirectMoneyMusdEnabled(\n messenger: TransactionPayControllerMessenger,\n): boolean {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const fiatFlags = state.remoteFeatureFlags?.confirmations_pay_fiat as\n | FiatFlags\n | undefined;\n return fiatFlags?.directMoneyMusdEnabled === true;\n}\n\nexport function getFiatVaultDisabled(\n messenger: TransactionPayControllerMessenger,\n): boolean {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const fiatFlags = state.remoteFeatureFlags?.confirmations_pay_fiat as\n | FiatFlags\n | undefined;\n return fiatFlags?.vaultDisabled === true;\n}\n\n/**\n * Returns the fiat order poll interval in milliseconds.\n *\n * Controls how frequently the fiat order status is polled during\n * the on-ramp completion wait loop. Defaults to 1 000 ms.\n *\n * @param messenger - Controller messenger.\n * @returns The poll interval in milliseconds.\n */\nexport function getFiatOrderPollIntervalMs(\n messenger: TransactionPayControllerMessenger,\n): number {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const fiatFlags = state.remoteFeatureFlags?.confirmations_pay_fiat as\n | FiatFlags\n | undefined;\n\n const interval = fiatFlags?.orderPollIntervalMs;\n\n return typeof interval === 'number' && interval > 0\n ? interval\n : DEFAULT_ORDER_POLL_INTERVAL_MS;\n}\n\n/**\n * Returns the fiat order poll timeout in milliseconds.\n *\n * Controls how long the fiat order polling loop waits for a terminal\n * status before timing out. Defaults to 600 000 ms (10 minutes).\n *\n * @param messenger - Controller messenger.\n * @returns The poll timeout in milliseconds.\n */\nexport function getFiatOrderPollTimeoutMs(\n messenger: TransactionPayControllerMessenger,\n): number {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const fiatFlags = state.remoteFeatureFlags?.confirmations_pay_fiat as\n | FiatFlags\n | undefined;\n\n const timeout = fiatFlags?.orderPollTimeoutMs;\n\n return typeof timeout === 'number' && timeout > 0\n ? timeout\n : DEFAULT_ORDER_POLL_TIMEOUT_MS;\n}\n\n/**\n * Get the HyperLiquid activation-fee configuration from the\n * `confirmations_pay_post_quote` feature flag for a transaction type.\n *\n * Resolves the transaction type's\n * `overrides.<transactionType>.hyperliquidActivationFee`, falling back to\n * `default.hyperliquidActivationFee`.\n *\n * When enabled, an unactivated HyperCore account withdrawing via Pay has the\n * one-time activation fee reserved from the amount sent to HyperLiquid (so the\n * `sendAsset` step retains enough balance) and surfaced as part of the\n * provider fee. Defaults to disabled with a $1 fee.\n *\n * @param messenger - Controller messenger.\n * @param transactionType - Parent transaction type used to resolve overrides.\n * @returns The activation-fee configuration.\n */\nexport function getHyperliquidActivationFeeConfig(\n messenger: TransactionPayControllerMessenger,\n transactionType?: string,\n): HyperliquidActivationFeeConfig {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const featureFlags = state.remoteFeatureFlags\n ?.confirmations_pay_post_quote as PostQuoteFeatureFlags | undefined;\n\n const override = transactionType\n ? featureFlags?.overrides?.[transactionType]\n : undefined;\n const config =\n override?.hyperliquidActivationFee ??\n featureFlags?.default?.hyperliquidActivationFee;\n\n const { amountUsd } = config ?? {};\n\n return {\n enabled: config?.enabled ?? false,\n amountUsd:\n typeof amountUsd === 'number' && amountUsd > 0\n ? amountUsd\n : DEFAULT_HYPERLIQUID_ACTIVATION_FEE_USD,\n };\n}\n\n/**\n * Checks if a chain supports EIP-7702.\n *\n * @param messenger - Controller messenger.\n * @param chainId - Chain ID to check.\n * @returns Whether the chain supports EIP-7702.\n */\nexport function isEIP7702Chain(\n messenger: TransactionPayControllerMessenger,\n chainId: Hex,\n): boolean {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const eip7702Flags = state.remoteFeatureFlags.confirmations_eip_7702 as\n | EIP7702FeatureFlag\n | undefined;\n\n const supportedChains = eip7702Flags?.supportedChains ?? [];\n\n return supportedChains.some(\n (supported) => supported.toLowerCase() === chainId.toLowerCase(),\n );\n}\n\n/**\n * Get the EIP-7702 upgrade contract address for a chain from the\n * `confirmations_eip_7702.contracts` feature flag, if any.\n *\n * @param messenger - Controller messenger.\n * @param chainId - Chain ID to resolve the upgrade contract for.\n * @returns The upgrade contract address, or `undefined` when none is set.\n */\nexport function getEIP7702UpgradeContractAddress(\n messenger: TransactionPayControllerMessenger,\n chainId: Hex,\n): Hex | undefined {\n const state = messenger.call('RemoteFeatureFlagController:getState');\n const eip7702Flags = state.remoteFeatureFlags.confirmations_eip_7702 as\n | EIP7702FeatureFlag\n | undefined;\n\n const contracts = getCaseInsensitive(eip7702Flags?.contracts, chainId);\n\n return contracts?.[0]?.address;\n}\n"]}
|
|
@@ -35,15 +35,17 @@ async function validateQuoteExecution({ messenger, quote, signal, simulation, })
|
|
|
35
35
|
requiredAmount: quote.sourceAmount.raw,
|
|
36
36
|
});
|
|
37
37
|
validateRequiredSourceAmount(messenger, quote, liveBalance);
|
|
38
|
-
log('Quote source amount check passed');
|
|
39
38
|
log('Checking decoded source transfers', {
|
|
40
39
|
sourceChainId: quote.request.sourceChainId,
|
|
41
40
|
sourceTokenAddress: quote.request.sourceTokenAddress,
|
|
42
|
-
|
|
41
|
+
transactions: simulation.transactions,
|
|
43
42
|
});
|
|
44
43
|
validateDecodedSourceTransfers(messenger, quote, liveBalance, simulation.transactions);
|
|
45
|
-
log('Decoded source transfers check passed');
|
|
46
44
|
throwIfAborted(signal);
|
|
45
|
+
await validateSimulation(messenger, quote, simulation, signal);
|
|
46
|
+
}
|
|
47
|
+
exports.validateQuoteExecution = validateQuoteExecution;
|
|
48
|
+
async function validateSimulation(messenger, quote, simulation, signal) {
|
|
47
49
|
log('Starting simulation', {
|
|
48
50
|
chainId: quote.request.sourceChainId,
|
|
49
51
|
transactions: simulation.transactions,
|
|
@@ -68,7 +70,6 @@ async function validateQuoteExecution({ messenger, quote, signal, simulation, })
|
|
|
68
70
|
throw error;
|
|
69
71
|
}
|
|
70
72
|
}
|
|
71
|
-
exports.validateQuoteExecution = validateQuoteExecution;
|
|
72
73
|
function isQuoteError(error) {
|
|
73
74
|
return error instanceof QuoteError;
|
|
74
75
|
}
|
|
@@ -130,11 +131,16 @@ async function getLiveSourceBalance(quote, messenger) {
|
|
|
130
131
|
}
|
|
131
132
|
function validateRequiredSourceAmount(messenger, quote, liveBalance) {
|
|
132
133
|
if (quote.request.isPostQuote || quote.request.paymentOverride) {
|
|
134
|
+
log('Skipping quote source amount check', {
|
|
135
|
+
hasPaymentOverride: Boolean(quote.request.paymentOverride),
|
|
136
|
+
isPostQuote: Boolean(quote.request.isPostQuote),
|
|
137
|
+
});
|
|
133
138
|
return;
|
|
134
139
|
}
|
|
135
140
|
const requiredAmount = new bignumber_js_1.BigNumber(quote.sourceAmount.raw);
|
|
136
141
|
const balance = new bignumber_js_1.BigNumber(liveBalance);
|
|
137
142
|
if (balance.isGreaterThanOrEqualTo(requiredAmount)) {
|
|
143
|
+
log('Quote source amount check passed');
|
|
138
144
|
return;
|
|
139
145
|
}
|
|
140
146
|
throw new QuoteError({
|
|
@@ -144,17 +150,24 @@ function validateRequiredSourceAmount(messenger, quote, liveBalance) {
|
|
|
144
150
|
});
|
|
145
151
|
}
|
|
146
152
|
function validateDecodedSourceTransfers(messenger, quote, liveBalance, transactions) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
153
|
+
// Only valid for a single source-token transfer. Multi-step batches produce
|
|
154
|
+
// or transform the source-token balance mid-batch, so comparing against the
|
|
155
|
+
// starting balance is wrong; rely on the full simulation instead.
|
|
156
|
+
if (transactions.length !== 1 ||
|
|
157
|
+
!isSourceTokenTransfer(quote, transactions[0])) {
|
|
158
|
+
log('Skipping decoded source transfer check: not a single source-token transfer');
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
// `isSourceTokenTransfer` has already confirmed the data decodes to a
|
|
162
|
+
// transfer, so the amount is defined here.
|
|
163
|
+
const requiredAmount = decodeTransferAmount(transactions[0].data);
|
|
151
164
|
const balance = new bignumber_js_1.BigNumber(liveBalance);
|
|
152
|
-
log('Decoded source transfer
|
|
153
|
-
decodedAmounts,
|
|
165
|
+
log('Decoded source transfer amount', {
|
|
154
166
|
liveBalance,
|
|
155
167
|
requiredAmount,
|
|
156
168
|
});
|
|
157
169
|
if (balance.isGreaterThanOrEqualTo(requiredAmount)) {
|
|
170
|
+
log('Decoded source transfers check passed');
|
|
158
171
|
return;
|
|
159
172
|
}
|
|
160
173
|
throw new QuoteError({
|
|
@@ -163,19 +176,22 @@ function validateDecodedSourceTransfers(messenger, quote, liveBalance, transacti
|
|
|
163
176
|
detail: formatBalanceShortfall(messenger, quote, requiredAmount, liveBalance),
|
|
164
177
|
});
|
|
165
178
|
}
|
|
166
|
-
function
|
|
179
|
+
function isSourceTokenTransfer(quote, transaction) {
|
|
180
|
+
if (!transaction?.to || !transaction.data) {
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
167
183
|
const { sourceChainId, sourceTokenAddress } = quote.request;
|
|
168
184
|
const isNativeSource = sourceTokenAddress.toLowerCase() ===
|
|
169
185
|
(0, token_js_1.getNativeToken)(sourceChainId).toLowerCase();
|
|
170
186
|
if (isNativeSource) {
|
|
171
|
-
return
|
|
187
|
+
return false;
|
|
172
188
|
}
|
|
173
189
|
const normalizedSourceTokenAddress = (0, token_js_1.normalizeTokenAddress)(sourceTokenAddress, sourceChainId, token_js_1.TokenAddressTarget.MetaMask).toLowerCase();
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
190
|
+
const normalizedTo = (0, token_js_1.normalizeTokenAddress)(transaction.to, sourceChainId, token_js_1.TokenAddressTarget.MetaMask).toLowerCase();
|
|
191
|
+
if (normalizedTo !== normalizedSourceTokenAddress) {
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
return decodeTransferAmount(transaction.data) !== undefined;
|
|
179
195
|
}
|
|
180
196
|
function decodeTransferAmount(data) {
|
|
181
197
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.cjs","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"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","sourcesContent":["import { Interface } from '@ethersproject/abi';\nimport { abiERC20 } from '@metamask/metamask-eth-abis';\nimport type { Hex } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { createModuleLogger, projectLogger } from '../logger.js';\nimport type {\n QuoteErrorInfo,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../types.js';\nimport {\n SimulationTransaction,\n simulateQuoteTransactions,\n TransactionPaySimulationError,\n} from './simulation.js';\nimport {\n getLiveTokenBalance,\n getNativeToken,\n getTokenInfo,\n normalizeTokenAddress,\n TokenAddressTarget,\n} from './token.js';\n\nconst log = createModuleLogger(projectLogger, 'validation');\n\nconst erc20Interface = new Interface(abiERC20);\n\nexport type QuoteSimulation = {\n transactions: SimulationTransaction[];\n};\n\nexport type QuoteExecutionRequest = {\n messenger: TransactionPayControllerMessenger;\n quote: TransactionPayQuote<unknown>;\n signal?: AbortSignal;\n simulation: QuoteSimulation;\n};\n\nexport class QuoteError extends Error {\n readonly info: QuoteErrorInfo;\n\n readonly quotes?: TransactionPayQuote<unknown>[];\n\n constructor(info: QuoteErrorInfo, quotes?: TransactionPayQuote<unknown>[]) {\n super(info.message);\n this.name = 'QuoteError';\n this.info = info;\n this.quotes = quotes;\n }\n}\n\nexport async function validateQuoteExecution({\n messenger,\n quote,\n signal,\n simulation,\n}: QuoteExecutionRequest): Promise<void> {\n throwIfAborted(signal);\n\n const liveBalance = await getLiveSourceBalance(quote, messenger);\n\n log('Live source balance', {\n from: quote.request.from,\n liveBalance,\n sourceChainId: quote.request.sourceChainId,\n sourceTokenAddress: quote.request.sourceTokenAddress,\n });\n\n throwIfAborted(signal);\n\n log('Checking quote source amount', {\n hasPaymentOverride: Boolean(quote.request.paymentOverride),\n isPostQuote: Boolean(quote.request.isPostQuote),\n liveBalance,\n requiredAmount: quote.sourceAmount.raw,\n });\n\n validateRequiredSourceAmount(messenger, quote, liveBalance);\n\n log('Quote source amount check passed');\n\n log('Checking decoded source transfers', {\n sourceChainId: quote.request.sourceChainId,\n sourceTokenAddress: quote.request.sourceTokenAddress,\n transactionCount: simulation.transactions.length,\n });\n\n validateDecodedSourceTransfers(\n messenger,\n quote,\n liveBalance,\n simulation.transactions,\n );\n\n log('Decoded source transfers check passed');\n\n throwIfAborted(signal);\n\n log('Starting simulation', {\n chainId: quote.request.sourceChainId,\n transactions: simulation.transactions,\n });\n\n try {\n await simulateQuoteTransactions({\n chainId: quote.request.sourceChainId,\n messenger,\n transactions: simulation.transactions,\n });\n\n log('Simulation passed');\n } catch (error) {\n throwIfAborted(signal);\n\n if (error instanceof TransactionPaySimulationError) {\n throw new QuoteError({\n message: 'Quote simulation failed',\n reason: 'simulation-failed',\n detail: [error.message],\n });\n }\n\n throw error;\n }\n}\n\nexport function isQuoteError(error: unknown): error is QuoteError {\n return error instanceof QuoteError;\n}\n\n/**\n * Format an amount shortfall into display-ready detail rows.\n *\n * Amounts are formatted using the source token decimals and symbol when\n * available (e.g. `Required: 1.5 USDC`), falling back to the raw atomic values\n * otherwise.\n *\n * @param messenger - Controller messenger.\n * @param quote - Quote being validated.\n * @param required - Required amount (raw string).\n * @param balance - Current balance (raw string).\n * @returns Detail rows: Required / Current / Missing.\n */\nfunction formatBalanceShortfall(\n messenger: TransactionPayControllerMessenger,\n quote: TransactionPayQuote<unknown>,\n required: string,\n balance: string,\n): string[] {\n const { sourceChainId, sourceTokenAddress } = quote.request;\n const tokenInfo = getTokenInfo(messenger, sourceTokenAddress, sourceChainId);\n\n const requiredBn = new BigNumber(required);\n const balanceBn = new BigNumber(balance);\n\n // Only ever called when balance < required, so the shortfall is positive.\n const missing = requiredBn.minus(balanceBn);\n\n return [\n `Required: ${formatTokenAmount(requiredBn, tokenInfo)}`,\n `Current: ${formatTokenAmount(balanceBn, tokenInfo)}`,\n `Missing: ${formatTokenAmount(missing, tokenInfo)}`,\n ];\n}\n\n/**\n * Format an atomic token amount as a human-readable string with symbol.\n *\n * @param rawAmount - Amount in atomic units.\n * @param tokenInfo - Source token decimals and symbol, if available.\n * @returns Human-readable amount suffixed with the token symbol when known,\n * otherwise the raw atomic value.\n */\nfunction formatTokenAmount(\n rawAmount: BigNumber,\n tokenInfo: { decimals: number; symbol: string } | undefined,\n): string {\n if (!tokenInfo) {\n return rawAmount.toFixed();\n }\n\n const human = rawAmount.shiftedBy(-tokenInfo.decimals).toFixed();\n\n return `${human} ${tokenInfo.symbol}`;\n}\n\nasync function getLiveSourceBalance(\n quote: TransactionPayQuote<unknown>,\n messenger: TransactionPayControllerMessenger,\n): Promise<string> {\n const { from, sourceChainId, sourceTokenAddress } = quote.request;\n const normalizedSourceTokenAddress = normalizeTokenAddress(\n sourceTokenAddress,\n sourceChainId,\n TokenAddressTarget.MetaMask,\n );\n\n try {\n return await getLiveTokenBalance(\n messenger,\n from,\n sourceChainId,\n normalizedSourceTokenAddress,\n );\n } catch (error) {\n throw new QuoteError({\n message: 'Unable to verify balance',\n reason: 'balance-unavailable',\n detail: [(error as Error).message],\n });\n }\n}\n\nfunction validateRequiredSourceAmount(\n messenger: TransactionPayControllerMessenger,\n quote: TransactionPayQuote<unknown>,\n liveBalance: string,\n): void {\n if (quote.request.isPostQuote || quote.request.paymentOverride) {\n return;\n }\n\n const requiredAmount = new BigNumber(quote.sourceAmount.raw);\n const balance = new BigNumber(liveBalance);\n\n if (balance.isGreaterThanOrEqualTo(requiredAmount)) {\n return;\n }\n\n throw new QuoteError({\n message: 'Insufficient source balance for quote',\n reason: 'insufficient-source-balance',\n detail: formatBalanceShortfall(\n messenger,\n quote,\n requiredAmount.toFixed(),\n balance.toFixed(),\n ),\n });\n}\n\nfunction validateDecodedSourceTransfers(\n messenger: TransactionPayControllerMessenger,\n quote: TransactionPayQuote<unknown>,\n liveBalance: string,\n transactions: SimulationTransaction[],\n): void {\n const decodedAmounts = getDecodedSourceTransferAmounts(quote, transactions);\n\n const requiredAmount = decodedAmounts\n .reduce((total, amount) => total.plus(amount), new BigNumber(0))\n .toString(10);\n\n const balance = new BigNumber(liveBalance);\n\n log('Decoded source transfer amounts', {\n decodedAmounts,\n liveBalance,\n requiredAmount,\n });\n\n if (balance.isGreaterThanOrEqualTo(requiredAmount)) {\n return;\n }\n\n throw new QuoteError({\n message: 'Insufficient source balance for decoded transfer',\n reason: 'insufficient-transfer-balance',\n detail: formatBalanceShortfall(\n messenger,\n quote,\n requiredAmount,\n liveBalance,\n ),\n });\n}\n\nfunction getDecodedSourceTransferAmounts(\n quote: TransactionPayQuote<unknown>,\n transactions: SimulationTransaction[],\n): string[] {\n const { sourceChainId, sourceTokenAddress } = quote.request;\n const isNativeSource =\n sourceTokenAddress.toLowerCase() ===\n getNativeToken(sourceChainId).toLowerCase();\n\n if (isNativeSource) {\n return [];\n }\n\n const normalizedSourceTokenAddress = normalizeTokenAddress(\n sourceTokenAddress,\n sourceChainId,\n TokenAddressTarget.MetaMask,\n ).toLowerCase();\n\n return transactions\n .filter(\n (transaction) =>\n transaction.to &&\n normalizeTokenAddress(\n transaction.to,\n sourceChainId,\n TokenAddressTarget.MetaMask,\n ).toLowerCase() === normalizedSourceTokenAddress,\n )\n .map((transaction) =>\n transaction.data ? decodeTransferAmount(transaction.data) : undefined,\n )\n .filter((amount): amount is string => amount !== undefined);\n}\n\nfunction decodeTransferAmount(data: Hex): string | undefined {\n try {\n const result = erc20Interface.decodeFunctionData('transfer', data);\n return new BigNumber(result._value.toString()).toString(10);\n } catch {\n return undefined;\n }\n}\n\nfunction throwIfAborted(signal?: AbortSignal): void {\n if (signal?.aborted) {\n throw new Error('Quote validation aborted');\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"validation.cjs","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":";;;AAAA,4CAA+C;AAC/C,mEAAuD;AAEvD,+CAAyC;AAEzC,6CAAiE;AAMjE,oDAIyB;AACzB,0CAMoB;AAEpB,MAAM,GAAG,GAAG,IAAA,8BAAkB,EAAC,yBAAa,EAAE,YAAY,CAAC,CAAC;AAE5D,MAAM,cAAc,GAAG,IAAI,eAAS,CAAC,4BAAQ,CAAC,CAAC;AAa/C,MAAa,UAAW,SAAQ,KAAK;IAKnC,YAAY,IAAoB,EAAE,MAAuC;QACvE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpB,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAXD,gCAWC;AAEM,KAAK,UAAU,sBAAsB,CAAC,EAC3C,SAAS,EACT,KAAK,EACL,MAAM,EACN,UAAU,GACY;IACtB,cAAc,CAAC,MAAM,CAAC,CAAC;IAEvB,MAAM,WAAW,GAAG,MAAM,oBAAoB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IAEjE,GAAG,CAAC,qBAAqB,EAAE;QACzB,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI;QACxB,WAAW;QACX,aAAa,EAAE,KAAK,CAAC,OAAO,CAAC,aAAa;QAC1C,kBAAkB,EAAE,KAAK,CAAC,OAAO,CAAC,kBAAkB;KACrD,CAAC,CAAC;IAEH,cAAc,CAAC,MAAM,CAAC,CAAC;IAEvB,GAAG,CAAC,8BAA8B,EAAE;QAClC,kBAAkB,EAAE,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,eAAe,CAAC;QAC1D,WAAW,EAAE,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC;QAC/C,WAAW;QACX,cAAc,EAAE,KAAK,CAAC,YAAY,CAAC,GAAG;KACvC,CAAC,CAAC;IAEH,4BAA4B,CAAC,SAAS,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC;IAE5D,GAAG,CAAC,mCAAmC,EAAE;QACvC,aAAa,EAAE,KAAK,CAAC,OAAO,CAAC,aAAa;QAC1C,kBAAkB,EAAE,KAAK,CAAC,OAAO,CAAC,kBAAkB;QACpD,YAAY,EAAE,UAAU,CAAC,YAAY;KACtC,CAAC,CAAC;IAEH,8BAA8B,CAC5B,SAAS,EACT,KAAK,EACL,WAAW,EACX,UAAU,CAAC,YAAY,CACxB,CAAC;IAEF,cAAc,CAAC,MAAM,CAAC,CAAC;IAEvB,MAAM,kBAAkB,CAAC,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;AACjE,CAAC;AA5CD,wDA4CC;AAED,KAAK,UAAU,kBAAkB,CAC/B,SAA4C,EAC5C,KAAmC,EACnC,UAA2B,EAC3B,MAAoB;IAEpB,GAAG,CAAC,qBAAqB,EAAE;QACzB,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,aAAa;QACpC,YAAY,EAAE,UAAU,CAAC,YAAY;KACtC,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,MAAM,IAAA,yCAAyB,EAAC;YAC9B,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,aAAa;YACpC,SAAS;YACT,YAAY,EAAE,UAAU,CAAC,YAAY;SACtC,CAAC,CAAC;QAEH,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,cAAc,CAAC,MAAM,CAAC,CAAC;QAEvB,IAAI,KAAK,YAAY,6CAA6B,EAAE,CAAC;YACnD,MAAM,IAAI,UAAU,CAAC;gBACnB,OAAO,EAAE,yBAAyB;gBAClC,MAAM,EAAE,mBAAmB;gBAC3B,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC;aACxB,CAAC,CAAC;QACL,CAAC;QAED,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAgB,YAAY,CAAC,KAAc;IACzC,OAAO,KAAK,YAAY,UAAU,CAAC;AACrC,CAAC;AAFD,oCAEC;AAED;;;;;;;;;;;;GAYG;AACH,SAAS,sBAAsB,CAC7B,SAA4C,EAC5C,KAAmC,EACnC,QAAgB,EAChB,OAAe;IAEf,MAAM,EAAE,aAAa,EAAE,kBAAkB,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC;IAC5D,MAAM,SAAS,GAAG,IAAA,uBAAY,EAAC,SAAS,EAAE,kBAAkB,EAAE,aAAa,CAAC,CAAC;IAE7E,MAAM,UAAU,GAAG,IAAI,wBAAS,CAAC,QAAQ,CAAC,CAAC;IAC3C,MAAM,SAAS,GAAG,IAAI,wBAAS,CAAC,OAAO,CAAC,CAAC;IAEzC,0EAA0E;IAC1E,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAE5C,OAAO;QACL,aAAa,iBAAiB,CAAC,UAAU,EAAE,SAAS,CAAC,EAAE;QACvD,YAAY,iBAAiB,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE;QACrD,YAAY,iBAAiB,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE;KACpD,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,iBAAiB,CACxB,SAAoB,EACpB,SAA2D;IAE3D,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,SAAS,CAAC,OAAO,EAAE,CAAC;IAC7B,CAAC;IAED,MAAM,KAAK,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC;IAEjE,OAAO,GAAG,KAAK,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;AACxC,CAAC;AAED,KAAK,UAAU,oBAAoB,CACjC,KAAmC,EACnC,SAA4C;IAE5C,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,kBAAkB,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC;IAClE,MAAM,4BAA4B,GAAG,IAAA,gCAAqB,EACxD,kBAAkB,EAClB,aAAa,EACb,6BAAkB,CAAC,QAAQ,CAC5B,CAAC;IAEF,IAAI,CAAC;QACH,OAAO,MAAM,IAAA,8BAAmB,EAC9B,SAAS,EACT,IAAI,EACJ,aAAa,EACb,4BAA4B,CAC7B,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,UAAU,CAAC;YACnB,OAAO,EAAE,0BAA0B;YACnC,MAAM,EAAE,qBAAqB;YAC7B,MAAM,EAAE,CAAE,KAAe,CAAC,OAAO,CAAC;SACnC,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,SAAS,4BAA4B,CACnC,SAA4C,EAC5C,KAAmC,EACnC,WAAmB;IAEnB,IAAI,KAAK,CAAC,OAAO,CAAC,WAAW,IAAI,KAAK,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC;QAC/D,GAAG,CAAC,oCAAoC,EAAE;YACxC,kBAAkB,EAAE,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,eAAe,CAAC;YAC1D,WAAW,EAAE,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC;SAChD,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,MAAM,cAAc,GAAG,IAAI,wBAAS,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IAC7D,MAAM,OAAO,GAAG,IAAI,wBAAS,CAAC,WAAW,CAAC,CAAC;IAE3C,IAAI,OAAO,CAAC,sBAAsB,CAAC,cAAc,CAAC,EAAE,CAAC;QACnD,GAAG,CAAC,kCAAkC,CAAC,CAAC;QACxC,OAAO;IACT,CAAC;IAED,MAAM,IAAI,UAAU,CAAC;QACnB,OAAO,EAAE,uCAAuC;QAChD,MAAM,EAAE,6BAA6B;QACrC,MAAM,EAAE,sBAAsB,CAC5B,SAAS,EACT,KAAK,EACL,cAAc,CAAC,OAAO,EAAE,EACxB,OAAO,CAAC,OAAO,EAAE,CAClB;KACF,CAAC,CAAC;AACL,CAAC;AAED,SAAS,8BAA8B,CACrC,SAA4C,EAC5C,KAAmC,EACnC,WAAmB,EACnB,YAAqC;IAErC,4EAA4E;IAC5E,4EAA4E;IAC5E,kEAAkE;IAClE,IACE,YAAY,CAAC,MAAM,KAAK,CAAC;QACzB,CAAC,qBAAqB,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,EAC9C,CAAC;QACD,GAAG,CACD,4EAA4E,CAC7E,CAAC;QACF,OAAO;IACT,CAAC;IAED,sEAAsE;IACtE,2CAA2C;IAC3C,MAAM,cAAc,GAAG,oBAAoB,CACzC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAW,CAClB,CAAC;IAEZ,MAAM,OAAO,GAAG,IAAI,wBAAS,CAAC,WAAW,CAAC,CAAC;IAE3C,GAAG,CAAC,gCAAgC,EAAE;QACpC,WAAW;QACX,cAAc;KACf,CAAC,CAAC;IAEH,IAAI,OAAO,CAAC,sBAAsB,CAAC,cAAc,CAAC,EAAE,CAAC;QACnD,GAAG,CAAC,uCAAuC,CAAC,CAAC;QAC7C,OAAO;IACT,CAAC;IAED,MAAM,IAAI,UAAU,CAAC;QACnB,OAAO,EAAE,kDAAkD;QAC3D,MAAM,EAAE,+BAA+B;QACvC,MAAM,EAAE,sBAAsB,CAC5B,SAAS,EACT,KAAK,EACL,cAAc,EACd,WAAW,CACZ;KACF,CAAC,CAAC;AACL,CAAC;AAED,SAAS,qBAAqB,CAC5B,KAAmC,EACnC,WAA8C;IAE9C,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;QAC1C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,EAAE,aAAa,EAAE,kBAAkB,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC;IAE5D,MAAM,cAAc,GAClB,kBAAkB,CAAC,WAAW,EAAE;QAChC,IAAA,yBAAc,EAAC,aAAa,CAAC,CAAC,WAAW,EAAE,CAAC;IAE9C,IAAI,cAAc,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,4BAA4B,GAAG,IAAA,gCAAqB,EACxD,kBAAkB,EAClB,aAAa,EACb,6BAAkB,CAAC,QAAQ,CAC5B,CAAC,WAAW,EAAE,CAAC;IAEhB,MAAM,YAAY,GAAG,IAAA,gCAAqB,EACxC,WAAW,CAAC,EAAE,EACd,aAAa,EACb,6BAAkB,CAAC,QAAQ,CAC5B,CAAC,WAAW,EAAE,CAAC;IAEhB,IAAI,YAAY,KAAK,4BAA4B,EAAE,CAAC;QAClD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,oBAAoB,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC;AAC9D,CAAC;AAED,SAAS,oBAAoB,CAAC,IAAS;IACrC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,cAAc,CAAC,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACnE,OAAO,IAAI,wBAAS,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC9D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,MAAoB;IAC1C,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC","sourcesContent":["import { Interface } from '@ethersproject/abi';\nimport { abiERC20 } from '@metamask/metamask-eth-abis';\nimport type { Hex } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { createModuleLogger, projectLogger } from '../logger.js';\nimport type {\n QuoteErrorInfo,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../types.js';\nimport {\n SimulationTransaction,\n simulateQuoteTransactions,\n TransactionPaySimulationError,\n} from './simulation.js';\nimport {\n getLiveTokenBalance,\n getNativeToken,\n getTokenInfo,\n normalizeTokenAddress,\n TokenAddressTarget,\n} from './token.js';\n\nconst log = createModuleLogger(projectLogger, 'validation');\n\nconst erc20Interface = new Interface(abiERC20);\n\nexport type QuoteSimulation = {\n transactions: SimulationTransaction[];\n};\n\nexport type QuoteExecutionRequest = {\n messenger: TransactionPayControllerMessenger;\n quote: TransactionPayQuote<unknown>;\n signal?: AbortSignal;\n simulation: QuoteSimulation;\n};\n\nexport class QuoteError extends Error {\n readonly info: QuoteErrorInfo;\n\n readonly quotes?: TransactionPayQuote<unknown>[];\n\n constructor(info: QuoteErrorInfo, quotes?: TransactionPayQuote<unknown>[]) {\n super(info.message);\n this.name = 'QuoteError';\n this.info = info;\n this.quotes = quotes;\n }\n}\n\nexport async function validateQuoteExecution({\n messenger,\n quote,\n signal,\n simulation,\n}: QuoteExecutionRequest): Promise<void> {\n throwIfAborted(signal);\n\n const liveBalance = await getLiveSourceBalance(quote, messenger);\n\n log('Live source balance', {\n from: quote.request.from,\n liveBalance,\n sourceChainId: quote.request.sourceChainId,\n sourceTokenAddress: quote.request.sourceTokenAddress,\n });\n\n throwIfAborted(signal);\n\n log('Checking quote source amount', {\n hasPaymentOverride: Boolean(quote.request.paymentOverride),\n isPostQuote: Boolean(quote.request.isPostQuote),\n liveBalance,\n requiredAmount: quote.sourceAmount.raw,\n });\n\n validateRequiredSourceAmount(messenger, quote, liveBalance);\n\n log('Checking decoded source transfers', {\n sourceChainId: quote.request.sourceChainId,\n sourceTokenAddress: quote.request.sourceTokenAddress,\n transactions: simulation.transactions,\n });\n\n validateDecodedSourceTransfers(\n messenger,\n quote,\n liveBalance,\n simulation.transactions,\n );\n\n throwIfAborted(signal);\n\n await validateSimulation(messenger, quote, simulation, signal);\n}\n\nasync function validateSimulation(\n messenger: TransactionPayControllerMessenger,\n quote: TransactionPayQuote<unknown>,\n simulation: QuoteSimulation,\n signal?: AbortSignal,\n): Promise<void> {\n log('Starting simulation', {\n chainId: quote.request.sourceChainId,\n transactions: simulation.transactions,\n });\n\n try {\n await simulateQuoteTransactions({\n chainId: quote.request.sourceChainId,\n messenger,\n transactions: simulation.transactions,\n });\n\n log('Simulation passed');\n } catch (error) {\n throwIfAborted(signal);\n\n if (error instanceof TransactionPaySimulationError) {\n throw new QuoteError({\n message: 'Quote simulation failed',\n reason: 'simulation-failed',\n detail: [error.message],\n });\n }\n\n throw error;\n }\n}\n\nexport function isQuoteError(error: unknown): error is QuoteError {\n return error instanceof QuoteError;\n}\n\n/**\n * Format an amount shortfall into display-ready detail rows.\n *\n * Amounts are formatted using the source token decimals and symbol when\n * available (e.g. `Required: 1.5 USDC`), falling back to the raw atomic values\n * otherwise.\n *\n * @param messenger - Controller messenger.\n * @param quote - Quote being validated.\n * @param required - Required amount (raw string).\n * @param balance - Current balance (raw string).\n * @returns Detail rows: Required / Current / Missing.\n */\nfunction formatBalanceShortfall(\n messenger: TransactionPayControllerMessenger,\n quote: TransactionPayQuote<unknown>,\n required: string,\n balance: string,\n): string[] {\n const { sourceChainId, sourceTokenAddress } = quote.request;\n const tokenInfo = getTokenInfo(messenger, sourceTokenAddress, sourceChainId);\n\n const requiredBn = new BigNumber(required);\n const balanceBn = new BigNumber(balance);\n\n // Only ever called when balance < required, so the shortfall is positive.\n const missing = requiredBn.minus(balanceBn);\n\n return [\n `Required: ${formatTokenAmount(requiredBn, tokenInfo)}`,\n `Current: ${formatTokenAmount(balanceBn, tokenInfo)}`,\n `Missing: ${formatTokenAmount(missing, tokenInfo)}`,\n ];\n}\n\n/**\n * Format an atomic token amount as a human-readable string with symbol.\n *\n * @param rawAmount - Amount in atomic units.\n * @param tokenInfo - Source token decimals and symbol, if available.\n * @returns Human-readable amount suffixed with the token symbol when known,\n * otherwise the raw atomic value.\n */\nfunction formatTokenAmount(\n rawAmount: BigNumber,\n tokenInfo: { decimals: number; symbol: string } | undefined,\n): string {\n if (!tokenInfo) {\n return rawAmount.toFixed();\n }\n\n const human = rawAmount.shiftedBy(-tokenInfo.decimals).toFixed();\n\n return `${human} ${tokenInfo.symbol}`;\n}\n\nasync function getLiveSourceBalance(\n quote: TransactionPayQuote<unknown>,\n messenger: TransactionPayControllerMessenger,\n): Promise<string> {\n const { from, sourceChainId, sourceTokenAddress } = quote.request;\n const normalizedSourceTokenAddress = normalizeTokenAddress(\n sourceTokenAddress,\n sourceChainId,\n TokenAddressTarget.MetaMask,\n );\n\n try {\n return await getLiveTokenBalance(\n messenger,\n from,\n sourceChainId,\n normalizedSourceTokenAddress,\n );\n } catch (error) {\n throw new QuoteError({\n message: 'Unable to verify balance',\n reason: 'balance-unavailable',\n detail: [(error as Error).message],\n });\n }\n}\n\nfunction validateRequiredSourceAmount(\n messenger: TransactionPayControllerMessenger,\n quote: TransactionPayQuote<unknown>,\n liveBalance: string,\n): void {\n if (quote.request.isPostQuote || quote.request.paymentOverride) {\n log('Skipping quote source amount check', {\n hasPaymentOverride: Boolean(quote.request.paymentOverride),\n isPostQuote: Boolean(quote.request.isPostQuote),\n });\n return;\n }\n\n const requiredAmount = new BigNumber(quote.sourceAmount.raw);\n const balance = new BigNumber(liveBalance);\n\n if (balance.isGreaterThanOrEqualTo(requiredAmount)) {\n log('Quote source amount check passed');\n return;\n }\n\n throw new QuoteError({\n message: 'Insufficient source balance for quote',\n reason: 'insufficient-source-balance',\n detail: formatBalanceShortfall(\n messenger,\n quote,\n requiredAmount.toFixed(),\n balance.toFixed(),\n ),\n });\n}\n\nfunction validateDecodedSourceTransfers(\n messenger: TransactionPayControllerMessenger,\n quote: TransactionPayQuote<unknown>,\n liveBalance: string,\n transactions: SimulationTransaction[],\n): void {\n // Only valid for a single source-token transfer. Multi-step batches produce\n // or transform the source-token balance mid-batch, so comparing against the\n // starting balance is wrong; rely on the full simulation instead.\n if (\n transactions.length !== 1 ||\n !isSourceTokenTransfer(quote, transactions[0])\n ) {\n log(\n 'Skipping decoded source transfer check: not a single source-token transfer',\n );\n return;\n }\n\n // `isSourceTokenTransfer` has already confirmed the data decodes to a\n // transfer, so the amount is defined here.\n const requiredAmount = decodeTransferAmount(\n transactions[0].data as Hex,\n ) as string;\n\n const balance = new BigNumber(liveBalance);\n\n log('Decoded source transfer amount', {\n liveBalance,\n requiredAmount,\n });\n\n if (balance.isGreaterThanOrEqualTo(requiredAmount)) {\n log('Decoded source transfers check passed');\n return;\n }\n\n throw new QuoteError({\n message: 'Insufficient source balance for decoded transfer',\n reason: 'insufficient-transfer-balance',\n detail: formatBalanceShortfall(\n messenger,\n quote,\n requiredAmount,\n liveBalance,\n ),\n });\n}\n\nfunction isSourceTokenTransfer(\n quote: TransactionPayQuote<unknown>,\n transaction: SimulationTransaction | undefined,\n): boolean {\n if (!transaction?.to || !transaction.data) {\n return false;\n }\n\n const { sourceChainId, sourceTokenAddress } = quote.request;\n\n const isNativeSource =\n sourceTokenAddress.toLowerCase() ===\n getNativeToken(sourceChainId).toLowerCase();\n\n if (isNativeSource) {\n return false;\n }\n\n const normalizedSourceTokenAddress = normalizeTokenAddress(\n sourceTokenAddress,\n sourceChainId,\n TokenAddressTarget.MetaMask,\n ).toLowerCase();\n\n const normalizedTo = normalizeTokenAddress(\n transaction.to,\n sourceChainId,\n TokenAddressTarget.MetaMask,\n ).toLowerCase();\n\n if (normalizedTo !== normalizedSourceTokenAddress) {\n return false;\n }\n\n return decodeTransferAmount(transaction.data) !== undefined;\n}\n\nfunction decodeTransferAmount(data: Hex): string | undefined {\n try {\n const result = erc20Interface.decodeFunctionData('transfer', data);\n return new BigNumber(result._value.toString()).toString(10);\n } catch {\n return undefined;\n }\n}\n\nfunction throwIfAborted(signal?: AbortSignal): void {\n if (signal?.aborted) {\n throw new Error('Quote validation aborted');\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.cts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,cAAc,EACd,iCAAiC,EACjC,mBAAmB,EACpB,qBAAoB;AACrB,OAAO,EACL,qBAAqB,EAGtB,yBAAwB;AAazB,MAAM,MAAM,eAAe,GAAG;IAC5B,YAAY,EAAE,qBAAqB,EAAE,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,SAAS,EAAE,iCAAiC,CAAC;IAC7C,KAAK,EAAE,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACpC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,UAAU,EAAE,eAAe,CAAC;CAC7B,CAAC;AAEF,qBAAa,UAAW,SAAQ,KAAK;IACnC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAE9B,QAAQ,CAAC,MAAM,CAAC,EAAE,mBAAmB,CAAC,OAAO,CAAC,EAAE,CAAC;gBAErC,IAAI,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,mBAAmB,CAAC,OAAO,CAAC,EAAE;CAM1E;AAED,wBAAsB,sBAAsB,CAAC,EAC3C,SAAS,EACT,KAAK,EACL,MAAM,EACN,UAAU,GACX,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"validation.d.cts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,cAAc,EACd,iCAAiC,EACjC,mBAAmB,EACpB,qBAAoB;AACrB,OAAO,EACL,qBAAqB,EAGtB,yBAAwB;AAazB,MAAM,MAAM,eAAe,GAAG;IAC5B,YAAY,EAAE,qBAAqB,EAAE,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,SAAS,EAAE,iCAAiC,CAAC;IAC7C,KAAK,EAAE,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACpC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,UAAU,EAAE,eAAe,CAAC;CAC7B,CAAC;AAEF,qBAAa,UAAW,SAAQ,KAAK;IACnC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAE9B,QAAQ,CAAC,MAAM,CAAC,EAAE,mBAAmB,CAAC,OAAO,CAAC,EAAE,CAAC;gBAErC,IAAI,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,mBAAmB,CAAC,OAAO,CAAC,EAAE;CAM1E;AAED,wBAAsB,sBAAsB,CAAC,EAC3C,SAAS,EACT,KAAK,EACL,MAAM,EACN,UAAU,GACX,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuCvC;AAoCD,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAEhE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.mts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,cAAc,EACd,iCAAiC,EACjC,mBAAmB,EACpB,qBAAoB;AACrB,OAAO,EACL,qBAAqB,EAGtB,yBAAwB;AAazB,MAAM,MAAM,eAAe,GAAG;IAC5B,YAAY,EAAE,qBAAqB,EAAE,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,SAAS,EAAE,iCAAiC,CAAC;IAC7C,KAAK,EAAE,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACpC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,UAAU,EAAE,eAAe,CAAC;CAC7B,CAAC;AAEF,qBAAa,UAAW,SAAQ,KAAK;IACnC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAE9B,QAAQ,CAAC,MAAM,CAAC,EAAE,mBAAmB,CAAC,OAAO,CAAC,EAAE,CAAC;gBAErC,IAAI,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,mBAAmB,CAAC,OAAO,CAAC,EAAE;CAM1E;AAED,wBAAsB,sBAAsB,CAAC,EAC3C,SAAS,EACT,KAAK,EACL,MAAM,EACN,UAAU,GACX,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"validation.d.mts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,cAAc,EACd,iCAAiC,EACjC,mBAAmB,EACpB,qBAAoB;AACrB,OAAO,EACL,qBAAqB,EAGtB,yBAAwB;AAazB,MAAM,MAAM,eAAe,GAAG;IAC5B,YAAY,EAAE,qBAAqB,EAAE,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,SAAS,EAAE,iCAAiC,CAAC;IAC7C,KAAK,EAAE,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACpC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,UAAU,EAAE,eAAe,CAAC;CAC7B,CAAC;AAEF,qBAAa,UAAW,SAAQ,KAAK;IACnC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAE9B,QAAQ,CAAC,MAAM,CAAC,EAAE,mBAAmB,CAAC,OAAO,CAAC,EAAE,CAAC;gBAErC,IAAI,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,mBAAmB,CAAC,OAAO,CAAC,EAAE;CAM1E;AAED,wBAAsB,sBAAsB,CAAC,EAC3C,SAAS,EACT,KAAK,EACL,MAAM,EACN,UAAU,GACX,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuCvC;AAoCD,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAEhE"}
|
|
@@ -31,15 +31,16 @@ export async function validateQuoteExecution({ messenger, quote, signal, simulat
|
|
|
31
31
|
requiredAmount: quote.sourceAmount.raw,
|
|
32
32
|
});
|
|
33
33
|
validateRequiredSourceAmount(messenger, quote, liveBalance);
|
|
34
|
-
log('Quote source amount check passed');
|
|
35
34
|
log('Checking decoded source transfers', {
|
|
36
35
|
sourceChainId: quote.request.sourceChainId,
|
|
37
36
|
sourceTokenAddress: quote.request.sourceTokenAddress,
|
|
38
|
-
|
|
37
|
+
transactions: simulation.transactions,
|
|
39
38
|
});
|
|
40
39
|
validateDecodedSourceTransfers(messenger, quote, liveBalance, simulation.transactions);
|
|
41
|
-
log('Decoded source transfers check passed');
|
|
42
40
|
throwIfAborted(signal);
|
|
41
|
+
await validateSimulation(messenger, quote, simulation, signal);
|
|
42
|
+
}
|
|
43
|
+
async function validateSimulation(messenger, quote, simulation, signal) {
|
|
43
44
|
log('Starting simulation', {
|
|
44
45
|
chainId: quote.request.sourceChainId,
|
|
45
46
|
transactions: simulation.transactions,
|
|
@@ -124,11 +125,16 @@ async function getLiveSourceBalance(quote, messenger) {
|
|
|
124
125
|
}
|
|
125
126
|
function validateRequiredSourceAmount(messenger, quote, liveBalance) {
|
|
126
127
|
if (quote.request.isPostQuote || quote.request.paymentOverride) {
|
|
128
|
+
log('Skipping quote source amount check', {
|
|
129
|
+
hasPaymentOverride: Boolean(quote.request.paymentOverride),
|
|
130
|
+
isPostQuote: Boolean(quote.request.isPostQuote),
|
|
131
|
+
});
|
|
127
132
|
return;
|
|
128
133
|
}
|
|
129
134
|
const requiredAmount = new BigNumber(quote.sourceAmount.raw);
|
|
130
135
|
const balance = new BigNumber(liveBalance);
|
|
131
136
|
if (balance.isGreaterThanOrEqualTo(requiredAmount)) {
|
|
137
|
+
log('Quote source amount check passed');
|
|
132
138
|
return;
|
|
133
139
|
}
|
|
134
140
|
throw new QuoteError({
|
|
@@ -138,17 +144,24 @@ function validateRequiredSourceAmount(messenger, quote, liveBalance) {
|
|
|
138
144
|
});
|
|
139
145
|
}
|
|
140
146
|
function validateDecodedSourceTransfers(messenger, quote, liveBalance, transactions) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
147
|
+
// Only valid for a single source-token transfer. Multi-step batches produce
|
|
148
|
+
// or transform the source-token balance mid-batch, so comparing against the
|
|
149
|
+
// starting balance is wrong; rely on the full simulation instead.
|
|
150
|
+
if (transactions.length !== 1 ||
|
|
151
|
+
!isSourceTokenTransfer(quote, transactions[0])) {
|
|
152
|
+
log('Skipping decoded source transfer check: not a single source-token transfer');
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
// `isSourceTokenTransfer` has already confirmed the data decodes to a
|
|
156
|
+
// transfer, so the amount is defined here.
|
|
157
|
+
const requiredAmount = decodeTransferAmount(transactions[0].data);
|
|
145
158
|
const balance = new BigNumber(liveBalance);
|
|
146
|
-
log('Decoded source transfer
|
|
147
|
-
decodedAmounts,
|
|
159
|
+
log('Decoded source transfer amount', {
|
|
148
160
|
liveBalance,
|
|
149
161
|
requiredAmount,
|
|
150
162
|
});
|
|
151
163
|
if (balance.isGreaterThanOrEqualTo(requiredAmount)) {
|
|
164
|
+
log('Decoded source transfers check passed');
|
|
152
165
|
return;
|
|
153
166
|
}
|
|
154
167
|
throw new QuoteError({
|
|
@@ -157,19 +170,22 @@ function validateDecodedSourceTransfers(messenger, quote, liveBalance, transacti
|
|
|
157
170
|
detail: formatBalanceShortfall(messenger, quote, requiredAmount, liveBalance),
|
|
158
171
|
});
|
|
159
172
|
}
|
|
160
|
-
function
|
|
173
|
+
function isSourceTokenTransfer(quote, transaction) {
|
|
174
|
+
if (!transaction?.to || !transaction.data) {
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
161
177
|
const { sourceChainId, sourceTokenAddress } = quote.request;
|
|
162
178
|
const isNativeSource = sourceTokenAddress.toLowerCase() ===
|
|
163
179
|
getNativeToken(sourceChainId).toLowerCase();
|
|
164
180
|
if (isNativeSource) {
|
|
165
|
-
return
|
|
181
|
+
return false;
|
|
166
182
|
}
|
|
167
183
|
const normalizedSourceTokenAddress = normalizeTokenAddress(sourceTokenAddress, sourceChainId, TokenAddressTarget.MetaMask).toLowerCase();
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
184
|
+
const normalizedTo = normalizeTokenAddress(transaction.to, sourceChainId, TokenAddressTarget.MetaMask).toLowerCase();
|
|
185
|
+
if (normalizedTo !== normalizedSourceTokenAddress) {
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
return decodeTransferAmount(transaction.data) !== undefined;
|
|
173
189
|
}
|
|
174
190
|
function decodeTransferAmount(data) {
|
|
175
191
|
try {
|