@metamask-previews/transaction-pay-controller 26.3.0-preview-e81fe8853 → 26.4.0-preview-3c77cf4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/CHANGELOG.md +15 -1
  2. package/dist/strategy/relay/polymarket/withdraw.cjs +96 -17
  3. package/dist/strategy/relay/polymarket/withdraw.cjs.map +1 -1
  4. package/dist/strategy/relay/polymarket/withdraw.d.cts +39 -0
  5. package/dist/strategy/relay/polymarket/withdraw.d.cts.map +1 -1
  6. package/dist/strategy/relay/polymarket/withdraw.d.mts +39 -0
  7. package/dist/strategy/relay/polymarket/withdraw.d.mts.map +1 -1
  8. package/dist/strategy/relay/polymarket/withdraw.mjs +92 -16
  9. package/dist/strategy/relay/polymarket/withdraw.mjs.map +1 -1
  10. package/dist/strategy/relay/relay-quotes.cjs +3 -7
  11. package/dist/strategy/relay/relay-quotes.cjs.map +1 -1
  12. package/dist/strategy/relay/relay-quotes.d.cts.map +1 -1
  13. package/dist/strategy/relay/relay-quotes.d.mts.map +1 -1
  14. package/dist/strategy/relay/relay-quotes.mjs +4 -8
  15. package/dist/strategy/relay/relay-quotes.mjs.map +1 -1
  16. package/dist/strategy/relay/relay-validation.cjs +42 -19
  17. package/dist/strategy/relay/relay-validation.cjs.map +1 -1
  18. package/dist/strategy/relay/relay-validation.d.cts.map +1 -1
  19. package/dist/strategy/relay/relay-validation.d.mts.map +1 -1
  20. package/dist/strategy/relay/relay-validation.mjs +42 -19
  21. package/dist/strategy/relay/relay-validation.mjs.map +1 -1
  22. package/dist/utils/feature-flags.cjs +22 -3
  23. package/dist/utils/feature-flags.cjs.map +1 -1
  24. package/dist/utils/feature-flags.d.cts +15 -3
  25. package/dist/utils/feature-flags.d.cts.map +1 -1
  26. package/dist/utils/feature-flags.d.mts +15 -3
  27. package/dist/utils/feature-flags.d.mts.map +1 -1
  28. package/dist/utils/feature-flags.mjs +22 -3
  29. package/dist/utils/feature-flags.mjs.map +1 -1
  30. package/dist/utils/validation.cjs +33 -17
  31. package/dist/utils/validation.cjs.map +1 -1
  32. package/dist/utils/validation.d.cts.map +1 -1
  33. package/dist/utils/validation.d.mts.map +1 -1
  34. package/dist/utils/validation.mjs +32 -16
  35. package/dist/utils/validation.mjs.map +1 -1
  36. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [26.4.0]
