@axonfi/sdk 0.9.0 → 0.11.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.cjs CHANGED
@@ -66,10 +66,12 @@ var EXPLORER_ADDR = {
66
66
  var DEFAULT_DEADLINE_SECONDS = 300;
67
67
  var WINDOW = {
68
68
  ONE_HOUR: 3600n,
69
+ THREE_HOURS: 10800n,
69
70
  ONE_DAY: 86400n,
70
71
  ONE_WEEK: 604800n,
71
72
  THIRTY_DAYS: 2592000n
72
73
  };
74
+ var ALLOWED_WINDOWS = new Set(Object.values(WINDOW));
73
75
  var PaymentErrorCode = {
74
76
  /** Payment destination is the vault itself */
75
77
  SELF_PAYMENT: "SELF_PAYMENT",
@@ -672,26 +674,6 @@ var AxonVaultAbi = [
672
674
  "name": "signature",
673
675
  "type": "bytes",
674
676
  "internalType": "bytes"
675
- },
676
- {
677
- "name": "fromToken",
678
- "type": "address",
679
- "internalType": "address"
680
- },
681
- {
682
- "name": "maxFromAmount",
683
- "type": "uint256",
684
- "internalType": "uint256"
685
- },
686
- {
687
- "name": "swapRouter",
688
- "type": "address",
689
- "internalType": "address"
690
- },
691
- {
692
- "name": "swapCalldata",
693
- "type": "bytes",
694
- "internalType": "bytes"
695
677
  }
696
678
  ],
697
679
  "outputs": [],
@@ -757,26 +739,6 @@ var AxonVaultAbi = [
757
739
  "name": "callData",
758
740
  "type": "bytes",
759
741
  "internalType": "bytes"
760
- },
761
- {
762
- "name": "fromToken",
763
- "type": "address",
764
- "internalType": "address"
765
- },
766
- {
767
- "name": "maxFromAmount",
768
- "type": "uint256",
769
- "internalType": "uint256"
770
- },
771
- {
772
- "name": "swapRouter",
773
- "type": "address",
774
- "internalType": "address"
775
- },
776
- {
777
- "name": "swapCalldata",
778
- "type": "bytes",
779
- "internalType": "bytes"
780
742
  }
781
743
  ],
782
744
  "outputs": [
@@ -2233,55 +2195,6 @@ var AxonVaultAbi = [
2233
2195
  ],
2234
2196
  "anonymous": false
2235
2197
  },
