@circle-fin/app-kit 1.4.0 → 1.4.2

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/index.mjs CHANGED
@@ -3412,6 +3412,8 @@ var Blockchain;
3412
3412
  Blockchain["Noble_Testnet"] = "Noble_Testnet";
3413
3413
  Blockchain["Optimism"] = "Optimism";
3414
3414
  Blockchain["Optimism_Sepolia"] = "Optimism_Sepolia";
3415
+ Blockchain["Pharos"] = "Pharos";
3416
+ Blockchain["Pharos_Testnet"] = "Pharos_Testnet";
3415
3417
  Blockchain["Polkadot_Asset_Hub"] = "Polkadot_Asset_Hub";
3416
3418
  Blockchain["Polkadot_Westmint"] = "Polkadot_Westmint";
3417
3419
  Blockchain["Plume"] = "Plume";
@@ -3620,6 +3622,7 @@ var BridgeChain;
3620
3622
  BridgeChain["Monad"] = "Monad";
3621
3623
  BridgeChain["Morph"] = "Morph";
3622
3624
  BridgeChain["Optimism"] = "Optimism";
3625
+ BridgeChain["Pharos"] = "Pharos";
3623
3626
  BridgeChain["Plume"] = "Plume";
3624
3627
  BridgeChain["Polygon"] = "Polygon";
3625
3628
  BridgeChain["Sei"] = "Sei";
@@ -3642,6 +3645,7 @@ var BridgeChain;
3642
3645
  BridgeChain["Monad_Testnet"] = "Monad_Testnet";
3643
3646
  BridgeChain["Morph_Testnet"] = "Morph_Testnet";
3644
3647
  BridgeChain["Optimism_Sepolia"] = "Optimism_Sepolia";
3648
+ BridgeChain["Pharos_Testnet"] = "Pharos_Testnet";
3645
3649
  BridgeChain["Plume_Testnet"] = "Plume_Testnet";
3646
3650
  BridgeChain["Polygon_Amoy_Testnet"] = "Polygon_Amoy_Testnet";
3647
3651
  BridgeChain["Sei_Testnet"] = "Sei_Testnet";
@@ -3987,6 +3991,12 @@ const SWAP_TOKEN_REGISTRY = {
3987
3991
  category: 'wrapped',
3988
3992
  description: 'Wrapped Polygon',
3989
3993
  },
3994
+ CIRBTC: {
3995
+ symbol: 'CIRBTC',
3996
+ decimals: 8,
3997
+ category: 'wrapped',
3998
+ description: 'Circle Bitcoin',
3999
+ },
3990
4000
  };
