@circle-fin/app-kit 1.12.1 → 1.14.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.
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';
@@ -2981,6 +2981,8 @@ class KitError extends Error {
2981
2981
  Blockchain["Optimism_Sepolia"] = "Optimism_Sepolia";
2982
2982
  Blockchain["Pharos"] = "Pharos";
2983
2983
  Blockchain["Pharos_Testnet"] = "Pharos_Testnet";
2984
+ Blockchain["Plasma"] = "Plasma";
2985
+ Blockchain["Plasma_Testnet"] = "Plasma_Testnet";
2984
2986
  Blockchain["Polkadot_Asset_Hub"] = "Polkadot_Asset_Hub";
2985
2987
  Blockchain["Polkadot_Westmint"] = "Polkadot_Westmint";
2986
2988
  Blockchain["Plume"] = "Plume";
@@ -3050,6 +3052,7 @@ var BridgeChain;
3050
3052
  BridgeChain["Morph"] = "Morph";
3051
3053
  BridgeChain["Optimism"] = "Optimism";
3052
3054
  BridgeChain["Pharos"] = "Pharos";
3055
+ BridgeChain["Plasma"] = "Plasma";
3053
3056
  BridgeChain["Plume"] = "Plume";
3054
3057
  BridgeChain["Polygon"] = "Polygon";
3055
3058
  BridgeChain["Sei"] = "Sei";
@@ -3076,6 +3079,7 @@ var BridgeChain;
3076
3079
  BridgeChain["Morph_Testnet"] = "Morph_Testnet";
3077
3080
  BridgeChain["Optimism_Sepolia"] = "Optimism_Sepolia";
3078
3081
  BridgeChain["Pharos_Testnet"] = "Pharos_Testnet";
3082
+ BridgeChain["Plasma_Testnet"] = "Plasma_Testnet";
3079
3083
  BridgeChain["Plume_Testnet"] = "Plume_Testnet";
3080
3084
  BridgeChain["Polygon_Amoy_Testnet"] = "Polygon_Amoy_Testnet";
3081
3085
  BridgeChain["Sei_Testnet"] = "Sei_Testnet";
@@ -3533,6 +3537,45 @@ var EarnChain;
3533
3537
  * This program handles minting operations for Gateway transactions
3534
3538
  * on Solana devnet.
3535
3539
  */ const GATEWAY_MINTER_SOLANA_DEVNET = 'GATEmKK2ECL1brEngQZWCgMWPbvrEYqsV6u29dAaHavr';
3540
+ /**
3541
+ * The `TokenMessengerWithFees` proxy contract address for EVM mainnet networks
3542
+ * (all chains except Edge).
3543
+ *
3544
+ * Deployed at a CREATE3-derived address; identical across all mainnet EVM
3545
+ * source chains. Present on any chain that supports the prepaid FORWARD path
3546
+ * via `depositForBurnWithHookAndFees`.
3547
+ */ const TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET = '0x71f54F818671cD0D7ea140Da213e5C8b5C92a408';
3548
+ /**
3549
+ * The `TokenMessengerWithFees` proxy contract address for EVM testnet networks.
3550
+ *
3551
+ * Identical across all testnet EVM source chains. Present on any testnet chain
3552
+ * that supports the prepaid FORWARD path via `depositForBurnWithHookAndFees`.
3553
+ */ const TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET = '0x8745D906D67C346E5eb1aEEED38Eb87F34DF0C0A';
3554
+ /**
3555
+ * The `DepositForHandler` proxy contract address for EVM mainnet networks.
3556
+ *
3557
+ * The handler the GenericExecutor calls on a fast-deposit destination chain to
3558
+ * run a cross-chain deposit into the GatewayWallet. Deployed at the same
3559
+ * address across all mainnet EVM destination chains.
3560
+ */ const DEPOSIT_FOR_HANDLER_EVM_MAINNET = '0x16529813203f77E036576666336554a1210dce4D';
3561
+ /**
3562
+ * The `DepositForHandler` proxy contract address for EVM testnet networks.
3563
+ *
3564
+ * Identical across all testnet EVM destination chains.
3565
+ */ const DEPOSIT_FOR_HANDLER_EVM_TESTNET = '0xD05E7D2E7d30b92c5F17d7d0fC575fce231F1A48';
3566
+ /**
3567
+ * The `GenericExecutor` proxy contract address for EVM mainnet networks.
3568
+ *
3569
+ * The GenericExecutor is the `mintRecipient` and `destinationCaller` on the
3570
+ * destination chain for the CCTP v2 prepaid FORWARD path. It receives the CCTP
3571
+ * mint and calls the `DepositForHandler` to complete the fast deposit.
3572
+ * Deployed at the same address across all mainnet EVM destination chains.
3573
+ */ const GENERIC_EXECUTOR_EVM_MAINNET = '0xFa7be2f04F3Ad4ca969260729c6d45B5625984A7';
3574
+ /**
3575
+ * The `GenericExecutor` proxy contract address for EVM testnet networks.
3576
+ *
3577
+ * Identical across all testnet EVM destination chains.
3578
+ */ const GENERIC_EXECUTOR_EVM_TESTNET = '0xEdC81040756AcCfF070c21D37b265b9D0b5Ba45e';
3536
3579
 
3537
3580
  /**
3538
3581
  * Arc Testnet chain definition
@@ -3570,6 +3613,7 @@ var EarnChain;
3570
3613
  v2: {
3571
3614
  type: 'split',
3572
3615
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
3616
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
3573
3617
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
3574
3618
  confirmations: 1,
3575
3619
  fastConfirmations: 1
@@ -3590,9 +3634,8 @@ var EarnChain;
3590
3634
  v1: {
3591
3635
  wallet: GATEWAY_WALLET_EVM_TESTNET,
3592
3636
  minter: GATEWAY_MINTER_EVM_TESTNET,
3593
- // DepositForHandler the GenericExecutor calls to run a fast cross-chain
3594
- // deposit into the GatewayWallet above.
3595
- depositForHandler: '0xD05E7D2E7d30b92c5F17d7d0fC575fce231F1A48'
3637
+ depositForHandler: DEPOSIT_FOR_HANDLER_EVM_TESTNET,
3638
+ genericExecutor: GENERIC_EXECUTOR_EVM_TESTNET
3596
3639
  }
3597
3640
  },
3598
3641
  forwarderSupported: {
@@ -3637,6 +3680,7 @@ var EarnChain;
3637
3680
  v2: {
3638
3681
  type: 'split',
3639
3682
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
3683
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
3640
3684
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
3641
3685
  confirmations: 65,
3642
3686
  fastConfirmations: 1
@@ -3701,6 +3745,7 @@ var EarnChain;
3701
3745
  v2: {
3702
3746
  type: 'split',
3703
3747
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
3748
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
3704
3749
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
3705
3750
  confirmations: 65,
3706
3751
  fastConfirmations: 1
@@ -3765,6 +3810,7 @@ var EarnChain;
3765
3810
  v2: {
3766
3811
  type: 'split',
3767
3812
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
3813
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
3768
3814
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
3769
3815
  confirmations: 1,
3770
3816
  fastConfirmations: 1
@@ -3784,7 +3830,9 @@ var EarnChain;
3784
3830
  contracts: {
3785
3831
  v1: {
3786
3832
  wallet: GATEWAY_WALLET_EVM_MAINNET,
3787
- minter: GATEWAY_MINTER_EVM_MAINNET
3833
+ minter: GATEWAY_MINTER_EVM_MAINNET,
3834
+ depositForHandler: DEPOSIT_FOR_HANDLER_EVM_MAINNET,
3835
+ genericExecutor: GENERIC_EXECUTOR_EVM_MAINNET
3788
3836
  }
3789
3837
  },
3790
3838
  forwarderSupported: {
@@ -3826,6 +3874,7 @@ var EarnChain;
3826
3874
  v2: {
3827
3875
  type: 'split',
3828
3876
  tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
3877
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
3829
3878
  messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
3830
3879
  confirmations: 1,
3831
3880
  fastConfirmations: 1
@@ -3847,7 +3896,9 @@ var EarnChain;
3847
3896
  contracts: {
3848
3897
  v1: {
3849
3898
  wallet: GATEWAY_WALLET_EVM_TESTNET,
3850
- minter: GATEWAY_MINTER_EVM_TESTNET
3899
+ minter: GATEWAY_MINTER_EVM_TESTNET,
3900
+ depositForHandler: DEPOSIT_FOR_HANDLER_EVM_TESTNET,
3901
+ genericExecutor: GENERIC_EXECUTOR_EVM_TESTNET
3851
3902
  }
3852
3903
  },
3853
3904
  forwarderSupported: {
@@ -3893,6 +3944,7 @@ var EarnChain;
3893
3944
  v2: {
3894
3945
  type: 'split',
3895
3946
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
3947
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
3896
3948
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
3897
3949
  confirmations: 65,
3898
3950
  fastConfirmations: 1
@@ -3957,6 +4009,7 @@ var EarnChain;
3957
4009
  v2: {
3958
4010
  type: 'split',
3959
4011
  tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
4012
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
3960
4013
  messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
3961
4014
  confirmations: 65,
3962
4015
  fastConfirmations: 1
@@ -4067,6 +4120,7 @@ var EarnChain;
4067
4120
  v2: {
4068
4121
  type: 'split',
4069
4122
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
4123
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
4070
4124
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
4071
4125
  confirmations: 65,
4072
4126
  fastConfirmations: 1
@@ -4111,6 +4165,7 @@ var EarnChain;
4111
4165
  v2: {
4112
4166
  type: 'split',
4113
4167
  tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
4168
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4114
4169
  messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
4115
4170
  confirmations: 65,
4116
4171
  fastConfirmations: 1
@@ -4156,6 +4211,7 @@ var EarnChain;
4156
4211
  v2: {
4157
4212
  type: 'split',
4158
4213
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
4214
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
4159
4215
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
4160
4216
  confirmations: 1,
4161
4217
  fastConfirmations: 1
@@ -4201,6 +4257,7 @@ var EarnChain;
4201
4257
  v2: {
4202
4258
  type: 'split',
4203
4259
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
4260
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4204
4261
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
4205
4262
  confirmations: 1,
4206
4263
  fastConfirmations: 1
@@ -4246,6 +4303,7 @@ var EarnChain;
4246
4303
  v2: {
4247
4304
  type: 'split',
4248
4305
  tokenMessenger: '0x98706A006bc632Df31CAdFCBD43F38887ce2ca5c',
4306
+ tokenMessengerWithFees: '0x3Ac96675F9a3E6922713e041645D82f3561d3686',
4249
4307
  messageTransmitter: '0x5b61381Fc9e58E70EfC13a4A97516997019198ee',
4250
4308
  confirmations: 65,
4251
4309
  fastConfirmations: 1
@@ -4291,6 +4349,7 @@ var EarnChain;
4291
4349
  v2: {
4292
4350
  type: 'split',
4293
4351
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
4352
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4294
4353
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
4295
4354
  confirmations: 65,
4296
4355
  fastConfirmations: 1
@@ -4342,6 +4401,7 @@ var EarnChain;
4342
4401
  v2: {
4343
4402
  type: 'split',
4344
4403
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
4404
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
4345
4405
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
4346
4406
  confirmations: 65,
4347
4407
  fastConfirmations: 2
@@ -4406,6 +4466,7 @@ var EarnChain;
4406
4466
  v2: {
4407
4467
  type: 'split',
4408
4468
  tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
4469
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4409
4470
  messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
4410
4471
  confirmations: 65,
4411
4472
  fastConfirmations: 2
@@ -4516,6 +4577,7 @@ var EarnChain;
4516
4577
  v2: {
4517
4578
  type: 'split',
4518
4579
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
4580
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
4519
4581
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
4520
4582
  confirmations: 1,
4521
4583
  fastConfirmations: 1
@@ -4575,6 +4637,7 @@ var EarnChain;
4575
4637
  v2: {
4576
4638
  type: 'split',
4577
4639
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
4640
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4578
4641
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
4579
4642
  confirmations: 1,
4580
4643
  fastConfirmations: 1
@@ -4635,6 +4698,7 @@ var EarnChain;
4635
4698
  v2: {
4636
4699
  type: 'split',
4637
4700
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
4701
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
4638
4702
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
4639
4703
  confirmations: 1,
4640
4704
  fastConfirmations: 1
@@ -4682,6 +4746,7 @@ var EarnChain;
4682
4746
  v2: {
4683
4747
  type: 'split',
4684
4748
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
4749
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4685
4750
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
4686
4751
  confirmations: 1,
4687
4752
  fastConfirmations: 1
@@ -4729,6 +4794,7 @@ var EarnChain;
4729
4794
  v2: {
4730
4795
  type: 'split',
4731
4796
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
4797
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
4732
4798
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
4733
4799
  confirmations: 65,
4734
4800
  fastConfirmations: 1
@@ -4776,6 +4842,7 @@ var EarnChain;
4776
4842
  v2: {
4777
4843
  type: 'split',
4778
4844
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
4845
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4779
4846
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
4780
4847
  confirmations: 65,
4781
4848
  fastConfirmations: 1
@@ -4820,6 +4887,7 @@ var EarnChain;
4820
4887
  v2: {
4821
4888
  type: 'split',
4822
4889
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
4890
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
4823
4891
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
4824
4892
  confirmations: 1,
4825
4893
  fastConfirmations: 1
@@ -4865,6 +4933,7 @@ var EarnChain;
4865
4933
  v2: {
4866
4934
  type: 'split',
4867
4935
  tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
4936
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4868
4937
  messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
4869
4938
  confirmations: 1,
4870
4939
  fastConfirmations: 1
@@ -4911,6 +4980,7 @@ var EarnChain;
4911
4980
  v2: {
4912
4981
  type: 'split',
4913
4982
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
4983
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
4914
4984
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
4915
4985
  confirmations: 1,
4916
4986
  fastConfirmations: 1
@@ -4958,6 +5028,7 @@ var EarnChain;
4958
5028
  v2: {
4959
5029
  type: 'split',
4960
5030
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
5031
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4961
5032
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
4962
5033
  confirmations: 1,
4963
5034
  fastConfirmations: 1
@@ -5003,6 +5074,7 @@ var EarnChain;
5003
5074
  v2: {
5004
5075
  type: 'split',
5005
5076
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
5077
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
5006
5078
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
5007
5079
  confirmations: 64,
5008
5080
  fastConfirmations: 1
@@ -5048,6 +5120,7 @@ var EarnChain;
5048
5120
  v2: {
5049
5121
  type: 'split',
5050
5122
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
5123
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
5051
5124
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
5052
5125
  confirmations: 64,
5053
5126
  fastConfirmations: 1
@@ -5224,6 +5297,7 @@ var EarnChain;
5224
5297
  v2: {
5225
5298
  type: 'split',
5226
5299
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
5300
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
5227
5301
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
5228
5302
  confirmations: 65,
5229
5303
  fastConfirmations: 1
@@ -5288,6 +5362,7 @@ var EarnChain;
5288
5362
  v2: {
5289
5363
  type: 'split',
5290
5364
  tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
5365
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
5291
5366
  messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
5292
5367
  confirmations: 65,
5293
5368
  fastConfirmations: 1
@@ -5347,6 +5422,7 @@ var EarnChain;
5347
5422
  v2: {
5348
5423
  type: 'split',
5349
5424
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
5425
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
5350
5426
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
5351
5427
  confirmations: 1,
5352
5428
  fastConfirmations: 1
@@ -5393,6 +5469,7 @@ var EarnChain;
5393
5469
  v2: {
5394
5470
  type: 'split',
5395
5471
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
5472
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
5396
5473
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
5397
5474
  confirmations: 1,
5398
5475
  fastConfirmations: 1
@@ -5408,6 +5485,98 @@ var EarnChain;
5408
5485
  }
5409
5486
  });
5410
5487
 
5488
+ /**
5489
+ * Plasma Mainnet chain definition
5490
+ * @remarks
5491
+ * This represents the official production network for the Plasma blockchain.
5492
+ * Plasma is an EVM-equivalent Layer 1 blockchain purpose-built for global
5493
+ * stablecoin payments, with deterministic BFT finality (PlasmaBFT/Fast-HotStuff).
5494
+ */ const Plasma = defineChain({
5495
+ type: 'evm',
5496
+ chain: Blockchain.Plasma,
5497
+ name: 'Plasma',
5498
+ title: 'Plasma Mainnet',
5499
+ nativeCurrency: {
5500
+ name: 'Plasma',
5501
+ symbol: 'XPL',
5502
+ decimals: 18
5503
+ },
5504
+ chainId: 9745,
5505
+ isTestnet: false,
5506
+ explorerUrl: 'https://plasmascan.to/tx/{hash}',
5507
+ rpcEndpoints: [
5508
+ 'https://rpc.plasma.to'
5509
+ ],
5510
+ eurcAddress: '0x3EE196E78d4d4248b849B8E1C7F44C5457FAFD2C',
5511
+ usdcAddress: '0x2d661C89D812261039AF9764eceaAee884f5F67F',
5512
+ usdtAddress: null,
5513
+ cctp: {
5514
+ domain: 33,
5515
+ contracts: {
5516
+ v2: {
5517
+ type: 'split',
5518
+ tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
5519
+ messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
5520
+ confirmations: 3,
5521
+ fastConfirmations: 1
5522
+ }
5523
+ },
5524
+ forwarderSupported: {
5525
+ source: false,
5526
+ destination: false
5527
+ }
5528
+ },
5529
+ kitContracts: {
5530
+ bridge: BRIDGE_CONTRACT_EVM_MAINNET
5531
+ }
5532
+ });
5533
+
5534
+ /**
5535
+ * Plasma Testnet chain definition
5536
+ * @remarks
5537
+ * This represents the official test network for the Plasma blockchain.
5538
+ * Plasma is an EVM-equivalent Layer 1 blockchain purpose-built for global
5539
+ * stablecoin payments, with deterministic BFT finality (PlasmaBFT/Fast-HotStuff).
5540
+ */ const PlasmaTestnet = defineChain({
5541
+ type: 'evm',
5542
+ chain: Blockchain.Plasma_Testnet,
5543
+ name: 'Plasma Testnet',
5544
+ title: 'Plasma Testnet',
5545
+ nativeCurrency: {
5546
+ name: 'Plasma',
5547
+ symbol: 'XPL',
5548
+ decimals: 18
5549
+ },
5550
+ chainId: 9746,
5551
+ isTestnet: true,
5552
+ explorerUrl: 'https://testnet.plasmascan.to/tx/{hash}',
5553
+ rpcEndpoints: [
5554
+ 'https://testnet-rpc.plasma.to'
5555
+ ],
5556
+ eurcAddress: '0x98AfA0F93Dd993B736399f9074eDcEBD1985A330',
5557
+ usdcAddress: '0xE67Fb267022cBA8064Dd388CC2FED724F3120D9D',
5558
+ usdtAddress: null,
5559
+ cctp: {
5560
+ domain: 33,
5561
+ contracts: {
5562
+ v2: {
5563
+ type: 'split',
5564
+ tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
5565
+ messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
5566
+ confirmations: 3,
5567
+ fastConfirmations: 1
5568
+ }
5569
+ },
5570
+ forwarderSupported: {
5571
+ source: false,
5572
+ destination: false
5573
+ }
5574
+ },
5575
+ kitContracts: {
5576
+ bridge: BRIDGE_CONTRACT_EVM_TESTNET
5577
+ }
5578
+ });
5579
+
5411
5580
  /**
5412
5581
  * Plume Mainnet chain definition
5413
5582
  * @remarks
@@ -5439,6 +5608,7 @@ var EarnChain;
5439
5608
  v2: {
5440
5609
  type: 'split',
5441
5610
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
5611
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
5442
5612
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
5443
5613
  confirmations: 65,
5444
5614
  fastConfirmations: 1
@@ -5485,6 +5655,7 @@ var EarnChain;
5485
5655
  v2: {
5486
5656
  type: 'split',
5487
5657
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
5658
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
5488
5659
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
5489
5660
  confirmations: 65,
5490
5661
  fastConfirmations: 1
@@ -5586,6 +5757,7 @@ var EarnChain;
5586
5757
  v2: {
5587
5758
  type: 'split',
5588
5759
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
5760
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
5589
5761
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
5590
5762
  confirmations: 33,
5591
5763
  fastConfirmations: 13
@@ -5605,7 +5777,9 @@ var EarnChain;
5605
5777
  contracts: {
5606
5778
  v1: {
5607
5779
  wallet: GATEWAY_WALLET_EVM_MAINNET,
5608
- minter: GATEWAY_MINTER_EVM_MAINNET
5780
+ minter: GATEWAY_MINTER_EVM_MAINNET,
5781
+ depositForHandler: DEPOSIT_FOR_HANDLER_EVM_MAINNET,
5782
+ genericExecutor: GENERIC_EXECUTOR_EVM_MAINNET
5609
5783
  }
5610
5784
  },
5611
5785
  forwarderSupported: {
@@ -5651,6 +5825,7 @@ var EarnChain;
5651
5825
  v2: {
5652
5826
  type: 'split',
5653
5827
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
5828
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
5654
5829
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
5655
5830
  confirmations: 33,
5656
5831
  fastConfirmations: 13
@@ -5669,7 +5844,9 @@ var EarnChain;
5669
5844
  contracts: {
5670
5845
  v1: {
5671
5846
  wallet: GATEWAY_WALLET_EVM_TESTNET,
5672
- minter: GATEWAY_MINTER_EVM_TESTNET
5847
+ minter: GATEWAY_MINTER_EVM_TESTNET,
5848
+ depositForHandler: DEPOSIT_FOR_HANDLER_EVM_TESTNET,
5849
+ genericExecutor: GENERIC_EXECUTOR_EVM_TESTNET
5673
5850
  }
5674
5851
  },
5675
5852
  forwarderSupported: {
@@ -5710,6 +5887,7 @@ var EarnChain;
5710
5887
  v2: {
5711
5888
  type: 'split',
5712
5889
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
5890
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
5713
5891
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
5714
5892
  confirmations: 1,
5715
5893
  fastConfirmations: 1
@@ -5769,6 +5947,7 @@ var EarnChain;
5769
5947
  v2: {
5770
5948
  type: 'split',
5771
5949
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
5950
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
5772
5951
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
5773
5952
  confirmations: 1,
5774
5953
  fastConfirmations: 1
@@ -5826,6 +6005,7 @@ var EarnChain;
5826
6005
  v2: {
5827
6006
  type: 'split',
5828
6007
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
6008
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
5829
6009
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
5830
6010
  confirmations: 1,
5831
6011
  fastConfirmations: 1
@@ -5884,6 +6064,7 @@ var EarnChain;
5884
6064
  v2: {
5885
6065
  type: 'split',
5886
6066
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
6067
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
5887
6068
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
5888
6069
  confirmations: 1,
5889
6070
  fastConfirmations: 1
@@ -6199,6 +6380,7 @@ var EarnChain;
6199
6380
  v2: {
6200
6381
  type: 'split',
6201
6382
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
6383
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
6202
6384
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
6203
6385
  confirmations: 65,
6204
6386
  fastConfirmations: 1
@@ -6263,6 +6445,7 @@ var EarnChain;
6263
6445
  v2: {
6264
6446
  type: 'split',
6265
6447
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
6448
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
6266
6449
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
6267
6450
  confirmations: 65,
6268
6451
  fastConfirmations: 1
@@ -6320,6 +6503,7 @@ var EarnChain;
6320
6503
  v2: {
6321
6504
  type: 'split',
6322
6505
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cF5d',
6506
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
6323
6507
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
6324
6508
  confirmations: 65,
6325
6509
  fastConfirmations: 1
@@ -6379,6 +6563,7 @@ var EarnChain;
6379
6563
  v2: {
6380
6564
  type: 'split',
6381
6565
  tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
6566
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
6382
6567
  messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
6383
6568
  confirmations: 65,
6384
6569
  fastConfirmations: 1
@@ -6439,6 +6624,7 @@ var EarnChain;
6439
6624
  v2: {
6440
6625
  type: 'split',
6441
6626
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
6627
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
6442
6628
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
6443
6629
  confirmations: 3,
6444
6630
  fastConfirmations: 3
@@ -6484,6 +6670,7 @@ var EarnChain;
6484
6670
  v2: {
6485
6671
  type: 'split',
6486
6672
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
6673
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
6487
6674
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
6488
6675
  confirmations: 3,
6489
6676
  fastConfirmations: 1
@@ -6694,6 +6881,8 @@ var Chains = /*#__PURE__*/Object.freeze({
6694
6881
  OptimismSepolia: OptimismSepolia,
6695
6882
  Pharos: Pharos,
6696
6883
  PharosTestnet: PharosTestnet,
6884
+ Plasma: Plasma,
6885
+ PlasmaTestnet: PlasmaTestnet,
6697
6886
  Plume: Plume,
6698
6887
  PlumeTestnet: PlumeTestnet,
6699
6888
  PolkadotAssetHub: PolkadotAssetHub,
@@ -6743,6 +6932,67 @@ var Chains = /*#__PURE__*/Object.freeze({
6743
6932
  return chain.cctp?.contracts.v2 !== undefined;
6744
6933
  }
6745
6934
 
6935
+ /**
6936
+ * Chains the Fee Service accepts as a SOURCE for source-paid ("receive-exact")
6937
+ * CCTP v2 fees. An explicit allowlist is required because the
6938
+ * `TokenMessengerWithFees` wrapper address is now shared with the fast-deposit
6939
+ * forwarder path, so wrapper presence no longer implies source-fee support.
6940
+ * Keep in sync with backend coverage.
6941
+ */ new Set([
6942
+ // Mainnet
6943
+ Blockchain.Ethereum,
6944
+ Blockchain.Base,
6945
+ Blockchain.Arbitrum,
6946
+ Blockchain.Unichain,
6947
+ Blockchain.Optimism,
6948
+ Blockchain.Codex,
6949
+ Blockchain.Ink,
6950
+ Blockchain.Plume,
6951
+ Blockchain.Linea,
6952
+ Blockchain.World_Chain,
6953
+ // Testnet counterparts
6954
+ Blockchain.Ethereum_Sepolia,
6955
+ Blockchain.Base_Sepolia,
6956
+ Blockchain.Arbitrum_Sepolia,
6957
+ Blockchain.Unichain_Sepolia,
6958
+ Blockchain.Optimism_Sepolia,
6959
+ Blockchain.Codex_Testnet,
6960
+ Blockchain.Ink_Testnet,
6961
+ Blockchain.Plume_Testnet,
6962
+ Blockchain.Linea_Sepolia,
6963
+ Blockchain.World_Chain_Sepolia
6964
+ ]);
6965
+
6966
+ /**
6967
+ * Temporary allowlist of chains permitted to initiate Gateway fast deposits.
6968
+ * Only chains keyed here are eligible; all others are rejected. Using the
6969
+ * {@link Blockchain} enum keeps entries type-safe and catches typos at compile
6970
+ * time. Remove this allowlist once roll-out is complete.
6971
+ */ new Set([
6972
+ // Mainnet
6973
+ Blockchain.Ethereum,
6974
+ Blockchain.Base,
6975
+ Blockchain.Arbitrum,
6976
+ Blockchain.Unichain,
6977
+ Blockchain.Optimism,
6978
+ Blockchain.Codex,
6979
+ Blockchain.Ink,
6980
+ Blockchain.Plume,
6981
+ Blockchain.Linea,
6982
+ Blockchain.World_Chain,
6983
+ // Testnet counterparts
6984
+ Blockchain.Ethereum_Sepolia,
6985
+ Blockchain.Base_Sepolia,
6986
+ Blockchain.Arbitrum_Sepolia,
6987
+ Blockchain.Unichain_Sepolia,
6988
+ Blockchain.Optimism_Sepolia,
6989
+ Blockchain.Codex_Testnet,
6990
+ Blockchain.Ink_Testnet,
6991
+ Blockchain.Plume_Testnet,
6992
+ Blockchain.Linea_Sepolia,
6993
+ Blockchain.World_Chain_Sepolia
6994
+ ]);
6995
+
6746
6996
  /**
6747
6997
  * Zod schema for validating Gateway v1 contract addresses.
6748
6998
  *
@@ -6764,7 +7014,10 @@ var Chains = /*#__PURE__*/Object.freeze({
6764
7014
  }).min(1, 'Gateway minter address cannot be empty.'),
6765
7015
  depositForHandler: z.string({
6766
7016
  invalid_type_error: 'Gateway depositForHandler address must be a string.'
6767
- }).min(1, 'Gateway depositForHandler address cannot be empty.').optional()
7017
+ }).min(1, 'Gateway depositForHandler address cannot be empty.').optional(),
7018
+ genericExecutor: z.string({
7019
+ invalid_type_error: 'Gateway genericExecutor address must be a string.'
7020
+ }).min(1, 'Gateway genericExecutor address cannot be empty.').optional()
6768
7021
  }).strict() // Reject any additional properties not defined in the schema
