@metamask-previews/transaction-pay-controller 30.1.0-preview-43fa35913 → 30.1.0-preview-4fa35a45a
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/dist/strategy/relay/polymarket/calldata.d.ts.map +1 -0
- package/dist/strategy/relay/polymarket/calldata.js.map +1 -0
- package/dist/strategy/relay/polymarket/constants.d.ts.map +1 -0
- package/dist/strategy/relay/polymarket/constants.js.map +1 -0
- package/dist/strategy/relay/polymarket/withdraw.d.ts +52 -0
- package/dist/strategy/relay/polymarket/withdraw.d.ts.map +1 -0
- package/dist/{utils → strategy/relay}/polymarket/withdraw.js +72 -88
- package/dist/strategy/relay/polymarket/withdraw.js.map +1 -0
- package/dist/strategy/relay/relay-quotes.d.ts.map +1 -1
- package/dist/strategy/relay/relay-quotes.js +7 -11
- package/dist/strategy/relay/relay-quotes.js.map +1 -1
- package/dist/strategy/relay/relay-submit.d.ts.map +1 -1
- package/dist/strategy/relay/relay-submit.js +4 -12
- package/dist/strategy/relay/relay-submit.js.map +1 -1
- package/dist/strategy/relay/relay-validation.d.ts.map +1 -1
- package/dist/strategy/relay/relay-validation.js +2 -8
- package/dist/strategy/relay/relay-validation.js.map +1 -1
- package/package.json +1 -1
- package/dist/strategy/relay/deposit-step.d.ts +0 -18
- package/dist/strategy/relay/deposit-step.d.ts.map +0 -1
- package/dist/strategy/relay/deposit-step.js +0 -21
- package/dist/strategy/relay/deposit-step.js.map +0 -1
- package/dist/utils/polymarket/calldata.d.ts.map +0 -1
- package/dist/utils/polymarket/calldata.js.map +0 -1
- package/dist/utils/polymarket/constants.d.ts.map +0 -1
- package/dist/utils/polymarket/constants.js.map +0 -1
- package/dist/utils/polymarket/withdraw.d.ts +0 -101
- package/dist/utils/polymarket/withdraw.d.ts.map +0 -1
- package/dist/utils/polymarket/withdraw.js.map +0 -1
- /package/dist/{utils → strategy/relay}/polymarket/calldata.d.ts +0 -0
- /package/dist/{utils → strategy/relay}/polymarket/calldata.js +0 -0
- /package/dist/{utils → strategy/relay}/polymarket/constants.d.ts +0 -0
- /package/dist/{utils → strategy/relay}/polymarket/constants.js +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calldata.d.ts","sourceRoot":"","sources":["../../../../src/strategy/relay/polymarket/calldata.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAS3C,wBAAgB,aAAa,CAAC,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAG,GAAG,CAE/D;AAED,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,SAAS,EACT,MAAM,GACP,EAAE;IACD,KAAK,EAAE,GAAG,CAAC;IACX,SAAS,EAAE,GAAG,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,GAAG,CAEN;AAED,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,SAAS,EACT,MAAM,GACP,EAAE;IACD,KAAK,EAAE,GAAG,CAAC;IACX,SAAS,EAAE,GAAG,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,GAAG,CAEN;AAED,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,GAAG,GAAG,GAAG,CAG5D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calldata.js","sourceRoot":"","sources":["../../../../src/strategy/relay/polymarket/calldata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAG/C,MAAM,KAAK,GAAG,IAAI,SAAS,CAAC;IAC1B,mDAAmD;IACnD,mEAAmE;IACnE,iEAAiE;IACjE,sDAAsD;CACvD,CAAC,CAAC;AAEH,MAAM,UAAU,aAAa,CAAC,OAAY,EAAE,MAAc;IACxD,OAAO,KAAK,CAAC,kBAAkB,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAQ,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,EAC3B,KAAK,EACL,SAAS,EACT,MAAM,GAKP;IACC,OAAO,KAAK,CAAC,kBAAkB,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC,CAAQ,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,EACzB,KAAK,EACL,SAAS,EACT,MAAM,GAKP;IACC,OAAO,KAAK,CAAC,kBAAkB,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC,CAAQ,CAAC;AAC7E,CAAC;AAED,MAAM,UAAU,6BAA6B,CAAC,IAAS;IACrD,MAAM,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IAC/D,OAAO,SAAgB,CAAC;AAC1B,CAAC","sourcesContent":["import { Interface } from '@ethersproject/abi';\nimport type { Hex } from '@metamask/utils';\n\nconst iface = new Interface([\n 'function approve(address spender, uint256 amount)',\n 'function unwrap(address asset, address recipient, uint256 amount)',\n 'function wrap(address asset, address recipient, uint256 amount)',\n 'function transfer(address recipient, uint256 amount)',\n]);\n\nexport function encodeApprove(spender: Hex, amount: bigint): Hex {\n return iface.encodeFunctionData('approve', [spender, amount]) as Hex;\n}\n\nexport function encodeUnwrap({\n asset,\n recipient,\n amount,\n}: {\n asset: Hex;\n recipient: Hex;\n amount: bigint;\n}): Hex {\n return iface.encodeFunctionData('unwrap', [asset, recipient, amount]) as Hex;\n}\n\nexport function encodeWrap({\n asset,\n recipient,\n amount,\n}: {\n asset: Hex;\n recipient: Hex;\n amount: bigint;\n}): Hex {\n return iface.encodeFunctionData('wrap', [asset, recipient, amount]) as Hex;\n}\n\nexport function extractErc20TransferRecipient(data: Hex): Hex {\n const [recipient] = iface.decodeFunctionData('transfer', data);\n return recipient as Hex;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/strategy/relay/polymarket/constants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAE3C,eAAO,MAAM,qCAAqC,EACA,GAAG,CAAC;AAEtD,eAAO,MAAM,oCAAoC,EACC,GAAG,CAAC;AAEtD,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAE9C,eAAO,MAAM,4BAA4B,OAAO,CAAC;AAEjD,eAAO,MAAM,6BAA6B,OAAO,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../../src/strategy/relay/polymarket/constants.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,qCAAqC,GAChD,4CAAmD,CAAC;AAEtD,MAAM,CAAC,MAAM,oCAAoC,GAC/C,4CAAmD,CAAC;AAEtD,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,CAAC;AAE9C,MAAM,CAAC,MAAM,4BAA4B,GAAG,IAAI,CAAC;AAEjD,MAAM,CAAC,MAAM,6BAA6B,GAAG,IAAI,CAAC","sourcesContent":["import type { Hex } from '@metamask/utils';\n\nexport const POLYMARKET_COLLATERAL_OFFRAMP_POLYGON =\n '0x2957922Eb93258b93368531d39fAcCA3B4dC5854' as Hex;\n\nexport const POLYMARKET_COLLATERAL_ONRAMP_POLYGON =\n '0x93070a847efEf7F70739046A929D47a521F5B8ee' as Hex;\n\nexport const SWEEP_BALANCE_RETRY_ATTEMPTS = 5;\n\nexport const SWEEP_BALANCE_RETRY_DELAY_MS = 1000;\n\nexport const SWEEP_RELAYER_SETTLE_DELAY_MS = 3000;\n"]}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { TransactionMeta } from '@metamask/transaction-controller';
|
|
2
|
+
import type { Hex } from '@metamask/utils';
|
|
3
|
+
import type { QuoteRequest, TransactionPayControllerMessenger, TransactionPayQuote } from '../../../types.js';
|
|
4
|
+
import type { QuoteSimulation } from '../../../utils/validation.js';
|
|
5
|
+
import type { RelayQuote, RelayQuoteRequest, RelayStatus } from '../types.js';
|
|
6
|
+
type RelayQuoteStep = RelayQuote['steps'][number];
|
|
7
|
+
/**
|
|
8
|
+
* Whether a quote request + transaction represent a Predict withdraw post-quote
|
|
9
|
+
* flow.
|
|
10
|
+
*
|
|
11
|
+
* @param request - Quote request.
|
|
12
|
+
* @param transaction - Original transaction metadata.
|
|
13
|
+
* @returns True when this is a Predict withdraw post-quote flow.
|
|
14
|
+
*/
|
|
15
|
+
export declare function isPredictWithdraw(request: QuoteRequest, transaction: TransactionMeta): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Resolve the Polymarket Safe proxy address that must act as `msg.sender` when
|
|
18
|
+
* estimating gas for the withdraw leg of a Safe-based Predict withdraw.
|
|
19
|
+
*
|
|
20
|
+
* Only applies to the Safe variant on deposit-style Relay routes: the source
|
|
21
|
+
* token lives in the Safe (carried as `request.refundTo`), and swap-only routes
|
|
22
|
+
* keep the EOA `from` because DEX aggregators reject contract callers.
|
|
23
|
+
*
|
|
24
|
+
* @param request - Quote request.
|
|
25
|
+
* @param steps - Relay quote steps (used to detect a deposit-style route).
|
|
26
|
+
* @param transaction - Original transaction metadata.
|
|
27
|
+
* @returns The Safe proxy address, or `undefined` when the default EOA `from`
|
|
28
|
+
* should be used.
|
|
29
|
+
*/
|
|
30
|
+
export declare function getPredictWithdrawSafeAddress(request: QuoteRequest, steps: RelayQuoteStep[], transaction: TransactionMeta): Hex | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Build the simulation for a Polymarket deposit-wallet Predict withdraw,
|
|
33
|
+
* mirroring the approve + unwrap batch broadcast by {@link submitPolymarketWithdraw}
|
|
34
|
+
* so validation checks the deposit wallet holds enough pUSD.
|
|
35
|
+
*
|
|
36
|
+
* @param quote - Relay quote (source amount + deposit step).
|
|
37
|
+
* @param from - The user EOA that owns the deposit wallet.
|
|
38
|
+
* @param messenger - Controller messenger.
|
|
39
|
+
* @returns Simulation for the approve + unwrap batch from the deposit wallet.
|
|
40
|
+
*/
|
|
41
|
+
export declare function buildPolymarketDepositWalletSimulation(quote: TransactionPayQuote<RelayQuote>, from: Hex, messenger: TransactionPayControllerMessenger): Promise<QuoteSimulation>;
|
|
42
|
+
export declare function applyPolymarketDepositWalletOverrides(body: Omit<RelayQuoteRequest, 'amount' | 'tradeType'>, request: QuoteRequest, messenger: TransactionPayControllerMessenger): Promise<void>;
|
|
43
|
+
export declare function submitPolymarketWithdraw(quote: TransactionPayQuote<RelayQuote>, from: Hex, messenger: TransactionPayControllerMessenger): Promise<{
|
|
44
|
+
sourceHash: Hex;
|
|
45
|
+
preSubmitUsdceBalance: bigint;
|
|
46
|
+
}>;
|
|
47
|
+
export declare function sweepPolymarketDepositWallet(from: Hex, messenger: TransactionPayControllerMessenger, options: {
|
|
48
|
+
relayStatus: RelayStatus | 'timeout';
|
|
49
|
+
preSubmitUsdceBalance: bigint;
|
|
50
|
+
}): Promise<void>;
|
|
51
|
+
export {};
|
|
52
|
+
//# sourceMappingURL=withdraw.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"withdraw.d.ts","sourceRoot":"","sources":["../../../../src/strategy/relay/polymarket/withdraw.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAS3C,OAAO,KAAK,EACV,YAAY,EACZ,iCAAiC,EACjC,mBAAmB,EACpB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,KAAK,EACV,UAAU,EACV,iBAAiB,EACjB,WAAW,EAEZ,MAAM,aAAa,CAAC;AAiBrB,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC;AAElD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,eAAe,GAC3B,OAAO,CAKT;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,YAAY,EACrB,KAAK,EAAE,cAAc,EAAE,EACvB,WAAW,EAAE,eAAe,GAC3B,GAAG,GAAG,SAAS,CAkBjB;AAED;;;;;;;;;GASG;AACH,wBAAsB,sCAAsC,CAC1D,KAAK,EAAE,mBAAmB,CAAC,UAAU,CAAC,EACtC,IAAI,EAAE,GAAG,EACT,SAAS,EAAE,iCAAiC,GAC3C,OAAO,CAAC,eAAe,CAAC,CAgB1B;AAED,wBAAsB,qCAAqC,CACzD,IAAI,EAAE,IAAI,CAAC,iBAAiB,EAAE,QAAQ,GAAG,WAAW,CAAC,EACrD,OAAO,EAAE,YAAY,EACrB,SAAS,EAAE,iCAAiC,GAC3C,OAAO,CAAC,IAAI,CAAC,CAWf;AAED,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,mBAAmB,CAAC,UAAU,CAAC,EACtC,IAAI,EAAE,GAAG,EACT,SAAS,EAAE,iCAAiC,GAC3C,OAAO,CAAC;IAAE,UAAU,EAAE,GAAG,CAAC;IAAC,qBAAqB,EAAE,MAAM,CAAA;CAAE,CAAC,CA0B7D;AAED,wBAAsB,4BAA4B,CAChD,IAAI,EAAE,GAAG,EACT,SAAS,EAAE,iCAAiC,EAC5C,OAAO,EAAE;IACP,WAAW,EAAE,WAAW,GAAG,SAAS,CAAC;IACrC,qBAAqB,EAAE,MAAM,CAAC;CAC/B,GACA,OAAO,CAAC,IAAI,CAAC,CAyDf"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { TransactionType, hasTransactionType, } from '@metamask/transaction-controller';
|
|
2
2
|
import { createModuleLogger } from '@metamask/utils';
|
|
3
|
-
import { CHAIN_ID_POLYGON, POLYGON_PUSD_ADDRESS, POLYGON_USDCE_ADDRESS, } from '
|
|
4
|
-
import { projectLogger } from '
|
|
5
|
-
import { getLiveTokenBalance } from '
|
|
3
|
+
import { CHAIN_ID_POLYGON, POLYGON_PUSD_ADDRESS, POLYGON_USDCE_ADDRESS, } from '../../../constants.js';
|
|
4
|
+
import { projectLogger } from '../../../logger.js';
|
|
5
|
+
import { getLiveTokenBalance } from '../../../utils/token.js';
|
|
6
6
|
import { encodeApprove, encodeUnwrap, encodeWrap, extractErc20TransferRecipient, } from './calldata.js';
|
|
7
7
|
import { POLYMARKET_COLLATERAL_OFFRAMP_POLYGON, POLYMARKET_COLLATERAL_ONRAMP_POLYGON, SWEEP_BALANCE_RETRY_ATTEMPTS, SWEEP_BALANCE_RETRY_DELAY_MS, SWEEP_RELAYER_SETTLE_DELAY_MS, } from './constants.js';
|
|
8
8
|
const log = createModuleLogger(projectLogger, 'polymarket-withdraw');
|
|
@@ -22,108 +22,85 @@ export function isPredictWithdraw(request, transaction) {
|
|
|
22
22
|
* Resolve the Polymarket Safe proxy address that must act as `msg.sender` when
|
|
23
23
|
* estimating gas for the withdraw leg of a Safe-based Predict withdraw.
|
|
24
24
|
*
|
|
25
|
-
* Only applies to the Safe variant on deposit-style routes: the source
|
|
26
|
-
* lives in the Safe (carried as `request.refundTo`), and swap-only routes
|
|
27
|
-
* the EOA `from` because DEX aggregators reject contract callers.
|
|
25
|
+
* Only applies to the Safe variant on deposit-style Relay routes: the source
|
|
26
|
+
* token lives in the Safe (carried as `request.refundTo`), and swap-only routes
|
|
27
|
+
* keep the EOA `from` because DEX aggregators reject contract callers.
|
|
28
28
|
*
|
|
29
29
|
* @param request - Quote request.
|
|
30
|
+
* @param steps - Relay quote steps (used to detect a deposit-style route).
|
|
30
31
|
* @param transaction - Original transaction metadata.
|
|
31
|
-
* @param hasDepositStep - Whether the quote routes through a deposit step.
|
|
32
32
|
* @returns The Safe proxy address, or `undefined` when the default EOA `from`
|
|
33
33
|
* should be used.
|
|
34
34
|
*/
|
|
35
|
-
export function getPredictWithdrawSafeAddress(request,
|
|
36
|
-
if (!
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
export function getPredictWithdrawSafeAddress(request, steps, transaction) {
|
|
36
|
+
if (!isPredictWithdraw(request, transaction)) {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
// Deposit-wallet withdraws are validated via their own simulation builder;
|
|
40
|
+
// `request.refundTo` is not the deposit wallet for that variant.
|
|
41
|
+
if (request.isPolymarketDepositWallet) {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
const hasDepositStep = steps.some((step) => step.id === 'deposit');
|
|
45
|
+
if (!hasDepositStep) {
|
|
39
46
|
return undefined;
|
|
40
47
|
}
|
|
41
48
|
return request.refundTo;
|
|
42
49
|
}
|
|
43
50
|
/**
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* withdraw route: the source token lives in the Safe and the EOA is empty until
|
|
48
|
-
* the Safe call runs mid-batch.
|
|
49
|
-
*
|
|
50
|
-
* @param request - Quote request.
|
|
51
|
-
* @param transaction - Original transaction metadata.
|
|
52
|
-
* @returns The Safe proxy address, or `undefined` for other flows.
|
|
53
|
-
*/
|
|
54
|
-
export function getPredictWithdrawFeeTokenAccount(request, transaction) {
|
|
55
|
-
return isPredictWithdraw(request, transaction) ? request.refundTo : undefined;
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Resolve the quote overrides for a deposit-wallet Predict withdraw. The deposit
|
|
59
|
-
* wallet is both the sender and the refund address, and the provider is funded
|
|
60
|
-
* with the USDC.e produced by unwrapping pUSD.
|
|
51
|
+
* Build the simulation for a Polymarket deposit-wallet Predict withdraw,
|
|
52
|
+
* mirroring the approve + unwrap batch broadcast by {@link submitPolymarketWithdraw}
|
|
53
|
+
* so validation checks the deposit wallet holds enough pUSD.
|
|
61
54
|
*
|
|
55
|
+
* @param quote - Relay quote (source amount + deposit step).
|
|
62
56
|
* @param from - The user EOA that owns the deposit wallet.
|
|
63
57
|
* @param messenger - Controller messenger.
|
|
64
|
-
* @returns The deposit wallet and the source token to quote.
|
|
65
|
-
*/
|
|
66
|
-
export async function getPolymarketDepositWalletOverrides(from, messenger) {
|
|
67
|
-
return {
|
|
68
|
-
depositWallet: await getDepositWalletAddress(messenger, from),
|
|
69
|
-
sourceTokenAddress: POLYGON_USDCE_ADDRESS,
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Build the simulation for a deposit-wallet Predict withdraw, mirroring the
|
|
74
|
-
* batch broadcast by {@link submitPolymarketWithdraw}.
|
|
75
|
-
*
|
|
76
|
-
* @param request - Withdraw request.
|
|
77
58
|
* @returns Simulation for the approve + unwrap batch from the deposit wallet.
|
|
78
59
|
*/
|
|
79
|
-
export async function buildPolymarketDepositWalletSimulation(
|
|
80
|
-
const
|
|
60
|
+
export async function buildPolymarketDepositWalletSimulation(quote, from, messenger) {
|
|
61
|
+
const depositWalletAddress = await getDepositWalletAddress(messenger, from);
|
|
62
|
+
const relayDepositAddress = extractRelayDepositAddress(quote.original);
|
|
63
|
+
const amount = BigInt(quote.sourceAmount.raw);
|
|
81
64
|
return {
|
|
82
|
-
transactions:
|
|
83
|
-
|
|
84
|
-
from: depositWallet,
|
|
65
|
+
transactions: buildDepositWalletUnwrapCalls(relayDepositAddress, amount).map((call) => ({
|
|
66
|
+
from: depositWalletAddress,
|
|
85
67
|
to: call.target,
|
|
68
|
+
data: call.data,
|
|
86
69
|
value: '0x0',
|
|
87
70
|
})),
|
|
88
71
|
};
|
|
89
72
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
const
|
|
100
|
-
const
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
73
|
+
export async function applyPolymarketDepositWalletOverrides(body, request, messenger) {
|
|
74
|
+
const depositWalletAddress = await getDepositWalletAddress(messenger, request.from);
|
|
75
|
+
body.originCurrency = POLYGON_USDCE_ADDRESS;
|
|
76
|
+
body.user = depositWalletAddress;
|
|
77
|
+
body.refundTo = depositWalletAddress;
|
|
78
|
+
body.useDepositAddress = true;
|
|
79
|
+
body.strict = true;
|
|
80
|
+
}
|
|
81
|
+
export async function submitPolymarketWithdraw(quote, from, messenger) {
|
|
82
|
+
const depositWalletAddress = await getDepositWalletAddress(messenger, from);
|
|
83
|
+
const relayDepositAddress = extractRelayDepositAddress(quote.original);
|
|
84
|
+
const amount = BigInt(quote.sourceAmount.raw);
|
|
85
|
+
const preSubmitUsdceBalance = await readUsdceBalanceOrZero(messenger, depositWalletAddress);
|
|
86
|
+
log('Submitting unwrap batch to Relay deposit address', {
|
|
87
|
+
depositWalletAddress,
|
|
88
|
+
relayDepositAddress,
|
|
89
|
+
amount: amount.toString(),
|
|
104
90
|
preSubmitUsdceBalance: preSubmitUsdceBalance.toString(),
|
|
105
|
-
sourceAmountRaw: request.sourceAmountRaw,
|
|
106
91
|
});
|
|
107
92
|
const result = await submitDepositWalletBatch(messenger, {
|
|
108
|
-
calls: calls.map((call) => ({ ...call, value: '0' })),
|
|
109
|
-
depositWallet,
|
|
110
93
|
eoa: from,
|
|
94
|
+
depositWallet: depositWalletAddress,
|
|
95
|
+
calls: buildDepositWalletUnwrapCalls(relayDepositAddress, amount).map((call) => ({ ...call, value: '0' })),
|
|
111
96
|
});
|
|
112
97
|
return { ...result, preSubmitUsdceBalance };
|
|
113
98
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
* @param options.from - The user EOA that owns the deposit wallet.
|
|
120
|
-
* @param options.isRefund - Whether the provider refunded the withdraw, in which
|
|
121
|
-
* case the sweep waits for the refunded balance to land.
|
|
122
|
-
* @param options.messenger - Controller messenger.
|
|
123
|
-
* @param options.preSubmitUsdceBalance - USDC.e balance before the withdraw.
|
|
124
|
-
*/
|
|
125
|
-
export async function sweepPolymarketDepositWallet({ from, isRefund, messenger, preSubmitUsdceBalance, }) {
|
|
126
|
-
const waitForBalanceAbove = isRefund ? preSubmitUsdceBalance : undefined;
|
|
99
|
+
export async function sweepPolymarketDepositWallet(from, messenger, options) {
|
|
100
|
+
const isRefund = options.relayStatus === 'refund' || options.relayStatus === 'refunded';
|
|
101
|
+
const waitForBalanceAbove = isRefund
|
|
102
|
+
? options.preSubmitUsdceBalance
|
|
103
|
+
: undefined;
|
|
127
104
|
const depositWalletAddress = await getDepositWalletAddress(messenger, from);
|
|
128
105
|
const usdceBalance = await readDepositWalletUsdceBalance(messenger, depositWalletAddress, waitForBalanceAbove);
|
|
129
106
|
if (usdceBalance === undefined) {
|
|
@@ -222,22 +199,29 @@ async function submitDepositWalletBatch(messenger, params) {
|
|
|
222
199
|
});
|
|
223
200
|
return result;
|
|
224
201
|
}
|
|
202
|
+
function extractRelayDepositAddress(relayQuote) {
|
|
203
|
+
const depositStep = relayQuote.steps.find((step) => step.id === 'deposit');
|
|
204
|
+
if (depositStep?.kind !== 'transaction') {
|
|
205
|
+
throw new Error('Polymarket deposit wallet withdraw: Relay quote has no deposit step');
|
|
206
|
+
}
|
|
207
|
+
const transactionStep = depositStep;
|
|
208
|
+
const depositCallData = transactionStep.items[0]?.data?.data;
|
|
209
|
+
if (!depositCallData) {
|
|
210
|
+
throw new Error('Polymarket deposit wallet withdraw: Relay quote deposit step is missing calldata');
|
|
211
|
+
}
|
|
212
|
+
return extractErc20TransferRecipient(depositCallData);
|
|
213
|
+
}
|
|
225
214
|
/**
|
|
226
215
|
* Build the approve + unwrap batch that moves a deposit wallet's pUSD to the
|
|
227
|
-
*
|
|
228
|
-
*
|
|
216
|
+
* Relay deposit address as USDC.e. Shared by the simulation and the real submit
|
|
217
|
+
* so both model the exact same calls.
|
|
229
218
|
*
|
|
230
|
-
* @param
|
|
231
|
-
*
|
|
232
|
-
* @param
|
|
219
|
+
* @param relayDepositAddress - The Relay deposit address that receives the
|
|
220
|
+
* unwrapped USDC.e.
|
|
221
|
+
* @param amount - The pUSD amount to unwrap.
|
|
233
222
|
* @returns The two `{ target, data }` calls.
|
|
234
223
|
*/
|
|
235
|
-
function
|
|
236
|
-
if (!depositData) {
|
|
237
|
-
throw new Error('Polymarket deposit wallet withdraw: quote has no deposit step calldata');
|
|
238
|
-
}
|
|
239
|
-
const depositAddress = extractErc20TransferRecipient(depositData);
|
|
240
|
-
const amount = BigInt(sourceAmountRaw);
|
|
224
|
+
function buildDepositWalletUnwrapCalls(relayDepositAddress, amount) {
|
|
241
225
|
return [
|
|
242
226
|
{
|
|
243
227
|
target: POLYGON_PUSD_ADDRESS,
|
|
@@ -247,7 +231,7 @@ function buildUnwrapCalls({ depositData, sourceAmountRaw, }) {
|
|
|
247
231
|
target: POLYMARKET_COLLATERAL_OFFRAMP_POLYGON,
|
|
248
232
|
data: encodeUnwrap({
|
|
249
233
|
asset: POLYGON_USDCE_ADDRESS,
|
|
250
|
-
recipient:
|
|
234
|
+
recipient: relayDepositAddress,
|
|
251
235
|
amount,
|
|
252
236
|
}),
|
|
253
237
|
},
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"withdraw.js","sourceRoot":"","sources":["../../../../src/strategy/relay/polymarket/withdraw.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n TransactionType,\n hasTransactionType,\n} from '@metamask/transaction-controller';\nimport type { TransactionMeta } from '@metamask/transaction-controller';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport {\n CHAIN_ID_POLYGON,\n POLYGON_PUSD_ADDRESS,\n POLYGON_USDCE_ADDRESS,\n} from '../../../constants.js';\nimport { projectLogger } from '../../../logger.js';\nimport type {\n QuoteRequest,\n TransactionPayControllerMessenger,\n TransactionPayQuote,\n} from '../../../types.js';\nimport { getLiveTokenBalance } from '../../../utils/token.js';\nimport type { QuoteSimulation } from '../../../utils/validation.js';\nimport type {\n RelayQuote,\n RelayQuoteRequest,\n RelayStatus,\n RelayTransactionStep,\n} from '../types.js';\nimport {\n encodeApprove,\n encodeUnwrap,\n encodeWrap,\n extractErc20TransferRecipient,\n} from './calldata.js';\nimport {\n POLYMARKET_COLLATERAL_OFFRAMP_POLYGON,\n POLYMARKET_COLLATERAL_ONRAMP_POLYGON,\n SWEEP_BALANCE_RETRY_ATTEMPTS,\n SWEEP_BALANCE_RETRY_DELAY_MS,\n SWEEP_RELAYER_SETTLE_DELAY_MS,\n} from './constants.js';\n\nconst log = createModuleLogger(projectLogger, 'polymarket-withdraw');\n\ntype RelayQuoteStep = RelayQuote['steps'][number];\n\n/**\n * Whether a quote request + transaction represent a Predict withdraw post-quote\n * flow.\n *\n * @param request - Quote request.\n * @param transaction - Original transaction metadata.\n * @returns True when this is a Predict withdraw post-quote flow.\n */\nexport function isPredictWithdraw(\n request: QuoteRequest,\n transaction: TransactionMeta,\n): boolean {\n return Boolean(\n request.isPostQuote &&\n hasTransactionType(transaction, [TransactionType.predictWithdraw]),\n );\n}\n\n/**\n * Resolve the Polymarket Safe proxy address that must act as `msg.sender` when\n * estimating gas for the withdraw leg of a Safe-based Predict withdraw.\n *\n * Only applies to the Safe variant on deposit-style Relay routes: the source\n * token lives in the Safe (carried as `request.refundTo`), and swap-only routes\n * keep the EOA `from` because DEX aggregators reject contract callers.\n *\n * @param request - Quote request.\n * @param steps - Relay quote steps (used to detect a deposit-style route).\n * @param transaction - Original transaction metadata.\n * @returns The Safe proxy address, or `undefined` when the default EOA `from`\n * should be used.\n */\nexport function getPredictWithdrawSafeAddress(\n request: QuoteRequest,\n steps: RelayQuoteStep[],\n transaction: TransactionMeta,\n): Hex | undefined {\n if (!isPredictWithdraw(request, transaction)) {\n return undefined;\n }\n\n // Deposit-wallet withdraws are validated via their own simulation builder;\n // `request.refundTo` is not the deposit wallet for that variant.\n if (request.isPolymarketDepositWallet) {\n return undefined;\n }\n\n const hasDepositStep = steps.some((step) => step.id === 'deposit');\n\n if (!hasDepositStep) {\n return undefined;\n }\n\n return request.refundTo;\n}\n\n/**\n * Build the simulation for a Polymarket deposit-wallet Predict withdraw,\n * mirroring the approve + unwrap batch broadcast by {@link submitPolymarketWithdraw}\n * so validation checks the deposit wallet holds enough pUSD.\n *\n * @param quote - Relay quote (source amount + deposit step).\n * @param from - The user EOA that owns the deposit wallet.\n * @param messenger - Controller messenger.\n * @returns Simulation for the approve + unwrap batch from the deposit wallet.\n */\nexport async function buildPolymarketDepositWalletSimulation(\n quote: TransactionPayQuote<RelayQuote>,\n from: Hex,\n messenger: TransactionPayControllerMessenger,\n): Promise<QuoteSimulation> {\n const depositWalletAddress = await getDepositWalletAddress(messenger, from);\n const relayDepositAddress = extractRelayDepositAddress(quote.original);\n const amount = BigInt(quote.sourceAmount.raw);\n\n return {\n transactions: buildDepositWalletUnwrapCalls(\n relayDepositAddress,\n amount,\n ).map((call) => ({\n from: depositWalletAddress,\n to: call.target,\n data: call.data,\n value: '0x0',\n })),\n };\n}\n\nexport async function applyPolymarketDepositWalletOverrides(\n body: Omit<RelayQuoteRequest, 'amount' | 'tradeType'>,\n request: QuoteRequest,\n messenger: TransactionPayControllerMessenger,\n): Promise<void> {\n const depositWalletAddress = await getDepositWalletAddress(\n messenger,\n request.from,\n );\n\n body.originCurrency = POLYGON_USDCE_ADDRESS;\n body.user = depositWalletAddress;\n body.refundTo = depositWalletAddress;\n body.useDepositAddress = true;\n body.strict = true;\n}\n\nexport async function submitPolymarketWithdraw(\n quote: TransactionPayQuote<RelayQuote>,\n from: Hex,\n messenger: TransactionPayControllerMessenger,\n): Promise<{ sourceHash: Hex; preSubmitUsdceBalance: bigint }> {\n const depositWalletAddress = await getDepositWalletAddress(messenger, from);\n const relayDepositAddress = extractRelayDepositAddress(quote.original);\n const amount = BigInt(quote.sourceAmount.raw);\n\n const preSubmitUsdceBalance = await readUsdceBalanceOrZero(\n messenger,\n depositWalletAddress,\n );\n\n log('Submitting unwrap batch to Relay deposit address', {\n depositWalletAddress,\n relayDepositAddress,\n amount: amount.toString(),\n preSubmitUsdceBalance: preSubmitUsdceBalance.toString(),\n });\n\n const result = await submitDepositWalletBatch(messenger, {\n eoa: from,\n depositWallet: depositWalletAddress,\n calls: buildDepositWalletUnwrapCalls(relayDepositAddress, amount).map(\n (call) => ({ ...call, value: '0' }),\n ),\n });\n\n return { ...result, preSubmitUsdceBalance };\n}\n\nexport async function sweepPolymarketDepositWallet(\n from: Hex,\n messenger: TransactionPayControllerMessenger,\n options: {\n relayStatus: RelayStatus | 'timeout';\n preSubmitUsdceBalance: bigint;\n },\n): Promise<void> {\n const isRefund =\n options.relayStatus === 'refund' || options.relayStatus === 'refunded';\n const waitForBalanceAbove = isRefund\n ? options.preSubmitUsdceBalance\n : undefined;\n\n const depositWalletAddress = await getDepositWalletAddress(messenger, from);\n const usdceBalance = await readDepositWalletUsdceBalance(\n messenger,\n depositWalletAddress,\n waitForBalanceAbove,\n );\n\n if (usdceBalance === undefined) {\n return;\n }\n\n if (usdceBalance === 0n) {\n log('USDC.e sweep: nothing to wrap');\n return;\n }\n\n if (waitForBalanceAbove !== undefined && usdceBalance > waitForBalanceAbove) {\n log('USDC.e sweep: waiting for relayer RPC to catch up to new balance');\n await new Promise((resolve) =>\n setTimeout(resolve, SWEEP_RELAYER_SETTLE_DELAY_MS),\n );\n }\n\n try {\n await submitDepositWalletBatch(messenger, {\n eoa: from,\n depositWallet: depositWalletAddress,\n calls: [\n {\n target: POLYGON_USDCE_ADDRESS,\n value: '0',\n data: encodeApprove(\n POLYMARKET_COLLATERAL_ONRAMP_POLYGON,\n usdceBalance,\n ),\n },\n {\n target: POLYMARKET_COLLATERAL_ONRAMP_POLYGON,\n value: '0',\n data: encodeWrap({\n asset: POLYGON_USDCE_ADDRESS,\n recipient: depositWalletAddress,\n amount: usdceBalance,\n }),\n },\n ],\n });\n } catch (error) {\n log('USDC.e sweep: batch submission failed', { error });\n }\n}\n\nasync function readUsdceBalanceOrZero(\n messenger: TransactionPayControllerMessenger,\n depositWalletAddress: Hex,\n): Promise<bigint> {\n try {\n const raw = await getLiveTokenBalance(\n messenger,\n depositWalletAddress,\n CHAIN_ID_POLYGON,\n POLYGON_USDCE_ADDRESS,\n );\n return BigInt(raw);\n } catch (error) {\n log('USDC.e balance read failed, defaulting to zero', { error });\n return 0n;\n }\n}\n\nasync function readDepositWalletUsdceBalance(\n messenger: TransactionPayControllerMessenger,\n depositWalletAddress: Hex,\n waitForBalanceAbove: bigint | undefined,\n): Promise<bigint | undefined> {\n const shouldRetry = waitForBalanceAbove !== undefined;\n const maxAttempts = shouldRetry ? SWEEP_BALANCE_RETRY_ATTEMPTS : 1;\n let lastBalance = 0n;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n if (attempt > 1) {\n await new Promise((resolve) =>\n setTimeout(resolve, SWEEP_BALANCE_RETRY_DELAY_MS),\n );\n }\n\n try {\n const raw = await getLiveTokenBalance(\n messenger,\n depositWalletAddress,\n CHAIN_ID_POLYGON,\n POLYGON_USDCE_ADDRESS,\n );\n lastBalance = BigInt(raw);\n } catch (error) {\n log('USDC.e sweep: failed to read deposit wallet balance', { error });\n return undefined;\n }\n\n log('USDC.e sweep: deposit wallet balance', {\n depositWalletAddress,\n balance: lastBalance.toString(),\n attempt,\n waitForBalanceAbove: waitForBalanceAbove?.toString(),\n });\n\n const hasIncreased =\n waitForBalanceAbove === undefined || lastBalance > waitForBalanceAbove;\n\n if (hasIncreased) {\n return lastBalance;\n }\n }\n\n return lastBalance;\n}\n\nasync function getDepositWalletAddress(\n messenger: TransactionPayControllerMessenger,\n eoa: Hex,\n): Promise<Hex> {\n const depositWalletAddress = await messenger.call(\n 'TransactionPayController:polymarketGetDepositWalletAddress',\n { eoa },\n );\n log('Polymarket callback: getDepositWalletAddress', {\n eoa,\n depositWalletAddress,\n });\n return depositWalletAddress;\n}\n\nasync function submitDepositWalletBatch(\n messenger: TransactionPayControllerMessenger,\n params: {\n eoa: Hex;\n depositWallet: Hex;\n calls: { target: Hex; data: Hex; value: string }[];\n },\n): Promise<{ sourceHash: Hex }> {\n log('Polymarket callback: submitDepositWalletBatch', {\n eoa: params.eoa,\n depositWallet: params.depositWallet,\n callCount: params.calls.length,\n });\n const result = await messenger.call(\n 'TransactionPayController:polymarketSubmitDepositWalletBatch',\n params,\n );\n log('Polymarket callback: submitDepositWalletBatch returned', {\n sourceHash: result.sourceHash,\n });\n return result;\n}\n\nfunction extractRelayDepositAddress(relayQuote: RelayQuote): Hex {\n const depositStep = relayQuote.steps.find((step) => step.id === 'deposit');\n\n if (depositStep?.kind !== 'transaction') {\n throw new Error(\n 'Polymarket deposit wallet withdraw: Relay quote has no deposit step',\n );\n }\n\n const transactionStep = depositStep as RelayTransactionStep;\n const depositCallData = transactionStep.items[0]?.data?.data;\n\n if (!depositCallData) {\n throw new Error(\n 'Polymarket deposit wallet withdraw: Relay quote deposit step is missing calldata',\n );\n }\n\n return extractErc20TransferRecipient(depositCallData);\n}\n\n/**\n * Build the approve + unwrap batch that moves a deposit wallet's pUSD to the\n * Relay deposit address as USDC.e. Shared by the simulation and the real submit\n * so both model the exact same calls.\n *\n * @param relayDepositAddress - The Relay deposit address that receives the\n * unwrapped USDC.e.\n * @param amount - The pUSD amount to unwrap.\n * @returns The two `{ target, data }` calls.\n */\nfunction buildDepositWalletUnwrapCalls(\n relayDepositAddress: Hex,\n amount: bigint,\n): { target: Hex; data: Hex }[] {\n return [\n {\n target: POLYGON_PUSD_ADDRESS,\n data: encodeApprove(POLYMARKET_COLLATERAL_OFFRAMP_POLYGON, amount),\n },\n {\n target: POLYMARKET_COLLATERAL_OFFRAMP_POLYGON,\n data: encodeUnwrap({\n asset: POLYGON_USDCE_ADDRESS,\n recipient: relayDepositAddress,\n amount,\n }),\n },\n ];\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relay-quotes.d.ts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-quotes.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAGV,2BAA2B,EAG3B,mBAAmB,EACpB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"relay-quotes.d.ts","sourceRoot":"","sources":["../../../src/strategy/relay/relay-quotes.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAGV,2BAA2B,EAG3B,mBAAmB,EACpB,MAAM,gBAAgB,CAAC;AAyCxB,OAAO,KAAK,EACV,UAAU,EAIX,MAAM,YAAY,CAAC;AAuBpB;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,mBAAmB,CAAC,UAAU,CAAC,EAAE,CAAC,CAsE5C"}
|
|
@@ -10,14 +10,13 @@ import { getFiatValueFromUsd } from '../../utils/amounts.js';
|
|
|
10
10
|
import { getFeatureFlags, getRelayOriginGasOverhead, getSlippage, getStablecoins, isAtomicMaxEnabled, isEIP7702Chain, isRelayExecuteEnabled, } from '../../utils/feature-flags.js';
|
|
11
11
|
import { GasPaymentMode, resolveGasPayment, resolveGasStationCost, } from '../../utils/gas-payment.js';
|
|
12
12
|
import { calculateGasCost } from '../../utils/gas.js';
|
|
13
|
-
import { getPolymarketDepositWalletOverrides, getPredictWithdrawFeeTokenAccount, getPredictWithdrawSafeAddress, } from '../../utils/polymarket/withdraw.js';
|
|
14
13
|
import { estimateQuoteGasLimits } from '../../utils/quote-gas.js';
|
|
15
14
|
import { resolveNonAtomicRecipient } from '../../utils/second-leg.js';
|
|
16
15
|
import { getNativeToken, getTokenFiatRate, normalizeTokenAddress, TokenAddressTarget, } from '../../utils/token.js';
|
|
17
16
|
import { getQuotePricing } from '../../utils/trade-type.js';
|
|
18
17
|
import { TOKEN_TRANSFER_FOUR_BYTE } from './constants.js';
|
|
19
|
-
import { hasRelayDepositStep } from './deposit-step.js';
|
|
20
18
|
import { applyHyperliquidActivationFee } from './hyperliquid-activation.js';
|
|
19
|
+
import { applyPolymarketDepositWalletOverrides, getPredictWithdrawSafeAddress, isPredictWithdraw, } from './polymarket/withdraw.js';
|
|
21
20
|
import { fetchRelayQuote } from './relay-api.js';
|
|
22
21
|
import { getRelayMaxQuote, isSubsidizedAtomicMaxQuote, throwAtomicPromotionFailed, } from './relay-max.js';
|
|
23
22
|
import { validateRelayQuotes } from './relay-validation.js';
|
|
@@ -193,13 +192,7 @@ async function getSingleQuote(request, fullRequest) {
|
|
|
193
192
|
user: from,
|
|
194
193
|
};
|
|
195
194
|
if (effectiveRequest.isPolymarketDepositWallet) {
|
|
196
|
-
|
|
197
|
-
const { depositWallet } = overrides;
|
|
198
|
-
body.originCurrency = overrides.sourceTokenAddress;
|
|
199
|
-
body.user = depositWallet;
|
|
200
|
-
body.refundTo = depositWallet;
|
|
201
|
-
body.useDepositAddress = true;
|
|
202
|
-
body.strict = true;
|
|
195
|
+
await applyPolymarketDepositWalletOverrides(body, effectiveRequest, messenger);
|
|
203
196
|
}
|
|
204
197
|
const isAtomic = effectiveRequest.atomic !== false;
|
|
205
198
|
const processedTransactions = await processTransactions(transaction, effectiveRequest, body, messenger);
|
|
@@ -569,6 +562,7 @@ async function calculateSourceNetworkCost(quote, messenger, request, transaction
|
|
|
569
562
|
.flatMap((step) => step.items)
|
|
570
563
|
.map((item) => item.data);
|
|
571
564
|
const { chainId, data, maxFeePerGas, maxPriorityFeePerGas, to, value } = relayParams[0];
|
|
565
|
+
const isPredictWithdrawFlow = isPredictWithdraw(request, transaction);
|
|
572
566
|
// `fromOverride = Safe proxy` is only valid for deposit-style Relay routes
|
|
573
567
|
// where the deposit contract reads the user's source-token balance directly.
|
|
574
568
|
// Same-chain destinations route through DEX swap aggregators that frequently
|
|
@@ -577,7 +571,7 @@ async function calculateSourceNetworkCost(quote, messenger, request, transaction
|
|
|
577
571
|
// native balance). Simulating those from the Safe proxy reverts and breaks
|
|
578
572
|
// gas estimation. For swap-only routes, fall back to the relay params'
|
|
579
573
|
// EOA `from` so simulation succeeds.
|
|
580
|
-
const fromOverride = getPredictWithdrawSafeAddress(request,
|
|
574
|
+
const fromOverride = getPredictWithdrawSafeAddress(request, quote.steps, transaction);
|
|
581
575
|
// For post-quote flows the original transaction will be prepended to the
|
|
582
576
|
// batch at submission time. Include it in the gas estimation so
|
|
583
577
|
// estimateGasBatch sees the full batch and can detect EIP-7702 support.
|
|
@@ -623,7 +617,9 @@ async function calculateSourceNetworkCost(quote, messenger, request, transaction
|
|
|
623
617
|
// return nothing and force users to hold POL.
|
|
624
618
|
// (`useFromOverride` only governs the gas-estimation `from` address, where
|
|
625
619
|
// swap-style routes need EOA because DEX routers reject contract callers.)
|
|
626
|
-
const proxyFeeTokenAccount =
|
|
620
|
+
const proxyFeeTokenAccount = isPredictWithdrawFlow
|
|
621
|
+
? request.refundTo
|
|
622
|
+
: undefined;
|
|
627
623
|
const gasStationCost = await resolveGasStationCost({
|
|
628
624
|
accountSupports7702,
|
|
629
625
|
feeTokenAccount: proxyFeeTokenAccount,
|