@metamask-previews/transaction-pay-controller 31.0.0-preview-2c49dc768 → 31.0.0-preview-21bea3028
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 +0 -8
- package/dist/strategy/relay/relay-validation.d.ts.map +1 -1
- package/dist/strategy/relay/relay-validation.js +93 -26
- package/dist/strategy/relay/relay-validation.js.map +1 -1
- package/dist/strategy/server/server-quotes.d.ts.map +1 -1
- package/dist/strategy/server/server-quotes.js +2 -11
- package/dist/strategy/server/server-quotes.js.map +1 -1
- package/dist/strategy/server/server-submit.d.ts +1 -33
- package/dist/strategy/server/server-submit.d.ts.map +1 -1
- package/dist/strategy/server/server-submit.js +29 -68
- package/dist/strategy/server/server-submit.js.map +1 -1
- package/dist/utils/feature-flags.d.ts +0 -22
- package/dist/utils/feature-flags.d.ts.map +1 -1
- package/dist/utils/feature-flags.js +21 -42
- package/dist/utils/feature-flags.js.map +1 -1
- package/dist/utils/polymarket/withdraw.d.ts +1 -1
- package/dist/utils/polymarket/withdraw.d.ts.map +1 -1
- package/dist/utils/polymarket/withdraw.js.map +1 -1
- package/dist/utils/simulation.d.ts +0 -48
- package/dist/utils/simulation.d.ts.map +1 -1
- package/dist/utils/simulation.js +0 -90
- package/dist/utils/simulation.js.map +1 -1
- package/dist/utils/validation.d.ts +4 -18
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +0 -46
- package/dist/utils/validation.js.map +1 -1
- package/package.json +2 -2
- package/dist/strategy/server/server-validation.d.ts +0 -19
- package/dist/strategy/server/server-validation.d.ts.map +0 -1
- package/dist/strategy/server/server-validation.js +0 -92
- package/dist/strategy/server/server-validation.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,14 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
-
### Added
|
|
11
|
-
|
|
12
|
-
- Add quote simulation to `ServerStrategy`, gated by the `confirmations_pay_extended.payStrategies.server.validationEnabled` feature flag ([#11198](https://github.com/MetaMask/core/pull/11198))
|
|
13
|
-
|
|
14
|
-
### Changed
|
|
15
|
-
|
|
16
|
-
- Bump `@metamask/assets-controller` from `^20.2.2` to `^20.2.3` ([#11326](https://github.com/MetaMask/core/pull/11326))
|
|
17
|
-
|
|
18
10
|
## [31.0.0]
|
|
19
11
|
|
|
20
12
|
### Changed
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relay-validation.d.ts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-validation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"relay-validation.d.ts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-validation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,eAAe,EAEhB,MAAM,kCAAkC,CAAC;AAM1C,OAAO,KAAK,EACV,iCAAiC,EACjC,mBAAmB,EACpB,MAAM,gBAAgB,CAAC;AAkBxB,OAAO,KAAK,EAAuB,UAAU,EAAE,MAAM,YAAY,CAAC;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,CAiCf"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { toHex } from '@metamask/controller-utils';
|
|
2
|
+
import { generateEIP7702BatchTransaction } from '@metamask/transaction-controller';
|
|
1
3
|
import { createModuleLogger } from '@metamask/utils';
|
|
2
4
|
import { BigNumber } from 'bignumber.js';
|
|
3
5
|
import { projectLogger } from '../../logger.js';
|
|
4
6
|
import { getEIP7702UpgradeContractAddress, isRelayValidationEnabled, } from '../../utils/feature-flags.js';
|
|
5
7
|
import { buildPolymarketDepositWalletSimulation, isPredictWithdraw, } from '../../utils/polymarket/withdraw.js';
|
|
6
|
-
import {
|
|
7
|
-
import { validateQuotes } from '../../utils/validation.js';
|
|
8
|
+
import { validateQuoteExecution, QuoteError, isQuoteError, } from '../../utils/validation.js';
|
|
8
9
|
import { getRelayDepositData } from './deposit-step.js';
|
|
9
10
|
import { getRelayExecuteRequest } from './relay-submit-execute.js';
|
|
10
11
|
import { getRelaySubmitCalls } from './relay-submit.js';
|
|
@@ -13,14 +14,33 @@ export async function validateRelayQuotes(request) {
|
|
|
13
14
|
if (!isRelayValidationEnabled(request.messenger, request.transaction)) {
|
|
14
15
|
return;
|
|
15
16
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
for (const quote of request.quotes) {
|
|
18
|
+
if (shouldSkipValidation(quote, request.transaction)) {
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
const simulation = await buildValidationSimulation(request, quote);
|
|
23
|
+
await validateQuoteExecution({
|
|
24
|
+
messenger: request.messenger,
|
|
25
|
+
quote,
|
|
26
|
+
signal: request.signal,
|
|
27
|
+
simulation,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
if (request.signal?.aborted) {
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
const quoteError = toQuoteError(error);
|
|
35
|
+
if (quoteError.info.reason === 'insufficient-source-balance') {
|
|
36
|
+
// Backwards compatibility: keep the entire quote batch (including
|
|
37
|
+
// quotes that may have passed or not yet been validated) so that
|
|
38
|
+
// clients can still show quote details alongside the balance error.
|
|
39
|
+
throw new QuoteError(quoteError.info, request.quotes);
|
|
40
|
+
}
|
|
41
|
+
throw quoteError;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
24
44
|
}
|
|
25
45
|
function shouldSkipValidation(quote, transaction) {
|
|
26
46
|
const { request } = quote;
|
|
@@ -66,6 +86,16 @@ async function buildValidationSimulation(request, quote) {
|
|
|
66
86
|
: undefined;
|
|
67
87
|
return buildRelayValidationSimulation(request.messenger, quote, calls, executeRequest);
|
|
68
88
|
}
|
|
89
|
+
function toQuoteError(error) {
|
|
90
|
+
if (isQuoteError(error)) {
|
|
91
|
+
return error;
|
|
92
|
+
}
|
|
93
|
+
return new QuoteError({
|
|
94
|
+
message: 'Quote simulation failed',
|
|
95
|
+
reason: 'simulation-failed',
|
|
96
|
+
detail: [error.message],
|
|
97
|
+
});
|
|
98
|
+
}
|
|
69
99
|
function buildRelayValidationSimulation(messenger, quote, calls, executeRequest) {
|
|
70
100
|
const { from, sourceChainId, targetChainId } = quote.request;
|
|
71
101
|
const context = { from, sourceChainId, targetChainId };
|
|
@@ -78,34 +108,71 @@ function buildRelayValidationSimulation(messenger, quote, calls, executeRequest)
|
|
|
78
108
|
return buildRelay7702BatchSimulation(messenger, quote, calls);
|
|
79
109
|
}
|
|
80
110
|
log('Building normal simulation', context);
|
|
81
|
-
return
|
|
111
|
+
return buildRelayNormalSimulation(calls);
|
|
82
112
|
}
|
|
83
113
|
function buildRelayExecuteSimulation(quote, executeRequest) {
|
|
84
|
-
const {
|
|
114
|
+
const { value } = executeRequest.data;
|
|
85
115
|
const valueHex = new BigNumber(value).toString(16).replace(/^/u, '0x');
|
|
86
|
-
return
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
116
|
+
return {
|
|
117
|
+
transactions: [
|
|
118
|
+
{
|
|
119
|
+
...(executeRequest.data.authorizationList?.length
|
|
120
|
+
? {
|
|
121
|
+
authorizationList: executeRequest.data.authorizationList.map((auth) => ({ address: auth.address, from: quote.request.from })),
|
|
122
|
+
}
|
|
123
|
+
: {}),
|
|
124
|
+
data: executeRequest.data.data,
|
|
125
|
+
from: quote.request.from,
|
|
126
|
+
to: executeRequest.data.to,
|
|
127
|
+
value: valueHex,
|
|
128
|
+
},
|
|
129
|
+
],
|
|
130
|
+
};
|
|
93
131
|
}
|
|
94
132
|
function buildRelay7702BatchSimulation(messenger, quote, calls) {
|
|
95
133
|
const { from, sourceChainId } = quote.request;
|
|
134
|
+
const gas = quote.original.metamask.gasLimits[0];
|
|
135
|
+
const batchTx = generateEIP7702BatchTransaction(from, calls.map((params) => ({
|
|
136
|
+
to: params.to,
|
|
137
|
+
data: params.data,
|
|
138
|
+
value: params.value,
|
|
139
|
+
})));
|
|
96
140
|
// The batch call is an ERC-7821 `execute` on the sender's own account, so the
|
|
97
141
|
// account must appear upgraded for the simulation to succeed. The quote does
|
|
98
142
|
// not always carry an authorization, and there is no fast way to check the
|
|
99
143
|
// live upgrade state, so an authorization is always included: the delegator
|
|
100
144
|
// address comes from the quote when present, otherwise from the configured
|
|
101
145
|
// EIP-7702 upgrade contract for the chain.
|
|
102
|
-
const
|
|
146
|
+
const address = quote.original.request.authorizationList?.[0]?.address ??
|
|
103
147
|
getEIP7702UpgradeContractAddress(messenger, sourceChainId);
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
148
|
+
const authorizationList = address ? [{ address, from }] : undefined;
|
|
149
|
+
return {
|
|
150
|
+
transactions: [
|
|
151
|
+
{
|
|
152
|
+
...(authorizationList ? { authorizationList } : {}),
|
|
153
|
+
data: batchTx.data,
|
|
154
|
+
from,
|
|
155
|
+
...(gas === undefined || gas === 0 ? {} : { gas: toHex(gas) }),
|
|
156
|
+
to: batchTx.to,
|
|
157
|
+
value: '0x0',
|
|
158
|
+
},
|
|
159
|
+
],
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
function buildRelayNormalSimulation(calls) {
|
|
163
|
+
return {
|
|
164
|
+
transactions: calls.map((params) => {
|
|
165
|
+
const gas = params.gas;
|
|
166
|
+
return {
|
|
167
|
+
data: params.data,
|
|
168
|
+
from: params.from,
|
|
169
|
+
...(gas === undefined || new BigNumber(gas).isZero() ? {} : { gas }),
|
|
170
|
+
maxFeePerGas: params.maxFeePerGas,
|
|
171
|
+
maxPriorityFeePerGas: params.maxPriorityFeePerGas,
|
|
172
|
+
to: params.to,
|
|
173
|
+
value: params.value,
|
|
174
|
+
};
|
|
175
|
+
}),
|
|
176
|
+
};
|
|
110
177
|
}
|
|
111
178
|
//# sourceMappingURL=relay-validation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relay-validation.js","sourceRoot":"","sources":["../../../src/strategy/relay/relay-validation.ts"],"names":[],"mappings":"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","sourcesContent":["import 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 buildPolymarketDepositWalletSimulation,\n isPredictWithdraw,\n} from '../../utils/polymarket/withdraw.js';\nimport {\n build7702BatchSimulation,\n buildCallsSimulation,\n buildDelegationSimulation,\n} from '../../utils/simulation.js';\nimport type { QuoteSimulation } from '../../utils/simulation.js';\nimport { validateQuotes } from '../../utils/validation.js';\nimport { getRelayDepositData } from './deposit-step.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, request.transaction)) {\n return;\n }\n\n await validateQuotes({\n buildSimulation: async (quote) =>\n shouldSkipValidation(quote, request.transaction)\n ? undefined\n : await buildValidationSimulation(request, quote),\n messenger: request.messenger,\n quotes: request.quotes,\n signal: request.signal,\n });\n}\n\nfunction shouldSkipValidation(\n quote: TransactionPayQuote<RelayQuote>,\n transaction: TransactionMeta,\n): boolean {\n const { request } = quote;\n\n if (request.isHyperliquidSource) {\n log('Skipping quote validation: Hyperliquid source', {\n from: request.from,\n });\n return true;\n }\n\n // Legacy Safe Predict withdraws convert USDC.e to pUSD outside the calls the\n // controller can see, so they cannot be faithfully simulated and are skipped.\n if (\n isPredictWithdraw(request, transaction) &&\n !request.isPolymarketDepositWallet\n ) {\n log('Skipping quote validation: legacy Safe Predict withdraw', {\n from: request.from,\n });\n return true;\n }\n\n return false;\n}\n\nasync function buildValidationSimulation(\n request: ValidateRelayQuotesRequest,\n quote: TransactionPayQuote<RelayQuote>,\n): Promise<QuoteSimulation> {\n if (quote.request.isPolymarketDepositWallet) {\n return await buildPolymarketDepositWalletSimulation({\n depositData: getRelayDepositData(quote.original),\n from: quote.request.from,\n messenger: request.messenger,\n sourceAmountRaw: quote.sourceAmount.raw,\n });\n }\n\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 return buildRelayValidationSimulation(\n request.messenger,\n quote,\n calls,\n executeRequest,\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 buildCallsSimulation(calls);\n}\n\nfunction buildRelayExecuteSimulation(\n quote: TransactionPayQuote<RelayQuote>,\n executeRequest: Omit<RelayExecuteRequest, 'metamask'>,\n): QuoteSimulation {\n const { authorizationList, data, to, value } = executeRequest.data;\n const valueHex = new BigNumber(value).toString(16).replace(/^/u, '0x') as Hex;\n\n return buildDelegationSimulation({\n authorizationList,\n data,\n from: quote.request.from,\n to,\n value: valueHex,\n });\n}\n\nfunction buildRelay7702BatchSimulation(\n messenger: TransactionPayControllerMessenger,\n quote: TransactionPayQuote<RelayQuote>,\n calls: TransactionParams[],\n): QuoteSimulation {\n const { from, sourceChainId } = quote.request;\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 authorizationAddress =\n quote.original.request.authorizationList?.[0]?.address ??\n getEIP7702UpgradeContractAddress(messenger, sourceChainId);\n\n return build7702BatchSimulation({\n authorizationAddress,\n calls,\n from,\n gas: quote.original.metamask.gasLimits[0],\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"relay-validation.js","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 buildPolymarketDepositWalletSimulation,\n isPredictWithdraw,\n} from '../../utils/polymarket/withdraw.js';\nimport {\n validateQuoteExecution,\n QuoteError,\n isQuoteError,\n} from '../../utils/validation.js';\nimport type { QuoteSimulation } from '../../utils/validation.js';\nimport { getRelayDepositData } from './deposit-step.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, request.transaction)) {\n return;\n }\n\n for (const quote of request.quotes) {\n if (shouldSkipValidation(quote, request.transaction)) {\n continue;\n }\n\n try {\n const simulation = await buildValidationSimulation(request, quote);\n\n await validateQuoteExecution({\n messenger: request.messenger,\n quote,\n signal: request.signal,\n simulation,\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(quoteError.info, request.quotes);\n }\n throw quoteError;\n }\n }\n}\n\nfunction shouldSkipValidation(\n quote: TransactionPayQuote<RelayQuote>,\n transaction: TransactionMeta,\n): boolean {\n const { request } = quote;\n\n if (request.isHyperliquidSource) {\n log('Skipping quote validation: Hyperliquid source', {\n from: request.from,\n });\n return true;\n }\n\n // Legacy Safe Predict withdraws convert USDC.e to pUSD outside the calls the\n // controller can see, so they cannot be faithfully simulated and are skipped.\n if (\n isPredictWithdraw(request, transaction) &&\n !request.isPolymarketDepositWallet\n ) {\n log('Skipping quote validation: legacy Safe Predict withdraw', {\n from: request.from,\n });\n return true;\n }\n\n return false;\n}\n\nasync function buildValidationSimulation(\n request: ValidateRelayQuotesRequest,\n quote: TransactionPayQuote<RelayQuote>,\n): Promise<QuoteSimulation> {\n if (quote.request.isPolymarketDepositWallet) {\n return await buildPolymarketDepositWalletSimulation({\n depositData: getRelayDepositData(quote.original),\n from: quote.request.from,\n messenger: request.messenger,\n sourceAmountRaw: quote.sourceAmount.raw,\n });\n }\n\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 return buildRelayValidationSimulation(\n request.messenger,\n quote,\n calls,\n executeRequest,\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,\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":"server-quotes.d.ts","sourceRoot":"","sources":["../../../src/strategy/server/server-quotes.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACV,2BAA2B,EAI3B,mBAAmB,EACpB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"server-quotes.d.ts","sourceRoot":"","sources":["../../../src/strategy/server/server-quotes.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACV,2BAA2B,EAI3B,mBAAmB,EACpB,MAAM,gBAAgB,CAAC;AAwBxB,OAAO,KAAK,EACV,WAAW,EAKZ,MAAM,YAAY,CAAC;AA6CpB;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,mBAAmB,CAAC,WAAW,CAAC,EAAE,CAAC,CAY7C"}
|
|
@@ -18,7 +18,6 @@ import { getQuotePricing, TradeType } from '../../utils/trade-type.js';
|
|
|
18
18
|
import { hasServerDepositStep } from './deposit-step.js';
|
|
19
19
|
import { normalizeServerPerpsRequest } from './perps.js';
|
|
20
20
|
import { fetchServerQuote } from './server-api.js';
|
|
21
|
-
import { validateServerQuotes } from './server-validation.js';
|
|
22
21
|
const log = createModuleLogger(projectLogger, 'server-quotes');
|
|
23
22
|
const HYPERCORE_CHAIN_ID_NUMBER = Number(CHAIN_ID_HYPERCORE);
|
|
24
23
|
const TOKEN_TRANSFER_FOUR_BYTE = '0xa9059cbb';
|
|
@@ -39,16 +38,8 @@ function isTransactionStep(step) {
|
|
|
39
38
|
export async function getServerQuotes(request) {
|
|
40
39
|
const quoteRequests = request.requests.filter(shouldRequestQuote);
|
|
41
40
|
log('Fetching quotes', { quoteRequests });
|
|
42
|
-
const quotes =
|
|
43
|
-
|
|
44
|
-
await validateServerQuotes({
|
|
45
|
-
messenger: request.messenger,
|
|
46
|
-
quotes,
|
|
47
|
-
signal: request.signal,
|
|
48
|
-
transaction: request.transaction,
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
return quotes;
|
|
41
|
+
const quotes = await Promise.all(quoteRequests.map((quoteRequest) => getQuotesForRequest(quoteRequest, request)));
|
|
42
|
+
return quotes.flat();
|
|
52
43
|
}
|
|
53
44
|
async function getQuotesForRequest(quoteRequest, fullRequest) {
|
|
54
45
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-quotes.js","sourceRoot":"","sources":["../../../src/strategy/server/server-quotes.ts"],"names":[],"mappings":"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","sourcesContent":["import { Interface } from '@ethersproject/abi';\nimport { toHex } from '@metamask/controller-utils';\nimport type {\n AuthorizationList,\n TransactionMeta,\n} from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { CHAIN_ID_HYPERCORE, TransactionPayStrategy } from '../../constants.js';\nimport { projectLogger } from '../../logger.js';\nimport type {\n PayStrategyGetQuotesRequest,\n QuoteRequest,\n TransactionPayControllerMessenger,\n TransactionPayFees,\n TransactionPayQuote,\n} from '../../types.js';\nimport { getFiatValueFromUsd } from '../../utils/amounts.js';\nimport { getSlippage, isEIP7702Chain } from '../../utils/feature-flags.js';\nimport {\n GasPaymentMode,\n resolveGasPayment,\n resolveGasStationCost,\n} from '../../utils/gas-payment.js';\nimport { calculateGasCost, getGasFee } from '../../utils/gas.js';\nimport {\n getPolymarketDepositWalletOverrides,\n getPredictWithdrawFeeTokenAccount,\n getPredictWithdrawSafeAddress,\n} from '../../utils/polymarket/withdraw.js';\nimport { processPostQuotePaymentOverride } from '../../utils/post-quote-payment-override.js';\nimport { reservePostQuoteGas } from '../../utils/post-quote.js';\nimport { estimateSourceGas } from '../../utils/quote-gas.js';\nimport type { QuoteGasTransaction } from '../../utils/quote-gas.js';\nimport { resolveQuoteRecipient } from '../../utils/quote-recipient.js';\nimport { getTokenFiatRate } from '../../utils/token.js';\nimport { getQuotePricing, TradeType } from '../../utils/trade-type.js';\nimport { hasServerDepositStep } from './deposit-step.js';\nimport { normalizeServerPerpsRequest } from './perps.js';\nimport { fetchServerQuote } from './server-api.js';\nimport { validateServerQuotes } from './server-validation.js';\nimport type {\n ServerQuote,\n ServerQuotePayload,\n ServerQuoteRequest,\n ServerQuoteResult,\n ServerTransactionStep,\n} from './types.js';\n\nconst log = createModuleLogger(projectLogger, 'server-quotes');\nconst HYPERCORE_CHAIN_ID_NUMBER = Number(CHAIN_ID_HYPERCORE);\nconst TOKEN_TRANSFER_FOUR_BYTE = '0xa9059cbb';\nconst TRANSFER_INTERFACE = new Interface([\n 'function transfer(address to, uint256 amount)',\n]);\nconst ZERO_AMOUNT = { fiat: '0', human: '0', raw: '0', usd: '0' };\nconst ZERO_FIAT_VALUE = { fiat: '0', usd: '0' };\n\ntype FulfilledServerQuoteResult = ServerQuoteResult & {\n quote: NonNullable<ServerQuoteResult['quote']>;\n};\n\n/**\n * A quote request whose pricing is not yet decided.\n *\n * The pricing basis depends on whether calls end up bundled into the request,\n * so it is derived once the calls are known. A step that bundles calls may pin\n * `amount` itself, in which case that amount wins.\n */\ntype ServerQuoteRequestDraft = Omit<\n ServerQuoteRequest,\n 'amount' | 'tradeType'\n> &\n Partial<Pick<ServerQuoteRequest, 'amount'>>;\n\ntype SourceNetworkCost = Pick<\n TransactionPayFees['sourceNetwork'],\n 'estimate' | 'max'\n> & {\n gasLimits: number[];\n is7702: boolean;\n isSourceGasFeeToken?: boolean;\n maxFeePerGas: string | undefined;\n maxPriorityFeePerGas: string | undefined;\n};\n\nfunction isTransactionStep(\n step: ServerQuote['steps'][number],\n): step is ServerTransactionStep {\n return step.type === 'transaction';\n}\n\n/**\n * Fetch server intents-api quotes and normalize them into Transaction Pay quotes.\n *\n * @param request - Quote request context.\n * @returns Normalized server strategy quotes.\n */\nexport async function getServerQuotes(\n request: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<ServerQuote>[]> {\n const quoteRequests = request.requests.filter(shouldRequestQuote);\n\n log('Fetching quotes', { quoteRequests });\n\n const quotes = (\n await Promise.all(\n quoteRequests.map((quoteRequest) =>\n getQuotesForRequest(quoteRequest, request),\n ),\n )\n ).flat();\n\n if (quotes.length) {\n await validateServerQuotes({\n messenger: request.messenger,\n quotes,\n signal: request.signal,\n transaction: request.transaction,\n });\n }\n\n return quotes;\n}\n\nasync function getQuotesForRequest(\n quoteRequest: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<ServerQuote>[]> {\n try {\n const quotes = await fetchQuotes(quoteRequest, fullRequest);\n\n if (!quoteRequest.isPostQuote) {\n return quotes;\n }\n\n // Post-quote flows commit the whole source balance, so any gas paid in the\n // source token has to be reserved by re-quoting the same provider for less.\n return await Promise.all(\n quotes.map((quote) =>\n reservePostQuoteGas({\n quote,\n requote: (adjustedRequest) =>\n requoteProvider(adjustedRequest, fullRequest, quote.original),\n }),\n ),\n );\n } catch (error) {\n log('Error fetching quotes', { error });\n return [];\n }\n}\n\nasync function requoteProvider(\n quoteRequest: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n { provider }: ServerQuote,\n): Promise<TransactionPayQuote<ServerQuote>> {\n const [quote] = await fetchQuotes(quoteRequest, fullRequest, provider);\n\n if (!quote) {\n throw new Error(`No re-quote from provider: ${provider}`);\n }\n\n return quote;\n}\n\nasync function fetchQuotes(\n quoteRequest: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n provider?: string,\n): Promise<TransactionPayQuote<ServerQuote>[]> {\n const { accountSupports7702, messenger, signal, transaction } = fullRequest;\n\n const body = await buildServerQuoteRequest(\n quoteRequest,\n transaction,\n messenger,\n accountSupports7702,\n );\n\n if (provider) {\n body.providers = [provider];\n }\n\n log('Request body', body);\n\n const response = await fetchServerQuote(messenger, body, signal);\n\n log('Raw quote response', response);\n\n const fulfilledResults = response.results.filter(\n (result): result is FulfilledServerQuoteResult =>\n isFulfilledResult(result) &&\n (!provider || result.provider === provider) &&\n isUsableDepositAddressQuote(body, result),\n );\n\n const normalized = await Promise.all(\n fulfilledResults.map((result) =>\n normalizeQuote(\n result,\n { ...quoteRequest, recipient: body.recipient },\n messenger,\n body,\n transaction,\n accountSupports7702,\n isSecondLegRequired(body, quoteRequest, transaction, result.quote),\n ),\n ),\n );\n\n log('Normalized quotes', normalized);\n\n return normalized;\n}\n\nasync function buildServerQuoteRequest(\n quoteRequest: QuoteRequest,\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n accountSupports7702: boolean,\n): Promise<ServerQuoteRequest> {\n const normalizedRequest = normalizeServerPerpsRequest(\n quoteRequest,\n transaction,\n );\n const {\n atomic,\n from,\n isMaxAmount,\n isPolymarketDepositWallet,\n isPostQuote,\n refundTo,\n sourceChainId,\n sourceTokenAddress,\n sourceTokenAmount,\n targetAmountMinimum,\n targetChainId,\n targetTokenAddress,\n } = normalizedRequest;\n\n const singleData = getSingleTransactionData(transaction);\n const isHypercore = targetChainId === CHAIN_ID_HYPERCORE;\n const isTokenTransfer =\n !isHypercore &&\n atomic !== false &&\n !isPostQuote &&\n !isPolymarketDepositWallet &&\n !normalizedRequest.skipProcessTransactions &&\n Boolean(singleData?.startsWith(TOKEN_TRANSFER_FOUR_BYTE));\n\n // `from` is the payer, which differs from the account the transaction's calls\n // run from when an account override (e.g. Money Account) is active.\n const executionAccount = transaction.txParams.from as Hex;\n\n const tokenTransferRecipient =\n isTokenTransfer && singleData\n ? decodeTransferRecipient(singleData)\n : undefined;\n\n const override = await processPostQuotePaymentOverride({\n messenger,\n request: normalizedRequest,\n transaction,\n });\n const recipient = await resolveQuoteRecipient({\n messenger,\n request: {\n ...normalizedRequest,\n recipient: override?.recipient ?? tokenTransferRecipient,\n },\n transaction,\n });\n\n const isHypercoreSource = sourceChainId === CHAIN_ID_HYPERCORE;\n\n // Deposit wallet withdraws are broadcast by the Polymarket relayer rather\n // than as a gasless EIP-7702 batch, so the provider must not quote gasless.\n const supportsGasless =\n !isHypercoreSource &&\n !isPolymarketDepositWallet &&\n accountSupports7702 &&\n isEIP7702Chain(messenger, sourceChainId);\n\n const body: ServerQuoteRequestDraft = {\n source: { chainId: Number(sourceChainId), token: sourceTokenAddress },\n target: { chainId: Number(targetChainId), token: targetTokenAddress },\n sender: from,\n recipient,\n slippage: Math.round(\n getSlippage(messenger, sourceChainId, sourceTokenAddress) * 10000,\n ),\n supportsGasless,\n };\n\n if (isPolymarketDepositWallet) {\n await applyDepositWalletOverrides(body, from, messenger);\n }\n\n const hasNoData = singleData === undefined || singleData === '0x';\n const skipDelegation =\n hasNoData ||\n isTokenTransfer ||\n isHypercore ||\n isHypercoreSource ||\n // Explicitly non-atomic requests want the calls run after settlement, so\n // they must not be embedded in the quote.\n atomic === false ||\n (isPostQuote ?? false) ||\n (isMaxAmount ?? false) ||\n // The deposit wallet funds the quote with a plain token transfer, so there\n // are no calls to embed.\n (isPolymarketDepositWallet ?? false);\n\n if (override) {\n body.amount = override.amount;\n body.calls = override.calls;\n\n if (override.authorizationList?.length) {\n body.authorizationList = normalizeAuthorizationList(\n override.authorizationList,\n );\n }\n } else if (!skipDelegation) {\n const delegation = await messenger.call(\n 'TransactionPayController:getDelegationTransaction',\n { transaction },\n );\n\n body.calls = [\n {\n data: buildTransferData(executionAccount, targetAmountMinimum),\n to: targetTokenAddress,\n value: '0x0',\n },\n {\n data: delegation.data,\n to: delegation.to,\n value: delegation.value,\n },\n ];\n\n // Prefer atomic execution, but let providers that cannot run the calls\n // still quote for the funds. The response determines whether execution is\n // deferred. Post-quote flows submit their own calls and must not opt in.\n if (\n canDeferCalls({\n accountSupports7702,\n messenger,\n targetChainId,\n transaction,\n })\n ) {\n body.supportsDeferredCalls = true;\n }\n\n if (delegation.authorizationList?.length) {\n body.authorizationList = normalizeAuthorizationList(\n delegation.authorizationList,\n );\n }\n } else if (isPostQuote || atomic === false) {\n // Honour the caller's refund address so a failed quote refunds the account\n // the funds came from, such as the Predict Safe, rather than the payer. A\n // deposit wallet refund address is kept, as the sweep reads refunds there.\n body.refundTo ??= refundTo;\n }\n\n const pricing = getQuotePricing({\n hasCalls: Boolean(body.calls?.length),\n sourceTokenAmount,\n targetAmountMinimum,\n transaction,\n });\n\n return {\n ...body,\n // A step that bundled its own calls has already pinned the amount those\n // calls consume, so it wins over the derived amount.\n amount: body.amount ?? pricing.amount,\n tradeType: pricing.tradeType,\n };\n}\n\n/**\n * Whether we can run the calls ourselves after the quote settles without\n * involving the user, so a funds-only quote is acceptable.\n *\n * The second leg is an internal, sponsored EIP-7702 batch on the target chain,\n * so the account must be able to sign EIP-7702 authorizations, the target chain\n * must support EIP-7702, and MetaMask must sponsor gas for the transaction on\n * that chain. Otherwise the user would need native gas on the target chain.\n *\n * Temporarily, only nested transactions are supported as second-leg calls, as\n * they are what the second leg re-encodes for the settled amount. Calls that\n * exist only on the top-level transaction are not deferred, so a provider that\n * cannot execute them declines rather than returning a funds-only quote.\n *\n * @param options - Check options.\n * @param options.accountSupports7702 - Whether the account can sign EIP-7702\n * authorizations.\n * @param options.messenger - Controller messenger.\n * @param options.targetChainId - Chain the second leg would run on.\n * @param options.transaction - Transaction being paid for.\n * @returns Whether the calls can be deferred to a second leg.\n */\nfunction canDeferCalls({\n accountSupports7702,\n messenger,\n targetChainId,\n transaction,\n}: {\n accountSupports7702: boolean;\n messenger: TransactionPayControllerMessenger;\n targetChainId: Hex;\n transaction: TransactionMeta;\n}): boolean {\n return (\n Boolean(transaction.nestedTransactions?.length) &&\n accountSupports7702 &&\n transaction.isGasFeeSponsored === true &&\n transaction.chainId === targetChainId &&\n isEIP7702Chain(messenger, targetChainId)\n );\n}\n\n/**\n * Quote a deposit wallet Predict withdraw from the deposit wallet itself.\n *\n * The deposit wallet funds the provider's deposit address with the USDC.e\n * unwrapped from its pUSD, and is also the refund address so the sweep can wrap\n * any refund back into pUSD.\n *\n * @param body - Quote request body to update.\n * @param from - The user EOA that owns the deposit wallet.\n * @param messenger - Controller messenger.\n */\nasync function applyDepositWalletOverrides(\n body: ServerQuoteRequestDraft,\n from: Hex,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n const { depositWallet, sourceTokenAddress } =\n await getPolymarketDepositWalletOverrides(from, messenger);\n\n body.source = { ...body.source, token: sourceTokenAddress };\n body.sender = depositWallet;\n body.refundTo = depositWallet;\n body.useDepositAddress = true;\n}\n\nfunction normalizeAuthorizationList(\n authorizationList: AuthorizationList,\n): NonNullable<ServerQuoteRequest['authorizationList']> {\n return authorizationList.map((entry) => ({\n address: entry.address,\n chainId: Number(entry.chainId),\n nonce: Number(entry.nonce),\n r: entry.r as Hex,\n s: entry.s as Hex,\n yParity: Number(entry.yParity),\n }));\n}\n\nfunction shouldRequestQuote(quoteRequest: QuoteRequest): boolean {\n return (\n quoteRequest.targetAmountMinimum !== '0' ||\n Boolean(quoteRequest.isPostQuote) ||\n Boolean(quoteRequest.isMaxAmount) ||\n Boolean(quoteRequest.isHyperliquidSource)\n );\n}\n\n/**\n * Determines whether the transaction's calls must be submitted as a separate\n * second leg on the target chain after the quote settles.\n *\n * `atomic` is only a hint: whether the calls can be executed by the provider\n * depends on the flow, so this checks what the built request actually carries\n * rather than what the caller asked for. Flows with nothing to run, or that\n * submit their own calls, are excluded.\n *\n * A second leg is needed either because we declined to embed the calls, or\n * because the provider that won the quote told us it will not execute them.\n * Non-atomic post-quote flows always need one: their calls come from the\n * payment override rather than the transaction, and run once funds settle.\n *\n * @param body - The built server quote request.\n * @param quoteRequest - The originating quote request.\n * @param transaction - Original transaction meta.\n * @param quote - The provider's quote payload.\n * @returns `true` when a second leg is required.\n */\nfunction isSecondLegRequired(\n body: ServerQuoteRequest,\n quoteRequest: QuoteRequest,\n transaction: TransactionMeta,\n quote: ServerQuotePayload,\n): boolean {\n // Embedded calls are executed by the provider as part of the quote, unless\n // it quoted for the funds alone and told us to run the calls ourselves.\n if (body.calls?.length && !quote.callsDeferred) {\n return false;\n }\n\n // HyperCore settles off-chain, so there is no target-chain transfer to read\n // a settled amount from. Checks the built body rather than the original\n // request, since perps deposits are only rewritten to HyperCore there.\n if (body.target.chainId === HYPERCORE_CHAIN_ID_NUMBER) {\n return false;\n }\n\n // Post-quote flows submit the original transaction alongside the quote, so\n // the second leg never re-runs it. Only non-atomic flows have override calls\n // left to run once the funds settle.\n if (quoteRequest.isPostQuote) {\n return quoteRequest.atomic === false;\n }\n\n if (body.source.chainId === HYPERCORE_CHAIN_ID_NUMBER) {\n return false;\n }\n\n // No calls to run. Plain funding transfers and empty calldata are already\n // satisfied by the quote delivering the target token to the recipient.\n if (!transaction.nestedTransactions?.length) {\n return false;\n }\n\n const singleData = getSingleTransactionData(transaction);\n\n if (singleData === undefined || singleData === '0x') {\n return false;\n }\n\n if (singleData.startsWith(TOKEN_TRANSFER_FOUR_BYTE)) {\n return false;\n }\n\n return true;\n}\n\nasync function normalizeQuote(\n result: FulfilledServerQuoteResult,\n quoteRequest: QuoteRequest,\n messenger: TransactionPayControllerMessenger,\n body: ServerQuoteRequest,\n transaction: TransactionMeta,\n accountSupports7702: boolean,\n requiresSecondLeg: boolean,\n): Promise<TransactionPayQuote<ServerQuote>> {\n const { quote } = result;\n const { gasless } = quote;\n const isInputBased = body.tradeType === TradeType.ExactInput;\n const transactionSteps = quote.steps.filter(isTransactionStep);\n const isSignatureOnly = transactionSteps.length === 0;\n const sourceNetwork = await calculateSourceNetworkCost({\n accountSupports7702,\n gasless: gasless || isSignatureOnly,\n messenger,\n quoteRequest,\n sender: body.sender,\n steps: transactionSteps,\n transaction,\n });\n\n const sourceFiatRate = getTokenFiatRate(\n messenger,\n quoteRequest.sourceTokenAddress,\n quoteRequest.sourceChainId,\n );\n\n const usdToFiatRate = sourceFiatRate\n ? new BigNumber(sourceFiatRate.fiatRate).dividedBy(sourceFiatRate.usdRate)\n : new BigNumber(1);\n\n const targetFiatRate = getTokenFiatRate(\n messenger,\n quoteRequest.targetTokenAddress,\n quoteRequest.targetChainId,\n );\n\n const metaMask = getFiatValueFromUsd(\n new BigNumber(quote.fees.metamask),\n usdToFiatRate,\n );\n\n const provider = getFiatValueFromUsd(\n new BigNumber(quote.fees.provider),\n usdToFiatRate,\n );\n\n return {\n dust: ZERO_FIAT_VALUE,\n estimatedDuration: quote.duration,\n fees: {\n ...(sourceNetwork.isSourceGasFeeToken\n ? { isSourceGasFeeToken: true }\n : {}),\n metaMask,\n provider,\n sourceNetwork: {\n estimate: sourceNetwork.estimate,\n max: sourceNetwork.max,\n },\n targetNetwork: ZERO_FIAT_VALUE,\n },\n isInputBased,\n original: {\n client: {\n gasLimits: sourceNetwork.gasLimits,\n is7702: sourceNetwork.is7702,\n maxFeePerGas: sourceNetwork.maxFeePerGas,\n maxPriorityFeePerGas: sourceNetwork.maxPriorityFeePerGas,\n },\n duration: quote.duration,\n fees: quote.fees,\n gasless,\n id: quote.id,\n input: quote.input,\n output: quote.output,\n provider: result.provider,\n steps: quote.steps,\n },\n request: quoteRequest,\n requiresSecondLeg,\n sourceAmount: {\n fiat: sourceFiatRate\n ? new BigNumber(quote.input.formatted)\n .multipliedBy(sourceFiatRate.fiatRate)\n .toString(10)\n : '0',\n human: quote.input.formatted,\n raw: quote.input.raw,\n usd: sourceFiatRate\n ? new BigNumber(quote.input.formatted)\n .multipliedBy(sourceFiatRate.usdRate)\n .toString(10)\n : '0',\n },\n strategy: TransactionPayStrategy.Server,\n targetAmount: {\n fiat: targetFiatRate\n ? new BigNumber(quote.output.formatted)\n .multipliedBy(targetFiatRate.fiatRate)\n .toString(10)\n : '0',\n usd: targetFiatRate\n ? new BigNumber(quote.output.formatted)\n .multipliedBy(targetFiatRate.usdRate)\n .toString(10)\n : '0',\n },\n };\n}\n\nasync function calculateSourceNetworkCost({\n accountSupports7702,\n gasless,\n messenger,\n quoteRequest,\n sender,\n steps,\n transaction,\n}: {\n accountSupports7702: boolean | undefined;\n gasless: boolean;\n messenger: TransactionPayControllerMessenger;\n quoteRequest: QuoteRequest;\n sender: Hex;\n steps: ServerTransactionStep[];\n transaction: TransactionMeta;\n}): Promise<SourceNetworkCost> {\n const noFees = {\n estimate: ZERO_AMOUNT,\n gasLimits: [],\n is7702: false,\n max: ZERO_AMOUNT,\n maxFeePerGas: undefined,\n maxPriorityFeePerGas: undefined,\n };\n\n const { from, isPolymarketDepositWallet, sourceChainId, sourceTokenAddress } =\n quoteRequest;\n\n // A deposit wallet withdraw is broadcast by the Polymarket relayer, which\n // pays the gas, so the user only signs.\n const gasPayment = resolveGasPayment({\n isDelegated: gasless || Boolean(isPolymarketDepositWallet),\n sourceTokenAddress,\n sponsorship: {\n accountSupports7702,\n request: quoteRequest,\n transaction,\n },\n });\n\n if (gasPayment.mode === GasPaymentMode.Delegation) {\n log('Zeroing source network fees as the user does not pay origin gas', {\n gasless,\n isPolymarketDepositWallet,\n });\n return noFees;\n }\n\n if (gasPayment.mode === GasPaymentMode.Sponsored) {\n log('Zeroing source network fees for sponsored same-chain server route');\n\n // Gas limit is zero as sponsored transactions go through the EIP-7702\n // gas station hook and do not require user-paid gas.\n return { ...noFees, gasLimits: [0], is7702: true };\n }\n\n const firstStep = steps[0];\n const chainIdHex = toHex(firstStep.chainId);\n\n const needsGasFeeEstimate =\n !firstStep.maxFeePerGas && !firstStep.maxPriorityFeePerGas;\n\n const gasFeeEstimate = needsGasFeeEstimate\n ? getGasFee(chainIdHex, messenger)\n : { maxFeePerGas: undefined, maxPriorityFeePerGas: undefined };\n\n const maxFeePerGas = firstStep.maxFeePerGas ?? gasFeeEstimate.maxFeePerGas;\n const maxPriorityFeePerGas =\n firstStep.maxPriorityFeePerGas ?? gasFeeEstimate.maxPriorityFeePerGas;\n\n // Legacy Safe Predict withdraws hold the source token in the Safe, so deposit\n // routes are estimated from the Safe. Swap routes keep the sender, as DEX\n // aggregators reject contract callers.\n const fromOverride = getPredictWithdrawSafeAddress(\n quoteRequest,\n transaction,\n hasServerDepositStep(steps),\n );\n\n const { gasLimits, is7702, totalGasEstimate, totalGasLimit } =\n await estimateSourceGas({\n fromOverride,\n messenger,\n request: quoteRequest,\n transaction,\n transactions: steps.map((step) => stepToGasTransaction(step, sender)),\n });\n\n const estimate = calculateGasCost({\n chainId: chainIdHex,\n gas: totalGasEstimate,\n maxFeePerGas: maxFeePerGas ?? '0',\n maxPriorityFeePerGas: maxPriorityFeePerGas ?? '0',\n messenger,\n });\n\n const max = calculateGasCost({\n chainId: chainIdHex,\n gas: totalGasLimit,\n isMax: true,\n maxFeePerGas: maxFeePerGas ?? '0',\n maxPriorityFeePerGas: maxPriorityFeePerGas ?? '0',\n messenger,\n });\n\n const fees = { maxFeePerGas, maxPriorityFeePerGas };\n\n // Every Predict withdraw holds the source token in the Safe, so the fee token\n // lookup must use it even on swap routes.\n const feeTokenAccount = getPredictWithdrawFeeTokenAccount(\n quoteRequest,\n transaction,\n );\n\n const gasStationCost = await resolveGasStationCost({\n feeTokenAccount,\n firstStepData: {\n data: firstStep.data,\n to: firstStep.to,\n value: firstStep.value,\n },\n messenger,\n nativeGasCostRaw: max.raw,\n request: {\n from,\n sourceChainId,\n sourceTokenAddress,\n },\n totalGasEstimate,\n totalItemCount: feeTokenAccount\n ? steps.length + 1\n : Math.max(steps.length, gasLimits.length),\n });\n\n if (!gasStationCost.amount) {\n return { estimate, gasLimits, is7702, max, ...fees };\n }\n\n log('Using gas fee token for source network', {\n feeTokenAccount,\n gasFeeTokenCost: gasStationCost.amount,\n });\n\n return {\n estimate: gasStationCost.amount,\n gasLimits,\n is7702,\n isSourceGasFeeToken: true,\n max: gasStationCost.amount,\n ...fees,\n };\n}\n\nfunction stepToGasTransaction(\n step: ServerTransactionStep,\n from: Hex,\n): QuoteGasTransaction {\n return {\n chainId: toHex(step.chainId),\n data: step.data,\n from,\n to: step.to,\n value: step.value,\n };\n}\n\nfunction getSingleTransactionData(\n transaction: TransactionMeta,\n): Hex | undefined {\n for (const nested of transaction.nestedTransactions ?? []) {\n if (nested.data && nested.data !== '0x') {\n return nested.data;\n }\n }\n\n return transaction.txParams?.data as Hex | undefined;\n}\n\nfunction isFulfilledResult(\n result: ServerQuoteResult,\n): result is FulfilledServerQuoteResult {\n return (\n result.quote?.id !== undefined &&\n result.quote.input !== undefined &&\n result.quote.output !== undefined\n );\n}\n\n/**\n * Whether a quote can be funded as requested. A deposit-address request is only\n * usable when the quote funds the provider with a plain token transfer, since\n * that transfer is what gets replaced by an unwrap straight to the deposit\n * address.\n *\n * @param body - The built server quote request.\n * @param result - Fulfilled provider result.\n * @returns True when the quote is usable.\n */\nfunction isUsableDepositAddressQuote(\n body: ServerQuoteRequest,\n result: FulfilledServerQuoteResult,\n): boolean {\n if (!body.useDepositAddress || hasServerDepositStep(result.quote.steps)) {\n return true;\n }\n\n log('Ignoring deposit address quote without a plain token transfer', {\n provider: result.provider,\n });\n\n return false;\n}\n\nfunction decodeTransferRecipient(data: Hex): Hex {\n return TRANSFER_INTERFACE.decodeFunctionData(\n 'transfer',\n data,\n ).to.toLowerCase() as Hex;\n}\n\nfunction buildTransferData(recipient: Hex, amountRaw: string): Hex {\n return TRANSFER_INTERFACE.encodeFunctionData('transfer', [\n recipient,\n amountRaw,\n ]) as Hex;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"server-quotes.js","sourceRoot":"","sources":["../../../src/strategy/server/server-quotes.ts"],"names":[],"mappings":"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","sourcesContent":["import { Interface } from '@ethersproject/abi';\nimport { toHex } from '@metamask/controller-utils';\nimport type {\n AuthorizationList,\n TransactionMeta,\n} from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\n\nimport { CHAIN_ID_HYPERCORE, TransactionPayStrategy } from '../../constants.js';\nimport { projectLogger } from '../../logger.js';\nimport type {\n PayStrategyGetQuotesRequest,\n QuoteRequest,\n TransactionPayControllerMessenger,\n TransactionPayFees,\n TransactionPayQuote,\n} from '../../types.js';\nimport { getFiatValueFromUsd } from '../../utils/amounts.js';\nimport { getSlippage, isEIP7702Chain } from '../../utils/feature-flags.js';\nimport {\n GasPaymentMode,\n resolveGasPayment,\n resolveGasStationCost,\n} from '../../utils/gas-payment.js';\nimport { calculateGasCost, getGasFee } from '../../utils/gas.js';\nimport {\n getPolymarketDepositWalletOverrides,\n getPredictWithdrawFeeTokenAccount,\n getPredictWithdrawSafeAddress,\n} from '../../utils/polymarket/withdraw.js';\nimport { processPostQuotePaymentOverride } from '../../utils/post-quote-payment-override.js';\nimport { reservePostQuoteGas } from '../../utils/post-quote.js';\nimport { estimateSourceGas } from '../../utils/quote-gas.js';\nimport type { QuoteGasTransaction } from '../../utils/quote-gas.js';\nimport { resolveQuoteRecipient } from '../../utils/quote-recipient.js';\nimport { getTokenFiatRate } from '../../utils/token.js';\nimport { getQuotePricing, TradeType } from '../../utils/trade-type.js';\nimport { hasServerDepositStep } from './deposit-step.js';\nimport { normalizeServerPerpsRequest } from './perps.js';\nimport { fetchServerQuote } from './server-api.js';\nimport type {\n ServerQuote,\n ServerQuotePayload,\n ServerQuoteRequest,\n ServerQuoteResult,\n ServerTransactionStep,\n} from './types.js';\n\nconst log = createModuleLogger(projectLogger, 'server-quotes');\nconst HYPERCORE_CHAIN_ID_NUMBER = Number(CHAIN_ID_HYPERCORE);\nconst TOKEN_TRANSFER_FOUR_BYTE = '0xa9059cbb';\nconst TRANSFER_INTERFACE = new Interface([\n 'function transfer(address to, uint256 amount)',\n]);\nconst ZERO_AMOUNT = { fiat: '0', human: '0', raw: '0', usd: '0' };\nconst ZERO_FIAT_VALUE = { fiat: '0', usd: '0' };\n\ntype FulfilledServerQuoteResult = ServerQuoteResult & {\n quote: NonNullable<ServerQuoteResult['quote']>;\n};\n\n/**\n * A quote request whose pricing is not yet decided.\n *\n * The pricing basis depends on whether calls end up bundled into the request,\n * so it is derived once the calls are known. A step that bundles calls may pin\n * `amount` itself, in which case that amount wins.\n */\ntype ServerQuoteRequestDraft = Omit<\n ServerQuoteRequest,\n 'amount' | 'tradeType'\n> &\n Partial<Pick<ServerQuoteRequest, 'amount'>>;\n\ntype SourceNetworkCost = Pick<\n TransactionPayFees['sourceNetwork'],\n 'estimate' | 'max'\n> & {\n gasLimits: number[];\n is7702: boolean;\n isSourceGasFeeToken?: boolean;\n maxFeePerGas: string | undefined;\n maxPriorityFeePerGas: string | undefined;\n};\n\nfunction isTransactionStep(\n step: ServerQuote['steps'][number],\n): step is ServerTransactionStep {\n return step.type === 'transaction';\n}\n\n/**\n * Fetch server intents-api quotes and normalize them into Transaction Pay quotes.\n *\n * @param request - Quote request context.\n * @returns Normalized server strategy quotes.\n */\nexport async function getServerQuotes(\n request: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<ServerQuote>[]> {\n const quoteRequests = request.requests.filter(shouldRequestQuote);\n\n log('Fetching quotes', { quoteRequests });\n\n const quotes = await Promise.all(\n quoteRequests.map((quoteRequest) =>\n getQuotesForRequest(quoteRequest, request),\n ),\n );\n\n return quotes.flat();\n}\n\nasync function getQuotesForRequest(\n quoteRequest: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n): Promise<TransactionPayQuote<ServerQuote>[]> {\n try {\n const quotes = await fetchQuotes(quoteRequest, fullRequest);\n\n if (!quoteRequest.isPostQuote) {\n return quotes;\n }\n\n // Post-quote flows commit the whole source balance, so any gas paid in the\n // source token has to be reserved by re-quoting the same provider for less.\n return await Promise.all(\n quotes.map((quote) =>\n reservePostQuoteGas({\n quote,\n requote: (adjustedRequest) =>\n requoteProvider(adjustedRequest, fullRequest, quote.original),\n }),\n ),\n );\n } catch (error) {\n log('Error fetching quotes', { error });\n return [];\n }\n}\n\nasync function requoteProvider(\n quoteRequest: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n { provider }: ServerQuote,\n): Promise<TransactionPayQuote<ServerQuote>> {\n const [quote] = await fetchQuotes(quoteRequest, fullRequest, provider);\n\n if (!quote) {\n throw new Error(`No re-quote from provider: ${provider}`);\n }\n\n return quote;\n}\n\nasync function fetchQuotes(\n quoteRequest: QuoteRequest,\n fullRequest: PayStrategyGetQuotesRequest,\n provider?: string,\n): Promise<TransactionPayQuote<ServerQuote>[]> {\n const { accountSupports7702, messenger, signal, transaction } = fullRequest;\n\n const body = await buildServerQuoteRequest(\n quoteRequest,\n transaction,\n messenger,\n accountSupports7702,\n );\n\n if (provider) {\n body.providers = [provider];\n }\n\n log('Request body', body);\n\n const response = await fetchServerQuote(messenger, body, signal);\n\n log('Raw quote response', response);\n\n const fulfilledResults = response.results.filter(\n (result): result is FulfilledServerQuoteResult =>\n isFulfilledResult(result) &&\n (!provider || result.provider === provider) &&\n isUsableDepositAddressQuote(body, result),\n );\n\n const normalized = await Promise.all(\n fulfilledResults.map((result) =>\n normalizeQuote(\n result,\n { ...quoteRequest, recipient: body.recipient },\n messenger,\n body,\n transaction,\n accountSupports7702,\n isSecondLegRequired(body, quoteRequest, transaction, result.quote),\n ),\n ),\n );\n\n log('Normalized quotes', normalized);\n\n return normalized;\n}\n\nasync function buildServerQuoteRequest(\n quoteRequest: QuoteRequest,\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n accountSupports7702: boolean,\n): Promise<ServerQuoteRequest> {\n const normalizedRequest = normalizeServerPerpsRequest(\n quoteRequest,\n transaction,\n );\n const {\n atomic,\n from,\n isMaxAmount,\n isPolymarketDepositWallet,\n isPostQuote,\n refundTo,\n sourceChainId,\n sourceTokenAddress,\n sourceTokenAmount,\n targetAmountMinimum,\n targetChainId,\n targetTokenAddress,\n } = normalizedRequest;\n\n const singleData = getSingleTransactionData(transaction);\n const isHypercore = targetChainId === CHAIN_ID_HYPERCORE;\n const isTokenTransfer =\n !isHypercore &&\n atomic !== false &&\n !isPostQuote &&\n !isPolymarketDepositWallet &&\n !normalizedRequest.skipProcessTransactions &&\n Boolean(singleData?.startsWith(TOKEN_TRANSFER_FOUR_BYTE));\n\n // `from` is the payer, which differs from the account the transaction's calls\n // run from when an account override (e.g. Money Account) is active.\n const executionAccount = transaction.txParams.from as Hex;\n\n const tokenTransferRecipient =\n isTokenTransfer && singleData\n ? decodeTransferRecipient(singleData)\n : undefined;\n\n const override = await processPostQuotePaymentOverride({\n messenger,\n request: normalizedRequest,\n transaction,\n });\n const recipient = await resolveQuoteRecipient({\n messenger,\n request: {\n ...normalizedRequest,\n recipient: override?.recipient ?? tokenTransferRecipient,\n },\n transaction,\n });\n\n const isHypercoreSource = sourceChainId === CHAIN_ID_HYPERCORE;\n\n // Deposit wallet withdraws are broadcast by the Polymarket relayer rather\n // than as a gasless EIP-7702 batch, so the provider must not quote gasless.\n const supportsGasless =\n !isHypercoreSource &&\n !isPolymarketDepositWallet &&\n accountSupports7702 &&\n isEIP7702Chain(messenger, sourceChainId);\n\n const body: ServerQuoteRequestDraft = {\n source: { chainId: Number(sourceChainId), token: sourceTokenAddress },\n target: { chainId: Number(targetChainId), token: targetTokenAddress },\n sender: from,\n recipient,\n slippage: Math.round(\n getSlippage(messenger, sourceChainId, sourceTokenAddress) * 10000,\n ),\n supportsGasless,\n };\n\n if (isPolymarketDepositWallet) {\n await applyDepositWalletOverrides(body, from, messenger);\n }\n\n const hasNoData = singleData === undefined || singleData === '0x';\n const skipDelegation =\n hasNoData ||\n isTokenTransfer ||\n isHypercore ||\n isHypercoreSource ||\n // Explicitly non-atomic requests want the calls run after settlement, so\n // they must not be embedded in the quote.\n atomic === false ||\n (isPostQuote ?? false) ||\n (isMaxAmount ?? false) ||\n // The deposit wallet funds the quote with a plain token transfer, so there\n // are no calls to embed.\n (isPolymarketDepositWallet ?? false);\n\n if (override) {\n body.amount = override.amount;\n body.calls = override.calls;\n\n if (override.authorizationList?.length) {\n body.authorizationList = normalizeAuthorizationList(\n override.authorizationList,\n );\n }\n } else if (!skipDelegation) {\n const delegation = await messenger.call(\n 'TransactionPayController:getDelegationTransaction',\n { transaction },\n );\n\n body.calls = [\n {\n data: buildTransferData(executionAccount, targetAmountMinimum),\n to: targetTokenAddress,\n value: '0x0',\n },\n {\n data: delegation.data,\n to: delegation.to,\n value: delegation.value,\n },\n ];\n\n // Prefer atomic execution, but let providers that cannot run the calls\n // still quote for the funds. The response determines whether execution is\n // deferred. Post-quote flows submit their own calls and must not opt in.\n if (\n canDeferCalls({\n accountSupports7702,\n messenger,\n targetChainId,\n transaction,\n })\n ) {\n body.supportsDeferredCalls = true;\n }\n\n if (delegation.authorizationList?.length) {\n body.authorizationList = normalizeAuthorizationList(\n delegation.authorizationList,\n );\n }\n } else if (isPostQuote || atomic === false) {\n // Honour the caller's refund address so a failed quote refunds the account\n // the funds came from, such as the Predict Safe, rather than the payer. A\n // deposit wallet refund address is kept, as the sweep reads refunds there.\n body.refundTo ??= refundTo;\n }\n\n const pricing = getQuotePricing({\n hasCalls: Boolean(body.calls?.length),\n sourceTokenAmount,\n targetAmountMinimum,\n transaction,\n });\n\n return {\n ...body,\n // A step that bundled its own calls has already pinned the amount those\n // calls consume, so it wins over the derived amount.\n amount: body.amount ?? pricing.amount,\n tradeType: pricing.tradeType,\n };\n}\n\n/**\n * Whether we can run the calls ourselves after the quote settles without\n * involving the user, so a funds-only quote is acceptable.\n *\n * The second leg is an internal, sponsored EIP-7702 batch on the target chain,\n * so the account must be able to sign EIP-7702 authorizations, the target chain\n * must support EIP-7702, and MetaMask must sponsor gas for the transaction on\n * that chain. Otherwise the user would need native gas on the target chain.\n *\n * Temporarily, only nested transactions are supported as second-leg calls, as\n * they are what the second leg re-encodes for the settled amount. Calls that\n * exist only on the top-level transaction are not deferred, so a provider that\n * cannot execute them declines rather than returning a funds-only quote.\n *\n * @param options - Check options.\n * @param options.accountSupports7702 - Whether the account can sign EIP-7702\n * authorizations.\n * @param options.messenger - Controller messenger.\n * @param options.targetChainId - Chain the second leg would run on.\n * @param options.transaction - Transaction being paid for.\n * @returns Whether the calls can be deferred to a second leg.\n */\nfunction canDeferCalls({\n accountSupports7702,\n messenger,\n targetChainId,\n transaction,\n}: {\n accountSupports7702: boolean;\n messenger: TransactionPayControllerMessenger;\n targetChainId: Hex;\n transaction: TransactionMeta;\n}): boolean {\n return (\n Boolean(transaction.nestedTransactions?.length) &&\n accountSupports7702 &&\n transaction.isGasFeeSponsored === true &&\n transaction.chainId === targetChainId &&\n isEIP7702Chain(messenger, targetChainId)\n );\n}\n\n/**\n * Quote a deposit wallet Predict withdraw from the deposit wallet itself.\n *\n * The deposit wallet funds the provider's deposit address with the USDC.e\n * unwrapped from its pUSD, and is also the refund address so the sweep can wrap\n * any refund back into pUSD.\n *\n * @param body - Quote request body to update.\n * @param from - The user EOA that owns the deposit wallet.\n * @param messenger - Controller messenger.\n */\nasync function applyDepositWalletOverrides(\n body: ServerQuoteRequestDraft,\n from: Hex,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n const { depositWallet, sourceTokenAddress } =\n await getPolymarketDepositWalletOverrides(from, messenger);\n\n body.source = { ...body.source, token: sourceTokenAddress };\n body.sender = depositWallet;\n body.refundTo = depositWallet;\n body.useDepositAddress = true;\n}\n\nfunction normalizeAuthorizationList(\n authorizationList: AuthorizationList,\n): NonNullable<ServerQuoteRequest['authorizationList']> {\n return authorizationList.map((entry) => ({\n address: entry.address,\n chainId: Number(entry.chainId),\n nonce: Number(entry.nonce),\n r: entry.r as Hex,\n s: entry.s as Hex,\n yParity: Number(entry.yParity),\n }));\n}\n\nfunction shouldRequestQuote(quoteRequest: QuoteRequest): boolean {\n return (\n quoteRequest.targetAmountMinimum !== '0' ||\n Boolean(quoteRequest.isPostQuote) ||\n Boolean(quoteRequest.isMaxAmount) ||\n Boolean(quoteRequest.isHyperliquidSource)\n );\n}\n\n/**\n * Determines whether the transaction's calls must be submitted as a separate\n * second leg on the target chain after the quote settles.\n *\n * `atomic` is only a hint: whether the calls can be executed by the provider\n * depends on the flow, so this checks what the built request actually carries\n * rather than what the caller asked for. Flows with nothing to run, or that\n * submit their own calls, are excluded.\n *\n * A second leg is needed either because we declined to embed the calls, or\n * because the provider that won the quote told us it will not execute them.\n * Non-atomic post-quote flows always need one: their calls come from the\n * payment override rather than the transaction, and run once funds settle.\n *\n * @param body - The built server quote request.\n * @param quoteRequest - The originating quote request.\n * @param transaction - Original transaction meta.\n * @param quote - The provider's quote payload.\n * @returns `true` when a second leg is required.\n */\nfunction isSecondLegRequired(\n body: ServerQuoteRequest,\n quoteRequest: QuoteRequest,\n transaction: TransactionMeta,\n quote: ServerQuotePayload,\n): boolean {\n // Embedded calls are executed by the provider as part of the quote, unless\n // it quoted for the funds alone and told us to run the calls ourselves.\n if (body.calls?.length && !quote.callsDeferred) {\n return false;\n }\n\n // HyperCore settles off-chain, so there is no target-chain transfer to read\n // a settled amount from. Checks the built body rather than the original\n // request, since perps deposits are only rewritten to HyperCore there.\n if (body.target.chainId === HYPERCORE_CHAIN_ID_NUMBER) {\n return false;\n }\n\n // Post-quote flows submit the original transaction alongside the quote, so\n // the second leg never re-runs it. Only non-atomic flows have override calls\n // left to run once the funds settle.\n if (quoteRequest.isPostQuote) {\n return quoteRequest.atomic === false;\n }\n\n if (body.source.chainId === HYPERCORE_CHAIN_ID_NUMBER) {\n return false;\n }\n\n // No calls to run. Plain funding transfers and empty calldata are already\n // satisfied by the quote delivering the target token to the recipient.\n if (!transaction.nestedTransactions?.length) {\n return false;\n }\n\n const singleData = getSingleTransactionData(transaction);\n\n if (singleData === undefined || singleData === '0x') {\n return false;\n }\n\n if (singleData.startsWith(TOKEN_TRANSFER_FOUR_BYTE)) {\n return false;\n }\n\n return true;\n}\n\nasync function normalizeQuote(\n result: FulfilledServerQuoteResult,\n quoteRequest: QuoteRequest,\n messenger: TransactionPayControllerMessenger,\n body: ServerQuoteRequest,\n transaction: TransactionMeta,\n accountSupports7702: boolean,\n requiresSecondLeg: boolean,\n): Promise<TransactionPayQuote<ServerQuote>> {\n const { quote } = result;\n const { gasless } = quote;\n const isInputBased = body.tradeType === TradeType.ExactInput;\n const transactionSteps = quote.steps.filter(isTransactionStep);\n const isSignatureOnly = transactionSteps.length === 0;\n const sourceNetwork = await calculateSourceNetworkCost({\n accountSupports7702,\n gasless: gasless || isSignatureOnly,\n messenger,\n quoteRequest,\n sender: body.sender,\n steps: transactionSteps,\n transaction,\n });\n\n const sourceFiatRate = getTokenFiatRate(\n messenger,\n quoteRequest.sourceTokenAddress,\n quoteRequest.sourceChainId,\n );\n\n const usdToFiatRate = sourceFiatRate\n ? new BigNumber(sourceFiatRate.fiatRate).dividedBy(sourceFiatRate.usdRate)\n : new BigNumber(1);\n\n const targetFiatRate = getTokenFiatRate(\n messenger,\n quoteRequest.targetTokenAddress,\n quoteRequest.targetChainId,\n );\n\n const metaMask = getFiatValueFromUsd(\n new BigNumber(quote.fees.metamask),\n usdToFiatRate,\n );\n\n const provider = getFiatValueFromUsd(\n new BigNumber(quote.fees.provider),\n usdToFiatRate,\n );\n\n return {\n dust: ZERO_FIAT_VALUE,\n estimatedDuration: quote.duration,\n fees: {\n ...(sourceNetwork.isSourceGasFeeToken\n ? { isSourceGasFeeToken: true }\n : {}),\n metaMask,\n provider,\n sourceNetwork: {\n estimate: sourceNetwork.estimate,\n max: sourceNetwork.max,\n },\n targetNetwork: ZERO_FIAT_VALUE,\n },\n isInputBased,\n original: {\n client: {\n gasLimits: sourceNetwork.gasLimits,\n is7702: sourceNetwork.is7702,\n maxFeePerGas: sourceNetwork.maxFeePerGas,\n maxPriorityFeePerGas: sourceNetwork.maxPriorityFeePerGas,\n },\n duration: quote.duration,\n fees: quote.fees,\n gasless,\n id: quote.id,\n input: quote.input,\n output: quote.output,\n provider: result.provider,\n steps: quote.steps,\n },\n request: quoteRequest,\n requiresSecondLeg,\n sourceAmount: {\n fiat: sourceFiatRate\n ? new BigNumber(quote.input.formatted)\n .multipliedBy(sourceFiatRate.fiatRate)\n .toString(10)\n : '0',\n human: quote.input.formatted,\n raw: quote.input.raw,\n usd: sourceFiatRate\n ? new BigNumber(quote.input.formatted)\n .multipliedBy(sourceFiatRate.usdRate)\n .toString(10)\n : '0',\n },\n strategy: TransactionPayStrategy.Server,\n targetAmount: {\n fiat: targetFiatRate\n ? new BigNumber(quote.output.formatted)\n .multipliedBy(targetFiatRate.fiatRate)\n .toString(10)\n : '0',\n usd: targetFiatRate\n ? new BigNumber(quote.output.formatted)\n .multipliedBy(targetFiatRate.usdRate)\n .toString(10)\n : '0',\n },\n };\n}\n\nasync function calculateSourceNetworkCost({\n accountSupports7702,\n gasless,\n messenger,\n quoteRequest,\n sender,\n steps,\n transaction,\n}: {\n accountSupports7702: boolean | undefined;\n gasless: boolean;\n messenger: TransactionPayControllerMessenger;\n quoteRequest: QuoteRequest;\n sender: Hex;\n steps: ServerTransactionStep[];\n transaction: TransactionMeta;\n}): Promise<SourceNetworkCost> {\n const noFees = {\n estimate: ZERO_AMOUNT,\n gasLimits: [],\n is7702: false,\n max: ZERO_AMOUNT,\n maxFeePerGas: undefined,\n maxPriorityFeePerGas: undefined,\n };\n\n const { from, isPolymarketDepositWallet, sourceChainId, sourceTokenAddress } =\n quoteRequest;\n\n // A deposit wallet withdraw is broadcast by the Polymarket relayer, which\n // pays the gas, so the user only signs.\n const gasPayment = resolveGasPayment({\n isDelegated: gasless || Boolean(isPolymarketDepositWallet),\n sourceTokenAddress,\n sponsorship: {\n accountSupports7702,\n request: quoteRequest,\n transaction,\n },\n });\n\n if (gasPayment.mode === GasPaymentMode.Delegation) {\n log('Zeroing source network fees as the user does not pay origin gas', {\n gasless,\n isPolymarketDepositWallet,\n });\n return noFees;\n }\n\n if (gasPayment.mode === GasPaymentMode.Sponsored) {\n log('Zeroing source network fees for sponsored same-chain server route');\n\n // Gas limit is zero as sponsored transactions go through the EIP-7702\n // gas station hook and do not require user-paid gas.\n return { ...noFees, gasLimits: [0], is7702: true };\n }\n\n const firstStep = steps[0];\n const chainIdHex = toHex(firstStep.chainId);\n\n const needsGasFeeEstimate =\n !firstStep.maxFeePerGas && !firstStep.maxPriorityFeePerGas;\n\n const gasFeeEstimate = needsGasFeeEstimate\n ? getGasFee(chainIdHex, messenger)\n : { maxFeePerGas: undefined, maxPriorityFeePerGas: undefined };\n\n const maxFeePerGas = firstStep.maxFeePerGas ?? gasFeeEstimate.maxFeePerGas;\n const maxPriorityFeePerGas =\n firstStep.maxPriorityFeePerGas ?? gasFeeEstimate.maxPriorityFeePerGas;\n\n // Legacy Safe Predict withdraws hold the source token in the Safe, so deposit\n // routes are estimated from the Safe. Swap routes keep the sender, as DEX\n // aggregators reject contract callers.\n const fromOverride = getPredictWithdrawSafeAddress(\n quoteRequest,\n transaction,\n hasServerDepositStep(steps),\n );\n\n const { gasLimits, is7702, totalGasEstimate, totalGasLimit } =\n await estimateSourceGas({\n fromOverride,\n messenger,\n request: quoteRequest,\n transaction,\n transactions: steps.map((step) => stepToGasTransaction(step, sender)),\n });\n\n const estimate = calculateGasCost({\n chainId: chainIdHex,\n gas: totalGasEstimate,\n maxFeePerGas: maxFeePerGas ?? '0',\n maxPriorityFeePerGas: maxPriorityFeePerGas ?? '0',\n messenger,\n });\n\n const max = calculateGasCost({\n chainId: chainIdHex,\n gas: totalGasLimit,\n isMax: true,\n maxFeePerGas: maxFeePerGas ?? '0',\n maxPriorityFeePerGas: maxPriorityFeePerGas ?? '0',\n messenger,\n });\n\n const fees = { maxFeePerGas, maxPriorityFeePerGas };\n\n // Every Predict withdraw holds the source token in the Safe, so the fee token\n // lookup must use it even on swap routes.\n const feeTokenAccount = getPredictWithdrawFeeTokenAccount(\n quoteRequest,\n transaction,\n );\n\n const gasStationCost = await resolveGasStationCost({\n feeTokenAccount,\n firstStepData: {\n data: firstStep.data,\n to: firstStep.to,\n value: firstStep.value,\n },\n messenger,\n nativeGasCostRaw: max.raw,\n request: {\n from,\n sourceChainId,\n sourceTokenAddress,\n },\n totalGasEstimate,\n totalItemCount: feeTokenAccount\n ? steps.length + 1\n : Math.max(steps.length, gasLimits.length),\n });\n\n if (!gasStationCost.amount) {\n return { estimate, gasLimits, is7702, max, ...fees };\n }\n\n log('Using gas fee token for source network', {\n feeTokenAccount,\n gasFeeTokenCost: gasStationCost.amount,\n });\n\n return {\n estimate: gasStationCost.amount,\n gasLimits,\n is7702,\n isSourceGasFeeToken: true,\n max: gasStationCost.amount,\n ...fees,\n };\n}\n\nfunction stepToGasTransaction(\n step: ServerTransactionStep,\n from: Hex,\n): QuoteGasTransaction {\n return {\n chainId: toHex(step.chainId),\n data: step.data,\n from,\n to: step.to,\n value: step.value,\n };\n}\n\nfunction getSingleTransactionData(\n transaction: TransactionMeta,\n): Hex | undefined {\n for (const nested of transaction.nestedTransactions ?? []) {\n if (nested.data && nested.data !== '0x') {\n return nested.data;\n }\n }\n\n return transaction.txParams?.data as Hex | undefined;\n}\n\nfunction isFulfilledResult(\n result: ServerQuoteResult,\n): result is FulfilledServerQuoteResult {\n return (\n result.quote?.id !== undefined &&\n result.quote.input !== undefined &&\n result.quote.output !== undefined\n );\n}\n\n/**\n * Whether a quote can be funded as requested. A deposit-address request is only\n * usable when the quote funds the provider with a plain token transfer, since\n * that transfer is what gets replaced by an unwrap straight to the deposit\n * address.\n *\n * @param body - The built server quote request.\n * @param result - Fulfilled provider result.\n * @returns True when the quote is usable.\n */\nfunction isUsableDepositAddressQuote(\n body: ServerQuoteRequest,\n result: FulfilledServerQuoteResult,\n): boolean {\n if (!body.useDepositAddress || hasServerDepositStep(result.quote.steps)) {\n return true;\n }\n\n log('Ignoring deposit address quote without a plain token transfer', {\n provider: result.provider,\n });\n\n return false;\n}\n\nfunction decodeTransferRecipient(data: Hex): Hex {\n return TRANSFER_INTERFACE.decodeFunctionData(\n 'transfer',\n data,\n ).to.toLowerCase() as Hex;\n}\n\nfunction buildTransferData(recipient: Hex, amountRaw: string): Hex {\n return TRANSFER_INTERFACE.encodeFunctionData('transfer', [\n recipient,\n amountRaw,\n ]) as Hex;\n}\n"]}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import type { TransactionMeta, TransactionParams } from '@metamask/transaction-controller';
|
|
2
1
|
import type { Hex } from '@metamask/utils';
|
|
3
|
-
import type {
|
|
4
|
-
import type { GasPayment } from '../../utils/gas-payment.js';
|
|
2
|
+
import type { PayStrategyExecuteRequest } from '../../types.js';
|
|
5
3
|
import type { ServerQuote } from './types.js';
|
|
6
4
|
/**
|
|
7
5
|
* Submits server intent quotes.
|
|
@@ -12,34 +10,4 @@ import type { ServerQuote } from './types.js';
|
|
|
12
10
|
export declare function submitServerQuotes(request: PayStrategyExecuteRequest<ServerQuote>): Promise<{
|
|
13
11
|
transactionHash?: Hex;
|
|
14
12
|
}>;
|
|
15
|
-
/**
|
|
16
|
-
* Build the transactions a server quote submits on-chain, including any
|
|
17
|
-
* post-quote or payment-override prepends.
|
|
18
|
-
*
|
|
19
|
-
* @param quote - Server quote.
|
|
20
|
-
* @param messenger - Controller messenger.
|
|
21
|
-
* @param transaction - Original transaction meta.
|
|
22
|
-
* @returns Ordered transaction params for submission.
|
|
23
|
-
*/
|
|
24
|
-
export declare function getServerSubmitParams(quote: TransactionPayQuote<ServerQuote>, messenger: TransactionPayControllerMessenger, transaction: TransactionMeta): Promise<TransactionParams[]>;
|
|
25
|
-
/**
|
|
26
|
-
* Resolve how the source network gas for a server quote is paid.
|
|
27
|
-
*
|
|
28
|
-
* @param quote - Server quote.
|
|
29
|
-
* @param messenger - Controller messenger.
|
|
30
|
-
* @param transaction - Original transaction meta.
|
|
31
|
-
* @returns The gas payment.
|
|
32
|
-
*/
|
|
33
|
-
export declare function getServerGasPayment(quote: TransactionPayQuote<ServerQuote>, messenger: TransactionPayControllerMessenger, transaction: TransactionMeta): GasPayment;
|
|
34
|
-
/**
|
|
35
|
-
* Build the delegation that redeems the source calls of a gasless server
|
|
36
|
-
* quote.
|
|
37
|
-
*
|
|
38
|
-
* @param quote - Server quote.
|
|
39
|
-
* @param params - Transactions to redeem.
|
|
40
|
-
* @param messenger - Controller messenger.
|
|
41
|
-
* @param transaction - Original transaction meta.
|
|
42
|
-
* @returns The delegation transaction.
|
|
43
|
-
*/
|
|
44
|
-
export declare function getServerExecuteDelegation(quote: TransactionPayQuote<ServerQuote>, params: TransactionParams[], messenger: TransactionPayControllerMessenger, transaction: TransactionMeta): ReturnType<GetDelegationTransactionCallback>;
|
|
45
13
|
//# sourceMappingURL=server-submit.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-submit.d.ts","sourceRoot":"","sources":["../../../src/strategy/server/server-submit.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server-submit.d.ts","sourceRoot":"","sources":["../../../src/strategy/server/server-submit.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAK3C,OAAO,KAAK,EACV,yBAAyB,EAG1B,MAAM,gBAAgB,CAAC;AAgCxB,OAAO,KAAK,EACV,WAAW,EAKZ,MAAM,YAAY,CAAC;AAkDpB;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,yBAAyB,CAAC,WAAW,CAAC,GAC9C,OAAO,CAAC;IAAE,eAAe,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC,CAgBpC"}
|