@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/estimateSwap.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 { hexlify, hexZeroPad } from '@ethersproject/bytes';
33
33
  import '@ethersproject/abi';
34
34
  import { getAddress } from '@ethersproject/address';
@@ -726,6 +726,38 @@ class KitError extends Error {
726
726
  name: 'INPUT_AMOUNT_OUT_OF_RANGE',
727
727
  type: 'INPUT'
728
728
  },
729
+ /**
730
+ * Protocol fee is denominated in a token that is not supported for the
731
+ * route (only the native gas token and the route's supported fee tokens,
732
+ * such as USDC, are accepted).
733
+ */ UNSUPPORTED_FEE_TOKEN: {
734
+ code: 1014,
735
+ name: 'INPUT_UNSUPPORTED_FEE_TOKEN',
736
+ type: 'INPUT'
737
+ },
738
+ /** Retry / resume is not supported by this provider for the given result */ RETRY_NOT_SUPPORTED: {
739
+ code: 1015,
740
+ name: 'INPUT_RETRY_NOT_SUPPORTED',
741
+ type: 'INPUT'
742
+ },
743
+ /** Bridge-step analysis for retry is not supported by this provider */ STEP_ANALYSIS_NOT_SUPPORTED: {
744
+ code: 1016,
745
+ name: 'INPUT_STEP_ANALYSIS_NOT_SUPPORTED',
746
+ type: 'INPUT'
747
+ },
748
+ /**
749
+ * A kit operation name collides with a reserved event-subscription
750
+ * method (`on` / `off`) at kit construction.
751
+ */ RESERVED_OPERATION_NAME: {
752
+ code: 1000,
753
+ name: 'INPUT_RESERVED_OPERATION_NAME',
754
+ type: 'INPUT'
755
+ },
756
+ /** A kit was constructed with a missing / undefined operation factory */ MISSING_OPERATION: {
757
+ code: 1017,
758
+ name: 'INPUT_MISSING_OPERATION',
759
+ type: 'INPUT'
760
+ },
729
761
  /** General validation failure for complex validation rules */ VALIDATION_FAILED: {
730
762
  code: 1098,
731
763
  name: 'INPUT_VALIDATION_FAILED',
@@ -936,8 +968,7 @@ class KitError extends Error {
936
968
  code: 8002,
937
969
  name: 'SERVICE_UNKNOWN_ERROR',
938
970
  type: 'SERVICE'
939
- }
940
- };
971
+ }};
941
972
 
942
973
  /**
943
974
  * Creates error for unsupported swap route.
@@ -1164,7 +1195,7 @@ class KitError extends Error {
1164
1195
  * import { createValidationErrorFromZod } from '@core/errors'
1165
1196
  *
1166
1197
  * function validateBridgeParams(params: unknown): asserts params is BridgeParams {
1167
- * const result = bridgeParamsSchema.safeParse(params)
1198
+ * const result = usdcBridgeParamsSchema.safeParse(params)
1168
1199
  * if (!result.success) {
1169
1200
  * throw createValidationErrorFromZod(result.error, 'bridge parameters')
1170
1201
  * }
@@ -2942,9 +2973,10 @@ class KitError extends Error {
2942
2973
  Blockchain["Algorand_Testnet"] = "Algorand_Testnet";
2943
2974
  Blockchain["Aptos"] = "Aptos";
2944
2975
  Blockchain["Aptos_Testnet"] = "Aptos_Testnet";
2945
- Blockchain["Arc_Testnet"] = "Arc_Testnet";
2946
2976
  Blockchain["Arbitrum"] = "Arbitrum";
2947
2977
  Blockchain["Arbitrum_Sepolia"] = "Arbitrum_Sepolia";
2978
+ Blockchain["Arc"] = "Arc";
2979
+ Blockchain["Arc_Testnet"] = "Arc_Testnet";
2948
2980
  Blockchain["Avalanche"] = "Avalanche";
2949
2981
  Blockchain["Avalanche_Fuji"] = "Avalanche_Fuji";
2950
2982
  Blockchain["Base"] = "Base";
@@ -3031,6 +3063,7 @@ var SwapChain;
3031
3063
  SwapChain["XDC"] = "XDC";
3032
3064
  SwapChain["HyperEVM"] = "HyperEVM";
3033
3065
  SwapChain["Monad"] = "Monad";
3066
+ SwapChain["Arc"] = "Arc";
3034
3067
  // Testnet chains with swap support
3035
3068
  SwapChain["Arc_Testnet"] = "Arc_Testnet";
3036
3069
  })(SwapChain || (SwapChain = {}));
@@ -3038,6 +3071,7 @@ var BridgeChain;
3038
3071
  (function(BridgeChain) {
3039
3072
  // Mainnet chains with CCTPv2 support
3040
3073
  BridgeChain["Arbitrum"] = "Arbitrum";
3074
+ BridgeChain["Arc"] = "Arc";
3041
3075
  BridgeChain["Avalanche"] = "Avalanche";
3042
3076
  BridgeChain["Base"] = "Base";
3043
3077
  BridgeChain["Codex"] = "Codex";
@@ -3093,6 +3127,7 @@ var BridgeChain;
3093
3127
  var UnifiedBalanceChain;
3094
3128
  (function(UnifiedBalanceChain) {
3095
3129
  // Mainnet chains with Gateway V1 support
3130
+ UnifiedBalanceChain["Arc"] = "Arc";
3096
3131
  UnifiedBalanceChain["Arbitrum"] = "Arbitrum";
3097
3132
  UnifiedBalanceChain["Avalanche"] = "Avalanche";
3098
3133
  UnifiedBalanceChain["Base"] = "Base";
@@ -3122,6 +3157,7 @@ var UnifiedBalanceChain;
3122
3157
  })(UnifiedBalanceChain || (UnifiedBalanceChain = {}));
3123
3158
  var EarnChain;
3124
3159
  (function(EarnChain) {
3160
+ EarnChain["Arc"] = "Arc";
3125
3161
  EarnChain["Arc_Testnet"] = "Arc_Testnet";
3126
3162
  })(EarnChain || (EarnChain = {}));
3127
3163
  /**
@@ -3138,8 +3174,11 @@ var EarnChain;
3138
3174
  * console.log(EARN_BRIDGE_SOURCE_BLOCKCHAINS.join(', '))
3139
3175
  * ```
3140
3176
  */ const EARN_BRIDGE_SOURCE_BLOCKCHAINS = [
3177
+ "Arbitrum",
3141
3178
  "Arbitrum_Sepolia",
3179
+ "Base",
3142
3180
  "Base_Sepolia",
3181
+ "Ethereum",
3143
3182
  "Ethereum_Sepolia"
3144
3183
  ];
3145
3184
  /**
@@ -3153,6 +3192,7 @@ var EarnChain;
3153
3192
  * console.log(EARN_BRIDGE_DESTINATION_BLOCKCHAINS.join(', '))
3154
3193
  * ```
3155
3194
  */ const EARN_BRIDGE_DESTINATION_BLOCKCHAINS = [
3195
+ "Arc",
3156
3196
  "Arc_Testnet"
3157
3197
  ];
3158
3198
 
@@ -3469,6 +3509,25 @@ var EarnChain;
3469
3509
  * EVM-compatible chains. Use this address when deploying or testing
3470
3510
  * cross-chain USDC transfers on test networks.
3471
3511
  */ const BRIDGE_CONTRACT_EVM_TESTNET = '0xC5567a5E3370d4DBfB0540025078e283e36A363d';
3512
+ /**
3513
+ * The CrossChainTokenService (CCTPx) service address for EVM testnet networks.
3514
+ *
3515
+ * This service coordinates CCTPx cross-chain token operations on testnet
3516
+ * environments and is shared by every EVM test network CCTPx supports. Read the
3517
+ * chain definitions via `isCCTPXSupported` rather than trusting a list here,
3518
+ * which goes stale as deployments land.
3519
+ */ const CCTPX_SERVICE_ADDRESS_EVM_TESTNET = '0x63753E722bd2C2A5DF6EE19C5106662208B81077';
3520
+ /**
3521
+ * CrossChainTokenService (CCTS) proxy address for CCTPx on EVM **mainnet**.
3522
+ *
3523
+ * @remarks
3524
+ * A distinct deployment from {@link CCTPX_SERVICE_ADDRESS_EVM_TESTNET}, shared
3525
+ * by every EVM mainnet chain that CCTPx supports. A chain becomes
3526
+ * CCTPx-eligible only once its definition carries this as
3527
+ * `cctpx.serviceAddress`, and a route additionally needs both of its endpoints
3528
+ * eligible — so adding a chain here is the deliberate, reviewable step that
3529
+ * opens mainnet CCTPx for it.
3530
+ */ const CCTPX_SERVICE_ADDRESS_EVM_MAINNET = '0x431871229103b780868f8C6BB820cd16ECf942BC';
3472
3531
  /**
3473
3532
  * The bridge contract address for EVM mainnet networks.
3474
3533
  *
@@ -3537,8 +3596,115 @@ var EarnChain;
3537
3596
  * This program handles minting operations for Gateway transactions
3538
3597
  * on Solana devnet.
3539
3598
  */ const GATEWAY_MINTER_SOLANA_DEVNET = 'GATEmKK2ECL1brEngQZWCgMWPbvrEYqsV6u29dAaHavr';