3991
4001
  /**
3992
4002
  * Special NATIVE token constant for swap operations.
@@ -5683,6 +5693,96 @@ const OptimismSepolia = defineChain({
5683
5693
  },
5684
5694
  });
5685
5695
 
5696
+ /**
5697
+ * Pharos Mainnet chain definition
5698
+ * @remarks
5699
+ * This represents the official production network for the Pharos blockchain.
5700
+ * Pharos is a modular, full-stack parallel Layer 1 blockchain with
5701
+ * sub-second finality and EVM compatibility.
5702
+ */
5703
+ const Pharos = defineChain({
5704
+ type: 'evm',
5705
+ chain: Blockchain.Pharos,
5706
+ name: 'Pharos',
5707
+ title: 'Pharos Mainnet',
5708
+ nativeCurrency: {
5709
+ name: 'Pharos',
5710
+ symbol: 'PHAROS',
5711
+ decimals: 18,
5712
+ },
5713
+ chainId: 1672,
5714
+ isTestnet: false,
5715
+ explorerUrl: 'https://pharos.socialscan.io/tx/{hash}',
5716
+ rpcEndpoints: ['https://rpc.pharos.xyz'],
5717
+ eurcAddress: null,
5718
+ usdcAddress: '0xC879C018dB60520F4355C26eD1a6D572cdAC1815',
5719
+ usdtAddress: null,
5720
+ cctp: {
5721
+ domain: 31,
5722
+ contracts: {
5723
+ v2: {
5724
+ type: 'split',
5725
+ tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
5726
+ messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
5727
+ confirmations: 1,
5728
+ fastConfirmations: 1,
5729
+ },
5730
+ },
5731
+ forwarderSupported: {
5732
+ source: false,
5733
+ destination: false,
5734
+ },
5735
+ },
5736
+ kitContracts: {
5737
+ bridge: BRIDGE_CONTRACT_EVM_MAINNET,
5738
+ },
5739
+ });
5740
+
5741
+ /**
5742
+ * Pharos Atlantic Testnet chain definition
5743
+ * @remarks
5744
+ * This represents the official test network for the Pharos blockchain.
5745
+ * Pharos is a modular, full-stack parallel Layer 1 blockchain with
5746
+ * sub-second finality and EVM compatibility.
5747
+ */
5748
+ const PharosTestnet = defineChain({
5749
+ type: 'evm',
5750
+ chain: Blockchain.Pharos_Testnet,
5751
+ name: 'Pharos Atlantic',
5752
+ title: 'Pharos Atlantic Testnet',
5753
+ nativeCurrency: {
5754
+ name: 'Pharos',
5755
+ symbol: 'PHAROS',
5756
+ decimals: 18,
5757
+ },
5758
+ chainId: 688689,
5759
+ isTestnet: true,
5760
+ explorerUrl: 'https://atlantic.pharosscan.xyz/tx/{hash}',
5761
+ rpcEndpoints: ['https://atlantic.dplabs-internal.com'],
5762
+ eurcAddress: null,
5763
+ usdcAddress: '0xcfC8330f4BCAB529c625D12781b1C19466A9Fc8B',
5764
+ usdtAddress: null,
5765
+ cctp: {
5766
+ domain: 31,
5767
+ contracts: {
5768
+ v2: {
5769
+ type: 'split',
5770
+ tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
5771
+ messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
5772
+ confirmations: 1,
5773
+ fastConfirmations: 1,
5774
+ },
5775
+ },
5776
+ forwarderSupported: {
5777
+ source: false,
5778
+ destination: false,
5779
+ },
5780
+ },
5781
+ kitContracts: {
5782
+ bridge: BRIDGE_CONTRACT_EVM_TESTNET,
5783
+ },
5784
+ });
5785
+
5686
5786
  /**
5687
5787
  * Plume Mainnet chain definition
5688
5788
  * @remarks
@@ -5965,7 +6065,7 @@ const Sei = defineChain({
5965
6065
  },
5966
6066
  chainId: 1329,
5967
6067
  isTestnet: false,
5968
- explorerUrl: 'https://seitrace.com/tx/{hash}?chain=pacific-1',
6068
+ explorerUrl: 'https://seiscan.io/tx/{hash}',
5969
6069
  rpcEndpoints: ['https://evm-rpc.sei-apis.com'],
5970
6070
  eurcAddress: null,
5971
6071
  usdcAddress: '0xe15fC38F6D8c56aF07bbCBe3BAf5708A2Bf42392',
@@ -6023,7 +6123,7 @@ const SeiTestnet = defineChain({
6023
6123
  },
6024
6124
  chainId: 1328,
6025
6125
  isTestnet: true,
6026
- explorerUrl: 'https://seitrace.com/tx/{hash}?chain=atlantic-2',
6126
+ explorerUrl: 'https://testnet.seiscan.io/tx/{hash}',
6027
6127
  rpcEndpoints: ['https://evm-rpc-testnet.sei-apis.com'],
6028
6128
  eurcAddress: null,
6029
6129
  usdcAddress: '0x4fCF1784B31630811181f670Aea7A7bEF803eaED',
@@ -6840,6 +6940,8 @@ var Chains = /*#__PURE__*/Object.freeze({
6840
6940
  NobleTestnet: NobleTestnet,
6841
6941
  Optimism: Optimism,
6842
6942
  OptimismSepolia: OptimismSepolia,
6943
+ Pharos: Pharos,
6944
+ PharosTestnet: PharosTestnet,
6843
6945
  Plume: Plume,
6844
6946
  PlumeTestnet: PlumeTestnet,
6845
6947
  PolkadotAssetHub: PolkadotAssetHub,
@@ -9108,6 +9210,7 @@ const USDC = {
9108
9210
  [Blockchain.NEAR]: '17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1',
9109
9211
  [Blockchain.Noble]: 'uusdc',
9110
9212
  [Blockchain.Optimism]: '0x0b2c639c533813f4aa9d7837caf62653d097ff85',
9213
+ [Blockchain.Pharos]: '0xC879C018dB60520F4355C26eD1a6D572cdAC1815',
9111
9214
  [Blockchain.Plume]: '0x222365EF19F7947e5484218551B56bb3965Aa7aF',
9112
9215
  [Blockchain.Polkadot_Asset_Hub]: '1337',
9113
9216
  [Blockchain.Polygon]: '0x3c499c542cef5e3811e1192ce70d8cc03d5c3359',
@@ -9139,6 +9242,7 @@ const USDC = {
9139
9242
  [Blockchain.NEAR_Testnet]: '3e2210e1184b45b64c8a434c0a7e7b23cc04ea7eb7a6c3c32520d03d4afcb8af',
9140
9243
  [Blockchain.Noble_Testnet]: 'uusdc',
9141
9244
  [Blockchain.Optimism_Sepolia]: '0x5fd84259d66Cd46123540766Be93DFE6D43130D7',
9245
+ [Blockchain.Pharos_Testnet]: '0xcfC8330f4BCAB529c625D12781b1C19466A9Fc8B',
9142
9246
  [Blockchain.Plume_Testnet]: '0xcB5f30e335672893c7eb944B374c196392C19D18',
9143
9247
  [Blockchain.Polkadot_Westmint]: '31337',
9144
9248
  [Blockchain.Polygon_Amoy_Testnet]: '0x41e94eb019c0762f9bfcf9fb1e58725bfb0e7582',
@@ -9419,6 +9523,32 @@ const MON = {
9419
9523
  },
9420
9524
  };
9421
9525
 
9526
+ /**
9527
+ * cirBTC (Circle Bitcoin) token definition with addresses and metadata.
9528
+ *
9529
+ * @remarks
9530
+ * Built-in cirBTC definition for the TokenRegistry. Currently deployed
9531
+ * on Arc Testnet.
9532
+ *
9533
+ * @example
9534
+ * ```typescript
9535
+ * import { CIRBTC } from '@core/tokens'
9536
+ * import { Blockchain } from '@core/chains'
9537
+ *
9538
+ * console.log(CIRBTC.symbol) // 'cirBTC'
9539
+ * console.log(CIRBTC.decimals) // 8
9540
+ * console.log(CIRBTC.locators[Blockchain.Arc_Testnet])
9541
+ * // '0xf0C4a4CE82A5746AbAAd9425360Ab04fbBA432BF'
9542
+ * ```
9543
+ */
9544
+ const CIRBTC = {
9545
+ symbol: 'cirBTC',
9546
+ decimals: 8,
9547
+ locators: {
9548
+ [Blockchain.Arc_Testnet]: '0xf0C4a4CE82A5746AbAAd9425360Ab04fbBA432BF',
9549
+ },
9550
+ };
9551
+
9422
9552
  // Re-export for consumers
9423
9553
  /**
9424
9554
  * All default token definitions.
@@ -9427,7 +9557,7 @@ const MON = {
9427
9557
  * These tokens are automatically included in the TokenRegistry when created
9428
9558
  * without explicit defaults. Extensions can override these definitions.
9429
9559
  * Includes USDC, USDT, EURC, DAI, USDE, PYUSD, WETH, WBTC, WSOL, WAVAX,
9430
- * WPOL, ETH, POL, PLUME, and MON.
9560
+ * WPOL, ETH, POL, PLUME, MON, and cirBTC.
9431
9561
  *
9432
9562
  * @example
9433
9563
  * ```typescript
@@ -9458,6 +9588,7 @@ const DEFAULT_TOKENS = [
9458
9588
  POL,
9459
9589
  PLUME,
9460
9590
  MON,
9591
+ CIRBTC,
9461
9592
  ];
9462
9593
  /**
9463
9594
  * Uppercased token symbols approved for swap fee collection.
@@ -10206,7 +10337,7 @@ async function retryAsync(fn, options) {
10206
10337
  }
10207
10338
 
10208
10339
  var name$2 = "@circle-fin/bridge-kit";
10209
- var version$3 = "1.8.3";
10340
+ var version$3 = "1.9.0";
10210
10341
  var pkg$3 = {
10211
10342
  name: name$2,
10212
10343
  version: version$3};
@@ -14337,11 +14468,18 @@ async function executePreparedChainRequest({ name, request, adapter, chain, conf
14337
14468
  step.explorerUrl = buildExplorerUrl(chain, txHash);
14338
14469
  if (outcome.errorMessage) {
14339
14470
  step.errorMessage = outcome.errorMessage;
14471
+ // Transaction was mined but reverted on-chain.
14472
+ step.errorCategory = 'chain_revert';
14340
14473
  }
14341
14474
  }
14342
14475
  catch (err) {
14343
14476
  step.state = 'error';
14344
14477
  step.error = err;
14478
+ // Sequential path does not yet attempt fine-grained classification of
14479
+ // pre-submission errors (user_rejected, capability errors, etc.). Mark
14480
+ // as `unknown` so consumers can at least detect the category is
14481
+ // populated uniformly across batched and sequential flows.
14482
+ step.errorCategory = 'unknown';
14345
14483
  // Optionally parse for common blockchain error formats
14346
14484
  if (err instanceof Error) {
14347
14485
  step.errorMessage = err.message;
@@ -15007,16 +15145,70 @@ async function executeBatchedApproveAndBurn(params, provider) {
15007
15145
  const batchResult = await adapter.batchExecute([approveCallData, burnCallData], chain);
15008
15146
  const approveReceipt = batchResult.receipts[0];
15009
15147
  const burnReceipt = batchResult.receipts[1];
15010
- const approveStep = await buildBatchedStep('approve', approveReceipt, batchResult.batchId, adapter, chain);
15011
- const burnStep = await buildBatchedStep('burn', burnReceipt, batchResult.batchId, adapter, chain);
15148
+ const approveStep = await buildBatchedStep('approve', approveReceipt, batchResult.batchId, adapter, chain, batchResult.statusCode, batchResult.error);
15149
+ const burnStep = await buildBatchedStep('burn', burnReceipt, batchResult.batchId, adapter, chain, batchResult.statusCode, batchResult.error);
15012
15150
  if (burnStep.state !== 'error' && !burnStep.txHash) {
15013
15151
  burnStep.state = 'error';
15014
15152
  burnStep.errorMessage =
15015
15153
  'Batched burn step completed but no transaction hash was returned.';
15154
+ burnStep.errorCategory = 'unknown';
15016
15155
  }
15017
15156
  const context = { burnTxHash: burnStep.txHash ?? '' };
15018
15157
  return { approveStep, burnStep, context };
15019
15158
  }
15159
+ /**
15160
+ * Derive a {@link BridgeStepErrorCategory} for a missing receipt.
15161
+ *
15162
+ * Combines the EIP-5792 `statusCode` (when present) with the underlying
15163
+ * polling error (when set) to produce the most specific category available.
15164
+ * Falls back to `'unknown'` when neither signal is conclusive.
15165
+ *
15166
+ * @param statusCode - The terminal `statusCode` from `wallet_getCallsStatus`, if any.
15167
+ * @param batchError - The polling error from `batchExecute`, if any.
15168
+ * @returns The derived error category for a missing-receipt step.
15169
+ *
15170
+ * @internal
15171
+ */
15172
+ function categorizeMissingReceipt(statusCode, batchError) {
15173
+ if (statusCode === 400)
15174
+ return 'failed_offchain';
15175
+ if (statusCode === 500)
15176
+ return 'reverted_onchain';
15177
+ if (statusCode === 600)
15178
+ return 'partial_reverted';
15179
+ if (batchError instanceof KitError &&
15180
+ batchError.code === NetworkError.TIMEOUT.code) {
15181
+ return 'polling_timeout';
15182
+ }
15183
+ return 'unknown';
15184
+ }
15185
+ /**
15186
+ * Derive a {@link BridgeStepErrorCategory} for a receipt that was returned
15187
+ * but whose per-call `status` is not `'success'`.
15188
+ *
15189
+ * A numeric EIP-5792 `statusCode` of 500 or 600 tells us the whole batch
15190
+ * reverted on-chain (completely or partially); otherwise the receipt
15191
+ * itself signalled a revert without a distinguishing code, so classify
15192
+ * as a plain on-chain revert.
15193
+ *
15194
+ * @param statusCode - The terminal `statusCode` from `wallet_getCallsStatus`, if any.
15195
+ * @returns The derived error category for a failed-receipt step.
15196
+ *
15197
+ * @internal
15198
+ */
15199
+ function categorizeFailedReceipt(statusCode) {
15200
+ // Mirror categorizeMissingReceipt: if the wallet's terminal status is
15201
+ // 400 ("batch not included onchain"), that judgement is authoritative
15202
+ // even when a non-success receipt is attached. Without this, a wrapped
15203
+ // 400 receipt would fall through to `chain_revert` and mislead UX.
15204
+ if (statusCode === 400)
15205
+ return 'failed_offchain';
15206
+ if (statusCode === 600)
15207
+ return 'partial_reverted';
15208
+ if (statusCode === 500)
15209
+ return 'reverted_onchain';
15210
+ return 'chain_revert';
15211
+ }
15020
15212
  /**
15021
15213
  * Build a {@link BridgeStep} from a single receipt within a batch.
15022
15214
  *
@@ -15031,11 +15223,17 @@ async function executeBatchedApproveAndBurn(params, provider) {
15031
15223
  * @param batchId - Wallet-assigned batch identifier.
15032
15224
  * @param adapter - The batch-capable adapter (used for confirmation).
15033
15225
  * @param chain - The EVM chain the batch was executed on.
15226
+ * @param statusCode - Optional EIP-5792 `statusCode` for the batch.
15227
+ * Used to classify the step's error category when the receipt is
15228
+ * missing or failed.
15229
+ * @param batchError - Optional polling error from `batchExecute`.
15230
+ * Preserved on the step so callers can inspect underlying timeouts
15231
+ * or RPC failures.
15034
15232
  * @returns A fully-populated bridge step with state, tx hash and explorer URL.
15035
15233
  *
15036
15234
  * @internal
15037
15235
  */
15038
- async function buildBatchedStep(name, receipt, batchId, adapter, chain) {
15236
+ async function buildBatchedStep(name, receipt, batchId, adapter, chain, statusCode, batchError) {
15039
15237
  const step = {
15040
15238
  name,
15041
15239
  state: 'pending',
@@ -15045,6 +15243,10 @@ async function buildBatchedStep(name, receipt, batchId, adapter, chain) {
15045
15243
  if (!receipt) {
15046
15244
  step.state = 'error';
15047
15245
  step.errorMessage = `No receipt returned for ${name} in batch ${batchId}.`;
15246
+ step.errorCategory = categorizeMissingReceipt(statusCode, batchError);
15247
+ if (batchError !== undefined) {
15248
+ step.error = batchError;
15249
+ }
15048
15250
  return step;
15049
15251
  }
15050
15252
  step.txHash = receipt.txHash;
@@ -15054,11 +15256,13 @@ async function buildBatchedStep(name, receipt, batchId, adapter, chain) {
15054
15256
  if (receipt.status !== 'success') {
15055
15257
  step.state = 'error';
15056
15258
  step.errorMessage = `${name} call failed within batch ${batchId}.`;
15259
+ step.errorCategory = categorizeFailedReceipt(statusCode);
15057
15260
  return step;
15058
15261
  }
15059
15262
  if (!receipt.txHash) {
15060
15263
  step.state = 'error';
15061
15264
  step.errorMessage = `${name} succeeded in batch but returned an empty transaction hash.`;
15265
+ step.errorCategory = 'unknown';
15062
15266
  return step;
15063
15267
  }
15064
15268
  try {
@@ -15073,6 +15277,7 @@ async function buildBatchedStep(name, receipt, batchId, adapter, chain) {
15073
15277
  step.data = transaction;
15074
15278
  if (outcome.errorMessage) {
15075
15279
  step.errorMessage = outcome.errorMessage;
15280
+ step.errorCategory = 'chain_revert';
15076
15281
  }
15077
15282
  }
15078
15283
  catch (err) {
@@ -15080,11 +15285,12 @@ async function buildBatchedStep(name, receipt, batchId, adapter, chain) {
15080
15285
  step.error = err;
15081
15286
  step.errorMessage =
15082
15287
  err instanceof Error ? err.message : 'Unknown error during confirmation.';
15288
+ step.errorCategory = 'unknown';
15083
15289
  }
15084
15290
  return step;
15085
15291
  }
15086
15292
 
15087
- var version$2 = "1.6.3";
15293
+ var version$2 = "1.7.0";
15088
15294
  var pkg$2 = {
15089
15295
  version: version$2};
15090
15296
 
@@ -15160,6 +15366,7 @@ async function executeBatchedPath(params, provider, result, invocation) {
15160
15366
  errorMessage: error_ instanceof Error
15161
15367
  ? error_.message
15162
15368
  : 'Batched approve + burn failed.',
15369
+ errorCategory: classifyPreSubmissionError(error_),
15163
15370
  });
15164
15371
  return undefined;
15165
15372
  }
@@ -15174,6 +15381,89 @@ function ensureStepErrorMessage(name, step) {
15174
15381
  step.errorMessage = `${name} step failed: ${getErrorMessage(step.error)}`;
15175
15382
  }
15176
15383
  }
15384
+ /**
15385
+ * Coerce a raw JSON-RPC `code` to a number.
15386
+ *
15387
+ * Some wallet SDKs serialize the JSON-RPC `code` as a string ("4001")
15388
+ * after round-tripping through JSON; accept both shapes so strict `===`
15389
+ * comparisons downstream still classify 5720/5730/5740 correctly — those
15390
+ * codes have no message-pattern fallback.
15391
+ *
15392
+ * @param rawCode - The raw `code` extracted from the error object.
15393
+ * @returns The numeric code, or `undefined` if the value cannot be parsed.
15394
+ *
15395
+ * @internal
15396
+ */
15397
+ function coerceRpcCode(rawCode) {
15398
+ if (typeof rawCode === 'number') {
15399
+ return rawCode;
15400
+ }
15401
+ if (typeof rawCode === 'string') {
15402
+ return Number.parseInt(rawCode, 10);
15403
+ }
15404
+ return undefined;
15405
+ }
15406
+ /**
15407
+ * Classify a pre-submission error thrown during `wallet_sendCalls`.
15408
+ *
15409
+ * Inspect the error's JSON-RPC `code` (falling back to message pattern
15410
+ * matching for wrapper errors like viem's `ChainMismatchError`) and map
15411
+ * it to a {@link BridgeStepErrorCategory}. This lets downstream consumers
15412
+ * distinguish user rejections, wallet capability gaps, and unknown
15413
+ * failures without parsing error messages.
15414
+ *
15415
+ * @remarks
15416
+ * Does NOT alter control flow — the SDK continues to surface a
15417
+ * `state: 'error'` step. Auto-fallback to sequential execution is
15418
+ * intentionally out of scope for this helper.
15419
+ *
15420
+ * @param err - The error thrown by `wallet_sendCalls`.
15421
+ * @returns The derived error category, or `'unknown'` if no match.
15422
+ *
15423
+ * @internal
15424
+ */
15425
+ function classifyPreSubmissionError(err) {
15426
+ // Cross-realm-safe duck typing: `instanceof Error` returns false for
15427
+ // errors thrown in a different JavaScript realm (e.g., a wallet
15428
+ // provider running inside an iframe, which is common with WalletConnect
15429
+ // and the Coinbase Wallet SDK).
15430
+ if (typeof err !== 'object' || err === null || !('message' in err)) {
15431
+ return 'unknown';
15432
+ }
15433
+ const code = coerceRpcCode(err.code);
15434
+ const message = String(err.message);
15435
+ // Numeric JSON-RPC codes are authoritative; check them before falling
15436
+ // back to message-pattern matching. Order matters: an error carrying
15437
+ // `code === 5750` with a message like "user rejected the upgrade"
15438
+ // is a capability problem, not a plain user rejection.
15439
+ if (code === 4001) {
15440
+ return 'user_rejected';
15441
+ }
15442
+ if (code === 5700 || code === 5710 || code === 5750) {
15443
+ return 'atomic_unsupported';
15444
+ }
15445
+ if (code === 5720) {
15446
+ return 'duplicate_batch_id';
15447
+ }
15448
+ if (code === 5730) {
15449
+ return 'unknown_bundle';
15450
+ }
15451
+ if (code === 5740) {
15452
+ return 'batch_too_large';
15453
+ }
15454
+ // Fall back to message patterns when no specific code is available —
15455
+ // viem (and other wrapper layers) sometimes strip the numeric code
15456
+ // while preserving the original wallet message in `Details:`.
15457
+ if (/EIP-7702 not supported/i.test(message) ||
15458
+ /does not support the requested chain/i.test(message) ||
15459
+ /rejected the upgrade/i.test(message)) {
15460
+ return 'atomic_unsupported';
15461
+ }
15462
+ if (/user rejected/i.test(message)) {
15463
+ return 'user_rejected';
15464
+ }
15465
+ return 'unknown';
15466
+ }
15177
15467
  /**
15178
15468
  * Execute a cross-chain USDC bridge using the CCTP v2 protocol.
15179
15469
  *
@@ -17317,7 +17607,7 @@ const createBridgeKit = (context) => {
17317
17607
  };
17318
17608
 
17319
17609
  var name$1 = "@circle-fin/swap-kit";
17320
- var version$1 = "1.1.0";
17610
+ var version$1 = "1.1.1";
17321
17611
  var pkg$1 = {
17322
17612
  name: name$1,
17323
17613
  version: version$1};
@@ -28691,7 +28981,7 @@ const prepareSend = async (params) => {
28691
28981
  const fromContext = params.from;
28692
28982
  const fromAdapter = fromContext.adapter;
28693
28983
  const fromChain = resolveChainIdentifier(fromContext.chain);
28694
- const fromAddress = await fromAdapter.getAddress(fromChain);
28984
+ const fromAddress = fromContext.address ?? (await fromAdapter.getAddress(fromChain));
28695
28985
  // resolve input parameters
28696
28986
  const token = params.token ?? 'USDC';
28697
28987
  // Validate token and determine if it's an alias or custom address
@@ -29136,7 +29426,7 @@ const getSupportedChains$2 = (context, operationType, unifiedBalance) => {
29136
29426
  };
29137
29427
 
29138
29428
  var name = "@circle-fin/unified-balance-kit";
29139
- var version = "1.0.0";
29429
+ var version = "1.0.2";
29140
29430
  var pkg = {
29141
29431
  name: name,
29142
29432
  version: version};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@circle-fin/app-kit",
3
- "version": "1.4.0",
3
+ "version": "1.4.2",
4
4
  "description": "A one-stop Circle SDK solution for building stablecoin (e.g. USDC) applications, with bridging, swapping, and more on-chain operations",
5
5
  "keywords": [
6
6
  "circle",
@@ -36,10 +36,10 @@
36
36
  "module": "./index.mjs",
37
37
  "types": "./index.d.ts",
38
38
  "dependencies": {
39
- "@circle-fin/unified-balance-kit": "1.0.0",
40
- "@circle-fin/provider-gateway-v1": "1.0.0",
41
- "@circle-fin/bridge-kit": "1.8.3",
42
- "@circle-fin/swap-kit": "1.1.0",
39
+ "@circle-fin/unified-balance-kit": "1.0.2",
40
+ "@circle-fin/provider-gateway-v1": "1.0.2",
41
+ "@circle-fin/bridge-kit": "1.9.0",
42
+ "@circle-fin/swap-kit": "1.1.1",
43
43
  "zod": "3.25.67",
44
44
  "@ethersproject/address": "^5.8.0",
45
45
  "@ethersproject/bytes": "^5.8.0",