@metamask-previews/transaction-pay-controller 30.1.0-preview-d687d3ab2 → 30.1.0-preview-b50d61887
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/server/server-quotes.d.ts.map +1 -1
- package/dist/strategy/server/server-quotes.js +51 -163
- package/dist/strategy/server/server-quotes.js.map +1 -1
- package/dist/strategy/server/server-submit.d.ts.map +1 -1
- package/dist/strategy/server/server-submit.js +16 -118
- package/dist/strategy/server/server-submit.js.map +1 -1
- package/dist/strategy/server/server-support.d.ts +3 -1
- package/dist/strategy/server/server-support.d.ts.map +1 -1
- package/dist/strategy/server/server-support.js +5 -0
- package/dist/strategy/server/server-support.js.map +1 -1
- package/dist/strategy/server/types.d.ts +0 -7
- package/dist/strategy/server/types.d.ts.map +1 -1
- package/dist/strategy/server/types.js.map +1 -1
- package/package.json +1 -1
- package/dist/strategy/server/deposit-step.d.ts +0 -18
- package/dist/strategy/server/deposit-step.d.ts.map +0 -1
- package/dist/strategy/server/deposit-step.js +0 -37
- package/dist/strategy/server/deposit-step.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
|
-
- Support Predict withdraw in `ServerStrategy` ([#10702](https://github.com/MetaMask/core/pull/10702))
|
|
13
|
-
- Polymarket deposit wallet withdrawals unwrap directly to a provider deposit address, then sweep any leftover or refunded USDC.e back into the deposit wallet.
|
|
14
|
-
- Polymarket deposit wallet withdrawals have no source network fee, as the Polymarket relayer pays origin gas.
|
|
15
|
-
- Non-atomic post-quote payment overrides, such as withdrawing to a Money Account, settle on the override recipient and run the override calls as a second leg.
|
|
16
|
-
- Post-quote quotes honour `refundTo`, include the original transaction in gas estimation, and reserve the gas fee token cost from the source amount.
|
|
17
|
-
|
|
18
10
|
### Changed
|
|
19
11
|
|
|
20
12
|
- Bump `@metamask/transaction-controller` from `^72.2.0` to `^72.2.1` ([#10817](https://github.com/MetaMask/core/pull/10817))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-quotes.d.ts","sourceRoot":"","sources":["../../../src/strategy/server/server-quotes.ts"],"names":[],"mappings":"AAgBA,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":"AAgBA,OAAO,KAAK,EACV,2BAA2B,EAI3B,mBAAmB,EACpB,MAAM,gBAAgB,CAAC;AAmBxB,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"}
|
|
@@ -5,16 +5,12 @@ import { BigNumber } from 'bignumber.js';
|
|
|
5
5
|
import { CHAIN_ID_HYPERCORE, PaymentOverride, TransactionPayStrategy, } from '../../constants.js';
|
|
6
6
|
import { projectLogger } from '../../logger.js';
|
|
7
7
|
import { getFiatValueFromUsd } from '../../utils/amounts.js';
|
|
8
|
-
import { getSlippage, isEIP7702Chain } from '../../utils/feature-flags.js';
|
|
8
|
+
import { getFeatureFlags, getSlippage, isEIP7702Chain, } from '../../utils/feature-flags.js';
|
|
9
9
|
import { GasPaymentMode, resolveGasPayment, resolveGasStationCost, } from '../../utils/gas-payment.js';
|
|
10
10
|
import { calculateGasCost, getGasFee } from '../../utils/gas.js';
|
|
11
|
-
import {
|
|
12
|
-
import { reservePostQuoteGas } from '../../utils/post-quote.js';
|
|
13
|
-
import { estimateSourceGas } from '../../utils/quote-gas.js';
|
|
14
|
-
import { resolveNonAtomicRecipient } from '../../utils/second-leg.js';
|
|
11
|
+
import { estimateQuoteGasLimits } from '../../utils/quote-gas.js';
|
|
15
12
|
import { getTokenFiatRate } from '../../utils/token.js';
|
|
16
13
|
import { getQuotePricing, TradeType } from '../../utils/trade-type.js';
|
|
17
|
-
import { hasServerDepositStep } from './deposit-step.js';
|
|
18
14
|
import { normalizeServerPerpsRequest } from './perps.js';
|
|
19
15
|
import { fetchServerQuote } from './server-api.js';
|
|
20
16
|
const log = createModuleLogger(projectLogger, 'server-quotes');
|
|
@@ -41,68 +37,31 @@ export async function getServerQuotes(request) {
|
|
|
41
37
|
return quotes.flat();
|
|
42
38
|
}
|
|
43
39
|
async function getQuotesForRequest(quoteRequest, fullRequest) {
|
|
40
|
+
const { accountSupports7702, messenger, signal, transaction } = fullRequest;
|
|
44
41
|
try {
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
//
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
42
|
+
const body = await buildServerQuoteRequest(quoteRequest, transaction, messenger, accountSupports7702);
|
|
43
|
+
log('Request body', body);
|
|
44
|
+
const response = await fetchServerQuote(messenger, body, signal);
|
|
45
|
+
log('Raw quote response', response);
|
|
46
|
+
const fulfilledResults = response.results.filter(isFulfilledResult);
|
|
47
|
+
// The second leg runs from `request.recipient`, so it has to match the
|
|
48
|
+
// executing account the quote settles on.
|
|
49
|
+
const settledRequest = {
|
|
50
|
+
...quoteRequest,
|
|
51
|
+
recipient: transaction.txParams.from,
|
|
52
|
+
};
|
|
53
|
+
const normalized = await Promise.all(fulfilledResults.map((result) => normalizeQuote(result, settledRequest, messenger, body.tradeType === TradeType.ExactInput, transaction, accountSupports7702, isSecondLegRequired(body, quoteRequest, transaction, result.quote))));
|
|
54
|
+
log('Normalized quotes', normalized);
|
|
55
|
+
return normalized;
|
|
55
56
|
}
|
|
56
57
|
catch (error) {
|
|
57
58
|
log('Error fetching quotes', { error });
|
|
58
59
|
return [];
|
|
59
60
|
}
|
|
60
61
|
}
|
|
61
|
-
async function requoteProvider(quoteRequest, fullRequest, { provider }) {
|
|
62
|
-
const [quote] = await fetchQuotes(quoteRequest, fullRequest, provider);
|
|
63
|
-
if (!quote) {
|
|
64
|
-
throw new Error(`No re-quote from provider: ${provider}`);
|
|
65
|
-
}
|
|
66
|
-
return quote;
|
|
67
|
-
}
|
|
68
|
-
async function fetchQuotes(quoteRequest, fullRequest, provider) {
|
|
69
|
-
const { accountSupports7702, messenger, signal, transaction } = fullRequest;
|
|
70
|
-
const settledRequest = await resolveSettledRequest(quoteRequest, transaction, messenger);
|
|
71
|
-
const body = await buildServerQuoteRequest(settledRequest, transaction, messenger, accountSupports7702);
|
|
72
|
-
if (provider) {
|
|
73
|
-
body.providers = [provider];
|
|
74
|
-
}
|
|
75
|
-
log('Request body', body);
|
|
76
|
-
const response = await fetchServerQuote(messenger, body, signal);
|
|
77
|
-
log('Raw quote response', response);
|
|
78
|
-
const fulfilledResults = response.results.filter((result) => isFulfilledResult(result) &&
|
|
79
|
-
(!provider || result.provider === provider) &&
|
|
80
|
-
isUsableDepositAddressQuote(body, result));
|
|
81
|
-
const normalized = await Promise.all(fulfilledResults.map((result) => normalizeQuote(result, settledRequest, messenger, body, transaction, accountSupports7702, isSecondLegRequired(body, settledRequest, transaction, result.quote))));
|
|
82
|
-
log('Normalized quotes', normalized);
|
|
83
|
-
return normalized;
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Carry the account the funds settle on as the request recipient.
|
|
87
|
-
*
|
|
88
|
-
* The second leg runs from `request.recipient`, which has to match where the
|
|
89
|
-
* funds actually landed. Non-atomic flows settle on the account submitting the
|
|
90
|
-
* second leg, such as the Money Account of a Predict withdraw. Otherwise the
|
|
91
|
-
* quote settles on the executing account rather than the payer.
|
|
92
|
-
*
|
|
93
|
-
* @param quoteRequest - Quote request.
|
|
94
|
-
* @param transaction - Original transaction meta.
|
|
95
|
-
* @param messenger - Controller messenger.
|
|
96
|
-
* @returns The request with the settlement recipient applied.
|
|
97
|
-
*/
|
|
98
|
-
async function resolveSettledRequest(quoteRequest, transaction, messenger) {
|
|
99
|
-
const recipient = (await resolveNonAtomicRecipient(transaction, quoteRequest, messenger)) ??
|
|
100
|
-
transaction.txParams.from;
|
|
101
|
-
return { ...quoteRequest, recipient };
|
|
102
|
-
}
|
|
103
62
|
async function buildServerQuoteRequest(quoteRequest, transaction, messenger, accountSupports7702) {
|
|
104
63
|
const normalizedRequest = normalizeServerPerpsRequest(quoteRequest, transaction);
|
|
105
|
-
const { atomic, from, isMaxAmount,
|
|
64
|
+
const { atomic, from, isMaxAmount, isPostQuote, paymentOverride, sourceChainId, sourceTokenAddress, sourceTokenAmount, targetAmountMinimum, targetChainId, targetTokenAddress, } = normalizedRequest;
|
|
106
65
|
const singleData = getSingleTransactionData(transaction);
|
|
107
66
|
const isHypercore = targetChainId === CHAIN_ID_HYPERCORE;
|
|
108
67
|
const isTokenTransfer = !isHypercore && Boolean(singleData?.startsWith(TOKEN_TRANSFER_FOUR_BYTE));
|
|
@@ -111,12 +70,9 @@ async function buildServerQuoteRequest(quoteRequest, transaction, messenger, acc
|
|
|
111
70
|
const executionAccount = transaction.txParams.from;
|
|
112
71
|
const recipient = isTokenTransfer && singleData
|
|
113
72
|
? decodeTransferRecipient(singleData)
|
|
114
|
-
:
|
|
73
|
+
: executionAccount;
|
|
115
74
|
const isHypercoreSource = sourceChainId === CHAIN_ID_HYPERCORE;
|
|
116
|
-
// Deposit wallet withdraws are broadcast by the Polymarket relayer rather
|
|
117
|
-
// than as a gasless EIP-7702 batch, so the provider must not quote gasless.
|
|
118
75
|
const supportsGasless = !isHypercoreSource &&
|
|
119
|
-
!isPolymarketDepositWallet &&
|
|
120
76
|
accountSupports7702 &&
|
|
121
77
|
isEIP7702Chain(messenger, sourceChainId);
|
|
122
78
|
const body = {
|
|
@@ -127,9 +83,6 @@ async function buildServerQuoteRequest(quoteRequest, transaction, messenger, acc
|
|
|
127
83
|
slippage: Math.round(getSlippage(messenger, sourceChainId, sourceTokenAddress) * 10000),
|
|
128
84
|
supportsGasless,
|
|
129
85
|
};
|
|
130
|
-
if (isPolymarketDepositWallet) {
|
|
131
|
-
await applyDepositWalletOverrides(body, from, messenger);
|
|
132
|
-
}
|
|
133
86
|
const hasNoData = singleData === undefined || singleData === '0x';
|
|
134
87
|
const skipDelegation = hasNoData ||
|
|
135
88
|
isTokenTransfer ||
|
|
@@ -139,13 +92,8 @@ async function buildServerQuoteRequest(quoteRequest, transaction, messenger, acc
|
|
|
139
92
|
// they must not be embedded in the quote.
|
|
140
93
|
atomic === false ||
|
|
141
94
|
(isPostQuote ?? false) ||
|
|
142
|
-
(isMaxAmount ?? false)
|
|
143
|
-
|
|
144
|
-
// are no calls to embed.
|
|
145
|
-
(isPolymarketDepositWallet ?? false);
|
|
146
|
-
if (isPostQuote &&
|
|
147
|
-
atomic !== false &&
|
|
148
|
-
paymentOverride === PaymentOverride.MoneyAccount) {
|
|
95
|
+
(isMaxAmount ?? false);
|
|
96
|
+
if (isPostQuote && paymentOverride === PaymentOverride.MoneyAccount) {
|
|
149
97
|
await processMoneyAccountPostQuote(transaction, normalizedRequest, body, messenger);
|
|
150
98
|
}
|
|
151
99
|
else if (!skipDelegation) {
|
|
@@ -179,12 +127,6 @@ async function buildServerQuoteRequest(quoteRequest, transaction, messenger, acc
|
|
|
179
127
|
body.authorizationList = normalizeAuthorizationList(delegation.authorizationList);
|
|
180
128
|
}
|
|
181
129
|
}
|
|
182
|
-
else if (isPostQuote || atomic === false) {
|
|
183
|
-
// Honour the caller's refund address so a failed quote refunds the account
|
|
184
|
-
// the funds came from, such as the Predict Safe, rather than the payer. A
|
|
185
|
-
// deposit wallet refund address is kept, as the sweep reads refunds there.
|
|
186
|
-
body.refundTo ??= refundTo;
|
|
187
|
-
}
|
|
188
130
|
const pricing = getQuotePricing({
|
|
189
131
|
hasCalls: Boolean(body.calls?.length),
|
|
190
132
|
sourceTokenAmount,
|
|
@@ -228,24 +170,6 @@ function canDeferCalls({ accountSupports7702, messenger, targetChainId, transact
|
|
|
228
170
|
transaction.chainId === targetChainId &&
|
|
229
171
|
isEIP7702Chain(messenger, targetChainId));
|
|
230
172
|
}
|
|
231
|
-
/**
|
|
232
|
-
* Quote a deposit wallet Predict withdraw from the deposit wallet itself.
|
|
233
|
-
*
|
|
234
|
-
* The deposit wallet funds the provider's deposit address with the USDC.e
|
|
235
|
-
* unwrapped from its pUSD, and is also the refund address so the sweep can wrap
|
|
236
|
-
* any refund back into pUSD.
|
|
237
|
-
*
|
|
238
|
-
* @param body - Quote request body to update.
|
|
239
|
-
* @param from - The user EOA that owns the deposit wallet.
|
|
240
|
-
* @param messenger - Controller messenger.
|
|
241
|
-
*/
|
|
242
|
-
async function applyDepositWalletOverrides(body, from, messenger) {
|
|
243
|
-
const { depositWallet, sourceTokenAddress } = await getPolymarketDepositWalletOverrides(from, messenger);
|
|
244
|
-
body.source = { ...body.source, token: sourceTokenAddress };
|
|
245
|
-
body.sender = depositWallet;
|
|
246
|
-
body.refundTo = depositWallet;
|
|
247
|
-
body.useDepositAddress = true;
|
|
248
|
-
}
|
|
249
173
|
function normalizeAuthorizationList(authorizationList) {
|
|
250
174
|
return authorizationList.map((entry) => ({
|
|
251
175
|
address: entry.address,
|
|
@@ -306,8 +230,6 @@ function shouldRequestQuote(quoteRequest) {
|
|
|
306
230
|
*
|
|
307
231
|
* A second leg is needed either because we declined to embed the calls, or
|
|
308
232
|
* because the provider that won the quote told us it will not execute them.
|
|
309
|
-
* Non-atomic post-quote flows always need one: their calls come from the
|
|
310
|
-
* payment override rather than the transaction, and run once funds settle.
|
|
311
233
|
*
|
|
312
234
|
* @param body - The built server quote request.
|
|
313
235
|
* @param quoteRequest - The originating quote request.
|
|
@@ -321,19 +243,6 @@ function isSecondLegRequired(body, quoteRequest, transaction, quote) {
|
|
|
321
243
|
if (body.calls?.length && !quote.callsDeferred) {
|
|
322
244
|
return false;
|
|
323
245
|
}
|
|
324
|
-
// HyperCore settles off-chain, so there is no target-chain transfer to read
|
|
325
|
-
// a settled amount from. Checks the built body rather than the original
|
|
326
|
-
// request, since perps deposits are only rewritten to HyperCore there.
|
|
327
|
-
if (body.target.chainId === HYPERCORE_CHAIN_ID_NUMBER ||
|
|
328
|
-
body.source.chainId === HYPERCORE_CHAIN_ID_NUMBER) {
|
|
329
|
-
return false;
|
|
330
|
-
}
|
|
331
|
-
// Post-quote flows submit the original transaction alongside the quote, so
|
|
332
|
-
// the second leg never re-runs it. Only non-atomic flows have override calls
|
|
333
|
-
// left to run once the funds settle.
|
|
334
|
-
if (quoteRequest.isPostQuote) {
|
|
335
|
-
return quoteRequest.atomic === false;
|
|
336
|
-
}
|
|
337
246
|
// No calls to run. Plain funding transfers and empty calldata are already
|
|
338
247
|
// satisfied by the quote delivering the target token to the recipient.
|
|
339
248
|
if (!transaction.nestedTransactions?.length) {
|
|
@@ -346,12 +255,23 @@ function isSecondLegRequired(body, quoteRequest, transaction, quote) {
|
|
|
346
255
|
if (singleData.startsWith(TOKEN_TRANSFER_FOUR_BYTE)) {
|
|
347
256
|
return false;
|
|
348
257
|
}
|
|
258
|
+
// HyperCore settles off-chain, so there is no target-chain transfer to read
|
|
259
|
+
// a settled amount from. Checks the built body rather than the original
|
|
260
|
+
// request, since perps deposits are only rewritten to HyperCore there.
|
|
261
|
+
if (body.target.chainId === HYPERCORE_CHAIN_ID_NUMBER ||
|
|
262
|
+
body.source.chainId === HYPERCORE_CHAIN_ID_NUMBER) {
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
// Post-quote flows submit the original transaction separately, so running it
|
|
266
|
+
// again as a second leg would double-execute it.
|
|
267
|
+
if (quoteRequest.isPostQuote) {
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
349
270
|
return true;
|
|
350
271
|
}
|
|
351
|
-
async function normalizeQuote(result, quoteRequest, messenger,
|
|
272
|
+
async function normalizeQuote(result, quoteRequest, messenger, isInputBased, transaction, accountSupports7702, requiresSecondLeg) {
|
|
352
273
|
const { quote } = result;
|
|
353
274
|
const { gasless } = quote;
|
|
354
|
-
const isInputBased = body.tradeType === TradeType.ExactInput;
|
|
355
275
|
const transactionSteps = quote.steps.filter(isTransactionStep);
|
|
356
276
|
const isSignatureOnly = transactionSteps.length === 0;
|
|
357
277
|
const sourceNetwork = await calculateSourceNetworkCost({
|
|
@@ -359,7 +279,6 @@ async function normalizeQuote(result, quoteRequest, messenger, body, transaction
|
|
|
359
279
|
gasless: gasless || isSignatureOnly,
|
|
360
280
|
messenger,
|
|
361
281
|
quoteRequest,
|
|
362
|
-
sender: body.sender,
|
|
363
282
|
steps: transactionSteps,
|
|
364
283
|
transaction,
|
|
365
284
|
});
|
|
@@ -433,7 +352,7 @@ async function normalizeQuote(result, quoteRequest, messenger, body, transaction
|
|
|
433
352
|
},
|
|
434
353
|
};
|
|
435
354
|
}
|
|
436
|
-
async function calculateSourceNetworkCost({ accountSupports7702, gasless, messenger, quoteRequest,
|
|
355
|
+
async function calculateSourceNetworkCost({ accountSupports7702, gasless, messenger, quoteRequest, steps, transaction, }) {
|
|
437
356
|
const noFees = {
|
|
438
357
|
estimate: ZERO_AMOUNT,
|
|
439
358
|
gasLimits: [],
|
|
@@ -442,11 +361,9 @@ async function calculateSourceNetworkCost({ accountSupports7702, gasless, messen
|
|
|
442
361
|
maxFeePerGas: undefined,
|
|
443
362
|
maxPriorityFeePerGas: undefined,
|
|
444
363
|
};
|
|
445
|
-
const { from,
|
|
446
|
-
// A deposit wallet withdraw is broadcast by the Polymarket relayer, which
|
|
447
|
-
// pays the gas, so the user only signs.
|
|
364
|
+
const { from, sourceChainId, sourceTokenAddress } = quoteRequest;
|
|
448
365
|
const gasPayment = resolveGasPayment({
|
|
449
|
-
isDelegated: gasless
|
|
366
|
+
isDelegated: gasless,
|
|
450
367
|
sourceTokenAddress,
|
|
451
368
|
sponsorship: {
|
|
452
369
|
accountSupports7702,
|
|
@@ -455,10 +372,7 @@ async function calculateSourceNetworkCost({ accountSupports7702, gasless, messen
|
|
|
455
372
|
},
|
|
456
373
|
});
|
|
457
374
|
if (gasPayment.mode === GasPaymentMode.Delegation) {
|
|
458
|
-
log('Zeroing source network fees
|
|
459
|
-
gasless,
|
|
460
|
-
isPolymarketDepositWallet,
|
|
461
|
-
});
|
|
375
|
+
log('Zeroing source network fees for gasless quote');
|
|
462
376
|
return noFees;
|
|
463
377
|
}
|
|
464
378
|
if (gasPayment.mode === GasPaymentMode.Sponsored) {
|
|
@@ -475,38 +389,34 @@ async function calculateSourceNetworkCost({ accountSupports7702, gasless, messen
|
|
|
475
389
|
: { maxFeePerGas: undefined, maxPriorityFeePerGas: undefined };
|
|
476
390
|
const maxFeePerGas = firstStep.maxFeePerGas ?? gasFeeEstimate.maxFeePerGas;
|
|
477
391
|
const maxPriorityFeePerGas = firstStep.maxPriorityFeePerGas ?? gasFeeEstimate.maxPriorityFeePerGas;
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
const { gasLimits, is7702, totalGasEstimate, totalGasLimit } = await estimateSourceGas({
|
|
483
|
-
fromOverride,
|
|
392
|
+
const gasTransactions = steps.map((step) => stepToGasTransaction(step, from));
|
|
393
|
+
const gasResult = await estimateQuoteGasLimits({
|
|
394
|
+
fallbackGas: getFeatureFlags(messenger).relayFallbackGas,
|
|
395
|
+
fallbackOnSimulationFailure: true,
|
|
484
396
|
messenger,
|
|
485
|
-
|
|
486
|
-
transaction,
|
|
487
|
-
transactions: steps.map((step) => stepToGasTransaction(step, sender)),
|
|
397
|
+
transactions: gasTransactions,
|
|
488
398
|
});
|
|
399
|
+
const { is7702 } = gasResult;
|
|
400
|
+
const gasLimits = is7702
|
|
401
|
+
? [gasResult.gasLimits[0].max]
|
|
402
|
+
: gasResult.gasLimits.map((gasLimit) => gasLimit.max);
|
|
489
403
|
const estimate = calculateGasCost({
|
|
490
404
|
chainId: chainIdHex,
|
|
491
|
-
gas: totalGasEstimate,
|
|
405
|
+
gas: gasResult.totalGasEstimate,
|
|
492
406
|
maxFeePerGas: maxFeePerGas ?? '0',
|
|
493
407
|
maxPriorityFeePerGas: maxPriorityFeePerGas ?? '0',
|
|
494
408
|
messenger,
|
|
495
409
|
});
|
|
496
410
|
const max = calculateGasCost({
|
|
497
411
|
chainId: chainIdHex,
|
|
498
|
-
gas: totalGasLimit,
|
|
412
|
+
gas: gasResult.totalGasLimit,
|
|
499
413
|
isMax: true,
|
|
500
414
|
maxFeePerGas: maxFeePerGas ?? '0',
|
|
501
415
|
maxPriorityFeePerGas: maxPriorityFeePerGas ?? '0',
|
|
502
416
|
messenger,
|
|
503
417
|
});
|
|
504
418
|
const fees = { maxFeePerGas, maxPriorityFeePerGas };
|
|
505
|
-
// Every Predict withdraw holds the source token in the Safe, so the fee token
|
|
506
|
-
// lookup must use it even on swap routes.
|
|
507
|
-
const feeTokenAccount = getPredictWithdrawFeeTokenAccount(quoteRequest, transaction);
|
|
508
419
|
const gasStationCost = await resolveGasStationCost({
|
|
509
|
-
feeTokenAccount,
|
|
510
420
|
firstStepData: {
|
|
511
421
|
data: firstStep.data,
|
|
512
422
|
to: firstStep.to,
|
|
@@ -519,16 +429,13 @@ async function calculateSourceNetworkCost({ accountSupports7702, gasless, messen
|
|
|
519
429
|
sourceChainId,
|
|
520
430
|
sourceTokenAddress,
|
|
521
431
|
},
|
|
522
|
-
totalGasEstimate,
|
|
523
|
-
totalItemCount:
|
|
524
|
-
? steps.length + 1
|
|
525
|
-
: Math.max(steps.length, gasLimits.length),
|
|
432
|
+
totalGasEstimate: gasResult.totalGasEstimate,
|
|
433
|
+
totalItemCount: steps.length,
|
|
526
434
|
});
|
|
527
435
|
if (!gasStationCost.amount) {
|
|
528
436
|
return { estimate, gasLimits, is7702, max, ...fees };
|
|
529
437
|
}
|
|
530
438
|
log('Using gas fee token for source network', {
|
|
531
|
-
feeTokenAccount,
|
|
532
439
|
gasFeeTokenCost: gasStationCost.amount,
|
|
533
440
|
});
|
|
534
441
|
return {
|
|
@@ -562,25 +469,6 @@ function isFulfilledResult(result) {
|
|
|
562
469
|
result.quote.input !== undefined &&
|
|
563
470
|
result.quote.output !== undefined);
|
|
564
471
|
}
|
|
565
|
-
/**
|
|
566
|
-
* Whether a quote can be funded as requested. A deposit-address request is only
|
|
567
|
-
* usable when the quote funds the provider with a plain token transfer, since
|
|
568
|
-
* that transfer is what gets replaced by an unwrap straight to the deposit
|
|
569
|
-
* address.
|
|
570
|
-
*
|
|
571
|
-
* @param body - The built server quote request.
|
|
572
|
-
* @param result - Fulfilled provider result.
|
|
573
|
-
* @returns True when the quote is usable.
|
|
574
|
-
*/
|
|
575
|
-
function isUsableDepositAddressQuote(body, result) {
|
|
576
|
-
if (!body.useDepositAddress || hasServerDepositStep(result.quote.steps)) {
|
|
577
|
-
return true;
|
|
578
|
-
}
|
|
579
|
-
log('Ignoring deposit address quote without a plain token transfer', {
|
|
580
|
-
provider: result.provider,
|
|
581
|
-
});
|
|
582
|
-
return false;
|
|
583
|
-
}
|
|
584
472
|
function decodeTransferRecipient(data) {
|
|
585
473
|
return TRANSFER_INTERFACE.decodeFunctionData('transfer', data).to.toLowerCase();
|
|
586
474
|
}
|
|
@@ -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 {\n CHAIN_ID_HYPERCORE,\n PaymentOverride,\n TransactionPayStrategy,\n} 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 { reservePostQuoteGas } from '../../utils/post-quote.js';\nimport { estimateSourceGas } from '../../utils/quote-gas.js';\nimport type { QuoteGasTransaction } from '../../utils/quote-gas.js';\nimport { resolveNonAtomicRecipient } from '../../utils/second-leg.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 settledRequest = await resolveSettledRequest(\n quoteRequest,\n transaction,\n messenger,\n );\n\n const body = await buildServerQuoteRequest(\n settledRequest,\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 settledRequest,\n messenger,\n body,\n transaction,\n accountSupports7702,\n isSecondLegRequired(body, settledRequest, transaction, result.quote),\n ),\n ),\n );\n\n log('Normalized quotes', normalized);\n\n return normalized;\n}\n\n/**\n * Carry the account the funds settle on as the request recipient.\n *\n * The second leg runs from `request.recipient`, which has to match where the\n * funds actually landed. Non-atomic flows settle on the account submitting the\n * second leg, such as the Money Account of a Predict withdraw. Otherwise the\n * quote settles on the executing account rather than the payer.\n *\n * @param quoteRequest - Quote request.\n * @param transaction - Original transaction meta.\n * @param messenger - Controller messenger.\n * @returns The request with the settlement recipient applied.\n */\nasync function resolveSettledRequest(\n quoteRequest: QuoteRequest,\n transaction: TransactionMeta,\n messenger: TransactionPayControllerMessenger,\n): Promise<QuoteRequest> {\n const recipient =\n (await resolveNonAtomicRecipient(transaction, quoteRequest, messenger)) ??\n (transaction.txParams.from as Hex);\n\n return { ...quoteRequest, recipient };\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 paymentOverride,\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 && 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 recipient =\n isTokenTransfer && singleData\n ? decodeTransferRecipient(singleData)\n : (normalizedRequest.recipient ?? executionAccount);\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 (\n isPostQuote &&\n atomic !== false &&\n paymentOverride === PaymentOverride.MoneyAccount\n ) {\n await processMoneyAccountPostQuote(\n transaction,\n normalizedRequest,\n body,\n messenger,\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. Only this path can fall back to a second leg:\n // the calls run as the execution account, which is also the recipient, so\n // we can submit them ourselves once the funds land. Post-quote flows submit\n // 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\nasync function processMoneyAccountPostQuote(\n transaction: TransactionMeta,\n request: QuoteRequest,\n body: ServerQuoteRequestDraft,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n const { transactionData: transactionDataList } = messenger.call(\n 'TransactionPayController:getState',\n );\n\n const transactionData = transactionDataList[transaction.id];\n const amountHuman = transactionData?.tokens?.[0]?.amountHuman ?? '0';\n\n const {\n calls: overrideCalls,\n recipient,\n authorizationList,\n } = await messenger.call('TransactionPayController:getPaymentOverrideData', {\n amount: amountHuman,\n transaction,\n transactionData,\n });\n\n if (!overrideCalls.length) {\n log('No payment override calls for money account post-quote');\n return;\n }\n\n const fundingRecipient = recipient ?? request.from;\n const rawAmount = transactionData?.tokens?.[0]?.amountRaw ?? '0';\n\n // The bundled calls transfer exactly this amount, so pin it rather than\n // letting the amount be derived from the request.\n body.amount = rawAmount;\n\n // Settle directly on the Money Account. The deposit calls are delegated from\n // the Money Account, so the funds have to be there before they run.\n body.recipient = fundingRecipient;\n\n body.calls = overrideCalls.map((call) => ({\n data: call.data as Hex,\n to: call.to as Hex,\n value: call.value ?? '0x0',\n }));\n\n if (authorizationList?.length) {\n body.authorizationList = normalizeAuthorizationList(authorizationList);\n }\n\n log('Added money account post-quote calls to server quote body', {\n callCount: overrideCalls.length,\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 (\n body.target.chainId === HYPERCORE_CHAIN_ID_NUMBER ||\n body.source.chainId === HYPERCORE_CHAIN_ID_NUMBER\n ) {\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 // 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 {\n CHAIN_ID_HYPERCORE,\n PaymentOverride,\n TransactionPayStrategy,\n} 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 {\n getFeatureFlags,\n getSlippage,\n isEIP7702Chain,\n} 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 { estimateQuoteGasLimits } from '../../utils/quote-gas.js';\nimport type { QuoteGasTransaction } from '../../utils/quote-gas.js';\nimport { getTokenFiatRate } from '../../utils/token.js';\nimport { getQuotePricing, TradeType } from '../../utils/trade-type.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 const { accountSupports7702, messenger, signal, transaction } = fullRequest;\n\n try {\n const body = await buildServerQuoteRequest(\n quoteRequest,\n transaction,\n messenger,\n accountSupports7702,\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(isFulfilledResult);\n\n // The second leg runs from `request.recipient`, so it has to match the\n // executing account the quote settles on.\n const settledRequest = {\n ...quoteRequest,\n recipient: transaction.txParams.from as Hex,\n };\n\n const normalized = await Promise.all(\n fulfilledResults.map((result) =>\n normalizeQuote(\n result,\n settledRequest,\n messenger,\n body.tradeType === TradeType.ExactInput,\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 } catch (error) {\n log('Error fetching quotes', { error });\n return [];\n }\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 isPostQuote,\n paymentOverride,\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 && 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 recipient =\n isTokenTransfer && singleData\n ? decodeTransferRecipient(singleData)\n : executionAccount;\n\n const isHypercoreSource = sourceChainId === CHAIN_ID_HYPERCORE;\n const supportsGasless =\n !isHypercoreSource &&\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 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\n if (isPostQuote && paymentOverride === PaymentOverride.MoneyAccount) {\n await processMoneyAccountPostQuote(\n transaction,\n normalizedRequest,\n body,\n messenger,\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. Only this path can fall back to a second leg:\n // the calls run as the execution account, which is also the recipient, so\n // we can submit them ourselves once the funds land. Post-quote flows submit\n // 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 }\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\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\nasync function processMoneyAccountPostQuote(\n transaction: TransactionMeta,\n request: QuoteRequest,\n body: ServerQuoteRequestDraft,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n const { transactionData: transactionDataList } = messenger.call(\n 'TransactionPayController:getState',\n );\n\n const transactionData = transactionDataList[transaction.id];\n const amountHuman = transactionData?.tokens?.[0]?.amountHuman ?? '0';\n\n const {\n calls: overrideCalls,\n recipient,\n authorizationList,\n } = await messenger.call('TransactionPayController:getPaymentOverrideData', {\n amount: amountHuman,\n transaction,\n transactionData,\n });\n\n if (!overrideCalls.length) {\n log('No payment override calls for money account post-quote');\n return;\n }\n\n const fundingRecipient = recipient ?? request.from;\n const rawAmount = transactionData?.tokens?.[0]?.amountRaw ?? '0';\n\n // The bundled calls transfer exactly this amount, so pin it rather than\n // letting the amount be derived from the request.\n body.amount = rawAmount;\n\n // Settle directly on the Money Account. The deposit calls are delegated from\n // the Money Account, so the funds have to be there before they run.\n body.recipient = fundingRecipient;\n\n body.calls = overrideCalls.map((call) => ({\n data: call.data as Hex,\n to: call.to as Hex,\n value: call.value ?? '0x0',\n }));\n\n if (authorizationList?.length) {\n body.authorizationList = normalizeAuthorizationList(authorizationList);\n }\n\n log('Added money account post-quote calls to server quote body', {\n callCount: overrideCalls.length,\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 *\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 // 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 // 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 (\n body.target.chainId === HYPERCORE_CHAIN_ID_NUMBER ||\n body.source.chainId === HYPERCORE_CHAIN_ID_NUMBER\n ) {\n return false;\n }\n\n // Post-quote flows submit the original transaction separately, so running it\n // again as a second leg would double-execute it.\n if (quoteRequest.isPostQuote) {\n return false;\n }\n\n return true;\n}\n\nasync function normalizeQuote(\n result: FulfilledServerQuoteResult,\n quoteRequest: QuoteRequest,\n messenger: TransactionPayControllerMessenger,\n isInputBased: boolean,\n transaction: TransactionMeta,\n accountSupports7702: boolean,\n requiresSecondLeg: boolean,\n): Promise<TransactionPayQuote<ServerQuote>> {\n const { quote } = result;\n const { gasless } = quote;\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 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 steps,\n transaction,\n}: {\n accountSupports7702: boolean | undefined;\n gasless: boolean;\n messenger: TransactionPayControllerMessenger;\n quoteRequest: QuoteRequest;\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, sourceChainId, sourceTokenAddress } = quoteRequest;\n\n const gasPayment = resolveGasPayment({\n isDelegated: gasless,\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 for gasless quote');\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 const gasTransactions = steps.map((step) => stepToGasTransaction(step, from));\n\n const gasResult = await estimateQuoteGasLimits({\n fallbackGas: getFeatureFlags(messenger).relayFallbackGas,\n fallbackOnSimulationFailure: true,\n messenger,\n transactions: gasTransactions,\n });\n\n const { is7702 } = gasResult;\n const gasLimits = is7702\n ? [gasResult.gasLimits[0].max]\n : gasResult.gasLimits.map((gasLimit) => gasLimit.max);\n\n const estimate = calculateGasCost({\n chainId: chainIdHex,\n gas: gasResult.totalGasEstimate,\n maxFeePerGas: maxFeePerGas ?? '0',\n maxPriorityFeePerGas: maxPriorityFeePerGas ?? '0',\n messenger,\n });\n\n const max = calculateGasCost({\n chainId: chainIdHex,\n gas: gasResult.totalGasLimit,\n isMax: true,\n maxFeePerGas: maxFeePerGas ?? '0',\n maxPriorityFeePerGas: maxPriorityFeePerGas ?? '0',\n messenger,\n });\n\n const fees = { maxFeePerGas, maxPriorityFeePerGas };\n\n const gasStationCost = await resolveGasStationCost({\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: gasResult.totalGasEstimate,\n totalItemCount: steps.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 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\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 +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":"AAWA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAK3C,OAAO,KAAK,EACV,yBAAyB,EAG1B,MAAM,gBAAgB,CAAC;AA2BxB,OAAO,KAAK,EACV,WAAW,EAKZ,MAAM,YAAY,CAAC;AA4CpB;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,yBAAyB,CAAC,WAAW,CAAC,GAC9C,OAAO,CAAC;IAAE,eAAe,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC,CAgBpC"}
|