3540
- /** TokenMessengerWithFees address shared by enabled EVM mainnet sources. */ const TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET = '0x71f54F818671cD0D7ea140Da213e5C8b5C92a408';
3541
- /** TokenMessengerWithFees address shared by enabled EVM testnet sources. */ const TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET = '0x8745D906D67C346E5eb1aEEED38Eb87F34DF0C0A';
3599
+ /**
3600
+ * The `TokenMessengerWithFees` proxy contract address for EVM mainnet networks
3601
+ * (all chains except Edge).
3602
+ *
3603
+ * Deployed at a CREATE3-derived address; identical across all mainnet EVM
3604
+ * source chains. Present on any chain that supports the prepaid FORWARD path
3605
+ * via `depositForBurnWithHookAndFees`.
3606
+ */ const TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET = '0x71f54F818671cD0D7ea140Da213e5C8b5C92a408';
3607
+ /**
3608
+ * The `TokenMessengerWithFees` proxy contract address for EVM testnet networks.
3609
+ *
3610
+ * Identical across all testnet EVM source chains. Present on any testnet chain
3611
+ * that supports the prepaid FORWARD path via `depositForBurnWithHookAndFees`.
3612
+ */ const TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET = '0x8745D906D67C346E5eb1aEEED38Eb87F34DF0C0A';
3613
+ /**
3614
+ * The `DepositForHandler` proxy contract address for EVM mainnet networks.
3615
+ *
3616
+ * The handler the GenericExecutor calls on a fast-deposit destination chain to
3617
+ * run a cross-chain deposit into the GatewayWallet. Deployed at the same
3618
+ * address across all mainnet EVM destination chains.
3619
+ */ const DEPOSIT_FOR_HANDLER_EVM_MAINNET = '0x16529813203f77E036576666336554a1210dce4D';
3620
+ /**
3621
+ * The `DepositForHandler` proxy contract address for EVM testnet networks.
3622
+ *
3623
+ * Identical across all testnet EVM destination chains.
3624
+ */ const DEPOSIT_FOR_HANDLER_EVM_TESTNET = '0xD05E7D2E7d30b92c5F17d7d0fC575fce231F1A48';
3625
+ /**
3626
+ * The `GenericExecutor` proxy contract address for EVM mainnet networks.
3627
+ *
3628
+ * The GenericExecutor is the `mintRecipient` and `destinationCaller` on the
3629
+ * destination chain for the CCTP v2 prepaid FORWARD path. It receives the CCTP
3630
+ * mint and calls the `DepositForHandler` to complete the fast deposit.
3631
+ * Deployed at the same address across all mainnet EVM destination chains.
3632
+ */ const GENERIC_EXECUTOR_EVM_MAINNET = '0xFa7be2f04F3Ad4ca969260729c6d45B5625984A7';
3633
+ /**
3634
+ * The `GenericExecutor` proxy contract address for EVM testnet networks.
3635
+ *
3636
+ * Identical across all testnet EVM destination chains.
3637
+ */ const GENERIC_EXECUTOR_EVM_TESTNET = '0xEdC81040756AcCfF070c21D37b265b9D0b5Ba45e';
3638
+
3639
+ /**
3640
+ * Arc Mainnet chain definition
3641
+ * @remarks
3642
+ * This represents the official production network for the Arc blockchain,
3643
+ * Circle's EVM-compatible Layer-1 designed for stablecoin finance
3644
+ * and asset tokenization. Arc uses USDC as the native gas token and
3645
+ * features the Malachite Byzantine Fault Tolerant (BFT) consensus
3646
+ * engine for sub-second finality.
3647
+ */ const Arc = defineChain({
3648
+ type: 'evm',
3649
+ chain: Blockchain.Arc,
3650
+ name: 'Arc',
3651
+ title: 'Arc Mainnet',
3652
+ nativeCurrency: {
3653
+ name: 'USDC',
3654
+ symbol: 'USDC',
3655
+ // Arc uses native USDC with 18 decimals for gas payments (EVM standard).
3656
+ // Note: The ERC-20 USDC contract at usdcAddress uses 6 decimals.
3657
+ // See: https://docs.arc.network/arc/references/contract-addresses
3658
+ decimals: 18
3659
+ },
3660
+ chainId: 5042,
3661
+ isTestnet: false,
3662
+ explorerUrl: 'https://explorer.arc.io/tx/{hash}',
3663
+ rpcEndpoints: [
3664
+ 'https://rpc.mainnet.arc.io/'
3665
+ ],
3666
+ eurcAddress: '0xbEf5f6d51CB62b58e6A8f77868681825C6fe21c1',
3667
+ usdcAddress: '0x3600000000000000000000000000000000000000',
3668
+ usdtAddress: null,
3669
+ cctp: {
3670
+ domain: 26,
3671
+ contracts: {
3672
+ v2: {
3673
+ type: 'split',
3674
+ tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
3675
+ messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
3676
+ confirmations: 1,
3677
+ fastConfirmations: 1
3678
+ }
3679
+ },
3680
+ forwarderSupported: {
3681
+ source: false,
3682
+ destination: true
3683
+ }
3684
+ },
3685
+ cctpx: {
3686
+ serviceAddress: CCTPX_SERVICE_ADDRESS_EVM_MAINNET
3687
+ },
3688
+ kitContracts: {
3689
+ bridge: BRIDGE_CONTRACT_EVM_MAINNET,
3690
+ adapter: ADAPTER_CONTRACT_EVM_MAINNET
3691
+ },
3692
+ gateway: {
3693
+ domain: 26,
3694
+ contracts: {
3695
+ v1: {
3696
+ wallet: GATEWAY_WALLET_EVM_MAINNET,
3697
+ minter: GATEWAY_MINTER_EVM_MAINNET,
3698
+ depositForHandler: DEPOSIT_FOR_HANDLER_EVM_MAINNET,
3699
+ genericExecutor: GENERIC_EXECUTOR_EVM_MAINNET
3700
+ }
3701
+ },
3702
+ forwarderSupported: {
3703
+ source: true,
3704
+ destination: true
3705
+ }
3706
+ }
3707
+ });
3542
3708
 
