@circle-fin/app-kit 1.13.0 → 1.15.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.
Files changed (53) hide show
  1. package/CHANGELOG.md +122 -0
  2. package/README.md +3 -3
  3. package/bridge.cjs +8388 -515
  4. package/bridge.d.cts +640 -61
  5. package/bridge.d.mts +640 -61
  6. package/bridge.d.ts +640 -61
  7. package/bridge.mjs +8389 -516
  8. package/chains.cjs +275 -15
  9. package/chains.d.cts +117 -2
  10. package/chains.d.mts +117 -2
  11. package/chains.d.ts +117 -2
  12. package/chains.mjs +275 -16
  13. package/context.d.cts +577 -57
  14. package/context.d.mts +577 -57
  15. package/context.d.ts +577 -57
  16. package/earn.cjs +973 -271
  17. package/earn.d.cts +577 -57
  18. package/earn.d.mts +577 -57
  19. package/earn.d.ts +577 -57
  20. package/earn.mjs +919 -221
  21. package/estimateBridge.cjs +8388 -518
  22. package/estimateBridge.d.cts +704 -82
  23. package/estimateBridge.d.mts +704 -82
  24. package/estimateBridge.d.ts +704 -82
  25. package/estimateBridge.mjs +8390 -520
  26. package/estimateSwap.cjs +982 -237
  27. package/estimateSwap.d.cts +577 -57
  28. package/estimateSwap.d.mts +577 -57
  29. package/estimateSwap.d.ts +577 -57
  30. package/estimateSwap.mjs +981 -237
  31. package/index.cjs +21401 -8522
  32. package/index.d.cts +6045 -2149
  33. package/index.d.mts +6045 -2149
  34. package/index.d.ts +6045 -2149
  35. package/index.mjs +21401 -8524
  36. package/package.json +17 -6
  37. package/server.cjs +10040 -0
  38. package/server.cjs.map +1 -0
  39. package/server.d.cts +2467 -0
  40. package/server.d.mts +2467 -0
  41. package/server.d.ts +2467 -0
  42. package/server.mjs +10028 -0
  43. package/server.mjs.map +1 -0
  44. package/swap.cjs +982 -237
  45. package/swap.d.cts +577 -57
  46. package/swap.d.mts +577 -57
  47. package/swap.d.ts +577 -57
  48. package/swap.mjs +981 -237
  49. package/unifiedBalance.cjs +20510 -7599
  50. package/unifiedBalance.d.cts +807 -201
  51. package/unifiedBalance.d.mts +807 -201
  52. package/unifiedBalance.d.ts +807 -201
  53. package/unifiedBalance.mjs +20513 -7603
package/earn.mjs CHANGED
@@ -28,7 +28,7 @@ if (typeof window !== 'undefined' && typeof window.Buffer === 'undefined') {
28
28
 
29
29
 
30
30
  import { z } from 'zod';
31
- import 'pino';
31
+ import pino from 'pino';
32
32
  import '@ethersproject/bytes';
33
33
  import '@ethersproject/abi';
34
34
  import '@ethersproject/address';
@@ -859,8 +859,7 @@ class KitError extends Error {
859
859
  code: 8002,
860
860
  name: 'SERVICE_UNKNOWN_ERROR',
861
861
  type: 'SERVICE'
862
- }
863
- };
862
+ }};
864
863
 
865
864
  /**
866
865
  * Creates error for network type mismatch between source and destination.
@@ -1047,7 +1046,7 @@ class KitError extends Error {
1047
1046
  * import { createValidationErrorFromZod } from '@core/errors'
1048
1047
  *
1049
1048
  * function validateBridgeParams(params: unknown): asserts params is BridgeParams {
1050
- * const result = bridgeParamsSchema.safeParse(params)
1049
+ * const result = usdcBridgeParamsSchema.safeParse(params)
1051
1050
  * if (!result.success) {
1052
1051
  * throw createValidationErrorFromZod(result.error, 'bridge parameters')
1053
1052
  * }
@@ -2308,9 +2307,10 @@ function getOptionalString(value) {
2308
2307
  Blockchain["Algorand_Testnet"] = "Algorand_Testnet";
2309
2308
  Blockchain["Aptos"] = "Aptos";
2310
2309
  Blockchain["Aptos_Testnet"] = "Aptos_Testnet";
2311
- Blockchain["Arc_Testnet"] = "Arc_Testnet";
2312
2310
  Blockchain["Arbitrum"] = "Arbitrum";
2313
2311
  Blockchain["Arbitrum_Sepolia"] = "Arbitrum_Sepolia";
2312
+ Blockchain["Arc"] = "Arc";
2313
+ Blockchain["Arc_Testnet"] = "Arc_Testnet";
2314
2314
  Blockchain["Avalanche"] = "Avalanche";
2315
2315
  Blockchain["Avalanche_Fuji"] = "Avalanche_Fuji";
2316
2316
  Blockchain["Base"] = "Base";
@@ -2397,6 +2397,7 @@ var SwapChain;
2397
2397
  SwapChain["XDC"] = "XDC";
2398
2398
  SwapChain["HyperEVM"] = "HyperEVM";
2399
2399
  SwapChain["Monad"] = "Monad";
2400
+ SwapChain["Arc"] = "Arc";
2400
2401
  // Testnet chains with swap support
2401
2402
  SwapChain["Arc_Testnet"] = "Arc_Testnet";
2402
2403
  })(SwapChain || (SwapChain = {}));
@@ -2404,6 +2405,7 @@ var BridgeChain;
2404
2405
  (function(BridgeChain) {
2405
2406
  // Mainnet chains with CCTPv2 support
2406
2407
  BridgeChain["Arbitrum"] = "Arbitrum";
2408
+ BridgeChain["Arc"] = "Arc";
2407
2409
  BridgeChain["Avalanche"] = "Avalanche";
2408
2410
  BridgeChain["Base"] = "Base";
2409
2411
  BridgeChain["Codex"] = "Codex";
@@ -2459,6 +2461,7 @@ var BridgeChain;
2459
2461
  var UnifiedBalanceChain;
2460
2462
  (function(UnifiedBalanceChain) {
2461
2463
  // Mainnet chains with Gateway V1 support
2464
+ UnifiedBalanceChain["Arc"] = "Arc";
2462
2465
  UnifiedBalanceChain["Arbitrum"] = "Arbitrum";
2463
2466
  UnifiedBalanceChain["Avalanche"] = "Avalanche";
2464
2467
  UnifiedBalanceChain["Base"] = "Base";
@@ -2488,6 +2491,7 @@ var UnifiedBalanceChain;
2488
2491
  })(UnifiedBalanceChain || (UnifiedBalanceChain = {}));
2489
2492
  var EarnChain;
2490
2493
  (function(EarnChain) {
2494
+ EarnChain["Arc"] = "Arc";
2491
2495
  EarnChain["Arc_Testnet"] = "Arc_Testnet";
2492
2496
  })(EarnChain || (EarnChain = {}));
2493
2497
  /**
@@ -2504,8 +2508,11 @@ var EarnChain;
2504
2508
  * console.log(EARN_BRIDGE_SOURCE_BLOCKCHAINS.join(', '))
2505
2509
  * ```
2506
2510
  */ const EARN_BRIDGE_SOURCE_BLOCKCHAINS = [
2511
+ "Arbitrum",
2507
2512
  "Arbitrum_Sepolia",
2513
+ "Base",
2508
2514
  "Base_Sepolia",
2515
+ "Ethereum",
2509
2516
  "Ethereum_Sepolia"
2510
2517
  ];
2511
2518
  /**
@@ -2519,6 +2526,7 @@ var EarnChain;
2519
2526
  * console.log(EARN_BRIDGE_DESTINATION_BLOCKCHAINS.join(', '))
2520
2527
  * ```
2521
2528
  */ const EARN_BRIDGE_DESTINATION_BLOCKCHAINS = [
2529
+ "Arc",
2522
2530
  "Arc_Testnet"
2523
2531
  ];
2524
2532
 
@@ -2824,6 +2832,25 @@ var EarnChain;
2824
2832
  * EVM-compatible chains. Use this address when deploying or testing
2825
2833
  * cross-chain USDC transfers on test networks.
2826
2834
  */ const BRIDGE_CONTRACT_EVM_TESTNET = '0xC5567a5E3370d4DBfB0540025078e283e36A363d';
2835
+ /**
2836
+ * The CrossChainTokenService (CCTPx) service address for EVM testnet networks.
2837
+ *
2838
+ * This service coordinates CCTPx cross-chain token operations on testnet
2839
+ * environments and is shared by every EVM test network CCTPx supports. Read the
2840
+ * chain definitions via `isCCTPXSupported` rather than trusting a list here,
2841
+ * which goes stale as deployments land.
2842
+ */ const CCTPX_SERVICE_ADDRESS_EVM_TESTNET = '0x63753E722bd2C2A5DF6EE19C5106662208B81077';
2843
+ /**
2844
+ * CrossChainTokenService (CCTS) proxy address for CCTPx on EVM **mainnet**.
2845
+ *
2846
+ * @remarks
2847
+ * A distinct deployment from {@link CCTPX_SERVICE_ADDRESS_EVM_TESTNET}, shared
2848
+ * by every EVM mainnet chain that CCTPx supports. A chain becomes
2849
+ * CCTPx-eligible only once its definition carries this as
2850
+ * `cctpx.serviceAddress`, and a route additionally needs both of its endpoints
2851
+ * eligible — so adding a chain here is the deliberate, reviewable step that
2852
+ * opens mainnet CCTPx for it.
2853
+ */ const CCTPX_SERVICE_ADDRESS_EVM_MAINNET = '0x431871229103b780868f8C6BB820cd16ECf942BC';
2827
2854
  /**
2828
2855
  * The bridge contract address for EVM mainnet networks.
2829
2856
  *
@@ -2892,8 +2919,115 @@ var EarnChain;
2892
2919
  * This program handles minting operations for Gateway transactions
2893
2920
  * on Solana devnet.
2894
2921
  */ const GATEWAY_MINTER_SOLANA_DEVNET = 'GATEmKK2ECL1brEngQZWCgMWPbvrEYqsV6u29dAaHavr';
