@circle-fin/app-kit 1.12.1 → 1.13.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/swap.cjs CHANGED
@@ -2987,6 +2987,8 @@ class KitError extends Error {
2987
2987
  Blockchain["Optimism_Sepolia"] = "Optimism_Sepolia";
2988
2988
  Blockchain["Pharos"] = "Pharos";
2989
2989
  Blockchain["Pharos_Testnet"] = "Pharos_Testnet";
2990
+ Blockchain["Plasma"] = "Plasma";
2991
+ Blockchain["Plasma_Testnet"] = "Plasma_Testnet";
2990
2992
  Blockchain["Polkadot_Asset_Hub"] = "Polkadot_Asset_Hub";
2991
2993
  Blockchain["Polkadot_Westmint"] = "Polkadot_Westmint";
2992
2994
  Blockchain["Plume"] = "Plume";
@@ -3056,6 +3058,7 @@ var BridgeChain;
3056
3058
  BridgeChain["Morph"] = "Morph";
3057
3059
  BridgeChain["Optimism"] = "Optimism";
3058
3060
  BridgeChain["Pharos"] = "Pharos";
3061
+ BridgeChain["Plasma"] = "Plasma";
3059
3062
  BridgeChain["Plume"] = "Plume";
3060
3063
  BridgeChain["Polygon"] = "Polygon";
3061
3064
  BridgeChain["Sei"] = "Sei";
@@ -3082,6 +3085,7 @@ var BridgeChain;
3082
3085
  BridgeChain["Morph_Testnet"] = "Morph_Testnet";
3083
3086
  BridgeChain["Optimism_Sepolia"] = "Optimism_Sepolia";
3084
3087
  BridgeChain["Pharos_Testnet"] = "Pharos_Testnet";
3088
+ BridgeChain["Plasma_Testnet"] = "Plasma_Testnet";
3085
3089
  BridgeChain["Plume_Testnet"] = "Plume_Testnet";
3086
3090
  BridgeChain["Polygon_Amoy_Testnet"] = "Polygon_Amoy_Testnet";
3087
3091
  BridgeChain["Sei_Testnet"] = "Sei_Testnet";
@@ -3539,6 +3543,8 @@ var EarnChain;
3539
3543
  * This program handles minting operations for Gateway transactions
3540
3544
  * on Solana devnet.
3541
3545
  */ const GATEWAY_MINTER_SOLANA_DEVNET = 'GATEmKK2ECL1brEngQZWCgMWPbvrEYqsV6u29dAaHavr';
3546
+ /** TokenMessengerWithFees address shared by enabled EVM mainnet sources. */ const TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET = '0x71f54F818671cD0D7ea140Da213e5C8b5C92a408';
3547
+ /** TokenMessengerWithFees address shared by enabled EVM testnet sources. */ const TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET = '0x8745D906D67C346E5eb1aEEED38Eb87F34DF0C0A';
3542
3548
 
3543
3549
  /**
3544
3550
  * Arc Testnet chain definition
@@ -3576,6 +3582,7 @@ var EarnChain;
3576
3582
  v2: {
3577
3583
  type: 'split',
3578
3584
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
3585
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
3579
3586
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
3580
3587
  confirmations: 1,
3581
3588
  fastConfirmations: 1
@@ -3643,6 +3650,7 @@ var EarnChain;
3643
3650
  v2: {
3644
3651
  type: 'split',
3645
3652
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
3653
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
3646
3654
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
3647
3655
  confirmations: 65,
3648
3656
  fastConfirmations: 1
@@ -3707,6 +3715,7 @@ var EarnChain;
3707
3715
  v2: {
3708
3716
  type: 'split',
3709
3717
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
3718
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
3710
3719
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
3711
3720
  confirmations: 65,
3712
3721
  fastConfirmations: 1
@@ -3771,6 +3780,7 @@ var EarnChain;
3771
3780
  v2: {
3772
3781
  type: 'split',
3773
3782
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
3783
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
3774
3784
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
3775
3785
  confirmations: 1,
3776
3786
  fastConfirmations: 1
@@ -3832,6 +3842,7 @@ var EarnChain;
3832
3842
  v2: {
3833
3843
  type: 'split',
3834
3844
  tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
3845
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
3835
3846
  messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
3836
3847
  confirmations: 1,
3837
3848
  fastConfirmations: 1
@@ -3899,6 +3910,7 @@ var EarnChain;
3899
3910
  v2: {
3900
3911
  type: 'split',
3901
3912
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
3913
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
3902
3914
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
3903
3915
  confirmations: 65,
3904
3916
  fastConfirmations: 1
@@ -3963,6 +3975,7 @@ var EarnChain;
3963
3975
  v2: {
3964
3976
  type: 'split',
3965
3977
  tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
3978
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
3966
3979
  messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
3967
3980
  confirmations: 65,
3968
3981
  fastConfirmations: 1
@@ -4073,6 +4086,7 @@ var EarnChain;
4073
4086
  v2: {
4074
4087
  type: 'split',
4075
4088
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
4089
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
4076
4090
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
4077
4091
  confirmations: 65,
4078
4092
  fastConfirmations: 1
@@ -4117,6 +4131,7 @@ var EarnChain;
4117
4131
  v2: {
4118
4132
  type: 'split',
4119
4133
  tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
4134
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4120
4135
  messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
4121
4136
  confirmations: 65,
4122
4137
  fastConfirmations: 1
@@ -4348,6 +4363,7 @@ var EarnChain;
4348
4363
  v2: {
4349
4364
  type: 'split',
4350
4365
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
4366
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
4351
4367
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
4352
4368
  confirmations: 65,
4353
4369
  fastConfirmations: 2
@@ -4412,6 +4428,7 @@ var EarnChain;
4412
4428
  v2: {
4413
4429
  type: 'split',
4414
4430
  tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
4431
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4415
4432
  messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
4416
4433
  confirmations: 65,
4417
4434
  fastConfirmations: 2
@@ -4522,6 +4539,7 @@ var EarnChain;
4522
4539
  v2: {
4523
4540
  type: 'split',
4524
4541
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
4542
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
4525
4543
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
4526
4544
  confirmations: 1,
4527
4545
  fastConfirmations: 1
@@ -4581,6 +4599,7 @@ var EarnChain;
4581
4599
  v2: {
4582
4600
  type: 'split',
4583
4601
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
4602
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4584
4603
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
4585
4604
  confirmations: 1,
4586
4605
  fastConfirmations: 1
@@ -4735,6 +4754,7 @@ var EarnChain;
4735
4754
  v2: {
4736
4755
  type: 'split',
4737
4756
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
4757
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
4738
4758
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
4739
4759
  confirmations: 65,
4740
4760
  fastConfirmations: 1
@@ -4782,6 +4802,7 @@ var EarnChain;
4782
4802
  v2: {
4783
4803
  type: 'split',
4784
4804
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
4805
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4785
4806
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
4786
4807
  confirmations: 65,
4787
4808
  fastConfirmations: 1
@@ -4826,6 +4847,7 @@ var EarnChain;
4826
4847
  v2: {
4827
4848
  type: 'split',
4828
4849
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
4850
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
4829
4851
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
4830
4852
  confirmations: 1,
4831
4853
  fastConfirmations: 1
@@ -4871,6 +4893,7 @@ var EarnChain;
4871
4893
  v2: {
4872
4894
  type: 'split',
4873
4895
  tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
4896
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4874
4897
  messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
4875
4898
  confirmations: 1,
4876
4899
  fastConfirmations: 1
@@ -4917,6 +4940,7 @@ var EarnChain;
4917
4940
  v2: {
4918
4941
  type: 'split',
4919
4942
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
4943
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
4920
4944
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
4921
4945
  confirmations: 1,
4922
4946
  fastConfirmations: 1
@@ -5230,6 +5254,7 @@ var EarnChain;
5230
5254
  v2: {
5231
5255
  type: 'split',
5232
5256
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
5257
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
5233
5258
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
5234
5259
  confirmations: 65,
5235
5260
  fastConfirmations: 1
@@ -5294,6 +5319,7 @@ var EarnChain;
5294
5319
  v2: {
5295
5320
  type: 'split',
5296
5321
  tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
5322
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
5297
5323
  messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
5298
5324
  confirmations: 65,
5299
5325
  fastConfirmations: 1
@@ -5414,6 +5440,98 @@ var EarnChain;
5414
5440
  }
5415
5441
  });
5416
5442
 
5443
+ /**
5444
+ * Plasma Mainnet chain definition
5445
+ * @remarks
5446
+ * This represents the official production network for the Plasma blockchain.
5447
+ * Plasma is an EVM-equivalent Layer 1 blockchain purpose-built for global
5448
+ * stablecoin payments, with deterministic BFT finality (PlasmaBFT/Fast-HotStuff).
5449
+ */ const Plasma = defineChain({
5450
+ type: 'evm',
5451
+ chain: Blockchain.Plasma,
5452
+ name: 'Plasma',
5453
+ title: 'Plasma Mainnet',
5454
+ nativeCurrency: {
5455
+ name: 'Plasma',
5456
+ symbol: 'XPL',
5457
+ decimals: 18
5458
+ },
5459
+ chainId: 9745,
5460
+ isTestnet: false,
5461
+ explorerUrl: 'https://plasmascan.to/tx/{hash}',
5462
+ rpcEndpoints: [
5463
+ 'https://rpc.plasma.to'
5464
+ ],
5465
+ eurcAddress: '0x3EE196E78d4d4248b849B8E1C7F44C5457FAFD2C',
5466
+ usdcAddress: '0x2d661C89D812261039AF9764eceaAee884f5F67F',
5467
+ usdtAddress: null,
5468
+ cctp: {
5469
+ domain: 33,
5470
+ contracts: {
5471
+ v2: {
5472
+ type: 'split',
5473
+ tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
5474
+ messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
5475
+ confirmations: 3,
5476
+ fastConfirmations: 1
5477
+ }
5478
+ },
5479
+ forwarderSupported: {
5480
+ source: false,
5481
+ destination: false
5482
+ }
5483
+ },
5484
+ kitContracts: {
5485
+ bridge: BRIDGE_CONTRACT_EVM_MAINNET
5486
+ }
5487
+ });
5488
+
5489
+ /**
5490
+ * Plasma Testnet chain definition
5491
+ * @remarks
5492
+ * This represents the official test network for the Plasma blockchain.
5493
+ * Plasma is an EVM-equivalent Layer 1 blockchain purpose-built for global
5494
+ * stablecoin payments, with deterministic BFT finality (PlasmaBFT/Fast-HotStuff).
5495
+ */ const PlasmaTestnet = defineChain({
5496
+ type: 'evm',
5497
+ chain: Blockchain.Plasma_Testnet,
5498
+ name: 'Plasma Testnet',
5499
+ title: 'Plasma Testnet',
5500
+ nativeCurrency: {
5501
+ name: 'Plasma',
5502
+ symbol: 'XPL',
5503
+ decimals: 18
5504
+ },
5505
+ chainId: 9746,
5506
+ isTestnet: true,
5507
+ explorerUrl: 'https://testnet.plasmascan.to/tx/{hash}',
5508
+ rpcEndpoints: [
5509
+ 'https://testnet-rpc.plasma.to'
5510
+ ],
5511
+ eurcAddress: '0x98AfA0F93Dd993B736399f9074eDcEBD1985A330',
5512
+ usdcAddress: '0xE67Fb267022cBA8064Dd388CC2FED724F3120D9D',
5513
+ usdtAddress: null,
5514
+ cctp: {
5515
+ domain: 33,
5516
+ contracts: {
5517
+ v2: {
5518
+ type: 'split',
5519
+ tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
5520
+ messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
5521
+ confirmations: 3,
5522
+ fastConfirmations: 1
5523
+ }
5524
+ },
5525
+ forwarderSupported: {
5526
+ source: false,
5527
+ destination: false
5528
+ }
5529
+ },
5530
+ kitContracts: {
5531
+ bridge: BRIDGE_CONTRACT_EVM_TESTNET
5532
+ }
5533
+ });
5534
+
5417
5535
  /**
5418
5536
  * Plume Mainnet chain definition
5419
5537
  * @remarks
@@ -5445,6 +5563,7 @@ var EarnChain;
5445
5563
  v2: {
5446
5564
  type: 'split',
5447
5565
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
5566
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
5448
5567
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
5449
5568
  confirmations: 65,
5450
5569
  fastConfirmations: 1
@@ -5491,6 +5610,7 @@ var EarnChain;
5491
5610
  v2: {
5492
5611
  type: 'split',
5493
5612
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
5613
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
5494
5614
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
5495
5615
  confirmations: 65,
5496
5616
  fastConfirmations: 1
@@ -5592,6 +5712,7 @@ var EarnChain;
5592
5712
  v2: {
5593
5713
  type: 'split',
5594
5714
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
5715
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
5595
5716
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
5596
5717
  confirmations: 33,
5597
5718
  fastConfirmations: 13
@@ -5657,6 +5778,7 @@ var EarnChain;
5657
5778
  v2: {
5658
5779
  type: 'split',
5659
5780
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
5781
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
5660
5782
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
5661
5783
  confirmations: 33,
5662
5784
  fastConfirmations: 13
@@ -5716,6 +5838,7 @@ var EarnChain;
5716
5838
  v2: {
5717
5839
  type: 'split',
5718
5840
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
5841
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
5719
5842
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
5720
5843
  confirmations: 1,
5721
5844
  fastConfirmations: 1
@@ -5775,6 +5898,7 @@ var EarnChain;
5775
5898
  v2: {
5776
5899
  type: 'split',
5777
5900
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
5901
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
5778
5902
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
5779
5903
  confirmations: 1,
5780
5904
  fastConfirmations: 1
@@ -5832,6 +5956,7 @@ var EarnChain;
5832
5956
  v2: {
5833
5957
  type: 'split',
5834
5958
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
5959
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
5835
5960
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
5836
5961
  confirmations: 1,
5837
5962
  fastConfirmations: 1
@@ -5890,6 +6015,7 @@ var EarnChain;
5890
6015
  v2: {
5891
6016
  type: 'split',
5892
6017
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
6018
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
5893
6019
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
5894
6020
  confirmations: 1,
5895
6021
  fastConfirmations: 1
@@ -6205,6 +6331,7 @@ var EarnChain;
6205
6331
  v2: {
6206
6332
  type: 'split',
6207
6333
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
6334
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
6208
6335
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
6209
6336
  confirmations: 65,
6210
6337
  fastConfirmations: 1
@@ -6269,6 +6396,7 @@ var EarnChain;
6269
6396
  v2: {
6270
6397
  type: 'split',
6271
6398
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
6399
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
6272
6400
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
6273
6401
  confirmations: 65,
6274
6402
  fastConfirmations: 1
@@ -6326,6 +6454,7 @@ var EarnChain;
6326
6454
  v2: {
6327
6455
  type: 'split',
6328
6456
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cF5d',
6457
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
6329
6458
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
6330
6459
  confirmations: 65,
6331
6460
  fastConfirmations: 1
@@ -6385,6 +6514,7 @@ var EarnChain;
6385
6514
  v2: {
6386
6515
  type: 'split',
6387
6516
  tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
6517
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
6388
6518
  messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
6389
6519
  confirmations: 65,
6390
6520
  fastConfirmations: 1
@@ -6445,6 +6575,7 @@ var EarnChain;
6445
6575
  v2: {
6446
6576
  type: 'split',
6447
6577
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
6578
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
6448
6579
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
6449
6580
  confirmations: 3,
6450
6581
  fastConfirmations: 3
@@ -6490,6 +6621,7 @@ var EarnChain;
6490
6621
  v2: {
6491
6622
  type: 'split',
6492
6623
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
6624
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
6493
6625
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
6494
6626
  confirmations: 3,
6495
6627
  fastConfirmations: 1
@@ -6700,6 +6832,8 @@ var Chains = {
6700
6832
  OptimismSepolia: OptimismSepolia,
6701
6833
  Pharos: Pharos,
6702
6834
  PharosTestnet: PharosTestnet,
6835
+ Plasma: Plasma,
6836
+ PlasmaTestnet: PlasmaTestnet,
6703
6837
  Plume: Plume,
6704
6838
  PlumeTestnet: PlumeTestnet,
6705
6839
  PolkadotAssetHub: PolkadotAssetHub,
@@ -8741,6 +8875,7 @@ const swapTokenEnumSchema = zod.z.enum([
8741
8875
  [Blockchain.Noble]: 'uusdc',
8742
8876
  [Blockchain.Optimism]: '0x0b2c639c533813f4aa9d7837caf62653d097ff85',
8743
8877
  [Blockchain.Pharos]: '0xC879C018dB60520F4355C26eD1a6D572cdAC1815',
8878
+ [Blockchain.Plasma]: '0x2d661C89D812261039AF9764eceaAee884f5F67F',
8744
8879
  [Blockchain.Plume]: '0x222365EF19F7947e5484218551B56bb3965Aa7aF',
8745
8880
  [Blockchain.Polkadot_Asset_Hub]: '1337',
8746
8881
  [Blockchain.Polygon]: '0x3c499c542cef5e3811e1192ce70d8cc03d5c3359',
@@ -8777,6 +8912,7 @@ const swapTokenEnumSchema = zod.z.enum([
8777
8912
  [Blockchain.Noble_Testnet]: 'uusdc',
8778
8913
  [Blockchain.Optimism_Sepolia]: '0x5fd84259d66Cd46123540766Be93DFE6D43130D7',
8779
8914
  [Blockchain.Pharos_Testnet]: '0xcfC8330f4BCAB529c625D12781b1C19466A9Fc8B',
8915
+ [Blockchain.Plasma_Testnet]: '0xE67Fb267022cBA8064Dd388CC2FED724F3120D9D',
8780
8916
  [Blockchain.Plume_Testnet]: '0xcB5f30e335672893c7eb944B374c196392C19D18',
8781
8917
  [Blockchain.Polkadot_Westmint]: '31337',
8782
8918
  [Blockchain.Polygon_Amoy_Testnet]: '0x41e94eb019c0762f9bfcf9fb1e58725bfb0e7582',
@@ -8839,6 +8975,7 @@ const swapTokenEnumSchema = zod.z.enum([
8839
8975
  [Blockchain.Base]: '0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42',
8840
8976
  [Blockchain.Cronos]: '0xA6dE01a2d62C6B5f3525d768f34d276652C554c8',
8841
8977
  [Blockchain.Ethereum]: '0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c',
8978
+ [Blockchain.Plasma]: '0x3EE196E78d4d4248b849B8E1C7F44C5457FAFD2C',
8842
8979
  [Blockchain.Solana]: 'HzwqbKZw8HxMN6bF2yFZNrht3c2iXXzpKcFu7uBEDKtr',
8843
8980
  [Blockchain.World_Chain]: '0x1C60ba0A0eD1019e8Eb035E6daF4155A5cE2380B',
8844
8981
  // =========================================================================
@@ -8847,7 +8984,8 @@ const swapTokenEnumSchema = zod.z.enum([
8847
8984
  [Blockchain.Arc_Testnet]: '0x89B50855Aa3bE2F677cD6303Cec089B5F319D72a',
8848
8985
  [Blockchain.Base_Sepolia]: '0x808456652fdb597867f38412077A9182bf77359F',
8849
8986
  [Blockchain.Cronos_Testnet]: '0x31f7538adb53cF16350e6B0c89d03D91b7D12c46',
8850
- [Blockchain.Ethereum_Sepolia]: '0x08210F9170F89Ab7658F0B5E3fF39b0E03C594D4'
8987
+ [Blockchain.Ethereum_Sepolia]: '0x08210F9170F89Ab7658F0B5E3fF39b0E03C594D4',
8988
+ [Blockchain.Plasma_Testnet]: '0x98AfA0F93Dd993B736399f9074eDcEBD1985A330'
8851
8989
  }
8852
8990
  };
8853
8991
 
@@ -10076,7 +10214,7 @@ const swapTokenEnumSchema = zod.z.enum([
10076
10214
  }
10077
10215
 
10078
10216
  var name$2 = "@circle-fin/bridge-kit";
10079
- var version$2 = "1.13.0";
10217
+ var version$2 = "1.14.0";
10080
10218
  var pkg$2 = {
10081
10219
  name: name$2,
10082
10220
  version: version$2};
@@ -10430,7 +10568,7 @@ const READ_ACTION_KEY_SET = new Set(READ_ACTION_KEYS);
10430
10568
  * const result = evmAddressSchema.safeParse(validAddress)
10431
10569
  * console.log(result.success) // true
10432
10570
  * ```
10433
- */ const evmAddressSchema = hexStringSchema.refine((value)=>value.length === 42, 'EVM address must be exactly 42 characters long (0x + 40 hex characters)').transform((value)=>value);
10571
+ */ const evmAddressSchema$1 = hexStringSchema.refine((value)=>value.length === 42, 'EVM address must be exactly 42 characters long (0x + 40 hex characters)').transform((value)=>value);
10434
10572
  /**
10435
10573
  * Schema for validating transaction hashes.
10436
10574
  *
@@ -10967,6 +11105,10 @@ var TransferSpeed;
10967
11105
  token: zod.z.literal('USDC').optional(),
10968
11106
  config: zod.z.object({
10969
11107
  transferSpeed: zod.z.nativeEnum(TransferSpeed).optional(),
11108
+ feePayment: zod.z.enum([
11109
+ 'source',
11110
+ 'destination'
11111
+ ]).optional(),
10970
11112
  maxFee: zod.z.string().min(1, 'Required').pipe(createDecimalStringValidator({
10971
11113
  allowZero: true,
10972
11114
  regexMessage: MAX_FEE_FORMAT_ERROR_MESSAGE,
@@ -10974,7 +11116,8 @@ var TransferSpeed;
10974
11116
  maxDecimals: 6
10975
11117
  })(zod.z.string())).optional(),
10976
11118
  customFee: customFeeSchema.optional()
10977
- }).optional()
11119
+ }).optional(),
11120
+ quote: zod.z.string().regex(/^0x([a-fA-F0-9]{2})+$/, 'must be non-empty 0x hex').optional()
10978
11121
  });
10979
11122
 
10980
11123
  /**
@@ -11152,13 +11295,182 @@ var TransferSpeed;
11152
11295
  * @internal
11153
11296
  */ Object.values(Chains).filter((chain)=>isCCTPV2Supported(chain));
11154
11297
 
11298
+ /** Decimal string in token minor units, constrained to be strictly positive. */ const positiveAmountSchema = zod.z.string().regex(/^\d+$/, 'must be a non-negative integer string')// Re-check the digit shape here: zod still runs this refinement when the
11299
+ // regex check above fails ("dirty"), so guard BigInt() against throwing on a
11300
+ // non-numeric value before comparing.
11301
+ .refine((value)=>/^\d+$/.test(value) && BigInt(value) > 0n, 'must be greater than zero');
11302
+ /**
11303
+ * A 20-byte EVM address in `0x` hex.
11304
+ *
11305
+ * The MVP prepaid-`FORWARD` `burn/usdc` path targets EVM contracts
11306
+ * (`TokenMessengerWithFees` / `GenericExecutor`), so `feeToken` and
11307
+ * `destinationCaller` are constrained to EVM addresses by design. This is an
11308
+ * intentional scope limit, not a permanent one: it can be widened to other
11309
+ * address formats as the fee service expands to more chains.
11310
+ */ const evmAddressSchema = zod.z.string().regex(/^0x[a-fA-F0-9]{40}$/, 'must be a 20-byte 0x address');
11311
+ /** Even-length `0x` hex (the empty `0x` is allowed). */ const hexSchema = zod.z.string().regex(/^0x([a-fA-F0-9]{2})*$/, 'must be even-length 0x hex');
11312
+ /** Non-empty, even-length `0x` hex. */ const nonEmptyHexSchema = zod.z.string().regex(/^0x([a-fA-F0-9]{2})+$/, 'must be non-empty 0x hex');
11313
+ /** A 32-byte `0x` hex hash. */ const bytes32Schema = zod.z.string().regex(/^0x[a-fA-F0-9]{64}$/, 'must be a 32-byte 0x hash');
11314
+ /** Decimal string in minor units, allowing zero. */ const numericStringSchema = zod.z.string().regex(/^\d+$/, 'must be a non-negative integer string');
11315
+ /** An `https:` URL, used for the optional base-URL override. */ const httpsUrlSchema = zod.z.string().refine((value)=>{
11316
+ try {
11317
+ return new URL(value).protocol === 'https:';
11318
+ } catch {
11319
+ return false;
11320
+ }
11321
+ }, 'must be an https URL');
11322
+ const forwardParamsSchema = zod.z.object({
11323
+ hookData: hexSchema.optional(),
11324
+ destinationCaller: evmAddressSchema.optional()
11325
+ }).strict();
11326
+ const forwardRequestSchema = zod.z.object({
11327
+ type: zod.z.literal('FORWARD'),
11328
+ params: forwardParamsSchema.optional()
11329
+ }).strict();
11330
+ const preFinalityRequestSchema = zod.z.object({
11331
+ type: zod.z.literal('PRE_FINALITY')
11332
+ }).strict();
11333
+ /** A single quote request item (`FORWARD` or `PRE_FINALITY`). */ const feeQuoteRequestSchema = zod.z.discriminatedUnion('type', [
11334
+ forwardRequestSchema,
11335
+ preFinalityRequestSchema
11336
+ ]);
11337
+ /** A non-empty list of quote request items with unique types. */ const feeQuoteRequestsSchema = zod.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');
11338
+ /**
11339
+ * A structured `Partial<ApiPollingConfig>` polling override.
11340
+ *
11341
+ * Validates the field types callers actually set, so a plain-JS caller passing
11342
+ * `{ timeout: 'soon' }` is rejected at the boundary rather than failing opaquely
11343
+ * inside the transport. Unknown keys pass through so a future `ApiPollingConfig`
11344
+ * field is forwarded rather than silently dropped.
11345
+ */ const apiPollingConfigSchema = zod.z.object({
11346
+ timeout: zod.z.number().int().positive().optional(),
11347
+ maxRetries: zod.z.number().int().nonnegative().optional(),
11348
+ retryDelay: zod.z.number().int().nonnegative().optional(),
11349
+ backoff: zod.z.enum([
11350
+ 'fixed',
11351
+ 'exponential'
11352
+ ]).optional(),
11353
+ maxRetryDelayMs: zod.z.number().int().positive().optional(),
11354
+ headers: zod.z.record(zod.z.string()).optional()
11355
+ }).passthrough();
11356
+ /**
11357
+ * The validatable input for {@link fetchFeeQuote}.
11358
+ *
11359
+ * This is the single source of truth for input validation, including the CCTP
11360
+ * domains and the `isTestnet` environment flag. Validating `isTestnet` at
11361
+ * runtime matters because a plain-JS caller who omits it would otherwise leave
11362
+ * it `undefined`, which is falsy and silently selects the production base URL.
11363
+ * (`buildFeeQuoteUrl` independently re-validates the domains for standalone
11364
+ * callers.)
11365
+ */ zod.z.object({
11366
+ sourceDomain: zod.z.number().int().nonnegative(),
11367
+ destinationDomain: zod.z.number().int().nonnegative(),
11368
+ amount: positiveAmountSchema,
11369
+ feeToken: evmAddressSchema.optional(),
11370
+ requests: feeQuoteRequestsSchema,
11371
+ isTestnet: zod.z.boolean(),
11372
+ baseUrl: httpsUrlSchema.optional(),
11373
+ config: apiPollingConfigSchema.optional()
11374
+ }).strict();
11375
+ const feeQuoteItemSchema = zod.z.object({
11376
+ type: zod.z.string().min(1),
11377
+ amount: numericStringSchema,
11378
+ args: zod.z.array(zod.z.string()),
11379
+ argsHash: bytes32Schema
11380
+ }).passthrough();
11381
+ const exchangeRatesSchema = zod.z.object({
11382
+ feeTokenUsd: zod.z.string(),
11383
+ destinationTokenUsd: zod.z.string()
11384
+ }).passthrough();
11385
+ const metadataSchema = zod.z.object({
11386
+ destinationGasPrice: zod.z.string().optional(),
11387
+ exchangeRates: exchangeRatesSchema.optional()
11388
+ }).passthrough();
11389
+ /** The `expiry` object the Quote API nests the quote TTL under. */ const expirySchema = zod.z.discriminatedUnion('mode', [
11390
+ zod.z.object({
11391
+ mode: zod.z.literal('TIMESTAMP'),
11392
+ expiresAt: zod.z.number().int().nonnegative()
11393
+ }).passthrough(),
11394
+ zod.z.object({
11395
+ mode: zod.z.literal('BLOCK_NUMBER'),
11396
+ expiresAtBlock: zod.z.number().int().nonnegative(),
11397
+ blockEstimatedAt: zod.z.number().int().nonnegative().optional()
11398
+ }).passthrough()
11399
+ ]);
11400
+ /** Schema for a signed fee quote returned by the Quote API. */ zod.z.object({
11401
+ // The runtime YAML spec maps signedQuote to a looser `hex` (which allows
11402
+ // an empty `0x`); we keep the stricter non-empty form. Do not relax
11403
+ // without a reason.
11404
+ signedQuote: nonEmptyHexSchema,
11405
+ issuedAt: zod.z.number().int().nonnegative(),
11406
+ // The API returns a mode-specific timestamp or source-block deadline.
11407
+ expiry: expirySchema,
11408
+ feeTotalAmount: numericStringSchema,
11409
+ feeToken: evmAddressSchema,
11410
+ nonce: numericStringSchema,
11411
+ items: zod.z.array(feeQuoteItemSchema),
11412
+ metadata: metadataSchema.optional()
11413
+ }).passthrough();
11414
+ /** Validate input to {@link validateQuote}. */ zod.z.object({
11415
+ sourceDomain: zod.z.number().int().nonnegative(),
11416
+ abiSignature: zod.z.string().min(1),
11417
+ args: zod.z.array(zod.z.union([
11418
+ zod.z.string(),
11419
+ zod.z.array(zod.z.string())
11420
+ ])),
11421
+ isTestnet: zod.z.boolean(),
11422
+ baseUrl: httpsUrlSchema.optional(),
11423
+ config: apiPollingConfigSchema.optional()
11424
+ }).strict();
11425
+ const quoteExpiryStatusSchema = zod.z.discriminatedUnion('mode', [
11426
+ zod.z.object({
11427
+ mode: zod.z.literal('TIMESTAMP'),
11428
+ expired: zod.z.boolean(),
11429
+ secondsRemaining: zod.z.number().int().nonnegative(),
11430
+ expiresAt: zod.z.number().int().nonnegative()
11431
+ }).passthrough(),
11432
+ zod.z.object({
11433
+ mode: zod.z.literal('BLOCK_NUMBER'),
11434
+ expired: zod.z.boolean(),
11435
+ secondsRemaining: zod.z.number().int().nonnegative(),
11436
+ expiresAtBlock: zod.z.number().int().nonnegative(),
11437
+ blockEstimatedAt: zod.z.number().int().nonnegative().optional()
11438
+ }).passthrough()
11439
+ ]);
11440
+ const validateQuoteItemSchema = zod.z.object({
11441
+ type: zod.z.string().min(1),
11442
+ argsMatch: zod.z.boolean(),
11443
+ amount: numericStringSchema.optional(),
11444
+ args: zod.z.array(zod.z.string()).optional(),
11445
+ argsHash: bytes32Schema.optional(),
11446
+ computedArgsHash: bytes32Schema.optional()
11447
+ }).passthrough();
11448
+ /**
11449
+ * Schema for a response from the Quote API validation endpoint.
11450
+ *
11451
+ * The endpoint takes the source domain as a URL path parameter and does not
11452
+ * return it in the response body, so `sourceDomain` is intentionally not part
11453
+ * of this schema.
11454
+ */ zod.z.object({
11455
+ signedQuote: nonEmptyHexSchema,
11456
+ expiry: quoteExpiryStatusSchema,
11457
+ feeTotalAmount: numericStringSchema,
11458
+ feeToken: evmAddressSchema,
11459
+ nonce: numericStringSchema,
11460
+ claimable: zod.z.boolean(),
11461
+ // Preserve newly introduced server-side reasons as opaque strings rather
11462
+ // than rejecting the entire safety response before the SDK is updated.
11463
+ failedChecks: zod.z.array(zod.z.string().min(1)),
11464
+ items: zod.z.array(validateQuoteItemSchema)
11465
+ }).passthrough();
11466
+
11155
11467
  /** SDK name used in telemetry payloads. */ resolveKitSdkName(pkg$2.name);
11156
11468
 
11157
11469
  // Auto-register this kit for user agent tracking
11158
11470
  registerKit(`${pkg$2.name}/${pkg$2.version}`);
11159
11471
 
11160
11472
  var name$1 = "@circle-fin/swap-kit";
11161
- var version$1 = "1.5.2";
11473
+ var version$1 = "1.6.0";
11162
11474
  var pkg$1 = {
11163
11475
  name: name$1,
11164
11476
  version: version$1};
@@ -11172,7 +11484,7 @@ const optionalChainIdentifierField = chainIdentifierField.optional();
11172
11484
  * Catches obviously malformed addresses at parse time; chain-specific validation
11173
11485
  * is performed in buildServiceParams.
11174
11486
  */ const destinationAddressSchema = zod.z.union([
11175
- evmAddressSchema,
11487
+ evmAddressSchema$1,
11176
11488
  solanaAddressSchema
11177
11489
  ]);
11178
11490
  /**
@@ -11218,9 +11530,16 @@ const optionalChainIdentifierField = chainIdentifierField.optional();
11218
11530
  message: 'stopLimit must be greater than 0'
11219
11531
  }).optional(),
11220
11532
  customFee: serviceSwapCustomFeeSchema.optional(),
11533
+ apiKey: zod.z.string({
11534
+ invalid_type_error: 'apiKey must be a string'
11535
+ })// Tolerate '' so the `process.env.CIRCLE_API_KEY ?? ''` idiom falls back to
11536
+ // kitKey via resolveApiKey instead of being rejected here.
11537
+ .optional(),
11221
11538
  kitKey: zod.z.string({
11222
11539
  invalid_type_error: 'kitKey must be a string'
11223
- }).min(1, 'kitKey must be a non-empty string').optional(),
11540
+ })// Tolerate '' so an unset kit-key env var yields the permissionless path,
11541
+ // matching buildServiceParams (which already omits an empty credential).
11542
+ .optional(),
11224
11543
  provider: zod.z.string({
11225
11544
  invalid_type_error: 'provider must be a string'
11226
11545
  }).min(1, 'provider must be a non-empty string').optional(),
@@ -11385,23 +11704,49 @@ const optionalChainIdentifierField = chainIdentifierField.optional();
11385
11704
  fees: zod.z.array(serviceSwapFeeSchema).optional()
11386
11705
  }).passthrough();
11387
11706
 
11388
- /** Placeholder used wherever a kit key is scrubbed from logs, traces, or errors. */ const REDACTED_KIT_KEY = '[redacted]';
11707
+ /** Placeholder used wherever a credential is scrubbed from logs, traces, or errors. */ const REDACTED_CREDENTIAL = '[redacted]';
11708
+ /**
11709
+ * Config fields that carry a Stablecoin Service credential.
11710
+ *
11711
+ * `apiKey` is the supported field; `kitKey` is the deprecated alias. Redaction
11712
+ * and credential resolution both read this list so a newly added field is
11713
+ * scrubbed everywhere it needs to be.
11714
+ */ const CREDENTIAL_CONFIG_FIELDS = [
11715
+ 'apiKey',
11716
+ 'kitKey'
11717
+ ];
11389
11718
 
11719
+ /**
11720
+ * Replaces any credential field present on a config with a redaction marker.
11721
+ *
11722
+ * Covers `apiKey` and the deprecated `kitKey`, so adding a credential field
11723
+ * without extending this list cannot silently leak it into a trace. Returns the
11724
+ * config unchanged when it carries no credential.
11725
+ */ const redactCredentialFields = (config)=>{
11726
+ const present = CREDENTIAL_CONFIG_FIELDS.filter((field)=>field in config);
11727
+ if (present.length === 0) {
11728
+ return config;
11729
+ }
11730
+ return present.reduce((acc, field)=>({
11731
+ ...acc,
11732
+ [field]: REDACTED_CREDENTIAL
11733
+ }), {
11734
+ ...config
11735
+ });
11736
+ };
11390
11737
  /**
11391
11738
  * Builds a redacted projection of swap params that is safe to embed in error
11392
11739
  * traces (which may be logged downstream). Allow-lists only non-sensitive
11393
11740
  * fields and drops `from` entirely — `from.adapter` can carry signer/private-key
11394
- * material for signer-backed (viem/ethers) flows — and redacts `config.kitKey`.
11741
+ * material for signer-backed (viem/ethers) flows — and redacts every credential
11742
+ * field on `config`.
11395
11743
  */ const redactSwapParamsForTrace = (params)=>{
11396
11744
  if (typeof params !== 'object' || params === null) {
11397
11745
  return params;
11398
11746
  }
11399
11747
  const record = params;
11400
11748
  const config = record['config'];
11401
- const redactedConfig = typeof config === 'object' && config !== null && 'kitKey' in config ? {
11402
- ...config,
11403
- kitKey: REDACTED_KIT_KEY
11404
- } : config;
11749
+ const redactedConfig = typeof config === 'object' && config !== null ? redactCredentialFields(config) : config;
11405
11750
  return {
11406
11751
  tokenIn: record['tokenIn'],
11407
11752
  tokenOut: record['tokenOut'],
@@ -11485,6 +11830,41 @@ const optionalChainIdentifierField = chainIdentifierField.optional();
11485
11830
  *
11486
11831
  * @internal
11487
11832
  */ const MAX_RATE_ADDRESSES_PER_REQUEST = 100;
11833
+ /**
11834
+ * Environment prefixes carried by Circle platform API keys.
11835
+ *
11836
+ * A Circle API key is `<ENV>_API_KEY:<keyId>:<keySecret>`, where `<ENV>` is one
11837
+ * of these prefixes.
11838
+ *
11839
+ * @internal
11840
+ */ const API_KEY_ENV_PREFIXES = [
11841
+ 'TEST',
11842
+ 'LIVE',
11843
+ 'SAND',
11844
+ 'SANDBOX',
11845
+ 'SMOK',
11846
+ 'PROD',
11847
+ 'STAG',
11848
+ 'DEV'
11849
+ ];
11850
+ /**
11851
+ * Accepted credential formats for Stablecoin Service authentication.
11852
+ *
11853
+ * Matches a Circle platform API key (`<ENV>_API_KEY:<keyId>:<keySecret>`) and
11854
+ * the legacy kit key (`KIT_KEY:<keyId>:<keySecret>`). API keys are the
11855
+ * recommended credential; kit keys remain accepted as the legacy path.
11856
+ *
11857
+ * @remarks
11858
+ * This is a local pre-flight check, not the authority — the Stablecoin Service
11859
+ * validates the credential and answers 401 when it rejects one. The prefix list
11860
+ * is therefore deliberately permissive: a valid key carrying a prefix this SDK
11861
+ * has not been taught about should reach the service and be judged there rather
11862
+ * than be refused locally, since refusing locally is indistinguishable from an
11863
+ * outage to the caller. Kept as the single source of truth so the pattern is
11864
+ * not restated per call site.
11865
+ *
11866
+ * @internal
11867
+ */ const API_KEY_PATTERN = new RegExp(`^(?:KIT_KEY|(?:${API_KEY_ENV_PREFIXES.join('|')})_API_KEY)` + ':[a-zA-Z0-9._-]+:[a-zA-Z0-9._-]+$');
11488
11868
 
11489
11869
  /**
11490
11870
  * Zod schema for validating stop limits.
@@ -11553,13 +11933,14 @@ const optionalChainIdentifierField = chainIdentifierField.optional();
11553
11933
  /**
11554
11934
  * Zod schema for validating API keys.
11555
11935
  *
11556
- * Validates that the API key is a valid API key format.
11936
+ * Accepts a Circle platform API key (`<ENV>_API_KEY:<keyId>:<keySecret>`) and
11937
+ * the legacy kit key (`KIT_KEY:<keyId>:<keySecret>`).
11557
11938
  *
11558
11939
  * @example
11559
11940
  * ```typescript
11560
11941
  * import { apiKeySchema } from '@core/service-client'
11561
11942
  *
11562
- * const result = apiKeySchema.safeParse('KIT_KEY:e84d2546d4e321b2ff427dc988c89503:f84d2548d4e322b2ff427fc989c87503')
11943
+ * const result = apiKeySchema.safeParse('TEST_API_KEY:e84d2546d4e321b2ff427dc988c89503:f84d2548d4e322b2ff427fc989c87503')
11563
11944
  * if (!result.success) {
11564
11945
  * console.error('Invalid API key format:', result.error.issues)
11565
11946
  * }
@@ -11567,7 +11948,7 @@ const optionalChainIdentifierField = chainIdentifierField.optional();
11567
11948
  */ const apiKeySchema = zod.z.string({
11568
11949
  required_error: 'API key is required',
11569
11950
  invalid_type_error: 'Invalid API key format'
11570
- }).regex(/^KIT_KEY:[a-zA-Z0-9._-]+:[a-zA-Z0-9._-]+$/, 'Invalid API key format');
11951
+ }).regex(API_KEY_PATTERN, 'Invalid API key format');
11571
11952
  /**
11572
11953
  * Zod schema for platform fees configuration.
11573
11954
  *
@@ -12088,21 +12469,55 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
12088
12469
  * ```
12089
12470
  */ const isGetTokenRatesResponse = (obj)=>getTokenRatesResponseSchema.safeParse(obj).success;
12090
12471
  /**
12091
- * Assert that a Stablecoin Service kit key is not being supplied from a browser.
12472
+ * Resolve the credential to authenticate a Stablecoin Service request with.
12473
+ *
12474
+ * `apiKey` is the supported field; `kitKey` is the deprecated alias kept for
12475
+ * existing integrations. When both are supplied `apiKey` wins, so a caller
12476
+ * migrating field-by-field cannot be silently pinned to a stale credential.
12477
+ *
12478
+ * An empty-string value is treated as absent on either field. Without this, the
12479
+ * common `process.env.CIRCLE_API_KEY ?? ''` idiom (which yields `''` when the
12480
+ * variable is unset) would either shadow a working `kitKey` or, on a bare
12481
+ * `kitKey: ''`, reach downstream validation as an invalid credential instead of
12482
+ * falling through to the permissionless path.
12483
+ *
12484
+ * @param source - Object carrying either credential field, or neither.
12485
+ * @returns The credential to use, or `undefined` for the permissionless
12486
+ * (keyless) path.
12487
+ *
12488
+ * @example
12489
+ * ```typescript
12490
+ * import { resolveApiKey } from '@core/service-client'
12491
+ *
12492
+ * resolveApiKey({ apiKey: 'TEST_API_KEY:id:secret' }) // 'TEST_API_KEY:id:secret'
12493
+ * resolveApiKey({ kitKey: 'KIT_KEY:id:secret' }) // 'KIT_KEY:id:secret'
12494
+ * resolveApiKey({ apiKey: '', kitKey: 'KIT_KEY:id:secret' }) // 'KIT_KEY:id:secret'
12495
+ * resolveApiKey({ kitKey: '' }) // undefined
12496
+ * resolveApiKey({}) // undefined
12497
+ * ```
12498
+ */ const resolveApiKey = (source)=>{
12499
+ // Treat an empty-string value as absent on either field so the
12500
+ // `env ?? ''` idiom falls through to the next credential (or permissionless).
12501
+ const normalize = (value)=>value !== undefined && value !== '' ? value : undefined;
12502
+ return normalize(source.apiKey) ?? normalize(source.kitKey);
12503
+ };
12504
+ /**
12505
+ * Assert that a Stablecoin Service credential is not supplied from a browser.
12092
12506
  *
12093
- * The kit key (`KIT_KEY:<id>:<secret>`) is a server-only secret. Every
12094
- * Stablecoin Service request that attaches an `Authorization: Bearer` header
12095
- * funnels through this package, so calling this guard before that header is
12096
- * built prevents the secret from being sent from and thus bundled into — a
12097
- * client application. In Node.js the check is a no-op, preserving the
12098
- * legitimate "hold the kit key on the server, forward the prepared transaction
12099
- * to the client" flow. When no kit key is supplied the permissionless (keyless)
12100
- * client path remains fully allowed.
12507
+ * An API key (`<ENV>_API_KEY:<id>:<secret>`) and a legacy kit key
12508
+ * (`KIT_KEY:<id>:<secret>`) are both server-only secrets. Every Stablecoin
12509
+ * Service request that attaches an `Authorization: Bearer` header funnels
12510
+ * through this package, so calling this guard before that header is built
12511
+ * prevents the secret from being sent from and thus bundled into — a client
12512
+ * application. In Node.js the check is a no-op, preserving the legitimate "hold
12513
+ * the credential on the server, forward the prepared transaction to the client"
12514
+ * flow. When no credential is supplied the permissionless (keyless) client path
12515
+ * remains fully allowed.
12101
12516
  *
12102
- * @param apiKey - The inline kit key for the request, or `undefined` when none
12103
- * was supplied (permissionless mode).
12517
+ * @param apiKey - The inline credential for the request, or `undefined` when
12518
+ * none was supplied (permissionless mode).
12104
12519
  * @returns Nothing.
12105
- * @throws KitError with VALIDATION_FAILED when a kit key is supplied while
12520
+ * @throws KitError with VALIDATION_FAILED when a credential is supplied while
12106
12521
  * running in a browser environment. The secret value is never echoed.
12107
12522
  *
12108
12523
  * @example
@@ -12110,10 +12525,10 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
12110
12525
  * import { assertBrowserSafeApiKey } from '@core/service-client'
12111
12526
  *
12112
12527
  * // Server (Node.js): no-op, request proceeds with the Authorization header.
12113
- * assertBrowserSafeApiKey('KIT_KEY:my-id:my-secret')
12528
+ * assertBrowserSafeApiKey('TEST_API_KEY:my-id:my-secret')
12114
12529
  *
12115
12530
  * // Browser: throws to stop the secret from leaking into the client bundle.
12116
- * assertBrowserSafeApiKey('KIT_KEY:my-id:my-secret')
12531
+ * assertBrowserSafeApiKey('TEST_API_KEY:my-id:my-secret')
12117
12532
  *
12118
12533
  * // Browser, permissionless: allowed.
12119
12534
  * assertBrowserSafeApiKey(undefined)
@@ -12123,7 +12538,7 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
12123
12538
  return;
12124
12539
  }
12125
12540
  if (isBrowserEnvironment()) {
12126
- 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');
12541
+ 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');
12127
12542
  }
12128
12543
  };
12129
12544
 
@@ -12135,7 +12550,8 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
12135
12550
  *
12136
12551
  * @remarks
12137
12552
  * - Input validation leverages Zod schemas to surface actionable KitErrors.
12138
- * - API key format must match `KIT_KEY:<keyId>:<keySecret>`
12553
+ * - API key format must match `<ENV>_API_KEY:<keyId>:<keySecret>`, or the
12554
+ * legacy `KIT_KEY:<keyId>:<keySecret>`
12139
12555
  *
12140
12556
  * @param params - The create transaction request parameters with API key.
12141
12557
  * @returns A promise that resolves to a typed {@link CreateSwapResponse}.
@@ -12164,7 +12580,7 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
12164
12580
  * recipientAddress: '0x050928e1f9086b20539c767c96909663ff7fbdf2',
12165
12581
  * },
12166
12582
  * },
12167
- * apiKey: 'KIT_KEY:example-key:example-secret',
12583
+ * apiKey: 'TEST_API_KEY:example-key:example-secret',
12168
12584
  * })
12169
12585
  *
12170
12586
  * console.log(`Transaction target: ${transaction.transaction.target}`)
@@ -12183,13 +12599,13 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
12183
12599
  const url = new URL('/v1/stablecoinKits/swap', STABLECOIN_SERVICE_BASE_URL).toString();
12184
12600
  // Remove the API key from the request body
12185
12601
  const { apiKey, ...requestBody } = validatedParams;
12186
- // Never let a server-only kit key leave a browser (no-op in Node.js).
12602
+ // Never let a server-only credential leave a browser (no-op in Node.js).
12187
12603
  assertBrowserSafeApiKey(apiKey);
12188
12604
  const effectiveConfig = {
12189
12605
  ...DEFAULT_CONFIG,
12190
12606
  headers: {
12191
12607
  ...DEFAULT_CONFIG.headers,
12192
- // Permissionless mode: no Authorization header when the kit key is absent.
12608
+ // Permissionless mode: no Authorization header when the credential is absent.
12193
12609
  ...apiKey !== undefined && {
12194
12610
  Authorization: `Bearer ${apiKey}`
12195
12611
  }
@@ -12339,7 +12755,7 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
12339
12755
  }
12340
12756
  // Use validated data
12341
12757
  const validatedParams = result.data;
12342
- // Never let a server-only kit key leave a browser (no-op in Node.js).
12758
+ // Never let a server-only credential leave a browser (no-op in Node.js).
12343
12759
  assertBrowserSafeApiKey(validatedParams.apiKey);
12344
12760
  // Build the API URL
12345
12761
  const url = buildQuoteUrl(validatedParams);
@@ -12348,7 +12764,7 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
12348
12764
  ...DEFAULT_CONFIG,
12349
12765
  headers: {
12350
12766
  ...DEFAULT_CONFIG.headers,
12351
- // Permissionless mode: no Authorization header when the kit key is absent.
12767
+ // Permissionless mode: no Authorization header when the credential is absent.
12352
12768
  ...validatedParams.apiKey !== undefined && {
12353
12769
  Authorization: `Bearer ${validatedParams.apiKey}`
12354
12770
  }
@@ -12413,14 +12829,14 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
12413
12829
  toChain: result.data.toChain
12414
12830
  }
12415
12831
  };
12416
- // Never let a server-only kit key leave a browser (no-op in Node.js).
12832
+ // Never let a server-only credential leave a browser (no-op in Node.js).
12417
12833
  assertBrowserSafeApiKey(validatedParams.apiKey);
12418
12834
  const url = buildSwapStatusUrl(validatedParams);
12419
12835
  const effectiveConfig = {
12420
12836
  ...DEFAULT_CONFIG,
12421
12837
  headers: {
12422
12838
  ...DEFAULT_CONFIG.headers,
12423
- // Permissionless mode: no Authorization header when the kit key is absent.
12839
+ // Permissionless mode: no Authorization header when the credential is absent.
12424
12840
  ...validatedParams.apiKey !== undefined && {
12425
12841
  Authorization: `Bearer ${validatedParams.apiKey}`
12426
12842
  }
@@ -12446,7 +12862,7 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
12446
12862
  * const url = buildTokenRatesUrl({
12447
12863
  * chain: 'Ethereum',
12448
12864
  * addresses: ['0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'],
12449
- * apiKey: 'KIT_KEY:key:secret',
12865
+ * apiKey: 'TEST_API_KEY:key:secret',
12450
12866
  * })
12451
12867
  * // => 'https://api.circle.com/v1/stablecoinKits/rates?chain=Ethereum&addresses=...'
12452
12868
  * ```
@@ -12519,14 +12935,14 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
12519
12935
  addresses: result.data.addresses
12520
12936
  }
12521
12937
  };
12522
- // Never let a server-only kit key leave a browser (no-op in Node.js).
12938
+ // Never let a server-only credential leave a browser (no-op in Node.js).
12523
12939
  assertBrowserSafeApiKey(validatedParams.apiKey);
12524
12940
  const url = buildTokenRatesUrl(validatedParams);
12525
12941
  const effectiveConfig = {
12526
12942
  ...DEFAULT_CONFIG,
12527
12943
  headers: {
12528
12944
  ...DEFAULT_CONFIG.headers,
12529
- // Permissionless mode: no Authorization header when the kit key is absent.
12945
+ // Permissionless mode: no Authorization header when the credential is absent.
12530
12946
  ...validatedParams.apiKey !== undefined && {
12531
12947
  Authorization: `Bearer ${validatedParams.apiKey}`
12532
12948
  }
@@ -12964,7 +13380,7 @@ const abiParameterSchema = zod.z.object({
12964
13380
  */ zod.z.object({
12965
13381
  type: zod.z.literal('evm'),
12966
13382
  abi: abiSchema,
12967
- address: evmAddressSchema,
13383
+ address: evmAddressSchema$1,
12968
13384
  functionName: zod.z.string({
12969
13385
  required_error: 'Function name is required',
12970
13386
  invalid_type_error: 'Function name must be a string'
@@ -13001,7 +13417,7 @@ const abiParameterSchema = zod.z.object({
13001
13417
  * }
13002
13418
  * ```
13003
13419
  */ zod.z.object({
13004
- address: evmAddressSchema,
13420
+ address: evmAddressSchema$1,
13005
13421
  value: zod.z.bigint({
13006
13422
  required_error: 'Value is required for native transfers',
13007
13423
  invalid_type_error: 'Value must be a bigint'
@@ -13533,7 +13949,7 @@ zod.z.object({
13533
13949
  signature: evmSignatureSchema,
13534
13950
  tokenInputs: zod.z.array(zod.z.object({
13535
13951
  permitType: zod.z.nativeEnum(PermitType),
13536
- token: evmAddressSchema,
13952
+ token: evmAddressSchema$1,
13537
13953
  amount: zod.z.bigint().refine((value)=>value >= 0n, {
13538
13954
  message: 'amount must be a non-negative bigint'
13539
13955
  }),
@@ -13794,7 +14210,7 @@ enc.encode('used_transfer_spec_hash');
13794
14210
  });
13795
14211
 
13796
14212
  /**
13797
- * Assert that the kit key is valid for swap operations.
14213
+ * Assert that the credential is valid for swap operations.
13798
14214
  *
13799
14215
  * @remarks
13800
14216
  * This validation is called when swap operations are executed, not at construction time.
@@ -13802,34 +14218,35 @@ enc.encode('used_transfer_spec_hash');
13802
14218
  * at usage time rather than construction time.
13803
14219
  *
13804
14220
  * Validates:
13805
- * - Kit key matches the required format (KIT_KEY:id:secret) when provided.
13806
- * An absent or empty kit key is permitted (permissionless mode) — the swap
13807
- * service now treats the key as optional.
14221
+ * - The credential matches an accepted format when provided — a Circle API key
14222
+ * (`<ENV>_API_KEY:id:secret`) or a legacy kit key (`KIT_KEY:id:secret`).
14223
+ * An absent or empty credential is permitted (permissionless mode) — the swap
14224
+ * service treats the credential as optional.
13808
14225
  *
13809
- * @param kitKey - The inline kit key from the swap operation config (optional)
13810
- * @throws KitError with VALIDATION_FAILED if a kit key is provided but does not
13811
- * match the KIT_KEY:<keyId>:<keySecret> format
14226
+ * @param apiKey - The inline credential from the swap operation config (optional)
14227
+ * @throws KitError with VALIDATION_FAILED if a credential is provided but does
14228
+ * not match an accepted format
13812
14229
  *
13813
14230
  * @example
13814
14231
  * ```typescript
13815
- * import { assertKitKey } from './assertKitKey'
14232
+ * import { assertApiKey } from './assertApiKey'
13816
14233
  *
13817
- * const kitKey = 'KIT_KEY:9d1bd085-bad2-4a2b-ae67-5814b85167c9:secretvalue'
14234
+ * const apiKey = 'TEST_API_KEY:9d1bd085-bad2-4a2b-ae67-5814b85167c9:secretvalue'
13818
14235
  *
13819
- * // Validate kit key before use
13820
- * assertKitKey(kitKey)
14236
+ * // Validate the credential before use
14237
+ * assertApiKey(apiKey)
13821
14238
  * ```
13822
- */ function assertKitKey(kitKey) {
13823
- // Permissionless mode: the swap service treats the kit key as optional, so an
13824
- // absent (or empty) key is valid. Only validate the format when a key is
14239
+ */ function assertApiKey(apiKey) {
14240
+ // Permissionless mode: the swap service treats the credential as optional, so
14241
+ // an absent (or empty) value is valid. Only validate the format when one is
13825
14242
  // actually provided.
13826
- if (!kitKey) {
14243
+ if (!apiKey) {
13827
14244
  return;
13828
14245
  }
13829
- const apiKeyResult = apiKeySchema.safeParse(kitKey);
14246
+ const apiKeyResult = apiKeySchema.safeParse(apiKey);
13830
14247
  if (!apiKeyResult.success) {
13831
14248
  const errors = apiKeyResult.error.issues.map((issue)=>issue.message).join(', ');
13832
- 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`);
14249
+ 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`);
13833
14250
  }
13834
14251
  }
13835
14252
 
@@ -14021,7 +14438,7 @@ const TOKEN_REGISTRY$3 = createTokenRegistry();
14021
14438
  }
14022
14439
  // Validate recipient address format matches the chain type
14023
14440
  if (chain.type === 'evm') {
14024
- const result = evmAddressSchema.safeParse(recipientAddress);
14441
+ const result = evmAddressSchema$1.safeParse(recipientAddress);
14025
14442
  if (!result.success) {
14026
14443
  throw createInvalidAddressError(recipientAddress, chain.name, '0x-prefixed 42-character hex string (0x + 40 hex characters)');
14027
14444
  }
@@ -14083,7 +14500,7 @@ function resolveFeePayoutChain(tokenIn, tokenOut, sourceChain, destinationChain)
14083
14500
  * to: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
14084
14501
  * config: {
14085
14502
  * slippageBps: 300,
14086
- * kitKey: 'KIT_KEY:...:...' // Required inline kit key
14503
+ * apiKey: 'TEST_API_KEY:...:...' // Inline credential (optional)
14087
14504
  * }
14088
14505
  * }
14089
14506
  *
@@ -14121,18 +14538,17 @@ function resolveFeePayoutChain(tokenIn, tokenOut, sourceChain, destinationChain)
14121
14538
  validateResolvedAddress(resolvedTokenInAddress, chain);
14122
14539
  validateResolvedAddress(resolvedTokenOutAddress, destinationChain);
14123
14540
  validateResolvedAddress(to, destinationChain);
14124
- const kitKey = config?.kitKey;
14125
- // Validate the kit key format when one is provided (permissionless otherwise).
14126
- assertKitKey(kitKey);
14541
+ const apiKey = resolveApiKey(config ?? {});
14542
+ // Validate the credential format when one is provided (permissionless
14543
+ // otherwise).
14544
+ assertApiKey(apiKey);
14127
14545
  // Validate custom fee configuration if present
14128
14546
  const customFee = config?.customFee;
14129
14547
  if (customFee !== undefined) {
14130
14548
  const feePayoutChain = resolveFeePayoutChain(tokenIn, tokenOut, chain, destinationChain);
14131
14549
  validateCustomFeeConfig(customFee, feePayoutChain);
14132
14550
  }
14133
- // Build CreateSwapParams for service client
14134
- // Use object spread to conditionally include optional properties
14135
- // Note: Service client expects 'apiKey' field, so we map kitKey → apiKey
14551
+ // Build CreateSwapParams for service client, spreading optional properties.
14136
14552
  const chainName = chain.chain // The API expects the Blockchain enum value format like "World_Chain"
14137
14553
  ;
14138
14554
  const destinationChainName = destinationChain.chain;
@@ -14167,9 +14583,9 @@ function resolveFeePayoutChain(tokenIn, tokenOut, sourceChain, destinationChain)
14167
14583
  }
14168
14584
  }
14169
14585
  },
14170
- // Map kitKey → apiKey for the service client; omitted in permissionless mode.
14171
- ...kitKey ? {
14172
- apiKey: kitKey
14586
+ // Omitted in permissionless mode.
14587
+ ...apiKey ? {
14588
+ apiKey
14173
14589
  } : {}
14174
14590
  };
14175
14591
  }
@@ -16073,9 +16489,9 @@ async function fetchSameChainStatusSnapshot({ isCrossChainSwap, txHash, chain, a
16073
16489
  * ```typescript
16074
16490
  * import { StablecoinServiceSwapProvider } from '@circle-fin/provider-stablecoin-service-swap'
16075
16491
  *
16076
- * // Create provider with developer fee (1 USDC)
16492
+ * // Create provider with developer fee (1 USDC).
16493
+ * // Credentials are supplied per operation via `config.apiKey`, not here.
16077
16494
  * const provider = new StablecoinServiceSwapProvider({
16078
- * kitKey: process.env.STABLECOIN_KIT_API_KEY,
16079
16495
  * customFee: {
16080
16496
  * amount: '1000000', // 1 USDC in base units (6 decimals)
16081
16497
  * recipientAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0'
@@ -16737,9 +17153,7 @@ async function fetchSameChainStatusSnapshot({ isCrossChainSwap, txHash, chain, a
16737
17153
  * import { createAdapterFromPrivateKey } from '@circle-fin/adapter-viem-v2'
16738
17154
  * import { Ethereum } from '@core/chains'
16739
17155
  *
16740
- * const provider = new StablecoinServiceSwapProvider({
16741
- * kitKey: process.env.STABLECOIN_KIT_API_KEY
16742
- * })
17156
+ * const provider = new StablecoinServiceSwapProvider()
16743
17157
  *
16744
17158
  * const adapter = createAdapterFromPrivateKey({
16745
17159
  * privateKey: process.env.PRIVATE_KEY
@@ -17233,7 +17647,7 @@ const optionalSwapChainIdentifierField = swapChainIdentifierField.optional();
17233
17647
  /**
17234
17648
  * Fee recipient address (required).
17235
17649
  * Must be a valid EVM address or Solana address.
17236
- */ recipientAddress: zod.z.string().refine((value)=>evmAddressSchema.safeParse(value).success || solanaAddressSchema.safeParse(value).success, {
17650
+ */ recipientAddress: zod.z.string().refine((value)=>evmAddressSchema$1.safeParse(value).success || solanaAddressSchema.safeParse(value).success, {
17237
17651
  message: 'recipientAddress must be a valid blockchain address: EVM (0x + 40 hex chars) or Solana (base58, 32-44 chars)'
17238
17652
  })
17239
17653
  }).strict();
@@ -17245,7 +17659,8 @@ const optionalSwapChainIdentifierField = swapChainIdentifierField.optional();
17245
17659
  * - slippageBps: Optional positive number for slippage tolerance
17246
17660
  * - stopLimit: Optional decimal string for minimum output
17247
17661
  * - customFee: Optional fee configuration
17248
- * - kitKey: Optional string identifier
17662
+ * - apiKey: Optional credential string
17663
+ * - kitKey: Optional credential string (deprecated alias for apiKey)
17249
17664
  */ const swapConfigSchema = zod.z.object({
17250
17665
  allowanceStrategy: allowanceStrategySchema.optional(),
17251
17666
  slippageBps: zod.z.number().int().min(0).optional(),
@@ -17255,11 +17670,12 @@ const optionalSwapChainIdentifierField = swapChainIdentifierField.optional();
17255
17670
  attributeName: 'stopLimit'
17256
17671
  })(zod.z.string())).optional(),
17257
17672
  customFee: swapCustomFeeSchema.optional(),
17673
+ apiKey: zod.z.string().optional(),
17258
17674
  kitKey: zod.z.string().optional()
17259
17675
  });
17260
17676
  const swapDestinationSchema = zod.z.object({
17261
17677
  chain: optionalSwapChainIdentifierField,
17262
- recipientAddress: zod.z.string().refine((value)=>evmAddressSchema.safeParse(value).success || solanaAddressSchema.safeParse(value).success, {
17678
+ recipientAddress: zod.z.string().refine((value)=>evmAddressSchema$1.safeParse(value).success || solanaAddressSchema.safeParse(value).success, {
17263
17679
  message: 'recipientAddress must be a valid blockchain address: EVM (0x + 40 hex chars) or Solana (base58, 32-44 chars)'
17264
17680
  }).optional()
17265
17681
  }).strict();
@@ -19366,7 +19782,8 @@ const transformAmount = (value, direction, decimals)=>formatUnits(value, decimal
19366
19782
  /**
19367
19783
  * Helper to format the config section of a swap result, transforming fee amounts.
19368
19784
  *
19369
- * Strips sensitive fields like kitKey from the config before returning.
19785
+ * Strips the credential fields (`apiKey` and the deprecated `kitKey`) from the
19786
+ * config before returning, so a result is safe to log or serialize.
19370
19787
  *
19371
19788
  * @param config - The swap config from the provider.
19372
19789
  * @param outputTokenTransform - The amount transformer for output-token-denominated values (fees and amountOut).
@@ -19375,11 +19792,11 @@ const transformAmount = (value, direction, decimals)=>formatUnits(value, decimal
19375
19792
  if (!config) {
19376
19793
  return undefined;
19377
19794
  }
19378
- // Remove kitKey from the config
19379
- const cloneConfig = {
19380
- ...config
19381
- };
19382
- delete cloneConfig.kitKey;
19795
+ // Rebuild the config without any credential field. Filtering entries rather
19796
+ // than deleting them avoids reading the deprecated `kitKey` property
19797
+ // directly, and keeps the credential list in one place.
19798
+ const credentialFields = CREDENTIAL_CONFIG_FIELDS;
19799
+ const cloneConfig = Object.fromEntries(Object.entries(config).filter(([key])=>!credentialFields.includes(key)));
19383
19800
  if (Object.keys(cloneConfig).length === 0) {
19384
19801
  return undefined;
19385
19802
  }
@@ -19580,9 +19997,9 @@ const transformAmount = (value, direction, decimals)=>formatUnits(value, decimal
19580
19997
  try {
19581
19998
  // Step 1: Build quote params directly (no need for buildServiceParams)
19582
19999
  // Use chain.chain (Blockchain enum value like "World_Chain") not chain.name
19583
- // The kit key is optional (permissionless mode); when absent the quote is
19584
- // fetched without an Authorization header.
19585
- const kitKey = params.config?.kitKey;
20000
+ // The credential is optional (permissionless mode); when absent the quote
20001
+ // is fetched without an Authorization header.
20002
+ const apiKey = resolveApiKey(params.config ?? {});
19586
20003
  // Resolve token aliases to addresses for the quote API
19587
20004
  // The quote endpoint requires resolved addresses, not aliases like 'USDC'
19588
20005
  const chain = params.from.chain;
@@ -19607,8 +20024,8 @@ const transformAmount = (value, direction, decimals)=>formatUnits(value, decimal
19607
20024
  ...params.config?.slippageBps !== undefined && {
19608
20025
  slippageBps: params.config.slippageBps
19609
20026
  },
19610
- ...kitKey ? {
19611
- apiKey: kitKey
20027
+ ...apiKey ? {
20028
+ apiKey
19612
20029
  } : {}
19613
20030
  };
19614
20031
  // Step 2: Get quote from service
@@ -20012,7 +20429,7 @@ const sleep$1 = async (ms)=>new Promise((resolve)=>setTimeout(resolve, ms));
20012
20429
  * the service returns `receivingTokenDecimals`. When decimals are missing
20013
20430
  * the field is omitted entirely (never raw base units).
20014
20431
  *
20015
- * @param params - `txHash`, `chainIn`, optional `chainOut`, and `kitKey`.
20432
+ * @param params - `txHash`, `chainIn`, optional `chainOut`, and `apiKey`.
20016
20433
  * @returns A single snapshot of the swap's status.
20017
20434
  * @throws \{KitError\} If `chainIn` or `chainOut` is malformed.
20018
20435
  *
@@ -20028,7 +20445,7 @@ const sleep$1 = async (ms)=>new Promise((resolve)=>setTimeout(resolve, ms));
20028
20445
  * txHash: result.txHash,
20029
20446
  * chainIn: result.chainIn,
20030
20447
  * chainOut: result.chainOut,
20031
- * kitKey: process.env.KIT_KEY ?? '',
20448
+ * apiKey: process.env.CIRCLE_API_KEY,
20032
20449
  * })
20033
20450
  * while (status.progress.status === 'PENDING') {
20034
20451
  * await new Promise((r) => setTimeout(r, 3_000))
@@ -20036,7 +20453,7 @@ const sleep$1 = async (ms)=>new Promise((resolve)=>setTimeout(resolve, ms));
20036
20453
  * txHash: result.txHash,
20037
20454
  * chainIn: result.chainIn,
20038
20455
  * chainOut: result.chainOut,
20039
- * kitKey: process.env.KIT_KEY ?? '',
20456
+ * apiKey: process.env.CIRCLE_API_KEY,
20040
20457
  * })
20041
20458
  * }
20042
20459
  *
@@ -20054,14 +20471,15 @@ const sleep$1 = async (ms)=>new Promise((resolve)=>setTimeout(resolve, ms));
20054
20471
  const chainIn = normalizeChain(params.chainIn, 'chainIn');
20055
20472
  const chainOut = params.chainOut === undefined ? undefined : normalizeChain(params.chainOut, 'chainOut');
20056
20473
  const isCrossChain = chainOut !== undefined && chainOut !== chainIn;
20474
+ const apiKey = resolveApiKey(params);
20057
20475
  const request = {
20058
20476
  txHash: params.txHash,
20059
20477
  chain: chainIn,
20060
20478
  ...isCrossChain && {
20061
20479
  toChain: chainOut
20062
20480
  },
20063
- ...params.kitKey ? {
20064
- apiKey: params.kitKey
20481
+ ...apiKey ? {
20482
+ apiKey
20065
20483
  } : {}
20066
20484
  };
20067
20485
  let raw = await getSwapStatus$1(request);
@@ -20140,9 +20558,9 @@ const isResultShape = (params)=>'result' in params;
20140
20558
  *
20141
20559
  * Two parameter shapes are accepted:
20142
20560
  *
20143
- * - Pass the {@link SwapResult} directly: `{ result, kitKey, ... }`.
20561
+ * - Pass the {@link SwapResult} directly: `{ result, apiKey, ... }`.
20144
20562
  * Cleanest when chaining off `kit.swap()`.
20145
- * - Pass discrete fields: `{ txHash, chainIn, chainOut?, kitKey, ... }`.
20563
+ * - Pass discrete fields: `{ txHash, chainIn, chainOut?, apiKey, ... }`.
20146
20564
  * Useful for resuming an in-flight swap from a persisted record.
20147
20565
  *
20148
20566
  * @param params - Wait configuration. See {@link WaitForSwapParams}.
@@ -20162,7 +20580,7 @@ const isResultShape = (params)=>'result' in params;
20162
20580
  *
20163
20581
  * const final = await waitForSwap({
20164
20582
  * result,
20165
- * kitKey: process.env.KIT_KEY ?? '',
20583
+ * apiKey: process.env.CIRCLE_API_KEY,
20166
20584
  * onProgress: (snapshot) => {
20167
20585
  * console.log(snapshot.progress.substatus ?? snapshot.progress.status)
20168
20586
  * },
@@ -20180,7 +20598,7 @@ const isResultShape = (params)=>'result' in params;
20180
20598
  * txHash: '0x…',
20181
20599
  * chainIn: 'Ethereum',
20182
20600
  * chainOut: 'Base',
20183
- * kitKey: process.env.KIT_KEY ?? '',
20601
+ * apiKey: process.env.CIRCLE_API_KEY,
20184
20602
  * })
20185
20603
  * ```
20186
20604
  */ async function waitForSwap(params) {
@@ -20196,14 +20614,15 @@ const isResultShape = (params)=>'result' in params;
20196
20614
  const chainOut = isResultShape(params) ? params.result.chainOut : params.chainOut;
20197
20615
  // Delegate parameter validation (txHash, chainIn, chainOut) to
20198
20616
  // getSwapStatus so the same rules apply to both helpers.
20617
+ const apiKey = resolveApiKey(params);
20199
20618
  const statusParams = {
20200
20619
  txHash,
20201
20620
  chainIn,
20202
20621
  ...chainOut !== undefined && {
20203
20622
  chainOut
20204
20623
  },
20205
- ...params.kitKey ? {
20206
- kitKey: params.kitKey
20624
+ ...apiKey ? {
20625
+ apiKey
20207
20626
  } : {}
20208
20627
  };
20209
20628
  const deadline = Date.now() + timeoutMs;
@@ -20327,7 +20746,7 @@ function resolveTokenEntry(entry, index, chain, chainDef, context) {
20327
20746
  *
20328
20747
  * @param context - SwapKit context (provides the `TokenRegistry` used for
20329
20748
  * symbol resolution).
20330
- * @param params - `chain`, optional `tokens`, and `kitKey`.
20749
+ * @param params - `chain`, optional `tokens`, and `apiKey`.
20331
20750
  * @returns A nested map of `[chain][address] → { priceUSD, fetchedAt }`.
20332
20751
  * @throws \{KitError\} If `chain` cannot be resolved, `tokens` exceeds 100
20333
20752
  * entries, or any entry is neither a registered symbol nor a
@@ -20342,7 +20761,7 @@ function resolveTokenEntry(entry, index, chain, chainDef, context) {
20342
20761
  * const { rates } = await getTokenRates(context, {
20343
20762
  * chain: Blockchain.Ethereum,
20344
20763
  * tokens: ['USDC', 'EURC', 'NATIVE'],
20345
- * kitKey: process.env.KIT_KEY ?? '',
20764
+ * apiKey: process.env.CIRCLE_API_KEY,
20346
20765
  * })
20347
20766
  *
20348
20767
  * const usdc = rates['Ethereum']?.['0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48']
@@ -20363,10 +20782,11 @@ function resolveTokenEntry(entry, index, chain, chainDef, context) {
20363
20782
  // valid Blockchain enum string, so `getChainByEnum` is guaranteed to resolve.
20364
20783
  const chainDef = getChainByEnum(chain);
20365
20784
  const resolvedAddresses = params.tokens?.map((entry, index)=>resolveTokenEntry(entry, index, chain, chainDef, context));
20785
+ const apiKey = resolveApiKey(params);
20366
20786
  return getTokenRates$1({
20367
20787
  chain,
20368
- ...params.kitKey ? {
20369
- apiKey: params.kitKey
20788
+ ...apiKey ? {
20789
+ apiKey
20370
20790
  } : {},
20371
20791
  ...resolvedAddresses !== undefined && {
20372
20792
  addresses: resolvedAddresses
@@ -20997,7 +21417,7 @@ function resolveTokenEntry(entry, index, chain, chainDef, context) {
20997
21417
  * is formatted as a human-readable decimal string; when decimals are
20998
21418
  * missing the field is omitted entirely (never raw base units).
20999
21419
  *
21000
- * @param params - `txHash`, `chainIn`, optional `chainOut`, and `kitKey`.
21420
+ * @param params - `txHash`, `chainIn`, optional `chainOut`, and `apiKey`.
21001
21421
  * @returns A snapshot of the swap's status at the time of the call.
21002
21422
  * @throws \{KitError\} If `chainIn` or `chainOut` is malformed.
21003
21423
  *
@@ -21010,7 +21430,7 @@ function resolveTokenEntry(entry, index, chain, chainDef, context) {
21010
21430
  * txHash: result.txHash,
21011
21431
  * chainIn: result.chainIn,
21012
21432
  * chainOut: result.chainOut,
21013
- * kitKey: process.env.KIT_KEY ?? '',
21433
+ * apiKey: process.env.CIRCLE_API_KEY,
21014
21434
  * })
21015
21435
  * console.log(status.progress.status, status.progress.substatus)
21016
21436
  * ```
@@ -21022,7 +21442,7 @@ function resolveTokenEntry(entry, index, chain, chainDef, context) {
21022
21442
  * txHash: result.txHash,
21023
21443
  * chainIn: result.chainIn,
21024
21444
  * chainOut: result.chainOut,
21025
- * kitKey: process.env.KIT_KEY ?? '',
21445
+ * apiKey: process.env.CIRCLE_API_KEY,
21026
21446
  * })
21027
21447
  * while (status.progress.status === 'PENDING') {
21028
21448
  * await new Promise((r) => setTimeout(r, 3_000))
@@ -21030,7 +21450,7 @@ function resolveTokenEntry(entry, index, chain, chainDef, context) {
21030
21450
  * txHash: result.txHash,
21031
21451
  * chainIn: result.chainIn,
21032
21452
  * chainOut: result.chainOut,
21033
- * kitKey: process.env.KIT_KEY ?? '',
21453
+ * apiKey: process.env.CIRCLE_API_KEY,
21034
21454
  * })
21035
21455
  * }
21036
21456
  *
@@ -21061,7 +21481,7 @@ function resolveTokenEntry(entry, index, chain, chainDef, context) {
21061
21481
  * 5xx, etc.) surface unchanged so the caller can decide whether to
21062
21482
  * retry the whole wait. The wait itself only emits a timeout error.
21063
21483
  *
21064
- * @param params - Wait configuration including identifiers, kit key,
21484
+ * @param params - Wait configuration including identifiers, API key,
21065
21485
  * optional `timeoutMs`, and an optional `onProgress`
21066
21486
  * callback fired on every successful poll.
21067
21487
  * @returns The first terminal {@link SwapStatusResult} observed.
@@ -21080,7 +21500,7 @@ function resolveTokenEntry(entry, index, chain, chainDef, context) {
21080
21500
  *
21081
21501
  * const final = await kit.waitForSwap({
21082
21502
  * result,
21083
- * kitKey: process.env.KIT_KEY ?? '',
21503
+ * apiKey: process.env.CIRCLE_API_KEY,
21084
21504
  * onProgress: (snap) => console.log(snap.progress.substatus ?? snap.progress.status),
21085
21505
  * })
21086
21506
  *
@@ -21098,7 +21518,7 @@ function resolveTokenEntry(entry, index, chain, chainDef, context) {
21098
21518
  * txHash: persisted.txHash,
21099
21519
  * chainIn: persisted.chainIn,
21100
21520
  * chainOut: persisted.chainOut,
21101
- * kitKey: process.env.KIT_KEY ?? '',
21521
+ * apiKey: process.env.CIRCLE_API_KEY,
21102
21522
  * })
21103
21523
  * ```
21104
21524
  */ async waitForSwap(params) {
@@ -21132,7 +21552,7 @@ function resolveTokenEntry(entry, index, chain, chainDef, context) {
21132
21552
  * not cache a rate for the native asset on that chain, the response simply
21133
21553
  * omits the address.
21134
21554
  *
21135
- * @param params - `chain`, optional `tokens`, and `kitKey`.
21555
+ * @param params - `chain`, optional `tokens`, and `apiKey`.
21136
21556
  * @returns A nested map of `[chain][address] → { priceUSD, fetchedAt }`.
21137
21557
  * @throws \{KitError\} If `chain` is malformed, `tokens` exceeds 100
21138
21558
  * entries, or any entry is neither a registered symbol nor a
@@ -21144,7 +21564,7 @@ function resolveTokenEntry(entry, index, chain, chainDef, context) {
21144
21564
  * const { rates } = await kit.getTokenRates({
21145
21565
  * chain: 'Ethereum',
21146
21566
  * tokens: ['USDC', 'EURC', 'NATIVE'],
21147
- * kitKey: process.env.KIT_KEY ?? '',
21567
+ * apiKey: process.env.CIRCLE_API_KEY,
21148
21568
  * })
21149
21569
  *
21150
21570
  * const usdc = rates['Ethereum']?.['0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48']
@@ -21158,7 +21578,7 @@ function resolveTokenEntry(entry, index, chain, chainDef, context) {
21158
21578
  * chain: 'Ethereum',
21159
21579
  * // 'USDC' (registry symbol) + raw USDT address
21160
21580
  * tokens: ['USDC', '0xdAC17F958D2ee523a2206206994597C13D831ec7'],
21161
- * kitKey: process.env.KIT_KEY ?? '',
21581
+ * apiKey: process.env.CIRCLE_API_KEY,
21162
21582
  * })
21163
21583
  * ```
21164
21584
  *
@@ -21167,7 +21587,7 @@ function resolveTokenEntry(entry, index, chain, chainDef, context) {
21167
21587
  * ```typescript
21168
21588
  * const { rates } = await kit.getTokenRates({
21169
21589
  * chain: 'Base',
21170
- * kitKey: process.env.KIT_KEY ?? '',
21590
+ * apiKey: process.env.CIRCLE_API_KEY,
21171
21591
  * })
21172
21592
  * ```
21173
21593
  */ async getTokenRates(params) {
@@ -21422,7 +21842,7 @@ registerKit(`${pkg$1.name}/${pkg$1.version}`);
21422
21842
  };
21423
21843
 
21424
21844
  var name = "@circle-fin/earn-kit";
21425
- var version = "1.5.1";
21845
+ var version = "1.6.0";
21426
21846
  var pkg = {
21427
21847
  name: name,
21428
21848
  version: version};
@@ -21494,7 +21914,7 @@ function isNonNegativeBigIntLike(value) {
21494
21914
  }
21495
21915
  }
21496
21916
  const hexSignatureSchema = evmSignatureSchema;
21497
- const hexAddressSchema = evmAddressSchema;
21917
+ const hexAddressSchema = evmAddressSchema$1;
21498
21918
  // '0x' prefix + 32 bytes * 2 hex chars.
21499
21919
  const BYTES32_HEX_LENGTH = 66;
21500
21920
  const bridgeFeeTokenSchema = hexAddressSchema;
@@ -22399,7 +22819,7 @@ createTokenRegistry();
22399
22819
  * fast instead of round-tripping to the service.
22400
22820
  *
22401
22821
  * @internal
22402
- */ 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');
22822
+ */ 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');
22403
22823
  /**
22404
22824
  * Schema for the adapter context within earn operations.
22405
22825
  *
@@ -22431,19 +22851,39 @@ const sourceAdapterContextSchema = zod.z.object({
22431
22851
  /**
22432
22852
  * Schema for the EarnConfig options.
22433
22853
  *
22434
- * Validate the optional Kit Key field using the standard `apiKeySchema`
22435
- * format (`KIT_KEY:<keyId>:<keySecret>`). When omitted, the SDK
22436
- * operates in permissionless mode. `baseUrl` overrides the Earn Service
22437
- * endpoint (e.g. staging); `batchTransactions: false` opts out of atomic
22438
- * batched execution. Both are forwarded to the provider, so this `.strict()`
22439
- * schema must accept them or a valid config object is rejected.
22854
+ * Validate the *resolved* credential using the standard `apiKeySchema` format
22855
+ * (`<ENV>_API_KEY:<keyId>:<keySecret>`, or a legacy
22856
+ * `KIT_KEY:<keyId>:<keySecret>`). `apiKey` takes precedence over the deprecated
22857
+ * `kitKey`, so a malformed `kitKey` that is being ignored must not fail a config
22858
+ * that supplies a valid `apiKey` (and vice versa) only the credential that
22859
+ * would actually be sent is format-checked. When neither is supplied the SDK
22860
+ * operates in permissionless mode. `baseUrl` overrides the Earn Service endpoint
22861
+ * (e.g. staging); `batchTransactions: false` opts out of atomic batched
22862
+ * execution. All are forwarded to the provider, so this `.strict()` schema must
22863
+ * accept them or a valid config object is rejected.
22440
22864
  *
22441
22865
  * @internal
22442
22866
  */ const earnConfigSchema = zod.z.object({
22443
- kitKey: apiKeySchema.optional(),
22867
+ apiKey: zod.z.string().optional(),
22868
+ kitKey: zod.z.string().optional(),
22444
22869
  baseUrl: zod.z.string().optional(),
22445
22870
  batchTransactions: zod.z.boolean().optional()
22446
- }).strict();
22871
+ }).strict().superRefine((config, ctx)=>{
22872
+ const credential = resolveApiKey(config);
22873
+ if (credential === undefined) {
22874
+ return;
22875
+ }
22876
+ const result = apiKeySchema.safeParse(credential);
22877
+ if (!result.success) {
22878
+ ctx.addIssue({
22879
+ code: zod.z.ZodIssueCode.custom,
22880
+ path: [
22881
+ credential === config.apiKey ? 'apiKey' : 'kitKey'
22882
+ ],
22883
+ message: result.error.issues[0]?.message ?? 'Invalid API key format'
22884
+ });
22885
+ }
22886
+ });
22447
22887
  /**
22448
22888
  * Canonical decimal form: a leading digit with no leading zeros (a single
22449
22889
  * '0' is only allowed immediately before the decimal point). Rejects the
@@ -22515,7 +22955,7 @@ const sourceAdapterContextSchema = zod.z.object({
22515
22955
  * currently supports EVM vault addresses on Arc Testnet.
22516
22956
  *
22517
22957
  * @internal
22518
- */ const vaultAddressSchema = evmAddressSchema.refine(isValidEip55Checksum, 'address has an invalid EIP-55 checksum');
22958
+ */ const vaultAddressSchema = evmAddressSchema$1.refine(isValidEip55Checksum, 'address has an invalid EIP-55 checksum');
22519
22959
  /**
22520
22960
  * Validation schema for VaultQuery.
22521
22961
  *
@@ -22790,7 +23230,7 @@ const sameChainGetDepositQuoteParamsSchema = zod.z.object({
22790
23230
  const crossChainGetDepositQuoteParamsSchema = zod.z.object({
22791
23231
  from: sourceAdapterContextSchema,
22792
23232
  chain: earnBridgeDestinationChainIdentifierSchema,
22793
- address: evmAddressSchema,
23233
+ address: evmAddressSchema$1,
22794
23234
  vaultAddress: vaultAddressSchema,
22795
23235
  amount: amountSchema,
22796
23236
  transferSpeed: zod.z.enum([