2236
- {
2237
- "type": "event",
2238
- "name": "SwapPaymentExecuted",
2239
- "inputs": [
2240
- {
2241
- "name": "bot",
2242
- "type": "address",
2243
- "indexed": true,
2244
- "internalType": "address"
2245
- },
2246
- {
2247
- "name": "to",
2248
- "type": "address",
2249
- "indexed": true,
2250
- "internalType": "address"
2251
- },
2252
- {
2253
- "name": "fromToken",
2254
- "type": "address",
2255
- "indexed": false,
2256
- "internalType": "address"
2257
- },
2258
- {
2259
- "name": "toToken",
2260
- "type": "address",
2261
- "indexed": false,
2262
- "internalType": "address"
2263
- },
2264
- {
2265
- "name": "fromAmount",
2266
- "type": "uint256",
2267
- "indexed": false,
2268
- "internalType": "uint256"
2269
- },
2270
- {
2271
- "name": "toAmount",
2272
- "type": "uint256",
2273
- "indexed": false,
2274
- "internalType": "uint256"
2275
- },
2276
- {
2277
- "name": "ref",
2278
- "type": "bytes32",
2279
- "indexed": false,
2280
- "internalType": "bytes32"
2281
- }
2282
- ],
2283
- "anonymous": false
2284
- },
2285
2198
  {
2286
2199
  "type": "event",
2287
2200
  "name": "Unpaused",
@@ -2424,22 +2337,22 @@ var AxonVaultAbi = [
2424
2337
  },
2425
2338
  {
2426
2339
  "type": "error",
2427
- "name": "InsufficientBalance",
2340
+ "name": "IntentAlreadyUsed",
2428
2341
  "inputs": []
2429
2342
  },
2430
2343
  {
2431
2344
  "type": "error",
2432
- "name": "IntentAlreadyUsed",
2345
+ "name": "InvalidInitialization",
2433
2346
  "inputs": []
2434
2347
  },
2435
2348
  {
2436
2349
  "type": "error",
2437
- "name": "InvalidInitialization",
2350
+ "name": "InvalidSignature",
2438
2351
  "inputs": []
2439
2352
  },
2440
2353
  {
2441
2354
  "type": "error",
2442
- "name": "InvalidSignature",
2355
+ "name": "InvalidSpendingWindow",
2443
2356
  "inputs": []
2444
2357
  },
2445
2358
  {
@@ -3250,6 +3163,12 @@ function createAxonWalletClient(privateKey, chainId) {
3250
3163
  var USDC_DECIMALS = 6n;
3251
3164
  var USDC_UNIT = 10n ** USDC_DECIMALS;
3252
3165
  function toBotConfigParams(input) {
3166
+ for (const sl of input.spendingLimits) {
3167
+ if (!ALLOWED_WINDOWS.has(BigInt(sl.windowSeconds))) {
3168
+ const allowed = [...ALLOWED_WINDOWS].map((w) => `${Number(w)}s`).join(", ");
3169
+ throw new Error(`Invalid spending window: ${sl.windowSeconds}s. Allowed values: ${allowed}. Use WINDOW constants.`);
3170
+ }
3171
+ }
3253
3172
  return {
3254
3173
  maxPerTxAmount: BigInt(Math.round(input.maxPerTxAmount * Number(USDC_UNIT))),
3255
3174
  maxRebalanceAmount: BigInt(Math.round(input.maxRebalanceAmount * Number(USDC_UNIT))),
@@ -3975,11 +3894,30 @@ var AxonClient = class {
3975
3894
  * - `"approved"`: fast path — txHash available immediately
3976
3895
  * - `"pending_review"`: AI scan or human review in progress — poll for status
3977
3896
  * - `"rejected"`: payment was rejected — reason field explains why
3897
+ *
3898
+ * If the vault doesn't hold enough of the payment token, the relayer returns
3899
+ * `errorCode: 'SWAP_REQUIRED'`. The SDK automatically signs a SwapIntent and
3900
+ * resubmits the payment with swap fields — no action needed from the caller.
3978
3901
  */
3979
3902
  async pay(input) {
3980
3903
  const intent = this._buildPaymentIntent(input);
3981
3904
  const signature = await signPayment(this.walletClient, this.vaultAddress, this.chainId, intent);
3982
- return this._submitPayment(intent, signature, input);
3905
+ const result = await this._submitPayment(intent, signature, input);
3906
+ if (result.status === "rejected" && result.errorCode === "SWAP_REQUIRED") {
3907
+ const swapIntent = {
3908
+ bot: this.botAddress,
3909
+ toToken: intent.token,
3910
+ // swap TO the payment token
3911
+ minToAmount: intent.amount,
3912
+ // need at least the payment amount
3913
+ deadline: intent.deadline,
3914
+ // same deadline
3915
+ ref: intent.ref
3916
+ };
3917
+ const swapSig = await signSwapIntent(this.walletClient, this.vaultAddress, this.chainId, swapIntent);
3918
+ return this._submitPaymentWithSwap(intent, signature, input, swapIntent, swapSig);
3919
+ }
3920
+ return result;
3983
3921
  }
3984
3922
  // ============================================================================
3985
3923
  // execute()
@@ -3990,6 +3928,12 @@ var AxonClient = class {
3990
3928
  * The vault approves `token` to `protocol`, calls it with `callData`,
3991
3929
  * then revokes the approval. Tokens stay in the vault or go to the protocol
3992
3930
  * as specified by the calldata.
3931
+ *
3932
+ * **Approval rules for default tokens** (USDC, WETH, etc.): when calling
3933
+ * `approve()` on a default token, the spender must be an approved protocol
3934
+ * or swap router — the contract rejects arbitrary addresses. The approve
3935
+ * amount is capped by the bot's `maxPerTxAmount` and counts toward
3936
+ * spending limits.
3993
3937
  */
3994
3938
  async execute(input) {
3995
3939
  const intent = this._buildExecuteIntent(input);
@@ -4252,6 +4196,38 @@ Timestamp: ${timestamp}`;
4252
4196
  ref: this._resolveRef(input.memo, input.ref)
4253
4197
  };
4254
4198
  }
4199
+ async _submitPaymentWithSwap(intent, signature, input, swapIntent, swapSignature) {
4200
+ const idempotencyKey = generateUuid();
4201
+ const body = {
4202
+ // Routing
4203
+ chainId: this.chainId,
4204
+ vaultAddress: this.vaultAddress,
4205
+ // Flat intent fields (matches relayer DTO)
4206
+ bot: intent.bot,
4207
+ to: intent.to,
4208
+ token: intent.token,
4209
+ amount: intent.amount.toString(),
4210
+ deadline: intent.deadline.toString(),
4211
+ ref: intent.ref,
4212
+ signature,
4213
+ // Swap fields
4214
+ swapSignature,
4215
+ swapToToken: swapIntent.toToken,
4216
+ swapMinToAmount: swapIntent.minToAmount.toString(),
4217
+ swapDeadline: swapIntent.deadline.toString(),
4218
+ swapRef: swapIntent.ref,
4219
+ // Off-chain metadata
4220
+ idempotencyKey,
4221
+ ...input.memo !== void 0 && { memo: input.memo },
4222
+ ...input.resourceUrl !== void 0 && { resourceUrl: input.resourceUrl },
4223
+ ...input.invoiceId !== void 0 && { invoiceId: input.invoiceId },
4224
+ ...input.orderId !== void 0 && { orderId: input.orderId },
4225
+ ...input.recipientLabel !== void 0 && { recipientLabel: input.recipientLabel },
4226
+ ...input.metadata !== void 0 && { metadata: input.metadata },
4227
+ ...input.x402Funding !== void 0 && { x402Funding: input.x402Funding }
4228
+ };
4229
+ return this._post(RELAYER_API.PAYMENTS, idempotencyKey, body);
4230
+ }
4255
4231
  async _submitPayment(intent, signature, input) {
4256
4232
  const idempotencyKey = input.idempotencyKey ?? generateUuid();
4257
4233
  const body = {
@@ -4280,8 +4256,6 @@ Timestamp: ${timestamp}`;
4280
4256
  }
4281
4257
  async _submitExecute(intent, signature, input) {
4282
4258
  const idempotencyKey = input.idempotencyKey ?? generateUuid();
4283
- const fromToken = input.fromToken !== void 0 ? resolveToken(input.fromToken, this.chainId) : void 0;
4284
- const maxFromAmount = input.maxFromAmount !== void 0 ? parseAmount(input.maxFromAmount, input.fromToken ?? input.tokens?.[0] ?? "USDC", this.chainId) : void 0;
4285
4259
  const body = {
4286
4260
  chainId: this.chainId,
4287
4261
  vaultAddress: this.vaultAddress,
@@ -4297,9 +4271,6 @@ Timestamp: ${timestamp}`;
4297
4271
  signature,
4298
4272
  // Protocol calldata
4299
4273
  callData: input.callData,
4300
- // Optional pre-swap
4301
- ...fromToken !== void 0 && { fromToken },
4302
- ...maxFromAmount !== void 0 && { maxFromAmount: maxFromAmount.toString() },
4303
4274
  // Off-chain metadata
4304
4275
  idempotencyKey,
4305
4276
  ...input.memo !== void 0 && { memo: input.memo },
@@ -4989,6 +4960,7 @@ var AxonRegistryAbi = [
4989
4960
  }
4990
4961
  ];
4991
4962
 
4963
+ exports.ALLOWED_WINDOWS = ALLOWED_WINDOWS;
4992
4964
  exports.AxonClient = AxonClient;
4993
4965
  exports.AxonRegistryAbi = AxonRegistryAbi;
4994
4966
  exports.AxonVaultAbi = AxonVaultAbi;