2895
- /** TokenMessengerWithFees address shared by enabled EVM mainnet sources. */ const TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET = '0x71f54F818671cD0D7ea140Da213e5C8b5C92a408';
2896
- /** TokenMessengerWithFees address shared by enabled EVM testnet sources. */ const TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET = '0x8745D906D67C346E5eb1aEEED38Eb87F34DF0C0A';
2922
+ /**
2923
+ * The `TokenMessengerWithFees` proxy contract address for EVM mainnet networks
2924
+ * (all chains except Edge).
2925
+ *
2926
+ * Deployed at a CREATE3-derived address; identical across all mainnet EVM
2927
+ * source chains. Present on any chain that supports the prepaid FORWARD path
2928
+ * via `depositForBurnWithHookAndFees`.
2929
+ */ const TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET = '0x71f54F818671cD0D7ea140Da213e5C8b5C92a408';
2930
+ /**
2931
+ * The `TokenMessengerWithFees` proxy contract address for EVM testnet networks.
2932
+ *
2933
+ * Identical across all testnet EVM source chains. Present on any testnet chain
2934
+ * that supports the prepaid FORWARD path via `depositForBurnWithHookAndFees`.
2935
+ */ const TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET = '0x8745D906D67C346E5eb1aEEED38Eb87F34DF0C0A';
2936
+ /**
2937
+ * The `DepositForHandler` proxy contract address for EVM mainnet networks.
2938
+ *
2939
+ * The handler the GenericExecutor calls on a fast-deposit destination chain to
2940
+ * run a cross-chain deposit into the GatewayWallet. Deployed at the same
2941
+ * address across all mainnet EVM destination chains.
2942
+ */ const DEPOSIT_FOR_HANDLER_EVM_MAINNET = '0x16529813203f77E036576666336554a1210dce4D';
2943
+ /**
2944
+ * The `DepositForHandler` proxy contract address for EVM testnet networks.
2945
+ *
2946
+ * Identical across all testnet EVM destination chains.
2947
+ */ const DEPOSIT_FOR_HANDLER_EVM_TESTNET = '0xD05E7D2E7d30b92c5F17d7d0fC575fce231F1A48';
2948
+ /**
2949
+ * The `GenericExecutor` proxy contract address for EVM mainnet networks.
2950
+ *
2951
+ * The GenericExecutor is the `mintRecipient` and `destinationCaller` on the
2952
+ * destination chain for the CCTP v2 prepaid FORWARD path. It receives the CCTP
2953
+ * mint and calls the `DepositForHandler` to complete the fast deposit.
2954
+ * Deployed at the same address across all mainnet EVM destination chains.
2955
+ */ const GENERIC_EXECUTOR_EVM_MAINNET = '0xFa7be2f04F3Ad4ca969260729c6d45B5625984A7';
2956
+ /**
2957
+ * The `GenericExecutor` proxy contract address for EVM testnet networks.
2958
+ *
2959
+ * Identical across all testnet EVM destination chains.
2960
+ */ const GENERIC_EXECUTOR_EVM_TESTNET = '0xEdC81040756AcCfF070c21D37b265b9D0b5Ba45e';
2961
+
2962
+ /**
2963
+ * Arc Mainnet chain definition
2964
+ * @remarks
2965
+ * This represents the official production network for the Arc blockchain,
2966
+ * Circle's EVM-compatible Layer-1 designed for stablecoin finance
2967
+ * and asset tokenization. Arc uses USDC as the native gas token and
2968
+ * features the Malachite Byzantine Fault Tolerant (BFT) consensus
2969
+ * engine for sub-second finality.
2970
+ */ const Arc = defineChain({
2971
+ type: 'evm',
2972
+ chain: Blockchain.Arc,
2973
+ name: 'Arc',
2974
+ title: 'Arc Mainnet',
2975
+ nativeCurrency: {
2976
+ name: 'USDC',
2977
+ symbol: 'USDC',
2978
+ // Arc uses native USDC with 18 decimals for gas payments (EVM standard).
2979
+ // Note: The ERC-20 USDC contract at usdcAddress uses 6 decimals.
2980
+ // See: https://docs.arc.network/arc/references/contract-addresses
2981
+ decimals: 18
2982
+ },
2983
+ chainId: 5042,
2984
+ isTestnet: false,
2985
+ explorerUrl: 'https://explorer.arc.io/tx/{hash}',
2986
+ rpcEndpoints: [
2987
+ 'https://rpc.mainnet.arc.io/'
2988
+ ],
2989
+ eurcAddress: '0xbEf5f6d51CB62b58e6A8f77868681825C6fe21c1',
2990
+ usdcAddress: '0x3600000000000000000000000000000000000000',
2991
+ usdtAddress: null,
2992
+ cctp: {
2993
+ domain: 26,
2994
+ contracts: {
2995
+ v2: {
2996
+ type: 'split',
2997
+ tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
2998
+ messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
2999
+ confirmations: 1,
3000
+ fastConfirmations: 1
3001
+ }
3002
+ },
3003
+ forwarderSupported: {
3004
+ source: false,
3005
+ destination: true
3006
+ }
3007
+ },
3008
+ cctpx: {
3009
+ serviceAddress: CCTPX_SERVICE_ADDRESS_EVM_MAINNET
3010
+ },
3011
+ kitContracts: {
3012
+ bridge: BRIDGE_CONTRACT_EVM_MAINNET,
3013
+ adapter: ADAPTER_CONTRACT_EVM_MAINNET
3014
+ },
3015
+ gateway: {
3016
+ domain: 26,
3017
+ contracts: {
3018
+ v1: {
3019
+ wallet: GATEWAY_WALLET_EVM_MAINNET,
3020
+ minter: GATEWAY_MINTER_EVM_MAINNET,
3021
+ depositForHandler: DEPOSIT_FOR_HANDLER_EVM_MAINNET,
3022
+ genericExecutor: GENERIC_EXECUTOR_EVM_MAINNET
3023
+ }
3024
+ },
3025
+ forwarderSupported: {
3026
+ source: true,
3027
+ destination: true
3028
+ }
3029
+ }
3030
+ });
2897
3031
 