3543
3709
  /**
3544
3710
  * Arc Testnet chain definition
@@ -3587,6 +3753,9 @@ var EarnChain;
3587
3753
  destination: true
3588
3754
  }
3589
3755
  },
3756
+ cctpx: {
3757
+ serviceAddress: CCTPX_SERVICE_ADDRESS_EVM_TESTNET
3758
+ },
3590
3759
  kitContracts: {
3591
3760
  bridge: BRIDGE_CONTRACT_EVM_TESTNET,
3592
3761
  adapter: ADAPTER_CONTRACT_EVM_TESTNET
@@ -3597,9 +3766,8 @@ var EarnChain;
3597
3766
  v1: {
3598
3767
  wallet: GATEWAY_WALLET_EVM_TESTNET,
3599
3768
  minter: GATEWAY_MINTER_EVM_TESTNET,
3600
- // DepositForHandler the GenericExecutor calls to run a fast cross-chain
3601
- // deposit into the GatewayWallet above.
3602
- depositForHandler: '0xD05E7D2E7d30b92c5F17d7d0fC575fce231F1A48'
3769
+ depositForHandler: DEPOSIT_FOR_HANDLER_EVM_TESTNET,
3770
+ genericExecutor: GENERIC_EXECUTOR_EVM_TESTNET
3603
3771
  }
3604
3772
  },
3605
3773
  forwarderSupported: {
@@ -3655,6 +3823,9 @@ var EarnChain;
3655
3823
  destination: true
3656
3824
  }
3657
3825
  },
3826
+ cctpx: {
3827
+ serviceAddress: CCTPX_SERVICE_ADDRESS_EVM_MAINNET
3828
+ },
3658
3829
  kitContracts: {
3659
3830
  bridge: BRIDGE_CONTRACT_EVM_MAINNET,
3660
3831
  adapter: ADAPTER_CONTRACT_EVM_MAINNET
@@ -3720,6 +3891,9 @@ var EarnChain;
3720
3891
  destination: true
3721
3892
  }
3722
3893
  },
3894
+ cctpx: {
3895
+ serviceAddress: CCTPX_SERVICE_ADDRESS_EVM_TESTNET
3896
+ },
3723
3897
  kitContracts: {
3724
3898
  bridge: BRIDGE_CONTRACT_EVM_TESTNET,
3725
3899
  adapter: ADAPTER_CONTRACT_EVM_TESTNET
@@ -3785,6 +3959,9 @@ var EarnChain;
3785
3959
  destination: true
3786
3960
  }
3787
3961
  },
3962
+ cctpx: {
3963
+ serviceAddress: CCTPX_SERVICE_ADDRESS_EVM_MAINNET
3964
+ },
3788
3965
  kitContracts: {
3789
3966
  bridge: BRIDGE_CONTRACT_EVM_MAINNET,
3790
3967
  adapter: ADAPTER_CONTRACT_EVM_MAINNET
@@ -3794,7 +3971,9 @@ var EarnChain;
3794
3971
  contracts: {
3795
3972
  v1: {
3796
3973
  wallet: GATEWAY_WALLET_EVM_MAINNET,
3797
- minter: GATEWAY_MINTER_EVM_MAINNET
3974
+ minter: GATEWAY_MINTER_EVM_MAINNET,
3975
+ depositForHandler: DEPOSIT_FOR_HANDLER_EVM_MAINNET,
3976
+ genericExecutor: GENERIC_EXECUTOR_EVM_MAINNET
3798
3977
  }
3799
3978
  },
3800
3979
  forwarderSupported: {
@@ -3850,6 +4029,9 @@ var EarnChain;
3850
4029
  rpcEndpoints: [
3851
4030
  'https://api.avax-test.network/ext/bc/C/rpc'
3852
4031
  ],
4032
+ cctpx: {
4033
+ serviceAddress: CCTPX_SERVICE_ADDRESS_EVM_TESTNET
4034
+ },
3853
4035
  kitContracts: {
3854
4036
  bridge: BRIDGE_CONTRACT_EVM_TESTNET
3855
4037
  },
@@ -3858,7 +4040,9 @@ var EarnChain;
3858
4040
  contracts: {
3859
4041
  v1: {
3860
4042
  wallet: GATEWAY_WALLET_EVM_TESTNET,
3861
- minter: GATEWAY_MINTER_EVM_TESTNET
4043
+ minter: GATEWAY_MINTER_EVM_TESTNET,
4044
+ depositForHandler: DEPOSIT_FOR_HANDLER_EVM_TESTNET,
4045
+ genericExecutor: GENERIC_EXECUTOR_EVM_TESTNET
3862
4046
  }
3863
4047
  },
3864
4048
  forwarderSupported: {
@@ -3915,6 +4099,9 @@ var EarnChain;
3915
4099
  destination: true
3916
4100
  }
3917
4101
  },
4102
+ cctpx: {
4103
+ serviceAddress: CCTPX_SERVICE_ADDRESS_EVM_MAINNET
4104
+ },
3918
4105
  kitContracts: {
3919
4106
  bridge: BRIDGE_CONTRACT_EVM_MAINNET,
3920
4107
  adapter: ADAPTER_CONTRACT_EVM_MAINNET
@@ -3980,6 +4167,9 @@ var EarnChain;
3980
4167
  destination: true
3981
4168
  }
3982
4169
  },
4170
+ cctpx: {
4171
+ serviceAddress: CCTPX_SERVICE_ADDRESS_EVM_TESTNET
4172
+ },
3983
4173
  kitContracts: {
3984
4174
  bridge: BRIDGE_CONTRACT_EVM_TESTNET,
3985
4175
  adapter: ADAPTER_CONTRACT_EVM_TESTNET
@@ -4171,6 +4361,7 @@ var EarnChain;
4171
4361
  v2: {
4172
4362
  type: 'split',
4173
4363
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
4364
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
4174
4365
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
4175
4366
  confirmations: 1,
4176
4367
  fastConfirmations: 1
@@ -4216,6 +4407,7 @@ var EarnChain;
4216
4407
  v2: {
4217
4408
  type: 'split',
4218
4409
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
4410
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4219
4411
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
4220
4412
  confirmations: 1,
4221
4413
  fastConfirmations: 1
@@ -4261,6 +4453,7 @@ var EarnChain;
4261
4453
  v2: {
4262
4454
  type: 'split',
4263
4455
  tokenMessenger: '0x98706A006bc632Df31CAdFCBD43F38887ce2ca5c',
4456
+ tokenMessengerWithFees: '0x3Ac96675F9a3E6922713e041645D82f3561d3686',
4264
4457
  messageTransmitter: '0x5b61381Fc9e58E70EfC13a4A97516997019198ee',
4265
4458
  confirmations: 65,
4266
4459
  fastConfirmations: 1
@@ -4306,6 +4499,7 @@ var EarnChain;
4306
4499
  v2: {
4307
4500
  type: 'split',
4308
4501
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
4502
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4309
4503
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
4310
4504
  confirmations: 65,
4311
4505
  fastConfirmations: 1
@@ -4368,6 +4562,9 @@ var EarnChain;
4368
4562
  destination: true
4369
4563
  }
4370
4564
  },
4565
+ cctpx: {
4566
+ serviceAddress: CCTPX_SERVICE_ADDRESS_EVM_MAINNET
4567
+ },
4371
4568
  kitContracts: {
4372
4569
  bridge: BRIDGE_CONTRACT_EVM_MAINNET,
4373
4570
  adapter: ADAPTER_CONTRACT_EVM_MAINNET
@@ -4433,6 +4630,9 @@ var EarnChain;
4433
4630
  destination: true
4434
4631
  }
4435
4632
  },
4633
+ cctpx: {
4634
+ serviceAddress: CCTPX_SERVICE_ADDRESS_EVM_TESTNET
4635
+ },
4436
4636
  kitContracts: {
4437
4637
  bridge: BRIDGE_CONTRACT_EVM_TESTNET,
4438
4638
  adapter: ADAPTER_CONTRACT_EVM_TESTNET
@@ -4654,6 +4854,7 @@ var EarnChain;
4654
4854
  v2: {
4655
4855
  type: 'split',
4656
4856
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
4857
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
4657
4858
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
4658
4859
  confirmations: 1,
4659
4860
  fastConfirmations: 1
@@ -4701,6 +4902,7 @@ var EarnChain;
4701
4902
  v2: {
4702
4903
  type: 'split',
4703
4904
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
4905
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4704
4906
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
4705
4907
  confirmations: 1,
4706
4908
  fastConfirmations: 1
@@ -4982,6 +5184,7 @@ var EarnChain;
4982
5184
  v2: {
4983
5185
  type: 'split',
4984
5186
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
5187
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4985
5188
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
4986
5189
  confirmations: 1,
4987
5190
  fastConfirmations: 1
@@ -5027,6 +5230,7 @@ var EarnChain;
5027
5230
  v2: {
5028
5231
  type: 'split',
5029
5232
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
5233
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
5030
5234
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
5031
5235
  confirmations: 64,
5032
5236
  fastConfirmations: 1
@@ -5072,6 +5276,7 @@ var EarnChain;
5072
5276
  v2: {
5073
5277
  type: 'split',
5074
5278
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
5279
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
5075
5280
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
5076
5281
  confirmations: 64,
5077
5282
  fastConfirmations: 1
@@ -5259,6 +5464,9 @@ var EarnChain;
5259
5464
  destination: true
5260
5465
  }
5261
5466
  },
5467
+ cctpx: {
5468
+ serviceAddress: CCTPX_SERVICE_ADDRESS_EVM_MAINNET
5469
+ },
5262
5470
  kitContracts: {
5263
5471
  bridge: BRIDGE_CONTRACT_EVM_MAINNET,
5264
5472
  adapter: ADAPTER_CONTRACT_EVM_MAINNET
@@ -5324,6 +5532,9 @@ var EarnChain;
5324
5532
  destination: true
5325
5533
  }
5326
5534
  },
5535
+ cctpx: {
5536
+ serviceAddress: CCTPX_SERVICE_ADDRESS_EVM_TESTNET
5537
+ },
5327
5538
  kitContracts: {
5328
5539
  bridge: BRIDGE_CONTRACT_EVM_TESTNET
5329
5540
  },
@@ -5373,6 +5584,7 @@ var EarnChain;
5373
5584
  v2: {
5374
5585
  type: 'split',
5375
5586
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
5587
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
5376
5588
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
5377
5589
  confirmations: 1,
5378
5590
  fastConfirmations: 1
@@ -5419,6 +5631,7 @@ var EarnChain;
5419
5631
  v2: {
5420
5632
  type: 'split',
5421
5633
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
5634
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
5422
5635
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
5423
5636
  confirmations: 1,
5424
5637
  fastConfirmations: 1
@@ -5717,6 +5930,9 @@ var EarnChain;
5717
5930
  destination: true
5718
5931
  }
5719
5932
  },
5933
+ cctpx: {
5934
+ serviceAddress: CCTPX_SERVICE_ADDRESS_EVM_MAINNET
5935
+ },
5720
5936
  kitContracts: {
5721
5937
  bridge: BRIDGE_CONTRACT_EVM_MAINNET,
5722
5938
  adapter: ADAPTER_CONTRACT_EVM_MAINNET
@@ -5726,7 +5942,9 @@ var EarnChain;
5726
5942
  contracts: {
5727
5943
  v1: {
5728
5944
  wallet: GATEWAY_WALLET_EVM_MAINNET,
5729
- minter: GATEWAY_MINTER_EVM_MAINNET
5945
+ minter: GATEWAY_MINTER_EVM_MAINNET,
5946
+ depositForHandler: DEPOSIT_FOR_HANDLER_EVM_MAINNET,
5947
+ genericExecutor: GENERIC_EXECUTOR_EVM_MAINNET
5730
5948
  }
5731
5949
  },
5732
5950
  forwarderSupported: {
@@ -5783,6 +6001,9 @@ var EarnChain;
5783
6001
  destination: true
5784
6002
  }
5785
6003
  },
6004
+ cctpx: {
6005
+ serviceAddress: CCTPX_SERVICE_ADDRESS_EVM_TESTNET
6006
+ },
5786
6007
  kitContracts: {
5787
6008
  bridge: BRIDGE_CONTRACT_EVM_TESTNET
5788
6009
  },
@@ -5791,7 +6012,9 @@ var EarnChain;
5791
6012
  contracts: {
5792
6013
  v1: {
5793
6014
  wallet: GATEWAY_WALLET_EVM_TESTNET,
5794
- minter: GATEWAY_MINTER_EVM_TESTNET
6015
+ minter: GATEWAY_MINTER_EVM_TESTNET,
6016
+ depositForHandler: DEPOSIT_FOR_HANDLER_EVM_TESTNET,
6017
+ genericExecutor: GENERIC_EXECUTOR_EVM_TESTNET
5795
6018
  }
5796
6019
  },
5797
6020
  forwarderSupported: {
@@ -6789,6 +7012,7 @@ var Chains = /*#__PURE__*/Object.freeze({
6789
7012
  AptosTestnet: AptosTestnet,
6790
7013
  Arbitrum: Arbitrum,
6791
7014
  ArbitrumSepolia: ArbitrumSepolia,
7015
+ Arc: Arc,
6792
7016
  ArcTestnet: ArcTestnet,
6793
7017
  Avalanche: Avalanche,
6794
7018
  AvalancheFuji: AvalancheFuji,
@@ -6877,6 +7101,67 @@ var Chains = /*#__PURE__*/Object.freeze({
6877
7101
  return chain.cctp?.contracts.v2 !== undefined;
6878
7102
  }
6879
7103
 
7104
+ /**
7105
+ * Chains the Fee Service accepts as a SOURCE for source-paid ("receive-exact")
7106
+ * CCTP v2 fees. An explicit allowlist is required because the
7107
+ * `TokenMessengerWithFees` wrapper address is now shared with the fast-deposit
7108
+ * forwarder path, so wrapper presence no longer implies source-fee support.
7109
+ * Keep in sync with backend coverage.
7110
+ */ new Set([
7111
+ // Mainnet
7112
+ Blockchain.Ethereum,
7113
+ Blockchain.Base,
7114
+ Blockchain.Arbitrum,
7115
+ Blockchain.Unichain,
7116
+ Blockchain.Optimism,
7117
+ Blockchain.Codex,
7118
+ Blockchain.Ink,
7119
+ Blockchain.Plume,
7120
+ Blockchain.Linea,
7121
+ Blockchain.World_Chain,
7122
+ // Testnet counterparts
7123
+ Blockchain.Ethereum_Sepolia,
7124
+ Blockchain.Base_Sepolia,
7125
+ Blockchain.Arbitrum_Sepolia,
7126
+ Blockchain.Unichain_Sepolia,
7127
+ Blockchain.Optimism_Sepolia,
7128
+ Blockchain.Codex_Testnet,
7129
+ Blockchain.Ink_Testnet,
7130
+ Blockchain.Plume_Testnet,
7131
+ Blockchain.Linea_Sepolia,
7132
+ Blockchain.World_Chain_Sepolia
7133
+ ]);
7134
+
7135
+ /**
7136
+ * Temporary allowlist of chains permitted to initiate Gateway fast deposits.
7137
+ * Only chains keyed here are eligible; all others are rejected. Using the
7138
+ * {@link Blockchain} enum keeps entries type-safe and catches typos at compile
7139
+ * time. Remove this allowlist once roll-out is complete.
7140
+ */ new Set([
7141
+ // Mainnet
7142
+ Blockchain.Ethereum,
7143
+ Blockchain.Base,
7144
+ Blockchain.Arbitrum,
7145
+ Blockchain.Unichain,
7146
+ Blockchain.Optimism,
7147
+ Blockchain.Codex,
7148
+ Blockchain.Ink,
7149
+ Blockchain.Plume,
7150
+ Blockchain.Linea,
7151
+ Blockchain.World_Chain,
7152
+ // Testnet counterparts
7153
+ Blockchain.Ethereum_Sepolia,
7154
+ Blockchain.Base_Sepolia,
7155
+ Blockchain.Arbitrum_Sepolia,
7156
+ Blockchain.Unichain_Sepolia,
7157
+ Blockchain.Optimism_Sepolia,
7158
+ Blockchain.Codex_Testnet,
7159
+ Blockchain.Ink_Testnet,
7160
+ Blockchain.Plume_Testnet,
7161
+ Blockchain.Linea_Sepolia,
7162
+ Blockchain.World_Chain_Sepolia
7163
+ ]);
7164
+
6880
7165
  /**
6881
7166
  * Zod schema for validating Gateway v1 contract addresses.
6882
7167
  *
@@ -6898,7 +7183,10 @@ var Chains = /*#__PURE__*/Object.freeze({
6898
7183
  }).min(1, 'Gateway minter address cannot be empty.'),
6899
7184
  depositForHandler: z.string({
6900
7185
  invalid_type_error: 'Gateway depositForHandler address must be a string.'
6901
- }).min(1, 'Gateway depositForHandler address cannot be empty.').optional()
7186
+ }).min(1, 'Gateway depositForHandler address cannot be empty.').optional(),
7187
+ genericExecutor: z.string({
7188
+ invalid_type_error: 'Gateway genericExecutor address must be a string.'
7189
+ }).min(1, 'Gateway genericExecutor address cannot be empty.').optional()
6902
7190
  }).strict() // Reject any additional properties not defined in the schema
6903
7191
  ;
