@circle-fin/app-kit 1.11.0 → 1.12.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.
@@ -40,6 +40,7 @@ var web3_js = require('@solana/web3.js');
40
40
  require('bn.js');
41
41
  require('@coral-xyz/anchor');
42
42
  require('@noble/curves/ed25519');
43
+ require('viem');
43
44
  var keccak256 = require('@ethersproject/keccak256');
44
45
 
45
46
  function _interopDefault (e) { return e && e.__esModule ? e.default : e; }
@@ -2562,6 +2563,8 @@ class KitError extends Error {
2562
2563
  Blockchain["World_Chain_Sepolia"] = "World_Chain_Sepolia";
2563
2564
  Blockchain["XDC"] = "XDC";
2564
2565
  Blockchain["XDC_Apothem"] = "XDC_Apothem";
2566
+ Blockchain["X_Layer"] = "X_Layer";
2567
+ Blockchain["X_Layer_Testnet"] = "X_Layer_Testnet";
2565
2568
  Blockchain["ZKSync_Era"] = "ZKSync_Era";
2566
2569
  Blockchain["ZKSync_Sepolia"] = "ZKSync_Sepolia";
2567
2570
  })(Blockchain || (Blockchain = {}));
@@ -2615,6 +2618,7 @@ var BridgeChain;
2615
2618
  BridgeChain["Unichain"] = "Unichain";
2616
2619
  BridgeChain["World_Chain"] = "World_Chain";
2617
2620
  BridgeChain["XDC"] = "XDC";
2621
+ BridgeChain["X_Layer"] = "X_Layer";
2618
2622
  // Testnet chains with CCTPv2 support
2619
2623
  BridgeChain["Arc_Testnet"] = "Arc_Testnet";
2620
2624
  BridgeChain["Arbitrum_Sepolia"] = "Arbitrum_Sepolia";
@@ -2640,6 +2644,7 @@ var BridgeChain;
2640
2644
  BridgeChain["Unichain_Sepolia"] = "Unichain_Sepolia";
2641
2645
  BridgeChain["World_Chain_Sepolia"] = "World_Chain_Sepolia";
2642
2646
  BridgeChain["XDC_Apothem"] = "XDC_Apothem";
2647
+ BridgeChain["X_Layer_Testnet"] = "X_Layer_Testnet";
2643
2648
  })(BridgeChain || (BridgeChain = {}));
2644
2649
  var UnifiedBalanceChain;
2645
2650
  (function(UnifiedBalanceChain) {
@@ -5177,7 +5182,8 @@ var EarnChain;
5177
5182
  isTestnet: true,
5178
5183
  explorerUrl: 'https://amoy.polygonscan.com/tx/{hash}',
5179
5184
  rpcEndpoints: [
5180
- 'https://rpc-amoy.polygon.technology'
5185
+ 'https://polygon-amoy-bor-rpc.publicnode.com',
5186
+ 'https://polygon-amoy.drpc.org'
5181
5187
  ],
5182
5188
  eurcAddress: null,
5183
5189
  usdcAddress: '0x41e94eb019c0762f9bfcf9fb1e58725bfb0e7582',
@@ -6042,6 +6048,104 @@ var EarnChain;
6042
6048
  }
6043
6049
  });
6044
6050
 
