Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
eed81ce
feat(transaction-pay-controller): add Polymarket Bridge withdrawal st…
matthewwalsh0 May 6, 2026
65f3e56
fix(transaction-pay-controller): bridge strategy fixes from E2E testing
matthewwalsh0 May 7, 2026
882fe68
feat(transaction-pay-controller): add Polymarket relayer submission p…
matthewwalsh0 May 7, 2026
5e9118d
fix(transaction-pay-controller): zero network fees for Polymarket dep…
matthewwalsh0 May 7, 2026
c4edabf
chore(transaction-pay-controller): link changelog entries to PR #8754
matthewwalsh0 May 11, 2026
1d0137d
Revert "feat(transaction-pay-controller): add Polymarket relayer subm…
matthewwalsh0 May 11, 2026
2076964
refactor(transaction-pay-controller): remove credential plumbing from…
matthewwalsh0 May 11, 2026
300ba24
feat(transaction-pay-controller): route via isPolymarketDepositWallet…
matthewwalsh0 May 11, 2026
d745e63
feat(transaction-pay-controller): surface Polymarket bridge fees, sou…
matthewwalsh0 May 11, 2026
1d4c071
fix(transaction-pay-controller): mark Polymarket bridge withdraws com…
matthewwalsh0 May 11, 2026
5d21988
feat(transaction-pay-controller): experimental Relay-backed Polymarke…
matthewwalsh0 May 11, 2026
cd158bd
feat(transaction-pay-controller): Polymarket bridge withdraw via Rela…
matthewwalsh0 May 11, 2026
4b204a2
refactor(transaction-pay-controller): split PolymarketStrategy into q…
matthewwalsh0 May 11, 2026
66f451f
refactor(transaction-pay-controller): fold Polymarket deposit wallet …
matthewwalsh0 May 11, 2026
d4691f7
refactor(transaction-pay-controller): tighten Polymarket integration …
matthewwalsh0 May 11, 2026
aacc6a6
refactor(transaction-pay-controller): cleanup Polymarket relay integr…
matthewwalsh0 May 11, 2026
e5f2ba2
refactor(transaction-pay-controller): split Polymarket relayer into a…
matthewwalsh0 May 12, 2026
52dc4af
fix(transaction-pay-controller): wait for refunded before sweeping an…
matthewwalsh0 May 12, 2026
638a3ad
fix(transaction-pay-controller): bump Polymarket batch deadline to th…
matthewwalsh0 May 12, 2026
5cd327b
refactor(transaction-pay-controller): inject Polymarket relayer via c…
matthewwalsh0 May 12, 2026
82552fe
feat(transaction-pay-controller): export PolymarketCallbacks and poly…
matthewwalsh0 May 12, 2026
c511f82
feat(transaction-pay-controller): log Polymarket callback boundaries
matthewwalsh0 May 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/transaction-pay-controller/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Add Polymarket deposit-wallet support to the Relay strategy for `predictWithdraw` transactions, routed via the `isPolymarketDepositWallet` flag on `TransactionConfig` ([#8754](https://github.com/MetaMask/core/pull/8754))

## [22.3.0]

### Changed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,30 @@ export type TransactionPayControllerGetStrategyAction = {
handler: TransactionPayController['getStrategy'];
};

/**
* Derives the Polymarket deposit-wallet address for an EOA via the
* client-supplied callback.
*
* @param params - The arguments forwarded to {@link PolymarketCallbacks.getDepositWalletAddress}.
* @returns A promise resolving to the deposit-wallet address.
*/
export type TransactionPayControllerPolymarketGetDepositWalletAddressAction = {
type: `TransactionPayController:polymarketGetDepositWalletAddress`;
handler: TransactionPayController['polymarketGetDepositWalletAddress'];
};

/**
* Signs and broadcasts a Polymarket deposit-wallet batch via the
* client-supplied callback.
*
* @param params - The arguments forwarded to {@link PolymarketCallbacks.submitDepositWalletBatch}.
* @returns A promise resolving to the relayer-issued source hash.
*/
export type TransactionPayControllerPolymarketSubmitDepositWalletBatchAction = {
type: `TransactionPayController:polymarketSubmitDepositWalletBatch`;
handler: TransactionPayController['polymarketSubmitDepositWalletBatch'];
};

/**
* Union of all TransactionPayController action types.
*/
Expand All @@ -89,4 +113,6 @@ export type TransactionPayControllerMethodActions =
| TransactionPayControllerUpdatePaymentTokenAction
| TransactionPayControllerUpdateFiatPaymentAction
| TransactionPayControllerGetDelegationTransactionAction
| TransactionPayControllerGetStrategyAction;
| TransactionPayControllerGetStrategyAction
| TransactionPayControllerPolymarketGetDepositWalletAddressAction
| TransactionPayControllerPolymarketSubmitDepositWalletBatchAction;
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { QuoteRefresher } from './helpers/QuoteRefresher';
import { deriveFiatAssetForFiatPayment } from './strategy/fiat/utils';
import type {
GetDelegationTransactionCallback,
PolymarketCallbacks,
TransactionConfigCallback,
TransactionData,
TransactionPayControllerMessenger,
Expand All @@ -36,6 +37,8 @@ import {
const MESSENGER_EXPOSED_METHODS = [
'getDelegationTransaction',
'getStrategy',
'polymarketGetDepositWalletAddress',
'polymarketSubmitDepositWalletBatch',
'setTransactionConfig',
'updateFiatPayment',
'updatePaymentToken',
Expand Down Expand Up @@ -69,11 +72,14 @@ export class TransactionPayController extends BaseController<
transaction: TransactionMeta,
) => TransactionPayStrategy[];

readonly #polymarket?: PolymarketCallbacks;

constructor({
getDelegationTransaction,
getStrategy,
getStrategies,
messenger,
polymarket,
state,
}: TransactionPayControllerOptions) {
super({
Expand All @@ -86,6 +92,7 @@ export class TransactionPayController extends BaseController<
this.#getDelegationTransaction = getDelegationTransaction;
this.#getStrategy = getStrategy;
this.#getStrategies = getStrategies;
this.#polymarket = polymarket;

this.messenger.registerMethodActionHandlers(
this,
Expand Down Expand Up @@ -130,6 +137,7 @@ export class TransactionPayController extends BaseController<
isMaxAmount: transactionData.isMaxAmount,
isPostQuote: transactionData.isPostQuote,
isHyperliquidSource: transactionData.isHyperliquidSource,
isPolymarketDepositWallet: transactionData.isPolymarketDepositWallet,
refundTo: transactionData.refundTo,
accountOverride: transactionData.accountOverride,
};
Expand All @@ -142,6 +150,8 @@ export class TransactionPayController extends BaseController<
transactionData.isMaxAmount = config.isMaxAmount;
transactionData.isPostQuote = config.isPostQuote;
transactionData.isHyperliquidSource = config.isHyperliquidSource;
transactionData.isPolymarketDepositWallet =
config.isPolymarketDepositWallet;
transactionData.refundTo = config.refundTo;

if (config.accountOverride !== previousAccountOverride) {
Expand Down Expand Up @@ -216,6 +226,41 @@ export class TransactionPayController extends BaseController<
return this.#getStrategiesWithFallback(transaction)[0];
}

/**
* Derives the Polymarket deposit-wallet address for an EOA via the
* client-supplied callback.
*
* @param params - The arguments forwarded to {@link PolymarketCallbacks.getDepositWalletAddress}.
* @returns A promise resolving to the deposit-wallet address.
*/
polymarketGetDepositWalletAddress(
...args: Parameters<PolymarketCallbacks['getDepositWalletAddress']>
): ReturnType<PolymarketCallbacks['getDepositWalletAddress']> {
return this.#requirePolymarket().getDepositWalletAddress(...args);
}

/**
* Signs and broadcasts a Polymarket deposit-wallet batch via the
* client-supplied callback.
*
* @param params - The arguments forwarded to {@link PolymarketCallbacks.submitDepositWalletBatch}.
* @returns A promise resolving to the relayer-issued source hash.
*/
polymarketSubmitDepositWalletBatch(
...args: Parameters<PolymarketCallbacks['submitDepositWalletBatch']>
): ReturnType<PolymarketCallbacks['submitDepositWalletBatch']> {
return this.#requirePolymarket().submitDepositWalletBatch(...args);
}

#requirePolymarket(): PolymarketCallbacks {
if (!this.#polymarket) {
throw new Error(
'TransactionPayController: polymarket callbacks were not supplied to the controller constructor; the Polymarket deposit-wallet flow is not available in this client.',
);
}
return this.#polymarket;
}

#removeTransactionData(transactionId: string): void {
this.update((state) => {
delete state.transactionData[transactionId];
Expand Down Expand Up @@ -325,6 +370,8 @@ export class TransactionPayController extends BaseController<
#getStrategiesWithFallback(
transaction: TransactionMeta,
): TransactionPayStrategy[] {
const transactionData = this.state.transactionData[transaction.id];

const strategyCandidates: unknown[] =
this.#getStrategies?.(transaction) ??
(this.#getStrategy ? [this.#getStrategy(transaction)] : []);
Expand All @@ -338,7 +385,6 @@ export class TransactionPayController extends BaseController<
return validStrategies;
}

const transactionData = this.state.transactionData[transaction.id];
const paymentToken = transactionData?.paymentToken;

return getStrategyOrder(
Expand Down
3 changes: 3 additions & 0 deletions packages/transaction-pay-controller/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export type {
TransactionPayControllerMessenger,
TransactionPayControllerOptions,
TransactionPayControllerState,
PolymarketCallbacks,
TransactionPayControllerStateChangeEvent,
TransactionPaymentToken,
TransactionPayQuote,
Expand All @@ -22,6 +23,8 @@ export type {
export type {
TransactionPayControllerGetDelegationTransactionAction,
TransactionPayControllerGetStrategyAction,
TransactionPayControllerPolymarketGetDepositWalletAddressAction,
TransactionPayControllerPolymarketSubmitDepositWalletBatchAction,
TransactionPayControllerSetTransactionConfigAction,
TransactionPayControllerUpdatePaymentTokenAction,
TransactionPayControllerUpdateFiatPaymentAction,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Interface } from '@ethersproject/abi';
import type { Hex } from '@metamask/utils';

const iface = new Interface([
'function approve(address spender, uint256 amount)',
'function unwrap(address asset, address recipient, uint256 amount)',
'function wrap(address asset, address recipient, uint256 amount)',
'function transfer(address recipient, uint256 amount)',
]);

export function encodeApprove(spender: Hex, amount: bigint): Hex {
return iface.encodeFunctionData('approve', [spender, amount]) as Hex;
}

export function encodeUnwrap({
asset,
recipient,
amount,
}: {
asset: Hex;
recipient: Hex;
amount: bigint;
}): Hex {
return iface.encodeFunctionData('unwrap', [asset, recipient, amount]) as Hex;
}

export function encodeWrap({
asset,
recipient,
amount,
}: {
asset: Hex;
recipient: Hex;
amount: bigint;
}): Hex {
return iface.encodeFunctionData('wrap', [asset, recipient, amount]) as Hex;
}

export function extractErc20TransferRecipient(data: Hex): Hex {
const [recipient] = iface.decodeFunctionData('transfer', data);
return recipient as Hex;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { Hex } from '@metamask/utils';

export const PUSD_ADDRESS_POLYGON =
'0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB' as Hex;

export const USDC_E_ADDRESS_POLYGON =
'0x2791bca1f2de4661ed88a30c99a7a9449aa84174' as Hex;

export const POLYMARKET_COLLATERAL_OFFRAMP_POLYGON =
'0x2957922Eb93258b93368531d39fAcCA3B4dC5854' as Hex;

export const POLYMARKET_COLLATERAL_ONRAMP_POLYGON =
'0x93070a847efEf7F70739046A929D47a521F5B8ee' as Hex;
Loading