6904
7192
  /**
@@ -6982,6 +7270,7 @@ var Chains = /*#__PURE__*/Object.freeze({
6982
7270
  usdcAddress: z.string().nullable(),
6983
7271
  usdtAddress: z.string().nullable(),
6984
7272
  cctp: z.any().nullable(),
7273
+ cctpx: z.any().optional(),
6985
7274
  kitContracts: z.object({
6986
7275
  bridge: z.string().optional(),
6987
7276
  adapter: z.string().optional()
@@ -7187,14 +7476,15 @@ const EARN_BRIDGE_DESTINATION_CHAIN_VALUES = EARN_BRIDGE_DESTINATION_BLOCKCHAINS
7187
7476
  * Zod schema for validating the source chain of a cross-chain Earn deposit.
7188
7477
  *
7189
7478
  * Accept a supported source Blockchain value, a matching string literal, or a
7190
- * ChainDefinition for a supported source chain. Source chains are Ethereum
7191
- * Sepolia, Arbitrum Sepolia, and Base Sepolia.
7479
+ * ChainDefinition for a supported source chain. Source chains are Ethereum,
7480
+ * Arbitrum, and Base (mainnet and testnet).
7192
7481
  *
7193
7482
  * @example
7194
7483
  * ```typescript
7195
7484
  * import { earnBridgeSourceChainIdentifierSchema } from '@core/chains'
7196
7485
  *
7197
7486
  * // Valid
7487
+ * earnBridgeSourceChainIdentifierSchema.parse('Ethereum')
7198
7488
  * earnBridgeSourceChainIdentifierSchema.parse('Ethereum_Sepolia')
7199
7489
  *
7200
7490
  * // Invalid (throws ZodError)
@@ -7213,14 +7503,15 @@ const EARN_BRIDGE_DESTINATION_CHAIN_VALUES = EARN_BRIDGE_DESTINATION_BLOCKCHAINS
7213
7503
  * deposit.
7214
7504
  *
7215
7505
  * Accept a supported destination Blockchain value, a matching string literal,
7216
- * or a ChainDefinition for a supported destination chain. Currently only Arc
7217
- * Testnet is supported.
7506
+ * or a ChainDefinition for a supported destination chain. Arc (mainnet) and
7507
+ * Arc Testnet are supported.
7218
7508
  *
7219
7509
  * @example
7220
7510
  * ```typescript
7221
7511
  * import { earnBridgeDestinationChainIdentifierSchema } from '@core/chains'
7222
7512
  *
7223
7513
  * // Valid
7514
+ * earnBridgeDestinationChainIdentifierSchema.parse('Arc')
7224
7515
  * earnBridgeDestinationChainIdentifierSchema.parse('Arc_Testnet')
7225
7516
  *
7226
7517
  * // Invalid (throws ZodError)
@@ -7398,7 +7689,10 @@ const swapTokenEnumSchema = z.enum([
7398
7689
  * Get decimal places for a supported swap token.
7399
7690
  *
7400
7691
  * @param token - Swap token symbol
7401
- * @returns Number of decimals, or null for NATIVE (chain-specific)
7692
+ * @returns Number of decimals; `null` for NATIVE (chain-specific) or when the
7693
+ * symbol is not in the swap registry. Callers must not read `null` as
7694
+ * "use the chain's native decimals" — for a CCTPx token that would scale
7695
+ * an 8-decimal amount as 18.
7402
7696
  *
7403
7697
  * @example
7404
7698
  * ```typescript
@@ -7410,6 +7704,15 @@ const swapTokenEnumSchema = z.enum([
7410
7704
  * ```
7411
7705
  */ function getSwapTokenDecimals(token) {
7412
7706
  if (token === NATIVE_TOKEN) return null;
7707
+ // Membership is checked rather than assumed: callers reach this through
7708
+ // `formatAmount`/`parseAmount` with a plain `string` token, so a value
7709
+ // outside the registry (a provider's own symbol, or a bytes32 id) is
7710
+ // reachable at runtime despite what the parameter type says. A bare index
7711
+ // would throw a raw TypeError from inside the formatter; `null` lets the
7712
+ // caller raise its own "could not determine decimals" error instead.
7713
+ if (!Object.hasOwn(SWAP_TOKEN_REGISTRY, token)) {
7714
+ return null;
7715
+ }
7413
7716
  return SWAP_TOKEN_REGISTRY[token].decimals;
7414
7717
  }
7415
7718
  /**
@@ -8851,6 +9154,7 @@ const swapTokenEnumSchema = z.enum([
8851
9154
  // Mainnets (alphabetically sorted)
8852
9155
  // =========================================================================
8853
9156
  [Blockchain.Arbitrum]: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',
9157
+ [Blockchain.Arc]: '0x3600000000000000000000000000000000000000',
8854
9158
  [Blockchain.Avalanche]: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E',
8855
9159
  [Blockchain.Base]: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
8856
9160
  [Blockchain.Celo]: '0xcebA9300f2b948710d2653dD7B07f33A8B32118C',
@@ -8965,6 +9269,7 @@ const swapTokenEnumSchema = z.enum([
8965
9269
  // =========================================================================
8966
9270
  // Mainnets
8967
9271
  // =========================================================================
9272
+ [Blockchain.Arc]: '0xbEf5f6d51CB62b58e6A8f77868681825C6fe21c1',
8968
9273
  [Blockchain.Avalanche]: '0xc891EB4cbdEFf6e073e859e987815Ed1505c2ACD',
8969
9274
  [Blockchain.Base]: '0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42',
8970
9275
  [Blockchain.Cronos]: '0xA6dE01a2d62C6B5f3525d768f34d276652C554c8',
@@ -9208,6 +9513,7 @@ const swapTokenEnumSchema = z.enum([
9208
9513
  // =========================================================================
9209
9514
  // Mainnets
9210
9515
  // =========================================================================
9516
+ [Blockchain.Arc]: '0x171A4217b86A807A64eB94757Db6849fb4bDbAA0',
9211
9517
  [Blockchain.Ethereum]: '0x72DFB2E44f59C5AD2bAFE84314E5b99a7cd5075E',
9212
9518
  // =========================================================================
9213
9519
  // Testnets
@@ -9300,13 +9606,28 @@ const swapTokenEnumSchema = z.enum([
9300
9606
  }
9301
9607
 
9302
9608
  /**
9303
- * Check if a selector is a raw token selector (object form).
9609
+ * Type guard: narrows a {@link TokenSelector} to a {@link RawTokenSelector}.
9304
9610
  *
9305
9611
  * @param selector - The token selector to check.
9306
- * @returns True if the selector is a raw token selector.
9612
+ * @returns `true` if `selector` is a raw token selector (object with `locator`).
9613
+ *
9614
+ * @example
9615
+ * ```typescript
9616
+ * if (isRawSelector(selector)) {
9617
+ * console.log(selector.locator)
9618
+ * }
9619
+ * ```
9307
9620
  */ function isRawSelector(selector) {
9308
- return typeof selector === 'object' && 'locator' in selector;
9621
+ // `typeof null === 'object'` (a JS quirk) and `'locator' in null`
9622
+ // throws, so the explicit `null` check is required at this exported
9623
+ // guard for JS consumers passing nullish values. The lint rule sees
9624
+ // the parameter typed as `TokenSelector` (no null) and flags the
9625
+ // check as unnecessary — disabled because the check IS necessary at
9626
+ // runtime even though TypeScript can prove it dead statically.
9627
+ return typeof selector === 'object' && // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
9628
+ selector !== null && 'locator' in selector;
9309
9629
  }
9630
+
9310
9631
  /**
9311
9632
  * Normalize a symbol to uppercase for case-insensitive lookup.
9312
9633
  *
@@ -9494,7 +9815,7 @@ const swapTokenEnumSchema = z.enum([
9494
9815
  if (typeof selector === 'string') {
9495
9816
  return resolveSymbol(selector, chainId);
9496
9817
  }
9497
- throw createTokenResolutionError(`Invalid selector type: ${typeof selector}. Expected string or object with locator.`, selector, chainId);
9818
+ throw createTokenResolutionError(`Invalid selector type: ${typeof selector}. Expected a token symbol or a raw selector (with locator).`, selector, chainId);
9498
9819
  },
9499
9820
  resolveByAddress (address, chainId) {
9500
9821
  if (!address || typeof address !== 'string') {
@@ -9616,9 +9937,17 @@ const swapTokenEnumSchema = z.enum([
9616
9937
  *
9617
9938
  * // Native token (chain-derived decimals)
9618
9939
  * formatAmount({ value: '3141592000000000000', token: 'NATIVE', chain: Ethereum }) // "3.141592"
9940
+ *
9941
+ * // Explicit decimals (skips all registry lookups)
9942
+ * formatAmount({ value: '100000000', token: 'USDC', decimals: 8 }) // "1"
9619
9943
  * ```
9620
9944
  */ const formatAmount = (params)=>{
9621
9945
  const { value, token, tokens } = params;
9946
+ // Explicit decimals win — used when the caller resolved decimals itself
9947
+ // (e.g. through a provider) for a token outside the built-in registries.
9948
+ if (params.decimals !== undefined) {
9949
+ return formatUnits(value, params.decimals);
9950
+ }
9622
9951
  // Handle NATIVE token first (chain-specific decimals)
9623
9952
  if (token === 'NATIVE') {
9624
9953
  if (params.chain === undefined) {
@@ -9806,7 +10135,7 @@ const swapTokenEnumSchema = z.enum([
9806
10135
  * allowlisted {@link ClientLogPayload} fields (and the allowlisted
9807
10136
  * sub-fields of `errorDetails` / `clientContext`) are copied across.
9808
10137
  * A regressing upstream mapper — or a plain-JS caller that bypasses the
9809
- * type — therefore cannot exfiltrate stray properties (secrets, PII,
10138
+ * type — therefore cannot exfiltrate stray properties (secrets,
9810
10139
  * raw error stacks) through the analytics channel. Optional fields are
9811
10140
  * only included when present so the serialised shape matches the
9812
10141
  * server's strict schema.
@@ -9829,6 +10158,9 @@ const swapTokenEnumSchema = z.enum([
9829
10158
  if (payload.destinationChain !== undefined) safe['destinationChain'] = payload.destinationChain;
9830
10159
  if (payload.tokenIn !== undefined) safe['tokenIn'] = payload.tokenIn;
9831
10160
  if (payload.tokenOut !== undefined) safe['tokenOut'] = payload.tokenOut;
10161
+ if (payload.amountIn !== undefined) safe['amountIn'] = payload.amountIn;
10162
+ if (payload.durationMs !== undefined) safe['durationMs'] = payload.durationMs;
10163
+ if (payload.sourceAddress !== undefined) safe['sourceAddress'] = payload.sourceAddress;
9832
10164
  if (payload.txHash !== undefined) safe['txHash'] = payload.txHash;
9833
10165
  if (payload.correlationId !== undefined) safe['correlationId'] = payload.correlationId;
9834
10166
  if (payload.errorDetails !== undefined) {
@@ -10062,14 +10394,28 @@ const swapTokenEnumSchema = z.enum([
10062
10394
  }
10063
10395
 
10064
10396
  /**
10065
- * Soft signal for the case where building or emitting a telemetry payload
10066
- * threw — for example, a buggy `TelemetryContextResolver`, a regression in
10397
+ * Emit a stable console warning when building or emitting a telemetry payload
10398
+ * throws — for example, a buggy `TelemetryContextResolver`, a regression in
10067
10399
  * `extractErrorDetails`, or a synchronous failure inside `emitAnalyticsLog`
10068
- * before it could swallow the error itself. Logged with a stable prefix so
10069
- * consumers can grep for it. We deliberately do not re-throw: the caller's
10070
- * original operation error must always win.
10400
+ * before it could swallow the error itself. Uses a stable prefix so the
10401
+ * drop is discoverable via grep. Never re-throws: the caller's original
10402
+ * operation error must always win.
10071
10403
  *
10072
10404
  * @internal
10405
+ *
10406
+ * @param eventType - The telemetry event type that was being emitted.
10407
+ * @param cause - The error or value that caused the drop.
10408
+ *
10409
+ * @example
10410
+ * ```typescript
10411
+ * import { warnTelemetryDrop } from '@core/utils'
10412
+ *
10413
+ * try {
10414
+ * void emitAnalyticsLog(payload)
10415
+ * } catch (err) {
10416
+ * warnTelemetryDrop('my_event', err)
10417
+ * }
10418
+ * ```
10073
10419
  */ function warnTelemetryDrop(eventType, cause) {
10074
10420
  try {
10075
10421
  // Pass `cause` as the second console.warn argument rather than
@@ -10109,6 +10455,9 @@ const swapTokenEnumSchema = z.enum([
10109
10455
  ...context?.tokenOut != null && {
10110
10456
  tokenOut: context.tokenOut
10111
10457
  },
10458
+ ...context?.amountIn != null && {
10459
+ amountIn: context.amountIn
10460
+ },
10112
10461
  ...context?.txHash != null && {
10113
10462
  txHash: context.txHash
10114
10463
  },
@@ -10208,7 +10557,7 @@ const swapTokenEnumSchema = z.enum([
10208
10557
  }
10209
10558
 
10210
10559
  var name$2 = "@circle-fin/bridge-kit";
10211
- var version$2 = "1.14.0";
10560
+ var version$2 = "1.15.0";
10212
10561
  var pkg$2 = {
10213
10562
  name: name$2,
10214
10563
  version: version$2};
@@ -10907,67 +11256,522 @@ var TransferSpeed;
10907
11256
  */ recipientAddress: z.string().trim().min(1, 'Fee recipient must be a non-empty string').optional()
10908
11257
  }).strict();
10909
11258
  /**
10910
- * Schema for validating bridge parameters.
10911
- * This ensures all required fields are present and properly typed.
10912
- * A bridge must include:
10913
- * - A valid amount (non-empty numeric string \> 0)
10914
- * - Valid source and destination wallet contexts
10915
- * - USDC as the token
10916
- * - Optional config with transfer speed and max fee settings
11259
+ * Factory for the bridge-params Zod schema, parameterized by the token
11260
+ * validator. The base schema enforces all non-token fields (amount,
11261
+ * source, destination, config); callers supply the Zod schema for the
11262
+ * `token` field, allowing each provider to validate the token type it
11263
+ * accepts.
11264
+ *
11265
+ * @param tokenSchema - Zod schema applied to the `token` field. Pass
11266
+ * `z.literal('USDC')` for USDC-only validation, or any
11267
+ * provider-specific schema (e.g. a `0x`-prefixed hex regex) for
11268
+ * providers that accept a different token type.
11269
+ * @param config - Required. `maxDecimals` caps the decimal precision
11270
+ * permitted in `amount` and `config.maxFee`. Pass the widest value
11271
+ * any of the provider's tokens require — `6` for USDC-only, `18`
11272
+ * for an ERC-20 family that includes wETH, etc. The schema is a
11273
+ * coarse syntactic gate; narrower per-token precision is enforced
11274
+ * by the provider downstream.
11275
+ * @returns A Zod object schema whose `token` field is validated by
11276
+ * `tokenSchema` and whose other fields (`amount`, `source`,
11277
+ * `destination`, `config`) are validated against the shared bridge
11278
+ * contract. Use `.safeParse` / `.parse` directly, or feed the schema
11279
+ * to {@link parseOrThrow} from `@core/utils` to surface validation
11280
+ * failures as `KitError` with the canonical
11281
+ * `INPUT_VALIDATION_FAILED` code.
11282
+ *
11283
+ * @example
11284
+ * ```typescript
11285
+ * import { createBridgeParamsSchema, z } from '@core/provider'
11286
+ *
11287
+ * const usdcSchema = createBridgeParamsSchema(z.literal('USDC'), { maxDecimals: 6 })
11288
+ * const hexSchema = createBridgeParamsSchema(
11289
+ * z.string().regex(/^0x[0-9a-fA-F]{64}$/),
11290
+ * { maxDecimals: 18 },
11291
+ * )
11292
+ * ```
11293
+ */ // The full inferred return type of `z.object({...})` here is
11294
+ // effectively impossible to spell out by hand without re-stating every
11295
+ // field's schema. TypeScript infers it from the body — callers receive
11296
+ // a precise Zod schema type via inference, and the explicit-return
11297
+ // rules are disabled for that reason.
11298
+ // eslint-disable-next-line @typescript-eslint/explicit-function-return-type, @typescript-eslint/explicit-module-boundary-types
11299
+ function createBridgeParamsSchema(tokenSchema, config) {
11300
+ const { maxDecimals } = config;
11301
+ return z.object({
11302
+ amount: z.string().min(1, 'Required').pipe(createDecimalStringValidator({
11303
+ allowZero: false,
11304
+ regexMessage: AMOUNT_FORMAT_ERROR_MESSAGE,
11305
+ attributeName: 'amount',
11306
+ maxDecimals
11307
+ })(z.string())),
11308
+ source: walletContextSchema,
11309
+ destination: bridgeDestinationSchema$1,
11310
+ token: tokenSchema,
11311
+ config: z.object({
11312
+ transferSpeed: z.nativeEnum(TransferSpeed).optional(),
11313
+ maxFee: z.string().pipe(createDecimalStringValidator({
11314
+ allowZero: true,
11315
+ regexMessage: MAX_FEE_FORMAT_ERROR_MESSAGE,
11316
+ attributeName: 'maxFee',
11317
+ maxDecimals
11318
+ })(z.string())).optional(),
11319
+ customFee: customFeeSchema.optional()
11320
+ })
11321
+ });
11322
+ }
11323
+ /**
11324
+ * Schema for validating bridge parameters with USDC as the token.
11325
+ * This ensures all required fields are present and properly typed.
11326
+ * A bridge must include:
11327
+ * - A valid amount (non-empty numeric string \> 0)
11328
+ * - Valid source and destination wallet contexts
11329
+ * - USDC as the token
11330
+ * - Optional config with transfer speed and max fee settings
11331
+ *
11332
+ * Providers that accept a non-USDC token type should call
11333
+ * {@link createBridgeParamsSchema} with their own token schema rather
11334
+ * than reusing this constant.
11335
+ *
11336
+ * @throws KitError if validation fails
11337
+ *
11338
+ * @example
11339
+ * ```typescript
11340
+ * import { usdcBridgeParamsSchema } from '@core/provider'
11341
+ *
11342
+ * const validBridge = {
11343
+ * amount: '100.50',
11344
+ * source: {
11345
+ * adapter: sourceAdapter,
11346
+ * address: '0xSourceAddress',
11347
+ * chain: sourceChain
11348
+ * },
11349
+ * destination: {
11350
+ * adapter: destAdapter,
11351
+ * address: '0xDestAddress',
11352
+ * chain: destChain
11353
+ * },
11354
+ * token: 'USDC',
11355
+ * config: {
11356
+ * transferSpeed: 'FAST',
11357
+ * maxFee: '1.5', // Must use dot as decimal separator
11358
+ * customFee: {
11359
+ * value: '0.5', // Must use dot as decimal separator
11360
+ * recipientAddress: '0x1234567890123456789012345678901234567890'
11361
+ * }
11362
+ * }
11363
+ * }
11364
+ *
11365
+ * const result = usdcBridgeParamsSchema.safeParse(validBridge)
11366
+ * console.log(result.success) // true
11367
+ * ```
11368
+ */ createBridgeParamsSchema(z.literal('USDC'), {
11369
+ maxDecimals: 6
11370
+ });
11371
+
11372
+ // ----------------------------------------------------------------------------
11373
+ // IRIS API base URLs
11374
+ // ----------------------------------------------------------------------------
11375
+ // ----------------------------------------------------------------------------
11376
+ // Known token symbols (DX convenience)
11377
+ // ----------------------------------------------------------------------------
11378
+ //
11379
+ // These constants back symbol -> id resolution as a convenience: a caller may
11380
+ // pass a known symbol instead of a raw bytes32 id. They do NOT gate
11381
+ // routability.
11382
+ /**
11383
+ * Display symbols the provider recognizes as a convenience for callers.
11384
+ *
11385
+ * A consumer may pass one of these symbols instead of a raw bytes32 token
11386
+ * id; the provider resolves it to the symbol's canonical bytes32 id via
11387
+ * {@link KNOWN_TOKEN_IDS_BY_NETWORK} (a symbol can map to more than one
11388
+ * bridge, so the map pins the canonical one). This list does NOT gate
11389
+ * routability: any token the IRIS registry lists with deployments on both
11390
+ * endpoints routes when passed by its bytes32 id, whether listed here or
11391
+ * not.
11392
+ *
11393
+ * @example
11394
+ * ```typescript
11395
+ * for (const symbol of KNOWN_TOKEN_SYMBOLS) console.log(symbol)
11396
+ * ```
11397
+ */ const KNOWN_TOKEN_SYMBOLS = [
11398
+ 'cirBTC',
11399
+ 'wETH',
11400
+ 'EURC'
11401
+ ];
11402
+
11403
+ /**
11404
+ * Define a schema for runtime logger interfaces.
11405
+ *
11406
+ * @remarks
11407
+ * Validate that a runtime logger provides the minimal methods expected by the SDK.
11408
+ *
11409
+ * @example
11410
+ * ```typescript
11411
+ * import { loggerSchema } from '@core/runtime'
11412
+ *
11413
+ * const logger = {
11414
+ * debug: () => undefined,
11415
+ * info: () => undefined,
11416
+ * warn: () => undefined,
11417
+ * error: () => undefined,
11418
+ * child: () => logger,
11419
+ * }
11420
+ *
11421
+ * loggerSchema.parse(logger)
11422
+ * ```
11423
+ */ const loggerSchema = z.custom((value)=>{
11424
+ if (value === null || typeof value !== 'object') {
11425
+ return false;
11426
+ }
11427
+ const record = value;
11428
+ return typeof record['debug'] === 'function' && typeof record['info'] === 'function' && typeof record['warn'] === 'function' && typeof record['error'] === 'function' && typeof record['child'] === 'function';
11429
+ }, {
11430
+ message: 'Invalid logger'
11431
+ });
11432
+
11433
+ /**
11434
+ * Define a schema for runtime metrics interfaces.
11435
+ *
11436
+ * @remarks
11437
+ * Validate that a metrics implementation exposes the minimal API expected by the runtime.
11438
+ *
11439
+ * @example
11440
+ * ```typescript
11441
+ * import { metricsSchema } from '@core/runtime'
11442
+ *
11443
+ * const metrics = {
11444
+ * counter: () => ({ inc: () => undefined }),
11445
+ * histogram: () => ({ observe: () => undefined }),
11446
+ * timer: () => ({ start: () => () => undefined }),
11447
+ * child: () => metrics,
11448
+ * }
11449
+ *
11450
+ * metricsSchema.parse(metrics)
11451
+ * ```
11452
+ */ const metricsSchema = z.custom((value)=>{
11453
+ if (value === null || typeof value !== 'object') {
11454
+ return false;
11455
+ }
11456
+ const record = value;
11457
+ return typeof record['counter'] === 'function' && typeof record['histogram'] === 'function' && typeof record['timer'] === 'function' && typeof record['child'] === 'function';
11458
+ }, {
11459
+ message: 'Invalid metrics'
11460
+ });
11461
+
11462
+ /**
11463
+ * Omit undefined values from an object.
11464
+ *
11465
+ * @param obj - The object to process.
11466
+ * @returns A new object with undefined values removed.
11467
+ *
11468
+ * @internal
11469
+ * @remarks
11470
+ * Used by both production and mock loggers to ensure consistent behavior.
11471
+ * This prevents undefined values from being serialized in log output,
11472
+ * which can cause issues with some log transports.
11473
+ */ function omitUndefined(obj) {
11474
+ const result = {};
11475
+ for (const [key, value] of Object.entries(obj)){
11476
+ if (value !== undefined) {
11477
+ result[key] = value;
11478
+ }
11479
+ }
11480
+ return result;
11481
+ }
11482
+
11483
+ /**
11484
+ * Default redaction paths for web3/blockchain SDKs.
11485
+ *
11486
+ * @remarks
11487
+ * These paths target common sensitive fields in blockchain applications.
11488
+ * All user fields are nested under `context`, so paths start with `context.`.
11489
+ * Wildcard `*` matches any key at that level.
11490
+ */ const DEFAULT_REDACT_PATHS = [
11491
+ // Generic Credentials
11492
+ 'context.password',
11493
+ 'context.passphrase',
11494
+ 'context.secret',
11495
+ 'context.token',
11496
+ 'context.*.password',
11497
+ 'context.*.passphrase',
11498
+ 'context.*.secret',
11499
+ 'context.*.token',
11500
+ // API Keys & Auth Tokens
11501
+ 'context.apiKey',
11502
+ 'context.apiSecret',
11503
+ 'context.accessToken',
11504
+ 'context.refreshToken',
11505
+ 'context.jwt',
11506
+ 'context.bearerToken',
11507
+ 'context.sessionId',
11508
+ 'context.authorization',
11509
+ 'context.cookie',
11510
+ 'context.*.apiKey',
11511
+ 'context.*.apiSecret',
11512
+ 'context.*.accessToken',
11513
+ 'context.*.refreshToken',
11514
+ 'context.*.jwt',
11515
+ 'context.*.bearerToken',
11516
+ 'context.*.sessionId',
11517
+ 'context.*.authorization',
11518
+ 'context.*.cookie',
11519
+ // Web3 / Crypto Keys
11520
+ 'context.privateKey',
11521
+ 'context.secretKey',
11522
+ 'context.signingKey',
11523
+ 'context.encryptionKey',
11524
+ 'context.*.privateKey',
11525
+ 'context.*.secretKey',
11526
+ 'context.*.signingKey',
11527
+ 'context.*.encryptionKey',
11528
+ // Web3 / Crypto Mnemonics and Seeds
11529
+ 'context.mnemonic',
11530
+ 'context.seed',
11531
+ 'context.seedPhrase',
11532
+ 'context.*.mnemonic',
11533
+ 'context.*.seed',
11534
+ 'context.*.seedPhrase',
11535
+ // OTP / Verification Codes
11536
+ 'context.otp',
11537
+ 'context.verificationCode',
11538
+ 'context.*.otp',
11539
+ 'context.*.verificationCode',
11540
+ // Payment Information
11541
+ 'context.cardNumber',
11542
+ 'context.cvv',
11543
+ 'context.accountNumber',
11544
+ 'context.*.cardNumber',
11545
+ 'context.*.cvv',
11546
+ 'context.*.accountNumber'
11547
+ ];
11548
+ /**
11549
+ * Wrap user fields under `context` to prevent collision with pino internals.
11550
+ *
11551
+ * @param fields - User-provided log fields.
11552
+ * @returns Object with fields nested under `context`, or undefined if empty.
11553
+ *
11554
+ * @remarks
11555
+ * This function handles edge cases by returning undefined for null, undefined,
11556
+ * or empty objects to avoid unnecessary wrapping in log output.
11557
+ * Undefined values are cleaned before wrapping.
11558
+ */ function wrapInContext(fields) {
11559
+ if (!fields) return undefined;
11560
+ // Clean undefined values for consistency and transport compatibility
11561
+ const cleaned = omitUndefined(fields);
11562
+ // Handle edge case: all values were undefined, resulting in empty object
11563
+ const keys = Object.keys(cleaned);
11564
+ if (keys.length === 0) return undefined;
11565
+ return {
11566
+ context: cleaned
11567
+ };
11568
+ }
11569
+ /**
11570
+ * Wrap a pino instance to conform to our Logger interface.
11571
+ *
11572
+ * @param pinoInstance - The pino logger instance to wrap.
11573
+ * @returns A Logger instance conforming to our stable interface.
11574
+ */ function wrapPino(pinoInstance) {
11575
+ return {
11576
+ debug (message, fields) {
11577
+ const wrapped = wrapInContext(fields);
11578
+ if (wrapped) {
11579
+ pinoInstance.debug(wrapped, message);
11580
+ } else {
11581
+ pinoInstance.debug(message);
11582
+ }
11583
+ },
11584
+ info (message, fields) {
11585
+ const wrapped = wrapInContext(fields);
11586
+ if (wrapped) {
11587
+ pinoInstance.info(wrapped, message);
11588
+ } else {
11589
+ pinoInstance.info(message);
11590
+ }
11591
+ },
11592
+ warn (message, fields) {
11593
+ const wrapped = wrapInContext(fields);
11594
+ if (wrapped) {
11595
+ pinoInstance.warn(wrapped, message);
11596
+ } else {
11597
+ pinoInstance.warn(message);
11598
+ }
11599
+ },
11600
+ error (message, fields) {
11601
+ const wrapped = wrapInContext(fields);
11602
+ if (wrapped) {
11603
+ pinoInstance.error(wrapped, message);
11604
+ } else {
11605
+ pinoInstance.error(message);
11606
+ }
11607
+ },
11608
+ child (tags) {
11609
+ // Child bindings stay flat (not wrapped) - they're part of logger's base context
11610
+ const cleaned = omitUndefined(tags);
11611
+ return wrapPino(pinoInstance.child(cleaned));
11612
+ }
11613
+ };
11614
+ }
11615
+ /**
11616
+ * Build pino redact configuration from our simplified options.
11617
+ *
11618
+ * @param redact - The redact configuration option.
11619
+ * @returns Pino-compatible redact configuration or undefined.
11620
+ */ function buildRedactConfig(redact) {
11621
+ // Explicitly disabled
11622
+ if (redact === false) {
11623
+ return undefined;
11624
+ }
11625
+ // Custom paths provided
11626
+ if (Array.isArray(redact)) {
11627
+ return redact.length > 0 ? {
11628
+ paths: redact,
11629
+ censor: '[REDACTED]'
11630
+ } : undefined;
11631
+ }
11632
+ // Default: use web3 sensible defaults
11633
+ return {
11634
+ paths: [
11635
+ ...DEFAULT_REDACT_PATHS
11636
+ ],
11637
+ censor: '[REDACTED]'
11638
+ };
11639
+ }
11640
+ /**
11641
+ * Create a logger backed by pino.
11642
+ *
11643
+ * @param options - Logger options (optional).
11644
+ * @param stream - Destination stream (optional).
11645
+ * @returns A Logger instance.
11646
+ * @throws Error if invalid pino options are provided.
11647
+ *
11648
+ * @remarks
11649
+ * This is a thin wrapper around pino that exposes our stable Logger interface.
11650
+ * Pino handles all transport concerns: JSON, pretty printing, file, remote, browser, etc.
11651
+ *
11652
+ * **Security**: By default, sensitive web3 fields (privateKey, mnemonic, apiKey, etc.)
11653
+ * are automatically redacted from log output. Use `redact: false` to disable.
11654
+ *
11655
+ * @example
11656
+ * ```typescript
11657
+ * import { createLogger } from '@core/runtime'
11658
+ *
11659
+ * // Default: web3 sensitive fields are redacted
11660
+ * const logger = createLogger({ level: 'info' })
11661
+ * logger.info('Signing', { privateKey: '0x123...' })
11662
+ * // Output: { context: { privateKey: '[REDACTED]' }, msg: 'Signing' }
11663
+ *
11664
+ * // Disable redaction (use with caution)
11665
+ * const unsafeLogger = createLogger({ level: 'debug', redact: false })
11666
+ *
11667
+ * // Custom redaction paths
11668
+ * const customLogger = createLogger({
11669
+ * level: 'info',
11670
+ * redact: ['context.mySecret', 'context.*.credentials']
11671
+ * })
11672
+ *
11673
+ * // Pretty output for development
11674
+ * const devLogger = createLogger({
11675
+ * level: 'debug',
11676
+ * transport: { target: 'pino-pretty' }
11677
+ * })
11678
+ *
11679
+ * // Browser logger
11680
+ * const browserLogger = createLogger({
11681
+ * browser: { asObject: true }
11682
+ * })
11683
+ * ```
11684
+ */ function createLogger(options, stream) {
11685
+ const { redact, ...pinoOptions } = options ?? {};
11686
+ // Build redaction config
11687
+ const redactConfig = buildRedactConfig(redact);
11688
+ // Build final pino options, only include redact if defined
11689
+ const finalOptions = redactConfig ? {
11690
+ ...pinoOptions,
11691
+ redact: redactConfig
11692
+ } : pinoOptions;
11693
+ const pinoInstance = pino(finalOptions);
11694
+ return wrapPino(pinoInstance);
11695
+ }
11696
+
11697
+ // ============================================================================
11698
+ // Validation Schema
11699
+ // ============================================================================
11700
+ /**
11701
+ * Schema for validating {@link RuntimeOptions}.
11702
+ *
11703
+ * @remarks
11704
+ * Used internally by {@link createRuntime} to validate options from JS consumers.
11705
+ * Exported for advanced use cases where manual validation is needed.
11706
+ */ z.object({
11707
+ logger: loggerSchema.optional(),
11708
+ metrics: metricsSchema.optional()
11709
+ }).passthrough();
11710
+
11711
+ // ============================================================================
11712
+ // Validation Schemas
11713
+ // ============================================================================
11714
+ /**
11715
+ * Schema for validating Caller.
11716
+ */ const callerSchema = z.object({
11717
+ type: z.string(),
11718
+ name: z.string(),
11719
+ version: z.string().optional()
11720
+ });
11721
+ /**
11722
+ * Schema for validating InvocationMeta input.
11723
+ */ z.object({
11724
+ traceId: z.string().optional(),
11725
+ runtime: z.object({}).passthrough().optional(),
11726
+ tokens: z.object({}).passthrough().optional(),
11727
+ callers: z.array(callerSchema).optional(),
11728
+ signal: z.instanceof(AbortSignal).optional()
11729
+ }).strict();
11730
+
11731
+ /**
11732
+ * Runtime package providing cross-cutting infrastructure for SDK operations.
10917
11733
  *
10918
- * @throws KitError if validation fails
11734
+ * @remarks
11735
+ * This package provides the core runtime infrastructure including:
11736
+ *
11737
+ * - **Runtime**: Complete container for logger, metrics, events, and clock
11738
+ * - **ExecutionContext**: Context for middleware with observability surface
11739
+ * - **Logger**: Isomorphic structured logging via {@link createLogger}
11740
+ * - **Events**: Type-safe event bus with {@link createEventBus}
11741
+ * - **Pipeline**: Middleware-based operation execution with {@link createPipeline}
11742
+ * - **Metrics**: Pluggable metrics collection with dimensional tags
10919
11743
  *
10920
11744
  * @example
10921
11745
  * ```typescript
10922
- * import { bridgeParamsSchema } from '@core/provider'
11746
+ * import {
11747
+ * createRuntime,
11748
+ * createExecutionContext,
11749
+ * createOpId,
11750
+ * createTraceId,
11751
+ * type Runtime,
11752
+ * type ExecutionContext,
11753
+ * } from '@core/runtime'
10923
11754
  *
10924
- * const validBridge = {
10925
- * amount: '100.50',
10926
- * source: {
10927
- * adapter: sourceAdapter,
10928
- * address: '0xSourceAddress',
10929
- * chain: sourceChain
10930
- * },
10931
- * destination: {
10932
- * adapter: destAdapter,
10933
- * address: '0xDestAddress',
10934
- * chain: destChain
10935
- * },
10936
- * token: 'USDC',
10937
- * config: {
10938
- * transferSpeed: 'FAST',
10939
- * maxFee: '1.5', // Must use dot as decimal separator
10940
- * customFee: {
10941
- * value: '0.5', // Must use dot as decimal separator
10942
- * recipientAddress: '0x1234567890123456789012345678901234567890'
10943
- * }
10944
- * }
10945
- * }
11755
+ * // Create a complete runtime
11756
+ * const runtime = createRuntime()
10946
11757
  *
10947
- * const result = bridgeParamsSchema.safeParse(validBridge)
10948
- * console.log(result.success) // true
11758
+ * // All services are guaranteed present
11759
+ * runtime.logger.info('Starting operation')
11760
+ * runtime.metrics.counter('requests').inc()
11761
+ * runtime.events.emit({ name: 'operation.started' })
10949
11762
  * ```
10950
- */ z.object({
10951
- amount: z.string().min(1, 'Required').pipe(createDecimalStringValidator({
10952
- allowZero: false,
10953
- regexMessage: AMOUNT_FORMAT_ERROR_MESSAGE,
10954
- attributeName: 'amount',
10955
- maxDecimals: 6
10956
- })(z.string())),
10957
- source: walletContextSchema,
10958
- destination: bridgeDestinationSchema$1,
10959
- token: z.literal('USDC'),
10960
- config: z.object({
10961
- transferSpeed: z.nativeEnum(TransferSpeed).optional(),
10962
- maxFee: z.string().pipe(createDecimalStringValidator({
10963
- allowZero: true,
10964
- regexMessage: MAX_FEE_FORMAT_ERROR_MESSAGE,
10965
- attributeName: 'maxFee',
10966
- maxDecimals: 6
10967
- })(z.string())).optional(),
10968
- customFee: customFeeSchema.optional()
10969
- })
10970
- });
11763
+ *
11764
+ * @packageDocumentation
11765
+ */ // Core types
11766
+ // Clock - expose defaultClock for backward compatibility
11767
+ /** Clock validation schema (backward compatibility). */ z.custom((val)=>val !== null && typeof val === 'object' && 'now' in val && typeof val['now'] === 'function');
11768
+ /** EventBus validation schema (backward compatibility). */ z.custom((val)=>val !== null && typeof val === 'object' && 'emit' in val && typeof val['emit'] === 'function');
11769
+ /** Runtime validation schema (backward compatibility). */ z.object({
11770
+ logger: z.any().optional(),
11771
+ events: z.any().optional(),
11772
+ metrics: z.any().optional(),
11773
+ clock: z.any().optional()
11774
+ }).passthrough();
10971
11775
 
10972
11776
  /**
10973
11777
  * Creates a Zod superRefine validator for recipient address format validation.
@@ -10992,6 +11796,22 @@ var TransferSpeed;
10992
11796
  }
10993
11797
  };
10994
11798
  }
11799
+ /**
11800
+ * Schema for `BridgeParams.token`.
11801
+ *
11802
+ * Accept `'USDC'`, a symbol from {@link KNOWN_TOKEN_SYMBOLS}, or a bytes32 id
11803
+ * (`0x` plus exactly 64 hex characters). Reject unknown symbols, malformed ids,
11804
+ * and `{ provider, id }` objects. A custom extra provider cannot introduce a
11805
+ * new symbol through this field — only a bytes32 id.
11806
+ *
11807
+ * Omit the field to default to `'USDC'`.
11808
+ */ const bridgeTokenSchema = z.union([
11809
+ z.enum([
11810
+ 'USDC',
11811
+ ...KNOWN_TOKEN_SYMBOLS
11812
+ ]),
11813
+ z.string().regex(/^0x[0-9a-fA-F]{64}$/, 'Token id must be a bytes32 (0x-prefixed, 64 hex chars)')
11814
+ ]);
10995
11815
  /**
10996
11816
  * Schema for validating AdapterContext for bridge operations.
10997
11817
  * Must always contain both adapter and chain explicitly.
@@ -11094,9 +11914,14 @@ var TransferSpeed;
11094
11914
  allowZero: false,
11095
11915
  regexMessage: AMOUNT_FORMAT_ERROR_MESSAGE,
11096
11916
  attributeName: 'amount',
11097
- maxDecimals: 6
11917
+ // Widest precision any routable token needs (wETH = 18). This gate is
11918
+ // token-agnostic and runs before the route provider is known, so it
11919
+ // can only cap coarsely; the token's exact precision is enforced later
11920
+ // at the scaling boundary (`BridgeKit.scaleResolvedAmount`). USDC (6)
11921
+ // and every narrower token stay valid.
11922
+ maxDecimals: 18
11098
11923
  })(z.string())),
11099
- token: z.literal('USDC').optional(),
11924
+ token: bridgeTokenSchema.optional(),
11100
11925
  config: z.object({
11101
11926
  transferSpeed: z.nativeEnum(TransferSpeed).optional(),
11102
11927
  feePayment: z.enum([
@@ -11107,150 +11932,26 @@ var TransferSpeed;
11107
11932
  allowZero: true,
11108
11933
  regexMessage: MAX_FEE_FORMAT_ERROR_MESSAGE,
11109
11934
  attributeName: 'maxFee',
11110
- maxDecimals: 6
11935
+ // See `amount` above: widest routable precision (18); the exact
11936
+ // per-token precision is enforced at the scaling boundary.
11937
+ maxDecimals: 18
11111
11938
  })(z.string())).optional(),
11112
11939
  customFee: customFeeSchema.optional()
11113
11940
  }).optional(),
11114
- quote: z.string().regex(/^0x([a-fA-F0-9]{2})+$/, 'must be non-empty 0x hex').optional()
11115
- });
11116
-
11117
- /**
11118
- * Define a schema for runtime logger interfaces.
11119
- *
11120
- * @remarks
11121
- * Validate that a runtime logger provides the minimal methods expected by the SDK.
11122
- *
11123
- * @example
11124
- * ```typescript
11125
- * import { loggerSchema } from '@core/runtime'
11126
- *
11127
- * const logger = {
11128
- * debug: () => undefined,
11129
- * info: () => undefined,
11130
- * warn: () => undefined,
11131
- * error: () => undefined,
11132
- * child: () => logger,
11133
- * }
11134
- *
11135
- * loggerSchema.parse(logger)
11136
- * ```
11137
- */ const loggerSchema = z.custom((value)=>{
11138
- if (value === null || typeof value !== 'object') {
11139
- return false;
11140
- }
11141
- const record = value;
11142
- return typeof record['debug'] === 'function' && typeof record['info'] === 'function' && typeof record['warn'] === 'function' && typeof record['error'] === 'function' && typeof record['child'] === 'function';
11143
- }, {
11144
- message: 'Invalid logger'
11145
- });
11146
-
11147
- /**
11148
- * Define a schema for runtime metrics interfaces.
11149
- *
11150
- * @remarks
11151
- * Validate that a metrics implementation exposes the minimal API expected by the runtime.
11152
- *
11153
- * @example
11154
- * ```typescript
11155
- * import { metricsSchema } from '@core/runtime'
11156
- *
11157
- * const metrics = {
11158
- * counter: () => ({ inc: () => undefined }),
11159
- * histogram: () => ({ observe: () => undefined }),
11160
- * timer: () => ({ start: () => () => undefined }),
11161
- * child: () => metrics,
11162
- * }
11163
- *
11164
- * metricsSchema.parse(metrics)
11165
- * ```
11166
- */ const metricsSchema = z.custom((value)=>{
11167
- if (value === null || typeof value !== 'object') {
11168
- return false;
11169
- }
11170
- const record = value;
11171
- return typeof record['counter'] === 'function' && typeof record['histogram'] === 'function' && typeof record['timer'] === 'function' && typeof record['child'] === 'function';
11172
- }, {
11173
- message: 'Invalid metrics'
11174
- });
11175
-
11176
- // ============================================================================
11177
- // Validation Schema
11178
- // ============================================================================
11179
- /**
11180
- * Schema for validating {@link RuntimeOptions}.
11181
- *
11182
- * @remarks
11183
- * Used internally by {@link createRuntime} to validate options from JS consumers.
11184
- * Exported for advanced use cases where manual validation is needed.
11185
- */ z.object({
11186
- logger: loggerSchema.optional(),
11187
- metrics: metricsSchema.optional()
11188
- }).passthrough();
11189
-
11190
- // ============================================================================
11191
- // Validation Schemas
11192
- // ============================================================================
11193
- /**
11194
- * Schema for validating Caller.
11195
- */ const callerSchema = z.object({
11196
- type: z.string(),
11197
- name: z.string(),
11198
- version: z.string().optional()
11941
+ // Top-level (not nested under `config`) to mirror `BridgeParams.quote`.
11942
+ //
11943
+ // `z.unknown()` rather than a shape: the quote belongs to whichever provider
11944
+ // issued it, and a route is matched to a provider only after these
11945
+ // parameters are validated, so there is no one shape to check here.
11946
+ //
11947
+ // It also keeps the value intact. This object strips unknown keys, so a
11948
+ // nested `z.object()` would clone the quote and drop every key not listed
11949
+ // losing a field the issuing provider added, between `estimate` and
11950
+ // `bridge`. Shape is checked where the quote is consumed instead: CCTPx
11951
+ // against its own envelope schema, and the receive-exact path in
11952
+ // `sourceFees.ts` before it calls the Fee Service.
11953
+ quote: z.unknown().optional()
11199
11954
  });
11200
- /**
11201
- * Schema for validating InvocationMeta input.
11202
- */ z.object({
11203
- traceId: z.string().optional(),
11204
- runtime: z.object({}).passthrough().optional(),
11205
- tokens: z.object({}).passthrough().optional(),
11206
- callers: z.array(callerSchema).optional(),
11207
- signal: z.instanceof(AbortSignal).optional()
11208
- }).strict();
11209
-
11210
- /**
11211
- * Runtime package providing cross-cutting infrastructure for SDK operations.
11212
- *
11213
- * @remarks
11214
- * This package provides the core runtime infrastructure including:
11215
- *
11216
- * - **Runtime**: Complete container for logger, metrics, events, and clock
11217
- * - **ExecutionContext**: Context for middleware with observability surface
11218
- * - **Logger**: Isomorphic structured logging via {@link createLogger}
11219
- * - **Events**: Type-safe event bus with {@link createEventBus}
11220
- * - **Pipeline**: Middleware-based operation execution with {@link createPipeline}
11221
- * - **Metrics**: Pluggable metrics collection with dimensional tags
11222
- *
11223
- * @example
11224
- * ```typescript
11225
- * import {
11226
- * createRuntime,
11227
- * createExecutionContext,
11228
- * createOpId,
11229
- * createTraceId,
11230
- * type Runtime,
11231
- * type ExecutionContext,
11232
- * } from '@core/runtime'
11233
- *
11234
- * // Create a complete runtime
11235
- * const runtime = createRuntime()
11236
- *
11237
- * // All services are guaranteed present
11238
- * runtime.logger.info('Starting operation')
11239
- * runtime.metrics.counter('requests').inc()
11240
- * runtime.events.emit({ name: 'operation.started' })
11241
- * ```
11242
- *
11243
- * @packageDocumentation
11244
- */ // Core types
11245
- // Clock - expose defaultClock for backward compatibility
11246
- /** Clock validation schema (backward compatibility). */ z.custom((val)=>val !== null && typeof val === 'object' && 'now' in val && typeof val['now'] === 'function');
11247
- /** EventBus validation schema (backward compatibility). */ z.custom((val)=>val !== null && typeof val === 'object' && 'emit' in val && typeof val['emit'] === 'function');
11248
- /** Runtime validation schema (backward compatibility). */ z.object({
11249
- logger: z.any().optional(),
11250
- events: z.any().optional(),
11251
- metrics: z.any().optional(),
11252
- clock: z.any().optional()
11253
- }).passthrough();
11254
11955
 
11255
11956
  /**
11256
11957
  * The ASCII "cctp-forward" magic, hex-encoded (no `0x`), that a forward-friendly
@@ -11280,6 +11981,9 @@ var TransferSpeed;
11280
11981
  [TransferSpeed.SLOW]: 2000
11281
11982
  });
11282
11983
 
11984
+ createLogger({
11985
+ name: 'provider-cctp-v2'
11986
+ });
11283
11987
  /**
11284
11988
  * All chains that are supported by the CCTP v2 provider.
11285
11989
  *
@@ -11289,7 +11993,11 @@ var TransferSpeed;
11289
11993
  * @internal
11290
11994
  */ Object.values(Chains).filter((chain)=>isCCTPV2Supported(chain));
11291
11995
 
11292
- /** 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
11996
+ /**
11997
+ * Decimal string in token minor units, constrained to be strictly positive.
11998
+ *
11999
+ * @internal
12000
+ */ 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
11293
12001
  // regex check above fails ("dirty"), so guard BigInt() against throwing on a
11294
12002
  // non-numeric value before comparing.
11295
12003
  .refine((value)=>/^\d+$/.test(value) && BigInt(value) > 0n, 'must be greater than zero');
@@ -11324,11 +12032,19 @@ const forwardRequestSchema = z.object({
11324
12032
  const preFinalityRequestSchema = z.object({
11325
12033
  type: z.literal('PRE_FINALITY')
11326
12034
  }).strict();
11327
- /** A single quote request item (`FORWARD` or `PRE_FINALITY`). */ const feeQuoteRequestSchema = z.discriminatedUnion('type', [
12035
+ /**
12036
+ * A single quote request item (`FORWARD` or `PRE_FINALITY`).
12037
+ *
12038
+ * @internal
12039
+ */ const feeQuoteRequestSchema = z.discriminatedUnion('type', [
11328
12040
  forwardRequestSchema,
11329
12041
  preFinalityRequestSchema
11330
12042
  ]);
11331
- /** 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');
12043
+ /**
12044
+ * A non-empty list of quote request items with unique types.
12045
+ *
12046
+ * @internal
12047
+ */ 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');
11332
12048
  /**
11333
12049
  * A structured `Partial<ApiPollingConfig>` polling override.
11334
12050
  *
@@ -11356,6 +12072,8 @@ const preFinalityRequestSchema = z.object({
11356
12072
  * it `undefined`, which is falsy and silently selects the production base URL.
11357
12073
  * (`buildFeeQuoteUrl` independently re-validates the domains for standalone
11358
12074
  * callers.)
12075
+ *
12076
+ * @internal
11359
12077
  */ z.object({
11360
12078
  sourceDomain: z.number().int().nonnegative(),
11361
12079
  destinationDomain: z.number().int().nonnegative(),
@@ -11391,7 +12109,11 @@ const metadataSchema = z.object({
11391
12109
  blockEstimatedAt: z.number().int().nonnegative().optional()
11392
12110
  }).passthrough()
11393
12111
  ]);
11394
- /** Schema for a signed fee quote returned by the Quote API. */ z.object({
12112
+ /**
12113
+ * Schema for a signed fee quote returned by the Quote API.
12114
+ *
12115
+ * @internal
12116
+ */ z.object({
11395
12117
  // The runtime YAML spec maps signedQuote to a looser `hex` (which allows
11396
12118
  // an empty `0x`); we keep the stricter non-empty form. Do not relax
11397
12119
  // without a reason.
@@ -11405,7 +12127,11 @@ const metadataSchema = z.object({
11405
12127
  items: z.array(feeQuoteItemSchema),
11406
12128
  metadata: metadataSchema.optional()
11407
12129
  }).passthrough();
11408
- /** Validate input to {@link validateQuote}. */ z.object({
12130
+ /**
12131
+ * Validates input to {@link validateQuote}.
12132
+ *
12133
+ * @internal
12134
+ */ z.object({
11409
12135
  sourceDomain: z.number().int().nonnegative(),
11410
12136
  abiSignature: z.string().min(1),
11411
12137
  args: z.array(z.union([
@@ -11440,11 +12166,13 @@ const validateQuoteItemSchema = z.object({
11440
12166
  computedArgsHash: bytes32Schema.optional()
11441
12167
  }).passthrough();
11442
12168
  /**
11443
- * Schema for a response from the Quote API validation endpoint.
12169
+ * Schema for a validate-quote result returned by the Iris `/validate/usdc/:sourceDomain` endpoint.
11444
12170
  *
11445
12171
  * The endpoint takes the source domain as a URL path parameter and does not
11446
12172
  * return it in the response body, so `sourceDomain` is intentionally not part
11447
12173
  * of this schema.
12174
+ *
12175
+ * @internal
11448
12176
  */ z.object({
11449
12177
  signedQuote: nonEmptyHexSchema,
11450
12178
  expiry: quoteExpiryStatusSchema,
@@ -11464,7 +12192,7 @@ const validateQuoteItemSchema = z.object({
11464
12192
  registerKit(`${pkg$2.name}/${pkg$2.version}`);
11465
12193
 
11466
12194
  var name$1 = "@circle-fin/swap-kit";
11467
- var version$1 = "1.6.0";
12195
+ var version$1 = "1.7.0";
11468
12196
  var pkg$1 = {
11469
12197
  name: name$1,
11470
12198
  version: version$1};
@@ -14725,6 +15453,11 @@ function resolveFeePayoutChain(tokenIn, tokenOut, sourceChain, destinationChain)
14725
15453
  name: 'USDC',
14726
15454
  version: '2'
14727
15455
  },
15456
+ Arc: {
15457
+ chainId: Arc.chainId,
15458
+ name: 'USDC',
15459
+ version: '2'
15460
+ },
14728
15461
  Arc_Testnet: {
14729
15462
  chainId: ArcTestnet.chainId,
14730
15463
  name: 'USDC',
@@ -21836,7 +22569,7 @@ registerKit(`${pkg$1.name}/${pkg$1.version}`);
21836
22569
  };
21837
22570
 
21838
22571
  var name = "@circle-fin/earn-kit";
21839
- var version = "1.6.0";
22572
+ var version = "1.7.0";
21840
22573
  var pkg = {
21841
22574
  name: name,
21842
22575
  version: version};
@@ -21851,18 +22584,22 @@ var pkg = {
21851
22584
  *
21852
22585
  * @internal
21853
22586
  */ const CHAIN_TO_API = {
22587
+ [Blockchain.Arc]: 'ARC',
21854
22588
  [Blockchain.Arc_Testnet]: 'ARC-TESTNET'
21855
22589
  };
21856
22590
  /**
21857
22591
  * Map SDK source chain identifiers to bridge source-chain strings.
21858
22592
  *
21859
- * Cross-chain Earn deposits currently support Ethereum Sepolia, Arbitrum
21860
- * Sepolia, and Base Sepolia as source chains.
22593
+ * Cross-chain Earn deposits support Ethereum, Arbitrum, and Base (mainnet
22594
+ * and testnet) as source chains.
21861
22595
  *
21862
22596
  * @internal
21863
22597
  */ ({
22598
+ [Blockchain.Arbitrum]: 'ARB',
21864
22599
  [Blockchain.Arbitrum_Sepolia]: 'ARB-SEPOLIA',
22600
+ [Blockchain.Base]: 'BASE',
21865
22601
  [Blockchain.Base_Sepolia]: 'BASE-SEPOLIA',
22602
+ [Blockchain.Ethereum]: 'ETH',
21866
22603
  [Blockchain.Ethereum_Sepolia]: 'ETH-SEPOLIA'
21867
22604
  });
21868
22605
  /**
@@ -21873,13 +22610,20 @@ var pkg = {
21873
22610
  *
21874
22611
  * @internal
21875
22612
  */ ({
22613
+ [Blockchain.Arc]: CHAIN_TO_API[Blockchain.Arc],
21876
22614
  [Blockchain.Arc_Testnet]: CHAIN_TO_API[Blockchain.Arc_Testnet]
21877
22615
  });
21878
22616
  ({
22617
+ [Blockchain.Arbitrum]: {
22618
+ },
21879
22619
  [Blockchain.Arbitrum_Sepolia]: {
21880
22620
  },
22621
+ [Blockchain.Base]: {
22622
+ },
21881
22623
  [Blockchain.Base_Sepolia]: {
21882
22624
  },
22625
+ [Blockchain.Ethereum]: {
22626
+ },
21883
22627
  [Blockchain.Ethereum_Sepolia]: {
21884
22628
  }
21885
22629
  });