6051
+ /**
6052
+ * X Layer Mainnet chain definition
6053
+ * @remarks
6054
+ * This represents the official production network for the X Layer blockchain.
6055
+ * X Layer is an EVM-compatible OP Stack Layer-2 blockchain built by OKX,
6056
+ * using OKB as its native gas token. (Migrated from Polygon zkEVM/CDK to the
6057
+ * OP Stack on 2025-10-27; older docs describing it as zkEVM are obsolete.)
6058
+ */ const XLayer = defineChain({
6059
+ type: 'evm',
6060
+ chain: Blockchain.X_Layer,
6061
+ name: 'X Layer',
6062
+ title: 'X Layer Mainnet',
6063
+ nativeCurrency: {
6064
+ name: 'OKB',
6065
+ symbol: 'OKB',
6066
+ decimals: 18
6067
+ },
6068
+ chainId: 196,
6069
+ isTestnet: false,
6070
+ explorerUrl: 'https://www.oklink.com/xlayer/tx/{hash}',
6071
+ rpcEndpoints: [
6072
+ 'https://xlayerrpc.okx.com'
6073
+ ],
6074
+ eurcAddress: null,
6075
+ usdcAddress: '0xB6CEceAB302E2E4948951eE7843FC24E92933061',
6076
+ usdtAddress: null,
6077
+ cctp: {
6078
+ domain: 37,
6079
+ contracts: {
6080
+ v2: {
6081
+ type: 'split',
6082
+ tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
6083
+ messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
6084
+ confirmations: 65,
6085
+ fastConfirmations: 1
6086
+ }
6087
+ },
6088
+ forwarderSupported: {
6089
+ source: false,
6090
+ destination: false
6091
+ }
6092
+ },
6093
+ kitContracts: {
6094
+ bridge: BRIDGE_CONTRACT_EVM_MAINNET
6095
+ }
6096
+ });
6097
+
6098
+ /**
6099
+ * X Layer Testnet chain definition
6100
+ * @remarks
6101
+ * This represents the official test network for the X Layer blockchain.
6102
+ * X Layer is an EVM-compatible OP Stack Layer-2 blockchain built by OKX,
6103
+ * using OKB as its native gas token. (Migrated from Polygon zkEVM/CDK to the
6104
+ * OP Stack on 2025-10-27; older docs describing it as zkEVM are obsolete.)
6105
+ */ const XLayerTestnet = defineChain({
6106
+ type: 'evm',
6107
+ chain: Blockchain.X_Layer_Testnet,
6108
+ name: 'X Layer Testnet',
6109
+ title: 'X Layer Testnet',
6110
+ nativeCurrency: {
6111
+ name: 'OKB',
6112
+ symbol: 'OKB',
6113
+ decimals: 18
6114
+ },
6115
+ chainId: 1952,
6116
+ isTestnet: true,
6117
+ // Deliberately not oklink.com (used for mainnet): viem's bundled OKLink
6118
+ // testnet URL targets the deprecated pre-rebrand chain ID 195, not this
6119
+ // chain's ID (1952). Verified against the internal chain-expansion-scripts
6120
+ // config (`v2config.sandbox.yml`) — do not "normalize" this to match mainnet.
6121
+ explorerUrl: 'https://web3.okx.com/explorer/x-layer-testnet/tx/{hash}',
6122
+ rpcEndpoints: [
6123
+ 'https://testrpc.xlayer.tech'
6124
+ ],
6125
+ eurcAddress: null,
6126
+ usdcAddress: '0xDec90b78111Ba2fc6FC6d84d8B9ec159A2d4b9B3',
6127
+ usdtAddress: null,
6128
+ cctp: {
6129
+ domain: 37,
6130
+ contracts: {
6131
+ v2: {
6132
+ type: 'split',
6133
+ tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
6134
+ messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
6135
+ confirmations: 65,
6136
+ fastConfirmations: 1
6137
+ }
6138
+ },
6139
+ forwarderSupported: {
6140
+ source: false,
6141
+ destination: false
6142
+ }
6143
+ },
6144
+ kitContracts: {
6145
+ bridge: BRIDGE_CONTRACT_EVM_TESTNET
6146
+ }
6147
+ });
6148
+
6045
6149
  /**
6046
6150
  * ZKSync Era Mainnet chain definition
6047
6151
  * @remarks
@@ -6161,6 +6265,8 @@ var Chains = {
6161
6265
  WorldChainSepolia: WorldChainSepolia,
6162
6266
  XDC: XDC,
6163
6267
  XDCApothem: XDCApothem,
6268
+ XLayer: XLayer,
6269
+ XLayerTestnet: XLayerTestnet,
6164
6270
  ZKSyncEra: ZKSyncEra,
6165
6271
  ZKSyncEraSepolia: ZKSyncEraSepolia
6166
6272
  };
@@ -8215,6 +8321,7 @@ const swapTokenEnumSchema = zod.z.enum([
8215
8321
  [Blockchain.Unichain]: '0x078D782b760474a361dDA0AF3839290b0EF57AD6',
8216
8322
  [Blockchain.World_Chain]: '0x79A02482A880bCE3F13e09Da970dC34db4CD24d1',
8217
8323
  [Blockchain.XDC]: '0xfA2958CB79b0491CC627c1557F441eF849Ca8eb1',
8324
+ [Blockchain.X_Layer]: '0xB6CEceAB302E2E4948951eE7843FC24E92933061',
8218
8325
  [Blockchain.ZKSync_Era]: '0x1d17CBcF0D6D143135aE902365D2E5e2A16538D4',
8219
8326
  // =========================================================================
8220
8327
  // Testnets (alphabetically sorted)
@@ -8249,6 +8356,7 @@ const swapTokenEnumSchema = zod.z.enum([
8249
8356
  [Blockchain.Unichain_Sepolia]: '0x31d0220469e10c4E71834a79b1f276d740d3768F',
8250
8357
  [Blockchain.World_Chain_Sepolia]: '0x66145f38cBAC35Ca6F1Dfb4914dF98F1614aeA88',
8251
8358
  [Blockchain.XDC_Apothem]: '0xb5AB69F7bBada22B28e79C8FFAECe55eF1c771D4',
8359
+ [Blockchain.X_Layer_Testnet]: '0xDec90b78111Ba2fc6FC6d84d8B9ec159A2d4b9B3',
8252
8360
  [Blockchain.ZKSync_Sepolia]: '0xAe045DE5638162fa134807Cb558E15A3F5A7F853'
8253
8361
  }
8254
8362
  };
@@ -9660,7 +9768,7 @@ function resolveOptions(options) {
9660
9768
  }
9661
9769
 
9662
9770
  var name$2 = "@circle-fin/bridge-kit";
9663
- var version$3 = "1.12.2";
9771
+ var version$3 = "1.13.0";
9664
9772
  var pkg$3 = {
9665
9773
  name: name$2,
9666
9774
  version: version$3};
@@ -9697,13 +9805,21 @@ const assertCustomFeePolicySymbol = Symbol('assertCustomFeePolicy');
9697
9805
  computeFee: zod.z.function().returns(zod.z.string().or(zod.z.promise(zod.z.string()))).optional(),
9698
9806
  calculateFee: zod.z.function().returns(zod.z.string().or(zod.z.promise(zod.z.string()))).optional(),
9699
9807
  resolveFeeRecipientAddress: zod.z.function().returns(zod.z.string().or(zod.z.promise(zod.z.string())))
9700
- }).strict().refine((data)=>{
9808
+ }).strict().superRefine((data, ctx)=>{
9701
9809
  const hasComputeFee = data.computeFee !== undefined;
9702
9810
  const hasCalculateFee = data.calculateFee !== undefined;
9703
- // XOR: exactly one must be provided
9704
- return hasComputeFee !== hasCalculateFee;
9705
- }, {
9706
- message: 'Provide either computeFee or calculateFee, not both. Use computeFee (recommended) for human-readable amounts.'
9811
+ if (hasComputeFee && hasCalculateFee) {
9812
+ ctx.addIssue({
9813
+ code: zod.z.ZodIssueCode.custom,
9814
+ message: 'Provide either computeFee or calculateFee, not both. Use computeFee (recommended) for human-readable amounts.'
9815
+ });
9816
+ }
9817
+ if (!hasComputeFee && !hasCalculateFee) {
9818
+ ctx.addIssue({
9819
+ code: zod.z.ZodIssueCode.custom,
9820
+ message: 'Provide either computeFee or calculateFee. Use computeFee (recommended) for human-readable amounts.'
9821
+ });
9822
+ }
9707
9823
  });
9708
9824
  /**
9709
9825
  * Assert that the provided value conforms to {@link CustomFeePolicy}.
@@ -12464,14 +12580,32 @@ const CUSTOM_BURN_GAS_ESTIMATE_EVM = 201_525n // p99 and max are same here: 201_
12464
12580
  ;
12465
12581
  const RECEIVE_MESSAGE_GAS_ESTIMATE_EVM = 237_401n // (99p: 163_963n + max: 310_839n) / 2 = 237_401n
12466
12582
  ;
12467
- // Hard execution caps: observed max + ~30% buffer, used as gasLimit overrides on
12468
- // chains whose eth_estimateGas under-reports (e.g. Cronos EIP-7623 calldata floor).
12469
- // Kept separate from the fee-estimate averages above.
12470
- const APPROVE_GAS_LIMIT_EVM = 100_000n // ERC-20 approve observed max ~46k
12583
+ // Gas FLOORS, not ceilings kept separate from the fee-estimate averages
12584
+ // above. `executePreparedChainRequest` submits
12585
+ // max(estimate * buffer, floor), so a chain whose real cost exceeds the floor
12586
+ // is covered by its own estimate, and a chain whose estimator under-reports
12587
+ // (Cronos: returns 30_600 where the EIP-7623 calldata floor is 45_000) is
12588
+ // covered by the floor.
12589
+ //
12590
+ // Two distinct chain surcharges drive these numbers, both measured live:
12591
+ // Sei — ~+51_500 per NEWLY CREATED storage slot (73_595 vs vanilla 22_100);
12592
+ // no flat per-tx surcharge (31_535, identical to Base).
12593
+ // Edge — ~+53_200 flat on EVERY tx (84_751 vs Base 31_535); storage priced
12594
+ // normally. Edge therefore fails warm as well as cold.
12595
+ // A floor must clear the worst COLD cost, since a slot that exists at estimate
12596
+ // time can be consumed before inclusion and cost a full step more on execution.
12597
+ // Each floor is therefore derived from the worst observed estimate *after* the
12598
+ // 1.25x buffer, plus headroom — sizing it below the buffered value would leave
12599
+ // the estimate governing and defeat the point of the floor.
12600
+ //
12601
+ // The `*_GAS_LIMIT_EVM` names are kept despite these being floors: they are
12602
+ // exported, so renaming to `*_GAS_FLOOR_EVM` would be a breaking change for
12603
+ // consumers. Read "LIMIT" here as "the limit we submit", never as a ceiling.
12604
+ const APPROVE_GAS_LIMIT_EVM = 150_000n // buffered worst cold 149_355 (Edge Testnet 119_484 x 1.25) + drift headroom
12471
12605
  ;
12472
- const DEPOSIT_FOR_BURN_GAS_LIMIT_EVM = 300_000n // observed max 226_506 + ~30%
12606
+ const DEPOSIT_FOR_BURN_GAS_LIMIT_EVM = 500_000n // buffered worst 474_078 (Sei 379_263 x 1.25) + ~26k headroom
12473
12607
  ;
12474
- const RECEIVE_MESSAGE_GAS_LIMIT_EVM = 400_000n // observed max 310_839 + ~30%
12608
+ const RECEIVE_MESSAGE_GAS_LIMIT_EVM = 400_000n // observed max 310_839; clears Cronos' calldata floor ~10x
12475
12609
  ;
12476
12610
  /**
12477
12611
  * The minimum finality threshold for CCTPv2 transfers.
@@ -13936,6 +14070,63 @@ function hasPendingState(analysis, result) {
13936
14070
  return waitForPendingTransaction(pendingStep, adapter, chain);
13937
14071
  }
13938
14072
 
14073
+ /**
14074
+ * Multiplier applied to a successful gas estimate before it is submitted.
14075
+ *
14076
+ * Estimates are exact, not padded: Sei returns 109_739 for an approve that
14077
+ * consumes 107_717 (1.9% headroom). Chains that price storage in large steps
14078
+ * can exceed the estimate if state changes between estimation and inclusion,
14079
+ * so the estimate is padded before use.
14080
+ *
14081
+ * @remarks
14082
+ * This buffer alone does NOT cover Sei's ~51_500 per-new-slot step at approve
14083
+ * scale (25% of ~110_000 is only ~27_500). For approve, the FLOOR is what
14084
+ * covers a slot that exists at estimation time and is consumed before
14085
+ * inclusion — so do not lower `APPROVE_GAS_LIMIT_EVM` on the reasoning that
14086
+ * the estimate covers it. For burn the buffer does cover a step (25% of
14087
+ * ~300_000 exceeds 51_500).
14088
+ */ const GAS_ESTIMATE_BUFFER_PERCENT = 125n;
14089
+ /**
14090
+ * Resolve the gas limit for an EVM request as `max(estimate * buffer, floor)`.
14091
+ *
14092
+ * Estimates first so chains whose real cost exceeds the floor are covered by
14093
+ * their own measurement, and falls back to the floor whenever estimation is
14094
+ * unavailable or under-reports. Estimation failure is never fatal here: before
14095
+ * floors existed these requests were submitted with a pinned limit and no
14096
+ * estimate at all, so degrading to the floor is never worse than the previous
14097
+ * behaviour.
14098
+ *
14099
+ * @param request - The prepared EVM request to size a gas limit for
14100
+ * @param gasFloor - The minimum gas limit to submit, in gas units
14101
+ * @returns The gas limit to submit, in gas units
14102
+ * @throws Never — estimation failures degrade to `gasFloor`
14103
+ *
14104
+ * @example
14105
+ * ```typescript
14106
+ * const gasLimit = await resolveGasLimit(request, 150_000)
14107
+ * ```
14108
+ */ const resolveGasLimit = async (request, gasFloor)=>{
14109
+ try {
14110
+ // Deliberately called without a `fallback`: both the viem and ethers
14111
+ // adapters *return* the supplied fallback object when estimation reverts
14112
+ // rather than throwing, which would set the estimate to the floor and then
14113
+ // multiply it by the buffer below. Omitting it routes reverts through the
14114
+ // catch, so a failed estimate degrades to exactly the floor.
14115
+ const estimate = await request.estimate();
14116
+ // The arithmetic stays inside the try on purpose. `EstimatedGas.gas` is
14117
+ // typed `bigint`, but adapters are a public extension point and may be
14118
+ // implemented in plain JS, so a non-bigint `gas` would throw here
14119
+ // ("Cannot mix BigInt and other types"). Guarding it keeps the documented
14120
+ // contract — estimation never aborts a step, it degrades to the floor.
14121
+ const buffered = estimate.gas * GAS_ESTIMATE_BUFFER_PERCENT / 100n;
14122
+ // Convert before comparing: Math.max throws on BigInt operands, and gas
14123
+ // units are far below Number.MAX_SAFE_INTEGER so the narrowing is lossless.
14124
+ return Math.max(Number(buffered), gasFloor);
14125
+ } catch {
14126
+ // Estimation is best-effort; the floor is the known-safe value.
14127
+ return gasFloor;
14128
+ }
14129
+ };
13939
14130
  /**
13940
14131
  * Executes a prepared chain request and returns the result as a bridge step.
13941
14132
  *
@@ -13949,8 +14140,8 @@ function hasPendingState(analysis, result) {
13949
14140
  * - `adapter`: The adapter that will execute the transaction
13950
14141
  * - `confirmations`: The number of confirmations to wait for (defaults to 1)
13951
14142
  * - `timeout`: The timeout for the request in milliseconds
13952
- * - `gasLimit`: Optional explicit gas limit (number) forwarded to EVM execute,
13953
- * bypassing `eth_estimateGas`; ignored for non-EVM requests
14143
+ * - `gasFloor`: Optional minimum gas limit (number); the request is submitted
14144
+ * with `max(estimate * 1.25, gasFloor)`. Ignored for non-EVM requests
13954
14145
  * @returns The bridge step with the transaction details and explorer URL
13955
14146
  * @throws If the transaction execution fails
13956
14147
  *
@@ -13965,7 +14156,7 @@ function hasPendingState(analysis, result) {
13965
14156
  * })
13966
14157
  * console.log('Transaction hash:', step.txHash)
13967
14158
  * ```
13968
- */ async function executePreparedChainRequest({ name, request, adapter, chain, confirmations = 1, timeout, gasLimit }) {
14159
+ */ async function executePreparedChainRequest({ name, request, adapter, chain, confirmations = 1, timeout, gasFloor }) {
13969
14160
  const step = {
13970
14161
  name,
13971
14162
  state: 'pending'
@@ -13978,8 +14169,8 @@ function hasPendingState(analysis, result) {
13978
14169
  step.state = 'noop';
13979
14170
  return step;
13980
14171
  }
13981
- const txHash = request.type === 'evm' && gasLimit !== undefined ? await request.execute({
13982
- gasLimit
14172
+ const txHash = request.type === 'evm' && gasFloor !== undefined ? await request.execute({
14173
+ gasLimit: await resolveGasLimit(request, gasFloor)
13983
14174
  }) : await request.execute();
13984
14175
  step.txHash = txHash;
13985
14176
  const retryOptions = {
@@ -14053,7 +14244,7 @@ function hasPendingState(analysis, result) {
14053
14244
  adapter: params.source.adapter,
14054
14245
  chain: params.source.chain,
14055
14246
  request: await provider.approve(params.source, approvalAmount),
14056
- gasLimit: Number(APPROVE_GAS_LIMIT_EVM)
14247
+ gasFloor: Number(APPROVE_GAS_LIMIT_EVM)
14057
14248
  });
14058
14249
  }
14059
14250
 
@@ -14081,7 +14272,7 @@ function hasPendingState(analysis, result) {
14081
14272
  adapter: params.source.adapter,
14082
14273
  chain: params.source.chain,
14083
14274
  request: await provider.burn(params),
14084
- gasLimit: Number(DEPOSIT_FOR_BURN_GAS_LIMIT_EVM)
14275
+ gasFloor: Number(DEPOSIT_FOR_BURN_GAS_LIMIT_EVM)
14085
14276
  });
14086
14277
  }
14087
14278
 
@@ -14175,10 +14366,9 @@ function hasPendingState(analysis, result) {
14175
14366
  request: mintRequest,
14176
14367
  // Some chains (e.g. Cronos) enforce an EIP-7623 calldata gas floor that
14177
14368
  // eth_estimateGas does not account for, returning a below-floor value
14178
- // without reverting. Pinning to a value above the observed execution max
14179
- // (310_839) bypasses re-estimation and guarantees we clear both the floor
14180
- // and the actual execution cost.
14181
- gasLimit: Number(RECEIVE_MESSAGE_GAS_LIMIT_EVM)
14369
+ // without reverting. The floor covers those; chains that cost more than the
14370
+ // floor are covered by their own estimate.
14371
+ gasFloor: Number(RECEIVE_MESSAGE_GAS_LIMIT_EVM)
14182
14372
  });
14183
14373
  // Add forwarded: false for non-relayer mints
14184
14374
  return {
@@ -14701,7 +14891,7 @@ const mockAttestationMessage = {
14701
14891
  return step;
14702
14892
  }
14703
14893
 
14704
- var version$2 = "1.10.1";
14894
+ var version$2 = "1.10.2";
14705
14895
  var pkg$2 = {
14706
14896
  version: version$2};
14707
14897
 
@@ -17299,7 +17489,9 @@ registerKit(`${pkg$3.name}/${pkg$3.version}`);
17299
17489
  headers: context.headers
17300
17490
  }
17301
17491
  });
