@metamask-previews/transaction-pay-controller 26.1.0-preview-d2f661012 → 26.1.1-preview-5a03e1b92
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 +21 -1
- package/dist/strategy/relay/relay-validation.cjs +36 -23
- 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 +37 -24
- package/dist/strategy/relay/relay-validation.mjs.map +1 -1
- package/dist/utils/feature-flags.cjs +16 -1
- package/dist/utils/feature-flags.cjs.map +1 -1
- package/dist/utils/feature-flags.d.cts +9 -0
- package/dist/utils/feature-flags.d.cts.map +1 -1
- package/dist/utils/feature-flags.d.mts +9 -0
- package/dist/utils/feature-flags.d.mts.map +1 -1
- package/dist/utils/feature-flags.mjs +14 -0
- package/dist/utils/feature-flags.mjs.map +1 -1
- package/dist/utils/quotes.cjs +14 -1
- package/dist/utils/quotes.cjs.map +1 -1
- package/dist/utils/quotes.mjs +14 -1
- package/dist/utils/quotes.mjs.map +1 -1
- package/dist/utils/simulation.cjs +40 -1
- package/dist/utils/simulation.cjs.map +1 -1
- package/dist/utils/simulation.d.cts.map +1 -1
- package/dist/utils/simulation.d.mts.map +1 -1
- package/dist/utils/simulation.mjs +40 -1
- package/dist/utils/simulation.mjs.map +1 -1
- package/dist/utils/validation.cjs +2 -1
- package/dist/utils/validation.cjs.map +1 -1
- package/dist/utils/validation.d.cts +2 -1
- package/dist/utils/validation.d.cts.map +1 -1
- package/dist/utils/validation.d.mts +2 -1
- package/dist/utils/validation.d.mts.map +1 -1
- package/dist/utils/validation.mjs +2 -1
- package/dist/utils/validation.mjs.map +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- Bump `@metamask/assets-controller` from `^13.0.0` to `^13.1.0` ([#9743](https://github.com/MetaMask/core/pull/9743))
|
|
13
|
+
- Bump `@metamask/assets-controllers` from `^110.0.3` to `^110.1.0` ([#9743](https://github.com/MetaMask/core/pull/9743))
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- Fix Relay quote validation ([#9723](https://github.com/MetaMask/core/pull/9723))
|
|
18
|
+
- Keep the quote when validation fails with reason `insufficient-source-balance`, while still surfacing `quoteError`; all other validation-failure reasons continue to remove the quote.
|
|
19
|
+
- Exclude a zero `gas` value from the simulated transaction.
|
|
20
|
+
- Always include an EIP-7702 authorization in the batch simulation so a not-yet-upgraded account is simulated as delegated, using the quote authorization address when present and otherwise the configured EIP-7702 upgrade contract for the chain.
|
|
21
|
+
- Surface the revert return data as `Custom Error - <return>` when a Sentinel simulation reverts with `execution reverted` and non-empty return data, falling back to `Reverted - Unknown Error` when the return data is empty, instead of the implied `execution reverted` message.
|
|
22
|
+
|
|
23
|
+
## [26.1.1]
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- Bump `@metamask/assets-controller` from `^12.0.0` to `^13.0.0` ([#9740](https://github.com/MetaMask/core/pull/9740))
|
|
28
|
+
|
|
10
29
|
## [26.1.0]
|
|
11
30
|
|
|
12
31
|
### Added
|
|
@@ -1362,7 +1381,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
1362
1381
|
|
|
1363
1382
|
- Initial release ([#6820](https://github.com/MetaMask/core/pull/6820))
|
|
1364
1383
|
|
|
1365
|
-
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@26.1.
|
|
1384
|
+
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@26.1.1...HEAD
|
|
1385
|
+
[26.1.1]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@26.1.0...@metamask/transaction-pay-controller@26.1.1
|
|
1366
1386
|
[26.1.0]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@26.0.1...@metamask/transaction-pay-controller@26.1.0
|
|
1367
1387
|
[26.0.1]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@26.0.0...@metamask/transaction-pay-controller@26.0.1
|
|
1368
1388
|
[26.0.0]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@25.1.1...@metamask/transaction-pay-controller@26.0.0
|
|
@@ -38,14 +38,21 @@ async function validateRelayQuotes(request) {
|
|
|
38
38
|
messenger: request.messenger,
|
|
39
39
|
quote,
|
|
40
40
|
signal: request.signal,
|
|
41
|
-
simulation: buildRelayValidationSimulation(quote, calls, executeRequest),
|
|
41
|
+
simulation: buildRelayValidationSimulation(request.messenger, quote, calls, executeRequest),
|
|
42
42
|
});
|
|
43
43
|
}
|
|
44
44
|
catch (error) {
|
|
45
45
|
if (request.signal?.aborted) {
|
|
46
46
|
throw error;
|
|
47
47
|
}
|
|
48
|
-
|
|
48
|
+
const quoteError = toQuoteError(error);
|
|
49
|
+
if (quoteError.info.reason === 'insufficient-source-balance') {
|
|
50
|
+
// Backwards compatibility: keep the entire quote batch (including
|
|
51
|
+
// quotes that may have passed or not yet been validated) so that
|
|
52
|
+
// clients can still show quote details alongside the balance error.
|
|
53
|
+
throw new validation_js_1.QuoteError(quoteError.info, request.quotes);
|
|
54
|
+
}
|
|
55
|
+
throw quoteError;
|
|
49
56
|
}
|
|
50
57
|
}
|
|
51
58
|
}
|
|
@@ -64,7 +71,7 @@ function toQuoteError(error) {
|
|
|
64
71
|
detail: [error.message],
|
|
65
72
|
});
|
|
66
73
|
}
|
|
67
|
-
function buildRelayValidationSimulation(quote, calls, executeRequest) {
|
|
74
|
+
function buildRelayValidationSimulation(messenger, quote, calls, executeRequest) {
|
|
68
75
|
const { from, sourceChainId, targetChainId } = quote.request;
|
|
69
76
|
const context = { from, sourceChainId, targetChainId };
|
|
70
77
|
if (executeRequest) {
|
|
@@ -73,7 +80,7 @@ function buildRelayValidationSimulation(quote, calls, executeRequest) {
|
|
|
73
80
|
}
|
|
74
81
|
if (quote.original.metamask.is7702) {
|
|
75
82
|
log('Building 7702 batch simulation', context);
|
|
76
|
-
return buildRelay7702BatchSimulation(quote, calls);
|
|
83
|
+
return buildRelay7702BatchSimulation(messenger, quote, calls);
|
|
77
84
|
}
|
|
78
85
|
log('Building normal simulation', context);
|
|
79
86
|
return buildRelayNormalSimulation(calls);
|
|
@@ -97,27 +104,30 @@ function buildRelayExecuteSimulation(quote, executeRequest) {
|
|
|
97
104
|
],
|
|
98
105
|
};
|
|
99
106
|
}
|
|
100
|
-
function buildRelay7702BatchSimulation(quote, calls) {
|
|
101
|
-
const { from } = quote.request;
|
|
107
|
+
function buildRelay7702BatchSimulation(messenger, quote, calls) {
|
|
108
|
+
const { from, sourceChainId } = quote.request;
|
|
102
109
|
const gas = quote.original.metamask.gasLimits[0];
|
|
103
110
|
const batchTx = (0, transaction_controller_1.generateEIP7702BatchTransaction)(from, calls.map((params) => ({
|
|
104
111
|
to: params.to,
|
|
105
112
|
data: params.data,
|
|
106
113
|
value: params.value,
|
|
107
114
|
})));
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
115
|
+
// The batch call is an ERC-7821 `execute` on the sender's own account, so the
|
|
116
|
+
// account must appear upgraded for the simulation to succeed. The quote does
|
|
117
|
+
// not always carry an authorization, and there is no fast way to check the
|
|
118
|
+
// live upgrade state, so an authorization is always included: the delegator
|
|
119
|
+
// address comes from the quote when present, otherwise from the configured
|
|
120
|
+
// EIP-7702 upgrade contract for the chain.
|
|
121
|
+
const address = quote.original.request.authorizationList?.[0]?.address ??
|
|
122
|
+
(0, feature_flags_js_1.getEIP7702UpgradeContractAddress)(messenger, sourceChainId);
|
|
123
|
+
const authorizationList = address ? [{ address, from }] : undefined;
|
|
114
124
|
return {
|
|
115
125
|
transactions: [
|
|
116
126
|
{
|
|
117
|
-
...(
|
|
127
|
+
...(authorizationList ? { authorizationList } : {}),
|
|
118
128
|
data: batchTx.data,
|
|
119
129
|
from,
|
|
120
|
-
...(gas === undefined ? {} : { gas: (0, controller_utils_1.toHex)(gas) }),
|
|
130
|
+
...(gas === undefined || gas === 0 ? {} : { gas: (0, controller_utils_1.toHex)(gas) }),
|
|
121
131
|
to: batchTx.to,
|
|
122
132
|
value: '0x0',
|
|
123
133
|
},
|
|
@@ -126,15 +136,18 @@ function buildRelay7702BatchSimulation(quote, calls) {
|
|
|
126
136
|
}
|
|
127
137
|
function buildRelayNormalSimulation(calls) {
|
|
128
138
|
return {
|
|
129
|
-
transactions: calls.map((params) =>
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
139
|
+
transactions: calls.map((params) => {
|
|
140
|
+
const gas = params.gas;
|
|
141
|
+
return {
|
|
142
|
+
data: params.data,
|
|
143
|
+
from: params.from,
|
|
144
|
+
...(gas === undefined || new bignumber_js_1.BigNumber(gas).isZero() ? {} : { gas }),
|
|
145
|
+
maxFeePerGas: params.maxFeePerGas,
|
|
146
|
+
maxPriorityFeePerGas: params.maxPriorityFeePerGas,
|
|
147
|
+
to: params.to,
|
|
148
|
+
value: params.value,
|
|
149
|
+
};
|
|
150
|
+
}),
|
|
138
151
|
};
|
|
139
152
|
}
|
|
140
153
|
//# sourceMappingURL=relay-validation.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relay-validation.cjs","sourceRoot":"","sources":["../../../src/strategy/relay/relay-validation.ts"],"names":[],"mappings":"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","sourcesContent":["import { toHex } from '@metamask/controller-utils';\nimport { generateEIP7702BatchTransaction } from '@metamask/transaction-controller';\nimport type {\n TransactionMeta,\n TransactionParams,\n} from '@metamask/transaction-controller';\nimport { createModuleLogger } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { projectLogger } from '../../logger.js';\nimport type {\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types.js';\nimport { isRelayValidationEnabled } from '../../utils/feature-flags.js';\nimport {\n validateQuoteExecution,\n QuoteError,\n isQuoteError,\n} from '../../utils/validation.js';\nimport type { QuoteSimulation } from '../../utils/validation.js';\nimport { getRelayExecuteRequest } from './relay-submit-execute.js';\nimport { getRelaySubmitCalls } from './relay-submit.js';\nimport type { RelayExecuteRequest, RelayQuote } from './types.js';\n\nconst log = createModuleLogger(projectLogger, 'relay-validation');\n\nexport type ValidateRelayQuotesRequest = {\n messenger: TransactionPayControllerMessenger;\n quotes: TransactionPayQuote<RelayQuote>[];\n signal?: AbortSignal;\n transaction: TransactionMeta;\n};\n\nexport async function validateRelayQuotes(\n request: ValidateRelayQuotesRequest,\n): Promise<void> {\n if (!isRelayValidationEnabled(request.messenger)) {\n return;\n }\n\n for (const quote of request.quotes) {\n if (shouldSkipValidation(quote)) {\n continue;\n }\n\n try {\n const { calls } = await getRelaySubmitCalls({\n messenger: request.messenger,\n quote,\n transaction: request.transaction,\n });\n\n const executeRequest = quote.original.metamask.isExecute\n ? await getRelayExecuteRequest({\n allParams: calls,\n messenger: request.messenger,\n quote,\n requestId: quote.original.steps[0].requestId,\n transaction: request.transaction,\n })\n : undefined;\n\n await validateQuoteExecution({\n messenger: request.messenger,\n quote,\n signal: request.signal,\n simulation: buildRelayValidationSimulation(\n quote,\n calls,\n executeRequest,\n ),\n });\n } catch (error) {\n if (request.signal?.aborted) {\n throw error;\n }\n throw toQuoteError(error);\n }\n }\n}\n\nfunction shouldSkipValidation(quote: TransactionPayQuote<RelayQuote>): boolean {\n const { request } = quote;\n return Boolean(\n request.isHyperliquidSource ?? request.isPolymarketDepositWallet ?? false,\n );\n}\n\nfunction toQuoteError(error: unknown): QuoteError {\n if (isQuoteError(error)) {\n return error;\n }\n return new QuoteError({\n message: 'Quote simulation failed',\n reason: 'simulation-failed',\n detail: [(error as Error).message],\n });\n}\n\nfunction buildRelayValidationSimulation(\n quote: TransactionPayQuote<RelayQuote>,\n calls: TransactionParams[],\n executeRequest?: Omit<RelayExecuteRequest, 'metamask'>,\n): QuoteSimulation {\n const { from, sourceChainId, targetChainId } = quote.request;\n const context = { from, sourceChainId, targetChainId };\n\n if (executeRequest) {\n log('Building execute simulation', context);\n return buildRelayExecuteSimulation(quote, executeRequest);\n }\n if (quote.original.metamask.is7702) {\n log('Building 7702 batch simulation', context);\n return buildRelay7702BatchSimulation(quote, calls);\n }\n log('Building normal simulation', context);\n return buildRelayNormalSimulation(calls);\n}\n\nfunction buildRelayExecuteSimulation(\n quote: TransactionPayQuote<RelayQuote>,\n executeRequest: Omit<RelayExecuteRequest, 'metamask'>,\n): QuoteSimulation {\n const { value } = executeRequest.data;\n const valueHex = new BigNumber(value).toString(16).replace(/^/u, '0x') as Hex;\n return {\n transactions: [\n {\n ...(executeRequest.data.authorizationList?.length\n ? {\n authorizationList: executeRequest.data.authorizationList.map(\n (auth) => ({ address: auth.address, from: quote.request.from }),\n ),\n }\n : {}),\n data: executeRequest.data.data,\n from: quote.request.from,\n to: executeRequest.data.to,\n value: valueHex,\n },\n ],\n };\n}\n\nfunction buildRelay7702BatchSimulation(\n quote: TransactionPayQuote<RelayQuote>,\n calls: TransactionParams[],\n): QuoteSimulation {\n const { from } = quote.request;\n const gas = quote.original.metamask.gasLimits[0];\n\n const batchTx = generateEIP7702BatchTransaction(\n from,\n calls.map((params) => ({\n to: params.to as Hex,\n data: params.data as Hex,\n value: params.value as Hex,\n })),\n );\n\n const authList = quote.original.request.authorizationList?.length\n ? quote.original.request.authorizationList.map((auth) => ({\n address: auth.address,\n from,\n }))\n : undefined;\n\n return {\n transactions: [\n {\n ...(authList ? { authorizationList: authList } : {}),\n data: batchTx.data,\n from,\n ...(gas === undefined ? {} : { gas: toHex(gas) }),\n to: batchTx.to as Hex,\n value: '0x0',\n },\n ],\n };\n}\n\nfunction buildRelayNormalSimulation(\n calls: TransactionParams[],\n): QuoteSimulation {\n return {\n transactions: calls.map((params) => ({\n data: params.data as Hex | undefined,\n from: params.from as Hex,\n gas: params.gas as Hex | undefined,\n maxFeePerGas: params.maxFeePerGas as Hex | undefined,\n maxPriorityFeePerGas: params.maxPriorityFeePerGas as Hex | undefined,\n to: params.to as Hex | undefined,\n value: params.value as Hex,\n })),\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"relay-validation.cjs","sourceRoot":"","sources":["../../../src/strategy/relay/relay-validation.ts"],"names":[],"mappings":"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","sourcesContent":["import { toHex } from '@metamask/controller-utils';\nimport { generateEIP7702BatchTransaction } from '@metamask/transaction-controller';\nimport type {\n TransactionMeta,\n TransactionParams,\n} from '@metamask/transaction-controller';\nimport { createModuleLogger } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { projectLogger } from '../../logger.js';\nimport type {\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types.js';\nimport {\n getEIP7702UpgradeContractAddress,\n isRelayValidationEnabled,\n} from '../../utils/feature-flags.js';\nimport {\n validateQuoteExecution,\n QuoteError,\n isQuoteError,\n} from '../../utils/validation.js';\nimport type { QuoteSimulation } from '../../utils/validation.js';\nimport { getRelayExecuteRequest } from './relay-submit-execute.js';\nimport { getRelaySubmitCalls } from './relay-submit.js';\nimport type { RelayExecuteRequest, RelayQuote } from './types.js';\n\nconst log = createModuleLogger(projectLogger, 'relay-validation');\n\nexport type ValidateRelayQuotesRequest = {\n messenger: TransactionPayControllerMessenger;\n quotes: TransactionPayQuote<RelayQuote>[];\n signal?: AbortSignal;\n transaction: TransactionMeta;\n};\n\nexport async function validateRelayQuotes(\n request: ValidateRelayQuotesRequest,\n): Promise<void> {\n if (!isRelayValidationEnabled(request.messenger)) {\n return;\n }\n\n for (const quote of request.quotes) {\n if (shouldSkipValidation(quote)) {\n continue;\n }\n\n try {\n const { calls } = await getRelaySubmitCalls({\n messenger: request.messenger,\n quote,\n transaction: request.transaction,\n });\n\n const executeRequest = quote.original.metamask.isExecute\n ? await getRelayExecuteRequest({\n allParams: calls,\n messenger: request.messenger,\n quote,\n requestId: quote.original.steps[0].requestId,\n transaction: request.transaction,\n })\n : undefined;\n\n await validateQuoteExecution({\n messenger: request.messenger,\n quote,\n signal: request.signal,\n simulation: buildRelayValidationSimulation(\n request.messenger,\n quote,\n calls,\n executeRequest,\n ),\n });\n } catch (error) {\n if (request.signal?.aborted) {\n throw error;\n }\n const quoteError = toQuoteError(error);\n if (quoteError.info.reason === 'insufficient-source-balance') {\n // Backwards compatibility: keep the entire quote batch (including\n // quotes that may have passed or not yet been validated) so that\n // clients can still show quote details alongside the balance error.\n throw new QuoteError(\n quoteError.info,\n request.quotes as TransactionPayQuote<unknown>[],\n );\n }\n throw quoteError;\n }\n }\n}\n\nfunction shouldSkipValidation(quote: TransactionPayQuote<RelayQuote>): boolean {\n const { request } = quote;\n return Boolean(\n request.isHyperliquidSource ?? request.isPolymarketDepositWallet ?? false,\n );\n}\n\nfunction toQuoteError(error: unknown): QuoteError {\n if (isQuoteError(error)) {\n return error;\n }\n return new QuoteError({\n message: 'Quote simulation failed',\n reason: 'simulation-failed',\n detail: [(error as Error).message],\n });\n}\n\nfunction buildRelayValidationSimulation(\n messenger: TransactionPayControllerMessenger,\n quote: TransactionPayQuote<RelayQuote>,\n calls: TransactionParams[],\n executeRequest?: Omit<RelayExecuteRequest, 'metamask'>,\n): QuoteSimulation {\n const { from, sourceChainId, targetChainId } = quote.request;\n const context = { from, sourceChainId, targetChainId };\n\n if (executeRequest) {\n log('Building execute simulation', context);\n return buildRelayExecuteSimulation(quote, executeRequest);\n }\n if (quote.original.metamask.is7702) {\n log('Building 7702 batch simulation', context);\n return buildRelay7702BatchSimulation(messenger, quote, calls);\n }\n log('Building normal simulation', context);\n return buildRelayNormalSimulation(calls);\n}\n\nfunction buildRelayExecuteSimulation(\n quote: TransactionPayQuote<RelayQuote>,\n executeRequest: Omit<RelayExecuteRequest, 'metamask'>,\n): QuoteSimulation {\n const { value } = executeRequest.data;\n const valueHex = new BigNumber(value).toString(16).replace(/^/u, '0x') as Hex;\n return {\n transactions: [\n {\n ...(executeRequest.data.authorizationList?.length\n ? {\n authorizationList: executeRequest.data.authorizationList.map(\n (auth) => ({ address: auth.address, from: quote.request.from }),\n ),\n }\n : {}),\n data: executeRequest.data.data,\n from: quote.request.from,\n to: executeRequest.data.to,\n value: valueHex,\n },\n ],\n };\n}\n\nfunction buildRelay7702BatchSimulation(\n messenger: TransactionPayControllerMessenger,\n quote: TransactionPayQuote<RelayQuote>,\n calls: TransactionParams[],\n): QuoteSimulation {\n const { from, sourceChainId } = quote.request;\n const gas = quote.original.metamask.gasLimits[0];\n\n const batchTx = generateEIP7702BatchTransaction(\n from,\n calls.map((params) => ({\n to: params.to as Hex,\n data: params.data as Hex,\n value: params.value as Hex,\n })),\n );\n\n // The batch call is an ERC-7821 `execute` on the sender's own account, so the\n // account must appear upgraded for the simulation to succeed. The quote does\n // not always carry an authorization, and there is no fast way to check the\n // live upgrade state, so an authorization is always included: the delegator\n // address comes from the quote when present, otherwise from the configured\n // EIP-7702 upgrade contract for the chain.\n const address =\n quote.original.request.authorizationList?.[0]?.address ??\n getEIP7702UpgradeContractAddress(messenger, sourceChainId);\n\n const authorizationList = address ? [{ address, from }] : undefined;\n\n return {\n transactions: [\n {\n ...(authorizationList ? { authorizationList } : {}),\n data: batchTx.data,\n from,\n ...(gas === undefined || gas === 0 ? {} : { gas: toHex(gas) }),\n to: batchTx.to as Hex,\n value: '0x0',\n },\n ],\n };\n}\n\nfunction buildRelayNormalSimulation(\n calls: TransactionParams[],\n): QuoteSimulation {\n return {\n transactions: calls.map((params) => {\n const gas = params.gas as Hex | undefined;\n return {\n data: params.data as Hex | undefined,\n from: params.from as Hex,\n ...(gas === undefined || new BigNumber(gas).isZero() ? {} : { gas }),\n maxFeePerGas: params.maxFeePerGas as Hex | undefined,\n maxPriorityFeePerGas: params.maxPriorityFeePerGas as Hex | undefined,\n to: params.to as Hex | undefined,\n value: params.value as Hex,\n };\n }),\n };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relay-validation.d.cts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-validation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,eAAe,EAEhB,yCAAyC;AAM1C,OAAO,KAAK,EACV,iCAAiC,EACjC,mBAAmB,EACpB,wBAAuB;
|
|
1
|
+
{"version":3,"file":"relay-validation.d.cts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-validation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,eAAe,EAEhB,yCAAyC;AAM1C,OAAO,KAAK,EACV,iCAAiC,EACjC,mBAAmB,EACpB,wBAAuB;AAaxB,OAAO,KAAK,EAAuB,UAAU,EAAE,oBAAmB;AAIlE,MAAM,MAAM,0BAA0B,GAAG;IACvC,SAAS,EAAE,iCAAiC,CAAC;IAC7C,MAAM,EAAE,mBAAmB,CAAC,UAAU,CAAC,EAAE,CAAC;IAC1C,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,WAAW,EAAE,eAAe,CAAC;CAC9B,CAAC;AAEF,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,IAAI,CAAC,CAuDf"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relay-validation.d.mts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-validation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,eAAe,EAEhB,yCAAyC;AAM1C,OAAO,KAAK,EACV,iCAAiC,EACjC,mBAAmB,EACpB,wBAAuB;
|
|
1
|
+
{"version":3,"file":"relay-validation.d.mts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-validation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,eAAe,EAEhB,yCAAyC;AAM1C,OAAO,KAAK,EACV,iCAAiC,EACjC,mBAAmB,EACpB,wBAAuB;AAaxB,OAAO,KAAK,EAAuB,UAAU,EAAE,oBAAmB;AAIlE,MAAM,MAAM,0BAA0B,GAAG;IACvC,SAAS,EAAE,iCAAiC,CAAC;IAC7C,MAAM,EAAE,mBAAmB,CAAC,UAAU,CAAC,EAAE,CAAC;IAC1C,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,WAAW,EAAE,eAAe,CAAC;CAC9B,CAAC;AAEF,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,IAAI,CAAC,CAuDf"}
|
|
@@ -3,7 +3,7 @@ import { generateEIP7702BatchTransaction } from "@metamask/transaction-controlle
|
|
|
3
3
|
import { createModuleLogger } from "@metamask/utils";
|
|
4
4
|
import { BigNumber } from "bignumber.js";
|
|
5
5
|
import { projectLogger } from "../../logger.mjs";
|
|
6
|
-
import { isRelayValidationEnabled } from "../../utils/feature-flags.mjs";
|
|
6
|
+
import { getEIP7702UpgradeContractAddress, isRelayValidationEnabled } from "../../utils/feature-flags.mjs";
|
|
7
7
|
import { validateQuoteExecution, QuoteError, isQuoteError } from "../../utils/validation.mjs";
|
|
8
8
|
import { getRelayExecuteRequest } from "./relay-submit-execute.mjs";
|
|
9
9
|
import { getRelaySubmitCalls } from "./relay-submit.mjs";
|
|
@@ -35,14 +35,21 @@ export async function validateRelayQuotes(request) {
|
|
|
35
35
|
messenger: request.messenger,
|
|
36
36
|
quote,
|
|
37
37
|
signal: request.signal,
|
|
38
|
-
simulation: buildRelayValidationSimulation(quote, calls, executeRequest),
|
|
38
|
+
simulation: buildRelayValidationSimulation(request.messenger, quote, calls, executeRequest),
|
|
39
39
|
});
|
|
40
40
|
}
|
|
41
41
|
catch (error) {
|
|
42
42
|
if (request.signal?.aborted) {
|
|
43
43
|
throw error;
|
|
44
44
|
}
|
|
45
|
-
|
|
45
|
+
const quoteError = toQuoteError(error);
|
|
46
|
+
if (quoteError.info.reason === 'insufficient-source-balance') {
|
|
47
|
+
// Backwards compatibility: keep the entire quote batch (including
|
|
48
|
+
// quotes that may have passed or not yet been validated) so that
|
|
49
|
+
// clients can still show quote details alongside the balance error.
|
|
50
|
+
throw new QuoteError(quoteError.info, request.quotes);
|
|
51
|
+
}
|
|
52
|
+
throw quoteError;
|
|
46
53
|
}
|
|
47
54
|
}
|
|
48
55
|
}
|
|
@@ -60,7 +67,7 @@ function toQuoteError(error) {
|
|
|
60
67
|
detail: [error.message],
|
|
61
68
|
});
|
|
62
69
|
}
|
|
63
|
-
function buildRelayValidationSimulation(quote, calls, executeRequest) {
|
|
70
|
+
function buildRelayValidationSimulation(messenger, quote, calls, executeRequest) {
|
|
64
71
|
const { from, sourceChainId, targetChainId } = quote.request;
|
|
65
72
|
const context = { from, sourceChainId, targetChainId };
|
|
66
73
|
if (executeRequest) {
|
|
@@ -69,7 +76,7 @@ function buildRelayValidationSimulation(quote, calls, executeRequest) {
|
|
|
69
76
|
}
|
|
70
77
|
if (quote.original.metamask.is7702) {
|
|
71
78
|
log('Building 7702 batch simulation', context);
|
|
72
|
-
return buildRelay7702BatchSimulation(quote, calls);
|
|
79
|
+
return buildRelay7702BatchSimulation(messenger, quote, calls);
|
|
73
80
|
}
|
|
74
81
|
log('Building normal simulation', context);
|
|
75
82
|
return buildRelayNormalSimulation(calls);
|
|
@@ -93,27 +100,30 @@ function buildRelayExecuteSimulation(quote, executeRequest) {
|
|
|
93
100
|
],
|
|
94
101
|
};
|
|
95
102
|
}
|
|
96
|
-
function buildRelay7702BatchSimulation(quote, calls) {
|
|
97
|
-
const { from } = quote.request;
|
|
103
|
+
function buildRelay7702BatchSimulation(messenger, quote, calls) {
|
|
104
|
+
const { from, sourceChainId } = quote.request;
|
|
98
105
|
const gas = quote.original.metamask.gasLimits[0];
|
|
99
106
|
const batchTx = generateEIP7702BatchTransaction(from, calls.map((params) => ({
|
|
100
107
|
to: params.to,
|
|
101
108
|
data: params.data,
|
|
102
109
|
value: params.value,
|
|
103
110
|
})));
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
111
|
+
// The batch call is an ERC-7821 `execute` on the sender's own account, so the
|
|
112
|
+
// account must appear upgraded for the simulation to succeed. The quote does
|
|
113
|
+
// not always carry an authorization, and there is no fast way to check the
|
|
114
|
+
// live upgrade state, so an authorization is always included: the delegator
|
|
115
|
+
// address comes from the quote when present, otherwise from the configured
|
|
116
|
+
// EIP-7702 upgrade contract for the chain.
|
|
117
|
+
const address = quote.original.request.authorizationList?.[0]?.address ??
|
|
118
|
+
getEIP7702UpgradeContractAddress(messenger, sourceChainId);
|
|
119
|
+
const authorizationList = address ? [{ address, from }] : undefined;
|
|
110
120
|
return {
|
|
111
121
|
transactions: [
|
|
112
122
|
{
|
|
113
|
-
...(
|
|
123
|
+
...(authorizationList ? { authorizationList } : {}),
|
|
114
124
|
data: batchTx.data,
|
|
115
125
|
from,
|
|
116
|
-
...(gas === undefined ? {} : { gas: toHex(gas) }),
|
|
126
|
+
...(gas === undefined || gas === 0 ? {} : { gas: toHex(gas) }),
|
|
117
127
|
to: batchTx.to,
|
|
118
128
|
value: '0x0',
|
|
119
129
|
},
|
|
@@ -122,15 +132,18 @@ function buildRelay7702BatchSimulation(quote, calls) {
|
|
|
122
132
|
}
|
|
123
133
|
function buildRelayNormalSimulation(calls) {
|
|
124
134
|
return {
|
|
125
|
-
transactions: calls.map((params) =>
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
135
|
+
transactions: calls.map((params) => {
|
|
136
|
+
const gas = params.gas;
|
|
137
|
+
return {
|
|
138
|
+
data: params.data,
|
|
139
|
+
from: params.from,
|
|
140
|
+
...(gas === undefined || new BigNumber(gas).isZero() ? {} : { gas }),
|
|
141
|
+
maxFeePerGas: params.maxFeePerGas,
|
|
142
|
+
maxPriorityFeePerGas: params.maxPriorityFeePerGas,
|
|
143
|
+
to: params.to,
|
|
144
|
+
value: params.value,
|
|
145
|
+
};
|
|
146
|
+
}),
|
|
134
147
|
};
|
|
135
148
|
}
|
|
136
149
|
//# sourceMappingURL=relay-validation.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relay-validation.mjs","sourceRoot":"","sources":["../../../src/strategy/relay/relay-validation.ts"],"names":[],"mappings":"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","sourcesContent":["import { toHex } from '@metamask/controller-utils';\nimport { generateEIP7702BatchTransaction } from '@metamask/transaction-controller';\nimport type {\n TransactionMeta,\n TransactionParams,\n} from '@metamask/transaction-controller';\nimport { createModuleLogger } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { projectLogger } from '../../logger.js';\nimport type {\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types.js';\nimport { isRelayValidationEnabled } from '../../utils/feature-flags.js';\nimport {\n validateQuoteExecution,\n QuoteError,\n isQuoteError,\n} from '../../utils/validation.js';\nimport type { QuoteSimulation } from '../../utils/validation.js';\nimport { getRelayExecuteRequest } from './relay-submit-execute.js';\nimport { getRelaySubmitCalls } from './relay-submit.js';\nimport type { RelayExecuteRequest, RelayQuote } from './types.js';\n\nconst log = createModuleLogger(projectLogger, 'relay-validation');\n\nexport type ValidateRelayQuotesRequest = {\n messenger: TransactionPayControllerMessenger;\n quotes: TransactionPayQuote<RelayQuote>[];\n signal?: AbortSignal;\n transaction: TransactionMeta;\n};\n\nexport async function validateRelayQuotes(\n request: ValidateRelayQuotesRequest,\n): Promise<void> {\n if (!isRelayValidationEnabled(request.messenger)) {\n return;\n }\n\n for (const quote of request.quotes) {\n if (shouldSkipValidation(quote)) {\n continue;\n }\n\n try {\n const { calls } = await getRelaySubmitCalls({\n messenger: request.messenger,\n quote,\n transaction: request.transaction,\n });\n\n const executeRequest = quote.original.metamask.isExecute\n ? await getRelayExecuteRequest({\n allParams: calls,\n messenger: request.messenger,\n quote,\n requestId: quote.original.steps[0].requestId,\n transaction: request.transaction,\n })\n : undefined;\n\n await validateQuoteExecution({\n messenger: request.messenger,\n quote,\n signal: request.signal,\n simulation: buildRelayValidationSimulation(\n quote,\n calls,\n executeRequest,\n ),\n });\n } catch (error) {\n if (request.signal?.aborted) {\n throw error;\n }\n throw toQuoteError(error);\n }\n }\n}\n\nfunction shouldSkipValidation(quote: TransactionPayQuote<RelayQuote>): boolean {\n const { request } = quote;\n return Boolean(\n request.isHyperliquidSource ?? request.isPolymarketDepositWallet ?? false,\n );\n}\n\nfunction toQuoteError(error: unknown): QuoteError {\n if (isQuoteError(error)) {\n return error;\n }\n return new QuoteError({\n message: 'Quote simulation failed',\n reason: 'simulation-failed',\n detail: [(error as Error).message],\n });\n}\n\nfunction buildRelayValidationSimulation(\n quote: TransactionPayQuote<RelayQuote>,\n calls: TransactionParams[],\n executeRequest?: Omit<RelayExecuteRequest, 'metamask'>,\n): QuoteSimulation {\n const { from, sourceChainId, targetChainId } = quote.request;\n const context = { from, sourceChainId, targetChainId };\n\n if (executeRequest) {\n log('Building execute simulation', context);\n return buildRelayExecuteSimulation(quote, executeRequest);\n }\n if (quote.original.metamask.is7702) {\n log('Building 7702 batch simulation', context);\n return buildRelay7702BatchSimulation(quote, calls);\n }\n log('Building normal simulation', context);\n return buildRelayNormalSimulation(calls);\n}\n\nfunction buildRelayExecuteSimulation(\n quote: TransactionPayQuote<RelayQuote>,\n executeRequest: Omit<RelayExecuteRequest, 'metamask'>,\n): QuoteSimulation {\n const { value } = executeRequest.data;\n const valueHex = new BigNumber(value).toString(16).replace(/^/u, '0x') as Hex;\n return {\n transactions: [\n {\n ...(executeRequest.data.authorizationList?.length\n ? {\n authorizationList: executeRequest.data.authorizationList.map(\n (auth) => ({ address: auth.address, from: quote.request.from }),\n ),\n }\n : {}),\n data: executeRequest.data.data,\n from: quote.request.from,\n to: executeRequest.data.to,\n value: valueHex,\n },\n ],\n };\n}\n\nfunction buildRelay7702BatchSimulation(\n quote: TransactionPayQuote<RelayQuote>,\n calls: TransactionParams[],\n): QuoteSimulation {\n const { from } = quote.request;\n const gas = quote.original.metamask.gasLimits[0];\n\n const batchTx = generateEIP7702BatchTransaction(\n from,\n calls.map((params) => ({\n to: params.to as Hex,\n data: params.data as Hex,\n value: params.value as Hex,\n })),\n );\n\n const authList = quote.original.request.authorizationList?.length\n ? quote.original.request.authorizationList.map((auth) => ({\n address: auth.address,\n from,\n }))\n : undefined;\n\n return {\n transactions: [\n {\n ...(authList ? { authorizationList: authList } : {}),\n data: batchTx.data,\n from,\n ...(gas === undefined ? {} : { gas: toHex(gas) }),\n to: batchTx.to as Hex,\n value: '0x0',\n },\n ],\n };\n}\n\nfunction buildRelayNormalSimulation(\n calls: TransactionParams[],\n): QuoteSimulation {\n return {\n transactions: calls.map((params) => ({\n data: params.data as Hex | undefined,\n from: params.from as Hex,\n gas: params.gas as Hex | undefined,\n maxFeePerGas: params.maxFeePerGas as Hex | undefined,\n maxPriorityFeePerGas: params.maxPriorityFeePerGas as Hex | undefined,\n to: params.to as Hex | undefined,\n value: params.value as Hex,\n })),\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"relay-validation.mjs","sourceRoot":"","sources":["../../../src/strategy/relay/relay-validation.ts"],"names":[],"mappings":"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","sourcesContent":["import { toHex } from '@metamask/controller-utils';\nimport { generateEIP7702BatchTransaction } from '@metamask/transaction-controller';\nimport type {\n TransactionMeta,\n TransactionParams,\n} from '@metamask/transaction-controller';\nimport { createModuleLogger } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { projectLogger } from '../../logger.js';\nimport type {\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../types.js';\nimport {\n getEIP7702UpgradeContractAddress,\n isRelayValidationEnabled,\n} from '../../utils/feature-flags.js';\nimport {\n validateQuoteExecution,\n QuoteError,\n isQuoteError,\n} from '../../utils/validation.js';\nimport type { QuoteSimulation } from '../../utils/validation.js';\nimport { getRelayExecuteRequest } from './relay-submit-execute.js';\nimport { getRelaySubmitCalls } from './relay-submit.js';\nimport type { RelayExecuteRequest, RelayQuote } from './types.js';\n\nconst log = createModuleLogger(projectLogger, 'relay-validation');\n\nexport type ValidateRelayQuotesRequest = {\n messenger: TransactionPayControllerMessenger;\n quotes: TransactionPayQuote<RelayQuote>[];\n signal?: AbortSignal;\n transaction: TransactionMeta;\n};\n\nexport async function validateRelayQuotes(\n request: ValidateRelayQuotesRequest,\n): Promise<void> {\n if (!isRelayValidationEnabled(request.messenger)) {\n return;\n }\n\n for (const quote of request.quotes) {\n if (shouldSkipValidation(quote)) {\n continue;\n }\n\n try {\n const { calls } = await getRelaySubmitCalls({\n messenger: request.messenger,\n quote,\n transaction: request.transaction,\n });\n\n const executeRequest = quote.original.metamask.isExecute\n ? await getRelayExecuteRequest({\n allParams: calls,\n messenger: request.messenger,\n quote,\n requestId: quote.original.steps[0].requestId,\n transaction: request.transaction,\n })\n : undefined;\n\n await validateQuoteExecution({\n messenger: request.messenger,\n quote,\n signal: request.signal,\n simulation: buildRelayValidationSimulation(\n request.messenger,\n quote,\n calls,\n executeRequest,\n ),\n });\n } catch (error) {\n if (request.signal?.aborted) {\n throw error;\n }\n const quoteError = toQuoteError(error);\n if (quoteError.info.reason === 'insufficient-source-balance') {\n // Backwards compatibility: keep the entire quote batch (including\n // quotes that may have passed or not yet been validated) so that\n // clients can still show quote details alongside the balance error.\n throw new QuoteError(\n quoteError.info,\n request.quotes as TransactionPayQuote<unknown>[],\n );\n }\n throw quoteError;\n }\n }\n}\n\nfunction shouldSkipValidation(quote: TransactionPayQuote<RelayQuote>): boolean {\n const { request } = quote;\n return Boolean(\n request.isHyperliquidSource ?? request.isPolymarketDepositWallet ?? false,\n );\n}\n\nfunction toQuoteError(error: unknown): QuoteError {\n if (isQuoteError(error)) {\n return error;\n }\n return new QuoteError({\n message: 'Quote simulation failed',\n reason: 'simulation-failed',\n detail: [(error as Error).message],\n });\n}\n\nfunction buildRelayValidationSimulation(\n messenger: TransactionPayControllerMessenger,\n quote: TransactionPayQuote<RelayQuote>,\n calls: TransactionParams[],\n executeRequest?: Omit<RelayExecuteRequest, 'metamask'>,\n): QuoteSimulation {\n const { from, sourceChainId, targetChainId } = quote.request;\n const context = { from, sourceChainId, targetChainId };\n\n if (executeRequest) {\n log('Building execute simulation', context);\n return buildRelayExecuteSimulation(quote, executeRequest);\n }\n if (quote.original.metamask.is7702) {\n log('Building 7702 batch simulation', context);\n return buildRelay7702BatchSimulation(messenger, quote, calls);\n }\n log('Building normal simulation', context);\n return buildRelayNormalSimulation(calls);\n}\n\nfunction buildRelayExecuteSimulation(\n quote: TransactionPayQuote<RelayQuote>,\n executeRequest: Omit<RelayExecuteRequest, 'metamask'>,\n): QuoteSimulation {\n const { value } = executeRequest.data;\n const valueHex = new BigNumber(value).toString(16).replace(/^/u, '0x') as Hex;\n return {\n transactions: [\n {\n ...(executeRequest.data.authorizationList?.length\n ? {\n authorizationList: executeRequest.data.authorizationList.map(\n (auth) => ({ address: auth.address, from: quote.request.from }),\n ),\n }\n : {}),\n data: executeRequest.data.data,\n from: quote.request.from,\n to: executeRequest.data.to,\n value: valueHex,\n },\n ],\n };\n}\n\nfunction buildRelay7702BatchSimulation(\n messenger: TransactionPayControllerMessenger,\n quote: TransactionPayQuote<RelayQuote>,\n calls: TransactionParams[],\n): QuoteSimulation {\n const { from, sourceChainId } = quote.request;\n const gas = quote.original.metamask.gasLimits[0];\n\n const batchTx = generateEIP7702BatchTransaction(\n from,\n calls.map((params) => ({\n to: params.to as Hex,\n data: params.data as Hex,\n value: params.value as Hex,\n })),\n );\n\n // The batch call is an ERC-7821 `execute` on the sender's own account, so the\n // account must appear upgraded for the simulation to succeed. The quote does\n // not always carry an authorization, and there is no fast way to check the\n // live upgrade state, so an authorization is always included: the delegator\n // address comes from the quote when present, otherwise from the configured\n // EIP-7702 upgrade contract for the chain.\n const address =\n quote.original.request.authorizationList?.[0]?.address ??\n getEIP7702UpgradeContractAddress(messenger, sourceChainId);\n\n const authorizationList = address ? [{ address, from }] : undefined;\n\n return {\n transactions: [\n {\n ...(authorizationList ? { authorizationList } : {}),\n data: batchTx.data,\n from,\n ...(gas === undefined || gas === 0 ? {} : { gas: toHex(gas) }),\n to: batchTx.to as Hex,\n value: '0x0',\n },\n ],\n };\n}\n\nfunction buildRelayNormalSimulation(\n calls: TransactionParams[],\n): QuoteSimulation {\n return {\n transactions: calls.map((params) => {\n const gas = params.gas as Hex | undefined;\n return {\n data: params.data as Hex | undefined,\n from: params.from as Hex,\n ...(gas === undefined || new BigNumber(gas).isZero() ? {} : { gas }),\n maxFeePerGas: params.maxFeePerGas as Hex | undefined,\n maxPriorityFeePerGas: params.maxPriorityFeePerGas as Hex | undefined,\n to: params.to as Hex | undefined,\n value: params.value as Hex,\n };\n }),\n };\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isEIP7702Chain = exports.getHyperliquidActivationFeeConfig = exports.getFiatOrderPollTimeoutMs = exports.getFiatOrderPollIntervalMs = exports.getFiatVaultDisabled = exports.getDirectMoneyMusdEnabled = exports.getFiatMaxRateDriftPercent = exports.getFiatFeeReserveMultiplier = exports.getFiatEnabledTypes = exports.getFiatAssetPerTransactionType = exports.getAssetsUnifyStateFeature = exports.getSlippage = exports.getGasBuffer = exports.getFallbackGas = exports.getServerPollingTimeout = exports.getServerPollingInterval = exports.getRelayPollingTimeout = exports.getRelayPollingInterval = exports.getRelayOriginGasOverhead = exports.isChainExcludedFromInfura = exports.isRelayValidationEnabled = exports.isRelayExecuteEnabled = exports.getPayStrategiesConfig = exports.getStablecoins = exports.getFeatureFlags = exports.getStrategy = exports.getStrategyOrder = exports.DEFAULT_STRATEGY_ORDER = exports.DEFAULT_SERVER_BASE_URL = exports.DEFAULT_ACROSS_API_BASE = exports.DEFAULT_HYPERLIQUID_ACTIVATION_FEE_USD = exports.DEFAULT_SLIPPAGE = exports.DEFAULT_RELAY_ORIGIN_GAS_OVERHEAD = exports.DEFAULT_RELAY_QUOTE_URL = exports.DEFAULT_RELAY_EXECUTE_URL = exports.DEFAULT_FALLBACK_GAS_MAX = exports.DEFAULT_FALLBACK_GAS_ESTIMATE = exports.DEFAULT_GAS_BUFFER = exports.DEFAULT_ORDER_POLL_TIMEOUT_MS = exports.DEFAULT_ORDER_POLL_INTERVAL_MS = exports.DEFAULT_MAX_RATE_DRIFT_PERCENT = exports.DEFAULT_FEE_RESERVE_MULTIPLIER = void 0;
|
|
3
|
+
exports.getEIP7702UpgradeContractAddress = exports.isEIP7702Chain = exports.getHyperliquidActivationFeeConfig = exports.getFiatOrderPollTimeoutMs = exports.getFiatOrderPollIntervalMs = exports.getFiatVaultDisabled = exports.getDirectMoneyMusdEnabled = exports.getFiatMaxRateDriftPercent = exports.getFiatFeeReserveMultiplier = exports.getFiatEnabledTypes = exports.getFiatAssetPerTransactionType = exports.getAssetsUnifyStateFeature = exports.getSlippage = exports.getGasBuffer = exports.getFallbackGas = exports.getServerPollingTimeout = exports.getServerPollingInterval = exports.getRelayPollingTimeout = exports.getRelayPollingInterval = exports.getRelayOriginGasOverhead = exports.isChainExcludedFromInfura = exports.isRelayValidationEnabled = exports.isRelayExecuteEnabled = exports.getPayStrategiesConfig = exports.getStablecoins = exports.getFeatureFlags = exports.getStrategy = exports.getStrategyOrder = exports.DEFAULT_STRATEGY_ORDER = exports.DEFAULT_SERVER_BASE_URL = exports.DEFAULT_ACROSS_API_BASE = exports.DEFAULT_HYPERLIQUID_ACTIVATION_FEE_USD = exports.DEFAULT_SLIPPAGE = exports.DEFAULT_RELAY_ORIGIN_GAS_OVERHEAD = exports.DEFAULT_RELAY_QUOTE_URL = exports.DEFAULT_RELAY_EXECUTE_URL = exports.DEFAULT_FALLBACK_GAS_MAX = exports.DEFAULT_FALLBACK_GAS_ESTIMATE = exports.DEFAULT_GAS_BUFFER = exports.DEFAULT_ORDER_POLL_TIMEOUT_MS = exports.DEFAULT_ORDER_POLL_INTERVAL_MS = exports.DEFAULT_MAX_RATE_DRIFT_PERCENT = exports.DEFAULT_FEE_RESERVE_MULTIPLIER = void 0;
|
|
4
4
|
const utils_1 = require("@metamask/utils");
|
|
5
5
|
const bignumber_js_1 = require("bignumber.js");
|
|
6
6
|
const lodash_1 = require("lodash");
|
|
@@ -639,4 +639,19 @@ function isEIP7702Chain(messenger, chainId) {
|
|
|
639
639
|
return supportedChains.some((supported) => supported.toLowerCase() === chainId.toLowerCase());
|
|
640
640
|
}
|
|
641
641
|
exports.isEIP7702Chain = isEIP7702Chain;
|
|
642
|
+
/**
|
|
643
|
+
* Get the EIP-7702 upgrade contract address for a chain from the
|
|
644
|
+
* `confirmations_eip_7702.contracts` feature flag, if any.
|
|
645
|
+
*
|
|
646
|
+
* @param messenger - Controller messenger.
|
|
647
|
+
* @param chainId - Chain ID to resolve the upgrade contract for.
|
|
648
|
+
* @returns The upgrade contract address, or `undefined` when none is set.
|
|
649
|
+
*/
|
|
650
|
+
function getEIP7702UpgradeContractAddress(messenger, chainId) {
|
|
651
|
+
const state = messenger.call('RemoteFeatureFlagController:getState');
|
|
652
|
+
const eip7702Flags = state.remoteFeatureFlags.confirmations_eip_7702;
|
|
653
|
+
const contracts = getCaseInsensitive(eip7702Flags?.contracts, chainId);
|
|
654
|
+
return contracts?.[0]?.address;
|
|
655
|
+
}
|
|
656
|
+
exports.getEIP7702UpgradeContractAddress = getEIP7702UpgradeContractAddress;
|
|
642
657
|
//# sourceMappingURL=feature-flags.cjs.map
|