11
+
12
+ ### Changed
13
+
14
+ - The `payStrategies.relay.validationEnabled` feature flag (in `confirmations_pay_extended`) is now an object `{ default?: boolean; transactionTypes?: { [type in TransactionType]?: boolean } }` instead of a boolean, adding per-`TransactionType` overrides that match nested transactions ([#9888](https://github.com/MetaMask/core/pull/9888))
15
+
16
+ ### Fixed
17
+
18
+ - Fix quote simulation for Polymarket Predict withdrawals ([#9891](https://github.com/MetaMask/core/pull/9891))
19
+
20
+ ## [26.3.1]
21
+
10
22
  ### Changed
11
23
 
12
24
  - Bump `@metamask/assets-controller` from `^13.1.2` to `^13.1.4` ([#9873](https://github.com/MetaMask/core/pull/9873), [#9886](https://github.com/MetaMask/core/pull/9886))
@@ -1438,7 +1450,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1438
1450
 
1439
1451
  - Initial release ([#6820](https://github.com/MetaMask/core/pull/6820))
1440
1452
 
1441
- [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@26.3.0...HEAD
1453
+ [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@26.4.0...HEAD
1454
+ [26.4.0]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@26.3.1...@metamask/transaction-pay-controller@26.4.0
1455
+ [26.3.1]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@26.3.0...@metamask/transaction-pay-controller@26.3.1
1442
1456
  [26.3.0]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@26.2.3...@metamask/transaction-pay-controller@26.3.0
1443
1457
  [26.2.3]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@26.2.2...@metamask/transaction-pay-controller@26.2.3
1444
1458
  [26.2.2]: https://github.com/MetaMask/core/compare/@metamask/transaction-pay-controller@26.2.1...@metamask/transaction-pay-controller@26.2.2
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.sweepPolymarketDepositWallet = exports.submitPolymarketWithdraw = exports.applyPolymarketDepositWalletOverrides = void 0;
3
+ exports.sweepPolymarketDepositWallet = exports.submitPolymarketWithdraw = exports.applyPolymarketDepositWalletOverrides = exports.buildPolymarketDepositWalletSimulation = exports.getPredictWithdrawSafeAddress = exports.isPredictWithdraw = void 0;
4
+ const transaction_controller_1 = require("@metamask/transaction-controller");
4
5
  const utils_1 = require("@metamask/utils");
5
6
  const constants_js_1 = require("../../../constants.cjs");
6
7
  const logger_js_1 = require("../../../logger.cjs");
@@ -8,6 +9,73 @@ const token_js_1 = require("../../../utils/token.cjs");
8
9
  const calldata_js_1 = require("./calldata.cjs");
9
10
  const constants_js_2 = require("./constants.cjs");
10
11
  const log = (0, utils_1.createModuleLogger)(logger_js_1.projectLogger, 'polymarket-withdraw');
12
+ /**
13
+ * Whether a quote request + transaction represent a Predict withdraw post-quote
14
+ * flow.
15
+ *
16
+ * @param request - Quote request.
17
+ * @param transaction - Original transaction metadata.
18
+ * @returns True when this is a Predict withdraw post-quote flow.
19
+ */
20
+ function isPredictWithdraw(request, transaction) {
21
+ return Boolean(request.isPostQuote &&
22
+ (0, transaction_controller_1.hasTransactionType)(transaction, [transaction_controller_1.TransactionType.predictWithdraw]));
23
+ }
24
+ exports.isPredictWithdraw = isPredictWithdraw;
25
+ /**
26
+ * Resolve the Polymarket Safe proxy address that must act as `msg.sender` when
27
+ * estimating gas for the withdraw leg of a Safe-based Predict withdraw.
28
+ *
29
+ * Only applies to the Safe variant on deposit-style Relay routes: the source
30
+ * token lives in the Safe (carried as `request.refundTo`), and swap-only routes
31
+ * keep the EOA `from` because DEX aggregators reject contract callers.
32
+ *
33
+ * @param request - Quote request.
34
+ * @param steps - Relay quote steps (used to detect a deposit-style route).
35
+ * @param transaction - Original transaction metadata.
36
+ * @returns The Safe proxy address, or `undefined` when the default EOA `from`
37
+ * should be used.
38
+ */
39
+ function getPredictWithdrawSafeAddress(request, steps, transaction) {
40
+ if (!isPredictWithdraw(request, transaction)) {
41
+ return undefined;
42
+ }
43
+ // Deposit-wallet withdraws are validated via their own simulation builder;
44
+ // `request.refundTo` is not the deposit wallet for that variant.
45
+ if (request.isPolymarketDepositWallet) {
46
+ return undefined;
47
+ }
48
+ const hasDepositStep = steps.some((step) => step.id === 'deposit');
49
+ if (!hasDepositStep) {
50
+ return undefined;
51
+ }
52
+ return request.refundTo;
53
+ }
54
+ exports.getPredictWithdrawSafeAddress = getPredictWithdrawSafeAddress;
55
+ /**
56
+ * Build the simulation for a Polymarket deposit-wallet Predict withdraw,
57
+ * mirroring the approve + unwrap batch broadcast by {@link submitPolymarketWithdraw}
58
+ * so validation checks the deposit wallet holds enough pUSD.
59
+ *
60
+ * @param quote - Relay quote (source amount + deposit step).
61
+ * @param from - The user EOA that owns the deposit wallet.
62
+ * @param messenger - Controller messenger.
63
+ * @returns Simulation for the approve + unwrap batch from the deposit wallet.
64
+ */
65
+ async function buildPolymarketDepositWalletSimulation(quote, from, messenger) {
66
+ const depositWalletAddress = await getDepositWalletAddress(messenger, from);
67
+ const relayDepositAddress = extractRelayDepositAddress(quote.original);
68
+ const amount = BigInt(quote.sourceAmount.raw);
69
+ return {
70
+ transactions: buildDepositWalletUnwrapCalls(relayDepositAddress, amount).map((call) => ({
71
+ from: depositWalletAddress,
72
+ to: call.target,
73
+ data: call.data,
74
+ value: '0x0',
75
+ })),
76
+ };
77
+ }
78
+ exports.buildPolymarketDepositWalletSimulation = buildPolymarketDepositWalletSimulation;
11
79
  async function applyPolymarketDepositWalletOverrides(body, request, messenger) {
12
80
  const depositWalletAddress = await getDepositWalletAddress(messenger, request.from);
13
81
  body.originCurrency = constants_js_1.POLYGON_USDCE_ADDRESS;
@@ -31,22 +99,7 @@ async function submitPolymarketWithdraw(quote, from, messenger) {
31
99
  const result = await submitDepositWalletBatch(messenger, {
32
100
  eoa: from,
33
101
  depositWallet: depositWalletAddress,
34
- calls: [
35
- {
36
- target: constants_js_1.POLYGON_PUSD_ADDRESS,
37
- value: '0',
38
- data: (0, calldata_js_1.encodeApprove)(constants_js_2.POLYMARKET_COLLATERAL_OFFRAMP_POLYGON, amount),
39
- },
40
- {
41
- target: constants_js_2.POLYMARKET_COLLATERAL_OFFRAMP_POLYGON,
42
- value: '0',
43
- data: (0, calldata_js_1.encodeUnwrap)({
44
- asset: constants_js_1.POLYGON_USDCE_ADDRESS,
45
- recipient: relayDepositAddress,
46
- amount,
47
- }),
48
- },
49
- ],
102
+ calls: buildDepositWalletUnwrapCalls(relayDepositAddress, amount).map((call) => ({ ...call, value: '0' })),
50
103
  });
51
104
  return { ...result, preSubmitUsdceBalance };
52
105
  }
@@ -167,4 +220,30 @@ function extractRelayDepositAddress(relayQuote) {
167
220
  }
168
221
  return (0, calldata_js_1.extractErc20TransferRecipient)(depositCallData);
169
222
  }
223
+ /**
224
+ * Build the approve + unwrap batch that moves a deposit wallet's pUSD to the
225
+ * Relay deposit address as USDC.e. Shared by the simulation and the real submit
226
+ * so both model the exact same calls.
227
+ *
228
+ * @param relayDepositAddress - The Relay deposit address that receives the
229
+ * unwrapped USDC.e.
230
+ * @param amount - The pUSD amount to unwrap.
231
+ * @returns The two `{ target, data }` calls.
232
+ */
233
+ function buildDepositWalletUnwrapCalls(relayDepositAddress, amount) {
234
+ return [
235
+ {
236
+ target: constants_js_1.POLYGON_PUSD_ADDRESS,
237
+ data: (0, calldata_js_1.encodeApprove)(constants_js_2.POLYMARKET_COLLATERAL_OFFRAMP_POLYGON, amount),
238
+ },
239
+ {
240
+ target: constants_js_2.POLYMARKET_COLLATERAL_OFFRAMP_POLYGON,
241
+ data: (0, calldata_js_1.encodeUnwrap)({
242
+ asset: constants_js_1.POLYGON_USDCE_ADDRESS,
243
+ recipient: relayDepositAddress,
244
+ amount,
245
+ }),
246
+ },
247
+ ];
248
+ }
170
249
  //# sourceMappingURL=withdraw.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"withdraw.cjs","sourceRoot":"","sources":["../../../../src/strategy/relay/polymarket/withdraw.ts"],"names":[],"mappings":"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","sourcesContent":["import 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 {\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\nexport async function applyPolymarketDepositWalletOverrides(\n body: RelayQuoteRequest,\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: [\n {\n target: POLYGON_PUSD_ADDRESS,\n value: '0',\n data: encodeApprove(POLYMARKET_COLLATERAL_OFFRAMP_POLYGON, amount),\n },\n {\n target: POLYMARKET_COLLATERAL_OFFRAMP_POLYGON,\n value: '0',\n data: encodeUnwrap({\n asset: POLYGON_USDCE_ADDRESS,\n recipient: relayDepositAddress,\n amount,\n }),\n },\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"]}
1
+ {"version":3,"file":"withdraw.cjs","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: RelayQuoteRequest,\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,6 +1,44 @@
1
+ import type { TransactionMeta } from "@metamask/transaction-controller";
1
2
  import type { Hex } from "@metamask/utils";
2
3
  import type { QuoteRequest, TransactionPayControllerMessenger, TransactionPayQuote } from "../../../types.cjs";
4
+ import type { QuoteSimulation } from "../../../utils/validation.cjs";
3
5
  import type { RelayQuote, RelayQuoteRequest, RelayStatus } from "../types.cjs";
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>;
4
42
  export declare function applyPolymarketDepositWalletOverrides(body: RelayQuoteRequest, request: QuoteRequest, messenger: TransactionPayControllerMessenger): Promise<void>;
5
43
  export declare function submitPolymarketWithdraw(quote: TransactionPayQuote<RelayQuote>, from: Hex, messenger: TransactionPayControllerMessenger): Promise<{
6
44
  sourceHash: Hex;
@@ -10,4 +48,5 @@ export declare function sweepPolymarketDepositWallet(from: Hex, messenger: Trans
10
48
  relayStatus: RelayStatus | 'timeout';
11
49
  preSubmitUsdceBalance: bigint;
12
50
  }): Promise<void>;
51
+ export {};
13
52
  //# sourceMappingURL=withdraw.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"withdraw.d.cts","sourceRoot":"","sources":["../../../../src/strategy/relay/polymarket/withdraw.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAS3C,OAAO,KAAK,EACV,YAAY,EACZ,iCAAiC,EACjC,mBAAmB,EACpB,2BAA0B;AAE3B,OAAO,KAAK,EACV,UAAU,EACV,iBAAiB,EACjB,WAAW,EAEZ,qBAAoB;AAiBrB,wBAAsB,qCAAqC,CACzD,IAAI,EAAE,iBAAiB,EACvB,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,CAuC7D;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
+ {"version":3,"file":"withdraw.d.cts","sourceRoot":"","sources":["../../../../src/strategy/relay/polymarket/withdraw.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,yCAAyC;AACxE,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAS3C,OAAO,KAAK,EACV,YAAY,EACZ,iCAAiC,EACjC,mBAAmB,EACpB,2BAA0B;AAE3B,OAAO,KAAK,EAAE,eAAe,EAAE,sCAAqC;AACpE,OAAO,KAAK,EACV,UAAU,EACV,iBAAiB,EACjB,WAAW,EAEZ,qBAAoB;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,iBAAiB,EACvB,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,6 +1,44 @@
1
+ import type { TransactionMeta } from "@metamask/transaction-controller";
1
2
  import type { Hex } from "@metamask/utils";
2
3
  import type { QuoteRequest, TransactionPayControllerMessenger, TransactionPayQuote } from "../../../types.mjs";
4
+ import type { QuoteSimulation } from "../../../utils/validation.mjs";
3
5
  import type { RelayQuote, RelayQuoteRequest, RelayStatus } from "../types.mjs";
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>;
4
42
  export declare function applyPolymarketDepositWalletOverrides(body: RelayQuoteRequest, request: QuoteRequest, messenger: TransactionPayControllerMessenger): Promise<void>;
5
43
  export declare function submitPolymarketWithdraw(quote: TransactionPayQuote<RelayQuote>, from: Hex, messenger: TransactionPayControllerMessenger): Promise<{
6
44
  sourceHash: Hex;
@@ -10,4 +48,5 @@ export declare function sweepPolymarketDepositWallet(from: Hex, messenger: Trans
10
48
  relayStatus: RelayStatus | 'timeout';
11
49
  preSubmitUsdceBalance: bigint;
12
50
  }): Promise<void>;
51
+ export {};
13
52
  //# sourceMappingURL=withdraw.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"withdraw.d.mts","sourceRoot":"","sources":["../../../../src/strategy/relay/polymarket/withdraw.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAS3C,OAAO,KAAK,EACV,YAAY,EACZ,iCAAiC,EACjC,mBAAmB,EACpB,2BAA0B;AAE3B,OAAO,KAAK,EACV,UAAU,EACV,iBAAiB,EACjB,WAAW,EAEZ,qBAAoB;AAiBrB,wBAAsB,qCAAqC,CACzD,IAAI,EAAE,iBAAiB,EACvB,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,CAuC7D;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
+ {"version":3,"file":"withdraw.d.mts","sourceRoot":"","sources":["../../../../src/strategy/relay/polymarket/withdraw.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,yCAAyC;AACxE,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAS3C,OAAO,KAAK,EACV,YAAY,EACZ,iCAAiC,EACjC,mBAAmB,EACpB,2BAA0B;AAE3B,OAAO,KAAK,EAAE,eAAe,EAAE,sCAAqC;AACpE,OAAO,KAAK,EACV,UAAU,EACV,iBAAiB,EACjB,WAAW,EAEZ,qBAAoB;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,iBAAiB,EACvB,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,3 +1,4 @@
1
+ import { TransactionType, hasTransactionType } from "@metamask/transaction-controller";
1
2
  import { createModuleLogger } from "@metamask/utils";
2
3
  import { CHAIN_ID_POLYGON, POLYGON_PUSD_ADDRESS, POLYGON_USDCE_ADDRESS } from "../../../constants.mjs";
3
4
  import { projectLogger } from "../../../logger.mjs";
@@ -5,6 +6,70 @@ import { getLiveTokenBalance } from "../../../utils/token.mjs";
5
6
  import { encodeApprove, encodeUnwrap, encodeWrap, extractErc20TransferRecipient } from "./calldata.mjs";
6
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.mjs";
7
8
  const log = createModuleLogger(projectLogger, 'polymarket-withdraw');
9
+ /**
10
+ * Whether a quote request + transaction represent a Predict withdraw post-quote
11
+ * flow.
12
+ *
13
+ * @param request - Quote request.
14
+ * @param transaction - Original transaction metadata.
15
+ * @returns True when this is a Predict withdraw post-quote flow.
16
+ */
17
+ export function isPredictWithdraw(request, transaction) {
18
+ return Boolean(request.isPostQuote &&
19
+ hasTransactionType(transaction, [TransactionType.predictWithdraw]));
20
+ }
21
+ /**
22
+ * Resolve the Polymarket Safe proxy address that must act as `msg.sender` when
23
+ * estimating gas for the withdraw leg of a Safe-based Predict withdraw.
24
+ *
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
+ *
29
+ * @param request - Quote request.
30
+ * @param steps - Relay quote steps (used to detect a deposit-style route).
31
+ * @param transaction - Original transaction metadata.
32
+ * @returns The Safe proxy address, or `undefined` when the default EOA `from`
33
+ * should be used.
34
+ */
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) {
46
+ return undefined;
47
+ }
48
+ return request.refundTo;
49
+ }
50
+ /**
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.
54
+ *
55
+ * @param quote - Relay quote (source amount + deposit step).
56
+ * @param from - The user EOA that owns the deposit wallet.
57
+ * @param messenger - Controller messenger.
58
+ * @returns Simulation for the approve + unwrap batch from the deposit wallet.
59
+ */
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);
64
+ return {
65
+ transactions: buildDepositWalletUnwrapCalls(relayDepositAddress, amount).map((call) => ({
66
+ from: depositWalletAddress,
67
+ to: call.target,
68
+ data: call.data,
69
+ value: '0x0',
70
+ })),
71
+ };
72
+ }
8
73
  export async function applyPolymarketDepositWalletOverrides(body, request, messenger) {
9
74
  const depositWalletAddress = await getDepositWalletAddress(messenger, request.from);
10
75
  body.originCurrency = POLYGON_USDCE_ADDRESS;
@@ -27,22 +92,7 @@ export async function submitPolymarketWithdraw(quote, from, messenger) {
27
92
  const result = await submitDepositWalletBatch(messenger, {
28
93
  eoa: from,
29
94
  depositWallet: depositWalletAddress,
30
- calls: [
31
- {
32
- target: POLYGON_PUSD_ADDRESS,
33
- value: '0',
34
- data: encodeApprove(POLYMARKET_COLLATERAL_OFFRAMP_POLYGON, amount),
35
- },
36
- {
37
- target: POLYMARKET_COLLATERAL_OFFRAMP_POLYGON,
38
- value: '0',
39
- data: encodeUnwrap({
40
- asset: POLYGON_USDCE_ADDRESS,
41
- recipient: relayDepositAddress,
42
- amount,
43
- }),
44
- },
45
- ],
95
+ calls: buildDepositWalletUnwrapCalls(relayDepositAddress, amount).map((call) => ({ ...call, value: '0' })),
46
96
  });
47
97
  return { ...result, preSubmitUsdceBalance };
48
98
  }
@@ -161,4 +211,30 @@ function extractRelayDepositAddress(relayQuote) {
161
211
  }
162
212
  return extractErc20TransferRecipient(depositCallData);
163
213
  }
214
+ /**
215
+ * Build the approve + unwrap batch that moves a deposit wallet's pUSD to the
216
+ * Relay deposit address as USDC.e. Shared by the simulation and the real submit
217
+ * so both model the exact same calls.
218
+ *
219
+ * @param relayDepositAddress - The Relay deposit address that receives the
220
+ * unwrapped USDC.e.
221
+ * @param amount - The pUSD amount to unwrap.
222
+ * @returns The two `{ target, data }` calls.
223
+ */
224
+ function buildDepositWalletUnwrapCalls(relayDepositAddress, amount) {
225
+ return [
226
+ {
227
+ target: POLYGON_PUSD_ADDRESS,
228
+ data: encodeApprove(POLYMARKET_COLLATERAL_OFFRAMP_POLYGON, amount),
229
+ },
230
+ {
231
+ target: POLYMARKET_COLLATERAL_OFFRAMP_POLYGON,
232
+ data: encodeUnwrap({
233
+ asset: POLYGON_USDCE_ADDRESS,
234
+ recipient: relayDepositAddress,
235
+ amount,
236
+ }),
237
+ },
238
+ ];
239
+ }
164
240
  //# sourceMappingURL=withdraw.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"withdraw.mjs","sourceRoot":"","sources":["../../../../src/strategy/relay/polymarket/withdraw.ts"],"names":[],"mappings":"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","sourcesContent":["import 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 {\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\nexport async function applyPolymarketDepositWalletOverrides(\n body: RelayQuoteRequest,\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: [\n {\n target: POLYGON_PUSD_ADDRESS,\n value: '0',\n data: encodeApprove(POLYMARKET_COLLATERAL_OFFRAMP_POLYGON, amount),\n },\n {\n target: POLYMARKET_COLLATERAL_OFFRAMP_POLYGON,\n value: '0',\n data: encodeUnwrap({\n asset: POLYGON_USDCE_ADDRESS,\n recipient: relayDepositAddress,\n amount,\n }),\n },\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"]}
1
+ {"version":3,"file":"withdraw.mjs","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: RelayQuoteRequest,\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"]}
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.getRelayQuotes = void 0;
5
5
  const abi_1 = require("@ethersproject/abi");
6
6
  const controller_utils_1 = require("@metamask/controller-utils");
7
- const transaction_controller_1 = require("@metamask/transaction-controller");
8
7
  const utils_1 = require("@metamask/utils");
9
8
  const bignumber_js_1 = require("bignumber.js");
10
9
  const constants_js_1 = require("../../constants.cjs");
@@ -598,8 +597,7 @@ async function calculateSourceNetworkCost(quote, messenger, request, transaction
598
597
  .flatMap((step) => step.items)
599
598
  .map((item) => item.data);
600
599
  const { chainId, data, maxFeePerGas, maxPriorityFeePerGas, to, value } = relayParams[0];
601
- const isPredictWithdraw = request.isPostQuote &&
602
- (0, transaction_controller_1.hasTransactionType)(transaction, [transaction_controller_1.TransactionType.predictWithdraw]);
600
+ const isPredictWithdrawFlow = (0, withdraw_js_1.isPredictWithdraw)(request, transaction);
603
601
  // `fromOverride = Safe proxy` is only valid for deposit-style Relay routes
604
602
  // where the deposit contract reads the user's source-token balance directly.
605
603
  // Same-chain destinations route through DEX swap aggregators that frequently
@@ -608,9 +606,7 @@ async function calculateSourceNetworkCost(quote, messenger, request, transaction
608
606
  // native balance). Simulating those from the Safe proxy reverts and breaks
609
607
  // gas estimation. For swap-only routes, fall back to the relay params'
610
608
  // EOA `from` so simulation succeeds.
611
- const hasDepositStep = quote.steps.some((step) => step.id === 'deposit');
612
- const useFromOverride = isPredictWithdraw && hasDepositStep;
613
- const fromOverride = useFromOverride ? request.refundTo : undefined;
609
+ const fromOverride = (0, withdraw_js_1.getPredictWithdrawSafeAddress)(request, quote.steps, transaction);
614
610
  // For post-quote flows the original transaction will be prepended to the
615
611
  // batch at submission time. Include it in the gas estimation so
616
612
  // estimateGasBatch sees the full batch and can detect EIP-7702 support.
@@ -677,7 +673,7 @@ async function calculateSourceNetworkCost(quote, messenger, request, transaction
677
673
  // return nothing and force users to hold POL.
678
674
  // (`useFromOverride` only governs the gas-estimation `from` address, where
679
675
  // swap-style routes need EOA because DEX routers reject contract callers.)
680
- if (isPredictWithdraw && request.refundTo) {
676
+ if (isPredictWithdrawFlow && request.refundTo) {
681
677
  log('Using proxy address for predict withdraw gas station simulation', {
682
678
  proxyAddress: request.refundTo,
683
679
  sourceTokenAddress,