@circle-fin/app-kit 1.4.1 → 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/CHANGELOG.md +10 -0
- package/README.md +3 -3
- package/chains.cjs +102 -2
- package/chains.d.ts +4 -2
- package/chains.mjs +102 -2
- package/index.cjs +301 -11
- package/index.d.ts +173 -2
- package/index.mjs +301 -11
- package/package.json +5 -5
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://
|
|
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://
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
40
|
-
"@circle-fin/provider-gateway-v1": "1.0.
|
|
41
|
-
"@circle-fin/bridge-kit": "1.
|
|
42
|
-
"@circle-fin/swap-kit": "1.1.
|
|
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",
|