@axonfi/sdk 0.8.0 → 0.10.0

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/index.d.cts CHANGED
@@ -499,10 +499,10 @@ interface PayInput {
499
499
  * Signed execute intent for DeFi protocol interactions.
500
500
  *
501
501
  * The bot signs this struct using EIP-712. The relayer submits it to
502
- * executeProtocol() on-chain. The contract approves `token` to `protocol`,
503
- * calls it with `callData`, then revokes the approval.
502
+ * executeProtocol() on-chain. The contract approves `tokens` to `protocol`,
503
+ * calls it with `callData`, then revokes the approvals.
504
504
  *
505
- * TypeHash: keccak256("ExecuteIntent(address bot,address protocol,bytes32 calldataHash,address token,uint256 amount,uint256 value,address[] extraTokens,uint256[] extraAmounts,uint256 deadline,bytes32 ref)")
505
+ * TypeHash: keccak256("ExecuteIntent(address bot,address protocol,bytes32 calldataHash,address[] tokens,uint256[] amounts,uint256 value,uint256 deadline,bytes32 ref)")
506
506
  */
507
507
  interface ExecuteIntent {
508
508
  /** Bot's own address. Must be registered in the vault. */
@@ -511,16 +511,12 @@ interface ExecuteIntent {
511
511
  protocol: Address;
512
512
  /** keccak256 of the callData bytes. Verified by relayer before submission. */
513
513
  calldataHash: Hex;
514
- /** Token to approve to the protocol before calling. */
515
- token: Address;
516
- /** Amount to approve (in token base units). */
517
- amount: bigint;
514
+ /** Tokens to approve to the protocol (e.g. [USDC, WETH] for GMX). Empty = no approvals. */
515
+ tokens: Address[];
516
+ /** Approval amounts for each token (must match tokens length). */
517
+ amounts: bigint[];
518
518
  /** Native ETH to send with the protocol call (e.g. WETH.deposit, Lido.submit). 0 = no ETH. */
519
519
  value: bigint;
520
- /** Additional tokens to approve to the SAME protocol (e.g. WETH for GMX execution fee). Bot-signed. */
521
- extraTokens: Address[];
522
- /** Approval amounts for each extra token. Must match extraTokens length. */
523
- extraAmounts: bigint[];
524
520
  /** Unix timestamp after which this intent is invalid. */
525
521
  deadline: bigint;
526
522
  /** keccak256 of the off-chain memo. Full memo text stored by relayer. */
@@ -555,16 +551,19 @@ interface ExecuteInput {
555
551
  protocol: Address;
556
552
  /** The actual calldata bytes to send to the protocol. */
557
553
  callData: Hex;
558
- /** Token to approve to the protocol — an address, Token enum, or bare symbol string ('USDC'). */
559
- token: TokenInput;
560
- /** Amount to approve: bigint (raw base units), number (human-readable), or string (human-readable). */
561
- amount: AmountInput;
554
+ /**
555
+ * Tokens to approve to the protocol. Each entry is an address, Token enum, or bare symbol string.
556
+ * Example: ['USDC'] for single token, ['USDC', 'WETH'] for multi-token (GMX).
557
+ * Empty or omitted = no token approvals (e.g. closing a position).
558
+ */
559
+ tokens?: TokenInput[];
560
+ /**
561
+ * Approval amounts for each token. Must match tokens length.
562
+ * Each entry: bigint (raw base units), number (human-readable), or string (human-readable).
563
+ */
564
+ amounts?: AmountInput[];
562
565
  /** Native ETH to send with the call (wei). Optional, defaults to 0. Used for payable functions like WETH.deposit() or Lido.submit(). */
563
566
  value?: bigint;
564
- /** Additional tokens to approve to the protocol (e.g. WETH for GMX execution fee). Bot signs these. */
565
- extraTokens?: Address[];
566
- /** Approval amounts for each extra token (raw base units). Must match extraTokens length. */
567
- extraAmounts?: bigint[];
568
567
  /** Human-readable description. Gets keccak256-hashed to ref. */
569
568
  memo?: string;
570
569
  /**
@@ -580,10 +579,6 @@ interface ExecuteInput {
580
579
  deadline?: bigint;
581
580
  /** Arbitrary metadata stored off-chain. */
582
581
  metadata?: Record<string, string>;
583
- /** Source token for pre-swap — an address, Token enum, or bare symbol string. */
584
- fromToken?: TokenInput;
585
- /** Max input for pre-swap: bigint (raw), number (human), or string (human). */
586
- maxFromAmount?: AmountInput;
587
582
  }
588
583
  /**
589
584
  * Input for AxonClient.swap(). Signs a SwapIntent and submits to
@@ -621,6 +616,13 @@ interface PaymentResult {
621
616
  estimatedResolutionMs?: number;
622
617
  /** Rejection reason. Present when status === 'rejected'. */
623
618
  reason?: string;
619
+ /**
620
+ * Machine-readable error code. Present when status === 'rejected'.
621
+ * Notable values:
622
+ * - `'SWAP_REQUIRED'` — vault lacks the payment token. The SDK auto-handles
623
+ * this by signing a SwapIntent and resubmitting.
624
+ */
625
+ errorCode?: string;
624
626
  }
625
627
  /** High-level vault info returned by AxonClient.getVaultInfo(). */
626
628
  interface VaultInfo {
@@ -798,6 +800,10 @@ declare class AxonClient {
798
800
  * - `"approved"`: fast path — txHash available immediately
799
801
  * - `"pending_review"`: AI scan or human review in progress — poll for status
800
802
  * - `"rejected"`: payment was rejected — reason field explains why
803
+ *
804
+ * If the vault doesn't hold enough of the payment token, the relayer returns
805
+ * `errorCode: 'SWAP_REQUIRED'`. The SDK automatically signs a SwapIntent and
806
+ * resubmits the payment with swap fields — no action needed from the caller.
801
807
  */
802
808
  pay(input: PayInput): Promise<PaymentResult>;
803
809
  /**
@@ -939,6 +945,7 @@ declare class AxonClient {
939
945
  private _buildPaymentIntent;
940
946
  private _buildExecuteIntent;
941
947
  private _buildSwapIntent;
948
+ private _submitPaymentWithSwap;
942
949
  private _submitPayment;
943
950
  private _submitExecute;
944
951
  private _submitSwap;
@@ -1681,25 +1688,17 @@ declare const AxonVaultAbi: readonly [{
1681
1688
  readonly type: "bytes32";
1682
1689
  readonly internalType: "bytes32";
1683
1690
  }, {
1684
- readonly name: "token";
1685
- readonly type: "address";
1686
- readonly internalType: "address";
1687
- }, {
1688
- readonly name: "amount";
1689
- readonly type: "uint256";
1690
- readonly internalType: "uint256";
1691
- }, {
1692
- readonly name: "value";
1693
- readonly type: "uint256";
1694
- readonly internalType: "uint256";
1695
- }, {
1696
- readonly name: "extraTokens";
1691
+ readonly name: "tokens";
1697
1692
  readonly type: "address[]";
1698
1693
  readonly internalType: "address[]";
1699
1694
  }, {
1700
- readonly name: "extraAmounts";
1695
+ readonly name: "amounts";
1701
1696
  readonly type: "uint256[]";
1702
1697
  readonly internalType: "uint256[]";
1698
+ }, {
1699
+ readonly name: "value";
1700
+ readonly type: "uint256";
1701
+ readonly internalType: "uint256";
1703
1702
  }, {
1704
1703
  readonly name: "deadline";
1705
1704
  readonly type: "uint256";
@@ -3142,6 +3141,10 @@ declare const AxonVaultAbi: readonly [{
3142
3141
  readonly type: "error";
3143
3142
  readonly name: "TooManySpendingLimits";
3144
3143
  readonly inputs: readonly [];
3144
+ }, {
3145
+ readonly type: "error";
3146
+ readonly name: "TooManyTokens";
3147
+ readonly inputs: readonly [];
3145
3148
  }, {
3146
3149
  readonly type: "error";
3147
3150
  readonly name: "UnexpectedETH";
package/dist/index.d.ts CHANGED
@@ -499,10 +499,10 @@ interface PayInput {
499
499
  * Signed execute intent for DeFi protocol interactions.
500
500
  *
501
501
  * The bot signs this struct using EIP-712. The relayer submits it to
502
- * executeProtocol() on-chain. The contract approves `token` to `protocol`,
503
- * calls it with `callData`, then revokes the approval.
502
+ * executeProtocol() on-chain. The contract approves `tokens` to `protocol`,
503
+ * calls it with `callData`, then revokes the approvals.
504
504
  *
505
- * TypeHash: keccak256("ExecuteIntent(address bot,address protocol,bytes32 calldataHash,address token,uint256 amount,uint256 value,address[] extraTokens,uint256[] extraAmounts,uint256 deadline,bytes32 ref)")
505
+ * TypeHash: keccak256("ExecuteIntent(address bot,address protocol,bytes32 calldataHash,address[] tokens,uint256[] amounts,uint256 value,uint256 deadline,bytes32 ref)")
506
506
  */
507
507
  interface ExecuteIntent {
508
508
  /** Bot's own address. Must be registered in the vault. */
@@ -511,16 +511,12 @@ interface ExecuteIntent {
511
511
  protocol: Address;
512
512
  /** keccak256 of the callData bytes. Verified by relayer before submission. */
513
513
  calldataHash: Hex;
514
- /** Token to approve to the protocol before calling. */
515
- token: Address;
516
- /** Amount to approve (in token base units). */
517
- amount: bigint;
514
+ /** Tokens to approve to the protocol (e.g. [USDC, WETH] for GMX). Empty = no approvals. */
515
+ tokens: Address[];
516
+ /** Approval amounts for each token (must match tokens length). */
517
+ amounts: bigint[];
518
518
  /** Native ETH to send with the protocol call (e.g. WETH.deposit, Lido.submit). 0 = no ETH. */
519
519
  value: bigint;
520
- /** Additional tokens to approve to the SAME protocol (e.g. WETH for GMX execution fee). Bot-signed. */
521
- extraTokens: Address[];
522
- /** Approval amounts for each extra token. Must match extraTokens length. */
523
- extraAmounts: bigint[];
524
520
  /** Unix timestamp after which this intent is invalid. */
525
521
  deadline: bigint;
526
522
  /** keccak256 of the off-chain memo. Full memo text stored by relayer. */
@@ -555,16 +551,19 @@ interface ExecuteInput {
555
551
  protocol: Address;
556
552
  /** The actual calldata bytes to send to the protocol. */
557
553
  callData: Hex;
558
- /** Token to approve to the protocol — an address, Token enum, or bare symbol string ('USDC'). */
559
- token: TokenInput;
560
- /** Amount to approve: bigint (raw base units), number (human-readable), or string (human-readable). */
561
- amount: AmountInput;
554
+ /**
555
+ * Tokens to approve to the protocol. Each entry is an address, Token enum, or bare symbol string.
556
+ * Example: ['USDC'] for single token, ['USDC', 'WETH'] for multi-token (GMX).
557
+ * Empty or omitted = no token approvals (e.g. closing a position).
558
+ */
559
+ tokens?: TokenInput[];
560
+ /**
561
+ * Approval amounts for each token. Must match tokens length.
562
+ * Each entry: bigint (raw base units), number (human-readable), or string (human-readable).
563
+ */
564
+ amounts?: AmountInput[];
562
565
  /** Native ETH to send with the call (wei). Optional, defaults to 0. Used for payable functions like WETH.deposit() or Lido.submit(). */
563
566
  value?: bigint;
564
- /** Additional tokens to approve to the protocol (e.g. WETH for GMX execution fee). Bot signs these. */
565
- extraTokens?: Address[];
566
- /** Approval amounts for each extra token (raw base units). Must match extraTokens length. */
567
- extraAmounts?: bigint[];
568
567
  /** Human-readable description. Gets keccak256-hashed to ref. */
569
568
  memo?: string;
570
569
  /**
@@ -580,10 +579,6 @@ interface ExecuteInput {
580
579
  deadline?: bigint;
581
580
  /** Arbitrary metadata stored off-chain. */
582
581
  metadata?: Record<string, string>;
583
- /** Source token for pre-swap — an address, Token enum, or bare symbol string. */
584
- fromToken?: TokenInput;
585
- /** Max input for pre-swap: bigint (raw), number (human), or string (human). */
586
- maxFromAmount?: AmountInput;
587
582
  }
588
583
  /**
589
584
  * Input for AxonClient.swap(). Signs a SwapIntent and submits to
@@ -621,6 +616,13 @@ interface PaymentResult {
621
616
  estimatedResolutionMs?: number;
622
617
  /** Rejection reason. Present when status === 'rejected'. */
623
618
  reason?: string;
619
+ /**
620
+ * Machine-readable error code. Present when status === 'rejected'.
621
+ * Notable values:
622
+ * - `'SWAP_REQUIRED'` — vault lacks the payment token. The SDK auto-handles
623
+ * this by signing a SwapIntent and resubmitting.
624
+ */
625
+ errorCode?: string;
624
626
  }
625
627
  /** High-level vault info returned by AxonClient.getVaultInfo(). */
626
628
  interface VaultInfo {
@@ -798,6 +800,10 @@ declare class AxonClient {
798
800
  * - `"approved"`: fast path — txHash available immediately
799
801
  * - `"pending_review"`: AI scan or human review in progress — poll for status
800
802
  * - `"rejected"`: payment was rejected — reason field explains why
803
+ *
804
+ * If the vault doesn't hold enough of the payment token, the relayer returns
805
+ * `errorCode: 'SWAP_REQUIRED'`. The SDK automatically signs a SwapIntent and
806
+ * resubmits the payment with swap fields — no action needed from the caller.
801
807
  */
802
808
  pay(input: PayInput): Promise<PaymentResult>;
803
809
  /**
@@ -939,6 +945,7 @@ declare class AxonClient {
939
945
  private _buildPaymentIntent;
940
946
  private _buildExecuteIntent;
941
947
  private _buildSwapIntent;
948
+ private _submitPaymentWithSwap;
942
949
  private _submitPayment;
943
950
  private _submitExecute;
944
951
  private _submitSwap;
@@ -1681,25 +1688,17 @@ declare const AxonVaultAbi: readonly [{
1681
1688
  readonly type: "bytes32";
1682
1689
  readonly internalType: "bytes32";
1683
1690
  }, {
1684
- readonly name: "token";
1685
- readonly type: "address";
1686
- readonly internalType: "address";
1687
- }, {
1688
- readonly name: "amount";
1689
- readonly type: "uint256";
1690
- readonly internalType: "uint256";
1691
- }, {
1692
- readonly name: "value";
1693
- readonly type: "uint256";
1694
- readonly internalType: "uint256";
1695
- }, {
1696
- readonly name: "extraTokens";
1691
+ readonly name: "tokens";
1697
1692
  readonly type: "address[]";
1698
1693
  readonly internalType: "address[]";
1699
1694
  }, {
1700
- readonly name: "extraAmounts";
1695
+ readonly name: "amounts";
1701
1696
  readonly type: "uint256[]";
1702
1697
  readonly internalType: "uint256[]";
1698
+ }, {
1699
+ readonly name: "value";
1700
+ readonly type: "uint256";
1701
+ readonly internalType: "uint256";
1703
1702
  }, {
1704
1703
  readonly name: "deadline";
1705
1704
  readonly type: "uint256";
@@ -3142,6 +3141,10 @@ declare const AxonVaultAbi: readonly [{
3142
3141
  readonly type: "error";
3143
3142
  readonly name: "TooManySpendingLimits";
3144
3143
  readonly inputs: readonly [];
3144
+ }, {
3145
+ readonly type: "error";
3146
+ readonly name: "TooManyTokens";
3147
+ readonly inputs: readonly [];
3145
3148
  }, {
3146
3149
  readonly type: "error";
3147
3150
  readonly name: "UnexpectedETH";
package/dist/index.js CHANGED
@@ -16,7 +16,7 @@ var PAYMENT_INTENT_TYPEHASH = keccak256(
16
16
  );
17
17
  var EXECUTE_INTENT_TYPEHASH = keccak256(
18
18
  stringToBytes(
19
- "ExecuteIntent(address bot,address protocol,bytes32 calldataHash,address token,uint256 amount,uint256 value,address[] extraTokens,uint256[] extraAmounts,uint256 deadline,bytes32 ref)"
19
+ "ExecuteIntent(address bot,address protocol,bytes32 calldataHash,address[] tokens,uint256[] amounts,uint256 value,uint256 deadline,bytes32 ref)"
20
20
  )
21
21
  );
22
22
  var SWAP_INTENT_TYPEHASH = keccak256(
@@ -151,11 +151,9 @@ var EXECUTE_INTENT_TYPES = {
151
151
  { name: "bot", type: "address" },
152
152
  { name: "protocol", type: "address" },
153
153
  { name: "calldataHash", type: "bytes32" },
154
- { name: "token", type: "address" },
155
- { name: "amount", type: "uint256" },
154
+ { name: "tokens", type: "address[]" },
155
+ { name: "amounts", type: "uint256[]" },
156
156
  { name: "value", type: "uint256" },
157
- { name: "extraTokens", type: "address[]" },
158
- { name: "extraAmounts", type: "uint256[]" },
159
157
  { name: "deadline", type: "uint256" },
160
158
  { name: "ref", type: "bytes32" }
161
159
  ]
@@ -209,11 +207,9 @@ async function signExecuteIntent(walletClient, vaultAddress, chainId, intent) {
209
207
  bot: intent.bot,
210
208
  protocol: intent.protocol,
211
209
  calldataHash: intent.calldataHash,
212
- token: intent.token,
213
- amount: intent.amount,
210
+ tokens: intent.tokens,
211
+ amounts: intent.amounts,
214
212
  value: intent.value,
215
- extraTokens: intent.extraTokens,
216
- extraAmounts: intent.extraAmounts,
217
213
  deadline: intent.deadline,
218
214
  ref: intent.ref
219
215
  }
@@ -724,30 +720,20 @@ var AxonVaultAbi = [
724
720
  "internalType": "bytes32"
725
721
  },
726
722
  {
727
- "name": "token",
728
- "type": "address",
729
- "internalType": "address"
723
+ "name": "tokens",
724
+ "type": "address[]",
725
+ "internalType": "address[]"
730
726
  },
731
727
  {
732
- "name": "amount",
733
- "type": "uint256",
734
- "internalType": "uint256"
728
+ "name": "amounts",
729
+ "type": "uint256[]",
730
+ "internalType": "uint256[]"
735
731
  },
736
732
  {
737
733
  "name": "value",
738
734
  "type": "uint256",
739
735
  "internalType": "uint256"
740
736
  },
741
- {
742
- "name": "extraTokens",
743
- "type": "address[]",
744
- "internalType": "address[]"
745
- },
746
- {
747
- "name": "extraAmounts",
748
- "type": "uint256[]",
749
- "internalType": "uint256[]"
750
- },
751
737
  {
752
738
  "name": "deadline",
753
739
  "type": "uint256",
@@ -2597,6 +2583,11 @@ var AxonVaultAbi = [
2597
2583
  "name": "TooManySpendingLimits",
2598
2584
  "inputs": []
2599
2585
  },
2586
+ {
2587
+ "type": "error",
2588
+ "name": "TooManyTokens",
2589
+ "inputs": []
2590
+ },
2600
2591
  {
2601
2592
  "type": "error",
2602
2593
  "name": "UnexpectedETH",
@@ -3982,11 +3973,30 @@ var AxonClient = class {
3982
3973
  * - `"approved"`: fast path — txHash available immediately
3983
3974
  * - `"pending_review"`: AI scan or human review in progress — poll for status
3984
3975
  * - `"rejected"`: payment was rejected — reason field explains why
3976
+ *
3977
+ * If the vault doesn't hold enough of the payment token, the relayer returns
3978
+ * `errorCode: 'SWAP_REQUIRED'`. The SDK automatically signs a SwapIntent and
3979
+ * resubmits the payment with swap fields — no action needed from the caller.
3985
3980
  */
3986
3981
  async pay(input) {
3987
3982
  const intent = this._buildPaymentIntent(input);
3988
3983
  const signature = await signPayment(this.walletClient, this.vaultAddress, this.chainId, intent);
3989
- return this._submitPayment(intent, signature, input);
3984
+ const result = await this._submitPayment(intent, signature, input);
3985
+ if (result.status === "rejected" && result.errorCode === "SWAP_REQUIRED") {
3986
+ const swapIntent = {
3987
+ bot: this.botAddress,
3988
+ toToken: intent.token,
3989
+ // swap TO the payment token
3990
+ minToAmount: intent.amount,
3991
+ // need at least the payment amount
3992
+ deadline: intent.deadline,
3993
+ // same deadline
3994
+ ref: intent.ref
3995
+ };
3996
+ const swapSig = await signSwapIntent(this.walletClient, this.vaultAddress, this.chainId, swapIntent);
3997
+ return this._submitPaymentWithSwap(intent, signature, input, swapIntent, swapSig);
3998
+ }
3999
+ return result;
3990
4000
  }
3991
4001
  // ============================================================================
3992
4002
  // execute()
@@ -4222,15 +4232,30 @@ Timestamp: ${timestamp}`;
4222
4232
  }
4223
4233
  _buildExecuteIntent(input) {
4224
4234
  _rejectBurnAddress(input.protocol, "Protocol address");
4235
+ const inputTokens = input.tokens ?? [];
4236
+ const inputAmounts = input.amounts ?? [];
4237
+ if (inputTokens.length !== inputAmounts.length) {
4238
+ throw new Error(`tokens length (${inputTokens.length}) must match amounts length (${inputAmounts.length})`);
4239
+ }
4240
+ if (inputTokens.length > 5) {
4241
+ throw new Error(`Too many tokens (${inputTokens.length}): maximum 5 allowed. Contact Axon if you need more.`);
4242
+ }
4243
+ const resolvedTokens = inputTokens.map((t) => resolveToken(t, this.chainId));
4244
+ const zeroAddr = "0x0000000000000000000000000000000000000000";
4245
+ for (const t of resolvedTokens) {
4246
+ if (t.toLowerCase() === zeroAddr) throw new Error("Zero address not allowed in tokens array");
4247
+ }
4248
+ const uniqueTokens = new Set(resolvedTokens.map((t) => t.toLowerCase()));
4249
+ if (uniqueTokens.size !== resolvedTokens.length) {
4250
+ throw new Error("Duplicate token addresses in tokens array");
4251
+ }
4225
4252
  return {
4226
4253
  bot: this.botAddress,
4227
4254
  protocol: input.protocol,
4228
4255
  calldataHash: keccak256(input.callData),
4229
- token: resolveToken(input.token, this.chainId),
4230
- amount: parseAmount(input.amount, input.token, this.chainId),
4256
+ tokens: resolvedTokens,
4257
+ amounts: inputTokens.map((t, i) => parseAmount(inputAmounts[i], t, this.chainId)),
4231
4258
  value: input.value ?? 0n,
4232
- extraTokens: input.extraTokens ?? [],
4233
- extraAmounts: input.extraAmounts ?? [],
4234
4259
  deadline: input.deadline ?? this._defaultDeadline(),
4235
4260
  ref: this._resolveRef(input.memo, input.ref)
4236
4261
  };
@@ -4244,6 +4269,38 @@ Timestamp: ${timestamp}`;
4244
4269
  ref: this._resolveRef(input.memo, input.ref)
4245
4270
  };
4246
4271
  }
4272
+ async _submitPaymentWithSwap(intent, signature, input, swapIntent, swapSignature) {
4273
+ const idempotencyKey = generateUuid();
4274
+ const body = {
4275
+ // Routing
4276
+ chainId: this.chainId,
4277
+ vaultAddress: this.vaultAddress,
4278
+ // Flat intent fields (matches relayer DTO)
4279
+ bot: intent.bot,
4280
+ to: intent.to,
4281
+ token: intent.token,
4282
+ amount: intent.amount.toString(),
4283
+ deadline: intent.deadline.toString(),
4284
+ ref: intent.ref,
4285
+ signature,
4286
+ // Swap fields
4287
+ swapSignature,
4288
+ swapToToken: swapIntent.toToken,
4289
+ swapMinToAmount: swapIntent.minToAmount.toString(),
4290
+ swapDeadline: swapIntent.deadline.toString(),
4291
+ swapRef: swapIntent.ref,
4292
+ // Off-chain metadata
4293
+ idempotencyKey,
4294
+ ...input.memo !== void 0 && { memo: input.memo },
4295
+ ...input.resourceUrl !== void 0 && { resourceUrl: input.resourceUrl },
4296
+ ...input.invoiceId !== void 0 && { invoiceId: input.invoiceId },
4297
+ ...input.orderId !== void 0 && { orderId: input.orderId },
4298
+ ...input.recipientLabel !== void 0 && { recipientLabel: input.recipientLabel },
4299
+ ...input.metadata !== void 0 && { metadata: input.metadata },
4300
+ ...input.x402Funding !== void 0 && { x402Funding: input.x402Funding }
4301
+ };
4302
+ return this._post(RELAYER_API.PAYMENTS, idempotencyKey, body);
4303
+ }
4247
4304
  async _submitPayment(intent, signature, input) {
4248
4305
  const idempotencyKey = input.idempotencyKey ?? generateUuid();
4249
4306
  const body = {
@@ -4272,8 +4329,6 @@ Timestamp: ${timestamp}`;
4272
4329
  }
4273
4330
  async _submitExecute(intent, signature, input) {
4274
4331
  const idempotencyKey = input.idempotencyKey ?? generateUuid();
4275
- const fromToken = input.fromToken !== void 0 ? resolveToken(input.fromToken, this.chainId) : void 0;
4276
- const maxFromAmount = input.maxFromAmount !== void 0 ? parseAmount(input.maxFromAmount, input.fromToken ?? input.token, this.chainId) : void 0;
4277
4332
  const body = {
4278
4333
  chainId: this.chainId,
4279
4334
  vaultAddress: this.vaultAddress,
@@ -4281,17 +4336,14 @@ Timestamp: ${timestamp}`;
4281
4336
  bot: intent.bot,
4282
4337
  protocol: intent.protocol,
4283
4338
  calldataHash: intent.calldataHash,
4284
- token: intent.token,
4285
- amount: intent.amount.toString(),
4339
+ tokens: intent.tokens,
4340
+ amounts: intent.amounts.map((a) => a.toString()),
4286
4341
  value: intent.value.toString(),
4287
4342
  deadline: intent.deadline.toString(),
4288
4343
  ref: intent.ref,
4289
4344
  signature,
4290
4345
  // Protocol calldata
4291
4346
  callData: input.callData,
4292
- // Optional pre-swap
4293
- ...fromToken !== void 0 && { fromToken },
4294
- ...maxFromAmount !== void 0 && { maxFromAmount: maxFromAmount.toString() },
4295
4347
  // Off-chain metadata
4296
4348
  idempotencyKey,
4297
4349
  ...input.memo !== void 0 && { memo: input.memo },