@circle-fin/app-kit 1.12.0 → 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/CHANGELOG.md +73 -0
- package/README.md +31 -12
- package/bridge.cjs +3893 -1714
- package/bridge.d.cts +186 -18
- package/bridge.d.mts +186 -18
- package/bridge.d.ts +186 -18
- package/bridge.mjs +3895 -1716
- package/chains.cjs +134 -0
- package/chains.d.cts +126 -1
- package/chains.d.mts +126 -1
- package/chains.d.ts +126 -1
- package/chains.mjs +133 -1
- package/context.d.cts +185 -17
- package/context.d.mts +185 -17
- package/context.d.ts +185 -17
- package/earn.cjs +651 -85
- package/earn.d.cts +185 -17
- package/earn.d.mts +185 -17
- package/earn.d.ts +185 -17
- package/earn.mjs +651 -85
- package/estimateBridge.cjs +3892 -1713
- package/estimateBridge.d.cts +295 -18
- package/estimateBridge.d.mts +295 -18
- package/estimateBridge.d.ts +295 -18
- package/estimateBridge.mjs +3894 -1715
- package/estimateSwap.cjs +748 -136
- package/estimateSwap.d.cts +185 -17
- package/estimateSwap.d.mts +185 -17
- package/estimateSwap.d.ts +185 -17
- package/estimateSwap.mjs +748 -136
- package/index.cjs +3806 -1952
- package/index.d.cts +2775 -1874
- package/index.d.mts +2775 -1874
- package/index.d.ts +2775 -1874
- package/index.mjs +3808 -1954
- package/package.json +6 -6
- package/swap.cjs +748 -136
- package/swap.d.cts +192 -18
- package/swap.d.mts +192 -18
- package/swap.d.ts +192 -18
- package/swap.mjs +748 -136
- package/unifiedBalance.cjs +509 -87
- package/unifiedBalance.d.cts +206 -33
- package/unifiedBalance.d.mts +206 -33
- package/unifiedBalance.d.ts +206 -33
- package/unifiedBalance.mjs +509 -87
package/unifiedBalance.cjs
CHANGED
|
@@ -664,6 +664,11 @@ class KitError extends Error {
|
|
|
664
664
|
name: 'INPUT_UNSUPPORTED_TOKEN',
|
|
665
665
|
type: 'INPUT'
|
|
666
666
|
},
|
|
667
|
+
/** Action not supported by this adapter / ecosystem */ UNSUPPORTED_ACTION: {
|
|
668
|
+
code: 1008,
|
|
669
|
+
name: 'INPUT_UNSUPPORTED_ACTION',
|
|
670
|
+
type: 'INPUT'
|
|
671
|
+
},
|
|
667
672
|
/** No route satisfies the slippage or minimum-output constraint */ SLIPPAGE_CONSTRAINT_NOT_MET: {
|
|
668
673
|
code: 1009,
|
|
669
674
|
name: 'INPUT_SLIPPAGE_CONSTRAINT_NOT_MET',
|
|
@@ -2298,6 +2303,8 @@ class KitError extends Error {
|
|
|
2298
2303
|
Blockchain["Optimism_Sepolia"] = "Optimism_Sepolia";
|
|
2299
2304
|
Blockchain["Pharos"] = "Pharos";
|
|
2300
2305
|
Blockchain["Pharos_Testnet"] = "Pharos_Testnet";
|
|
2306
|
+
Blockchain["Plasma"] = "Plasma";
|
|
2307
|
+
Blockchain["Plasma_Testnet"] = "Plasma_Testnet";
|
|
2301
2308
|
Blockchain["Polkadot_Asset_Hub"] = "Polkadot_Asset_Hub";
|
|
2302
2309
|
Blockchain["Polkadot_Westmint"] = "Polkadot_Westmint";
|
|
2303
2310
|
Blockchain["Plume"] = "Plume";
|
|
@@ -2367,6 +2374,7 @@ var BridgeChain;
|
|
|
2367
2374
|
BridgeChain["Morph"] = "Morph";
|
|
2368
2375
|
BridgeChain["Optimism"] = "Optimism";
|
|
2369
2376
|
BridgeChain["Pharos"] = "Pharos";
|
|
2377
|
+
BridgeChain["Plasma"] = "Plasma";
|
|
2370
2378
|
BridgeChain["Plume"] = "Plume";
|
|
2371
2379
|
BridgeChain["Polygon"] = "Polygon";
|
|
2372
2380
|
BridgeChain["Sei"] = "Sei";
|
|
@@ -2393,6 +2401,7 @@ var BridgeChain;
|
|
|
2393
2401
|
BridgeChain["Morph_Testnet"] = "Morph_Testnet";
|
|
2394
2402
|
BridgeChain["Optimism_Sepolia"] = "Optimism_Sepolia";
|
|
2395
2403
|
BridgeChain["Pharos_Testnet"] = "Pharos_Testnet";
|
|
2404
|
+
BridgeChain["Plasma_Testnet"] = "Plasma_Testnet";
|
|
2396
2405
|
BridgeChain["Plume_Testnet"] = "Plume_Testnet";
|
|
2397
2406
|
BridgeChain["Polygon_Amoy_Testnet"] = "Polygon_Amoy_Testnet";
|
|
2398
2407
|
BridgeChain["Sei_Testnet"] = "Sei_Testnet";
|
|
@@ -2839,6 +2848,8 @@ var EarnChain;
|
|
|
2839
2848
|
* This program handles minting operations for Gateway transactions
|
|
2840
2849
|
* on Solana devnet.
|
|
2841
2850
|
*/ const GATEWAY_MINTER_SOLANA_DEVNET = 'GATEmKK2ECL1brEngQZWCgMWPbvrEYqsV6u29dAaHavr';
|
|
2851
|
+
/** TokenMessengerWithFees address shared by enabled EVM mainnet sources. */ const TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET = '0x71f54F818671cD0D7ea140Da213e5C8b5C92a408';
|
|
2852
|
+
/** TokenMessengerWithFees address shared by enabled EVM testnet sources. */ const TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET = '0x8745D906D67C346E5eb1aEEED38Eb87F34DF0C0A';
|
|
2842
2853
|
/**
|
|
2843
2854
|
* Circle's fee recipient address for EVM chains.
|
|
2844
2855
|
*
|
|
@@ -2886,6 +2897,7 @@ var EarnChain;
|
|
|
2886
2897
|
v2: {
|
|
2887
2898
|
type: 'split',
|
|
2888
2899
|
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
2900
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
2889
2901
|
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
2890
2902
|
confirmations: 1,
|
|
2891
2903
|
fastConfirmations: 1
|
|
@@ -2953,6 +2965,7 @@ var EarnChain;
|
|
|
2953
2965
|
v2: {
|
|
2954
2966
|
type: 'split',
|
|
2955
2967
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
2968
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
2956
2969
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
2957
2970
|
confirmations: 65,
|
|
2958
2971
|
fastConfirmations: 1
|
|
@@ -3017,6 +3030,7 @@ var EarnChain;
|
|
|
3017
3030
|
v2: {
|
|
3018
3031
|
type: 'split',
|
|
3019
3032
|
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
3033
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
3020
3034
|
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
3021
3035
|
confirmations: 65,
|
|
3022
3036
|
fastConfirmations: 1
|
|
@@ -3081,6 +3095,7 @@ var EarnChain;
|
|
|
3081
3095
|
v2: {
|
|
3082
3096
|
type: 'split',
|
|
3083
3097
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
3098
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
3084
3099
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
3085
3100
|
confirmations: 1,
|
|
3086
3101
|
fastConfirmations: 1
|
|
@@ -3142,6 +3157,7 @@ var EarnChain;
|
|
|
3142
3157
|
v2: {
|
|
3143
3158
|
type: 'split',
|
|
3144
3159
|
tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
|
|
3160
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
3145
3161
|
messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
|
|
3146
3162
|
confirmations: 1,
|
|
3147
3163
|
fastConfirmations: 1
|
|
@@ -3209,6 +3225,7 @@ var EarnChain;
|
|
|
3209
3225
|
v2: {
|
|
3210
3226
|
type: 'split',
|
|
3211
3227
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
3228
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
3212
3229
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
3213
3230
|
confirmations: 65,
|
|
3214
3231
|
fastConfirmations: 1
|
|
@@ -3273,6 +3290,7 @@ var EarnChain;
|
|
|
3273
3290
|
v2: {
|
|
3274
3291
|
type: 'split',
|
|
3275
3292
|
tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
|
|
3293
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
3276
3294
|
messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
|
|
3277
3295
|
confirmations: 65,
|
|
3278
3296
|
fastConfirmations: 1
|
|
@@ -3383,6 +3401,7 @@ var EarnChain;
|
|
|
3383
3401
|
v2: {
|
|
3384
3402
|
type: 'split',
|
|
3385
3403
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
3404
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
3386
3405
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
3387
3406
|
confirmations: 65,
|
|
3388
3407
|
fastConfirmations: 1
|
|
@@ -3427,6 +3446,7 @@ var EarnChain;
|
|
|
3427
3446
|
v2: {
|
|
3428
3447
|
type: 'split',
|
|
3429
3448
|
tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
|
|
3449
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
3430
3450
|
messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
|
|
3431
3451
|
confirmations: 65,
|
|
3432
3452
|
fastConfirmations: 1
|
|
@@ -3658,6 +3678,7 @@ var EarnChain;
|
|
|
3658
3678
|
v2: {
|
|
3659
3679
|
type: 'split',
|
|
3660
3680
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
3681
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
3661
3682
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
3662
3683
|
confirmations: 65,
|
|
3663
3684
|
fastConfirmations: 2
|
|
@@ -3722,6 +3743,7 @@ var EarnChain;
|
|
|
3722
3743
|
v2: {
|
|
3723
3744
|
type: 'split',
|
|
3724
3745
|
tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
|
|
3746
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
3725
3747
|
messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
|
|
3726
3748
|
confirmations: 65,
|
|
3727
3749
|
fastConfirmations: 2
|
|
@@ -3832,6 +3854,7 @@ var EarnChain;
|
|
|
3832
3854
|
v2: {
|
|
3833
3855
|
type: 'split',
|
|
3834
3856
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
3857
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
3835
3858
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
3836
3859
|
confirmations: 1,
|
|
3837
3860
|
fastConfirmations: 1
|
|
@@ -3891,6 +3914,7 @@ var EarnChain;
|
|
|
3891
3914
|
v2: {
|
|
3892
3915
|
type: 'split',
|
|
3893
3916
|
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
3917
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
3894
3918
|
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
3895
3919
|
confirmations: 1,
|
|
3896
3920
|
fastConfirmations: 1
|
|
@@ -4045,6 +4069,7 @@ var EarnChain;
|
|
|
4045
4069
|
v2: {
|
|
4046
4070
|
type: 'split',
|
|
4047
4071
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
4072
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
4048
4073
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
4049
4074
|
confirmations: 65,
|
|
4050
4075
|
fastConfirmations: 1
|
|
@@ -4092,6 +4117,7 @@ var EarnChain;
|
|
|
4092
4117
|
v2: {
|
|
4093
4118
|
type: 'split',
|
|
4094
4119
|
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
4120
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
4095
4121
|
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
4096
4122
|
confirmations: 65,
|
|
4097
4123
|
fastConfirmations: 1
|
|
@@ -4136,6 +4162,7 @@ var EarnChain;
|
|
|
4136
4162
|
v2: {
|
|
4137
4163
|
type: 'split',
|
|
4138
4164
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
4165
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
4139
4166
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
4140
4167
|
confirmations: 1,
|
|
4141
4168
|
fastConfirmations: 1
|
|
@@ -4181,6 +4208,7 @@ var EarnChain;
|
|
|
4181
4208
|
v2: {
|
|
4182
4209
|
type: 'split',
|
|
4183
4210
|
tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
|
|
4211
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
4184
4212
|
messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
|
|
4185
4213
|
confirmations: 1,
|
|
4186
4214
|
fastConfirmations: 1
|
|
@@ -4227,6 +4255,7 @@ var EarnChain;
|
|
|
4227
4255
|
v2: {
|
|
4228
4256
|
type: 'split',
|
|
4229
4257
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
4258
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
4230
4259
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
4231
4260
|
confirmations: 1,
|
|
4232
4261
|
fastConfirmations: 1
|
|
@@ -4540,6 +4569,7 @@ var EarnChain;
|
|
|
4540
4569
|
v2: {
|
|
4541
4570
|
type: 'split',
|
|
4542
4571
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
4572
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
4543
4573
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
4544
4574
|
confirmations: 65,
|
|
4545
4575
|
fastConfirmations: 1
|
|
@@ -4604,6 +4634,7 @@ var EarnChain;
|
|
|
4604
4634
|
v2: {
|
|
4605
4635
|
type: 'split',
|
|
4606
4636
|
tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
|
|
4637
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
4607
4638
|
messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
|
|
4608
4639
|
confirmations: 65,
|
|
4609
4640
|
fastConfirmations: 1
|
|
@@ -4724,6 +4755,98 @@ var EarnChain;
|
|
|
4724
4755
|
}
|
|
4725
4756
|
});
|
|
4726
4757
|
|
|
4758
|
+
/**
|
|
4759
|
+
* Plasma Mainnet chain definition
|
|
4760
|
+
* @remarks
|
|
4761
|
+
* This represents the official production network for the Plasma blockchain.
|
|
4762
|
+
* Plasma is an EVM-equivalent Layer 1 blockchain purpose-built for global
|
|
4763
|
+
* stablecoin payments, with deterministic BFT finality (PlasmaBFT/Fast-HotStuff).
|
|
4764
|
+
*/ const Plasma = defineChain({
|
|
4765
|
+
type: 'evm',
|
|
4766
|
+
chain: Blockchain.Plasma,
|
|
4767
|
+
name: 'Plasma',
|
|
4768
|
+
title: 'Plasma Mainnet',
|
|
4769
|
+
nativeCurrency: {
|
|
4770
|
+
name: 'Plasma',
|
|
4771
|
+
symbol: 'XPL',
|
|
4772
|
+
decimals: 18
|
|
4773
|
+
},
|
|
4774
|
+
chainId: 9745,
|
|
4775
|
+
isTestnet: false,
|
|
4776
|
+
explorerUrl: 'https://plasmascan.to/tx/{hash}',
|
|
4777
|
+
rpcEndpoints: [
|
|
4778
|
+
'https://rpc.plasma.to'
|
|
4779
|
+
],
|
|
4780
|
+
eurcAddress: '0x3EE196E78d4d4248b849B8E1C7F44C5457FAFD2C',
|
|
4781
|
+
usdcAddress: '0x2d661C89D812261039AF9764eceaAee884f5F67F',
|
|
4782
|
+
usdtAddress: null,
|
|
4783
|
+
cctp: {
|
|
4784
|
+
domain: 33,
|
|
4785
|
+
contracts: {
|
|
4786
|
+
v2: {
|
|
4787
|
+
type: 'split',
|
|
4788
|
+
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
4789
|
+
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
4790
|
+
confirmations: 3,
|
|
4791
|
+
fastConfirmations: 1
|
|
4792
|
+
}
|
|
4793
|
+
},
|
|
4794
|
+
forwarderSupported: {
|
|
4795
|
+
source: false,
|
|
4796
|
+
destination: false
|
|
4797
|
+
}
|
|
4798
|
+
},
|
|
4799
|
+
kitContracts: {
|
|
4800
|
+
bridge: BRIDGE_CONTRACT_EVM_MAINNET
|
|
4801
|
+
}
|
|
4802
|
+
});
|
|
4803
|
+
|
|
4804
|
+
/**
|
|
4805
|
+
* Plasma Testnet chain definition
|
|
4806
|
+
* @remarks
|
|
4807
|
+
* This represents the official test network for the Plasma blockchain.
|
|
4808
|
+
* Plasma is an EVM-equivalent Layer 1 blockchain purpose-built for global
|
|
4809
|
+
* stablecoin payments, with deterministic BFT finality (PlasmaBFT/Fast-HotStuff).
|
|
4810
|
+
*/ const PlasmaTestnet = defineChain({
|
|
4811
|
+
type: 'evm',
|
|
4812
|
+
chain: Blockchain.Plasma_Testnet,
|
|
4813
|
+
name: 'Plasma Testnet',
|
|
4814
|
+
title: 'Plasma Testnet',
|
|
4815
|
+
nativeCurrency: {
|
|
4816
|
+
name: 'Plasma',
|
|
4817
|
+
symbol: 'XPL',
|
|
4818
|
+
decimals: 18
|
|
4819
|
+
},
|
|
4820
|
+
chainId: 9746,
|
|
4821
|
+
isTestnet: true,
|
|
4822
|
+
explorerUrl: 'https://testnet.plasmascan.to/tx/{hash}',
|
|
4823
|
+
rpcEndpoints: [
|
|
4824
|
+
'https://testnet-rpc.plasma.to'
|
|
4825
|
+
],
|
|
4826
|
+
eurcAddress: '0x98AfA0F93Dd993B736399f9074eDcEBD1985A330',
|
|
4827
|
+
usdcAddress: '0xE67Fb267022cBA8064Dd388CC2FED724F3120D9D',
|
|
4828
|
+
usdtAddress: null,
|
|
4829
|
+
cctp: {
|
|
4830
|
+
domain: 33,
|
|
4831
|
+
contracts: {
|
|
4832
|
+
v2: {
|
|
4833
|
+
type: 'split',
|
|
4834
|
+
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
4835
|
+
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
4836
|
+
confirmations: 3,
|
|
4837
|
+
fastConfirmations: 1
|
|
4838
|
+
}
|
|
4839
|
+
},
|
|
4840
|
+
forwarderSupported: {
|
|
4841
|
+
source: false,
|
|
4842
|
+
destination: false
|
|
4843
|
+
}
|
|
4844
|
+
},
|
|
4845
|
+
kitContracts: {
|
|
4846
|
+
bridge: BRIDGE_CONTRACT_EVM_TESTNET
|
|
4847
|
+
}
|
|
4848
|
+
});
|
|
4849
|
+
|
|
4727
4850
|
/**
|
|
4728
4851
|
* Plume Mainnet chain definition
|
|
4729
4852
|
* @remarks
|
|
@@ -4755,6 +4878,7 @@ var EarnChain;
|
|
|
4755
4878
|
v2: {
|
|
4756
4879
|
type: 'split',
|
|
4757
4880
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
4881
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
4758
4882
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
4759
4883
|
confirmations: 65,
|
|
4760
4884
|
fastConfirmations: 1
|
|
@@ -4801,6 +4925,7 @@ var EarnChain;
|
|
|
4801
4925
|
v2: {
|
|
4802
4926
|
type: 'split',
|
|
4803
4927
|
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
4928
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
4804
4929
|
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
4805
4930
|
confirmations: 65,
|
|
4806
4931
|
fastConfirmations: 1
|
|
@@ -4902,6 +5027,7 @@ var EarnChain;
|
|
|
4902
5027
|
v2: {
|
|
4903
5028
|
type: 'split',
|
|
4904
5029
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
5030
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
4905
5031
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
4906
5032
|
confirmations: 33,
|
|
4907
5033
|
fastConfirmations: 13
|
|
@@ -4967,6 +5093,7 @@ var EarnChain;
|
|
|
4967
5093
|
v2: {
|
|
4968
5094
|
type: 'split',
|
|
4969
5095
|
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
5096
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
4970
5097
|
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
4971
5098
|
confirmations: 33,
|
|
4972
5099
|
fastConfirmations: 13
|
|
@@ -5026,6 +5153,7 @@ var EarnChain;
|
|
|
5026
5153
|
v2: {
|
|
5027
5154
|
type: 'split',
|
|
5028
5155
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
5156
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
5029
5157
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
5030
5158
|
confirmations: 1,
|
|
5031
5159
|
fastConfirmations: 1
|
|
@@ -5085,6 +5213,7 @@ var EarnChain;
|
|
|
5085
5213
|
v2: {
|
|
5086
5214
|
type: 'split',
|
|
5087
5215
|
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
5216
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
5088
5217
|
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
5089
5218
|
confirmations: 1,
|
|
5090
5219
|
fastConfirmations: 1
|
|
@@ -5142,6 +5271,7 @@ var EarnChain;
|
|
|
5142
5271
|
v2: {
|
|
5143
5272
|
type: 'split',
|
|
5144
5273
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
5274
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
5145
5275
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
5146
5276
|
confirmations: 1,
|
|
5147
5277
|
fastConfirmations: 1
|
|
@@ -5200,6 +5330,7 @@ var EarnChain;
|
|
|
5200
5330
|
v2: {
|
|
5201
5331
|
type: 'split',
|
|
5202
5332
|
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
5333
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
5203
5334
|
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
5204
5335
|
confirmations: 1,
|
|
5205
5336
|
fastConfirmations: 1
|
|
@@ -5515,6 +5646,7 @@ var EarnChain;
|
|
|
5515
5646
|
v2: {
|
|
5516
5647
|
type: 'split',
|
|
5517
5648
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
5649
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
5518
5650
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
5519
5651
|
confirmations: 65,
|
|
5520
5652
|
fastConfirmations: 1
|
|
@@ -5579,6 +5711,7 @@ var EarnChain;
|
|
|
5579
5711
|
v2: {
|
|
5580
5712
|
type: 'split',
|
|
5581
5713
|
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
5714
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
5582
5715
|
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
5583
5716
|
confirmations: 65,
|
|
5584
5717
|
fastConfirmations: 1
|
|
@@ -5636,6 +5769,7 @@ var EarnChain;
|
|
|
5636
5769
|
v2: {
|
|
5637
5770
|
type: 'split',
|
|
5638
5771
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cF5d',
|
|
5772
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
5639
5773
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
5640
5774
|
confirmations: 65,
|
|
5641
5775
|
fastConfirmations: 1
|
|
@@ -5695,6 +5829,7 @@ var EarnChain;
|
|
|
5695
5829
|
v2: {
|
|
5696
5830
|
type: 'split',
|
|
5697
5831
|
tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
|
|
5832
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
5698
5833
|
messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
|
|
5699
5834
|
confirmations: 65,
|
|
5700
5835
|
fastConfirmations: 1
|
|
@@ -5755,6 +5890,7 @@ var EarnChain;
|
|
|
5755
5890
|
v2: {
|
|
5756
5891
|
type: 'split',
|
|
5757
5892
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
5893
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
5758
5894
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
5759
5895
|
confirmations: 3,
|
|
5760
5896
|
fastConfirmations: 3
|
|
@@ -5800,6 +5936,7 @@ var EarnChain;
|
|
|
5800
5936
|
v2: {
|
|
5801
5937
|
type: 'split',
|
|
5802
5938
|
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
5939
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
5803
5940
|
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
5804
5941
|
confirmations: 3,
|
|
5805
5942
|
fastConfirmations: 1
|
|
@@ -6010,6 +6147,8 @@ var Chains = {
|
|
|
6010
6147
|
OptimismSepolia: OptimismSepolia,
|
|
6011
6148
|
Pharos: Pharos,
|
|
6012
6149
|
PharosTestnet: PharosTestnet,
|
|
6150
|
+
Plasma: Plasma,
|
|
6151
|
+
PlasmaTestnet: PlasmaTestnet,
|
|
6013
6152
|
Plume: Plume,
|
|
6014
6153
|
PlumeTestnet: PlumeTestnet,
|
|
6015
6154
|
PolkadotAssetHub: PolkadotAssetHub,
|
|
@@ -7975,6 +8114,7 @@ function parseOrThrow(value, schema, context) {
|
|
|
7975
8114
|
[Blockchain.Noble]: 'uusdc',
|
|
7976
8115
|
[Blockchain.Optimism]: '0x0b2c639c533813f4aa9d7837caf62653d097ff85',
|
|
7977
8116
|
[Blockchain.Pharos]: '0xC879C018dB60520F4355C26eD1a6D572cdAC1815',
|
|
8117
|
+
[Blockchain.Plasma]: '0x2d661C89D812261039AF9764eceaAee884f5F67F',
|
|
7978
8118
|
[Blockchain.Plume]: '0x222365EF19F7947e5484218551B56bb3965Aa7aF',
|
|
7979
8119
|
[Blockchain.Polkadot_Asset_Hub]: '1337',
|
|
7980
8120
|
[Blockchain.Polygon]: '0x3c499c542cef5e3811e1192ce70d8cc03d5c3359',
|
|
@@ -7995,6 +8135,7 @@ function parseOrThrow(value, schema, context) {
|
|
|
7995
8135
|
[Blockchain.Arbitrum_Sepolia]: '0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d',
|
|
7996
8136
|
[Blockchain.Avalanche_Fuji]: '0x5425890298aed601595a70AB815c96711a31Bc65',
|
|
7997
8137
|
[Blockchain.Base_Sepolia]: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',
|
|
8138
|
+
[Blockchain.Celo_Alfajores_Testnet]: '0x2F25deB3848C207fc8E0c34035B3Ba7fC157602B',
|
|
7998
8139
|
[Blockchain.Codex_Testnet]: '0x6d7f141b6819C2c9CC2f818e6ad549E7Ca090F8f',
|
|
7999
8140
|
[Blockchain.Cronos_Testnet]: '0xEb33dc5fac03833e132593659e1dE7256aB59794',
|
|
8000
8141
|
[Blockchain.Edge_Testnet]: '0x2d9F7CAD728051AA35Ecdc472a14cf8cDF5CFD6B',
|
|
@@ -8010,6 +8151,7 @@ function parseOrThrow(value, schema, context) {
|
|
|
8010
8151
|
[Blockchain.Noble_Testnet]: 'uusdc',
|
|
8011
8152
|
[Blockchain.Optimism_Sepolia]: '0x5fd84259d66Cd46123540766Be93DFE6D43130D7',
|
|
8012
8153
|
[Blockchain.Pharos_Testnet]: '0xcfC8330f4BCAB529c625D12781b1C19466A9Fc8B',
|
|
8154
|
+
[Blockchain.Plasma_Testnet]: '0xE67Fb267022cBA8064Dd388CC2FED724F3120D9D',
|
|
8013
8155
|
[Blockchain.Plume_Testnet]: '0xcB5f30e335672893c7eb944B374c196392C19D18',
|
|
8014
8156
|
[Blockchain.Polkadot_Westmint]: '31337',
|
|
8015
8157
|
[Blockchain.Polygon_Amoy_Testnet]: '0x41e94eb019c0762f9bfcf9fb1e58725bfb0e7582',
|
|
@@ -8072,6 +8214,7 @@ function parseOrThrow(value, schema, context) {
|
|
|
8072
8214
|
[Blockchain.Base]: '0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42',
|
|
8073
8215
|
[Blockchain.Cronos]: '0xA6dE01a2d62C6B5f3525d768f34d276652C554c8',
|
|
8074
8216
|
[Blockchain.Ethereum]: '0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c',
|
|
8217
|
+
[Blockchain.Plasma]: '0x3EE196E78d4d4248b849B8E1C7F44C5457FAFD2C',
|
|
8075
8218
|
[Blockchain.Solana]: 'HzwqbKZw8HxMN6bF2yFZNrht3c2iXXzpKcFu7uBEDKtr',
|
|
8076
8219
|
[Blockchain.World_Chain]: '0x1C60ba0A0eD1019e8Eb035E6daF4155A5cE2380B',
|
|
8077
8220
|
// =========================================================================
|
|
@@ -8080,7 +8223,8 @@ function parseOrThrow(value, schema, context) {
|
|
|
8080
8223
|
[Blockchain.Arc_Testnet]: '0x89B50855Aa3bE2F677cD6303Cec089B5F319D72a',
|
|
8081
8224
|
[Blockchain.Base_Sepolia]: '0x808456652fdb597867f38412077A9182bf77359F',
|
|
8082
8225
|
[Blockchain.Cronos_Testnet]: '0x31f7538adb53cF16350e6B0c89d03D91b7D12c46',
|
|
8083
|
-
[Blockchain.Ethereum_Sepolia]: '0x08210F9170F89Ab7658F0B5E3fF39b0E03C594D4'
|
|
8226
|
+
[Blockchain.Ethereum_Sepolia]: '0x08210F9170F89Ab7658F0B5E3fF39b0E03C594D4',
|
|
8227
|
+
[Blockchain.Plasma_Testnet]: '0x98AfA0F93Dd993B736399f9074eDcEBD1985A330'
|
|
8084
8228
|
}
|
|
8085
8229
|
};
|
|
8086
8230
|
|
|
@@ -8887,7 +9031,7 @@ function parseOrThrow(value, schema, context) {
|
|
|
8887
9031
|
}
|
|
8888
9032
|
|
|
8889
9033
|
var name = "@circle-fin/unified-balance-kit";
|
|
8890
|
-
var version = "1.
|
|
9034
|
+
var version = "1.5.0";
|
|
8891
9035
|
var pkg = {
|
|
8892
9036
|
name: name,
|
|
8893
9037
|
version: version};
|
|
@@ -9170,6 +9314,110 @@ var pkg = {
|
|
|
9170
9314
|
* ```
|
|
9171
9315
|
*/ const USDC_DECIMALS$1 = 6;
|
|
9172
9316
|
|
|
9317
|
+
/**
|
|
9318
|
+
* Canonical list of actions that do not prepare or submit transactions.
|
|
9319
|
+
*
|
|
9320
|
+
* @internal
|
|
9321
|
+
*/ const READ_ACTION_KEYS = [
|
|
9322
|
+
'token.allowance',
|
|
9323
|
+
'token.balanceOf',
|
|
9324
|
+
'token.name',
|
|
9325
|
+
'native.balanceOf',
|
|
9326
|
+
'usdc.allowance',
|
|
9327
|
+
'usdc.balanceOf',
|
|
9328
|
+
'usdc.name',
|
|
9329
|
+
'gateway.v1.isDelegate',
|
|
9330
|
+
'gateway.v1.withdrawingBalance',
|
|
9331
|
+
'gateway.v1.withdrawalBlock',
|
|
9332
|
+
'gateway.v1.signBurnIntents'
|
|
9333
|
+
];
|
|
9334
|
+
const READ_ACTION_KEY_SET = new Set(READ_ACTION_KEYS);
|
|
9335
|
+
/**
|
|
9336
|
+
* Check whether a runtime value identifies a read action.
|
|
9337
|
+
*
|
|
9338
|
+
* @param action - The value to classify.
|
|
9339
|
+
* @returns Whether the value is a registered read-action key.
|
|
9340
|
+
*
|
|
9341
|
+
* @example
|
|
9342
|
+
* ```typescript
|
|
9343
|
+
* import { isReadActionKey } from '@core/adapter'
|
|
9344
|
+
*
|
|
9345
|
+
* if (isReadActionKey(value)) {
|
|
9346
|
+
* await adapter.readAction(value, params, context)
|
|
9347
|
+
* }
|
|
9348
|
+
* ```
|
|
9349
|
+
*
|
|
9350
|
+
* @internal
|
|
9351
|
+
*/ function isReadActionKey(action) {
|
|
9352
|
+
return typeof action === 'string' && READ_ACTION_KEY_SET.has(action);
|
|
9353
|
+
}
|
|
9354
|
+
|
|
9355
|
+
/**
|
|
9356
|
+
* Create the standard error for a missing or non-read action.
|
|
9357
|
+
*
|
|
9358
|
+
* @param action - The unsupported action value.
|
|
9359
|
+
* @returns A fatal unsupported-action error.
|
|
9360
|
+
*
|
|
9361
|
+
* @internal
|
|
9362
|
+
*/ function createUnsupportedReadActionError(action) {
|
|
9363
|
+
return new KitError({
|
|
9364
|
+
...InputError.UNSUPPORTED_ACTION,
|
|
9365
|
+
recoverability: 'FATAL',
|
|
9366
|
+
message: `Read action "${String(action)}" is not registered in this adapter.`
|
|
9367
|
+
});
|
|
9368
|
+
}
|
|
9369
|
+
/**
|
|
9370
|
+
* Execute a read through the adapter's dedicated read seam when available.
|
|
9371
|
+
*
|
|
9372
|
+
* @remarks
|
|
9373
|
+
* Fall back to the legacy `prepareAction().execute()` contract so providers
|
|
9374
|
+
* remain runtime-compatible with adapter versions released before `readAction`.
|
|
9375
|
+
* Consumers must upgrade their adapter package for reads to bypass custom
|
|
9376
|
+
* `prepareAction` wrappers.
|
|
9377
|
+
*
|
|
9378
|
+
* @typeParam TAdapterCapabilities - The adapter capabilities type.
|
|
9379
|
+
* @typeParam TActionKey - The read action key.
|
|
9380
|
+
* @param adapter - The adapter that owns the read action.
|
|
9381
|
+
* @param action - The read action to execute.
|
|
9382
|
+
* @param params - The parameters for the read action.
|
|
9383
|
+
* @param ctx - The operation context.
|
|
9384
|
+
* @returns The raw read-action result.
|
|
9385
|
+
* @throws {KitError} When `action` is not a supported read-action key.
|
|
9386
|
+
*
|
|
9387
|
+
* @example
|
|
9388
|
+
* ```typescript
|
|
9389
|
+
* import { executeAdapterReadAction } from '@core/adapter'
|
|
9390
|
+
* import { Ethereum } from '@core/chains'
|
|
9391
|
+
*
|
|
9392
|
+
* const allowance = await executeAdapterReadAction(
|
|
9393
|
+
* adapter,
|
|
9394
|
+
* 'token.allowance',
|
|
9395
|
+
* { tokenAddress, delegate },
|
|
9396
|
+
* { chain: Ethereum },
|
|
9397
|
+
* )
|
|
9398
|
+
* ```
|
|
9399
|
+
*
|
|
9400
|
+
* @internal
|
|
9401
|
+
*/ async function executeAdapterReadAction(adapter, action, params, ctx) {
|
|
9402
|
+
if (!isReadActionKey(action)) {
|
|
9403
|
+
throw createUnsupportedReadActionError(action);
|
|
9404
|
+
}
|
|
9405
|
+
const runtimeAdapter = adapter;
|
|
9406
|
+
if (typeof runtimeAdapter.readAction === 'function') {
|
|
9407
|
+
return runtimeAdapter.readAction(action, params, ctx);
|
|
9408
|
+
}
|
|
9409
|
+
let request;
|
|
9410
|
+
try {
|
|
9411
|
+
request = await adapter.prepareAction(action, params, ctx);
|
|
9412
|
+
} catch (error) {
|
|
9413
|
+
if (error instanceof Error && error.message === `Action ${action} is not supported`) {
|
|
9414
|
+
throw createUnsupportedReadActionError(action);
|
|
9415
|
+
}
|
|
9416
|
+
throw error;
|
|
9417
|
+
}
|
|
9418
|
+
return request.execute();
|
|
9419
|
+
}
|
|
9420
|
+
|
|
9173
9421
|
/**
|
|
9174
9422
|
* Schema for validating hexadecimal strings with '0x' prefix.
|
|
9175
9423
|
*
|
|
@@ -9379,16 +9627,15 @@ var pkg = {
|
|
|
9379
9627
|
* ```
|
|
9380
9628
|
*/ const validateBalanceForTransaction = async (params)=>{
|
|
9381
9629
|
const { amount, adapter, token, tokenAddress, operationContext } = params;
|
|
9382
|
-
const
|
|
9630
|
+
const balance = await executeAdapterReadAction(adapter, 'usdc.balanceOf', {
|
|
9383
9631
|
walletAddress: operationContext.address
|
|
9384
9632
|
}, operationContext);
|
|
9385
|
-
|
|
9386
|
-
if (BigInt(balance) < BigInt(amount)) {
|
|
9633
|
+
if (BigInt(String(balance)) < BigInt(amount)) {
|
|
9387
9634
|
// Extract chain name from operationContext
|
|
9388
9635
|
const chainName = extractChainInfo(operationContext.chain).name;
|
|
9389
9636
|
// Create KitError with rich context in trace
|
|
9390
9637
|
throw createInsufficientTokenBalanceError(chainName, token, {
|
|
9391
|
-
balance: balance
|
|
9638
|
+
balance: String(balance),
|
|
9392
9639
|
amount,
|
|
9393
9640
|
tokenAddress,
|
|
9394
9641
|
walletAddress: operationContext.address
|
|
@@ -12360,6 +12607,23 @@ async function signUnits(group, signingUnits) {
|
|
|
12360
12607
|
}
|
|
12361
12608
|
return signedSets;
|
|
12362
12609
|
}
|
|
12610
|
+
/**
|
|
12611
|
+
* Fail loudly if a signing group carries an intent it does not own.
|
|
12612
|
+
*
|
|
12613
|
+
* Every intent in a group is signed by `group.address`, so that signer must own
|
|
12614
|
+
* each intent's `spec.sourceSigner`. If distinct spend sources ever collapse
|
|
12615
|
+
* into one group again (DEVX-3638), this throws before signing instead of
|
|
12616
|
+
* silently producing a wrong-signer signature. specs are bytes32 and
|
|
12617
|
+
* `group.address` is a native address, so normalize both before comparing.
|
|
12618
|
+
*/ function assertGroupSignerOwnsIntents(group) {
|
|
12619
|
+
if (group.address == null || group.address === '') return;
|
|
12620
|
+
const groupSigner = convertAddress(group.address, 'bytes32').toLowerCase();
|
|
12621
|
+
for (const intent of group.intents){
|
|
12622
|
+
if (intent.spec.sourceSigner.toLowerCase() !== groupSigner) {
|
|
12623
|
+
throw createValidationFailedError$1('group.address', group.address, `Signing group for ${group.address} carries an intent whose ` + `sourceSigner is ${intent.spec.sourceSigner}; a group must be signed ` + 'by the wallet that owns every intent it carries. This indicates ' + 'distinct spend sources collapsed into a single signing group.');
|
|
12624
|
+
}
|
|
12625
|
+
}
|
|
12626
|
+
}
|
|
12363
12627
|
/**
|
|
12364
12628
|
* Sign an EVM adapter group.
|
|
12365
12629
|
*
|
|
@@ -12402,22 +12666,42 @@ async function signUnits(group, signingUnits) {
|
|
|
12402
12666
|
// Validate the collection before doing bytecode reads or asking a wallet
|
|
12403
12667
|
// to sign. evmSigningData owns the canonical BurnIntent validation.
|
|
12404
12668
|
validateGroupIntents(group.intents);
|
|
12669
|
+
// Guard against a wrong-signer collapse: the group's signer must own every
|
|
12670
|
+
// intent it carries.
|
|
12671
|
+
assertGroupSignerOwnsIntents(group);
|
|
12405
12672
|
const chainsByDomain = collectChainsByDomain(group);
|
|
12406
12673
|
const signerTypeByDomain = await classifySignerTypes(group, chainsByDomain);
|
|
12407
12674
|
const signingUnits = createSigningUnits(group, signerTypeByDomain);
|
|
12408
12675
|
return await signUnits(group, signingUnits);
|
|
12409
12676
|
}
|
|
12410
12677
|
|
|
12678
|
+
// One adapter instance can serve several signer addresses (e.g. a single
|
|
12679
|
+
// dev-controlled adapter used for multiple wallets), so the group map must be
|
|
12680
|
+
// keyed on `(adapter, sourceSigner)` rather than the adapter reference alone.
|
|
12681
|
+
// Keying on the adapter alone collapsed two same-chain sources into one group,
|
|
12682
|
+
// signing the second wallet's intent with the first wallet (DEVX-3638 /
|
|
12683
|
+
// DEVX-3194). A Map needs a primitive key, so give each adapter instance a
|
|
12684
|
+
// stable token and combine it with the (case-normalized) signer address.
|
|
12685
|
+
const adapterTokens = new WeakMap();
|
|
12686
|
+
let nextAdapterToken = 0;
|
|
12687
|
+
function groupKey(alloc) {
|
|
12688
|
+
let token = adapterTokens.get(alloc.adapter);
|
|
12689
|
+
if (token === undefined) {
|
|
12690
|
+
token = nextAdapterToken++;
|
|
12691
|
+
adapterTokens.set(alloc.adapter, token);
|
|
12692
|
+
}
|
|
12693
|
+
return `${String(token)}:${alloc.sourceSigner.toLowerCase()}`;
|
|
12694
|
+
}
|
|
12411
12695
|
/**
|
|
12412
12696
|
* Add an EVM intent into the batched EVM group map.
|
|
12413
12697
|
*
|
|
12414
|
-
* On EVM, all intents for the same adapter are batched into a
|
|
12415
|
-
* group. The signing step uses `chainsByDomain` to preserve EOA batching
|
|
12698
|
+
* On EVM, all intents for the same adapter **and signer** are batched into a
|
|
12699
|
+
* single group. The signing step uses `chainsByDomain` to preserve EOA batching
|
|
12416
12700
|
* while signing ERC-1271 intents separately on their source chains.
|
|
12417
12701
|
*
|
|
12418
12702
|
* @param intent - The burn intent to group.
|
|
12419
12703
|
* @param alloc - The allocation that resolved to this intent.
|
|
12420
|
-
* @param evmGroups - Mutable map of adapter → EVM group.
|
|
12704
|
+
* @param evmGroups - Mutable map of `(adapter, sourceSigner)` key → EVM group.
|
|
12421
12705
|
*
|
|
12422
12706
|
* @example
|
|
12423
12707
|
* ```typescript
|
|
@@ -12427,12 +12711,13 @@ async function signUnits(group, signingUnits) {
|
|
|
12427
12711
|
* groupEvmIntents(intent, alloc, groups)
|
|
12428
12712
|
* ```
|
|
12429
12713
|
*/ function groupEvmIntents(intent, alloc, evmGroups) {
|
|
12430
|
-
const
|
|
12714
|
+
const key = groupKey(alloc);
|
|
12715
|
+
const existing = evmGroups.get(key);
|
|
12431
12716
|
if (existing) {
|
|
12432
12717
|
existing.intents.push(intent);
|
|
12433
12718
|
existing.chainsByDomain.set(alloc.chain.gateway.domain, alloc.chain);
|
|
12434
12719
|
} else {
|
|
12435
|
-
evmGroups.set(
|
|
12720
|
+
evmGroups.set(key, {
|
|
12436
12721
|
adapter: alloc.adapter,
|
|
12437
12722
|
chain: alloc.chain,
|
|
12438
12723
|
intents: [
|
|
@@ -13461,6 +13746,8 @@ const gatewayInfoSchema = zod.z.object({
|
|
|
13461
13746
|
* Fetch Gateway info from the `/v1/info` endpoint.
|
|
13462
13747
|
*
|
|
13463
13748
|
* @param isTestnet - Whether to query the testnet or mainnet API.
|
|
13749
|
+
* @param config - Optional polling config overrides, including custom
|
|
13750
|
+
* `headers` forwarded with the request.
|
|
13464
13751
|
* @returns Parsed Gateway info including per-domain processed heights.
|
|
13465
13752
|
* @throws KitError on HTTP failure or invalid response.
|
|
13466
13753
|
*
|
|
@@ -13469,11 +13756,11 @@ const gatewayInfoSchema = zod.z.object({
|
|
|
13469
13756
|
* const info = await fetchGatewayInfo(true)
|
|
13470
13757
|
* console.log(info.domains.map(d => `${d.chain}: ${d.processedHeight}`))
|
|
13471
13758
|
* ```
|
|
13472
|
-
*/ async function fetchGatewayInfo(isTestnet) {
|
|
13759
|
+
*/ async function fetchGatewayInfo(isTestnet, config) {
|
|
13473
13760
|
const apiBaseUrl = getGatewayApiBaseUrl(isTestnet);
|
|
13474
13761
|
const url = `${apiBaseUrl}/v1/info`;
|
|
13475
13762
|
try {
|
|
13476
|
-
return await pollApiGet(url, assertGatewayInfoResponse);
|
|
13763
|
+
return await pollApiGet(url, assertGatewayInfoResponse, config);
|
|
13477
13764
|
} catch (error) {
|
|
13478
13765
|
if (error instanceof KitError) {
|
|
13479
13766
|
throw error;
|
|
@@ -13499,6 +13786,8 @@ const gatewayInfoSchema = zod.z.object({
|
|
|
13499
13786
|
*
|
|
13500
13787
|
* @param isTestnet - Whether to query the testnet or mainnet API.
|
|
13501
13788
|
* @param domain - The Gateway domain number (e.g. 0 = Ethereum, 6 = Base).
|
|
13789
|
+
* @param config - Optional polling config overrides, including custom
|
|
13790
|
+
* `headers` forwarded with the `/v1/info` request.
|
|
13502
13791
|
* @returns The processed height as a bigint.
|
|
13503
13792
|
* @throws KitError when the domain is not found in the response.
|
|
13504
13793
|
*
|
|
@@ -13507,10 +13796,10 @@ const gatewayInfoSchema = zod.z.object({
|
|
|
13507
13796
|
* const height = await getProcessedHeight(true, 6) // Base Sepolia
|
|
13508
13797
|
* console.log(`Gateway processed up to block ${height}`)
|
|
13509
13798
|
* ```
|
|
13510
|
-
*/ async function getProcessedHeight(isTestnet, domain) {
|
|
13799
|
+
*/ async function getProcessedHeight(isTestnet, domain, config) {
|
|
13511
13800
|
// No caching in v1 — /v1/info is cheap and delegate status checks
|
|
13512
13801
|
// are infrequent. Revisit if rate-limit or latency issues appear.
|
|
13513
|
-
const info = await fetchGatewayInfo(isTestnet);
|
|
13802
|
+
const info = await fetchGatewayInfo(isTestnet, config);
|
|
13514
13803
|
const entry = info.domains.find((d)=>d.domain === domain);
|
|
13515
13804
|
if (!entry) {
|
|
13516
13805
|
throw new KitError({
|
|
@@ -13976,12 +14265,22 @@ function throwNetworkMismatch(expected, actual) {
|
|
|
13976
14265
|
* @param allocations - Normalized allocations used to map domain → adapter/chain.
|
|
13977
14266
|
* @returns Array of groups, each with adapter, chain, and intents to sign.
|
|
13978
14267
|
*/ function groupIntentsByAdapter(intents, allocations) {
|
|
14268
|
+
// Keyed by `(adapter, sourceSigner)` (see groupEvmIntents), not by adapter
|
|
14269
|
+
// alone: two spend sources on the same chain — including two addresses behind
|
|
14270
|
+
// one shared adapter — must stay in separate signing groups.
|
|
13979
14271
|
const evmGroups = new Map();
|
|
13980
14272
|
const solanaGroups = [];
|
|
13981
14273
|
for (const intent of intents){
|
|
13982
|
-
|
|
14274
|
+
// Match each intent back to its source allocation by BOTH Gateway domain
|
|
14275
|
+
// and signer. Two spend sources on the same chain share a domain, so
|
|
14276
|
+
// matching on domain alone always returned the FIRST allocation — folding
|
|
14277
|
+
// the second wallet's intent into the first wallet's signing group so it
|
|
14278
|
+
// was signed by the wrong wallet (DEVX-3638). specs carry sourceSigner as
|
|
14279
|
+
// bytes32 and allocations carry native addresses, so normalize both.
|
|
14280
|
+
const intentSigner = intent.spec.sourceSigner.toLowerCase();
|
|
14281
|
+
const alloc = allocations.find((a)=>a.chain.gateway.domain === intent.spec.sourceDomain && convertAddress(a.sourceSigner, 'bytes32').toLowerCase() === intentSigner);
|
|
13983
14282
|
if (!alloc) {
|
|
13984
|
-
throw createValidationFailedError$1('intent.spec.sourceDomain', intent.spec.sourceDomain, `No allocation found for sourceDomain ${String(intent.spec.sourceDomain)}; ` + 'estimate response contains an intent that does not match any allocation');
|
|
14283
|
+
throw createValidationFailedError$1('intent.spec.sourceDomain', intent.spec.sourceDomain, `No allocation found for sourceDomain ${String(intent.spec.sourceDomain)} and sourceSigner ${String(intent.spec.sourceSigner)}; ` + 'estimate response contains an intent that does not match any allocation');
|
|
13985
14284
|
}
|
|
13986
14285
|
if (alloc.chain.type === 'solana') {
|
|
13987
14286
|
solanaGroups.push(groupSolanaIntents(intent, alloc));
|
|
@@ -17398,12 +17697,12 @@ const FORWARDER_POLL_TIMEOUT_MS = 300_000;
|
|
|
17398
17697
|
* exceeds the 5-minute timeout without reaching a terminal status.
|
|
17399
17698
|
* @throws KitError Propagated from {@link pollApiGet} if the HTTP
|
|
17400
17699
|
* request itself fails or returns a non-OK response.
|
|
17401
|
-
*/ async function pollForwarderCompletion(apiBaseUrl, transferId) {
|
|
17700
|
+
*/ async function pollForwarderCompletion(apiBaseUrl, transferId, requestConfig) {
|
|
17402
17701
|
const startTime = Date.now();
|
|
17403
17702
|
while(Date.now() - startTime < FORWARDER_POLL_TIMEOUT_MS){
|
|
17404
17703
|
let status;
|
|
17405
17704
|
try {
|
|
17406
|
-
status = await pollApiGet(`${apiBaseUrl}/v1/transfer/${transferId}`, assertGatewayTransferDetails);
|
|
17705
|
+
status = await pollApiGet(`${apiBaseUrl}/v1/transfer/${transferId}`, assertGatewayTransferDetails, requestConfig);
|
|
17407
17706
|
} catch (error) {
|
|
17408
17707
|
throwGatewayApiError(error);
|
|
17409
17708
|
}
|
|
@@ -17521,7 +17820,7 @@ const FORWARDER_POLL_TIMEOUT_MS = 300_000;
|
|
|
17521
17820
|
* @param params - Spend parameters (source(s) and token).
|
|
17522
17821
|
* @param destChain - Resolved destination chain (used for network type).
|
|
17523
17822
|
* @returns Confirmed balances tagged with their originating source index.
|
|
17524
|
-
*/ async function fetchChainBalances(params, destChain) {
|
|
17823
|
+
*/ async function fetchChainBalances(params, destChain, requestConfig) {
|
|
17525
17824
|
const rawSources = Array.isArray(params.from) ? params.from : [
|
|
17526
17825
|
params.from
|
|
17527
17826
|
];
|
|
@@ -17550,7 +17849,7 @@ const FORWARDER_POLL_TIMEOUT_MS = 300_000;
|
|
|
17550
17849
|
token: params.token,
|
|
17551
17850
|
sources: querySource,
|
|
17552
17851
|
networkType
|
|
17553
|
-
});
|
|
17852
|
+
}, requestConfig);
|
|
17554
17853
|
}));
|
|
17555
17854
|
const chainBalances = [];
|
|
17556
17855
|
for(let i = 0; i < balanceResults.length; i++){
|
|
@@ -17623,9 +17922,9 @@ const FORWARDER_POLL_TIMEOUT_MS = 300_000;
|
|
|
17623
17922
|
* @param recipientAddress - Resolved recipient address.
|
|
17624
17923
|
* @param useForwarder - Whether the Forwarding Service path is active.
|
|
17625
17924
|
* @returns Allocations, intents, and (auto-allocation only) confirmed balances.
|
|
17626
|
-
*/ async function resolveAllocationsAndIntents(params, destChain, recipientAddress, useForwarder) {
|
|
17925
|
+
*/ async function resolveAllocationsAndIntents(params, destChain, recipientAddress, useForwarder, requestConfig) {
|
|
17627
17926
|
if (params.amountIn) {
|
|
17628
|
-
const chainBalances = await fetchChainBalances(params, destChain);
|
|
17927
|
+
const chainBalances = await fetchChainBalances(params, destChain, requestConfig);
|
|
17629
17928
|
const { allocations, intents } = await buildAutoAllocatedFromBalances(params, destChain, recipientAddress, useForwarder, params.amountIn, chainBalances);
|
|
17630
17929
|
return {
|
|
17631
17930
|
allocations,
|
|
@@ -17648,11 +17947,11 @@ const FORWARDER_POLL_TIMEOUT_MS = 300_000;
|
|
|
17648
17947
|
* @param useForwarder - Whether the Forwarding Service path is active.
|
|
17649
17948
|
* @param allocations - Normalised allocations (forwarded to error handler).
|
|
17650
17949
|
* @returns Estimate entries and optional forwarding fee.
|
|
17651
|
-
*/ async function fetchEstimate(apiBaseUrl, estimateBody, useForwarder, allocations) {
|
|
17950
|
+
*/ async function fetchEstimate(apiBaseUrl, estimateBody, useForwarder, allocations, requestConfig) {
|
|
17652
17951
|
if (useForwarder) {
|
|
17653
17952
|
let fwdResponse;
|
|
17654
17953
|
try {
|
|
17655
|
-
fwdResponse = await pollApiPost(`${apiBaseUrl}/v1/estimate?enableForwarder=true`, estimateBody, assertGatewayForwarderEstimateResponse);
|
|
17954
|
+
fwdResponse = await pollApiPost(`${apiBaseUrl}/v1/estimate?enableForwarder=true`, estimateBody, assertGatewayForwarderEstimateResponse, requestConfig);
|
|
17656
17955
|
} catch (error) {
|
|
17657
17956
|
throwGatewayApiError(error, allocations);
|
|
17658
17957
|
}
|
|
@@ -17663,7 +17962,7 @@ const FORWARDER_POLL_TIMEOUT_MS = 300_000;
|
|
|
17663
17962
|
}
|
|
17664
17963
|
let entries;
|
|
17665
17964
|
try {
|
|
17666
|
-
entries = await pollApiPost(`${apiBaseUrl}/v1/estimate`, estimateBody, assertGatewayEstimateResponse);
|
|
17965
|
+
entries = await pollApiPost(`${apiBaseUrl}/v1/estimate`, estimateBody, assertGatewayEstimateResponse, requestConfig);
|
|
17667
17966
|
} catch (error) {
|
|
17668
17967
|
throwGatewayApiError(error, allocations);
|
|
17669
17968
|
}
|
|
@@ -17734,14 +18033,14 @@ const FORWARDER_POLL_TIMEOUT_MS = 300_000;
|
|
|
17734
18033
|
* @param destChain - Resolved destination chain with Gateway v1 config.
|
|
17735
18034
|
* @param useForwarder - Whether the Forwarding Service path is active.
|
|
17736
18035
|
* @returns Estimated intents (with real maxFee) and optional forwarding fee.
|
|
17737
|
-
*/ async function validateAndEstimate(allocations, intents, destChain, useForwarder) {
|
|
18036
|
+
*/ async function validateAndEstimate(allocations, intents, destChain, useForwarder, requestConfig) {
|
|
17738
18037
|
assertNetworkCompatibility(allocations, destChain);
|
|
17739
18038
|
if (useForwarder) {
|
|
17740
18039
|
assertForwarderRouteSupport(destChain, allocations);
|
|
17741
18040
|
}
|
|
17742
18041
|
const apiBaseUrl = getGatewayApiBaseUrl(destChain.isTestnet);
|
|
17743
18042
|
const estimateBody = buildEstimateRequestBody(intents);
|
|
17744
|
-
const { entries, forwardingFee } = await fetchEstimate(apiBaseUrl, estimateBody, useForwarder, allocations);
|
|
18043
|
+
const { entries, forwardingFee } = await fetchEstimate(apiBaseUrl, estimateBody, useForwarder, allocations, requestConfig);
|
|
17745
18044
|
const estimatedIntents = parseEstimateResponse(entries, intents);
|
|
17746
18045
|
return {
|
|
17747
18046
|
estimatedIntents,
|
|
@@ -17800,7 +18099,7 @@ const FORWARDER_POLL_TIMEOUT_MS = 300_000;
|
|
|
17800
18099
|
}
|
|
17801
18100
|
throw err;
|
|
17802
18101
|
}
|
|
17803
|
-
const { estimatedIntents, forwardingFee } = await validateAndEstimate(corrected.allocations, corrected.intents, opts.destChain, opts.useForwarder);
|
|
18102
|
+
const { estimatedIntents, forwardingFee } = await validateAndEstimate(corrected.allocations, corrected.intents, opts.destChain, opts.useForwarder, opts.requestConfig);
|
|
17804
18103
|
const stillOverdrawn = findOverdrawnChains(estimatedIntents, corrected.allocations, opts.chainBalances);
|
|
17805
18104
|
if (stillOverdrawn.length === 0) {
|
|
17806
18105
|
return {
|
|
@@ -17834,12 +18133,12 @@ const FORWARDER_POLL_TIMEOUT_MS = 300_000;
|
|
|
17834
18133
|
* @param recipientAddress - Resolved recipient address.
|
|
17835
18134
|
* @param useForwarder - Whether the Forwarding Service path is active.
|
|
17836
18135
|
* @returns Allocations, estimated intents, and optional forwarding fee.
|
|
17837
|
-
*/ async function resolveValidatedIntents(params, destChain, recipientAddress, useForwarder) {
|
|
18136
|
+
*/ async function resolveValidatedIntents(params, destChain, recipientAddress, useForwarder, requestConfig) {
|
|
17838
18137
|
if (useForwarder) {
|
|
17839
18138
|
assertForwarderRouteSupport(destChain);
|
|
17840
18139
|
}
|
|
17841
|
-
const { allocations, intents, chainBalances } = await resolveAllocationsAndIntents(params, destChain, recipientAddress, useForwarder);
|
|
17842
|
-
const { estimatedIntents, forwardingFee } = await validateAndEstimate(allocations, intents, destChain, useForwarder);
|
|
18140
|
+
const { allocations, intents, chainBalances } = await resolveAllocationsAndIntents(params, destChain, recipientAddress, useForwarder, requestConfig);
|
|
18141
|
+
const { estimatedIntents, forwardingFee } = await validateAndEstimate(allocations, intents, destChain, useForwarder, requestConfig);
|
|
17843
18142
|
if (params.amountIn && chainBalances) {
|
|
17844
18143
|
const overdrawn = findOverdrawnChains(estimatedIntents, allocations, chainBalances);
|
|
17845
18144
|
if (overdrawn.length > 0) {
|
|
@@ -17852,7 +18151,10 @@ const FORWARDER_POLL_TIMEOUT_MS = 300_000;
|
|
|
17852
18151
|
chainBalances,
|
|
17853
18152
|
estimatedIntents,
|
|
17854
18153
|
allocations,
|
|
17855
|
-
overdrawn
|
|
18154
|
+
overdrawn,
|
|
18155
|
+
...requestConfig ? {
|
|
18156
|
+
requestConfig
|
|
18157
|
+
} : {}
|
|
17856
18158
|
});
|
|
17857
18159
|
}
|
|
17858
18160
|
}
|
|
@@ -17896,10 +18198,10 @@ const FORWARDER_POLL_TIMEOUT_MS = 300_000;
|
|
|
17896
18198
|
attestationSignature: transferResponse.signature
|
|
17897
18199
|
};
|
|
17898
18200
|
}
|
|
17899
|
-
async function runSpendNormalPath(params, destChain, useForwarder, dispatcher, steps) {
|
|
18201
|
+
async function runSpendNormalPath(params, destChain, useForwarder, dispatcher, steps, requestConfig) {
|
|
17900
18202
|
const chainName = destChain.name;
|
|
17901
18203
|
const recipientAddress = await resolveRecipientAddress(params.to);
|
|
17902
|
-
const { allocations, estimatedIntents, forwardingFee: estimateFwdFee } = await resolveValidatedIntents(params, destChain, recipientAddress, useForwarder);
|
|
18204
|
+
const { allocations, estimatedIntents, forwardingFee: estimateFwdFee } = await resolveValidatedIntents(params, destChain, recipientAddress, useForwarder, requestConfig);
|
|
17903
18205
|
pushStep(steps, dispatcher, 'gateway.spend.step.buildBurnIntents', chainName, {
|
|
17904
18206
|
name: 'buildBurnIntents',
|
|
17905
18207
|
state: 'success',
|
|
@@ -17936,7 +18238,7 @@ async function runSpendNormalPath(params, destChain, useForwarder, dispatcher, s
|
|
|
17936
18238
|
const forwarderParam = useForwarder ? '?enableForwarder=true' : '';
|
|
17937
18239
|
let transferResponse;
|
|
17938
18240
|
try {
|
|
17939
|
-
transferResponse = await pollApiPost(`${transferApiBaseUrl}/v1/transfer${forwarderParam}`, transferBody, assertGatewayTransferResponse);
|
|
18241
|
+
transferResponse = await pollApiPost(`${transferApiBaseUrl}/v1/transfer${forwarderParam}`, transferBody, assertGatewayTransferResponse, requestConfig);
|
|
17940
18242
|
} catch (error) {
|
|
17941
18243
|
throwGatewayApiError(error, allocations);
|
|
17942
18244
|
}
|
|
@@ -18016,10 +18318,11 @@ function updateFeesWithActual(fees, completionStatus) {
|
|
|
18016
18318
|
amount: actual
|
|
18017
18319
|
} : f);
|
|
18018
18320
|
}
|
|
18019
|
-
async function resolveDestinationTxHash(
|
|
18321
|
+
async function resolveDestinationTxHash(opts) {
|
|
18322
|
+
const { params, destChain, forwarder, transferId, attestation, attestationSignature, fees, requestConfig } = opts;
|
|
18020
18323
|
if (forwarder && transferId) {
|
|
18021
18324
|
const apiBaseUrl = getGatewayApiBaseUrl(destChain.isTestnet);
|
|
18022
|
-
const completionStatus = await pollForwarderCompletion(apiBaseUrl, transferId);
|
|
18325
|
+
const completionStatus = await pollForwarderCompletion(apiBaseUrl, transferId, requestConfig);
|
|
18023
18326
|
if (!completionStatus.transactionHash) {
|
|
18024
18327
|
throw new KitError({
|
|
18025
18328
|
...OnchainError.TRANSACTION_REVERTED,
|
|
@@ -18102,9 +18405,20 @@ function buildSpendResult(recipientAddress, destChain, txHash, allocationResults
|
|
|
18102
18405
|
/**
|
|
18103
18406
|
* Execute the mint step, recording success/error as a spend step.
|
|
18104
18407
|
*/ async function executeMintStep(opts) {
|
|
18105
|
-
const { params, destChain, forwarder, transferId, attestation, attestationSignature, fees, steps, dispatcher } = opts;
|
|
18408
|
+
const { params, destChain, forwarder, transferId, attestation, attestationSignature, fees, steps, dispatcher, requestConfig } = opts;
|
|
18106
18409
|
try {
|
|
18107
|
-
const mintResult = await resolveDestinationTxHash(
|
|
18410
|
+
const mintResult = await resolveDestinationTxHash({
|
|
18411
|
+
params,
|
|
18412
|
+
destChain,
|
|
18413
|
+
forwarder,
|
|
18414
|
+
transferId,
|
|
18415
|
+
attestation,
|
|
18416
|
+
attestationSignature,
|
|
18417
|
+
fees,
|
|
18418
|
+
...requestConfig ? {
|
|
18419
|
+
requestConfig
|
|
18420
|
+
} : {}
|
|
18421
|
+
});
|
|
18108
18422
|
pushStep(steps, dispatcher, 'gateway.spend.step.mint', destChain.name, {
|
|
18109
18423
|
name: 'mint',
|
|
18110
18424
|
state: 'success',
|
|
@@ -18159,7 +18473,8 @@ function buildSpendResult(recipientAddress, destChain, txHash, allocationResults
|
|
|
18159
18473
|
assertSpendAddresses(params, destChain);
|
|
18160
18474
|
const forwarder = isForwarderEnabled(params.to);
|
|
18161
18475
|
const steps = [];
|
|
18162
|
-
const
|
|
18476
|
+
const requestConfig = options?.requestConfig;
|
|
18477
|
+
const context = params.config?.retry ? await resolveRetryContext(params) : await resolveNormalContext(params, destChain, forwarder, dispatcher, steps, requestConfig);
|
|
18163
18478
|
const fees = appendForwarderFee(context.fees, context.forwardingFee);
|
|
18164
18479
|
const mintResult = await executeMintStep({
|
|
18165
18480
|
params,
|
|
@@ -18170,7 +18485,10 @@ function buildSpendResult(recipientAddress, destChain, txHash, allocationResults
|
|
|
18170
18485
|
attestationSignature: context.attestationSignature,
|
|
18171
18486
|
fees,
|
|
18172
18487
|
steps,
|
|
18173
|
-
dispatcher
|
|
18488
|
+
dispatcher,
|
|
18489
|
+
...requestConfig ? {
|
|
18490
|
+
requestConfig
|
|
18491
|
+
} : {}
|
|
18174
18492
|
});
|
|
18175
18493
|
// A throwing `onBroadcast` must never strand the caller after a
|
|
18176
18494
|
// successful mint — the chain has moved. `safeInvokeCallback` swallows
|
|
@@ -18187,14 +18505,14 @@ function buildSpendResult(recipientAddress, destChain, txHash, allocationResults
|
|
|
18187
18505
|
/**
|
|
18188
18506
|
* Resolve the spend context via the normal (non-retry) path.
|
|
18189
18507
|
* Validates `from`, then delegates to `runSpendNormalPath`.
|
|
18190
|
-
*/ async function resolveNormalContext(params, destChain, forwarder, dispatcher, steps) {
|
|
18508
|
+
*/ async function resolveNormalContext(params, destChain, forwarder, dispatcher, steps, requestConfig) {
|
|
18191
18509
|
if (!params.from) {
|
|
18192
18510
|
throw createValidationFailedError$1('from', params.from, 'Source (from) is required when config.retry is not provided.');
|
|
18193
18511
|
}
|
|
18194
18512
|
return runSpendNormalPath({
|
|
18195
18513
|
...params,
|
|
18196
18514
|
from: params.from
|
|
18197
|
-
}, destChain, forwarder, dispatcher, steps);
|
|
18515
|
+
}, destChain, forwarder, dispatcher, steps, requestConfig);
|
|
18198
18516
|
}
|
|
18199
18517
|
/**
|
|
18200
18518
|
* Estimate fees for a Gateway spend without executing it.
|
|
@@ -18217,13 +18535,13 @@ function buildSpendResult(recipientAddress, destChain, txHash, allocationResults
|
|
|
18217
18535
|
* })
|
|
18218
18536
|
* fees.forEach((f) => console.log(f.type, f.amount, f.allocations))
|
|
18219
18537
|
* ```
|
|
18220
|
-
*/ async function estimateSpend$1(params) {
|
|
18538
|
+
*/ async function estimateSpend$1(params, requestConfig) {
|
|
18221
18539
|
const destChain = resolveChainIdentifier(params.to.chain);
|
|
18222
18540
|
assertGatewayV1(destChain);
|
|
18223
18541
|
assertSpendAddresses(params, destChain);
|
|
18224
18542
|
const forwarder = isForwarderEnabled(params.to);
|
|
18225
18543
|
const recipientAddress = await resolveRecipientAddress(params.to);
|
|
18226
|
-
const { allocations, estimatedIntents, forwardingFee } = await resolveValidatedIntents(params, destChain, recipientAddress, forwarder);
|
|
18544
|
+
const { allocations, estimatedIntents, forwardingFee } = await resolveValidatedIntents(params, destChain, recipientAddress, forwarder, requestConfig);
|
|
18227
18545
|
const fees = computeEstimateFees(estimatedIntents, allocations, params.config?.customFee);
|
|
18228
18546
|
if (forwardingFee) {
|
|
18229
18547
|
fees.push({
|
|
@@ -18347,6 +18665,9 @@ function assertNotSelfDelegation(chain, signerAddress, delegateAddress, action)
|
|
|
18347
18665
|
* the delegate is `'ready'` (finalized); otherwise it is `'pending'`.
|
|
18348
18666
|
*
|
|
18349
18667
|
* @param params - The adapter context (`from`), delegate address, and token.
|
|
18668
|
+
* @param requestConfig - Optional polling config overrides, including custom
|
|
18669
|
+
* `headers` forwarded with the `/v1/info` request used on the EVM finality
|
|
18670
|
+
* check.
|
|
18350
18671
|
* @returns Promise resolving to `'none'`, `'pending'`, or `'ready'`.
|
|
18351
18672
|
* @throws KitError if the chain is unsupported or `/v1/info` fails.
|
|
18352
18673
|
*
|
|
@@ -18366,7 +18687,7 @@ function assertNotSelfDelegation(chain, signerAddress, delegateAddress, action)
|
|
|
18366
18687
|
* const status = await getDelegateStatus(params)
|
|
18367
18688
|
* if (status === 'ready') { // safe to spend }
|
|
18368
18689
|
* ```
|
|
18369
|
-
*/ async function getDelegateStatus$1(params) {
|
|
18690
|
+
*/ async function getDelegateStatus$1(params, requestConfig) {
|
|
18370
18691
|
const { from, delegateAddress } = params;
|
|
18371
18692
|
const { adapter } = from;
|
|
18372
18693
|
const chain = resolveChainIdentifier(from.chain);
|
|
@@ -18382,8 +18703,7 @@ function assertNotSelfDelegation(chain, signerAddress, delegateAddress, action)
|
|
|
18382
18703
|
chain
|
|
18383
18704
|
};
|
|
18384
18705
|
// Step 1: Quick check at latest block (no HTTP call)
|
|
18385
|
-
const
|
|
18386
|
-
const latestResult = await latestRequest.execute();
|
|
18706
|
+
const latestResult = await executeAdapterReadAction(adapter, 'gateway.v1.isDelegate', baseActionParams, operationContext);
|
|
18387
18707
|
if (String(latestResult).toLowerCase() !== 'true') {
|
|
18388
18708
|
return 'none';
|
|
18389
18709
|
}
|
|
@@ -18392,13 +18712,12 @@ function assertNotSelfDelegation(chain, signerAddress, delegateAddress, action)
|
|
|
18392
18712
|
// Solana uses confirmed vs finalized commitment as a proxy for
|
|
18393
18713
|
// Gateway finality. This is conservative — can only over-report
|
|
18394
18714
|
// 'pending', never falsely report 'ready'.
|
|
18395
|
-
const finalizedRequest = await adapter.prepareAction('gateway.v1.isDelegate', {
|
|
18396
|
-
...baseActionParams,
|
|
18397
|
-
commitment: 'finalized'
|
|
18398
|
-
}, operationContext);
|
|
18399
18715
|
let finalizedResult;
|
|
18400
18716
|
try {
|
|
18401
|
-
finalizedResult = await
|
|
18717
|
+
finalizedResult = await executeAdapterReadAction(adapter, 'gateway.v1.isDelegate', {
|
|
18718
|
+
...baseActionParams,
|
|
18719
|
+
commitment: 'finalized'
|
|
18720
|
+
}, operationContext);
|
|
18402
18721
|
} catch (error) {
|
|
18403
18722
|
if (isBlockRangeError(error)) {
|
|
18404
18723
|
return 'pending';
|
|
@@ -18408,11 +18727,7 @@ function assertNotSelfDelegation(chain, signerAddress, delegateAddress, action)
|
|
|
18408
18727
|
return String(finalizedResult).toLowerCase() === 'true' ? 'ready' : 'pending';
|
|
18409
18728
|
}
|
|
18410
18729
|
// EVM: use processedHeight from /v1/info
|
|
18411
|
-
const processedHeight = await getProcessedHeight(chain.isTestnet, chain.gateway.domain);
|
|
18412
|
-
const finalizedRequest = await adapter.prepareAction('gateway.v1.isDelegate', {
|
|
18413
|
-
...baseActionParams,
|
|
18414
|
-
blockNumber: processedHeight
|
|
18415
|
-
}, operationContext);
|
|
18730
|
+
const processedHeight = await getProcessedHeight(chain.isTestnet, chain.gateway.domain, requestConfig);
|
|
18416
18731
|
// If the RPC node lags Gateway's indexer view, the historical read at
|
|
18417
18732
|
// processedHeight may throw a block-range error. This is safe to treat
|
|
18418
18733
|
// as 'pending' because processedHeight comes from Gateway's /v1/info
|
|
@@ -18421,7 +18736,10 @@ function assertNotSelfDelegation(chain, signerAddress, delegateAddress, action)
|
|
|
18421
18736
|
// Re-throw structural errors to avoid masking real bugs.
|
|
18422
18737
|
let finalizedResult;
|
|
18423
18738
|
try {
|
|
18424
|
-
finalizedResult = await
|
|
18739
|
+
finalizedResult = await executeAdapterReadAction(adapter, 'gateway.v1.isDelegate', {
|
|
18740
|
+
...baseActionParams,
|
|
18741
|
+
blockNumber: processedHeight
|
|
18742
|
+
}, operationContext);
|
|
18425
18743
|
} catch (error) {
|
|
18426
18744
|
if (isBlockRangeError(error)) {
|
|
18427
18745
|
return 'pending';
|
|
@@ -18482,8 +18800,8 @@ function parseAmountSafe(amount) {
|
|
|
18482
18800
|
chain
|
|
18483
18801
|
};
|
|
18484
18802
|
const [withdrawingRaw, withdrawalBlockRaw] = await Promise.all([
|
|
18485
|
-
adapter
|
|
18486
|
-
adapter
|
|
18803
|
+
executeAdapterReadAction(adapter, 'gateway.v1.withdrawingBalance', readParams, operationContext),
|
|
18804
|
+
executeAdapterReadAction(adapter, 'gateway.v1.withdrawalBlock', readParams, operationContext)
|
|
18487
18805
|
]);
|
|
18488
18806
|
const withdrawingValue = safeBigInt(String(withdrawingRaw), 'withdrawingBalance');
|
|
18489
18807
|
const withdrawalBlockValue = safeBigInt(String(withdrawalBlockRaw), 'withdrawalBlock');
|
|
@@ -18523,12 +18841,11 @@ function parseAmountSafe(amount) {
|
|
|
18523
18841
|
const tokenAddress = getTokenAddress(chain, params.token);
|
|
18524
18842
|
// Read the pending balance before withdrawing — the contract resets it to 0
|
|
18525
18843
|
// after withdraw() executes, so this is the only way to capture the amount.
|
|
18526
|
-
const
|
|
18844
|
+
const withdrawingRaw = await executeAdapterReadAction(adapter, 'gateway.v1.withdrawingBalance', {
|
|
18527
18845
|
token: tokenAddress,
|
|
18528
18846
|
depositor: signerAddress,
|
|
18529
18847
|
chain
|
|
18530
18848
|
}, operationContext);
|
|
18531
|
-
const withdrawingRaw = await withdrawingBalanceReq.execute();
|
|
18532
18849
|
const withdrawingValue = safeBigInt(String(withdrawingRaw), 'withdrawingBalance');
|
|
18533
18850
|
if (withdrawingValue === 0n) {
|
|
18534
18851
|
throw new KitError({
|
|
@@ -18628,6 +18945,35 @@ function dispatchEvent(dispatcher, opName, stage, chain, data) {
|
|
|
18628
18945
|
dispatchEvent(dispatcher, opName, 'failed', chain, extractErrorInfo(error));
|
|
18629
18946
|
}
|
|
18630
18947
|
|
|
18948
|
+
// ---------------------------------------------------------------------------
|
|
18949
|
+
// Config validation
|
|
18950
|
+
// ---------------------------------------------------------------------------
|
|
18951
|
+
function isPlainObject(value) {
|
|
18952
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
18953
|
+
return false;
|
|
18954
|
+
}
|
|
18955
|
+
const prototype = Object.getPrototypeOf(value);
|
|
18956
|
+
return prototype === Object.prototype || prototype === null;
|
|
18957
|
+
}
|
|
18958
|
+
function assertHeadersConfig(headers) {
|
|
18959
|
+
if (headers === undefined) {
|
|
18960
|
+
return;
|
|
18961
|
+
}
|
|
18962
|
+
if (!isPlainObject(headers)) {
|
|
18963
|
+
throw createValidationFailedError$1('config.headers', headers, 'config.headers must be a plain object with string header values when provided');
|
|
18964
|
+
}
|
|
18965
|
+
for (const [name, value] of Object.entries(headers)){
|
|
18966
|
+
if (typeof value !== 'string') {
|
|
18967
|
+
throw createValidationFailedError$1(`config.headers.${name}`, value, 'header values must be strings');
|
|
18968
|
+
}
|
|
18969
|
+
}
|
|
18970
|
+
}
|
|
18971
|
+
function assertGatewayV1Config(config) {
|
|
18972
|
+
if (!isPlainObject(config)) {
|
|
18973
|
+
throw createValidationFailedError$1('config', config, 'config must be a plain object when provided');
|
|
18974
|
+
}
|
|
18975
|
+
assertHeadersConfig(config['headers']);
|
|
18976
|
+
}
|
|
18631
18977
|
// ---------------------------------------------------------------------------
|
|
18632
18978
|
// Factory
|
|
18633
18979
|
// ---------------------------------------------------------------------------
|
|
@@ -18637,7 +18983,12 @@ function dispatchEvent(dispatcher, opName, stage, chain, data) {
|
|
|
18637
18983
|
* Returns a plain object that implements {@link IGatewayProvider} by
|
|
18638
18984
|
* delegating to the standalone functions in `operations/`.
|
|
18639
18985
|
*
|
|
18986
|
+
* @param config - Optional provider configuration. Supply `headers` to
|
|
18987
|
+
* forward custom HTTP headers with every Gateway API request. See
|
|
18988
|
+
* {@link GatewayV1Config}.
|
|
18640
18989
|
* @returns An {@link IGatewayProvider} instance.
|
|
18990
|
+
* @throws Throws when `config` or `config.headers` is not a plain object, or a
|
|
18991
|
+
* header value is not a string.
|
|
18641
18992
|
*
|
|
18642
18993
|
* @example
|
|
18643
18994
|
* ```typescript
|
|
@@ -18646,7 +18997,23 @@ function dispatchEvent(dispatcher, opName, stage, chain, data) {
|
|
|
18646
18997
|
* const provider = createGatewayV1Provider()
|
|
18647
18998
|
* const chains = provider.getSupportedChains()
|
|
18648
18999
|
* ```
|
|
18649
|
-
|
|
19000
|
+
*
|
|
19001
|
+
* @example
|
|
19002
|
+
* ```typescript
|
|
19003
|
+
* // Forward a custom header on every Gateway API request.
|
|
19004
|
+
* const provider = createGatewayV1Provider({
|
|
19005
|
+
* headers: { 'X-Access-Key': process.env.GATEWAY_ACCESS_KEY! },
|
|
19006
|
+
* })
|
|
19007
|
+
* ```
|
|
19008
|
+
*/ function createGatewayV1Provider(config = {}) {
|
|
19009
|
+
assertGatewayV1Config(config);
|
|
19010
|
+
// Captured once and threaded to every Gateway API call the operations make,
|
|
19011
|
+
// so a configured header reaches balances, estimate, transfer, forwarder
|
|
19012
|
+
// status, and /v1/info alike. Left undefined when no headers are configured
|
|
19013
|
+
// so the operations keep their existing defaults untouched.
|
|
19014
|
+
const requestConfig = config.headers ? {
|
|
19015
|
+
headers: config.headers
|
|
19016
|
+
} : undefined;
|
|
18650
19017
|
/**
|
|
18651
19018
|
* Execute an operation with started/succeeded/failed event dispatch.
|
|
18652
19019
|
*/ async function withEvents(opName, chain, startedData, params, fn) {
|
|
@@ -18677,21 +19044,25 @@ function dispatchEvent(dispatcher, opName, stage, chain, data) {
|
|
|
18677
19044
|
}, params, depositFor$1),
|
|
18678
19045
|
spend: async (params, options)=>{
|
|
18679
19046
|
const destChainName = extractChainInfo(params.to.chain).name;
|
|
19047
|
+
const mergedOptions = requestConfig ? {
|
|
19048
|
+
...options,
|
|
19049
|
+
requestConfig
|
|
19050
|
+
} : options;
|
|
18680
19051
|
return withEvents('spend', destChainName, {
|
|
18681
19052
|
destinationChain: destChainName,
|
|
18682
19053
|
token: params.token ?? 'USDC'
|
|
18683
|
-
}, params, async (p)=>spend$1(p, provider.actionDispatcher,
|
|
19054
|
+
}, params, async (p)=>spend$1(p, provider.actionDispatcher, mergedOptions));
|
|
18684
19055
|
},
|
|
18685
19056
|
estimateSpend: async (params)=>{
|
|
18686
19057
|
const destChainName = extractChainInfo(params.to.chain).name;
|
|
18687
19058
|
return withEvents('estimateSpend', destChainName, {
|
|
18688
19059
|
destinationChain: destChainName,
|
|
18689
19060
|
token: params.token ?? 'USDC'
|
|
18690
|
-
}, params, estimateSpend$1);
|
|
19061
|
+
}, params, async (p)=>estimateSpend$1(p, requestConfig));
|
|
18691
19062
|
},
|
|
18692
19063
|
getBalances: async (params)=>withEvents('getBalances', 'aggregate', {
|
|
18693
19064
|
token: params.token ?? 'USDC'
|
|
18694
|
-
}, params, getBalances$1),
|
|
19065
|
+
}, params, async (p)=>getBalances$1(p, requestConfig)),
|
|
18695
19066
|
addDelegate: async (params)=>withEvents('addDelegate', extractChainInfo(params.from.chain).name, {
|
|
18696
19067
|
delegateAddress: params.delegateAddress
|
|
18697
19068
|
}, params, addDelegate$1),
|
|
@@ -18709,7 +19080,9 @@ function dispatchEvent(dispatcher, opName, stage, chain, data) {
|
|
|
18709
19080
|
// in withEvents. getSupportedChains is synchronous. getDelegateStatus is a
|
|
18710
19081
|
// lightweight read that consumers treat as a utility check, unlike
|
|
18711
19082
|
// getBalances which involves API polling and benefits from lifecycle events.
|
|
18712
|
-
getDelegateStatus
|
|
19083
|
+
// getDelegateStatus is wrapped to forward the provider's request config to
|
|
19084
|
+
// its /v1/info call; getSupportedChains makes no API call.
|
|
19085
|
+
getDelegateStatus: async (params)=>getDelegateStatus$1(params, requestConfig),
|
|
18713
19086
|
getSupportedChains: getSupportedChains$1
|
|
18714
19087
|
};
|
|
18715
19088
|
return provider;
|
|
@@ -18719,6 +19092,7 @@ function dispatchEvent(dispatcher, opName, stage, chain, data) {
|
|
|
18719
19092
|
* The default providers that will be used in addition to the providers
|
|
18720
19093
|
* provided to the createUnifiedBalanceKitContext factory function.
|
|
18721
19094
|
*
|
|
19095
|
+
* @param config - Optional configuration forwarded to the default provider.
|
|
18722
19096
|
* @returns A readonly tuple with one element: the default Gateway v1 provider
|
|
18723
19097
|
* instance created via {@link createGatewayV1Provider}.
|
|
18724
19098
|
* @internal
|
|
@@ -18730,8 +19104,10 @@ function dispatchEvent(dispatcher, opName, stage, chain, data) {
|
|
|
18730
19104
|
* const { providers } = createUnifiedBalanceKitContext()
|
|
18731
19105
|
* // providers[0] is the default Gateway v1 instance from getDefaultProviders()
|
|
18732
19106
|
* ```
|
|
18733
|
-
*/ const getDefaultProviders = ()=>[
|
|
18734
|
-
createGatewayV1Provider(
|
|
19107
|
+
*/ const getDefaultProviders = (config = {})=>[
|
|
19108
|
+
createGatewayV1Provider(config.headers ? {
|
|
19109
|
+
headers: config.headers
|
|
19110
|
+
} : {})
|
|
18735
19111
|
];
|
|
18736
19112
|
function createUnifiedBalanceKitContext(config = {}) {
|
|
18737
19113
|
// Runtime guard: `excludeDefaultProviders: true` with no `providers` is
|
|
@@ -18745,7 +19121,10 @@ function createUnifiedBalanceKitContext(config = {}) {
|
|
|
18745
19121
|
// Initialize default providers — either the canonical singleton tuple or
|
|
18746
19122
|
// an empty list when the caller has opted out. Typed loosely here; each
|
|
18747
19123
|
// public overload narrows the return type for callers.
|
|
18748
|
-
const
|
|
19124
|
+
const defaultProvidersConfig = config.headers ? {
|
|
19125
|
+
headers: config.headers
|
|
19126
|
+
} : {};
|
|
19127
|
+
const defaultProviders = config.excludeDefaultProviders === true ? [] : getDefaultProviders(defaultProvidersConfig);
|
|
18749
19128
|
const providers = [
|
|
18750
19129
|
...defaultProviders,
|
|
18751
19130
|
...config.providers ?? []
|
|
@@ -19436,29 +19815,65 @@ function sumAllocationsFromSources(sources) {
|
|
|
19436
19815
|
}
|
|
19437
19816
|
});
|
|
19438
19817
|
|
|
19818
|
+
function normalizeAddressIdentity(value) {
|
|
19819
|
+
if (typeof value !== 'string') return undefined;
|
|
19820
|
+
try {
|
|
19821
|
+
return convertAddress(value, 'bytes32').toLowerCase();
|
|
19822
|
+
} catch {
|
|
19823
|
+
// Address validation below owns the structured error for invalid input.
|
|
19824
|
+
return value;
|
|
19825
|
+
}
|
|
19826
|
+
}
|
|
19439
19827
|
/**
|
|
19440
|
-
* Reject `from` arrays
|
|
19441
|
-
*
|
|
19442
|
-
*
|
|
19828
|
+
* Reject `from` arrays that describe the same spend source more than once.
|
|
19829
|
+
*
|
|
19830
|
+
* One adapter instance may legitimately be reused across distinct Gateway
|
|
19831
|
+
* source accounts. When `sourceAccount` is omitted, the signer address
|
|
19832
|
+
* identifies the source. Must run on the raw input (before Zod parsing)
|
|
19833
|
+
* because `z.object()` creates new wrapper objects and adapter identity
|
|
19834
|
+
* (`===`) is lost.
|
|
19443
19835
|
*
|
|
19444
19836
|
* @internal
|
|
19445
|
-
*/ function
|
|
19837
|
+
*/ function assertNoDuplicateSpendSources(params) {
|
|
19446
19838
|
if (params == null || typeof params !== 'object') return;
|
|
19447
19839
|
const from = params['from'];
|
|
19448
19840
|
if (!Array.isArray(from) || from.length < 2) return;
|
|
19449
|
-
const seen = new
|
|
19841
|
+
const seen = new Map();
|
|
19450
19842
|
for (const source of from){
|
|
19451
19843
|
if (source == null || typeof source !== 'object') continue;
|
|
19452
|
-
const
|
|
19844
|
+
const record = source;
|
|
19845
|
+
const adapter = record['adapter'];
|
|
19453
19846
|
if (adapter == null) continue;
|
|
19454
|
-
|
|
19847
|
+
const sourceAccount = normalizeAddressIdentity(record['sourceAccount']) ?? normalizeAddressIdentity(record['address']);
|
|
19848
|
+
let sourceAccounts = seen.get(adapter);
|
|
19849
|
+
if (sourceAccounts == null) {
|
|
19850
|
+
sourceAccounts = new Set();
|
|
19851
|
+
seen.set(adapter, sourceAccounts);
|
|
19852
|
+
}
|
|
19853
|
+
if (sourceAccounts.has(sourceAccount)) {
|
|
19455
19854
|
throw new KitError({
|
|
19456
19855
|
...InputError.VALIDATION_FAILED,
|
|
19457
19856
|
recoverability: 'FATAL',
|
|
19458
|
-
message: 'Duplicate
|
|
19857
|
+
message: 'Duplicate spend source detected in from array. The same adapter ' + 'and Gateway source account are reused more than once.'
|
|
19459
19858
|
});
|
|
19460
19859
|
}
|
|
19461
|
-
|
|
19860
|
+
sourceAccounts.add(sourceAccount);
|
|
19861
|
+
}
|
|
19862
|
+
}
|
|
19863
|
+
function assertSourceAddressContexts(from) {
|
|
19864
|
+
const sources = Array.isArray(from) ? from : [
|
|
19865
|
+
from
|
|
19866
|
+
];
|
|
19867
|
+
for (const raw of sources){
|
|
19868
|
+
if (raw == null || typeof raw !== 'object') continue;
|
|
19869
|
+
const source = raw;
|
|
19870
|
+
const addressContext = source.adapter?.capabilities?.addressContext;
|
|
19871
|
+
if (addressContext === 'developer-controlled' && (typeof source.address !== 'string' || source.address === '')) {
|
|
19872
|
+
throw createValidationFailedError$1('address', source.address, 'Address is required for developer-controlled adapters.');
|
|
19873
|
+
}
|
|
19874
|
+
if (addressContext === 'user-controlled' && source.address !== undefined) {
|
|
19875
|
+
throw createValidationFailedError$1('address', source.address, 'Address should not be provided for user-controlled adapters. ' + 'The address is automatically resolved from the connected wallet.');
|
|
19876
|
+
}
|
|
19462
19877
|
}
|
|
19463
19878
|
}
|
|
19464
19879
|
/**
|
|
@@ -19472,14 +19887,17 @@ function sumAllocationsFromSources(sources) {
|
|
|
19472
19887
|
* @throws \{KitError\} When validation fails; error code is
|
|
19473
19888
|
* {@link InputError.VALIDATION_FAILED}.
|
|
19474
19889
|
*/ function assertSpendParams(params) {
|
|
19475
|
-
|
|
19890
|
+
assertNoDuplicateSpendSources(params);
|
|
19891
|
+
if (params != null && typeof params === 'object' && 'from' in params) {
|
|
19892
|
+
assertSourceAddressContexts(params['from']);
|
|
19893
|
+
}
|
|
19476
19894
|
const result = spendParamsSchema.safeParse(params);
|
|
19477
19895
|
if (!result.success) {
|
|
19478
19896
|
throw convertZodErrorToStructured(result.error, params);
|
|
19479
19897
|
}
|
|
19480
19898
|
const data = result.data;
|
|
19481
19899
|
// Validate recipientAddress against the destination chain
|
|
19482
|
-
if (data.to.recipientAddress) {
|
|
19900
|
+
if (data.to.recipientAddress !== undefined && data.to.recipientAddress !== '') {
|
|
19483
19901
|
const toChain = data.to.chain;
|
|
19484
19902
|
if (!isValidAddressForChain(data.to.recipientAddress, toChain)) {
|
|
19485
19903
|
const chainInfo = extractChainInfo(toChain);
|
|
@@ -19487,7 +19905,7 @@ function sumAllocationsFromSources(sources) {
|
|
|
19487
19905
|
}
|
|
19488
19906
|
}
|
|
19489
19907
|
// Validate sourceAccount against each source's allocation chain
|
|
19490
|
-
if (data.from) {
|
|
19908
|
+
if (data.from !== undefined) {
|
|
19491
19909
|
assertSourceAccountAddresses(data.from);
|
|
19492
19910
|
}
|
|
19493
19911
|
}
|
|
@@ -19502,11 +19920,15 @@ function assertSourceAccountAddresses(from) {
|
|
|
19502
19920
|
from
|
|
19503
19921
|
];
|
|
19504
19922
|
for (const raw of sources){
|
|
19505
|
-
if (
|
|
19923
|
+
if (raw === null || typeof raw !== 'object' || !('sourceAccount' in raw)) {
|
|
19924
|
+
continue;
|
|
19925
|
+
}
|
|
19506
19926
|
const source = raw;
|
|
19507
|
-
if (
|
|
19927
|
+
if (source.sourceAccount === undefined || source.sourceAccount === '') {
|
|
19928
|
+
continue;
|
|
19929
|
+
}
|
|
19508
19930
|
const sourceChain = getSourceChainFromAllocations(source.allocations);
|
|
19509
|
-
if (
|
|
19931
|
+
if (sourceChain === undefined) continue;
|
|
19510
19932
|
if (!isValidAddressForChain(source.sourceAccount, sourceChain)) {
|
|
19511
19933
|
const chainInfo = extractChainInfo(sourceChain);
|
|
19512
19934
|
throw createInvalidAddressError(source.sourceAccount, String(chainInfo.name), chainInfo.expectedAddressFormat);
|