17302
- if (hasBoth) {
17492
+ if (context.customFeePolicy?.bridge != null) {
17493
+ kit.setCustomFeePolicy(context.customFeePolicy.bridge);
17494
+ } else if (hasBoth) {
17303
17495
  kit.setCustomFeePolicy({
17304
17496
  calculateFee: async (params)=>{
17305
17497
  const feeStr = await getFee('bridge', params);
@@ -17315,7 +17507,7 @@ registerKit(`${pkg$3.name}/${pkg$3.version}`);
17315
17507
  };
17316
17508
 
17317
17509
  var name$1 = "@circle-fin/swap-kit";
17318
- var version$1 = "1.5.0";
17510
+ var version$1 = "1.5.1";
17319
17511
  var pkg$1 = {
17320
17512
  name: name$1,
17321
17513
  version: version$1};
@@ -19258,7 +19450,7 @@ new Set(Object.values(Blockchain));
19258
19450
  registerKit(`${pkg$1.name}/${pkg$1.version}`);
19259
19451
 
19260
19452
  var name = "@circle-fin/earn-kit";
19261
- var version = "1.4.0";
19453
+ var version = "1.5.0";
19262
19454
  var pkg = {
19263
19455
  name: name,
19264
19456
  version: version};
@@ -20269,11 +20461,16 @@ const sourceAdapterContextSchema = zod.z.object({
20269
20461
  *
20270
20462
  * Validate the optional Kit Key field using the standard `apiKeySchema`
20271
20463
  * format (`KIT_KEY:<keyId>:<keySecret>`). When omitted, the SDK
20272
- * operates in permissionless mode.
20464
+ * operates in permissionless mode. `baseUrl` overrides the Earn Service
20465
+ * endpoint (e.g. staging); `batchTransactions: false` opts out of atomic
20466
+ * batched execution. Both are forwarded to the provider, so this `.strict()`
20467
+ * schema must accept them or a valid config object is rejected.
20273
20468
  *
20274
20469
  * @internal
20275
20470
  */ const earnConfigSchema = zod.z.object({
20276
- kitKey: apiKeySchema.optional()
20471
+ kitKey: apiKeySchema.optional(),
20472
+ baseUrl: zod.z.string().optional(),
20473
+ batchTransactions: zod.z.boolean().optional()
20277
20474
  }).strict();
20278
20475
  /**
20279
20476
  * Canonical decimal form: a leading digit with no leading zeros (a single