6769
7022
  ;
6770
7023
  /**
@@ -8735,6 +8988,7 @@ const swapTokenEnumSchema = z.enum([
8735
8988
  [Blockchain.Noble]: 'uusdc',
8736
8989
  [Blockchain.Optimism]: '0x0b2c639c533813f4aa9d7837caf62653d097ff85',
8737
8990
  [Blockchain.Pharos]: '0xC879C018dB60520F4355C26eD1a6D572cdAC1815',
8991
+ [Blockchain.Plasma]: '0x2d661C89D812261039AF9764eceaAee884f5F67F',
8738
8992
  [Blockchain.Plume]: '0x222365EF19F7947e5484218551B56bb3965Aa7aF',
8739
8993
  [Blockchain.Polkadot_Asset_Hub]: '1337',
8740
8994
  [Blockchain.Polygon]: '0x3c499c542cef5e3811e1192ce70d8cc03d5c3359',
@@ -8771,6 +9025,7 @@ const swapTokenEnumSchema = z.enum([
8771
9025
  [Blockchain.Noble_Testnet]: 'uusdc',
8772
9026
  [Blockchain.Optimism_Sepolia]: '0x5fd84259d66Cd46123540766Be93DFE6D43130D7',
8773
9027
  [Blockchain.Pharos_Testnet]: '0xcfC8330f4BCAB529c625D12781b1C19466A9Fc8B',
9028
+ [Blockchain.Plasma_Testnet]: '0xE67Fb267022cBA8064Dd388CC2FED724F3120D9D',
8774
9029
  [Blockchain.Plume_Testnet]: '0xcB5f30e335672893c7eb944B374c196392C19D18',
8775
9030
  [Blockchain.Polkadot_Westmint]: '31337',
8776
9031
  [Blockchain.Polygon_Amoy_Testnet]: '0x41e94eb019c0762f9bfcf9fb1e58725bfb0e7582',
@@ -8833,6 +9088,7 @@ const swapTokenEnumSchema = z.enum([
8833
9088
  [Blockchain.Base]: '0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42',
8834
9089
  [Blockchain.Cronos]: '0xA6dE01a2d62C6B5f3525d768f34d276652C554c8',
8835
9090
  [Blockchain.Ethereum]: '0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c',
9091
+ [Blockchain.Plasma]: '0x3EE196E78d4d4248b849B8E1C7F44C5457FAFD2C',
8836
9092
  [Blockchain.Solana]: 'HzwqbKZw8HxMN6bF2yFZNrht3c2iXXzpKcFu7uBEDKtr',
8837
9093
  [Blockchain.World_Chain]: '0x1C60ba0A0eD1019e8Eb035E6daF4155A5cE2380B',
8838
9094
  // =========================================================================
@@ -8841,7 +9097,8 @@ const swapTokenEnumSchema = z.enum([
8841
9097
  [Blockchain.Arc_Testnet]: '0x89B50855Aa3bE2F677cD6303Cec089B5F319D72a',
8842
9098
  [Blockchain.Base_Sepolia]: '0x808456652fdb597867f38412077A9182bf77359F',
8843
9099
  [Blockchain.Cronos_Testnet]: '0x31f7538adb53cF16350e6B0c89d03D91b7D12c46',
8844
- [Blockchain.Ethereum_Sepolia]: '0x08210F9170F89Ab7658F0B5E3fF39b0E03C594D4'
9100
+ [Blockchain.Ethereum_Sepolia]: '0x08210F9170F89Ab7658F0B5E3fF39b0E03C594D4',
9101
+ [Blockchain.Plasma_Testnet]: '0x98AfA0F93Dd993B736399f9074eDcEBD1985A330'
8845
9102
  }
8846
9103
  };
8847
9104
 
@@ -9668,7 +9925,7 @@ const swapTokenEnumSchema = z.enum([
9668
9925
  * allowlisted {@link ClientLogPayload} fields (and the allowlisted
9669
9926
  * sub-fields of `errorDetails` / `clientContext`) are copied across.
9670
9927
  * A regressing upstream mapper — or a plain-JS caller that bypasses the
9671
- * type — therefore cannot exfiltrate stray properties (secrets, PII,
9928
+ * type — therefore cannot exfiltrate stray properties (secrets,
9672
9929
  * raw error stacks) through the analytics channel. Optional fields are
9673
9930
  * only included when present so the serialised shape matches the
9674
9931
  * server's strict schema.
@@ -9691,6 +9948,9 @@ const swapTokenEnumSchema = z.enum([
9691
9948
  if (payload.destinationChain !== undefined) safe['destinationChain'] = payload.destinationChain;
9692
9949
  if (payload.tokenIn !== undefined) safe['tokenIn'] = payload.tokenIn;
9693
9950
  if (payload.tokenOut !== undefined) safe['tokenOut'] = payload.tokenOut;
9951
+ if (payload.amountIn !== undefined) safe['amountIn'] = payload.amountIn;
9952
+ if (payload.durationMs !== undefined) safe['durationMs'] = payload.durationMs;
9953
+ if (payload.sourceAddress !== undefined) safe['sourceAddress'] = payload.sourceAddress;
9694
9954
  if (payload.txHash !== undefined) safe['txHash'] = payload.txHash;
9695
9955
  if (payload.correlationId !== undefined) safe['correlationId'] = payload.correlationId;
9696
9956
  if (payload.errorDetails !== undefined) {
@@ -9924,14 +10184,28 @@ const swapTokenEnumSchema = z.enum([
9924
10184
  }
9925
10185
 
9926
10186
  /**
9927
- * Soft signal for the case where building or emitting a telemetry payload
9928
- * threw — for example, a buggy `TelemetryContextResolver`, a regression in
10187
+ * Emit a stable console warning when building or emitting a telemetry payload
10188
+ * throws — for example, a buggy `TelemetryContextResolver`, a regression in
9929
10189
  * `extractErrorDetails`, or a synchronous failure inside `emitAnalyticsLog`
9930
- * before it could swallow the error itself. Logged with a stable prefix so
9931
- * consumers can grep for it. We deliberately do not re-throw: the caller's
9932
- * original operation error must always win.
10190
+ * before it could swallow the error itself. Uses a stable prefix so the
10191
+ * drop is discoverable via grep. Never re-throws: the caller's original
10192
+ * operation error must always win.
9933
10193
  *
9934
10194
  * @internal
10195
+ *
10196
+ * @param eventType - The telemetry event type that was being emitted.
10197
+ * @param cause - The error or value that caused the drop.
10198
+ *
10199
+ * @example
10200
+ * ```typescript
10201
+ * import { warnTelemetryDrop } from '@core/utils'
10202
+ *
10203
+ * try {
10204
+ * void emitAnalyticsLog(payload)
10205
+ * } catch (err) {
10206
+ * warnTelemetryDrop('my_event', err)
10207
+ * }
10208
+ * ```
9935
10209
  */ function warnTelemetryDrop(eventType, cause) {
9936
10210
  try {
9937
10211
  // Pass `cause` as the second console.warn argument rather than
@@ -9971,6 +10245,9 @@ const swapTokenEnumSchema = z.enum([
9971
10245
  ...context?.tokenOut != null && {
9972
10246
  tokenOut: context.tokenOut
9973
10247
  },
10248
+ ...context?.amountIn != null && {
10249
+ amountIn: context.amountIn
10250
+ },
9974
10251
  ...context?.txHash != null && {
9975
10252
  txHash: context.txHash
9976
10253
  },
@@ -10070,7 +10347,7 @@ const swapTokenEnumSchema = z.enum([
10070
10347
  }
10071
10348
 
10072
10349
  var name$2 = "@circle-fin/bridge-kit";
10073
- var version$2 = "1.13.0";
10350
+ var version$2 = "1.14.1";
10074
10351
  var pkg$2 = {
10075
10352
  name: name$2,
10076
10353
  version: version$2};
@@ -10424,7 +10701,7 @@ const READ_ACTION_KEY_SET = new Set(READ_ACTION_KEYS);
10424
10701
  * const result = evmAddressSchema.safeParse(validAddress)
10425
10702
  * console.log(result.success) // true
10426
10703
  * ```
10427
- */ const evmAddressSchema = hexStringSchema.refine((value)=>value.length === 42, 'EVM address must be exactly 42 characters long (0x + 40 hex characters)').transform((value)=>value);
10704
+ */ const evmAddressSchema$1 = hexStringSchema.refine((value)=>value.length === 42, 'EVM address must be exactly 42 characters long (0x + 40 hex characters)').transform((value)=>value);
10428
10705
  /**
10429
10706
  * Schema for validating transaction hashes.
10430
10707
  *
@@ -10961,6 +11238,10 @@ var TransferSpeed;
10961
11238
  token: z.literal('USDC').optional(),
10962
11239
  config: z.object({
10963
11240
  transferSpeed: z.nativeEnum(TransferSpeed).optional(),
11241
+ feePayment: z.enum([
11242
+ 'source',
11243
+ 'destination'
11244
+ ]).optional(),
10964
11245
  maxFee: z.string().min(1, 'Required').pipe(createDecimalStringValidator({
10965
11246
  allowZero: true,
10966
11247
  regexMessage: MAX_FEE_FORMAT_ERROR_MESSAGE,
@@ -10968,7 +11249,8 @@ var TransferSpeed;
10968
11249
  maxDecimals: 6
10969
11250
  })(z.string())).optional(),
10970
11251
  customFee: customFeeSchema.optional()
10971
- }).optional()
11252
+ }).optional(),
11253
+ quote: z.string().regex(/^0x([a-fA-F0-9]{2})+$/, 'must be non-empty 0x hex').optional()
10972
11254
  });
10973
11255
 
10974
11256
  /**
@@ -11030,6 +11312,241 @@ var TransferSpeed;
11030
11312
  message: 'Invalid metrics'
11031
11313
  });
11032
11314
 
11315
+ /**
11316
+ * Omit undefined values from an object.
11317
+ *
11318
+ * @param obj - The object to process.
11319
+ * @returns A new object with undefined values removed.
11320
+ *
11321
+ * @internal
11322
+ * @remarks
11323
+ * Used by both production and mock loggers to ensure consistent behavior.
11324
+ * This prevents undefined values from being serialized in log output,
11325
+ * which can cause issues with some log transports.
11326
+ */ function omitUndefined(obj) {
11327
+ const result = {};
11328
+ for (const [key, value] of Object.entries(obj)){
11329
+ if (value !== undefined) {
11330
+ result[key] = value;
11331
+ }
11332
+ }
11333
+ return result;
11334
+ }
11335
+
11336
+ /**
11337
+ * Default redaction paths for web3/blockchain SDKs.
11338
+ *
11339
+ * @remarks
11340
+ * These paths target common sensitive fields in blockchain applications.
11341
+ * All user fields are nested under `context`, so paths start with `context.`.
11342
+ * Wildcard `*` matches any key at that level.
11343
+ */ const DEFAULT_REDACT_PATHS = [
11344
+ // Generic Credentials
11345
+ 'context.password',
11346
+ 'context.passphrase',
11347
+ 'context.secret',
11348
+ 'context.token',
11349
+ 'context.*.password',
11350
+ 'context.*.passphrase',
11351
+ 'context.*.secret',
11352
+ 'context.*.token',
11353
+ // API Keys & Auth Tokens
11354
+ 'context.apiKey',
11355
+ 'context.apiSecret',
11356
+ 'context.accessToken',
11357
+ 'context.refreshToken',
11358
+ 'context.jwt',
11359
+ 'context.bearerToken',
11360
+ 'context.sessionId',
11361
+ 'context.authorization',
11362
+ 'context.cookie',
11363
+ 'context.*.apiKey',
11364
+ 'context.*.apiSecret',
11365
+ 'context.*.accessToken',
11366
+ 'context.*.refreshToken',
11367
+ 'context.*.jwt',
11368
+ 'context.*.bearerToken',
11369
+ 'context.*.sessionId',
11370
+ 'context.*.authorization',
11371
+ 'context.*.cookie',
11372
+ // Web3 / Crypto Keys
11373
+ 'context.privateKey',
11374
+ 'context.secretKey',
11375
+ 'context.signingKey',
11376
+ 'context.encryptionKey',
11377
+ 'context.*.privateKey',
11378
+ 'context.*.secretKey',
11379
+ 'context.*.signingKey',
11380
+ 'context.*.encryptionKey',
11381
+ // Web3 / Crypto Mnemonics and Seeds
11382
+ 'context.mnemonic',
11383
+ 'context.seed',
11384
+ 'context.seedPhrase',
11385
+ 'context.*.mnemonic',
11386
+ 'context.*.seed',
11387
+ 'context.*.seedPhrase',
11388
+ // OTP / Verification Codes
11389
+ 'context.otp',
11390
+ 'context.verificationCode',
11391
+ 'context.*.otp',
11392
+ 'context.*.verificationCode',
11393
+ // Payment Information
11394
+ 'context.cardNumber',
11395
+ 'context.cvv',
11396
+ 'context.accountNumber',
11397
+ 'context.*.cardNumber',
11398
+ 'context.*.cvv',
11399
+ 'context.*.accountNumber'
11400
+ ];
11401
+ /**
11402
+ * Wrap user fields under `context` to prevent collision with pino internals.
11403
+ *
11404
+ * @param fields - User-provided log fields.
11405
+ * @returns Object with fields nested under `context`, or undefined if empty.
11406
+ *
11407
+ * @remarks
11408
+ * This function handles edge cases by returning undefined for null, undefined,
11409
+ * or empty objects to avoid unnecessary wrapping in log output.
11410
+ * Undefined values are cleaned before wrapping.
11411
+ */ function wrapInContext(fields) {
11412
+ if (!fields) return undefined;
11413
+ // Clean undefined values for consistency and transport compatibility
11414
+ const cleaned = omitUndefined(fields);
11415
+ // Handle edge case: all values were undefined, resulting in empty object
11416
+ const keys = Object.keys(cleaned);
11417
+ if (keys.length === 0) return undefined;
11418
+ return {
11419
+ context: cleaned
11420
+ };
11421
+ }
11422
+ /**
11423
+ * Wrap a pino instance to conform to our Logger interface.
11424
+ *
11425
+ * @param pinoInstance - The pino logger instance to wrap.
11426
+ * @returns A Logger instance conforming to our stable interface.
11427
+ */ function wrapPino(pinoInstance) {
11428
+ return {
11429
+ debug (message, fields) {
11430
+ const wrapped = wrapInContext(fields);
11431
+ if (wrapped) {
11432
+ pinoInstance.debug(wrapped, message);
11433
+ } else {
11434
+ pinoInstance.debug(message);
11435
+ }
11436
+ },
11437
+ info (message, fields) {
11438
+ const wrapped = wrapInContext(fields);
11439
+ if (wrapped) {
11440
+ pinoInstance.info(wrapped, message);
11441
+ } else {
11442
+ pinoInstance.info(message);
11443
+ }
11444
+ },
11445
+ warn (message, fields) {
11446
+ const wrapped = wrapInContext(fields);
11447
+ if (wrapped) {
11448
+ pinoInstance.warn(wrapped, message);
11449
+ } else {
11450
+ pinoInstance.warn(message);
11451
+ }
11452
+ },
11453
+ error (message, fields) {
11454
+ const wrapped = wrapInContext(fields);
11455
+ if (wrapped) {
11456
+ pinoInstance.error(wrapped, message);
11457
+ } else {
11458
+ pinoInstance.error(message);
11459
+ }
11460
+ },
11461
+ child (tags) {
11462
+ // Child bindings stay flat (not wrapped) - they're part of logger's base context
11463
+ const cleaned = omitUndefined(tags);
11464
+ return wrapPino(pinoInstance.child(cleaned));
11465
+ }
11466
+ };
11467
+ }
11468
+ /**
11469
+ * Build pino redact configuration from our simplified options.
11470
+ *
11471
+ * @param redact - The redact configuration option.
11472
+ * @returns Pino-compatible redact configuration or undefined.
11473
+ */ function buildRedactConfig(redact) {
11474
+ // Explicitly disabled
11475
+ if (redact === false) {
11476
+ return undefined;
11477
+ }
11478
+ // Custom paths provided
11479
+ if (Array.isArray(redact)) {
11480
+ return redact.length > 0 ? {
11481
+ paths: redact,
11482
+ censor: '[REDACTED]'
11483
+ } : undefined;
11484
+ }
11485
+ // Default: use web3 sensible defaults
11486
+ return {
11487
+ paths: [
11488
+ ...DEFAULT_REDACT_PATHS
11489
+ ],
11490
+ censor: '[REDACTED]'
11491
+ };
11492
+ }
11493
+ /**
11494
+ * Create a logger backed by pino.
11495
+ *
11496
+ * @param options - Logger options (optional).
11497
+ * @param stream - Destination stream (optional).
11498
+ * @returns A Logger instance.
11499
+ * @throws Error if invalid pino options are provided.
11500
+ *
11501
+ * @remarks
11502
+ * This is a thin wrapper around pino that exposes our stable Logger interface.
11503
+ * Pino handles all transport concerns: JSON, pretty printing, file, remote, browser, etc.
11504
+ *
11505
+ * **Security**: By default, sensitive web3 fields (privateKey, mnemonic, apiKey, etc.)
11506
+ * are automatically redacted from log output. Use `redact: false` to disable.
11507
+ *
11508
+ * @example
11509
+ * ```typescript
11510
+ * import { createLogger } from '@core/runtime'
11511
+ *
11512
+ * // Default: web3 sensitive fields are redacted
11513
+ * const logger = createLogger({ level: 'info' })
11514
+ * logger.info('Signing', { privateKey: '0x123...' })
11515
+ * // Output: { context: { privateKey: '[REDACTED]' }, msg: 'Signing' }
11516
+ *
11517
+ * // Disable redaction (use with caution)
11518
+ * const unsafeLogger = createLogger({ level: 'debug', redact: false })
11519
+ *
11520
+ * // Custom redaction paths
11521
+ * const customLogger = createLogger({
11522
+ * level: 'info',
11523
+ * redact: ['context.mySecret', 'context.*.credentials']
11524
+ * })
11525
+ *
11526
+ * // Pretty output for development
11527
+ * const devLogger = createLogger({
11528
+ * level: 'debug',
11529
+ * transport: { target: 'pino-pretty' }
11530
+ * })
11531
+ *
11532
+ * // Browser logger
11533
+ * const browserLogger = createLogger({
11534
+ * browser: { asObject: true }
11535
+ * })
11536
+ * ```
11537
+ */ function createLogger(options, stream) {
11538
+ const { redact, ...pinoOptions } = options ?? {};
11539
+ // Build redaction config
11540
+ const redactConfig = buildRedactConfig(redact);
11541
+ // Build final pino options, only include redact if defined
11542
+ const finalOptions = redactConfig ? {
11543
+ ...pinoOptions,
11544
+ redact: redactConfig
11545
+ } : pinoOptions;
11546
+ const pinoInstance = pino(finalOptions);
11547
+ return wrapPino(pinoInstance);
11548
+ }
11549
+
11033
11550
  // ============================================================================
11034
11551
  // Validation Schema
11035
11552
  // ============================================================================
@@ -11137,6 +11654,9 @@ var TransferSpeed;
11137
11654
  [TransferSpeed.SLOW]: 2000
11138
11655
  });
11139
11656
 
11657
+ createLogger({
11658
+ name: 'provider-cctp-v2'
11659
+ });
11140
11660
  /**
11141
11661
  * All chains that are supported by the CCTP v2 provider.
11142
11662
  *
@@ -11146,13 +11666,206 @@ var TransferSpeed;
11146
11666
  * @internal
11147
11667
  */ Object.values(Chains).filter((chain)=>isCCTPV2Supported(chain));
11148
11668
 
11669
+ /**
11670
+ * Decimal string in token minor units, constrained to be strictly positive.
11671
+ *
11672
+ * @internal
11673
+ */ 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
11674
+ // regex check above fails ("dirty"), so guard BigInt() against throwing on a
11675
+ // non-numeric value before comparing.
11676
+ .refine((value)=>/^\d+$/.test(value) && BigInt(value) > 0n, 'must be greater than zero');
11677
+ /**
11678
+ * A 20-byte EVM address in `0x` hex.
11679
+ *
11680
+ * The MVP prepaid-`FORWARD` `burn/usdc` path targets EVM contracts
11681
+ * (`TokenMessengerWithFees` / `GenericExecutor`), so `feeToken` and
11682
+ * `destinationCaller` are constrained to EVM addresses by design. This is an
11683
+ * intentional scope limit, not a permanent one: it can be widened to other
11684
+ * address formats as the fee service expands to more chains.
11685
+ */ const evmAddressSchema = z.string().regex(/^0x[a-fA-F0-9]{40}$/, 'must be a 20-byte 0x address');
11686
+ /** Even-length `0x` hex (the empty `0x` is allowed). */ const hexSchema = z.string().regex(/^0x([a-fA-F0-9]{2})*$/, 'must be even-length 0x hex');
11687
+ /** Non-empty, even-length `0x` hex. */ const nonEmptyHexSchema = z.string().regex(/^0x([a-fA-F0-9]{2})+$/, 'must be non-empty 0x hex');
11688
+ /** A 32-byte `0x` hex hash. */ const bytes32Schema = z.string().regex(/^0x[a-fA-F0-9]{64}$/, 'must be a 32-byte 0x hash');
11689
+ /** Decimal string in minor units, allowing zero. */ const numericStringSchema = z.string().regex(/^\d+$/, 'must be a non-negative integer string');
11690
+ /** An `https:` URL, used for the optional base-URL override. */ const httpsUrlSchema = z.string().refine((value)=>{
11691
+ try {
11692
+ return new URL(value).protocol === 'https:';
11693
+ } catch {
11694
+ return false;
11695
+ }
11696
+ }, 'must be an https URL');
11697
+ const forwardParamsSchema = z.object({
11698
+ hookData: hexSchema.optional(),
11699
+ destinationCaller: evmAddressSchema.optional()
11700
+ }).strict();
11701
+ const forwardRequestSchema = z.object({
11702
+ type: z.literal('FORWARD'),
11703
+ params: forwardParamsSchema.optional()
11704
+ }).strict();
11705
+ const preFinalityRequestSchema = z.object({
11706
+ type: z.literal('PRE_FINALITY')
11707
+ }).strict();
11708
+ /**
11709
+ * A single quote request item (`FORWARD` or `PRE_FINALITY`).
11710
+ *
11711
+ * @internal
11712
+ */ const feeQuoteRequestSchema = z.discriminatedUnion('type', [
11713
+ forwardRequestSchema,
11714
+ preFinalityRequestSchema
11715
+ ]);
11716
+ /**
11717
+ * A non-empty list of quote request items with unique types.
11718
+ *
11719
+ * @internal
11720
+ */ 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');
11721
+ /**
11722
+ * A structured `Partial<ApiPollingConfig>` polling override.
11723
+ *
11724
+ * Validates the field types callers actually set, so a plain-JS caller passing
11725
+ * `{ timeout: 'soon' }` is rejected at the boundary rather than failing opaquely
11726
+ * inside the transport. Unknown keys pass through so a future `ApiPollingConfig`
11727
+ * field is forwarded rather than silently dropped.
11728
+ */ const apiPollingConfigSchema = z.object({
11729
+ timeout: z.number().int().positive().optional(),
11730
+ maxRetries: z.number().int().nonnegative().optional(),
11731
+ retryDelay: z.number().int().nonnegative().optional(),
11732
+ backoff: z.enum([
11733
+ 'fixed',
11734
+ 'exponential'
11735
+ ]).optional(),
11736
+ maxRetryDelayMs: z.number().int().positive().optional(),
11737
+ headers: z.record(z.string()).optional()
11738
+ }).passthrough();
11739
+ /**
11740
+ * The validatable input for {@link fetchFeeQuote}.
11741
+ *
11742
+ * This is the single source of truth for input validation, including the CCTP
11743
+ * domains and the `isTestnet` environment flag. Validating `isTestnet` at
11744
+ * runtime matters because a plain-JS caller who omits it would otherwise leave
11745
+ * it `undefined`, which is falsy and silently selects the production base URL.
11746
+ * (`buildFeeQuoteUrl` independently re-validates the domains for standalone
11747
+ * callers.)
11748
+ *
11749
+ * @internal
11750
+ */ z.object({
11751
+ sourceDomain: z.number().int().nonnegative(),
11752
+ destinationDomain: z.number().int().nonnegative(),
11753
+ amount: positiveAmountSchema,
11754
+ feeToken: evmAddressSchema.optional(),
11755
+ requests: feeQuoteRequestsSchema,
11756
+ isTestnet: z.boolean(),
11757
+ baseUrl: httpsUrlSchema.optional(),
11758
+ config: apiPollingConfigSchema.optional()
11759
+ }).strict();
11760
+ const feeQuoteItemSchema = z.object({
11761
+ type: z.string().min(1),
11762
+ amount: numericStringSchema,
11763
+ args: z.array(z.string()),
11764
+ argsHash: bytes32Schema
11765
+ }).passthrough();
11766
+ const exchangeRatesSchema = z.object({
11767
+ feeTokenUsd: z.string(),
11768
+ destinationTokenUsd: z.string()
11769
+ }).passthrough();
11770
+ const metadataSchema = z.object({
11771
+ destinationGasPrice: z.string().optional(),
11772
+ exchangeRates: exchangeRatesSchema.optional()
11773
+ }).passthrough();
11774
+ /** The `expiry` object the Quote API nests the quote TTL under. */ const expirySchema = z.discriminatedUnion('mode', [
11775
+ z.object({
11776
+ mode: z.literal('TIMESTAMP'),
11777
+ expiresAt: z.number().int().nonnegative()
11778
+ }).passthrough(),
11779
+ z.object({
11780
+ mode: z.literal('BLOCK_NUMBER'),
11781
+ expiresAtBlock: z.number().int().nonnegative(),
11782
+ blockEstimatedAt: z.number().int().nonnegative().optional()
11783
+ }).passthrough()
11784
+ ]);
11785
+ /**
11786
+ * Schema for a signed fee quote returned by the Quote API.
11787
+ *
11788
+ * @internal
11789
+ */ z.object({
11790
+ // The runtime YAML spec maps signedQuote to a looser `hex` (which allows
11791
+ // an empty `0x`); we keep the stricter non-empty form. Do not relax
11792
+ // without a reason.
11793
+ signedQuote: nonEmptyHexSchema,
11794
+ issuedAt: z.number().int().nonnegative(),
11795
+ // The API returns a mode-specific timestamp or source-block deadline.
11796
+ expiry: expirySchema,
11797
+ feeTotalAmount: numericStringSchema,
11798
+ feeToken: evmAddressSchema,
11799
+ nonce: numericStringSchema,
11800
+ items: z.array(feeQuoteItemSchema),
11801
+ metadata: metadataSchema.optional()
11802
+ }).passthrough();
11803
+ /**
11804
+ * Validates input to {@link validateQuote}.
11805
+ *
11806
+ * @internal
11807
+ */ z.object({
11808
+ sourceDomain: z.number().int().nonnegative(),
11809
+ abiSignature: z.string().min(1),
11810
+ args: z.array(z.union([
11811
+ z.string(),
11812
+ z.array(z.string())
11813
+ ])),
11814
+ isTestnet: z.boolean(),
11815
+ baseUrl: httpsUrlSchema.optional(),
11816
+ config: apiPollingConfigSchema.optional()
11817
+ }).strict();
11818
+ const quoteExpiryStatusSchema = z.discriminatedUnion('mode', [
11819
+ z.object({
11820
+ mode: z.literal('TIMESTAMP'),
11821
+ expired: z.boolean(),
11822
+ secondsRemaining: z.number().int().nonnegative(),
11823
+ expiresAt: z.number().int().nonnegative()
11824
+ }).passthrough(),
11825
+ z.object({
11826
+ mode: z.literal('BLOCK_NUMBER'),
11827
+ expired: z.boolean(),
11828
+ secondsRemaining: z.number().int().nonnegative(),
11829
+ expiresAtBlock: z.number().int().nonnegative(),
11830
+ blockEstimatedAt: z.number().int().nonnegative().optional()
11831
+ }).passthrough()
11832
+ ]);
11833
+ const validateQuoteItemSchema = z.object({
11834
+ type: z.string().min(1),
11835
+ argsMatch: z.boolean(),
11836
+ amount: numericStringSchema.optional(),
11837
+ args: z.array(z.string()).optional(),
11838
+ argsHash: bytes32Schema.optional(),
11839
+ computedArgsHash: bytes32Schema.optional()
11840
+ }).passthrough();
11841
+ /**
11842
+ * Schema for a validate-quote result returned by the Iris `/validate/usdc/:sourceDomain` endpoint.
11843
+ *
11844
+ * The endpoint takes the source domain as a URL path parameter and does not
11845
+ * return it in the response body, so `sourceDomain` is intentionally not part
11846
+ * of this schema.
11847
+ *
11848
+ * @internal
11849
+ */ z.object({
11850
+ signedQuote: nonEmptyHexSchema,
11851
+ expiry: quoteExpiryStatusSchema,
11852
+ feeTotalAmount: numericStringSchema,
11853
+ feeToken: evmAddressSchema,
11854
+ nonce: numericStringSchema,
11855
+ claimable: z.boolean(),
11856
+ // Preserve newly introduced server-side reasons as opaque strings rather
11857
+ // than rejecting the entire safety response before the SDK is updated.
11858
+ failedChecks: z.array(z.string().min(1)),
11859
+ items: z.array(validateQuoteItemSchema)
11860
+ }).passthrough();
11861
+
11149
11862
  /** SDK name used in telemetry payloads. */ resolveKitSdkName(pkg$2.name);
11150
11863
 
11151
11864
  // Auto-register this kit for user agent tracking
11152
11865
  registerKit(`${pkg$2.name}/${pkg$2.version}`);
11153
11866
 
11154
11867
  var name$1 = "@circle-fin/swap-kit";
11155
- var version$1 = "1.5.2";
11868
+ var version$1 = "1.6.1";
11156
11869
  var pkg$1 = {
11157
11870
  name: name$1,
11158
11871
  version: version$1};
@@ -11166,7 +11879,7 @@ const optionalChainIdentifierField = chainIdentifierField.optional();
11166
11879
  * Catches obviously malformed addresses at parse time; chain-specific validation
11167
11880
  * is performed in buildServiceParams.
11168
11881
  */ const destinationAddressSchema = z.union([
11169
- evmAddressSchema,
11882
+ evmAddressSchema$1,
11170
11883
  solanaAddressSchema
11171
11884
  ]);
11172
11885
  /**
@@ -11212,9 +11925,16 @@ const optionalChainIdentifierField = chainIdentifierField.optional();
11212
11925
  message: 'stopLimit must be greater than 0'
11213
11926
  }).optional(),
11214
11927
  customFee: serviceSwapCustomFeeSchema.optional(),
11928
+ apiKey: z.string({
11929
+ invalid_type_error: 'apiKey must be a string'
11930
+ })// Tolerate '' so the `process.env.CIRCLE_API_KEY ?? ''` idiom falls back to
11931
+ // kitKey via resolveApiKey instead of being rejected here.
11932
+ .optional(),
11215
11933
  kitKey: z.string({
11216
11934
  invalid_type_error: 'kitKey must be a string'
11217
- }).min(1, 'kitKey must be a non-empty string').optional(),
11935
+ })// Tolerate '' so an unset kit-key env var yields the permissionless path,
11936
+ // matching buildServiceParams (which already omits an empty credential).
11937
+ .optional(),
11218
11938
  provider: z.string({
11219
11939
  invalid_type_error: 'provider must be a string'
11220
11940
  }).min(1, 'provider must be a non-empty string').optional(),
@@ -11379,23 +12099,49 @@ const optionalChainIdentifierField = chainIdentifierField.optional();
11379
12099
  fees: z.array(serviceSwapFeeSchema).optional()
11380
12100
  }).passthrough();
11381
12101
 
11382
- /** Placeholder used wherever a kit key is scrubbed from logs, traces, or errors. */ const REDACTED_KIT_KEY = '[redacted]';
12102
+ /** Placeholder used wherever a credential is scrubbed from logs, traces, or errors. */ const REDACTED_CREDENTIAL = '[redacted]';
12103
+ /**
12104
+ * Config fields that carry a Stablecoin Service credential.
12105
+ *
12106
+ * `apiKey` is the supported field; `kitKey` is the deprecated alias. Redaction
12107
+ * and credential resolution both read this list so a newly added field is
12108
+ * scrubbed everywhere it needs to be.
12109
+ */ const CREDENTIAL_CONFIG_FIELDS = [
12110
+ 'apiKey',
12111
+ 'kitKey'
12112
+ ];
11383
12113
 
12114
+ /**
12115
+ * Replaces any credential field present on a config with a redaction marker.
12116
+ *
12117
+ * Covers `apiKey` and the deprecated `kitKey`, so adding a credential field
12118
+ * without extending this list cannot silently leak it into a trace. Returns the
12119
+ * config unchanged when it carries no credential.
12120
+ */ const redactCredentialFields = (config)=>{
12121
+ const present = CREDENTIAL_CONFIG_FIELDS.filter((field)=>field in config);
12122
+ if (present.length === 0) {
12123
+ return config;
12124
+ }
12125
+ return present.reduce((acc, field)=>({
12126
+ ...acc,
12127
+ [field]: REDACTED_CREDENTIAL
12128
+ }), {
12129
+ ...config
12130
+ });
12131
+ };
11384
12132
  /**
11385
12133
  * Builds a redacted projection of swap params that is safe to embed in error
11386
12134
  * traces (which may be logged downstream). Allow-lists only non-sensitive
11387
12135
  * fields and drops `from` entirely — `from.adapter` can carry signer/private-key
11388
- * material for signer-backed (viem/ethers) flows — and redacts `config.kitKey`.
12136
+ * material for signer-backed (viem/ethers) flows — and redacts every credential
12137
+ * field on `config`.
11389
12138
  */ const redactSwapParamsForTrace = (params)=>{
11390
12139
  if (typeof params !== 'object' || params === null) {
11391
12140
  return params;
11392
12141
  }
11393
12142
  const record = params;
11394
12143
  const config = record['config'];
11395
- const redactedConfig = typeof config === 'object' && config !== null && 'kitKey' in config ? {
11396
- ...config,
11397
- kitKey: REDACTED_KIT_KEY
11398
- } : config;
12144
+ const redactedConfig = typeof config === 'object' && config !== null ? redactCredentialFields(config) : config;
11399
12145
  return {
11400
12146
  tokenIn: record['tokenIn'],
11401
12147
  tokenOut: record['tokenOut'],
@@ -11479,6 +12225,41 @@ const optionalChainIdentifierField = chainIdentifierField.optional();
11479
12225
  *
11480
12226
  * @internal
11481
12227
  */ const MAX_RATE_ADDRESSES_PER_REQUEST = 100;
12228
+ /**
12229
+ * Environment prefixes carried by Circle platform API keys.
12230
+ *
12231
+ * A Circle API key is `<ENV>_API_KEY:<keyId>:<keySecret>`, where `<ENV>` is one
12232
+ * of these prefixes.
12233
+ *
12234
+ * @internal
12235
+ */ const API_KEY_ENV_PREFIXES = [
12236
+ 'TEST',
12237
+ 'LIVE',
12238
+ 'SAND',
12239
+ 'SANDBOX',
12240
+ 'SMOK',
12241
+ 'PROD',
12242
+ 'STAG',
12243
+ 'DEV'
12244
+ ];
12245
+ /**
12246
+ * Accepted credential formats for Stablecoin Service authentication.
12247
+ *
12248
+ * Matches a Circle platform API key (`<ENV>_API_KEY:<keyId>:<keySecret>`) and
12249
+ * the legacy kit key (`KIT_KEY:<keyId>:<keySecret>`). API keys are the
12250
+ * recommended credential; kit keys remain accepted as the legacy path.
12251
+ *
12252
+ * @remarks
12253
+ * This is a local pre-flight check, not the authority — the Stablecoin Service
12254
+ * validates the credential and answers 401 when it rejects one. The prefix list
12255
+ * is therefore deliberately permissive: a valid key carrying a prefix this SDK
12256
+ * has not been taught about should reach the service and be judged there rather
12257
+ * than be refused locally, since refusing locally is indistinguishable from an
12258
+ * outage to the caller. Kept as the single source of truth so the pattern is
12259
+ * not restated per call site.
12260
+ *
12261
+ * @internal
12262
+ */ const API_KEY_PATTERN = new RegExp(`^(?:KIT_KEY|(?:${API_KEY_ENV_PREFIXES.join('|')})_API_KEY)` + ':[a-zA-Z0-9._-]+:[a-zA-Z0-9._-]+$');
11482
12263
 
11483
12264
  /**
11484
12265
  * Zod schema for validating stop limits.
@@ -11547,13 +12328,14 @@ const optionalChainIdentifierField = chainIdentifierField.optional();
11547
12328
  /**
11548
12329
  * Zod schema for validating API keys.
11549
12330
  *
11550
- * Validates that the API key is a valid API key format.
12331
+ * Accepts a Circle platform API key (`<ENV>_API_KEY:<keyId>:<keySecret>`) and
12332
+ * the legacy kit key (`KIT_KEY:<keyId>:<keySecret>`).
11551
12333
  *
11552
12334
  * @example
11553
12335
  * ```typescript
11554
12336
  * import { apiKeySchema } from '@core/service-client'
11555
12337
  *
11556
- * const result = apiKeySchema.safeParse('KIT_KEY:e84d2546d4e321b2ff427dc988c89503:f84d2548d4e322b2ff427fc989c87503')
12338
+ * const result = apiKeySchema.safeParse('TEST_API_KEY:e84d2546d4e321b2ff427dc988c89503:f84d2548d4e322b2ff427fc989c87503')
11557
12339
  * if (!result.success) {
11558
12340
  * console.error('Invalid API key format:', result.error.issues)
11559
12341
  * }
@@ -11561,7 +12343,7 @@ const optionalChainIdentifierField = chainIdentifierField.optional();
11561
12343
  */ const apiKeySchema = z.string({
11562
12344
  required_error: 'API key is required',
11563
12345
  invalid_type_error: 'Invalid API key format'
11564
- }).regex(/^KIT_KEY:[a-zA-Z0-9._-]+:[a-zA-Z0-9._-]+$/, 'Invalid API key format');
12346
+ }).regex(API_KEY_PATTERN, 'Invalid API key format');
11565
12347
  /**
11566
12348
  * Zod schema for platform fees configuration.
11567
12349
  *
@@ -12082,21 +12864,55 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
12082
12864
  * ```
12083
12865
  */ const isGetTokenRatesResponse = (obj)=>getTokenRatesResponseSchema.safeParse(obj).success;
12084
12866
  /**
12085
- * Assert that a Stablecoin Service kit key is not being supplied from a browser.
12867
+ * Resolve the credential to authenticate a Stablecoin Service request with.
12868
+ *
12869
+ * `apiKey` is the supported field; `kitKey` is the deprecated alias kept for
12870
+ * existing integrations. When both are supplied `apiKey` wins, so a caller
12871
+ * migrating field-by-field cannot be silently pinned to a stale credential.
12086
12872
  *
12087
- * The kit key (`KIT_KEY:<id>:<secret>`) is a server-only secret. Every
12088
- * Stablecoin Service request that attaches an `Authorization: Bearer` header
12089
- * funnels through this package, so calling this guard before that header is
12090
- * built prevents the secret from being sent from and thus bundled into — a
12091
- * client application. In Node.js the check is a no-op, preserving the
12092
- * legitimate "hold the kit key on the server, forward the prepared transaction
12093
- * to the client" flow. When no kit key is supplied the permissionless (keyless)
12094
- * client path remains fully allowed.
12873
+ * An empty-string value is treated as absent on either field. Without this, the
12874
+ * common `process.env.CIRCLE_API_KEY ?? ''` idiom (which yields `''` when the
12875
+ * variable is unset) would either shadow a working `kitKey` or, on a bare
12876
+ * `kitKey: ''`, reach downstream validation as an invalid credential instead of
12877
+ * falling through to the permissionless path.
12878
+ *
12879
+ * @param source - Object carrying either credential field, or neither.
12880
+ * @returns The credential to use, or `undefined` for the permissionless
12881
+ * (keyless) path.
12882
+ *
12883
+ * @example
12884
+ * ```typescript
12885
+ * import { resolveApiKey } from '@core/service-client'
12886
+ *
12887
+ * resolveApiKey({ apiKey: 'TEST_API_KEY:id:secret' }) // 'TEST_API_KEY:id:secret'
12888
+ * resolveApiKey({ kitKey: 'KIT_KEY:id:secret' }) // 'KIT_KEY:id:secret'
12889
+ * resolveApiKey({ apiKey: '', kitKey: 'KIT_KEY:id:secret' }) // 'KIT_KEY:id:secret'
12890
+ * resolveApiKey({ kitKey: '' }) // undefined
12891
+ * resolveApiKey({}) // undefined
12892
+ * ```
12893
+ */ const resolveApiKey = (source)=>{
12894
+ // Treat an empty-string value as absent on either field so the
12895
+ // `env ?? ''` idiom falls through to the next credential (or permissionless).
12896
+ const normalize = (value)=>value !== undefined && value !== '' ? value : undefined;
12897
+ return normalize(source.apiKey) ?? normalize(source.kitKey);
12898
+ };
12899
+ /**
12900
+ * Assert that a Stablecoin Service credential is not supplied from a browser.
12095
12901
  *
12096
- * @param apiKey - The inline kit key for the request, or `undefined` when none
12097
- * was supplied (permissionless mode).
12902
+ * An API key (`<ENV>_API_KEY:<id>:<secret>`) and a legacy kit key
12903
+ * (`KIT_KEY:<id>:<secret>`) are both server-only secrets. Every Stablecoin
12904
+ * Service request that attaches an `Authorization: Bearer` header funnels
12905
+ * through this package, so calling this guard before that header is built
12906
+ * prevents the secret from being sent from — and thus bundled into — a client
12907
+ * application. In Node.js the check is a no-op, preserving the legitimate "hold
12908
+ * the credential on the server, forward the prepared transaction to the client"
12909
+ * flow. When no credential is supplied the permissionless (keyless) client path
12910
+ * remains fully allowed.
12911
+ *
12912
+ * @param apiKey - The inline credential for the request, or `undefined` when
12913
+ * none was supplied (permissionless mode).
12098
12914
  * @returns Nothing.
12099
- * @throws KitError with VALIDATION_FAILED when a kit key is supplied while
12915
+ * @throws KitError with VALIDATION_FAILED when a credential is supplied while
12100
12916
  * running in a browser environment. The secret value is never echoed.
12101
12917
  *
12102
12918
  * @example
@@ -12104,10 +12920,10 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
12104
12920
  * import { assertBrowserSafeApiKey } from '@core/service-client'
12105
12921
  *
12106
12922
  * // Server (Node.js): no-op, request proceeds with the Authorization header.
12107
- * assertBrowserSafeApiKey('KIT_KEY:my-id:my-secret')
12923
+ * assertBrowserSafeApiKey('TEST_API_KEY:my-id:my-secret')
12108
12924
  *
12109
12925
  * // Browser: throws to stop the secret from leaking into the client bundle.
12110
- * assertBrowserSafeApiKey('KIT_KEY:my-id:my-secret')
12926
+ * assertBrowserSafeApiKey('TEST_API_KEY:my-id:my-secret')
12111
12927
  *
12112
12928
  * // Browser, permissionless: allowed.
12113
12929
  * assertBrowserSafeApiKey(undefined)
@@ -12117,7 +12933,7 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
12117
12933
  return;
12118
12934
  }
12119
12935
  if (isBrowserEnvironment()) {
12120
- throw createValidationFailedError$1('kitKey', '[redacted]', 'kitKey must not be provided in a browser environment — it is a server-only secret. Run kit operations that use a kit key on your server, or omit kitKey to use the permissionless (keyless) client path');
12936
+ throw createValidationFailedError$1('apiKey', '[redacted]', 'apiKey must not be provided in a browser environment — it is a server-only secret. Run kit operations that use an API key on your server, or omit apiKey (and the legacy kitKey) to use the permissionless (keyless) client path');
12121
12937
  }
12122
12938
  };
12123
12939
 
@@ -12129,7 +12945,8 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
12129
12945
  *
12130
12946
  * @remarks
12131
12947
  * - Input validation leverages Zod schemas to surface actionable KitErrors.
12132
- * - API key format must match `KIT_KEY:<keyId>:<keySecret>`
12948
+ * - API key format must match `<ENV>_API_KEY:<keyId>:<keySecret>`, or the
12949
+ * legacy `KIT_KEY:<keyId>:<keySecret>`
12133
12950
  *
12134
12951
  * @param params - The create transaction request parameters with API key.
12135
12952
  * @returns A promise that resolves to a typed {@link CreateSwapResponse}.
@@ -12158,7 +12975,7 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
12158
12975
  * recipientAddress: '0x050928e1f9086b20539c767c96909663ff7fbdf2',
12159
12976
  * },
12160
12977
  * },
12161
- * apiKey: 'KIT_KEY:example-key:example-secret',
12978
+ * apiKey: 'TEST_API_KEY:example-key:example-secret',
12162
12979
  * })
12163
12980
  *
12164
12981
  * console.log(`Transaction target: ${transaction.transaction.target}`)
@@ -12177,13 +12994,13 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
12177
12994
  const url = new URL('/v1/stablecoinKits/swap', STABLECOIN_SERVICE_BASE_URL).toString();
12178
12995
  // Remove the API key from the request body
12179
12996
  const { apiKey, ...requestBody } = validatedParams;
12180
- // Never let a server-only kit key leave a browser (no-op in Node.js).
12997
+ // Never let a server-only credential leave a browser (no-op in Node.js).
12181
12998
  assertBrowserSafeApiKey(apiKey);
12182
12999
  const effectiveConfig = {
12183
13000
  ...DEFAULT_CONFIG,
12184
13001
  headers: {
12185
13002
  ...DEFAULT_CONFIG.headers,
12186
- // Permissionless mode: no Authorization header when the kit key is absent.
13003
+ // Permissionless mode: no Authorization header when the credential is absent.
12187
13004
  ...apiKey !== undefined && {
12188
13005
  Authorization: `Bearer ${apiKey}`
12189
13006
  }
@@ -12333,7 +13150,7 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
12333
13150
  }
12334
13151
  // Use validated data
12335
13152
  const validatedParams = result.data;
12336
- // Never let a server-only kit key leave a browser (no-op in Node.js).
13153
+ // Never let a server-only credential leave a browser (no-op in Node.js).
12337
13154
  assertBrowserSafeApiKey(validatedParams.apiKey);
12338
13155
  // Build the API URL
12339
13156
  const url = buildQuoteUrl(validatedParams);
@@ -12342,7 +13159,7 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
12342
13159
  ...DEFAULT_CONFIG,
12343
13160
  headers: {
12344
13161
  ...DEFAULT_CONFIG.headers,
12345
- // Permissionless mode: no Authorization header when the kit key is absent.
13162
+ // Permissionless mode: no Authorization header when the credential is absent.
12346
13163
  ...validatedParams.apiKey !== undefined && {
12347
13164
  Authorization: `Bearer ${validatedParams.apiKey}`
12348
13165
  }
@@ -12407,14 +13224,14 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
12407
13224
  toChain: result.data.toChain
12408
13225
  }
12409
13226
  };
12410
- // Never let a server-only kit key leave a browser (no-op in Node.js).
13227
+ // Never let a server-only credential leave a browser (no-op in Node.js).
12411
13228
  assertBrowserSafeApiKey(validatedParams.apiKey);
12412
13229
  const url = buildSwapStatusUrl(validatedParams);
12413
13230
  const effectiveConfig = {
12414
13231
  ...DEFAULT_CONFIG,
12415
13232
  headers: {
12416
13233
  ...DEFAULT_CONFIG.headers,
12417
- // Permissionless mode: no Authorization header when the kit key is absent.
13234
+ // Permissionless mode: no Authorization header when the credential is absent.
12418
13235
  ...validatedParams.apiKey !== undefined && {
12419
13236
  Authorization: `Bearer ${validatedParams.apiKey}`
12420
13237
  }
@@ -12440,7 +13257,7 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
12440
13257
  * const url = buildTokenRatesUrl({
12441
13258
  * chain: 'Ethereum',
12442
13259
  * addresses: ['0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'],
12443
- * apiKey: 'KIT_KEY:key:secret',
13260
+ * apiKey: 'TEST_API_KEY:key:secret',
12444
13261
  * })
12445
13262
  * // => 'https://api.circle.com/v1/stablecoinKits/rates?chain=Ethereum&addresses=...'
12446
13263
  * ```
@@ -12513,14 +13330,14 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
12513
13330
  addresses: result.data.addresses
12514
13331
  }
12515
13332
  };
12516
- // Never let a server-only kit key leave a browser (no-op in Node.js).
13333
+ // Never let a server-only credential leave a browser (no-op in Node.js).
12517
13334
  assertBrowserSafeApiKey(validatedParams.apiKey);
12518
13335
  const url = buildTokenRatesUrl(validatedParams);
12519
13336
  const effectiveConfig = {
12520
13337
  ...DEFAULT_CONFIG,
12521
13338
  headers: {
12522
13339
  ...DEFAULT_CONFIG.headers,
12523
- // Permissionless mode: no Authorization header when the kit key is absent.
13340
+ // Permissionless mode: no Authorization header when the credential is absent.
12524
13341
  ...validatedParams.apiKey !== undefined && {
12525
13342
  Authorization: `Bearer ${validatedParams.apiKey}`
12526
13343
  }
@@ -12958,7 +13775,7 @@ const abiParameterSchema = z.object({
12958
13775
  */ z.object({
12959
13776
  type: z.literal('evm'),
12960
13777
  abi: abiSchema,
12961
- address: evmAddressSchema,
13778
+ address: evmAddressSchema$1,
12962
13779
  functionName: z.string({
12963
13780
  required_error: 'Function name is required',
12964
13781
  invalid_type_error: 'Function name must be a string'
@@ -12995,7 +13812,7 @@ const abiParameterSchema = z.object({
12995
13812
  * }
12996
13813
  * ```
12997
13814
  */ z.object({
12998
- address: evmAddressSchema,
13815
+ address: evmAddressSchema$1,
12999
13816
  value: z.bigint({
13000
13817
  required_error: 'Value is required for native transfers',
13001
13818
  invalid_type_error: 'Value must be a bigint'
@@ -13527,7 +14344,7 @@ z.object({
13527
14344
  signature: evmSignatureSchema,
13528
14345
  tokenInputs: z.array(z.object({
13529
14346
  permitType: z.nativeEnum(PermitType),
13530
- token: evmAddressSchema,
14347
+ token: evmAddressSchema$1,
13531
14348
  amount: z.bigint().refine((value)=>value >= 0n, {
13532
14349
  message: 'amount must be a non-negative bigint'
13533
14350
  }),
@@ -13788,7 +14605,7 @@ enc.encode('used_transfer_spec_hash');
13788
14605
  });
13789
14606
 
13790
14607
  /**
13791
- * Assert that the kit key is valid for swap operations.
14608
+ * Assert that the credential is valid for swap operations.
13792
14609
  *
13793
14610
  * @remarks
13794
14611
  * This validation is called when swap operations are executed, not at construction time.
@@ -13796,34 +14613,35 @@ enc.encode('used_transfer_spec_hash');
13796
14613
  * at usage time rather than construction time.
13797
14614
  *
13798
14615
  * Validates:
13799
- * - Kit key matches the required format (KIT_KEY:id:secret) when provided.
13800
- * An absent or empty kit key is permitted (permissionless mode) — the swap
13801
- * service now treats the key as optional.
14616
+ * - The credential matches an accepted format when provided — a Circle API key
14617
+ * (`<ENV>_API_KEY:id:secret`) or a legacy kit key (`KIT_KEY:id:secret`).
14618
+ * An absent or empty credential is permitted (permissionless mode) — the swap
14619
+ * service treats the credential as optional.
13802
14620
  *
13803
- * @param kitKey - The inline kit key from the swap operation config (optional)
13804
- * @throws KitError with VALIDATION_FAILED if a kit key is provided but does not
13805
- * match the KIT_KEY:<keyId>:<keySecret> format
14621
+ * @param apiKey - The inline credential from the swap operation config (optional)
14622
+ * @throws KitError with VALIDATION_FAILED if a credential is provided but does
14623
+ * not match an accepted format
13806
14624
  *
13807
14625
  * @example
13808
14626
  * ```typescript
13809
- * import { assertKitKey } from './assertKitKey'
14627
+ * import { assertApiKey } from './assertApiKey'
13810
14628
  *
13811
- * const kitKey = 'KIT_KEY:9d1bd085-bad2-4a2b-ae67-5814b85167c9:secretvalue'
14629
+ * const apiKey = 'TEST_API_KEY:9d1bd085-bad2-4a2b-ae67-5814b85167c9:secretvalue'
13812
14630
  *
13813
- * // Validate kit key before use
13814
- * assertKitKey(kitKey)
14631
+ * // Validate the credential before use
14632
+ * assertApiKey(apiKey)
13815
14633
  * ```
13816
- */ function assertKitKey(kitKey) {
13817
- // Permissionless mode: the swap service treats the kit key as optional, so an
13818
- // absent (or empty) key is valid. Only validate the format when a key is
14634
+ */ function assertApiKey(apiKey) {
14635
+ // Permissionless mode: the swap service treats the credential as optional, so
14636
+ // an absent (or empty) value is valid. Only validate the format when one is
13819
14637
  // actually provided.
13820
- if (!kitKey) {
14638
+ if (!apiKey) {
13821
14639
  return;
13822
14640
  }
13823
- const apiKeyResult = apiKeySchema.safeParse(kitKey);
14641
+ const apiKeyResult = apiKeySchema.safeParse(apiKey);
13824
14642
  if (!apiKeyResult.success) {
13825
14643
  const errors = apiKeyResult.error.issues.map((issue)=>issue.message).join(', ');
13826
- throw createValidationFailedError$1('kitKey', REDACTED_KIT_KEY, `Invalid API key format. ${errors}. Expected format: KIT_KEY:<keyId>:<keySecret>. Get your free Kit Key at: https://developers.circle.com/w3s/keys#kit-keys`);
14644
+ throw createValidationFailedError$1('apiKey', REDACTED_CREDENTIAL, `Invalid API key format. ${errors}. Expected format: <ENV>_API_KEY:<keyId>:<keySecret> (for example TEST_API_KEY:... or LIVE_API_KEY:...). Legacy KIT_KEY:<keyId>:<keySecret> values are still accepted. Get your key at: https://developers.circle.com/w3s/keys`);
13827
14645
  }
13828
14646
  }
13829
14647
 
@@ -14015,7 +14833,7 @@ const TOKEN_REGISTRY$3 = createTokenRegistry();
14015
14833
  }
14016
14834
  // Validate recipient address format matches the chain type
14017
14835
  if (chain.type === 'evm') {
14018
- const result = evmAddressSchema.safeParse(recipientAddress);
14836
+ const result = evmAddressSchema$1.safeParse(recipientAddress);
14019
14837
  if (!result.success) {
14020
14838
  throw createInvalidAddressError(recipientAddress, chain.name, '0x-prefixed 42-character hex string (0x + 40 hex characters)');
14021
14839
  }
@@ -14077,7 +14895,7 @@ function resolveFeePayoutChain(tokenIn, tokenOut, sourceChain, destinationChain)
14077
14895
  * to: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
14078
14896
  * config: {
14079
14897
  * slippageBps: 300,
14080
- * kitKey: 'KIT_KEY:...:...' // Required inline kit key
14898
+ * apiKey: 'TEST_API_KEY:...:...' // Inline credential (optional)
14081
14899
  * }
14082
14900
  * }
14083
14901
  *
@@ -14115,18 +14933,17 @@ function resolveFeePayoutChain(tokenIn, tokenOut, sourceChain, destinationChain)
14115
14933
  validateResolvedAddress(resolvedTokenInAddress, chain);
14116
14934
  validateResolvedAddress(resolvedTokenOutAddress, destinationChain);
14117
14935
  validateResolvedAddress(to, destinationChain);
14118
- const kitKey = config?.kitKey;
14119
- // Validate the kit key format when one is provided (permissionless otherwise).
14120
- assertKitKey(kitKey);
14936
+ const apiKey = resolveApiKey(config ?? {});
14937
+ // Validate the credential format when one is provided (permissionless
14938
+ // otherwise).
14939
+ assertApiKey(apiKey);
14121
14940
  // Validate custom fee configuration if present
14122
14941
  const customFee = config?.customFee;
14123
14942
  if (customFee !== undefined) {
14124
14943
  const feePayoutChain = resolveFeePayoutChain(tokenIn, tokenOut, chain, destinationChain);
14125
14944
  validateCustomFeeConfig(customFee, feePayoutChain);
14126
14945
  }
14127
- // Build CreateSwapParams for service client
14128
- // Use object spread to conditionally include optional properties
14129
- // Note: Service client expects 'apiKey' field, so we map kitKey → apiKey
14946
+ // Build CreateSwapParams for service client, spreading optional properties.
14130
14947
  const chainName = chain.chain // The API expects the Blockchain enum value format like "World_Chain"
14131
14948
  ;
14132
14949
  const destinationChainName = destinationChain.chain;
@@ -14161,9 +14978,9 @@ function resolveFeePayoutChain(tokenIn, tokenOut, sourceChain, destinationChain)
14161
14978
  }
14162
14979
  }
14163
14980
  },
14164
- // Map kitKey → apiKey for the service client; omitted in permissionless mode.
14165
- ...kitKey ? {
14166
- apiKey: kitKey
14981
+ // Omitted in permissionless mode.
14982
+ ...apiKey ? {
14983
+ apiKey
14167
14984
  } : {}
14168
14985
  };
14169
14986
  }
@@ -16067,9 +16884,9 @@ async function fetchSameChainStatusSnapshot({ isCrossChainSwap, txHash, chain, a
16067
16884
  * ```typescript
16068
16885
  * import { StablecoinServiceSwapProvider } from '@circle-fin/provider-stablecoin-service-swap'
16069
16886
  *
16070
- * // Create provider with developer fee (1 USDC)
16887
+ * // Create provider with developer fee (1 USDC).
16888
+ * // Credentials are supplied per operation via `config.apiKey`, not here.
16071
16889
  * const provider = new StablecoinServiceSwapProvider({
16072
- * kitKey: process.env.STABLECOIN_KIT_API_KEY,
16073
16890
  * customFee: {
16074
16891
  * amount: '1000000', // 1 USDC in base units (6 decimals)
16075
16892
  * recipientAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0'
@@ -16731,9 +17548,7 @@ async function fetchSameChainStatusSnapshot({ isCrossChainSwap, txHash, chain, a
16731
17548
  * import { createAdapterFromPrivateKey } from '@circle-fin/adapter-viem-v2'
16732
17549
  * import { Ethereum } from '@core/chains'
16733
17550
  *
16734
- * const provider = new StablecoinServiceSwapProvider({
16735
- * kitKey: process.env.STABLECOIN_KIT_API_KEY
16736
- * })
17551
+ * const provider = new StablecoinServiceSwapProvider()
16737
17552
  *
16738
17553
  * const adapter = createAdapterFromPrivateKey({
16739
17554
  * privateKey: process.env.PRIVATE_KEY
@@ -17227,7 +18042,7 @@ const optionalSwapChainIdentifierField = swapChainIdentifierField.optional();
17227
18042
  /**
17228
18043
  * Fee recipient address (required).
17229
18044
  * Must be a valid EVM address or Solana address.
17230
- */ recipientAddress: z.string().refine((value)=>evmAddressSchema.safeParse(value).success || solanaAddressSchema.safeParse(value).success, {
18045
+ */ recipientAddress: z.string().refine((value)=>evmAddressSchema$1.safeParse(value).success || solanaAddressSchema.safeParse(value).success, {
17231
18046
  message: 'recipientAddress must be a valid blockchain address: EVM (0x + 40 hex chars) or Solana (base58, 32-44 chars)'
17232
18047
  })
17233
18048
  }).strict();
@@ -17239,7 +18054,8 @@ const optionalSwapChainIdentifierField = swapChainIdentifierField.optional();
17239
18054
  * - slippageBps: Optional positive number for slippage tolerance
17240
18055
  * - stopLimit: Optional decimal string for minimum output
17241
18056
  * - customFee: Optional fee configuration
17242
- * - kitKey: Optional string identifier
18057
+ * - apiKey: Optional credential string
18058
+ * - kitKey: Optional credential string (deprecated alias for apiKey)
17243
18059
  */ const swapConfigSchema = z.object({
17244
18060
  allowanceStrategy: allowanceStrategySchema.optional(),
17245
18061
  slippageBps: z.number().int().min(0).optional(),
@@ -17249,11 +18065,12 @@ const optionalSwapChainIdentifierField = swapChainIdentifierField.optional();
17249
18065
  attributeName: 'stopLimit'
17250
18066
  })(z.string())).optional(),
17251
18067
  customFee: swapCustomFeeSchema.optional(),
18068
+ apiKey: z.string().optional(),
17252
18069
  kitKey: z.string().optional()
17253
18070
  });
17254
18071
  const swapDestinationSchema = z.object({
17255
18072
  chain: optionalSwapChainIdentifierField,
17256
- recipientAddress: z.string().refine((value)=>evmAddressSchema.safeParse(value).success || solanaAddressSchema.safeParse(value).success, {
18073
+ recipientAddress: z.string().refine((value)=>evmAddressSchema$1.safeParse(value).success || solanaAddressSchema.safeParse(value).success, {
17257
18074
  message: 'recipientAddress must be a valid blockchain address: EVM (0x + 40 hex chars) or Solana (base58, 32-44 chars)'
17258
18075
  }).optional()
17259
18076
  }).strict();
@@ -19360,7 +20177,8 @@ const transformAmount = (value, direction, decimals)=>formatUnits(value, decimal
19360
20177
  /**
19361
20178
  * Helper to format the config section of a swap result, transforming fee amounts.
19362
20179
  *
19363
- * Strips sensitive fields like kitKey from the config before returning.
20180
+ * Strips the credential fields (`apiKey` and the deprecated `kitKey`) from the
20181
+ * config before returning, so a result is safe to log or serialize.
19364
20182
  *
19365
20183
  * @param config - The swap config from the provider.
19366
20184
  * @param outputTokenTransform - The amount transformer for output-token-denominated values (fees and amountOut).
@@ -19369,11 +20187,11 @@ const transformAmount = (value, direction, decimals)=>formatUnits(value, decimal
19369
20187
  if (!config) {
19370
20188
  return undefined;
19371
20189
  }
19372
- // Remove kitKey from the config
19373
- const cloneConfig = {
19374
- ...config
19375
- };
19376
- delete cloneConfig.kitKey;
20190
+ // Rebuild the config without any credential field. Filtering entries rather
20191
+ // than deleting them avoids reading the deprecated `kitKey` property
20192
+ // directly, and keeps the credential list in one place.
20193
+ const credentialFields = CREDENTIAL_CONFIG_FIELDS;
20194
+ const cloneConfig = Object.fromEntries(Object.entries(config).filter(([key])=>!credentialFields.includes(key)));
19377
20195
  if (Object.keys(cloneConfig).length === 0) {
19378
20196
  return undefined;
19379
20197
  }
@@ -19574,9 +20392,9 @@ const transformAmount = (value, direction, decimals)=>formatUnits(value, decimal
19574
20392
  try {
19575
20393
  // Step 1: Build quote params directly (no need for buildServiceParams)
19576
20394
  // Use chain.chain (Blockchain enum value like "World_Chain") not chain.name
19577
- // The kit key is optional (permissionless mode); when absent the quote is
19578
- // fetched without an Authorization header.
19579
- const kitKey = params.config?.kitKey;
20395
+ // The credential is optional (permissionless mode); when absent the quote
20396
+ // is fetched without an Authorization header.
20397
+ const apiKey = resolveApiKey(params.config ?? {});
19580
20398
  // Resolve token aliases to addresses for the quote API
19581
20399
  // The quote endpoint requires resolved addresses, not aliases like 'USDC'
19582
20400
  const chain = params.from.chain;
@@ -19601,8 +20419,8 @@ const transformAmount = (value, direction, decimals)=>formatUnits(value, decimal
19601
20419
  ...params.config?.slippageBps !== undefined && {
19602
20420
  slippageBps: params.config.slippageBps
19603
20421
  },
19604
- ...kitKey ? {
19605
- apiKey: kitKey
20422
+ ...apiKey ? {
20423
+ apiKey
19606
20424
  } : {}
19607
20425
  };
19608
20426
  // Step 2: Get quote from service
@@ -20006,7 +20824,7 @@ const sleep$1 = async (ms)=>new Promise((resolve)=>setTimeout(resolve, ms));
20006
20824
  * the service returns `receivingTokenDecimals`. When decimals are missing
20007
20825
  * the field is omitted entirely (never raw base units).
20008
20826
  *
20009
- * @param params - `txHash`, `chainIn`, optional `chainOut`, and `kitKey`.
20827
+ * @param params - `txHash`, `chainIn`, optional `chainOut`, and `apiKey`.
20010
20828
  * @returns A single snapshot of the swap's status.
20011
20829
  * @throws \{KitError\} If `chainIn` or `chainOut` is malformed.
20012
20830
  *
@@ -20022,7 +20840,7 @@ const sleep$1 = async (ms)=>new Promise((resolve)=>setTimeout(resolve, ms));
20022
20840
  * txHash: result.txHash,
20023
20841
  * chainIn: result.chainIn,
20024
20842
  * chainOut: result.chainOut,
20025
- * kitKey: process.env.KIT_KEY ?? '',
20843
+ * apiKey: process.env.CIRCLE_API_KEY,
20026
20844
  * })
20027
20845
  * while (status.progress.status === 'PENDING') {
20028
20846
  * await new Promise((r) => setTimeout(r, 3_000))
@@ -20030,7 +20848,7 @@ const sleep$1 = async (ms)=>new Promise((resolve)=>setTimeout(resolve, ms));
20030
20848
  * txHash: result.txHash,
20031
20849
  * chainIn: result.chainIn,
20032
20850
  * chainOut: result.chainOut,
20033
- * kitKey: process.env.KIT_KEY ?? '',
20851
+ * apiKey: process.env.CIRCLE_API_KEY,
20034
20852
  * })
20035
20853
  * }
20036
20854
  *
@@ -20048,14 +20866,15 @@ const sleep$1 = async (ms)=>new Promise((resolve)=>setTimeout(resolve, ms));
20048
20866
  const chainIn = normalizeChain(params.chainIn, 'chainIn');
20049
20867
  const chainOut = params.chainOut === undefined ? undefined : normalizeChain(params.chainOut, 'chainOut');
20050
20868
  const isCrossChain = chainOut !== undefined && chainOut !== chainIn;
20869
+ const apiKey = resolveApiKey(params);
20051
20870
  const request = {
20052
20871
  txHash: params.txHash,
20053
20872
  chain: chainIn,
20054
20873
  ...isCrossChain && {
20055
20874
  toChain: chainOut
20056
20875
  },
20057
- ...params.kitKey ? {
20058
- apiKey: params.kitKey
20876
+ ...apiKey ? {
20877
+ apiKey
20059
20878
  } : {}
20060
20879
  };
20061
20880
  let raw = await getSwapStatus$1(request);
@@ -20134,9 +20953,9 @@ const isResultShape = (params)=>'result' in params;
20134
20953
  *
20135
20954
  * Two parameter shapes are accepted:
20136
20955
  *
20137
- * - Pass the {@link SwapResult} directly: `{ result, kitKey, ... }`.
20956
+ * - Pass the {@link SwapResult} directly: `{ result, apiKey, ... }`.
20138
20957
  * Cleanest when chaining off `kit.swap()`.
20139
- * - Pass discrete fields: `{ txHash, chainIn, chainOut?, kitKey, ... }`.
20958
+ * - Pass discrete fields: `{ txHash, chainIn, chainOut?, apiKey, ... }`.
20140
20959
  * Useful for resuming an in-flight swap from a persisted record.
20141
20960
  *
20142
20961
  * @param params - Wait configuration. See {@link WaitForSwapParams}.
@@ -20156,7 +20975,7 @@ const isResultShape = (params)=>'result' in params;
20156
20975
  *
20157
20976
  * const final = await waitForSwap({
20158
20977
  * result,
20159
- * kitKey: process.env.KIT_KEY ?? '',
20978
+ * apiKey: process.env.CIRCLE_API_KEY,
20160
20979
  * onProgress: (snapshot) => {
20161
20980
  * console.log(snapshot.progress.substatus ?? snapshot.progress.status)
20162
20981
  * },
@@ -20174,7 +20993,7 @@ const isResultShape = (params)=>'result' in params;
20174
20993
  * txHash: '0x…',
20175
20994
  * chainIn: 'Ethereum',
20176
20995
  * chainOut: 'Base',
20177
- * kitKey: process.env.KIT_KEY ?? '',
20996
+ * apiKey: process.env.CIRCLE_API_KEY,
20178
20997
  * })
20179
20998
  * ```
20180
20999
  */ async function waitForSwap(params) {
@@ -20190,14 +21009,15 @@ const isResultShape = (params)=>'result' in params;
20190
21009
  const chainOut = isResultShape(params) ? params.result.chainOut : params.chainOut;
20191
21010
  // Delegate parameter validation (txHash, chainIn, chainOut) to
20192
21011
  // getSwapStatus so the same rules apply to both helpers.
21012
+ const apiKey = resolveApiKey(params);
20193
21013
  const statusParams = {
20194
21014
  txHash,
20195
21015
  chainIn,
20196
21016
  ...chainOut !== undefined && {
20197
21017
  chainOut
20198
21018
  },
20199
- ...params.kitKey ? {
20200
- kitKey: params.kitKey
21019
+ ...apiKey ? {
21020
+ apiKey
20201
21021
  } : {}
20202
21022
  };
20203
21023
  const deadline = Date.now() + timeoutMs;
@@ -20321,7 +21141,7 @@ function resolveTokenEntry(entry, index, chain, chainDef, context) {
20321
21141
  *
20322
21142
  * @param context - SwapKit context (provides the `TokenRegistry` used for
20323
21143
  * symbol resolution).
20324
- * @param params - `chain`, optional `tokens`, and `kitKey`.
21144
+ * @param params - `chain`, optional `tokens`, and `apiKey`.
20325
21145
  * @returns A nested map of `[chain][address] → { priceUSD, fetchedAt }`.
20326
21146
  * @throws \{KitError\} If `chain` cannot be resolved, `tokens` exceeds 100
20327
21147
  * entries, or any entry is neither a registered symbol nor a
@@ -20336,7 +21156,7 @@ function resolveTokenEntry(entry, index, chain, chainDef, context) {
20336
21156
  * const { rates } = await getTokenRates(context, {
20337
21157
  * chain: Blockchain.Ethereum,
20338
21158
  * tokens: ['USDC', 'EURC', 'NATIVE'],
20339
- * kitKey: process.env.KIT_KEY ?? '',
21159
+ * apiKey: process.env.CIRCLE_API_KEY,
20340
21160
  * })
20341
21161
  *
20342
21162
  * const usdc = rates['Ethereum']?.['0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48']
@@ -20357,10 +21177,11 @@ function resolveTokenEntry(entry, index, chain, chainDef, context) {
20357
21177
  // valid Blockchain enum string, so `getChainByEnum` is guaranteed to resolve.
20358
21178
  const chainDef = getChainByEnum(chain);
20359
21179
  const resolvedAddresses = params.tokens?.map((entry, index)=>resolveTokenEntry(entry, index, chain, chainDef, context));
21180
+ const apiKey = resolveApiKey(params);
20360
21181
  return getTokenRates$1({
20361
21182
  chain,
20362
- ...params.kitKey ? {
20363
- apiKey: params.kitKey
21183
+ ...apiKey ? {
21184
+ apiKey
20364
21185
  } : {},
20365
21186
  ...resolvedAddresses !== undefined && {
20366
21187
  addresses: resolvedAddresses
@@ -20991,7 +21812,7 @@ function resolveTokenEntry(entry, index, chain, chainDef, context) {
20991
21812
  * is formatted as a human-readable decimal string; when decimals are
20992
21813
  * missing the field is omitted entirely (never raw base units).
20993
21814
  *
20994
- * @param params - `txHash`, `chainIn`, optional `chainOut`, and `kitKey`.
21815
+ * @param params - `txHash`, `chainIn`, optional `chainOut`, and `apiKey`.
20995
21816
  * @returns A snapshot of the swap's status at the time of the call.
20996
21817
  * @throws \{KitError\} If `chainIn` or `chainOut` is malformed.
20997
21818
  *
@@ -21004,7 +21825,7 @@ function resolveTokenEntry(entry, index, chain, chainDef, context) {
21004
21825
  * txHash: result.txHash,
21005
21826
  * chainIn: result.chainIn,
21006
21827
  * chainOut: result.chainOut,
21007
- * kitKey: process.env.KIT_KEY ?? '',
21828
+ * apiKey: process.env.CIRCLE_API_KEY,
21008
21829
  * })
21009
21830
  * console.log(status.progress.status, status.progress.substatus)
21010
21831
  * ```
@@ -21016,7 +21837,7 @@ function resolveTokenEntry(entry, index, chain, chainDef, context) {
21016
21837
  * txHash: result.txHash,
21017
21838
  * chainIn: result.chainIn,
21018
21839
  * chainOut: result.chainOut,
21019
- * kitKey: process.env.KIT_KEY ?? '',
21840
+ * apiKey: process.env.CIRCLE_API_KEY,
21020
21841
  * })
21021
21842
  * while (status.progress.status === 'PENDING') {
21022
21843
  * await new Promise((r) => setTimeout(r, 3_000))
@@ -21024,7 +21845,7 @@ function resolveTokenEntry(entry, index, chain, chainDef, context) {
21024
21845
  * txHash: result.txHash,
21025
21846
  * chainIn: result.chainIn,
21026
21847
  * chainOut: result.chainOut,
21027
- * kitKey: process.env.KIT_KEY ?? '',
21848
+ * apiKey: process.env.CIRCLE_API_KEY,
21028
21849
  * })
21029
21850
  * }
21030
21851
  *
@@ -21055,7 +21876,7 @@ function resolveTokenEntry(entry, index, chain, chainDef, context) {
21055
21876
  * 5xx, etc.) surface unchanged so the caller can decide whether to
21056
21877
  * retry the whole wait. The wait itself only emits a timeout error.
21057
21878
  *
21058
- * @param params - Wait configuration including identifiers, kit key,
21879
+ * @param params - Wait configuration including identifiers, API key,
21059
21880
  * optional `timeoutMs`, and an optional `onProgress`
21060
21881
  * callback fired on every successful poll.
21061
21882
  * @returns The first terminal {@link SwapStatusResult} observed.
@@ -21074,7 +21895,7 @@ function resolveTokenEntry(entry, index, chain, chainDef, context) {
21074
21895
  *
21075
21896
  * const final = await kit.waitForSwap({
21076
21897
  * result,
21077
- * kitKey: process.env.KIT_KEY ?? '',
21898
+ * apiKey: process.env.CIRCLE_API_KEY,
21078
21899
  * onProgress: (snap) => console.log(snap.progress.substatus ?? snap.progress.status),
21079
21900
  * })
21080
21901
  *
@@ -21092,7 +21913,7 @@ function resolveTokenEntry(entry, index, chain, chainDef, context) {
21092
21913
  * txHash: persisted.txHash,
21093
21914
  * chainIn: persisted.chainIn,
21094
21915
  * chainOut: persisted.chainOut,
21095
- * kitKey: process.env.KIT_KEY ?? '',
21916
+ * apiKey: process.env.CIRCLE_API_KEY,
21096
21917
  * })
21097
21918
  * ```
21098
21919
  */ async waitForSwap(params) {
@@ -21126,7 +21947,7 @@ function resolveTokenEntry(entry, index, chain, chainDef, context) {
21126
21947
  * not cache a rate for the native asset on that chain, the response simply
21127
21948
  * omits the address.
21128
21949
  *
21129
- * @param params - `chain`, optional `tokens`, and `kitKey`.
21950
+ * @param params - `chain`, optional `tokens`, and `apiKey`.
21130
21951
  * @returns A nested map of `[chain][address] → { priceUSD, fetchedAt }`.
21131
21952
  * @throws \{KitError\} If `chain` is malformed, `tokens` exceeds 100
21132
21953
  * entries, or any entry is neither a registered symbol nor a
@@ -21138,7 +21959,7 @@ function resolveTokenEntry(entry, index, chain, chainDef, context) {
21138
21959
  * const { rates } = await kit.getTokenRates({
21139
21960
  * chain: 'Ethereum',
21140
21961
  * tokens: ['USDC', 'EURC', 'NATIVE'],
21141
- * kitKey: process.env.KIT_KEY ?? '',
21962
+ * apiKey: process.env.CIRCLE_API_KEY,
21142
21963
  * })
21143
21964
  *
21144
21965
  * const usdc = rates['Ethereum']?.['0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48']
@@ -21152,7 +21973,7 @@ function resolveTokenEntry(entry, index, chain, chainDef, context) {
21152
21973
  * chain: 'Ethereum',
21153
21974
  * // 'USDC' (registry symbol) + raw USDT address
21154
21975
  * tokens: ['USDC', '0xdAC17F958D2ee523a2206206994597C13D831ec7'],
21155
- * kitKey: process.env.KIT_KEY ?? '',
21976
+ * apiKey: process.env.CIRCLE_API_KEY,
21156
21977
  * })
21157
21978
  * ```
21158
21979
  *
@@ -21161,7 +21982,7 @@ function resolveTokenEntry(entry, index, chain, chainDef, context) {
21161
21982
  * ```typescript
21162
21983
  * const { rates } = await kit.getTokenRates({
21163
21984
  * chain: 'Base',
21164
- * kitKey: process.env.KIT_KEY ?? '',
21985
+ * apiKey: process.env.CIRCLE_API_KEY,
21165
21986
  * })
21166
21987
  * ```
21167
21988
  */ async getTokenRates(params) {
@@ -21416,7 +22237,7 @@ registerKit(`${pkg$1.name}/${pkg$1.version}`);
21416
22237
  };
21417
22238
 
21418
22239
  var name = "@circle-fin/earn-kit";
21419
- var version = "1.5.1";
22240
+ var version = "1.6.1";
21420
22241
  var pkg = {
21421
22242
  name: name,
21422
22243
  version: version};
@@ -21488,7 +22309,7 @@ function isNonNegativeBigIntLike(value) {
21488
22309
  }
21489
22310
  }
21490
22311
  const hexSignatureSchema = evmSignatureSchema;
21491
- const hexAddressSchema = evmAddressSchema;
22312
+ const hexAddressSchema = evmAddressSchema$1;
21492
22313
  // '0x' prefix + 32 bytes * 2 hex chars.
21493
22314
  const BYTES32_HEX_LENGTH = 66;
21494
22315
  const bridgeFeeTokenSchema = hexAddressSchema;
@@ -22393,7 +23214,7 @@ createTokenRegistry();
22393
23214
  * fast instead of round-tripping to the service.
22394
23215
  *
22395
23216
  * @internal
22396
- */ const recipientEvmAddressSchema = evmAddressSchema.refine((address)=>!ZERO_EVM_ADDRESS_REGEX.test(address), 'address must not be the zero address').refine(isValidEip55Checksum, 'address has an invalid EIP-55 checksum');
23217
+ */ const recipientEvmAddressSchema = evmAddressSchema$1.refine((address)=>!ZERO_EVM_ADDRESS_REGEX.test(address), 'address must not be the zero address').refine(isValidEip55Checksum, 'address has an invalid EIP-55 checksum');
22397
23218
  /**
22398
23219
  * Schema for the adapter context within earn operations.
22399
23220
  *
@@ -22425,19 +23246,39 @@ const sourceAdapterContextSchema = z.object({
22425
23246
  /**
22426
23247
  * Schema for the EarnConfig options.
22427
23248
  *
22428
- * Validate the optional Kit Key field using the standard `apiKeySchema`
22429
- * format (`KIT_KEY:<keyId>:<keySecret>`). When omitted, the SDK
22430
- * operates in permissionless mode. `baseUrl` overrides the Earn Service
22431
- * endpoint (e.g. staging); `batchTransactions: false` opts out of atomic
22432
- * batched execution. Both are forwarded to the provider, so this `.strict()`
22433
- * schema must accept them or a valid config object is rejected.
23249
+ * Validate the *resolved* credential using the standard `apiKeySchema` format
23250
+ * (`<ENV>_API_KEY:<keyId>:<keySecret>`, or a legacy
23251
+ * `KIT_KEY:<keyId>:<keySecret>`). `apiKey` takes precedence over the deprecated
23252
+ * `kitKey`, so a malformed `kitKey` that is being ignored must not fail a config
23253
+ * that supplies a valid `apiKey` (and vice versa) only the credential that
23254
+ * would actually be sent is format-checked. When neither is supplied the SDK
23255
+ * operates in permissionless mode. `baseUrl` overrides the Earn Service endpoint
23256
+ * (e.g. staging); `batchTransactions: false` opts out of atomic batched
23257
+ * execution. All are forwarded to the provider, so this `.strict()` schema must
23258
+ * accept them or a valid config object is rejected.
22434
23259
  *
22435
23260
  * @internal
22436
23261
  */ const earnConfigSchema = z.object({
22437
- kitKey: apiKeySchema.optional(),
23262
+ apiKey: z.string().optional(),
23263
+ kitKey: z.string().optional(),
22438
23264
  baseUrl: z.string().optional(),
22439
23265
  batchTransactions: z.boolean().optional()
22440
- }).strict();
23266
+ }).strict().superRefine((config, ctx)=>{
23267
+ const credential = resolveApiKey(config);
23268
+ if (credential === undefined) {
23269
+ return;
23270
+ }
23271
+ const result = apiKeySchema.safeParse(credential);
23272
+ if (!result.success) {
23273
+ ctx.addIssue({
23274
+ code: z.ZodIssueCode.custom,
23275
+ path: [
23276
+ credential === config.apiKey ? 'apiKey' : 'kitKey'
23277
+ ],
23278
+ message: result.error.issues[0]?.message ?? 'Invalid API key format'
23279
+ });
23280
+ }
23281
+ });
22441
23282
  /**
22442
23283
  * Canonical decimal form: a leading digit with no leading zeros (a single
22443
23284
  * '0' is only allowed immediately before the decimal point). Rejects the
@@ -22509,7 +23350,7 @@ const sourceAdapterContextSchema = z.object({
22509
23350
  * currently supports EVM vault addresses on Arc Testnet.
22510
23351
  *
22511
23352
  * @internal
22512
- */ const vaultAddressSchema = evmAddressSchema.refine(isValidEip55Checksum, 'address has an invalid EIP-55 checksum');
23353
+ */ const vaultAddressSchema = evmAddressSchema$1.refine(isValidEip55Checksum, 'address has an invalid EIP-55 checksum');
22513
23354
  /**
22514
23355
  * Validation schema for VaultQuery.
22515
23356
  *
@@ -22784,7 +23625,7 @@ const sameChainGetDepositQuoteParamsSchema = z.object({
22784
23625
  const crossChainGetDepositQuoteParamsSchema = z.object({
22785
23626
  from: sourceAdapterContextSchema,
22786
23627
  chain: earnBridgeDestinationChainIdentifierSchema,
22787
- address: evmAddressSchema,
23628
+ address: evmAddressSchema$1,
22788
23629
  vaultAddress: vaultAddressSchema,
22789
23630
  amount: amountSchema,
22790
23631
  transferSpeed: z.enum([