2898
3032
  /**
2899
3033
  * Arc Testnet chain definition
@@ -2942,6 +3076,9 @@ var EarnChain;
2942
3076
  destination: true
2943
3077
  }
2944
3078
  },
3079
+ cctpx: {
3080
+ serviceAddress: CCTPX_SERVICE_ADDRESS_EVM_TESTNET
3081
+ },
2945
3082
  kitContracts: {
2946
3083
  bridge: BRIDGE_CONTRACT_EVM_TESTNET,
2947
3084
  adapter: ADAPTER_CONTRACT_EVM_TESTNET
@@ -2952,9 +3089,8 @@ var EarnChain;
2952
3089
  v1: {
2953
3090
  wallet: GATEWAY_WALLET_EVM_TESTNET,
2954
3091
  minter: GATEWAY_MINTER_EVM_TESTNET,
2955
- // DepositForHandler the GenericExecutor calls to run a fast cross-chain
2956
- // deposit into the GatewayWallet above.
2957
- depositForHandler: '0xD05E7D2E7d30b92c5F17d7d0fC575fce231F1A48'
3092
+ depositForHandler: DEPOSIT_FOR_HANDLER_EVM_TESTNET,
3093
+ genericExecutor: GENERIC_EXECUTOR_EVM_TESTNET
2958
3094
  }
2959
3095
  },
2960
3096
  forwarderSupported: {
@@ -3010,6 +3146,9 @@ var EarnChain;
3010
3146
  destination: true
3011
3147
  }
3012
3148
  },
3149
+ cctpx: {
3150
+ serviceAddress: CCTPX_SERVICE_ADDRESS_EVM_MAINNET
3151
+ },
3013
3152
  kitContracts: {
3014
3153
  bridge: BRIDGE_CONTRACT_EVM_MAINNET,
3015
3154
  adapter: ADAPTER_CONTRACT_EVM_MAINNET
@@ -3075,6 +3214,9 @@ var EarnChain;
3075
3214
  destination: true
3076
3215
  }
3077
3216
  },
3217
+ cctpx: {
3218
+ serviceAddress: CCTPX_SERVICE_ADDRESS_EVM_TESTNET
3219
+ },
3078
3220
  kitContracts: {
3079
3221
  bridge: BRIDGE_CONTRACT_EVM_TESTNET,
3080
3222
  adapter: ADAPTER_CONTRACT_EVM_TESTNET
@@ -3140,6 +3282,9 @@ var EarnChain;
3140
3282
  destination: true
3141
3283
  }
3142
3284
  },
3285
+ cctpx: {
3286
+ serviceAddress: CCTPX_SERVICE_ADDRESS_EVM_MAINNET
3287
+ },
3143
3288
  kitContracts: {
3144
3289
  bridge: BRIDGE_CONTRACT_EVM_MAINNET,
3145
3290
  adapter: ADAPTER_CONTRACT_EVM_MAINNET
@@ -3149,7 +3294,9 @@ var EarnChain;
3149
3294
  contracts: {
3150
3295
  v1: {
3151
3296
  wallet: GATEWAY_WALLET_EVM_MAINNET,
3152
- minter: GATEWAY_MINTER_EVM_MAINNET
3297
+ minter: GATEWAY_MINTER_EVM_MAINNET,
3298
+ depositForHandler: DEPOSIT_FOR_HANDLER_EVM_MAINNET,
3299
+ genericExecutor: GENERIC_EXECUTOR_EVM_MAINNET
3153
3300
  }
3154
3301
  },
3155
3302
  forwarderSupported: {
@@ -3205,6 +3352,9 @@ var EarnChain;
3205
3352
  rpcEndpoints: [
3206
3353
  'https://api.avax-test.network/ext/bc/C/rpc'
3207
3354
  ],
3355
+ cctpx: {
3356
+ serviceAddress: CCTPX_SERVICE_ADDRESS_EVM_TESTNET
3357
+ },
3208
3358
  kitContracts: {
3209
3359
  bridge: BRIDGE_CONTRACT_EVM_TESTNET
3210
3360
  },
@@ -3213,7 +3363,9 @@ var EarnChain;
3213
3363
  contracts: {
3214
3364
  v1: {
3215
3365
  wallet: GATEWAY_WALLET_EVM_TESTNET,
3216
- minter: GATEWAY_MINTER_EVM_TESTNET
3366
+ minter: GATEWAY_MINTER_EVM_TESTNET,
3367
+ depositForHandler: DEPOSIT_FOR_HANDLER_EVM_TESTNET,
3368
+ genericExecutor: GENERIC_EXECUTOR_EVM_TESTNET
3217
3369
  }
3218
3370
  },
3219
3371
  forwarderSupported: {
@@ -3270,6 +3422,9 @@ var EarnChain;
3270
3422
  destination: true
3271
3423
  }
3272
3424
  },
3425
+ cctpx: {
3426
+ serviceAddress: CCTPX_SERVICE_ADDRESS_EVM_MAINNET
3427
+ },
3273
3428
  kitContracts: {
3274
3429
  bridge: BRIDGE_CONTRACT_EVM_MAINNET,
3275
3430
  adapter: ADAPTER_CONTRACT_EVM_MAINNET
@@ -3335,6 +3490,9 @@ var EarnChain;
3335
3490
  destination: true
3336
3491
  }
3337
3492
  },
3493
+ cctpx: {
3494
+ serviceAddress: CCTPX_SERVICE_ADDRESS_EVM_TESTNET
3495
+ },
3338
3496
  kitContracts: {
3339
3497
  bridge: BRIDGE_CONTRACT_EVM_TESTNET,
3340
3498
  adapter: ADAPTER_CONTRACT_EVM_TESTNET
@@ -3526,6 +3684,7 @@ var EarnChain;
3526
3684
  v2: {
3527
3685
  type: 'split',
3528
3686
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
3687
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
3529
3688
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
3530
3689
  confirmations: 1,
3531
3690
  fastConfirmations: 1
@@ -3571,6 +3730,7 @@ var EarnChain;
3571
3730
  v2: {
3572
3731
  type: 'split',
3573
3732
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
3733
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
3574
3734
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
3575
3735
  confirmations: 1,
3576
3736
  fastConfirmations: 1
@@ -3616,6 +3776,7 @@ var EarnChain;
3616
3776
  v2: {
3617
3777
  type: 'split',
3618
3778
  tokenMessenger: '0x98706A006bc632Df31CAdFCBD43F38887ce2ca5c',
3779
+ tokenMessengerWithFees: '0x3Ac96675F9a3E6922713e041645D82f3561d3686',
3619
3780
  messageTransmitter: '0x5b61381Fc9e58E70EfC13a4A97516997019198ee',
3620
3781
  confirmations: 65,
3621
3782
  fastConfirmations: 1
@@ -3661,6 +3822,7 @@ var EarnChain;
3661
3822
  v2: {
3662
3823
  type: 'split',
3663
3824
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
3825
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
3664
3826
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
3665
3827
  confirmations: 65,
3666
3828
  fastConfirmations: 1
@@ -3723,6 +3885,9 @@ var EarnChain;
3723
3885
  destination: true
3724
3886
  }
3725
3887
  },
3888
+ cctpx: {
3889
+ serviceAddress: CCTPX_SERVICE_ADDRESS_EVM_MAINNET
3890
+ },
3726
3891
  kitContracts: {
3727
3892
  bridge: BRIDGE_CONTRACT_EVM_MAINNET,
3728
3893
  adapter: ADAPTER_CONTRACT_EVM_MAINNET
@@ -3788,6 +3953,9 @@ var EarnChain;
3788
3953
  destination: true
3789
3954
  }
3790
3955
  },
3956
+ cctpx: {
3957
+ serviceAddress: CCTPX_SERVICE_ADDRESS_EVM_TESTNET
3958
+ },
3791
3959
  kitContracts: {
3792
3960
  bridge: BRIDGE_CONTRACT_EVM_TESTNET,
3793
3961
  adapter: ADAPTER_CONTRACT_EVM_TESTNET
@@ -4009,6 +4177,7 @@ var EarnChain;
4009
4177
  v2: {
4010
4178
  type: 'split',
4011
4179
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
4180
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
4012
4181
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
4013
4182
  confirmations: 1,
4014
4183
  fastConfirmations: 1
@@ -4056,6 +4225,7 @@ var EarnChain;
4056
4225
  v2: {
4057
4226
  type: 'split',
4058
4227
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
4228
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4059
4229
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
4060
4230
  confirmations: 1,
4061
4231
  fastConfirmations: 1
@@ -4337,6 +4507,7 @@ var EarnChain;
4337
4507
  v2: {
4338
4508
  type: 'split',
4339
4509
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
4510
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4340
4511
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
4341
4512
  confirmations: 1,
4342
4513
  fastConfirmations: 1
@@ -4382,6 +4553,7 @@ var EarnChain;
4382
4553
  v2: {
4383
4554
  type: 'split',
4384
4555
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
4556
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
4385
4557
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
4386
4558
  confirmations: 64,
4387
4559
  fastConfirmations: 1
@@ -4427,6 +4599,7 @@ var EarnChain;
4427
4599
  v2: {
4428
4600
  type: 'split',
4429
4601
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
4602
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4430
4603
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
4431
4604
  confirmations: 64,
4432
4605
  fastConfirmations: 1
@@ -4614,6 +4787,9 @@ var EarnChain;
4614
4787
  destination: true
4615
4788
  }
4616
4789
  },
4790
+ cctpx: {
4791
+ serviceAddress: CCTPX_SERVICE_ADDRESS_EVM_MAINNET
4792
+ },
4617
4793
  kitContracts: {
4618
4794
  bridge: BRIDGE_CONTRACT_EVM_MAINNET,
4619
4795
  adapter: ADAPTER_CONTRACT_EVM_MAINNET
@@ -4679,6 +4855,9 @@ var EarnChain;
4679
4855
  destination: true
4680
4856
  }
4681
4857
  },
4858
+ cctpx: {
4859
+ serviceAddress: CCTPX_SERVICE_ADDRESS_EVM_TESTNET
4860
+ },
4682
4861
  kitContracts: {
4683
4862
  bridge: BRIDGE_CONTRACT_EVM_TESTNET
4684
4863
  },
@@ -4728,6 +4907,7 @@ var EarnChain;
4728
4907
  v2: {
4729
4908
  type: 'split',
4730
4909
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
4910
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
4731
4911
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
4732
4912
  confirmations: 1,
4733
4913
  fastConfirmations: 1
@@ -4774,6 +4954,7 @@ var EarnChain;
4774
4954
  v2: {
4775
4955
  type: 'split',
4776
4956
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
4957
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4777
4958
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
4778
4959
  confirmations: 1,
4779
4960
  fastConfirmations: 1
@@ -5072,6 +5253,9 @@ var EarnChain;
5072
5253
  destination: true
5073
5254
  }
5074
5255
  },
5256
+ cctpx: {
5257
+ serviceAddress: CCTPX_SERVICE_ADDRESS_EVM_MAINNET
5258
+ },
5075
5259
  kitContracts: {
5076
5260
  bridge: BRIDGE_CONTRACT_EVM_MAINNET,
5077
5261
  adapter: ADAPTER_CONTRACT_EVM_MAINNET
@@ -5081,7 +5265,9 @@ var EarnChain;
5081
5265
  contracts: {
5082
5266
  v1: {
5083
5267
  wallet: GATEWAY_WALLET_EVM_MAINNET,
5084
- minter: GATEWAY_MINTER_EVM_MAINNET
5268
+ minter: GATEWAY_MINTER_EVM_MAINNET,
5269
+ depositForHandler: DEPOSIT_FOR_HANDLER_EVM_MAINNET,
5270
+ genericExecutor: GENERIC_EXECUTOR_EVM_MAINNET
5085
5271
  }
5086
5272
  },
5087
5273
  forwarderSupported: {
@@ -5138,6 +5324,9 @@ var EarnChain;
5138
5324
  destination: true
5139
5325
  }
5140
5326
  },
5327
+ cctpx: {
5328
+ serviceAddress: CCTPX_SERVICE_ADDRESS_EVM_TESTNET
5329
+ },
5141
5330
  kitContracts: {
5142
5331
  bridge: BRIDGE_CONTRACT_EVM_TESTNET
5143
5332
  },
@@ -5146,7 +5335,9 @@ var EarnChain;
5146
5335
  contracts: {
5147
5336
  v1: {
5148
5337
  wallet: GATEWAY_WALLET_EVM_TESTNET,
5149
- minter: GATEWAY_MINTER_EVM_TESTNET
5338
+ minter: GATEWAY_MINTER_EVM_TESTNET,
5339
+ depositForHandler: DEPOSIT_FOR_HANDLER_EVM_TESTNET,
5340
+ genericExecutor: GENERIC_EXECUTOR_EVM_TESTNET
5150
5341
  }
5151
5342
  },
5152
5343
  forwarderSupported: {
@@ -6144,6 +6335,7 @@ var Chains = /*#__PURE__*/Object.freeze({
6144
6335
  AptosTestnet: AptosTestnet,
6145
6336
  Arbitrum: Arbitrum,
6146
6337
  ArbitrumSepolia: ArbitrumSepolia,
6338
+ Arc: Arc,
6147
6339
  ArcTestnet: ArcTestnet,
6148
6340
  Avalanche: Avalanche,
6149
6341
  AvalancheFuji: AvalancheFuji,
@@ -6232,6 +6424,67 @@ var Chains = /*#__PURE__*/Object.freeze({
6232
6424
  return chain.cctp?.contracts.v2 !== undefined;
6233
6425
  }
6234
6426
 
6427
+ /**
6428
+ * Chains the Fee Service accepts as a SOURCE for source-paid ("receive-exact")
6429
+ * CCTP v2 fees. An explicit allowlist is required because the
6430
+ * `TokenMessengerWithFees` wrapper address is now shared with the fast-deposit
6431
+ * forwarder path, so wrapper presence no longer implies source-fee support.
6432
+ * Keep in sync with backend coverage.
6433
+ */ new Set([
6434
+ // Mainnet
6435
+ Blockchain.Ethereum,
6436
+ Blockchain.Base,
6437
+ Blockchain.Arbitrum,
6438
+ Blockchain.Unichain,
6439
+ Blockchain.Optimism,
6440
+ Blockchain.Codex,
6441
+ Blockchain.Ink,
6442
+ Blockchain.Plume,
6443
+ Blockchain.Linea,
6444
+ Blockchain.World_Chain,
6445
+ // Testnet counterparts
6446
+ Blockchain.Ethereum_Sepolia,
6447
+ Blockchain.Base_Sepolia,
6448
+ Blockchain.Arbitrum_Sepolia,
6449
+ Blockchain.Unichain_Sepolia,
6450
+ Blockchain.Optimism_Sepolia,
6451
+ Blockchain.Codex_Testnet,
6452
+ Blockchain.Ink_Testnet,
6453
+ Blockchain.Plume_Testnet,
6454
+ Blockchain.Linea_Sepolia,
6455
+ Blockchain.World_Chain_Sepolia
6456
+ ]);
6457
+
6458
+ /**
6459
+ * Temporary allowlist of chains permitted to initiate Gateway fast deposits.
6460
+ * Only chains keyed here are eligible; all others are rejected. Using the
6461
+ * {@link Blockchain} enum keeps entries type-safe and catches typos at compile
6462
+ * time. Remove this allowlist once roll-out is complete.
6463
+ */ new Set([
6464
+ // Mainnet
6465
+ Blockchain.Ethereum,
6466
+ Blockchain.Base,
6467
+ Blockchain.Arbitrum,
6468
+ Blockchain.Unichain,
6469
+ Blockchain.Optimism,
6470
+ Blockchain.Codex,
6471
+ Blockchain.Ink,
6472
+ Blockchain.Plume,
6473
+ Blockchain.Linea,
6474
+ Blockchain.World_Chain,
6475
+ // Testnet counterparts
6476
+ Blockchain.Ethereum_Sepolia,
6477
+ Blockchain.Base_Sepolia,
6478
+ Blockchain.Arbitrum_Sepolia,
6479
+ Blockchain.Unichain_Sepolia,
6480
+ Blockchain.Optimism_Sepolia,
6481
+ Blockchain.Codex_Testnet,
6482
+ Blockchain.Ink_Testnet,
6483
+ Blockchain.Plume_Testnet,
6484
+ Blockchain.Linea_Sepolia,
6485
+ Blockchain.World_Chain_Sepolia
6486
+ ]);
6487
+
6235
6488
  /**
6236
6489
  * Zod schema for validating Gateway v1 contract addresses.
6237
6490
  *
@@ -6253,7 +6506,10 @@ var Chains = /*#__PURE__*/Object.freeze({
6253
6506
  }).min(1, 'Gateway minter address cannot be empty.'),
6254
6507
  depositForHandler: z.string({
6255
6508
  invalid_type_error: 'Gateway depositForHandler address must be a string.'
6256
- }).min(1, 'Gateway depositForHandler address cannot be empty.').optional()
6509
+ }).min(1, 'Gateway depositForHandler address cannot be empty.').optional(),
6510
+ genericExecutor: z.string({
6511
+ invalid_type_error: 'Gateway genericExecutor address must be a string.'
6512
+ }).min(1, 'Gateway genericExecutor address cannot be empty.').optional()
6257
6513
  }).strict() // Reject any additional properties not defined in the schema
