@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/earn.mjs CHANGED
@@ -28,7 +28,7 @@ if (typeof window !== 'undefined' && typeof window.Buffer === 'undefined') {
28
28
 
29
29
 
30
30
  import { z } from 'zod';
31
- import 'pino';
31
+ import pino from 'pino';
32
32
  import '@ethersproject/bytes';
33
33
  import '@ethersproject/abi';
34
34
  import '@ethersproject/address';
@@ -2347,6 +2347,8 @@ function getOptionalString(value) {
2347
2347
  Blockchain["Optimism_Sepolia"] = "Optimism_Sepolia";
2348
2348
  Blockchain["Pharos"] = "Pharos";
2349
2349
  Blockchain["Pharos_Testnet"] = "Pharos_Testnet";
2350
+ Blockchain["Plasma"] = "Plasma";
2351
+ Blockchain["Plasma_Testnet"] = "Plasma_Testnet";
2350
2352
  Blockchain["Polkadot_Asset_Hub"] = "Polkadot_Asset_Hub";
2351
2353
  Blockchain["Polkadot_Westmint"] = "Polkadot_Westmint";
2352
2354
  Blockchain["Plume"] = "Plume";
@@ -2416,6 +2418,7 @@ var BridgeChain;
2416
2418
  BridgeChain["Morph"] = "Morph";
2417
2419
  BridgeChain["Optimism"] = "Optimism";
2418
2420
  BridgeChain["Pharos"] = "Pharos";
2421
+ BridgeChain["Plasma"] = "Plasma";
2419
2422
  BridgeChain["Plume"] = "Plume";
2420
2423
  BridgeChain["Polygon"] = "Polygon";
2421
2424
  BridgeChain["Sei"] = "Sei";
@@ -2442,6 +2445,7 @@ var BridgeChain;
2442
2445
  BridgeChain["Morph_Testnet"] = "Morph_Testnet";
2443
2446
  BridgeChain["Optimism_Sepolia"] = "Optimism_Sepolia";
2444
2447
  BridgeChain["Pharos_Testnet"] = "Pharos_Testnet";
2448
+ BridgeChain["Plasma_Testnet"] = "Plasma_Testnet";
2445
2449
  BridgeChain["Plume_Testnet"] = "Plume_Testnet";
2446
2450
  BridgeChain["Polygon_Amoy_Testnet"] = "Polygon_Amoy_Testnet";
2447
2451
  BridgeChain["Sei_Testnet"] = "Sei_Testnet";
@@ -2888,6 +2892,45 @@ var EarnChain;
2888
2892
  * This program handles minting operations for Gateway transactions
2889
2893
  * on Solana devnet.
2890
2894
  */ const GATEWAY_MINTER_SOLANA_DEVNET = 'GATEmKK2ECL1brEngQZWCgMWPbvrEYqsV6u29dAaHavr';
2895
+ /**
2896
+ * The `TokenMessengerWithFees` proxy contract address for EVM mainnet networks
2897
+ * (all chains except Edge).
2898
+ *
2899
+ * Deployed at a CREATE3-derived address; identical across all mainnet EVM
2900
+ * source chains. Present on any chain that supports the prepaid FORWARD path
2901
+ * via `depositForBurnWithHookAndFees`.
2902
+ */ const TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET = '0x71f54F818671cD0D7ea140Da213e5C8b5C92a408';
2903
+ /**
2904
+ * The `TokenMessengerWithFees` proxy contract address for EVM testnet networks.
2905
+ *
2906
+ * Identical across all testnet EVM source chains. Present on any testnet chain
2907
+ * that supports the prepaid FORWARD path via `depositForBurnWithHookAndFees`.
2908
+ */ const TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET = '0x8745D906D67C346E5eb1aEEED38Eb87F34DF0C0A';
2909
+ /**
2910
+ * The `DepositForHandler` proxy contract address for EVM mainnet networks.
2911
+ *
2912
+ * The handler the GenericExecutor calls on a fast-deposit destination chain to
2913
+ * run a cross-chain deposit into the GatewayWallet. Deployed at the same
2914
+ * address across all mainnet EVM destination chains.
2915
+ */ const DEPOSIT_FOR_HANDLER_EVM_MAINNET = '0x16529813203f77E036576666336554a1210dce4D';
2916
+ /**
2917
+ * The `DepositForHandler` proxy contract address for EVM testnet networks.
2918
+ *
2919
+ * Identical across all testnet EVM destination chains.
2920
+ */ const DEPOSIT_FOR_HANDLER_EVM_TESTNET = '0xD05E7D2E7d30b92c5F17d7d0fC575fce231F1A48';
2921
+ /**
2922
+ * The `GenericExecutor` proxy contract address for EVM mainnet networks.
2923
+ *
2924
+ * The GenericExecutor is the `mintRecipient` and `destinationCaller` on the
2925
+ * destination chain for the CCTP v2 prepaid FORWARD path. It receives the CCTP
2926
+ * mint and calls the `DepositForHandler` to complete the fast deposit.
2927
+ * Deployed at the same address across all mainnet EVM destination chains.
2928
+ */ const GENERIC_EXECUTOR_EVM_MAINNET = '0xFa7be2f04F3Ad4ca969260729c6d45B5625984A7';
2929
+ /**
2930
+ * The `GenericExecutor` proxy contract address for EVM testnet networks.
2931
+ *
2932
+ * Identical across all testnet EVM destination chains.
2933
+ */ const GENERIC_EXECUTOR_EVM_TESTNET = '0xEdC81040756AcCfF070c21D37b265b9D0b5Ba45e';
2891
2934
 
2892
2935
  /**
2893
2936
  * Arc Testnet chain definition
@@ -2925,6 +2968,7 @@ var EarnChain;
2925
2968
  v2: {
2926
2969
  type: 'split',
2927
2970
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
2971
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
2928
2972
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
2929
2973
  confirmations: 1,
2930
2974
  fastConfirmations: 1
@@ -2945,9 +2989,8 @@ var EarnChain;
2945
2989
  v1: {
2946
2990
  wallet: GATEWAY_WALLET_EVM_TESTNET,
2947
2991
  minter: GATEWAY_MINTER_EVM_TESTNET,
2948
- // DepositForHandler the GenericExecutor calls to run a fast cross-chain
2949
- // deposit into the GatewayWallet above.
2950
- depositForHandler: '0xD05E7D2E7d30b92c5F17d7d0fC575fce231F1A48'
2992
+ depositForHandler: DEPOSIT_FOR_HANDLER_EVM_TESTNET,
2993
+ genericExecutor: GENERIC_EXECUTOR_EVM_TESTNET
2951
2994
  }
2952
2995
  },
2953
2996
  forwarderSupported: {
@@ -2992,6 +3035,7 @@ var EarnChain;
2992
3035
  v2: {
2993
3036
  type: 'split',
2994
3037
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
3038
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
2995
3039
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
2996
3040
  confirmations: 65,
2997
3041
  fastConfirmations: 1
@@ -3056,6 +3100,7 @@ var EarnChain;
3056
3100
  v2: {
3057
3101
  type: 'split',
3058
3102
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
3103
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
3059
3104
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
3060
3105
  confirmations: 65,
3061
3106
  fastConfirmations: 1
@@ -3120,6 +3165,7 @@ var EarnChain;
3120
3165
  v2: {
3121
3166
  type: 'split',
3122
3167
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
3168
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
3123
3169
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
3124
3170
  confirmations: 1,
3125
3171
  fastConfirmations: 1
@@ -3139,7 +3185,9 @@ var EarnChain;
3139
3185
  contracts: {
3140
3186
  v1: {
3141
3187
  wallet: GATEWAY_WALLET_EVM_MAINNET,
3142
- minter: GATEWAY_MINTER_EVM_MAINNET
3188
+ minter: GATEWAY_MINTER_EVM_MAINNET,
3189
+ depositForHandler: DEPOSIT_FOR_HANDLER_EVM_MAINNET,
3190
+ genericExecutor: GENERIC_EXECUTOR_EVM_MAINNET
3143
3191
  }
3144
3192
  },
3145
3193
  forwarderSupported: {
@@ -3181,6 +3229,7 @@ var EarnChain;
3181
3229
  v2: {
3182
3230
  type: 'split',
3183
3231
  tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
3232
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
3184
3233
  messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
3185
3234
  confirmations: 1,
3186
3235
  fastConfirmations: 1
@@ -3202,7 +3251,9 @@ var EarnChain;
3202
3251
  contracts: {
3203
3252
  v1: {
3204
3253
  wallet: GATEWAY_WALLET_EVM_TESTNET,
3205
- minter: GATEWAY_MINTER_EVM_TESTNET
3254
+ minter: GATEWAY_MINTER_EVM_TESTNET,
3255
+ depositForHandler: DEPOSIT_FOR_HANDLER_EVM_TESTNET,
3256
+ genericExecutor: GENERIC_EXECUTOR_EVM_TESTNET
3206
3257
  }
3207
3258
  },
3208
3259
  forwarderSupported: {
@@ -3248,6 +3299,7 @@ var EarnChain;
3248
3299
  v2: {
3249
3300
  type: 'split',
3250
3301
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
3302
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
3251
3303
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
3252
3304
  confirmations: 65,
3253
3305
  fastConfirmations: 1
@@ -3312,6 +3364,7 @@ var EarnChain;
3312
3364
  v2: {
3313
3365
  type: 'split',
3314
3366
  tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
3367
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
3315
3368
  messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
3316
3369
  confirmations: 65,
3317
3370
  fastConfirmations: 1
@@ -3422,6 +3475,7 @@ var EarnChain;
3422
3475
  v2: {
3423
3476
  type: 'split',
3424
3477
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
3478
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
3425
3479
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
3426
3480
  confirmations: 65,
3427
3481
  fastConfirmations: 1
@@ -3466,6 +3520,7 @@ var EarnChain;
3466
3520
  v2: {
3467
3521
  type: 'split',
3468
3522
  tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
3523
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
3469
3524
  messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
3470
3525
  confirmations: 65,
3471
3526
  fastConfirmations: 1
@@ -3511,6 +3566,7 @@ var EarnChain;
3511
3566
  v2: {
3512
3567
  type: 'split',
3513
3568
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
3569
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
3514
3570
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
3515
3571
  confirmations: 1,
3516
3572
  fastConfirmations: 1
@@ -3556,6 +3612,7 @@ var EarnChain;
3556
3612
  v2: {
3557
3613
  type: 'split',
3558
3614
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
3615
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
3559
3616
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
3560
3617
  confirmations: 1,
3561
3618
  fastConfirmations: 1
@@ -3601,6 +3658,7 @@ var EarnChain;
3601
3658
  v2: {
3602
3659
  type: 'split',
3603
3660
  tokenMessenger: '0x98706A006bc632Df31CAdFCBD43F38887ce2ca5c',
3661
+ tokenMessengerWithFees: '0x3Ac96675F9a3E6922713e041645D82f3561d3686',
3604
3662
  messageTransmitter: '0x5b61381Fc9e58E70EfC13a4A97516997019198ee',
3605
3663
  confirmations: 65,
3606
3664
  fastConfirmations: 1
@@ -3646,6 +3704,7 @@ var EarnChain;
3646
3704
  v2: {
3647
3705
  type: 'split',
3648
3706
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
3707
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
3649
3708
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
3650
3709
  confirmations: 65,
3651
3710
  fastConfirmations: 1
@@ -3697,6 +3756,7 @@ var EarnChain;
3697
3756
  v2: {
3698
3757
  type: 'split',
3699
3758
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
3759
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
3700
3760
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
3701
3761
  confirmations: 65,
3702
3762
  fastConfirmations: 2
@@ -3761,6 +3821,7 @@ var EarnChain;
3761
3821
  v2: {
3762
3822
  type: 'split',
3763
3823
  tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
3824
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
3764
3825
  messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
3765
3826
  confirmations: 65,
3766
3827
  fastConfirmations: 2
@@ -3871,6 +3932,7 @@ var EarnChain;
3871
3932
  v2: {
3872
3933
  type: 'split',
3873
3934
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
3935
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
3874
3936
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
3875
3937
  confirmations: 1,
3876
3938
  fastConfirmations: 1
@@ -3930,6 +3992,7 @@ var EarnChain;
3930
3992
  v2: {
3931
3993
  type: 'split',
3932
3994
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
3995
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
3933
3996
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
3934
3997
  confirmations: 1,
3935
3998
  fastConfirmations: 1
@@ -3990,6 +4053,7 @@ var EarnChain;
3990
4053
  v2: {
3991
4054
  type: 'split',
3992
4055
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
4056
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
3993
4057
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
3994
4058
  confirmations: 1,
3995
4059
  fastConfirmations: 1
@@ -4037,6 +4101,7 @@ var EarnChain;
4037
4101
  v2: {
4038
4102
  type: 'split',
4039
4103
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
4104
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4040
4105
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
4041
4106
  confirmations: 1,
4042
4107
  fastConfirmations: 1
@@ -4084,6 +4149,7 @@ var EarnChain;
4084
4149
  v2: {
4085
4150
  type: 'split',
4086
4151
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
4152
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
4087
4153
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
4088
4154
  confirmations: 65,
4089
4155
  fastConfirmations: 1
@@ -4131,6 +4197,7 @@ var EarnChain;
4131
4197
  v2: {
4132
4198
  type: 'split',
4133
4199
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
4200
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4134
4201
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
4135
4202
  confirmations: 65,
4136
4203
  fastConfirmations: 1
@@ -4175,6 +4242,7 @@ var EarnChain;
4175
4242
  v2: {
4176
4243
  type: 'split',
4177
4244
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
4245
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
4178
4246
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
4179
4247
  confirmations: 1,
4180
4248
  fastConfirmations: 1
@@ -4220,6 +4288,7 @@ var EarnChain;
4220
4288
  v2: {
4221
4289
  type: 'split',
4222
4290
  tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
4291
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4223
4292
  messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
4224
4293
  confirmations: 1,
4225
4294
  fastConfirmations: 1
@@ -4266,6 +4335,7 @@ var EarnChain;
4266
4335
  v2: {
4267
4336
  type: 'split',
4268
4337
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
4338
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
4269
4339
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
4270
4340
  confirmations: 1,
4271
4341
  fastConfirmations: 1
@@ -4313,6 +4383,7 @@ var EarnChain;
4313
4383
  v2: {
4314
4384
  type: 'split',
4315
4385
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
4386
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4316
4387
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
4317
4388
  confirmations: 1,
4318
4389
  fastConfirmations: 1
@@ -4358,6 +4429,7 @@ var EarnChain;
4358
4429
  v2: {
4359
4430
  type: 'split',
4360
4431
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
4432
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
4361
4433
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
4362
4434
  confirmations: 64,
4363
4435
  fastConfirmations: 1
@@ -4403,6 +4475,7 @@ var EarnChain;
4403
4475
  v2: {
4404
4476
  type: 'split',
4405
4477
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
4478
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4406
4479
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
4407
4480
  confirmations: 64,
4408
4481
  fastConfirmations: 1
@@ -4579,6 +4652,7 @@ var EarnChain;
4579
4652
  v2: {
4580
4653
  type: 'split',
4581
4654
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
4655
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
4582
4656
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
4583
4657
  confirmations: 65,
4584
4658
  fastConfirmations: 1
@@ -4643,6 +4717,7 @@ var EarnChain;
4643
4717
  v2: {
4644
4718
  type: 'split',
4645
4719
  tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
4720
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4646
4721
  messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
4647
4722
  confirmations: 65,
4648
4723
  fastConfirmations: 1
@@ -4702,6 +4777,7 @@ var EarnChain;
4702
4777
  v2: {
4703
4778
  type: 'split',
4704
4779
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
4780
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
4705
4781
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
4706
4782
  confirmations: 1,
4707
4783
  fastConfirmations: 1
@@ -4748,6 +4824,7 @@ var EarnChain;
4748
4824
  v2: {
4749
4825
  type: 'split',
4750
4826
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
4827
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4751
4828
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
4752
4829
  confirmations: 1,
4753
4830
  fastConfirmations: 1
@@ -4763,6 +4840,98 @@ var EarnChain;
4763
4840
  }
4764
4841
  });
4765
4842
 
4843
+ /**
4844
+ * Plasma Mainnet chain definition
4845
+ * @remarks
4846
+ * This represents the official production network for the Plasma blockchain.
4847
+ * Plasma is an EVM-equivalent Layer 1 blockchain purpose-built for global
4848
+ * stablecoin payments, with deterministic BFT finality (PlasmaBFT/Fast-HotStuff).
4849
+ */ const Plasma = defineChain({
4850
+ type: 'evm',
4851
+ chain: Blockchain.Plasma,
4852
+ name: 'Plasma',
4853
+ title: 'Plasma Mainnet',
4854
+ nativeCurrency: {
4855
+ name: 'Plasma',
4856
+ symbol: 'XPL',
4857
+ decimals: 18
4858
+ },
4859
+ chainId: 9745,
4860
+ isTestnet: false,
4861
+ explorerUrl: 'https://plasmascan.to/tx/{hash}',
4862
+ rpcEndpoints: [
4863
+ 'https://rpc.plasma.to'
4864
+ ],
4865
+ eurcAddress: '0x3EE196E78d4d4248b849B8E1C7F44C5457FAFD2C',
4866
+ usdcAddress: '0x2d661C89D812261039AF9764eceaAee884f5F67F',
4867
+ usdtAddress: null,
4868
+ cctp: {
4869
+ domain: 33,
4870
+ contracts: {
4871
+ v2: {
4872
+ type: 'split',
4873
+ tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
4874
+ messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
4875
+ confirmations: 3,
4876
+ fastConfirmations: 1
4877
+ }
4878
+ },
4879
+ forwarderSupported: {
4880
+ source: false,
4881
+ destination: false
4882
+ }
4883
+ },
4884
+ kitContracts: {
4885
+ bridge: BRIDGE_CONTRACT_EVM_MAINNET
4886
+ }
4887
+ });
4888
+
4889
+ /**
4890
+ * Plasma Testnet chain definition
4891
+ * @remarks
4892
+ * This represents the official test network for the Plasma blockchain.
4893
+ * Plasma is an EVM-equivalent Layer 1 blockchain purpose-built for global
4894
+ * stablecoin payments, with deterministic BFT finality (PlasmaBFT/Fast-HotStuff).
4895
+ */ const PlasmaTestnet = defineChain({
4896
+ type: 'evm',
4897
+ chain: Blockchain.Plasma_Testnet,
4898
+ name: 'Plasma Testnet',
4899
+ title: 'Plasma Testnet',
4900
+ nativeCurrency: {
4901
+ name: 'Plasma',
4902
+ symbol: 'XPL',
4903
+ decimals: 18
4904
+ },
4905
+ chainId: 9746,
4906
+ isTestnet: true,
4907
+ explorerUrl: 'https://testnet.plasmascan.to/tx/{hash}',
4908
+ rpcEndpoints: [
4909
+ 'https://testnet-rpc.plasma.to'
4910
+ ],
4911
+ eurcAddress: '0x98AfA0F93Dd993B736399f9074eDcEBD1985A330',
4912
+ usdcAddress: '0xE67Fb267022cBA8064Dd388CC2FED724F3120D9D',
4913
+ usdtAddress: null,
4914
+ cctp: {
4915
+ domain: 33,
4916
+ contracts: {
4917
+ v2: {
4918
+ type: 'split',
4919
+ tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
4920
+ messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
4921
+ confirmations: 3,
4922
+ fastConfirmations: 1
4923
+ }
4924
+ },
4925
+ forwarderSupported: {
4926
+ source: false,
4927
+ destination: false
4928
+ }
4929
+ },
4930
+ kitContracts: {
4931
+ bridge: BRIDGE_CONTRACT_EVM_TESTNET
4932
+ }
4933
+ });
4934
+
4766
4935
  /**
4767
4936
  * Plume Mainnet chain definition
4768
4937
  * @remarks
@@ -4794,6 +4963,7 @@ var EarnChain;
4794
4963
  v2: {
4795
4964
  type: 'split',
4796
4965
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
4966
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
4797
4967
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
4798
4968
  confirmations: 65,
4799
4969
  fastConfirmations: 1
@@ -4840,6 +5010,7 @@ var EarnChain;
4840
5010
  v2: {
4841
5011
  type: 'split',
4842
5012
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
5013
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
4843
5014
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
4844
5015
  confirmations: 65,
4845
5016
  fastConfirmations: 1
@@ -4941,6 +5112,7 @@ var EarnChain;
4941
5112
  v2: {
4942
5113
  type: 'split',
4943
5114
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
5115
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
4944
5116
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
4945
5117
  confirmations: 33,
4946
5118
  fastConfirmations: 13
@@ -4960,7 +5132,9 @@ var EarnChain;
4960
5132
  contracts: {
4961
5133
  v1: {
4962
5134
  wallet: GATEWAY_WALLET_EVM_MAINNET,
4963
- minter: GATEWAY_MINTER_EVM_MAINNET
5135
+ minter: GATEWAY_MINTER_EVM_MAINNET,
5136
+ depositForHandler: DEPOSIT_FOR_HANDLER_EVM_MAINNET,
5137
+ genericExecutor: GENERIC_EXECUTOR_EVM_MAINNET
4964
5138
  }
4965
5139
  },
4966
5140
  forwarderSupported: {
@@ -5006,6 +5180,7 @@ var EarnChain;
5006
5180
  v2: {
5007
5181
  type: 'split',
5008
5182
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
5183
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
5009
5184
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
5010
5185
  confirmations: 33,
5011
5186
  fastConfirmations: 13
@@ -5024,7 +5199,9 @@ var EarnChain;
5024
5199
  contracts: {
5025
5200
  v1: {
5026
5201
  wallet: GATEWAY_WALLET_EVM_TESTNET,
5027
- minter: GATEWAY_MINTER_EVM_TESTNET
5202
+ minter: GATEWAY_MINTER_EVM_TESTNET,
5203
+ depositForHandler: DEPOSIT_FOR_HANDLER_EVM_TESTNET,
5204
+ genericExecutor: GENERIC_EXECUTOR_EVM_TESTNET
5028
5205
  }
5029
5206
  },
5030
5207
  forwarderSupported: {
@@ -5065,6 +5242,7 @@ var EarnChain;
5065
5242
  v2: {
5066
5243
  type: 'split',
5067
5244
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
5245
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
5068
5246
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
5069
5247
  confirmations: 1,
5070
5248
  fastConfirmations: 1
@@ -5124,6 +5302,7 @@ var EarnChain;
5124
5302
  v2: {
5125
5303
  type: 'split',
5126
5304
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
5305
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
5127
5306
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
5128
5307
  confirmations: 1,
5129
5308
  fastConfirmations: 1
@@ -5181,6 +5360,7 @@ var EarnChain;
5181
5360
  v2: {
5182
5361
  type: 'split',
5183
5362
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
5363
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
5184
5364
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
5185
5365
  confirmations: 1,
5186
5366
  fastConfirmations: 1
@@ -5239,6 +5419,7 @@ var EarnChain;
5239
5419
  v2: {
5240
5420
  type: 'split',
5241
5421
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
5422
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
5242
5423
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
5243
5424
  confirmations: 1,
5244
5425
  fastConfirmations: 1
@@ -5554,6 +5735,7 @@ var EarnChain;
5554
5735
  v2: {
5555
5736
  type: 'split',
5556
5737
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
5738
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
5557
5739
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
5558
5740
  confirmations: 65,
5559
5741
  fastConfirmations: 1
@@ -5618,6 +5800,7 @@ var EarnChain;
5618
5800
  v2: {
5619
5801
  type: 'split',
5620
5802
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
5803
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
5621
5804
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
5622
5805
  confirmations: 65,
5623
5806
  fastConfirmations: 1
@@ -5675,6 +5858,7 @@ var EarnChain;
5675
5858
  v2: {
5676
5859
  type: 'split',
5677
5860
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cF5d',
5861
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
5678
5862
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
5679
5863
  confirmations: 65,
5680
5864
  fastConfirmations: 1
@@ -5734,6 +5918,7 @@ var EarnChain;
5734
5918
  v2: {
5735
5919
  type: 'split',
5736
5920
  tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
5921
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
5737
5922
  messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
5738
5923
  confirmations: 65,
5739
5924
  fastConfirmations: 1
@@ -5794,6 +5979,7 @@ var EarnChain;
5794
5979
  v2: {
5795
5980
  type: 'split',
5796
5981
  tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
5982
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
5797
5983
  messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
5798
5984
  confirmations: 3,
5799
5985
  fastConfirmations: 3
@@ -5839,6 +6025,7 @@ var EarnChain;
5839
6025
  v2: {
5840
6026
  type: 'split',
5841
6027
  tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
6028
+ tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
5842
6029
  messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
5843
6030
  confirmations: 3,
5844
6031
  fastConfirmations: 1
@@ -6049,6 +6236,8 @@ var Chains = /*#__PURE__*/Object.freeze({
6049
6236
  OptimismSepolia: OptimismSepolia,
6050
6237
  Pharos: Pharos,
6051
6238
  PharosTestnet: PharosTestnet,
6239
+ Plasma: Plasma,
6240
+ PlasmaTestnet: PlasmaTestnet,
6052
6241
  Plume: Plume,
6053
6242
  PlumeTestnet: PlumeTestnet,
6054
6243
  PolkadotAssetHub: PolkadotAssetHub,
@@ -6098,6 +6287,67 @@ var Chains = /*#__PURE__*/Object.freeze({
6098
6287
  return chain.cctp?.contracts.v2 !== undefined;
6099
6288
  }
6100
6289
 
6290
+ /**
6291
+ * Chains the Fee Service accepts as a SOURCE for source-paid ("receive-exact")
6292
+ * CCTP v2 fees. An explicit allowlist is required because the
6293
+ * `TokenMessengerWithFees` wrapper address is now shared with the fast-deposit
6294
+ * forwarder path, so wrapper presence no longer implies source-fee support.
6295
+ * Keep in sync with backend coverage.
6296
+ */ new Set([
6297
+ // Mainnet
6298
+ Blockchain.Ethereum,
6299
+ Blockchain.Base,
6300
+ Blockchain.Arbitrum,
6301
+ Blockchain.Unichain,
6302
+ Blockchain.Optimism,
6303
+ Blockchain.Codex,
6304
+ Blockchain.Ink,
6305
+ Blockchain.Plume,
6306
+ Blockchain.Linea,
6307
+ Blockchain.World_Chain,
6308
+ // Testnet counterparts
6309
+ Blockchain.Ethereum_Sepolia,
6310
+ Blockchain.Base_Sepolia,
6311
+ Blockchain.Arbitrum_Sepolia,
6312
+ Blockchain.Unichain_Sepolia,
6313
+ Blockchain.Optimism_Sepolia,
6314
+ Blockchain.Codex_Testnet,
6315
+ Blockchain.Ink_Testnet,
6316
+ Blockchain.Plume_Testnet,
6317
+ Blockchain.Linea_Sepolia,
6318
+ Blockchain.World_Chain_Sepolia
6319
+ ]);
6320
+
6321
+ /**
6322
+ * Temporary allowlist of chains permitted to initiate Gateway fast deposits.
6323
+ * Only chains keyed here are eligible; all others are rejected. Using the
6324
+ * {@link Blockchain} enum keeps entries type-safe and catches typos at compile
6325
+ * time. Remove this allowlist once roll-out is complete.
6326
+ */ new Set([
6327
+ // Mainnet
6328
+ Blockchain.Ethereum,
6329
+ Blockchain.Base,
6330
+ Blockchain.Arbitrum,
6331
+ Blockchain.Unichain,
6332
+ Blockchain.Optimism,
6333
+ Blockchain.Codex,
6334
+ Blockchain.Ink,
6335
+ Blockchain.Plume,
6336
+ Blockchain.Linea,
6337
+ Blockchain.World_Chain,
6338
+ // Testnet counterparts
6339
+ Blockchain.Ethereum_Sepolia,
6340
+ Blockchain.Base_Sepolia,
6341
+ Blockchain.Arbitrum_Sepolia,
6342
+ Blockchain.Unichain_Sepolia,
6343
+ Blockchain.Optimism_Sepolia,
6344
+ Blockchain.Codex_Testnet,
6345
+ Blockchain.Ink_Testnet,
6346
+ Blockchain.Plume_Testnet,
6347
+ Blockchain.Linea_Sepolia,
6348
+ Blockchain.World_Chain_Sepolia
6349
+ ]);
6350
+
6101
6351
  /**
6102
6352
  * Zod schema for validating Gateway v1 contract addresses.
6103
6353
  *
@@ -6119,7 +6369,10 @@ var Chains = /*#__PURE__*/Object.freeze({
6119
6369
  }).min(1, 'Gateway minter address cannot be empty.'),
6120
6370
  depositForHandler: z.string({
6121
6371
  invalid_type_error: 'Gateway depositForHandler address must be a string.'
6122
- }).min(1, 'Gateway depositForHandler address cannot be empty.').optional()
6372
+ }).min(1, 'Gateway depositForHandler address cannot be empty.').optional(),
6373
+ genericExecutor: z.string({
6374
+ invalid_type_error: 'Gateway genericExecutor address must be a string.'
6375
+ }).min(1, 'Gateway genericExecutor address cannot be empty.').optional()
6123
6376
  }).strict() // Reject any additional properties not defined in the schema
6124
6377
  ;
6125
6378
  /**
@@ -7505,6 +7758,7 @@ const swapTokenEnumSchema = z.enum([
7505
7758
  [Blockchain.Noble]: 'uusdc',
7506
7759
  [Blockchain.Optimism]: '0x0b2c639c533813f4aa9d7837caf62653d097ff85',
7507
7760
  [Blockchain.Pharos]: '0xC879C018dB60520F4355C26eD1a6D572cdAC1815',
7761
+ [Blockchain.Plasma]: '0x2d661C89D812261039AF9764eceaAee884f5F67F',
7508
7762
  [Blockchain.Plume]: '0x222365EF19F7947e5484218551B56bb3965Aa7aF',
7509
7763
  [Blockchain.Polkadot_Asset_Hub]: '1337',
7510
7764
  [Blockchain.Polygon]: '0x3c499c542cef5e3811e1192ce70d8cc03d5c3359',
@@ -7541,6 +7795,7 @@ const swapTokenEnumSchema = z.enum([
7541
7795
  [Blockchain.Noble_Testnet]: 'uusdc',
7542
7796
  [Blockchain.Optimism_Sepolia]: '0x5fd84259d66Cd46123540766Be93DFE6D43130D7',
7543
7797
  [Blockchain.Pharos_Testnet]: '0xcfC8330f4BCAB529c625D12781b1C19466A9Fc8B',
7798
+ [Blockchain.Plasma_Testnet]: '0xE67Fb267022cBA8064Dd388CC2FED724F3120D9D',
7544
7799
  [Blockchain.Plume_Testnet]: '0xcB5f30e335672893c7eb944B374c196392C19D18',
7545
7800
  [Blockchain.Polkadot_Westmint]: '31337',
7546
7801
  [Blockchain.Polygon_Amoy_Testnet]: '0x41e94eb019c0762f9bfcf9fb1e58725bfb0e7582',
@@ -7603,6 +7858,7 @@ const swapTokenEnumSchema = z.enum([
7603
7858
  [Blockchain.Base]: '0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42',
7604
7859
  [Blockchain.Cronos]: '0xA6dE01a2d62C6B5f3525d768f34d276652C554c8',
7605
7860
  [Blockchain.Ethereum]: '0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c',
7861
+ [Blockchain.Plasma]: '0x3EE196E78d4d4248b849B8E1C7F44C5457FAFD2C',
7606
7862
  [Blockchain.Solana]: 'HzwqbKZw8HxMN6bF2yFZNrht3c2iXXzpKcFu7uBEDKtr',
7607
7863
  [Blockchain.World_Chain]: '0x1C60ba0A0eD1019e8Eb035E6daF4155A5cE2380B',
7608
7864
  // =========================================================================
@@ -7611,7 +7867,8 @@ const swapTokenEnumSchema = z.enum([
7611
7867
  [Blockchain.Arc_Testnet]: '0x89B50855Aa3bE2F677cD6303Cec089B5F319D72a',
7612
7868
  [Blockchain.Base_Sepolia]: '0x808456652fdb597867f38412077A9182bf77359F',
7613
7869
  [Blockchain.Cronos_Testnet]: '0x31f7538adb53cF16350e6B0c89d03D91b7D12c46',
7614
- [Blockchain.Ethereum_Sepolia]: '0x08210F9170F89Ab7658F0B5E3fF39b0E03C594D4'
7870
+ [Blockchain.Ethereum_Sepolia]: '0x08210F9170F89Ab7658F0B5E3fF39b0E03C594D4',
7871
+ [Blockchain.Plasma_Testnet]: '0x98AfA0F93Dd993B736399f9074eDcEBD1985A330'
7615
7872
  }
7616
7873
  };
7617
7874
 
@@ -8329,7 +8586,7 @@ const swapTokenEnumSchema = z.enum([
8329
8586
  * allowlisted {@link ClientLogPayload} fields (and the allowlisted
8330
8587
  * sub-fields of `errorDetails` / `clientContext`) are copied across.
8331
8588
  * A regressing upstream mapper — or a plain-JS caller that bypasses the
8332
- * type — therefore cannot exfiltrate stray properties (secrets, PII,
8589
+ * type — therefore cannot exfiltrate stray properties (secrets,
8333
8590
  * raw error stacks) through the analytics channel. Optional fields are
8334
8591
  * only included when present so the serialised shape matches the
8335
8592
  * server's strict schema.
@@ -8352,6 +8609,9 @@ const swapTokenEnumSchema = z.enum([
8352
8609
  if (payload.destinationChain !== undefined) safe['destinationChain'] = payload.destinationChain;
8353
8610
  if (payload.tokenIn !== undefined) safe['tokenIn'] = payload.tokenIn;
8354
8611
  if (payload.tokenOut !== undefined) safe['tokenOut'] = payload.tokenOut;
8612
+ if (payload.amountIn !== undefined) safe['amountIn'] = payload.amountIn;
8613
+ if (payload.durationMs !== undefined) safe['durationMs'] = payload.durationMs;
8614
+ if (payload.sourceAddress !== undefined) safe['sourceAddress'] = payload.sourceAddress;
8355
8615
  if (payload.txHash !== undefined) safe['txHash'] = payload.txHash;
8356
8616
  if (payload.correlationId !== undefined) safe['correlationId'] = payload.correlationId;
8357
8617
  if (payload.errorDetails !== undefined) {
@@ -8548,14 +8808,28 @@ const swapTokenEnumSchema = z.enum([
8548
8808
  }
8549
8809
 
8550
8810
  /**
8551
- * Soft signal for the case where building or emitting a telemetry payload
8552
- * threw — for example, a buggy `TelemetryContextResolver`, a regression in
8811
+ * Emit a stable console warning when building or emitting a telemetry payload
8812
+ * throws — for example, a buggy `TelemetryContextResolver`, a regression in
8553
8813
  * `extractErrorDetails`, or a synchronous failure inside `emitAnalyticsLog`
8554
- * before it could swallow the error itself. Logged with a stable prefix so
8555
- * consumers can grep for it. We deliberately do not re-throw: the caller's
8556
- * original operation error must always win.
8814
+ * before it could swallow the error itself. Uses a stable prefix so the
8815
+ * drop is discoverable via grep. Never re-throws: the caller's original
8816
+ * operation error must always win.
8557
8817
  *
8558
8818
  * @internal
8819
+ *
8820
+ * @param eventType - The telemetry event type that was being emitted.
8821
+ * @param cause - The error or value that caused the drop.
8822
+ *
8823
+ * @example
8824
+ * ```typescript
8825
+ * import { warnTelemetryDrop } from '@core/utils'
8826
+ *
8827
+ * try {
8828
+ * void emitAnalyticsLog(payload)
8829
+ * } catch (err) {
8830
+ * warnTelemetryDrop('my_event', err)
8831
+ * }
8832
+ * ```
8559
8833
  */ function warnTelemetryDrop(eventType, cause) {
8560
8834
  try {
8561
8835
  // Pass `cause` as the second console.warn argument rather than
@@ -8595,6 +8869,9 @@ const swapTokenEnumSchema = z.enum([
8595
8869
  ...context?.tokenOut != null && {
8596
8870
  tokenOut: context.tokenOut
8597
8871
  },
8872
+ ...context?.amountIn != null && {
8873
+ amountIn: context.amountIn
8874
+ },
8598
8875
  ...context?.txHash != null && {
8599
8876
  txHash: context.txHash
8600
8877
  },
@@ -8694,7 +8971,7 @@ const swapTokenEnumSchema = z.enum([
8694
8971
  }
8695
8972
 
8696
8973
  var name$3 = "@circle-fin/bridge-kit";
8697
- var version$3 = "1.13.0";
8974
+ var version$3 = "1.14.1";
8698
8975
  var pkg$3 = {
8699
8976
  name: name$3,
8700
8977
  version: version$3};
@@ -8969,7 +9246,7 @@ const READ_ACTION_KEY_SET = new Set(READ_ACTION_KEYS);
8969
9246
  * const result = evmAddressSchema.safeParse(validAddress)
8970
9247
  * console.log(result.success) // true
8971
9248
  * ```
8972
- */ const evmAddressSchema = hexStringSchema.refine((value)=>value.length === 42, 'EVM address must be exactly 42 characters long (0x + 40 hex characters)').transform((value)=>value);
9249
+ */ const evmAddressSchema$1 = hexStringSchema.refine((value)=>value.length === 42, 'EVM address must be exactly 42 characters long (0x + 40 hex characters)').transform((value)=>value);
8973
9250
  /**
8974
9251
  * Schema for validating transaction hashes.
8975
9252
  *
@@ -9506,6 +9783,10 @@ var TransferSpeed;
9506
9783
  token: z.literal('USDC').optional(),
9507
9784
  config: z.object({
9508
9785
  transferSpeed: z.nativeEnum(TransferSpeed).optional(),
9786
+ feePayment: z.enum([
9787
+ 'source',
9788
+ 'destination'
9789
+ ]).optional(),
9509
9790
  maxFee: z.string().min(1, 'Required').pipe(createDecimalStringValidator({
9510
9791
  allowZero: true,
9511
9792
  regexMessage: MAX_FEE_FORMAT_ERROR_MESSAGE,
@@ -9513,7 +9794,8 @@ var TransferSpeed;
9513
9794
  maxDecimals: 6
9514
9795
  })(z.string())).optional(),
9515
9796
  customFee: customFeeSchema.optional()
9516
- }).optional()
9797
+ }).optional(),
9798
+ quote: z.string().regex(/^0x([a-fA-F0-9]{2})+$/, 'must be non-empty 0x hex').optional()
9517
9799
  });
9518
9800
 
9519
9801
  // ============================================================================
@@ -9621,6 +9903,241 @@ var TransferSpeed;
9621
9903
  message: 'Invalid metrics'
9622
9904
  });
9623
9905
 
9906
+ /**
9907
+ * Omit undefined values from an object.
9908
+ *
9909
+ * @param obj - The object to process.
9910
+ * @returns A new object with undefined values removed.
9911
+ *
9912
+ * @internal
9913
+ * @remarks
9914
+ * Used by both production and mock loggers to ensure consistent behavior.
9915
+ * This prevents undefined values from being serialized in log output,
9916
+ * which can cause issues with some log transports.
9917
+ */ function omitUndefined(obj) {
9918
+ const result = {};
9919
+ for (const [key, value] of Object.entries(obj)){
9920
+ if (value !== undefined) {
9921
+ result[key] = value;
9922
+ }
9923
+ }
9924
+ return result;
9925
+ }
9926
+
9927
+ /**
9928
+ * Default redaction paths for web3/blockchain SDKs.
9929
+ *
9930
+ * @remarks
9931
+ * These paths target common sensitive fields in blockchain applications.
9932
+ * All user fields are nested under `context`, so paths start with `context.`.
9933
+ * Wildcard `*` matches any key at that level.
9934
+ */ const DEFAULT_REDACT_PATHS = [
9935
+ // Generic Credentials
9936
+ 'context.password',
9937
+ 'context.passphrase',
9938
+ 'context.secret',
9939
+ 'context.token',
9940
+ 'context.*.password',
9941
+ 'context.*.passphrase',
9942
+ 'context.*.secret',
9943
+ 'context.*.token',
9944
+ // API Keys & Auth Tokens
9945
+ 'context.apiKey',
9946
+ 'context.apiSecret',
9947
+ 'context.accessToken',
9948
+ 'context.refreshToken',
9949
+ 'context.jwt',
9950
+ 'context.bearerToken',
9951
+ 'context.sessionId',
9952
+ 'context.authorization',
9953
+ 'context.cookie',
9954
+ 'context.*.apiKey',
9955
+ 'context.*.apiSecret',
9956
+ 'context.*.accessToken',
9957
+ 'context.*.refreshToken',
9958
+ 'context.*.jwt',
9959
+ 'context.*.bearerToken',
9960
+ 'context.*.sessionId',
9961
+ 'context.*.authorization',
9962
+ 'context.*.cookie',
9963
+ // Web3 / Crypto Keys
9964
+ 'context.privateKey',
9965
+ 'context.secretKey',
9966
+ 'context.signingKey',
9967
+ 'context.encryptionKey',
9968
+ 'context.*.privateKey',
9969
+ 'context.*.secretKey',
9970
+ 'context.*.signingKey',
9971
+ 'context.*.encryptionKey',
9972
+ // Web3 / Crypto Mnemonics and Seeds
9973
+ 'context.mnemonic',
9974
+ 'context.seed',
9975
+ 'context.seedPhrase',
9976
+ 'context.*.mnemonic',
9977
+ 'context.*.seed',
9978
+ 'context.*.seedPhrase',
9979
+ // OTP / Verification Codes
9980
+ 'context.otp',
9981
+ 'context.verificationCode',
9982
+ 'context.*.otp',
9983
+ 'context.*.verificationCode',
9984
+ // Payment Information
9985
+ 'context.cardNumber',
9986
+ 'context.cvv',
9987
+ 'context.accountNumber',
9988
+ 'context.*.cardNumber',
9989
+ 'context.*.cvv',
9990
+ 'context.*.accountNumber'
9991
+ ];
9992
+ /**
9993
+ * Wrap user fields under `context` to prevent collision with pino internals.
9994
+ *
9995
+ * @param fields - User-provided log fields.
9996
+ * @returns Object with fields nested under `context`, or undefined if empty.
9997
+ *
9998
+ * @remarks
9999
+ * This function handles edge cases by returning undefined for null, undefined,
10000
+ * or empty objects to avoid unnecessary wrapping in log output.
10001
+ * Undefined values are cleaned before wrapping.
10002
+ */ function wrapInContext(fields) {
10003
+ if (!fields) return undefined;
10004
+ // Clean undefined values for consistency and transport compatibility
10005
+ const cleaned = omitUndefined(fields);
10006
+ // Handle edge case: all values were undefined, resulting in empty object
10007
+ const keys = Object.keys(cleaned);
10008
+ if (keys.length === 0) return undefined;
10009
+ return {
10010
+ context: cleaned
10011
+ };
10012
+ }
10013
+ /**
10014
+ * Wrap a pino instance to conform to our Logger interface.
10015
+ *
10016
+ * @param pinoInstance - The pino logger instance to wrap.
10017
+ * @returns A Logger instance conforming to our stable interface.
10018
+ */ function wrapPino(pinoInstance) {
10019
+ return {
10020
+ debug (message, fields) {
10021
+ const wrapped = wrapInContext(fields);
10022
+ if (wrapped) {
10023
+ pinoInstance.debug(wrapped, message);
10024
+ } else {
10025
+ pinoInstance.debug(message);
10026
+ }
10027
+ },
10028
+ info (message, fields) {
10029
+ const wrapped = wrapInContext(fields);
10030
+ if (wrapped) {
10031
+ pinoInstance.info(wrapped, message);
10032
+ } else {
10033
+ pinoInstance.info(message);
10034
+ }
10035
+ },
10036
+ warn (message, fields) {
10037
+ const wrapped = wrapInContext(fields);
10038
+ if (wrapped) {
10039
+ pinoInstance.warn(wrapped, message);
10040
+ } else {
10041
+ pinoInstance.warn(message);
10042
+ }
10043
+ },
10044
+ error (message, fields) {
10045
+ const wrapped = wrapInContext(fields);
10046
+ if (wrapped) {
10047
+ pinoInstance.error(wrapped, message);
10048
+ } else {
10049
+ pinoInstance.error(message);
10050
+ }
10051
+ },
10052
+ child (tags) {
10053
+ // Child bindings stay flat (not wrapped) - they're part of logger's base context
10054
+ const cleaned = omitUndefined(tags);
10055
+ return wrapPino(pinoInstance.child(cleaned));
10056
+ }
10057
+ };
10058
+ }
10059
+ /**
10060
+ * Build pino redact configuration from our simplified options.
10061
+ *
10062
+ * @param redact - The redact configuration option.
10063
+ * @returns Pino-compatible redact configuration or undefined.
10064
+ */ function buildRedactConfig(redact) {
10065
+ // Explicitly disabled
10066
+ if (redact === false) {
10067
+ return undefined;
10068
+ }
10069
+ // Custom paths provided
10070
+ if (Array.isArray(redact)) {
10071
+ return redact.length > 0 ? {
10072
+ paths: redact,
10073
+ censor: '[REDACTED]'
10074
+ } : undefined;
10075
+ }
10076
+ // Default: use web3 sensible defaults
10077
+ return {
10078
+ paths: [
10079
+ ...DEFAULT_REDACT_PATHS
10080
+ ],
10081
+ censor: '[REDACTED]'
10082
+ };
10083
+ }
10084
+ /**
10085
+ * Create a logger backed by pino.
10086
+ *
10087
+ * @param options - Logger options (optional).
10088
+ * @param stream - Destination stream (optional).
10089
+ * @returns A Logger instance.
10090
+ * @throws Error if invalid pino options are provided.
10091
+ *
10092
+ * @remarks
10093
+ * This is a thin wrapper around pino that exposes our stable Logger interface.
10094
+ * Pino handles all transport concerns: JSON, pretty printing, file, remote, browser, etc.
10095
+ *
10096
+ * **Security**: By default, sensitive web3 fields (privateKey, mnemonic, apiKey, etc.)
10097
+ * are automatically redacted from log output. Use `redact: false` to disable.
10098
+ *
10099
+ * @example
10100
+ * ```typescript
10101
+ * import { createLogger } from '@core/runtime'
10102
+ *
10103
+ * // Default: web3 sensitive fields are redacted
10104
+ * const logger = createLogger({ level: 'info' })
10105
+ * logger.info('Signing', { privateKey: '0x123...' })
10106
+ * // Output: { context: { privateKey: '[REDACTED]' }, msg: 'Signing' }
10107
+ *
10108
+ * // Disable redaction (use with caution)
10109
+ * const unsafeLogger = createLogger({ level: 'debug', redact: false })
10110
+ *
10111
+ * // Custom redaction paths
10112
+ * const customLogger = createLogger({
10113
+ * level: 'info',
10114
+ * redact: ['context.mySecret', 'context.*.credentials']
10115
+ * })
10116
+ *
10117
+ * // Pretty output for development
10118
+ * const devLogger = createLogger({
10119
+ * level: 'debug',
10120
+ * transport: { target: 'pino-pretty' }
10121
+ * })
10122
+ *
10123
+ * // Browser logger
10124
+ * const browserLogger = createLogger({
10125
+ * browser: { asObject: true }
10126
+ * })
10127
+ * ```
10128
+ */ function createLogger(options, stream) {
10129
+ const { redact, ...pinoOptions } = options ?? {};
10130
+ // Build redaction config
10131
+ const redactConfig = buildRedactConfig(redact);
10132
+ // Build final pino options, only include redact if defined
10133
+ const finalOptions = redactConfig ? {
10134
+ ...pinoOptions,
10135
+ redact: redactConfig
10136
+ } : pinoOptions;
10137
+ const pinoInstance = pino(finalOptions);
10138
+ return wrapPino(pinoInstance);
10139
+ }
10140
+
9624
10141
  // ============================================================================
9625
10142
  // Validation Schema
9626
10143
  // ============================================================================
@@ -9728,6 +10245,9 @@ var TransferSpeed;
9728
10245
  [TransferSpeed.SLOW]: 2000
9729
10246
  });
9730
10247
 
10248
+ createLogger({
10249
+ name: 'provider-cctp-v2'
10250
+ });
9731
10251
  /**
9732
10252
  * All chains that are supported by the CCTP v2 provider.
9733
10253
  *
@@ -9737,13 +10257,206 @@ var TransferSpeed;
9737
10257
  * @internal
9738
10258
  */ Object.values(Chains).filter((chain)=>isCCTPV2Supported(chain));
9739
10259
 
10260
+ /**
10261
+ * Decimal string in token minor units, constrained to be strictly positive.
10262
+ *
10263
+ * @internal
10264
+ */ 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
10265
+ // regex check above fails ("dirty"), so guard BigInt() against throwing on a
10266
+ // non-numeric value before comparing.
10267
+ .refine((value)=>/^\d+$/.test(value) && BigInt(value) > 0n, 'must be greater than zero');
10268
+ /**
10269
+ * A 20-byte EVM address in `0x` hex.
10270
+ *
10271
+ * The MVP prepaid-`FORWARD` `burn/usdc` path targets EVM contracts
10272
+ * (`TokenMessengerWithFees` / `GenericExecutor`), so `feeToken` and
10273
+ * `destinationCaller` are constrained to EVM addresses by design. This is an
10274
+ * intentional scope limit, not a permanent one: it can be widened to other
10275
+ * address formats as the fee service expands to more chains.
10276
+ */ const evmAddressSchema = z.string().regex(/^0x[a-fA-F0-9]{40}$/, 'must be a 20-byte 0x address');
10277
+ /** 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');
10278
+ /** Non-empty, even-length `0x` hex. */ const nonEmptyHexSchema = z.string().regex(/^0x([a-fA-F0-9]{2})+$/, 'must be non-empty 0x hex');
10279
+ /** A 32-byte `0x` hex hash. */ const bytes32Schema = z.string().regex(/^0x[a-fA-F0-9]{64}$/, 'must be a 32-byte 0x hash');
10280
+ /** Decimal string in minor units, allowing zero. */ const numericStringSchema = z.string().regex(/^\d+$/, 'must be a non-negative integer string');
10281
+ /** An `https:` URL, used for the optional base-URL override. */ const httpsUrlSchema = z.string().refine((value)=>{
10282
+ try {
10283
+ return new URL(value).protocol === 'https:';
10284
+ } catch {
10285
+ return false;
10286
+ }
10287
+ }, 'must be an https URL');
10288
+ const forwardParamsSchema = z.object({
10289
+ hookData: hexSchema.optional(),
10290
+ destinationCaller: evmAddressSchema.optional()
10291
+ }).strict();
10292
+ const forwardRequestSchema = z.object({
10293
+ type: z.literal('FORWARD'),
10294
+ params: forwardParamsSchema.optional()
10295
+ }).strict();
10296
+ const preFinalityRequestSchema = z.object({
10297
+ type: z.literal('PRE_FINALITY')
10298
+ }).strict();
10299
+ /**
10300
+ * A single quote request item (`FORWARD` or `PRE_FINALITY`).
10301
+ *
10302
+ * @internal
10303
+ */ const feeQuoteRequestSchema = z.discriminatedUnion('type', [
10304
+ forwardRequestSchema,
10305
+ preFinalityRequestSchema
10306
+ ]);
10307
+ /**
10308
+ * A non-empty list of quote request items with unique types.
10309
+ *
10310
+ * @internal
10311
+ */ 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');
10312
+ /**
10313
+ * A structured `Partial<ApiPollingConfig>` polling override.
10314
+ *
10315
+ * Validates the field types callers actually set, so a plain-JS caller passing
10316
+ * `{ timeout: 'soon' }` is rejected at the boundary rather than failing opaquely
10317
+ * inside the transport. Unknown keys pass through so a future `ApiPollingConfig`
10318
+ * field is forwarded rather than silently dropped.
10319
+ */ const apiPollingConfigSchema = z.object({
10320
+ timeout: z.number().int().positive().optional(),
10321
+ maxRetries: z.number().int().nonnegative().optional(),
10322
+ retryDelay: z.number().int().nonnegative().optional(),
10323
+ backoff: z.enum([
10324
+ 'fixed',
10325
+ 'exponential'
10326
+ ]).optional(),
10327
+ maxRetryDelayMs: z.number().int().positive().optional(),
10328
+ headers: z.record(z.string()).optional()
10329
+ }).passthrough();
10330
+ /**
10331
+ * The validatable input for {@link fetchFeeQuote}.
10332
+ *
10333
+ * This is the single source of truth for input validation, including the CCTP
10334
+ * domains and the `isTestnet` environment flag. Validating `isTestnet` at
10335
+ * runtime matters because a plain-JS caller who omits it would otherwise leave
10336
+ * it `undefined`, which is falsy and silently selects the production base URL.
10337
+ * (`buildFeeQuoteUrl` independently re-validates the domains for standalone
10338
+ * callers.)
10339
+ *
10340
+ * @internal
10341
+ */ z.object({
10342
+ sourceDomain: z.number().int().nonnegative(),
10343
+ destinationDomain: z.number().int().nonnegative(),
10344
+ amount: positiveAmountSchema,
10345
+ feeToken: evmAddressSchema.optional(),
10346
+ requests: feeQuoteRequestsSchema,
10347
+ isTestnet: z.boolean(),
10348
+ baseUrl: httpsUrlSchema.optional(),
10349
+ config: apiPollingConfigSchema.optional()
10350
+ }).strict();
10351
+ const feeQuoteItemSchema = z.object({
10352
+ type: z.string().min(1),
10353
+ amount: numericStringSchema,
10354
+ args: z.array(z.string()),
10355
+ argsHash: bytes32Schema
10356
+ }).passthrough();
10357
+ const exchangeRatesSchema = z.object({
10358
+ feeTokenUsd: z.string(),
10359
+ destinationTokenUsd: z.string()
10360
+ }).passthrough();
10361
+ const metadataSchema = z.object({
10362
+ destinationGasPrice: z.string().optional(),
10363
+ exchangeRates: exchangeRatesSchema.optional()
10364
+ }).passthrough();
10365
+ /** The `expiry` object the Quote API nests the quote TTL under. */ const expirySchema = z.discriminatedUnion('mode', [
10366
+ z.object({
10367
+ mode: z.literal('TIMESTAMP'),
10368
+ expiresAt: z.number().int().nonnegative()
10369
+ }).passthrough(),
10370
+ z.object({
10371
+ mode: z.literal('BLOCK_NUMBER'),
10372
+ expiresAtBlock: z.number().int().nonnegative(),
10373
+ blockEstimatedAt: z.number().int().nonnegative().optional()
10374
+ }).passthrough()
10375
+ ]);
10376
+ /**
10377
+ * Schema for a signed fee quote returned by the Quote API.
10378
+ *
10379
+ * @internal
10380
+ */ z.object({
10381
+ // The runtime YAML spec maps signedQuote to a looser `hex` (which allows
10382
+ // an empty `0x`); we keep the stricter non-empty form. Do not relax
10383
+ // without a reason.
10384
+ signedQuote: nonEmptyHexSchema,
10385
+ issuedAt: z.number().int().nonnegative(),
10386
+ // The API returns a mode-specific timestamp or source-block deadline.
10387
+ expiry: expirySchema,
10388
+ feeTotalAmount: numericStringSchema,
10389
+ feeToken: evmAddressSchema,
10390
+ nonce: numericStringSchema,
10391
+ items: z.array(feeQuoteItemSchema),
10392
+ metadata: metadataSchema.optional()
10393
+ }).passthrough();
10394
+ /**
10395
+ * Validates input to {@link validateQuote}.
10396
+ *
10397
+ * @internal
10398
+ */ z.object({
10399
+ sourceDomain: z.number().int().nonnegative(),
10400
+ abiSignature: z.string().min(1),
10401
+ args: z.array(z.union([
10402
+ z.string(),
10403
+ z.array(z.string())
10404
+ ])),
10405
+ isTestnet: z.boolean(),
10406
+ baseUrl: httpsUrlSchema.optional(),
10407
+ config: apiPollingConfigSchema.optional()
10408
+ }).strict();
10409
+ const quoteExpiryStatusSchema = z.discriminatedUnion('mode', [
10410
+ z.object({
10411
+ mode: z.literal('TIMESTAMP'),
10412
+ expired: z.boolean(),
10413
+ secondsRemaining: z.number().int().nonnegative(),
10414
+ expiresAt: z.number().int().nonnegative()
10415
+ }).passthrough(),
10416
+ z.object({
10417
+ mode: z.literal('BLOCK_NUMBER'),
10418
+ expired: z.boolean(),
10419
+ secondsRemaining: z.number().int().nonnegative(),
10420
+ expiresAtBlock: z.number().int().nonnegative(),
10421
+ blockEstimatedAt: z.number().int().nonnegative().optional()
10422
+ }).passthrough()
10423
+ ]);
10424
+ const validateQuoteItemSchema = z.object({
10425
+ type: z.string().min(1),
10426
+ argsMatch: z.boolean(),
10427
+ amount: numericStringSchema.optional(),
10428
+ args: z.array(z.string()).optional(),
10429
+ argsHash: bytes32Schema.optional(),
10430
+ computedArgsHash: bytes32Schema.optional()
10431
+ }).passthrough();
10432
+ /**
10433
+ * Schema for a validate-quote result returned by the Iris `/validate/usdc/:sourceDomain` endpoint.
10434
+ *
10435
+ * The endpoint takes the source domain as a URL path parameter and does not
10436
+ * return it in the response body, so `sourceDomain` is intentionally not part
10437
+ * of this schema.
10438
+ *
10439
+ * @internal
10440
+ */ z.object({
10441
+ signedQuote: nonEmptyHexSchema,
10442
+ expiry: quoteExpiryStatusSchema,
10443
+ feeTotalAmount: numericStringSchema,
10444
+ feeToken: evmAddressSchema,
10445
+ nonce: numericStringSchema,
10446
+ claimable: z.boolean(),
10447
+ // Preserve newly introduced server-side reasons as opaque strings rather
10448
+ // than rejecting the entire safety response before the SDK is updated.
10449
+ failedChecks: z.array(z.string().min(1)),
10450
+ items: z.array(validateQuoteItemSchema)
10451
+ }).passthrough();
10452
+
9740
10453
  /** SDK name used in telemetry payloads. */ resolveKitSdkName(pkg$3.name);
9741
10454
 
9742
10455
  // Auto-register this kit for user agent tracking
9743
10456
  registerKit(`${pkg$3.name}/${pkg$3.version}`);
9744
10457
 
9745
10458
  var name$2 = "@circle-fin/swap-kit";
9746
- var version$2 = "1.5.2";
10459
+ var version$2 = "1.6.1";
9747
10460
  var pkg$2 = {
9748
10461
  name: name$2,
9749
10462
  version: version$2};
@@ -9757,7 +10470,7 @@ const optionalChainIdentifierField = chainIdentifierField.optional();
9757
10470
  * Catches obviously malformed addresses at parse time; chain-specific validation
9758
10471
  * is performed in buildServiceParams.
9759
10472
  */ const destinationAddressSchema = z.union([
9760
- evmAddressSchema,
10473
+ evmAddressSchema$1,
9761
10474
  solanaAddressSchema
9762
10475
  ]);
9763
10476
  /**
@@ -9803,9 +10516,16 @@ const optionalChainIdentifierField = chainIdentifierField.optional();
9803
10516
  message: 'stopLimit must be greater than 0'
9804
10517
  }).optional(),
9805
10518
  customFee: serviceSwapCustomFeeSchema.optional(),
10519
+ apiKey: z.string({
10520
+ invalid_type_error: 'apiKey must be a string'
10521
+ })// Tolerate '' so the `process.env.CIRCLE_API_KEY ?? ''` idiom falls back to
10522
+ // kitKey via resolveApiKey instead of being rejected here.
10523
+ .optional(),
9806
10524
  kitKey: z.string({
9807
10525
  invalid_type_error: 'kitKey must be a string'
9808
- }).min(1, 'kitKey must be a non-empty string').optional(),
10526
+ })// Tolerate '' so an unset kit-key env var yields the permissionless path,
10527
+ // matching buildServiceParams (which already omits an empty credential).
10528
+ .optional(),
9809
10529
  provider: z.string({
9810
10530
  invalid_type_error: 'provider must be a string'
9811
10531
  }).min(1, 'provider must be a non-empty string').optional(),
@@ -9978,6 +10698,41 @@ const optionalChainIdentifierField = chainIdentifierField.optional();
9978
10698
  *
9979
10699
  * @internal
9980
10700
  */ const MAX_RATE_ADDRESSES_PER_REQUEST = 100;
10701
+ /**
10702
+ * Environment prefixes carried by Circle platform API keys.
10703
+ *
10704
+ * A Circle API key is `<ENV>_API_KEY:<keyId>:<keySecret>`, where `<ENV>` is one
10705
+ * of these prefixes.
10706
+ *
10707
+ * @internal
10708
+ */ const API_KEY_ENV_PREFIXES = [
10709
+ 'TEST',
10710
+ 'LIVE',
10711
+ 'SAND',
10712
+ 'SANDBOX',
10713
+ 'SMOK',
10714
+ 'PROD',
10715
+ 'STAG',
10716
+ 'DEV'
10717
+ ];
10718
+ /**
10719
+ * Accepted credential formats for Stablecoin Service authentication.
10720
+ *
10721
+ * Matches a Circle platform API key (`<ENV>_API_KEY:<keyId>:<keySecret>`) and
10722
+ * the legacy kit key (`KIT_KEY:<keyId>:<keySecret>`). API keys are the
10723
+ * recommended credential; kit keys remain accepted as the legacy path.
10724
+ *
10725
+ * @remarks
10726
+ * This is a local pre-flight check, not the authority — the Stablecoin Service
10727
+ * validates the credential and answers 401 when it rejects one. The prefix list
10728
+ * is therefore deliberately permissive: a valid key carrying a prefix this SDK
10729
+ * has not been taught about should reach the service and be judged there rather
10730
+ * than be refused locally, since refusing locally is indistinguishable from an
10731
+ * outage to the caller. Kept as the single source of truth so the pattern is
10732
+ * not restated per call site.
10733
+ *
10734
+ * @internal
10735
+ */ const API_KEY_PATTERN = new RegExp(`^(?:KIT_KEY|(?:${API_KEY_ENV_PREFIXES.join('|')})_API_KEY)` + ':[a-zA-Z0-9._-]+:[a-zA-Z0-9._-]+$');
9981
10736
 
9982
10737
  /**
9983
10738
  * Zod schema for validating stop limits.
@@ -10046,13 +10801,14 @@ const optionalChainIdentifierField = chainIdentifierField.optional();
10046
10801
  /**
10047
10802
  * Zod schema for validating API keys.
10048
10803
  *
10049
- * Validates that the API key is a valid API key format.
10804
+ * Accepts a Circle platform API key (`<ENV>_API_KEY:<keyId>:<keySecret>`) and
10805
+ * the legacy kit key (`KIT_KEY:<keyId>:<keySecret>`).
10050
10806
  *
10051
10807
  * @example
10052
10808
  * ```typescript
10053
10809
  * import { apiKeySchema } from '@core/service-client'
10054
10810
  *
10055
- * const result = apiKeySchema.safeParse('KIT_KEY:e84d2546d4e321b2ff427dc988c89503:f84d2548d4e322b2ff427fc989c87503')
10811
+ * const result = apiKeySchema.safeParse('TEST_API_KEY:e84d2546d4e321b2ff427dc988c89503:f84d2548d4e322b2ff427fc989c87503')
10056
10812
  * if (!result.success) {
10057
10813
  * console.error('Invalid API key format:', result.error.issues)
10058
10814
  * }
@@ -10060,7 +10816,7 @@ const optionalChainIdentifierField = chainIdentifierField.optional();
10060
10816
  */ const apiKeySchema = z.string({
10061
10817
  required_error: 'API key is required',
10062
10818
  invalid_type_error: 'Invalid API key format'
10063
- }).regex(/^KIT_KEY:[a-zA-Z0-9._-]+:[a-zA-Z0-9._-]+$/, 'Invalid API key format');
10819
+ }).regex(API_KEY_PATTERN, 'Invalid API key format');
10064
10820
  /**
10065
10821
  * Zod schema for platform fees configuration.
10066
10822
  *
@@ -10503,8 +11259,8 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
10503
11259
  * Validates that an API key is properly formatted for Circle Stablecoin Service.
10504
11260
  *
10505
11261
  * This function performs validation on API keys to ensure they conform to the
10506
- * expected format before making API requests. The key must follow the structure:
10507
- * `KIT_KEY:keyId:keySecret`
11262
+ * expected format before making API requests. The key must follow the structure
11263
+ * `<ENV>_API_KEY:keyId:keySecret`, or the legacy `KIT_KEY:keyId:keySecret`.
10508
11264
  *
10509
11265
  * @param apiKey - The API key to validate (can be any type for graceful handling).
10510
11266
  * @returns True if the API key is valid, false otherwise.
@@ -10512,7 +11268,8 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
10512
11268
  * @remarks
10513
11269
  * This function handles invalid inputs gracefully by returning false rather than
10514
11270
  * throwing errors. It validates:
10515
- * - The key starts with the `KIT_KEY:` prefix
11271
+ * - The key carries a recognized prefix — `<ENV>_API_KEY:` for a Circle platform
11272
+ * API key, or `KIT_KEY:` for the legacy kit key
10516
11273
  * - Contains exactly three colon-separated parts
10517
11274
  * - keyId and keySecret contain only valid characters (alphanumeric, `-`, `_`, `.`)
10518
11275
  * - keyId and keySecret are non-empty
@@ -10520,23 +11277,62 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
10520
11277
  *
10521
11278
  * Valid characters in keyId and keySecret: `a-z`, `A-Z`, `0-9`, `-`, `_`, `.`
10522
11279
  *
11280
+ * Format is checked locally only so an obviously malformed credential fails
11281
+ * before a request is made. The Stablecoin Service remains the authority on
11282
+ * whether a well-formed key is actually accepted.
11283
+ *
10523
11284
  * @example
10524
11285
  * ```typescript
10525
11286
  * import { isValidApiKey } from '@core/service-client'
10526
11287
  *
10527
11288
  * // Valid API key
10528
- * const isValid = isValidApiKey('KIT_KEY:e84d2546d4e321b2ff427dc988c89503:f84d2548d4e322b2ff427fc989c87503')
11289
+ * const isValid = isValidApiKey('TEST_API_KEY:e84d2546d4e321b2ff427dc988c89503:f84d2548d4e322b2ff427fc989c87503')
10529
11290
  * console.log(isValid) // true
10530
11291
  *
11292
+ * // Legacy kit keys remain valid
11293
+ * console.log(isValidApiKey('KIT_KEY:my-key-id:my-key-secret')) // true
11294
+ *
10531
11295
  * ```
10532
11296
  */ const isValidApiKey = (apiKey)=>{
10533
11297
  // Handle invalid input types
10534
11298
  if (typeof apiKey !== 'string') {
10535
11299
  return false;
10536
11300
  }
10537
- const apiKeyPattern = /^KIT_KEY:[a-zA-Z0-9._-]+:[a-zA-Z0-9._-]+$/;
10538
11301
  // Validate without trimming - any whitespace will cause validation to fail
10539
- return apiKeyPattern.test(apiKey);
11302
+ return API_KEY_PATTERN.test(apiKey);
11303
+ };
11304
+ /**
11305
+ * Resolve the credential to authenticate a Stablecoin Service request with.
11306
+ *
11307
+ * `apiKey` is the supported field; `kitKey` is the deprecated alias kept for
11308
+ * existing integrations. When both are supplied `apiKey` wins, so a caller
11309
+ * migrating field-by-field cannot be silently pinned to a stale credential.
11310
+ *
11311
+ * An empty-string value is treated as absent on either field. Without this, the
11312
+ * common `process.env.CIRCLE_API_KEY ?? ''` idiom (which yields `''` when the
11313
+ * variable is unset) would either shadow a working `kitKey` or, on a bare
11314
+ * `kitKey: ''`, reach downstream validation as an invalid credential instead of
11315
+ * falling through to the permissionless path.
11316
+ *
11317
+ * @param source - Object carrying either credential field, or neither.
11318
+ * @returns The credential to use, or `undefined` for the permissionless
11319
+ * (keyless) path.
11320
+ *
11321
+ * @example
11322
+ * ```typescript
11323
+ * import { resolveApiKey } from '@core/service-client'
11324
+ *
11325
+ * resolveApiKey({ apiKey: 'TEST_API_KEY:id:secret' }) // 'TEST_API_KEY:id:secret'
11326
+ * resolveApiKey({ kitKey: 'KIT_KEY:id:secret' }) // 'KIT_KEY:id:secret'
11327
+ * resolveApiKey({ apiKey: '', kitKey: 'KIT_KEY:id:secret' }) // 'KIT_KEY:id:secret'
11328
+ * resolveApiKey({ kitKey: '' }) // undefined
11329
+ * resolveApiKey({}) // undefined
11330
+ * ```
11331
+ */ const resolveApiKey = (source)=>{
11332
+ // Treat an empty-string value as absent on either field so the
11333
+ // `env ?? ''` idiom falls through to the next credential (or permissionless).
11334
+ const normalize = (value)=>value !== undefined && value !== '' ? value : undefined;
11335
+ return normalize(source.apiKey) ?? normalize(source.kitKey);
10540
11336
  };
10541
11337
 
10542
11338
  /**
@@ -11273,7 +12069,7 @@ const abiParameterSchema = z.object({
11273
12069
  */ z.object({
11274
12070
  type: z.literal('evm'),
11275
12071
  abi: abiSchema,
11276
- address: evmAddressSchema,
12072
+ address: evmAddressSchema$1,
11277
12073
  functionName: z.string({
11278
12074
  required_error: 'Function name is required',
11279
12075
  invalid_type_error: 'Function name must be a string'
@@ -11310,7 +12106,7 @@ const abiParameterSchema = z.object({
11310
12106
  * }
11311
12107
  * ```
11312
12108
  */ z.object({
11313
- address: evmAddressSchema,
12109
+ address: evmAddressSchema$1,
11314
12110
  value: z.bigint({
11315
12111
  required_error: 'Value is required for native transfers',
11316
12112
  invalid_type_error: 'Value must be a bigint'
@@ -11478,7 +12274,7 @@ z.object({
11478
12274
  signature: evmSignatureSchema,
11479
12275
  tokenInputs: z.array(z.object({
11480
12276
  permitType: z.nativeEnum(PermitType),
11481
- token: evmAddressSchema,
12277
+ token: evmAddressSchema$1,
11482
12278
  amount: z.bigint().refine((value)=>value >= 0n, {
11483
12279
  message: 'amount must be a non-negative bigint'
11484
12280
  }),
@@ -11898,7 +12694,7 @@ const optionalSwapChainIdentifierField = swapChainIdentifierField.optional();
11898
12694
  /**
11899
12695
  * Fee recipient address (required).
11900
12696
  * Must be a valid EVM address or Solana address.
11901
- */ recipientAddress: z.string().refine((value)=>evmAddressSchema.safeParse(value).success || solanaAddressSchema.safeParse(value).success, {
12697
+ */ recipientAddress: z.string().refine((value)=>evmAddressSchema$1.safeParse(value).success || solanaAddressSchema.safeParse(value).success, {
11902
12698
  message: 'recipientAddress must be a valid blockchain address: EVM (0x + 40 hex chars) or Solana (base58, 32-44 chars)'
11903
12699
  })
11904
12700
  }).strict();
@@ -11910,7 +12706,8 @@ const optionalSwapChainIdentifierField = swapChainIdentifierField.optional();
11910
12706
  * - slippageBps: Optional positive number for slippage tolerance
11911
12707
  * - stopLimit: Optional decimal string for minimum output
11912
12708
  * - customFee: Optional fee configuration
11913
- * - kitKey: Optional string identifier
12709
+ * - apiKey: Optional credential string
12710
+ * - kitKey: Optional credential string (deprecated alias for apiKey)
11914
12711
  */ const swapConfigSchema = z.object({
11915
12712
  allowanceStrategy: allowanceStrategySchema.optional(),
11916
12713
  slippageBps: z.number().int().min(0).optional(),
@@ -11920,11 +12717,12 @@ const optionalSwapChainIdentifierField = swapChainIdentifierField.optional();
11920
12717
  attributeName: 'stopLimit'
11921
12718
  })(z.string())).optional(),
11922
12719
  customFee: swapCustomFeeSchema.optional(),
12720
+ apiKey: z.string().optional(),
11923
12721
  kitKey: z.string().optional()
11924
12722
  });
11925
12723
  const swapDestinationSchema = z.object({
11926
12724
  chain: optionalSwapChainIdentifierField,
11927
- recipientAddress: z.string().refine((value)=>evmAddressSchema.safeParse(value).success || solanaAddressSchema.safeParse(value).success, {
12725
+ recipientAddress: z.string().refine((value)=>evmAddressSchema$1.safeParse(value).success || solanaAddressSchema.safeParse(value).success, {
11928
12726
  message: 'recipientAddress must be a valid blockchain address: EVM (0x + 40 hex chars) or Solana (base58, 32-44 chars)'
11929
12727
  }).optional()
11930
12728
  }).strict();
@@ -13357,7 +14155,7 @@ new Set(Object.values(Blockchain));
13357
14155
  registerKit(`${pkg$2.name}/${pkg$2.version}`);
13358
14156
 
13359
14157
  var name$1 = "@circle-fin/earn-kit";
13360
- var version$1 = "1.5.1";
14158
+ var version$1 = "1.6.1";
13361
14159
  var pkg$1 = {
13362
14160
  name: name$1,
13363
14161
  version: version$1};
@@ -13573,7 +14371,7 @@ function toSdkChain(chain) {
13573
14371
  *
13574
14372
  * @internal
13575
14373
  */ function assertHexAddress(field, value, message = `${field} must be a 0x-prefixed 20-byte hex address`) {
13576
- const result = evmAddressSchema.safeParse(value);
14374
+ const result = evmAddressSchema$1.safeParse(value);
13577
14375
  if (!result.success) {
13578
14376
  throw createValidationFailedError(field, value, message);
13579
14377
  }
@@ -15221,7 +16019,7 @@ const EARN_OPERATIONS = new Set([
15221
16019
  // Store the original service params non-enumerably. `retry()` reads them by
15222
16020
  // direct property access (`trace.params`), but JSON.stringify, console.log,
15223
16021
  // and telemetry serializers skip non-enumerable properties — so a
15224
- // permissioned call's `config.kitKey` (a `KIT_KEY:<id>:<secret>` value) and
16022
+ // permissioned call's `config.apiKey` (a credential value) and
15225
16023
  // the in-memory adapter never leak through a logged error. defineProperty
15226
16024
  // also redefines any enumerable `params` an upstream trace may have carried.
15227
16025
  Object.defineProperty(trace, 'params', {
@@ -15292,7 +16090,7 @@ function isNonNegativeBigIntLike(value) {
15292
16090
  }
15293
16091
  }
15294
16092
  const hexSignatureSchema = evmSignatureSchema;
15295
- const hexAddressSchema = evmAddressSchema;
16093
+ const hexAddressSchema = evmAddressSchema$1;
15296
16094
  // '0x' prefix + 32 bytes * 2 hex chars.
15297
16095
  const BYTES32_HEX_LENGTH = 66;
15298
16096
  const bridgeFeeTokenSchema = hexAddressSchema;
@@ -16261,7 +17059,7 @@ const bridgeDepositPrepareReviewSchema = z.object({
16261
17059
  }
16262
17060
 
16263
17061
  var name = "@circle-fin/provider-earn-service";
16264
- var version = "1.4.1";
17062
+ var version = "1.5.1";
16265
17063
  var pkg = {
16266
17064
  name: name,
16267
17065
  version: version};
@@ -16323,10 +17121,12 @@ var pkg = {
16323
17121
  *
16324
17122
  * @internal
16325
17123
  */ function buildConfig(serviceConfig) {
16326
- // The kit key is a server-only secret. Reject it in the browser so it cannot
16327
- // leak into a client bundle (no-op in Node.js). Keyless usage stays allowed.
16328
- if (serviceConfig?.kitKey !== undefined && isBrowserEnvironment()) {
16329
- throw createValidationFailedError('kitKey', '[redacted]', 'kitKey must not be provided in a browser environment — it is a server-only secret. Run EarnKit operations that use a kit key on your server, or omit kitKey to use the permissionless (keyless) client path');
17124
+ const apiKey = resolveApiKey(serviceConfig ?? {});
17125
+ // The credential is a server-only secret. Reject it in the browser so it
17126
+ // cannot leak into a client bundle (no-op in Node.js). Keyless usage stays
17127
+ // allowed.
17128
+ if (apiKey !== undefined && isBrowserEnvironment()) {
17129
+ throw createValidationFailedError('apiKey', '[redacted]', 'apiKey must not be provided in a browser environment — it is a server-only secret. Run EarnKit operations that use an API key on your server, or omit apiKey (and the legacy kitKey) to use the permissionless (keyless) client path');
16330
17130
  }
16331
17131
  const baseUrl = serviceConfig?.baseUrl ?? EARN_SERVICE_BASE_URL;
16332
17132
  // The API CORS policy does not allow this custom header. Keep the existing
@@ -16335,7 +17135,7 @@ var pkg = {
16335
17135
  const sdkVersionHeader = isNodeEnvironment() ? {
16336
17136
  [SDK_VERSION_HEADER]: resolveSdkVersionHeader()
16337
17137
  } : {};
16338
- if (serviceConfig?.kitKey === undefined) {
17138
+ if (apiKey === undefined) {
16339
17139
  return {
16340
17140
  pollingConfig: {
16341
17141
  ...DEFAULT_CONFIG,
@@ -16347,11 +17147,11 @@ var pkg = {
16347
17147
  baseUrl
16348
17148
  };
16349
17149
  }
16350
- if (!isValidApiKey(serviceConfig.kitKey)) {
17150
+ if (!isValidApiKey(apiKey)) {
16351
17151
  throw new KitError({
16352
17152
  ...InputError.VALIDATION_FAILED,
16353
17153
  recoverability: 'FATAL',
16354
- message: 'Invalid kitKey format. Expected KIT_KEY:<keyId>:<keySecret>.'
17154
+ message: 'Invalid apiKey format. Expected <ENV>_API_KEY:<keyId>:<keySecret> (for example TEST_API_KEY:...), or a legacy KIT_KEY:<keyId>:<keySecret>.'
16355
17155
  });
16356
17156
  }
16357
17157
  return {
@@ -16360,7 +17160,7 @@ var pkg = {
16360
17160
  headers: {
16361
17161
  ...DEFAULT_CONFIG.headers,
16362
17162
  ...sdkVersionHeader,
16363
- Authorization: `Bearer ${serviceConfig.kitKey}`
17163
+ Authorization: `Bearer ${apiKey}`
16364
17164
  }
16365
17165
  },
16366
17166
  baseUrl
@@ -17667,9 +18467,9 @@ function finishElapsedWait(lastStatus, lastError) {
17667
18467
  * // Permissionless mode
17668
18468
  * const provider = new EarnServiceProvider()
17669
18469
  *
17670
- * // Permissioned mode with Kit Key
18470
+ * // Permissioned mode with an API key
17671
18471
  * const provider = new EarnServiceProvider({
17672
- * kitKey: 'KIT_KEY:keyId:keySecret',
18472
+ * apiKey: 'TEST_API_KEY:keyId:keySecret',
17673
18473
  * })
17674
18474
  *
17675
18475
  * // Custom base URL for testing
@@ -18896,7 +19696,7 @@ function findProvider(context, chain, operation = 'earn') {
18896
19696
  * fast instead of round-tripping to the service.
18897
19697
  *
18898
19698
  * @internal
18899
- */ 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');
19699
+ */ 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');
18900
19700
  /**
18901
19701
  * Schema for the adapter context within earn operations.
18902
19702
  *
@@ -18928,19 +19728,39 @@ const sourceAdapterContextSchema = z.object({
18928
19728
  /**
18929
19729
  * Schema for the EarnConfig options.
18930
19730
  *
18931
- * Validate the optional Kit Key field using the standard `apiKeySchema`
18932
- * format (`KIT_KEY:<keyId>:<keySecret>`). When omitted, the SDK
18933
- * operates in permissionless mode. `baseUrl` overrides the Earn Service
18934
- * endpoint (e.g. staging); `batchTransactions: false` opts out of atomic
18935
- * batched execution. Both are forwarded to the provider, so this `.strict()`
18936
- * schema must accept them or a valid config object is rejected.
19731
+ * Validate the *resolved* credential using the standard `apiKeySchema` format
19732
+ * (`<ENV>_API_KEY:<keyId>:<keySecret>`, or a legacy
19733
+ * `KIT_KEY:<keyId>:<keySecret>`). `apiKey` takes precedence over the deprecated
19734
+ * `kitKey`, so a malformed `kitKey` that is being ignored must not fail a config
19735
+ * that supplies a valid `apiKey` (and vice versa) only the credential that
19736
+ * would actually be sent is format-checked. When neither is supplied the SDK
19737
+ * operates in permissionless mode. `baseUrl` overrides the Earn Service endpoint
19738
+ * (e.g. staging); `batchTransactions: false` opts out of atomic batched
19739
+ * execution. All are forwarded to the provider, so this `.strict()` schema must
19740
+ * accept them or a valid config object is rejected.
18937
19741
  *
18938
19742
  * @internal
18939
19743
  */ const earnConfigSchema = z.object({
18940
- kitKey: apiKeySchema.optional(),
19744
+ apiKey: z.string().optional(),
19745
+ kitKey: z.string().optional(),
18941
19746
  baseUrl: z.string().optional(),
18942
19747
  batchTransactions: z.boolean().optional()
18943
- }).strict();
19748
+ }).strict().superRefine((config, ctx)=>{
19749
+ const credential = resolveApiKey(config);
19750
+ if (credential === undefined) {
19751
+ return;
19752
+ }
19753
+ const result = apiKeySchema.safeParse(credential);
19754
+ if (!result.success) {
19755
+ ctx.addIssue({
19756
+ code: z.ZodIssueCode.custom,
19757
+ path: [
19758
+ credential === config.apiKey ? 'apiKey' : 'kitKey'
19759
+ ],
19760
+ message: result.error.issues[0]?.message ?? 'Invalid API key format'
19761
+ });
19762
+ }
19763
+ });
18944
19764
  /**
18945
19765
  * Canonical decimal form: a leading digit with no leading zeros (a single
18946
19766
  * '0' is only allowed immediately before the decimal point). Rejects the
@@ -19012,7 +19832,7 @@ const sourceAdapterContextSchema = z.object({
19012
19832
  * currently supports EVM vault addresses on Arc Testnet.
19013
19833
  *
19014
19834
  * @internal
19015
- */ const vaultAddressSchema = evmAddressSchema.refine(isValidEip55Checksum, 'address has an invalid EIP-55 checksum');
19835
+ */ const vaultAddressSchema = evmAddressSchema$1.refine(isValidEip55Checksum, 'address has an invalid EIP-55 checksum');
19016
19836
  /**
19017
19837
  * Validation schema for VaultQuery.
19018
19838
  *
@@ -19287,7 +20107,7 @@ const sameChainGetDepositQuoteParamsSchema = z.object({
19287
20107
  const crossChainGetDepositQuoteParamsSchema = z.object({
19288
20108
  from: sourceAdapterContextSchema,
19289
20109
  chain: earnBridgeDestinationChainIdentifierSchema,
19290
- address: evmAddressSchema,
20110
+ address: evmAddressSchema$1,
19291
20111
  vaultAddress: vaultAddressSchema,
19292
20112
  amount: amountSchema,
19293
20113
  transferSpeed: z.enum([