6258
6514
  ;
6259
6515
  /**
@@ -6337,6 +6593,7 @@ var Chains = /*#__PURE__*/Object.freeze({
6337
6593
  usdcAddress: z.string().nullable(),
6338
6594
  usdtAddress: z.string().nullable(),
6339
6595
  cctp: z.any().nullable(),
6596
+ cctpx: z.any().optional(),
6340
6597
  kitContracts: z.object({
6341
6598
  bridge: z.string().optional(),
6342
6599
  adapter: z.string().optional()
@@ -6542,14 +6799,15 @@ const EARN_BRIDGE_DESTINATION_CHAIN_VALUES = EARN_BRIDGE_DESTINATION_BLOCKCHAINS
6542
6799
  * Zod schema for validating the source chain of a cross-chain Earn deposit.
6543
6800
  *
6544
6801
  * Accept a supported source Blockchain value, a matching string literal, or a
6545
- * ChainDefinition for a supported source chain. Source chains are Ethereum
6546
- * Sepolia, Arbitrum Sepolia, and Base Sepolia.
6802
+ * ChainDefinition for a supported source chain. Source chains are Ethereum,
6803
+ * Arbitrum, and Base (mainnet and testnet).
6547
6804
  *
6548
6805
  * @example
6549
6806
  * ```typescript
6550
6807
  * import { earnBridgeSourceChainIdentifierSchema } from '@core/chains'
6551
6808
  *
6552
6809
  * // Valid
6810
+ * earnBridgeSourceChainIdentifierSchema.parse('Ethereum')
6553
6811
  * earnBridgeSourceChainIdentifierSchema.parse('Ethereum_Sepolia')
6554
6812
  *
6555
6813
  * // Invalid (throws ZodError)
@@ -6568,14 +6826,15 @@ const EARN_BRIDGE_DESTINATION_CHAIN_VALUES = EARN_BRIDGE_DESTINATION_BLOCKCHAINS
6568
6826
  * deposit.
6569
6827
  *
6570
6828
  * Accept a supported destination Blockchain value, a matching string literal,
6571
- * or a ChainDefinition for a supported destination chain. Currently only Arc
6572
- * Testnet is supported.
6829
+ * or a ChainDefinition for a supported destination chain. Arc (mainnet) and
6830
+ * Arc Testnet are supported.
6573
6831
  *
6574
6832
  * @example
6575
6833
  * ```typescript
6576
6834
  * import { earnBridgeDestinationChainIdentifierSchema } from '@core/chains'
6577
6835
  *
6578
6836
  * // Valid
6837
+ * earnBridgeDestinationChainIdentifierSchema.parse('Arc')
6579
6838
  * earnBridgeDestinationChainIdentifierSchema.parse('Arc_Testnet')
6580
6839
  *
6581
6840
  * // Invalid (throws ZodError)
@@ -7621,6 +7880,7 @@ const swapTokenEnumSchema = z.enum([
7621
7880
  // Mainnets (alphabetically sorted)
7622
7881
  // =========================================================================
7623
7882
  [Blockchain.Arbitrum]: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',
7883
+ [Blockchain.Arc]: '0x3600000000000000000000000000000000000000',
7624
7884
  [Blockchain.Avalanche]: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E',
7625
7885
  [Blockchain.Base]: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
7626
7886
  [Blockchain.Celo]: '0xcebA9300f2b948710d2653dD7B07f33A8B32118C',
@@ -7735,6 +7995,7 @@ const swapTokenEnumSchema = z.enum([
7735
7995
  // =========================================================================
7736
7996
  // Mainnets
7737
7997
  // =========================================================================
7998
+ [Blockchain.Arc]: '0xbEf5f6d51CB62b58e6A8f77868681825C6fe21c1',
7738
7999
  [Blockchain.Avalanche]: '0xc891EB4cbdEFf6e073e859e987815Ed1505c2ACD',
7739
8000
  [Blockchain.Base]: '0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42',
7740
8001
  [Blockchain.Cronos]: '0xA6dE01a2d62C6B5f3525d768f34d276652C554c8',
@@ -7978,6 +8239,7 @@ const swapTokenEnumSchema = z.enum([
7978
8239
  // =========================================================================
7979
8240
  // Mainnets
7980
8241
  // =========================================================================
8242
+ [Blockchain.Arc]: '0x171A4217b86A807A64eB94757Db6849fb4bDbAA0',
7981
8243
  [Blockchain.Ethereum]: '0x72DFB2E44f59C5AD2bAFE84314E5b99a7cd5075E',
7982
8244
  // =========================================================================
7983
8245
  // Testnets
@@ -8070,13 +8332,28 @@ const swapTokenEnumSchema = z.enum([
8070
8332
  }
8071
8333
 
8072
8334
  /**
8073
- * Check if a selector is a raw token selector (object form).
8335
+ * Type guard: narrows a {@link TokenSelector} to a {@link RawTokenSelector}.
8074
8336
  *
8075
8337
  * @param selector - The token selector to check.
8076
- * @returns True if the selector is a raw token selector.
8338
+ * @returns `true` if `selector` is a raw token selector (object with `locator`).
8339
+ *
8340
+ * @example
8341
+ * ```typescript
8342
+ * if (isRawSelector(selector)) {
8343
+ * console.log(selector.locator)
8344
+ * }
8345
+ * ```
8077
8346
  */ function isRawSelector(selector) {
8078
- return typeof selector === 'object' && 'locator' in selector;
8347
+ // `typeof null === 'object'` (a JS quirk) and `'locator' in null`
8348
+ // throws, so the explicit `null` check is required at this exported
8349
+ // guard for JS consumers passing nullish values. The lint rule sees
8350
+ // the parameter typed as `TokenSelector` (no null) and flags the
8351
+ // check as unnecessary — disabled because the check IS necessary at
8352
+ // runtime even though TypeScript can prove it dead statically.
8353
+ return typeof selector === 'object' && // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
8354
+ selector !== null && 'locator' in selector;
8079
8355
  }
8356
+
8080
8357
  /**
8081
8358
  * Normalize a symbol to uppercase for case-insensitive lookup.
8082
8359
  *
@@ -8264,7 +8541,7 @@ const swapTokenEnumSchema = z.enum([
8264
8541
  if (typeof selector === 'string') {
8265
8542
  return resolveSymbol(selector, chainId);
8266
8543
  }
8267
- throw createTokenResolutionError(`Invalid selector type: ${typeof selector}. Expected string or object with locator.`, selector, chainId);
8544
+ throw createTokenResolutionError(`Invalid selector type: ${typeof selector}. Expected a token symbol or a raw selector (with locator).`, selector, chainId);
8268
8545
  },
8269
8546
  resolveByAddress (address, chainId) {
8270
8547
  if (!address || typeof address !== 'string') {
@@ -8467,7 +8744,7 @@ const swapTokenEnumSchema = z.enum([
8467
8744
  * allowlisted {@link ClientLogPayload} fields (and the allowlisted
8468
8745
  * sub-fields of `errorDetails` / `clientContext`) are copied across.
8469
8746
  * A regressing upstream mapper — or a plain-JS caller that bypasses the
8470
- * type — therefore cannot exfiltrate stray properties (secrets, PII,
8747
+ * type — therefore cannot exfiltrate stray properties (secrets,
8471
8748
  * raw error stacks) through the analytics channel. Optional fields are
8472
8749
  * only included when present so the serialised shape matches the
8473
8750
  * server's strict schema.
@@ -8490,6 +8767,9 @@ const swapTokenEnumSchema = z.enum([
8490
8767
  if (payload.destinationChain !== undefined) safe['destinationChain'] = payload.destinationChain;
8491
8768
  if (payload.tokenIn !== undefined) safe['tokenIn'] = payload.tokenIn;
8492
8769
  if (payload.tokenOut !== undefined) safe['tokenOut'] = payload.tokenOut;
8770
+ if (payload.amountIn !== undefined) safe['amountIn'] = payload.amountIn;
8771
+ if (payload.durationMs !== undefined) safe['durationMs'] = payload.durationMs;
8772
+ if (payload.sourceAddress !== undefined) safe['sourceAddress'] = payload.sourceAddress;
8493
8773
  if (payload.txHash !== undefined) safe['txHash'] = payload.txHash;
8494
8774
  if (payload.correlationId !== undefined) safe['correlationId'] = payload.correlationId;
8495
8775
  if (payload.errorDetails !== undefined) {
@@ -8686,14 +8966,28 @@ const swapTokenEnumSchema = z.enum([
8686
8966
  }
8687
8967
 
8688
8968
  /**
8689
- * Soft signal for the case where building or emitting a telemetry payload
8690
- * threw — for example, a buggy `TelemetryContextResolver`, a regression in
8969
+ * Emit a stable console warning when building or emitting a telemetry payload
8970
+ * throws — for example, a buggy `TelemetryContextResolver`, a regression in
8691
8971
  * `extractErrorDetails`, or a synchronous failure inside `emitAnalyticsLog`
8692
- * before it could swallow the error itself. Logged with a stable prefix so
8693
- * consumers can grep for it. We deliberately do not re-throw: the caller's
8694
- * original operation error must always win.
8972
+ * before it could swallow the error itself. Uses a stable prefix so the
8973
+ * drop is discoverable via grep. Never re-throws: the caller's original
8974
+ * operation error must always win.
8695
8975
  *
8696
8976
  * @internal
8977
+ *
8978
+ * @param eventType - The telemetry event type that was being emitted.
8979
+ * @param cause - The error or value that caused the drop.
8980
+ *
8981
+ * @example
8982
+ * ```typescript
8983
+ * import { warnTelemetryDrop } from '@core/utils'
8984
+ *
8985
+ * try {
8986
+ * void emitAnalyticsLog(payload)
8987
+ * } catch (err) {
8988
+ * warnTelemetryDrop('my_event', err)
8989
+ * }
8990
+ * ```
8697
8991
  */ function warnTelemetryDrop(eventType, cause) {
8698
8992
  try {
8699
8993
  // Pass `cause` as the second console.warn argument rather than
@@ -8733,6 +9027,9 @@ const swapTokenEnumSchema = z.enum([
8733
9027
  ...context?.tokenOut != null && {
8734
9028
  tokenOut: context.tokenOut
8735
9029
  },
9030
+ ...context?.amountIn != null && {
9031
+ amountIn: context.amountIn
9032
+ },
8736
9033
  ...context?.txHash != null && {
8737
9034
  txHash: context.txHash
8738
9035
  },
@@ -8832,7 +9129,7 @@ const swapTokenEnumSchema = z.enum([
8832
9129
  }
8833
9130
 
8834
9131
  var name$3 = "@circle-fin/bridge-kit";
8835
- var version$3 = "1.14.0";
9132
+ var version$3 = "1.15.0";
8836
9133
  var pkg$3 = {
8837
9134
  name: name$3,
8838
9135
  version: version$3};
@@ -9452,7 +9749,72 @@ var TransferSpeed;
9452
9749
  */ recipientAddress: z.string().trim().min(1, 'Fee recipient must be a non-empty string').optional()
9453
9750
  }).strict();
9454
9751
  /**
9455
- * Schema for validating bridge parameters.
9752
+ * Factory for the bridge-params Zod schema, parameterized by the token
9753
+ * validator. The base schema enforces all non-token fields (amount,
9754
+ * source, destination, config); callers supply the Zod schema for the
9755
+ * `token` field, allowing each provider to validate the token type it
9756
+ * accepts.
9757
+ *
9758
+ * @param tokenSchema - Zod schema applied to the `token` field. Pass
9759
+ * `z.literal('USDC')` for USDC-only validation, or any
9760
+ * provider-specific schema (e.g. a `0x`-prefixed hex regex) for
9761
+ * providers that accept a different token type.
9762
+ * @param config - Required. `maxDecimals` caps the decimal precision
9763
+ * permitted in `amount` and `config.maxFee`. Pass the widest value
9764
+ * any of the provider's tokens require — `6` for USDC-only, `18`
9765
+ * for an ERC-20 family that includes wETH, etc. The schema is a
9766
+ * coarse syntactic gate; narrower per-token precision is enforced
9767
+ * by the provider downstream.
9768
+ * @returns A Zod object schema whose `token` field is validated by
9769
+ * `tokenSchema` and whose other fields (`amount`, `source`,
9770
+ * `destination`, `config`) are validated against the shared bridge
9771
+ * contract. Use `.safeParse` / `.parse` directly, or feed the schema
9772
+ * to {@link parseOrThrow} from `@core/utils` to surface validation
9773
+ * failures as `KitError` with the canonical
9774
+ * `INPUT_VALIDATION_FAILED` code.
9775
+ *
9776
+ * @example
9777
+ * ```typescript
9778
+ * import { createBridgeParamsSchema, z } from '@core/provider'
9779
+ *
9780
+ * const usdcSchema = createBridgeParamsSchema(z.literal('USDC'), { maxDecimals: 6 })
9781
+ * const hexSchema = createBridgeParamsSchema(
9782
+ * z.string().regex(/^0x[0-9a-fA-F]{64}$/),
9783
+ * { maxDecimals: 18 },
9784
+ * )
9785
+ * ```
9786
+ */ // The full inferred return type of `z.object({...})` here is
9787
+ // effectively impossible to spell out by hand without re-stating every
9788
+ // field's schema. TypeScript infers it from the body — callers receive
9789
+ // a precise Zod schema type via inference, and the explicit-return
9790
+ // rules are disabled for that reason.
9791
+ // eslint-disable-next-line @typescript-eslint/explicit-function-return-type, @typescript-eslint/explicit-module-boundary-types
9792
+ function createBridgeParamsSchema(tokenSchema, config) {
9793
+ const { maxDecimals } = config;
9794
+ return z.object({
9795
+ amount: z.string().min(1, 'Required').pipe(createDecimalStringValidator({
9796
+ allowZero: false,
9797
+ regexMessage: AMOUNT_FORMAT_ERROR_MESSAGE,
9798
+ attributeName: 'amount',
9799
+ maxDecimals
9800
+ })(z.string())),
9801
+ source: walletContextSchema,
9802
+ destination: bridgeDestinationSchema$1,
9803
+ token: tokenSchema,
9804
+ config: z.object({
9805
+ transferSpeed: z.nativeEnum(TransferSpeed).optional(),
9806
+ maxFee: z.string().pipe(createDecimalStringValidator({
9807
+ allowZero: true,
9808
+ regexMessage: MAX_FEE_FORMAT_ERROR_MESSAGE,
9809
+ attributeName: 'maxFee',
9810
+ maxDecimals
9811
+ })(z.string())).optional(),
9812
+ customFee: customFeeSchema.optional()
9813
+ })
9814
+ });
9815
+ }
9816
+ /**
9817
+ * Schema for validating bridge parameters with USDC as the token.
9456
9818
  * This ensures all required fields are present and properly typed.
9457
9819
  * A bridge must include:
9458
9820
  * - A valid amount (non-empty numeric string \> 0)
@@ -9460,11 +9822,15 @@ var TransferSpeed;
9460
9822
  * - USDC as the token
9461
9823
  * - Optional config with transfer speed and max fee settings
9462
9824
  *
9825
+ * Providers that accept a non-USDC token type should call
9826
+ * {@link createBridgeParamsSchema} with their own token schema rather
9827
+ * than reusing this constant.
9828
+ *
9463
9829
  * @throws KitError if validation fails
9464
9830
  *
9465
9831
  * @example
9466
9832
  * ```typescript
9467
- * import { bridgeParamsSchema } from '@core/provider'
9833
+ * import { usdcBridgeParamsSchema } from '@core/provider'
9468
9834
  *
9469
9835
  * const validBridge = {
9470
9836
  * amount: '100.50',
@@ -9489,193 +9855,61 @@ var TransferSpeed;
9489
9855
  * }
9490
9856
  * }
9491
9857
  *
9492
- * const result = bridgeParamsSchema.safeParse(validBridge)
9858
+ * const result = usdcBridgeParamsSchema.safeParse(validBridge)
9493
9859
  * console.log(result.success) // true
9494
9860
  * ```
9495
- */ z.object({
9496
- amount: z.string().min(1, 'Required').pipe(createDecimalStringValidator({
9497
- allowZero: false,
9498
- regexMessage: AMOUNT_FORMAT_ERROR_MESSAGE,
9499
- attributeName: 'amount',
9500
- maxDecimals: 6
9501
- })(z.string())),
9502
- source: walletContextSchema,
9503
- destination: bridgeDestinationSchema$1,
9504
- token: z.literal('USDC'),
9505
- config: z.object({
9506
- transferSpeed: z.nativeEnum(TransferSpeed).optional(),
9507
- maxFee: z.string().pipe(createDecimalStringValidator({
9508
- allowZero: true,
9509
- regexMessage: MAX_FEE_FORMAT_ERROR_MESSAGE,
9510
- attributeName: 'maxFee',
9511
- maxDecimals: 6
9512
- })(z.string())).optional(),
9513
- customFee: customFeeSchema.optional()
9514
- })
9861
+ */ createBridgeParamsSchema(z.literal('USDC'), {
9862
+ maxDecimals: 6
9515
9863
  });
9516
9864
 
9517
- /**
9518
- * Creates a Zod superRefine validator for recipient address format validation.
9519
- * Validates that the address format matches the expected format for the chain type.
9865
+ // ----------------------------------------------------------------------------
9866
+ // IRIS API base URLs
9867
+ // ----------------------------------------------------------------------------
9868
+ // ----------------------------------------------------------------------------
9869
+ // Known token symbols (DX convenience)
9870
+ // ----------------------------------------------------------------------------
9871
+ //
9872
+ // These constants back symbol -> id resolution as a convenience: a caller may
9873
+ // pass a known symbol instead of a raw bytes32 id. They do NOT gate
9874
+ // routability.
9875
+ /**
9876
+ * Display symbols the provider recognizes as a convenience for callers.
9877
+ *
9878
+ * A consumer may pass one of these symbols instead of a raw bytes32 token
9879
+ * id; the provider resolves it to the symbol's canonical bytes32 id via
9880
+ * {@link KNOWN_TOKEN_IDS_BY_NETWORK} (a symbol can map to more than one
9881
+ * bridge, so the map pins the canonical one). This list does NOT gate
9882
+ * routability: any token the IRIS registry lists with deployments on both
9883
+ * endpoints routes when passed by its bytes32 id, whether listed here or
9884
+ * not.
9520
9885
  *
9521
- * @returns A superRefine function that validates recipientAddress against chain type
9522
- */ function createRecipientAddressValidator() {
9523
- return (data, ctx)=>{
9524
- const chain = data.chain;
9525
- if (chain === null) {
9526
- return;
9527
- }
9528
- if (!isValidAddressForChain(data.recipientAddress, chain)) {
9529
- const chainInfo = extractChainInfo(chain);
9530
- ctx.addIssue({
9531
- code: z.ZodIssueCode.custom,
9532
- path: [
9533
- 'recipientAddress'
9534
- ],
9535
- message: `Invalid address format for ${String(chainInfo.name)}. Expected ${chainInfo.expectedAddressFormat}, but received: ${data.recipientAddress}`
9536
- });
9537
- }
9538
- };
9886
+ * @example
9887
+ * ```typescript
9888
+ * for (const symbol of KNOWN_TOKEN_SYMBOLS) console.log(symbol)
9889
+ * ```
9890
+ */ const KNOWN_TOKEN_SYMBOLS = [
9891
+ 'cirBTC',
9892
+ 'wETH',
9893
+ 'EURC'
9894
+ ];
9895
+
9896
+ // ============================================================================
9897
+ // Crypto Utilities (Internal)
9898
+ // ============================================================================
9899
+ /** @internal */ function hasGetRandomValues() {
9900
+ return typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function';
9901
+ }
9902
+ /** @internal */ function hasRandomUUID() {
9903
+ return typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function';
9539
9904
  }
9540
9905
  /**
9541
- * Schema for validating AdapterContext for bridge operations.
9542
- * Must always contain both adapter and chain explicitly.
9543
- *
9544
- * Optionally includes address for developer-controlled adapters.
9545
- */ const adapterContextSchema$3 = z.object({
9546
- adapter: adapterSchema,
9547
- chain: bridgeChainIdentifierSchema,
9548
- address: z.string().optional()
9549
- });
9550
- /**
9551
- * Schema for validating BridgeDestinationWithAddress objects.
9552
- * Contains an explicit recipientAddress along with adapter and chain.
9553
- * The address format is validated based on the chain type (EVM or Solana).
9554
- */ const bridgeDestinationWithAddressSchema = adapterContextSchema$3.extend({
9555
- recipientAddress: z.string().min(1, 'Recipient address is required'),
9556
- useForwarder: z.boolean().optional()
9557
- }).superRefine(createRecipientAddressValidator());
9558
- /**
9559
- * Schema for validating AdapterContext with optional useForwarder.
9560
- * Extends adapterContextSchema with the useForwarder flag.
9561
- */ const adapterContextWithForwarderSchema = adapterContextSchema$3.extend({
9562
- useForwarder: z.boolean().optional()
9563
- });
9564
- /**
9565
- * Schema for validating ForwarderDestination objects.
9566
- * Used when useForwarder is true and no adapter is provided.
9567
- * Requires chain, recipientAddress, and useForwarder: true.
9568
- *
9569
- * When using this destination type:
9570
- * - The mint step completes when the IRIS API confirms forwardState === 'CONFIRMED'
9571
- * - No on-chain transaction confirmation is performed (no adapter available)
9572
- * - The mint step's data field will be undefined (no transaction receipt)
9573
- */ const forwarderDestinationSchema = z.object({
9574
- chain: bridgeChainIdentifierSchema,
9575
- recipientAddress: z.string().min(1, 'Recipient address is required'),
9576
- useForwarder: z.literal(true)
9577
- }).strict().superRefine(createRecipientAddressValidator());
9578
- /**
9579
- * Schema for validating BridgeDestination union type.
9580
- * Supports three destination configurations:
9581
- * - BridgeDestinationWithAddress (adapter with explicit recipient)
9582
- * - ForwarderDestination (no adapter, requires useForwarder: true and recipientAddress)
9583
- * - AdapterContext with optional useForwarder (adapter for default recipient)
9584
- *
9585
- * When using ForwarderDestination (no adapter):
9586
- * - The mint step completes when the IRIS API confirms forwardState === 'CONFIRMED'
9587
- * - No on-chain transaction confirmation is performed
9906
+ * Create an RFC 4122 compliant UUIDv4.
9588
9907
  *
9589
- * The order matters: we check the more specific schemas first.
9590
- * This ensures that objects with specific fields are matched correctly.
9591
- */ const bridgeDestinationSchema = z.union([
9592
- bridgeDestinationWithAddressSchema,
9593
- forwarderDestinationSchema,
9594
- adapterContextWithForwarderSchema.strict()
9595
- ]);
9596
- /**
9597
- * Schema for validating bridge parameters with chain identifiers.
9598
- * This extends the core provider's schema but adapts it for the bridge kit's
9599
- * more flexible interface that accepts chain identifiers.
9908
+ * @returns UUID string (8-4-4-4-12 hex digits with hyphens).
9600
9909
  *
9601
- * The schema validates:
9602
- * - From adapter context (must always include both adapter and chain)
9603
- * - To bridge destination (AdapterContext or BridgeDestinationWithAddress)
9604
- * - Amount is a non-empty numeric string \> 0
9605
- * - Token is optional and defaults to 'USDC'
9606
- * - Optional config parameters (transfer speed, max fee)
9607
- *
9608
- * @example
9609
- * ```typescript
9610
- * import { bridgeParamsWithChainIdentifierSchema } from '@circle-fin/bridge-kit'
9611
- *
9612
- * const params = {
9613
- * from: {
9614
- * adapter: sourceAdapter,
9615
- * chain: 'Ethereum'
9616
- * },
9617
- * to: {
9618
- * adapter: destAdapter,
9619
- * chain: 'Base'
9620
- * },
9621
- * amount: '100.50',
9622
- * token: 'USDC',
9623
- * config: {
9624
- * transferSpeed: 'FAST'
9625
- * }
9626
- * }
9627
- *
9628
- * const result = bridgeParamsWithChainIdentifierSchema.safeParse(params)
9629
- * if (result.success) {
9630
- * console.log('Parameters are valid')
9631
- * } else {
9632
- * console.error('Validation failed:', result.error)
9633
- * }
9634
- * ```
9635
- */ z.object({
9636
- from: adapterContextSchema$3.strict(),
9637
- to: bridgeDestinationSchema,
9638
- amount: z.string().min(1, 'Required').pipe(createDecimalStringValidator({
9639
- allowZero: false,
9640
- regexMessage: AMOUNT_FORMAT_ERROR_MESSAGE,
9641
- attributeName: 'amount',
9642
- maxDecimals: 6
9643
- })(z.string())),
9644
- token: z.literal('USDC').optional(),
9645
- config: z.object({
9646
- transferSpeed: z.nativeEnum(TransferSpeed).optional(),
9647
- feePayment: z.enum([
9648
- 'source',
9649
- 'destination'
9650
- ]).optional(),
9651
- maxFee: z.string().min(1, 'Required').pipe(createDecimalStringValidator({
9652
- allowZero: true,
9653
- regexMessage: MAX_FEE_FORMAT_ERROR_MESSAGE,
9654
- attributeName: 'maxFee',
9655
- maxDecimals: 6
9656
- })(z.string())).optional(),
9657
- customFee: customFeeSchema.optional()
9658
- }).optional(),
9659
- quote: z.string().regex(/^0x([a-fA-F0-9]{2})+$/, 'must be non-empty 0x hex').optional()
9660
- });
9661
-
9662
- // ============================================================================
9663
- // Crypto Utilities (Internal)
9664
- // ============================================================================
9665
- /** @internal */ function hasGetRandomValues() {
9666
- return typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function';
9667
- }
9668
- /** @internal */ function hasRandomUUID() {
9669
- return typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function';
9670
- }
9671
- /**
9672
- * Create an RFC 4122 compliant UUIDv4.
9673
- *
9674
- * @returns UUID string (8-4-4-4-12 hex digits with hyphens).
9675
- *
9676
- * @remarks
9677
- * Use when external systems require RFC 4122 UUID format.
9678
- * For traceId, use {@link createTraceId} instead.
9910
+ * @remarks
9911
+ * Use when external systems require RFC 4122 UUID format.
9912
+ * For traceId, use {@link createTraceId} instead.
9679
9913
  *
9680
9914
  * @example
9681
9915
  * ```typescript
@@ -9764,6 +9998,241 @@ var TransferSpeed;
9764
9998
  message: 'Invalid metrics'
9765
9999
  });
9766
10000
 
10001
+ /**
10002
+ * Omit undefined values from an object.
10003
+ *
10004
+ * @param obj - The object to process.
10005
+ * @returns A new object with undefined values removed.
10006
+ *
10007
+ * @internal
10008
+ * @remarks
10009
+ * Used by both production and mock loggers to ensure consistent behavior.
10010
+ * This prevents undefined values from being serialized in log output,
10011
+ * which can cause issues with some log transports.
10012
+ */ function omitUndefined(obj) {
10013
+ const result = {};
10014
+ for (const [key, value] of Object.entries(obj)){
10015
+ if (value !== undefined) {
10016
+ result[key] = value;
10017
+ }
10018
+ }
10019
+ return result;
10020
+ }
10021
+
10022
+ /**
10023
+ * Default redaction paths for web3/blockchain SDKs.
10024
+ *
10025
+ * @remarks
10026
+ * These paths target common sensitive fields in blockchain applications.
10027
+ * All user fields are nested under `context`, so paths start with `context.`.
10028
+ * Wildcard `*` matches any key at that level.
10029
+ */ const DEFAULT_REDACT_PATHS = [
10030
+ // Generic Credentials
10031
+ 'context.password',
10032
+ 'context.passphrase',
10033
+ 'context.secret',
10034
+ 'context.token',
10035
+ 'context.*.password',
10036
+ 'context.*.passphrase',
10037
+ 'context.*.secret',
10038
+ 'context.*.token',
10039
+ // API Keys & Auth Tokens
10040
+ 'context.apiKey',
10041
+ 'context.apiSecret',
10042
+ 'context.accessToken',
10043
+ 'context.refreshToken',
10044
+ 'context.jwt',
10045
+ 'context.bearerToken',
10046
+ 'context.sessionId',
10047
+ 'context.authorization',
10048
+ 'context.cookie',
10049
+ 'context.*.apiKey',
10050
+ 'context.*.apiSecret',
10051
+ 'context.*.accessToken',
10052
+ 'context.*.refreshToken',
10053
+ 'context.*.jwt',
10054
+ 'context.*.bearerToken',
10055
+ 'context.*.sessionId',
10056
+ 'context.*.authorization',
10057
+ 'context.*.cookie',
10058
+ // Web3 / Crypto Keys
10059
+ 'context.privateKey',
10060
+ 'context.secretKey',
10061
+ 'context.signingKey',
10062
+ 'context.encryptionKey',
10063
+ 'context.*.privateKey',
10064
+ 'context.*.secretKey',
10065
+ 'context.*.signingKey',
10066
+ 'context.*.encryptionKey',
10067
+ // Web3 / Crypto Mnemonics and Seeds
10068
+ 'context.mnemonic',
10069
+ 'context.seed',
10070
+ 'context.seedPhrase',
10071
+ 'context.*.mnemonic',
10072
+ 'context.*.seed',
10073
+ 'context.*.seedPhrase',
10074
+ // OTP / Verification Codes
10075
+ 'context.otp',
10076
+ 'context.verificationCode',
10077
+ 'context.*.otp',
10078
+ 'context.*.verificationCode',
10079
+ // Payment Information
10080
+ 'context.cardNumber',
10081
+ 'context.cvv',
10082
+ 'context.accountNumber',
10083
+ 'context.*.cardNumber',
10084
+ 'context.*.cvv',
10085
+ 'context.*.accountNumber'
10086
+ ];
10087
+ /**
10088
+ * Wrap user fields under `context` to prevent collision with pino internals.
10089
+ *
10090
+ * @param fields - User-provided log fields.
10091
+ * @returns Object with fields nested under `context`, or undefined if empty.
10092
+ *
10093
+ * @remarks
10094
+ * This function handles edge cases by returning undefined for null, undefined,
10095
+ * or empty objects to avoid unnecessary wrapping in log output.
10096
+ * Undefined values are cleaned before wrapping.
10097
+ */ function wrapInContext(fields) {
10098
+ if (!fields) return undefined;
10099
+ // Clean undefined values for consistency and transport compatibility
10100
+ const cleaned = omitUndefined(fields);
10101
+ // Handle edge case: all values were undefined, resulting in empty object
10102
+ const keys = Object.keys(cleaned);
10103
+ if (keys.length === 0) return undefined;
10104
+ return {
10105
+ context: cleaned
10106
+ };
10107
+ }
10108
+ /**
10109
+ * Wrap a pino instance to conform to our Logger interface.
10110
+ *
10111
+ * @param pinoInstance - The pino logger instance to wrap.
10112
+ * @returns A Logger instance conforming to our stable interface.
10113
+ */ function wrapPino(pinoInstance) {
10114
+ return {
10115
+ debug (message, fields) {
10116
+ const wrapped = wrapInContext(fields);
10117
+ if (wrapped) {
10118
+ pinoInstance.debug(wrapped, message);
10119
+ } else {
10120
+ pinoInstance.debug(message);
10121
+ }
10122
+ },
10123
+ info (message, fields) {
10124
+ const wrapped = wrapInContext(fields);
10125
+ if (wrapped) {
10126
+ pinoInstance.info(wrapped, message);
10127
+ } else {
10128
+ pinoInstance.info(message);
10129
+ }
10130
+ },
10131
+ warn (message, fields) {
10132
+ const wrapped = wrapInContext(fields);
10133
+ if (wrapped) {
10134
+ pinoInstance.warn(wrapped, message);
10135
+ } else {
10136
+ pinoInstance.warn(message);
10137
+ }
10138
+ },
10139
+ error (message, fields) {
10140
+ const wrapped = wrapInContext(fields);
10141
+ if (wrapped) {
10142
+ pinoInstance.error(wrapped, message);
10143
+ } else {
10144
+ pinoInstance.error(message);
10145
+ }
10146
+ },
10147
+ child (tags) {
10148
+ // Child bindings stay flat (not wrapped) - they're part of logger's base context
10149
+ const cleaned = omitUndefined(tags);
10150
+ return wrapPino(pinoInstance.child(cleaned));
10151
+ }
10152
+ };
10153
+ }
10154
+ /**
10155
+ * Build pino redact configuration from our simplified options.
10156
+ *
10157
+ * @param redact - The redact configuration option.
10158
+ * @returns Pino-compatible redact configuration or undefined.
10159
+ */ function buildRedactConfig(redact) {
10160
+ // Explicitly disabled
10161
+ if (redact === false) {
10162
+ return undefined;
10163
+ }
10164
+ // Custom paths provided
10165
+ if (Array.isArray(redact)) {
10166
+ return redact.length > 0 ? {
10167
+ paths: redact,
10168
+ censor: '[REDACTED]'
10169
+ } : undefined;
10170
+ }
10171
+ // Default: use web3 sensible defaults
10172
+ return {
10173
+ paths: [
10174
+ ...DEFAULT_REDACT_PATHS
10175
+ ],
10176
+ censor: '[REDACTED]'
10177
+ };
10178
+ }
10179
+ /**
10180
+ * Create a logger backed by pino.
10181
+ *
10182
+ * @param options - Logger options (optional).
10183
+ * @param stream - Destination stream (optional).
10184
+ * @returns A Logger instance.
10185
+ * @throws Error if invalid pino options are provided.
10186
+ *
10187
+ * @remarks
10188
+ * This is a thin wrapper around pino that exposes our stable Logger interface.
10189
+ * Pino handles all transport concerns: JSON, pretty printing, file, remote, browser, etc.
10190
+ *
10191
+ * **Security**: By default, sensitive web3 fields (privateKey, mnemonic, apiKey, etc.)
10192
+ * are automatically redacted from log output. Use `redact: false` to disable.
10193
+ *
10194
+ * @example
10195
+ * ```typescript
10196
+ * import { createLogger } from '@core/runtime'
10197
+ *
10198
+ * // Default: web3 sensitive fields are redacted
10199
+ * const logger = createLogger({ level: 'info' })
10200
+ * logger.info('Signing', { privateKey: '0x123...' })
10201
+ * // Output: { context: { privateKey: '[REDACTED]' }, msg: 'Signing' }
10202
+ *
10203
+ * // Disable redaction (use with caution)
10204
+ * const unsafeLogger = createLogger({ level: 'debug', redact: false })
10205
+ *
10206
+ * // Custom redaction paths
10207
+ * const customLogger = createLogger({
10208
+ * level: 'info',
10209
+ * redact: ['context.mySecret', 'context.*.credentials']
10210
+ * })
10211
+ *
10212
+ * // Pretty output for development
10213
+ * const devLogger = createLogger({
10214
+ * level: 'debug',
10215
+ * transport: { target: 'pino-pretty' }
10216
+ * })
10217
+ *
10218
+ * // Browser logger
10219
+ * const browserLogger = createLogger({
10220
+ * browser: { asObject: true }
10221
+ * })
10222
+ * ```
10223
+ */ function createLogger(options, stream) {
10224
+ const { redact, ...pinoOptions } = options ?? {};
10225
+ // Build redaction config
10226
+ const redactConfig = buildRedactConfig(redact);
10227
+ // Build final pino options, only include redact if defined
10228
+ const finalOptions = redactConfig ? {
10229
+ ...pinoOptions,
10230
+ redact: redactConfig
10231
+ } : pinoOptions;
10232
+ const pinoInstance = pino(finalOptions);
10233
+ return wrapPino(pinoInstance);
10234
+ }
10235
+
9767
10236
  // ============================================================================
9768
10237
  // Validation Schema
9769
10238
  // ============================================================================
@@ -9843,6 +10312,186 @@ var TransferSpeed;
9843
10312
  clock: z.any().optional()
9844
10313
  }).passthrough();
9845
10314
 
10315
+ /**
10316
+ * Creates a Zod superRefine validator for recipient address format validation.
10317
+ * Validates that the address format matches the expected format for the chain type.
10318
+ *
10319
+ * @returns A superRefine function that validates recipientAddress against chain type
10320
+ */ function createRecipientAddressValidator() {
10321
+ return (data, ctx)=>{
10322
+ const chain = data.chain;
10323
+ if (chain === null) {
10324
+ return;
10325
+ }
10326
+ if (!isValidAddressForChain(data.recipientAddress, chain)) {
10327
+ const chainInfo = extractChainInfo(chain);
10328
+ ctx.addIssue({
10329
+ code: z.ZodIssueCode.custom,
10330
+ path: [
10331
+ 'recipientAddress'
10332
+ ],
10333
+ message: `Invalid address format for ${String(chainInfo.name)}. Expected ${chainInfo.expectedAddressFormat}, but received: ${data.recipientAddress}`
10334
+ });
10335
+ }
10336
+ };
10337
+ }
10338
+ /**
10339
+ * Schema for `BridgeParams.token`.
10340
+ *
10341
+ * Accept `'USDC'`, a symbol from {@link KNOWN_TOKEN_SYMBOLS}, or a bytes32 id
10342
+ * (`0x` plus exactly 64 hex characters). Reject unknown symbols, malformed ids,
10343
+ * and `{ provider, id }` objects. A custom extra provider cannot introduce a
10344
+ * new symbol through this field — only a bytes32 id.
10345
+ *
10346
+ * Omit the field to default to `'USDC'`.
10347
+ */ const bridgeTokenSchema = z.union([
10348
+ z.enum([
10349
+ 'USDC',
10350
+ ...KNOWN_TOKEN_SYMBOLS
10351
+ ]),
10352
+ z.string().regex(/^0x[0-9a-fA-F]{64}$/, 'Token id must be a bytes32 (0x-prefixed, 64 hex chars)')
10353
+ ]);
10354
+ /**
10355
+ * Schema for validating AdapterContext for bridge operations.
10356
+ * Must always contain both adapter and chain explicitly.
10357
+ *
10358
+ * Optionally includes address for developer-controlled adapters.
10359
+ */ const adapterContextSchema$3 = z.object({
10360
+ adapter: adapterSchema,
10361
+ chain: bridgeChainIdentifierSchema,
10362
+ address: z.string().optional()
10363
+ });
10364
+ /**
10365
+ * Schema for validating BridgeDestinationWithAddress objects.
10366
+ * Contains an explicit recipientAddress along with adapter and chain.
10367
+ * The address format is validated based on the chain type (EVM or Solana).
10368
+ */ const bridgeDestinationWithAddressSchema = adapterContextSchema$3.extend({
10369
+ recipientAddress: z.string().min(1, 'Recipient address is required'),
10370
+ useForwarder: z.boolean().optional()
10371
+ }).superRefine(createRecipientAddressValidator());
10372
+ /**
10373
+ * Schema for validating AdapterContext with optional useForwarder.
10374
+ * Extends adapterContextSchema with the useForwarder flag.
10375
+ */ const adapterContextWithForwarderSchema = adapterContextSchema$3.extend({
10376
+ useForwarder: z.boolean().optional()
10377
+ });
10378
+ /**
10379
+ * Schema for validating ForwarderDestination objects.
10380
+ * Used when useForwarder is true and no adapter is provided.
10381
+ * Requires chain, recipientAddress, and useForwarder: true.
10382
+ *
10383
+ * When using this destination type:
10384
+ * - The mint step completes when the IRIS API confirms forwardState === 'CONFIRMED'
10385
+ * - No on-chain transaction confirmation is performed (no adapter available)
10386
+ * - The mint step's data field will be undefined (no transaction receipt)
10387
+ */ const forwarderDestinationSchema = z.object({
10388
+ chain: bridgeChainIdentifierSchema,
10389
+ recipientAddress: z.string().min(1, 'Recipient address is required'),
10390
+ useForwarder: z.literal(true)
10391
+ }).strict().superRefine(createRecipientAddressValidator());
10392
+ /**
10393
+ * Schema for validating BridgeDestination union type.
10394
+ * Supports three destination configurations:
10395
+ * - BridgeDestinationWithAddress (adapter with explicit recipient)
10396
+ * - ForwarderDestination (no adapter, requires useForwarder: true and recipientAddress)
10397
+ * - AdapterContext with optional useForwarder (adapter for default recipient)
10398
+ *
10399
+ * When using ForwarderDestination (no adapter):
10400
+ * - The mint step completes when the IRIS API confirms forwardState === 'CONFIRMED'
10401
+ * - No on-chain transaction confirmation is performed
10402
+ *
10403
+ * The order matters: we check the more specific schemas first.
10404
+ * This ensures that objects with specific fields are matched correctly.
10405
+ */ const bridgeDestinationSchema = z.union([
10406
+ bridgeDestinationWithAddressSchema,
10407
+ forwarderDestinationSchema,
10408
+ adapterContextWithForwarderSchema.strict()
10409
+ ]);
10410
+ /**
10411
+ * Schema for validating bridge parameters with chain identifiers.
10412
+ * This extends the core provider's schema but adapts it for the bridge kit's
10413
+ * more flexible interface that accepts chain identifiers.
10414
+ *
10415
+ * The schema validates:
10416
+ * - From adapter context (must always include both adapter and chain)
10417
+ * - To bridge destination (AdapterContext or BridgeDestinationWithAddress)
10418
+ * - Amount is a non-empty numeric string \> 0
10419
+ * - Token is optional and defaults to 'USDC'
10420
+ * - Optional config parameters (transfer speed, max fee)
10421
+ *
10422
+ * @example
10423
+ * ```typescript
10424
+ * import { bridgeParamsWithChainIdentifierSchema } from '@circle-fin/bridge-kit'
10425
+ *
10426
+ * const params = {
10427
+ * from: {
10428
+ * adapter: sourceAdapter,
10429
+ * chain: 'Ethereum'
10430
+ * },
10431
+ * to: {
10432
+ * adapter: destAdapter,
10433
+ * chain: 'Base'
10434
+ * },
10435
+ * amount: '100.50',
10436
+ * token: 'USDC',
10437
+ * config: {
10438
+ * transferSpeed: 'FAST'
10439
+ * }
10440
+ * }
10441
+ *
10442
+ * const result = bridgeParamsWithChainIdentifierSchema.safeParse(params)
10443
+ * if (result.success) {
10444
+ * console.log('Parameters are valid')
10445
+ * } else {
10446
+ * console.error('Validation failed:', result.error)
10447
+ * }
10448
+ * ```
10449
+ */ z.object({
10450
+ from: adapterContextSchema$3.strict(),
10451
+ to: bridgeDestinationSchema,
10452
+ amount: z.string().min(1, 'Required').pipe(createDecimalStringValidator({
10453
+ allowZero: false,
10454
+ regexMessage: AMOUNT_FORMAT_ERROR_MESSAGE,
10455
+ attributeName: 'amount',
10456
+ // Widest precision any routable token needs (wETH = 18). This gate is
10457
+ // token-agnostic and runs before the route provider is known, so it
10458
+ // can only cap coarsely; the token's exact precision is enforced later
10459
+ // at the scaling boundary (`BridgeKit.scaleResolvedAmount`). USDC (6)
10460
+ // and every narrower token stay valid.
10461
+ maxDecimals: 18
10462
+ })(z.string())),
10463
+ token: bridgeTokenSchema.optional(),
10464
+ config: z.object({
10465
+ transferSpeed: z.nativeEnum(TransferSpeed).optional(),
10466
+ feePayment: z.enum([
10467
+ 'source',
10468
+ 'destination'
10469
+ ]).optional(),
10470
+ maxFee: z.string().min(1, 'Required').pipe(createDecimalStringValidator({
10471
+ allowZero: true,
10472
+ regexMessage: MAX_FEE_FORMAT_ERROR_MESSAGE,
10473
+ attributeName: 'maxFee',
10474
+ // See `amount` above: widest routable precision (18); the exact
10475
+ // per-token precision is enforced at the scaling boundary.
10476
+ maxDecimals: 18
10477
+ })(z.string())).optional(),
10478
+ customFee: customFeeSchema.optional()
10479
+ }).optional(),
10480
+ // Top-level (not nested under `config`) to mirror `BridgeParams.quote`.
10481
+ //
10482
+ // `z.unknown()` rather than a shape: the quote belongs to whichever provider
10483
+ // issued it, and a route is matched to a provider only after these
10484
+ // parameters are validated, so there is no one shape to check here.
10485
+ //
10486
+ // It also keeps the value intact. This object strips unknown keys, so a
10487
+ // nested `z.object()` would clone the quote and drop every key not listed —
10488
+ // losing a field the issuing provider added, between `estimate` and
10489
+ // `bridge`. Shape is checked where the quote is consumed instead: CCTPx
10490
+ // against its own envelope schema, and the receive-exact path in
10491
+ // `sourceFees.ts` before it calls the Fee Service.
10492
+ quote: z.unknown().optional()
10493
+ });
10494
+
9846
10495
  /**
9847
10496
  * The ASCII "cctp-forward" magic, hex-encoded (no `0x`), that a forward-friendly
9848
10497
  * hookData must start with.
@@ -9871,6 +10520,9 @@ var TransferSpeed;
9871
10520
  [TransferSpeed.SLOW]: 2000
9872
10521
  });
9873
10522
 
10523
+ createLogger({
10524
+ name: 'provider-cctp-v2'
10525
+ });
9874
10526
  /**
9875
10527
  * All chains that are supported by the CCTP v2 provider.
9876
10528
  *
@@ -9880,7 +10532,11 @@ var TransferSpeed;
9880
10532
  * @internal
9881
10533
  */ Object.values(Chains).filter((chain)=>isCCTPV2Supported(chain));
9882
10534
 
9883
- /** Decimal string in token minor units, constrained to be strictly positive. */ const positiveAmountSchema = z.string().regex(/^\d+$/, 'must be a non-negative integer string')// Re-check the digit shape here: zod still runs this refinement when the
10535
+ /**
10536
+ * Decimal string in token minor units, constrained to be strictly positive.
10537
+ *
10538
+ * @internal
10539
+ */ const positiveAmountSchema = z.string().regex(/^\d+$/, 'must be a non-negative integer string')// Re-check the digit shape here: zod still runs this refinement when the
9884
10540
  // regex check above fails ("dirty"), so guard BigInt() against throwing on a
9885
10541
  // non-numeric value before comparing.
9886
10542
  .refine((value)=>/^\d+$/.test(value) && BigInt(value) > 0n, 'must be greater than zero');
@@ -9915,11 +10571,19 @@ const forwardRequestSchema = z.object({
9915
10571
  const preFinalityRequestSchema = z.object({
9916
10572
  type: z.literal('PRE_FINALITY')
9917
10573
  }).strict();
9918
- /** A single quote request item (`FORWARD` or `PRE_FINALITY`). */ const feeQuoteRequestSchema = z.discriminatedUnion('type', [
10574
+ /**
10575
+ * A single quote request item (`FORWARD` or `PRE_FINALITY`).
10576
+ *
10577
+ * @internal
10578
+ */ const feeQuoteRequestSchema = z.discriminatedUnion('type', [
9919
10579
  forwardRequestSchema,
9920
10580
  preFinalityRequestSchema
9921
10581
  ]);
9922
- /** A non-empty list of quote request items with unique types. */ const feeQuoteRequestsSchema = z.array(feeQuoteRequestSchema).min(1, 'at least one request item is required').refine((items)=>new Set(items.map((item)=>item.type)).size === items.length, 'request item types must be unique');
10582
+ /**
10583
+ * A non-empty list of quote request items with unique types.
10584
+ *
10585
+ * @internal
10586
+ */ const feeQuoteRequestsSchema = z.array(feeQuoteRequestSchema).min(1, 'at least one request item is required').refine((items)=>new Set(items.map((item)=>item.type)).size === items.length, 'request item types must be unique');
9923
10587
  /**
9924
10588
  * A structured `Partial<ApiPollingConfig>` polling override.
9925
10589
  *
@@ -9947,6 +10611,8 @@ const preFinalityRequestSchema = z.object({
9947
10611
  * it `undefined`, which is falsy and silently selects the production base URL.
9948
10612
  * (`buildFeeQuoteUrl` independently re-validates the domains for standalone
9949
10613
  * callers.)
10614
+ *
10615
+ * @internal
9950
10616
  */ z.object({
9951
10617
  sourceDomain: z.number().int().nonnegative(),
9952
10618
  destinationDomain: z.number().int().nonnegative(),
@@ -9982,7 +10648,11 @@ const metadataSchema = z.object({
9982
10648
  blockEstimatedAt: z.number().int().nonnegative().optional()
9983
10649
  }).passthrough()
9984
10650
  ]);
9985
- /** Schema for a signed fee quote returned by the Quote API. */ z.object({
10651
+ /**
10652
+ * Schema for a signed fee quote returned by the Quote API.
10653
+ *
10654
+ * @internal
10655
+ */ z.object({
9986
10656
  // The runtime YAML spec maps signedQuote to a looser `hex` (which allows
9987
10657
  // an empty `0x`); we keep the stricter non-empty form. Do not relax
9988
10658
  // without a reason.
@@ -9996,7 +10666,11 @@ const metadataSchema = z.object({
9996
10666
  items: z.array(feeQuoteItemSchema),
9997
10667
  metadata: metadataSchema.optional()
9998
10668
  }).passthrough();
9999
- /** Validate input to {@link validateQuote}. */ z.object({
10669
+ /**
10670
+ * Validates input to {@link validateQuote}.
10671
+ *
10672
+ * @internal
10673
+ */ z.object({
10000
10674
  sourceDomain: z.number().int().nonnegative(),
10001
10675
  abiSignature: z.string().min(1),
10002
10676
  args: z.array(z.union([
@@ -10031,11 +10705,13 @@ const validateQuoteItemSchema = z.object({
10031
10705
  computedArgsHash: bytes32Schema.optional()
10032
10706
  }).passthrough();
10033
10707
  /**
10034
- * Schema for a response from the Quote API validation endpoint.
10708
+ * Schema for a validate-quote result returned by the Iris `/validate/usdc/:sourceDomain` endpoint.
10035
10709
  *
10036
10710
  * The endpoint takes the source domain as a URL path parameter and does not
10037
10711
  * return it in the response body, so `sourceDomain` is intentionally not part
10038
10712
  * of this schema.
10713
+ *
10714
+ * @internal
10039
10715
  */ z.object({
10040
10716
  signedQuote: nonEmptyHexSchema,
10041
10717
  expiry: quoteExpiryStatusSchema,
@@ -10055,7 +10731,7 @@ const validateQuoteItemSchema = z.object({
10055
10731
  registerKit(`${pkg$3.name}/${pkg$3.version}`);
10056
10732
 
10057
10733
  var name$2 = "@circle-fin/swap-kit";
10058
- var version$2 = "1.6.0";
10734
+ var version$2 = "1.7.0";
10059
10735
  var pkg$2 = {
10060
10736
  name: name$2,
10061
10737
  version: version$2};
@@ -12219,6 +12895,11 @@ createTokenRegistry();
12219
12895
  name: 'USDC',
12220
12896
  version: '2'
12221
12897
  },
12898
+ Arc: {
12899
+ chainId: Arc.chainId,
12900
+ name: 'USDC',
12901
+ version: '2'
12902
+ },
12222
12903
  Arc_Testnet: {
12223
12904
  chainId: ArcTestnet.chainId,
12224
12905
  name: 'USDC',
@@ -13754,7 +14435,7 @@ new Set(Object.values(Blockchain));
13754
14435
  registerKit(`${pkg$2.name}/${pkg$2.version}`);
13755
14436
 
13756
14437
  var name$1 = "@circle-fin/earn-kit";
13757
- var version$1 = "1.6.0";
14438
+ var version$1 = "1.7.0";
13758
14439
  var pkg$1 = {
13759
14440
  name: name$1,
13760
14441
  version: version$1};
@@ -13782,18 +14463,22 @@ const EARN_BRIDGE_ERC3009_TOKEN_SYMBOLS = [
13782
14463
  *
13783
14464
  * @internal
13784
14465
  */ const CHAIN_TO_API = {
14466
+ [Blockchain.Arc]: 'ARC',
13785
14467
  [Blockchain.Arc_Testnet]: 'ARC-TESTNET'
13786
14468
  };
13787
14469
  /**
13788
14470
  * Map SDK source chain identifiers to bridge source-chain strings.
13789
14471
  *
13790
- * Cross-chain Earn deposits currently support Ethereum Sepolia, Arbitrum
13791
- * Sepolia, and Base Sepolia as source chains.
14472
+ * Cross-chain Earn deposits support Ethereum, Arbitrum, and Base (mainnet
14473
+ * and testnet) as source chains.
13792
14474
  *
13793
14475
  * @internal
13794
14476
  */ const EARN_BRIDGE_SOURCE_CHAIN_TO_API = {
14477
+ [Blockchain.Arbitrum]: 'ARB',
13795
14478
  [Blockchain.Arbitrum_Sepolia]: 'ARB-SEPOLIA',
14479
+ [Blockchain.Base]: 'BASE',
13796
14480
  [Blockchain.Base_Sepolia]: 'BASE-SEPOLIA',
14481
+ [Blockchain.Ethereum]: 'ETH',
13797
14482
  [Blockchain.Ethereum_Sepolia]: 'ETH-SEPOLIA'
13798
14483
  };
13799
14484
  /**
@@ -13804,17 +14489,30 @@ const EARN_BRIDGE_ERC3009_TOKEN_SYMBOLS = [
13804
14489
  *
13805
14490
  * @internal
13806
14491
  */ const EARN_BRIDGE_DESTINATION_CHAIN_TO_API = {
14492
+ [Blockchain.Arc]: CHAIN_TO_API[Blockchain.Arc],
13807
14493
  [Blockchain.Arc_Testnet]: CHAIN_TO_API[Blockchain.Arc_Testnet]
13808
14494
  };
13809
14495
  const EARN_BRIDGE_USDC_ERC3009_DOMAINS = {
14496
+ [Blockchain.Arbitrum]: {
14497
+ name: 'USD Coin',
14498
+ version: '2'
14499
+ },
13810
14500
  [Blockchain.Arbitrum_Sepolia]: {
13811
14501
  name: 'USD Coin',
13812
14502
  version: '2'
13813
14503
  },
14504
+ [Blockchain.Base]: {
14505
+ name: 'USD Coin',
14506
+ version: '2'
14507
+ },
13814
14508
  [Blockchain.Base_Sepolia]: {
13815
14509
  name: 'USDC',
13816
14510
  version: '2'
13817
14511
  },
14512
+ [Blockchain.Ethereum]: {
14513
+ name: 'USD Coin',
14514
+ version: '2'
14515
+ },
13818
14516
  [Blockchain.Ethereum_Sepolia]: {
13819
14517
  name: 'USDC',
13820
14518
  version: '2'
@@ -16658,7 +17356,7 @@ const bridgeDepositPrepareReviewSchema = z.object({
16658
17356
  }
16659
17357
 
16660
17358
  var name = "@circle-fin/provider-earn-service";
16661
- var version = "1.5.0";
17359
+ var version = "1.6.0";
16662
17360
  var pkg = {
16663
17361
  name: name,
16664
17362
  version: version};