@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.mjs
CHANGED
|
@@ -658,6 +658,11 @@ class KitError extends Error {
|
|
|
658
658
|
name: 'INPUT_UNSUPPORTED_TOKEN',
|
|
659
659
|
type: 'INPUT'
|
|
660
660
|
},
|
|
661
|
+
/** Action not supported by this adapter / ecosystem */ UNSUPPORTED_ACTION: {
|
|
662
|
+
code: 1008,
|
|
663
|
+
name: 'INPUT_UNSUPPORTED_ACTION',
|
|
664
|
+
type: 'INPUT'
|
|
665
|
+
},
|
|
661
666
|
/** No route satisfies the slippage or minimum-output constraint */ SLIPPAGE_CONSTRAINT_NOT_MET: {
|
|
662
667
|
code: 1009,
|
|
663
668
|
name: 'INPUT_SLIPPAGE_CONSTRAINT_NOT_MET',
|
|
@@ -2292,6 +2297,8 @@ class KitError extends Error {
|
|
|
2292
2297
|
Blockchain["Optimism_Sepolia"] = "Optimism_Sepolia";
|
|
2293
2298
|
Blockchain["Pharos"] = "Pharos";
|
|
2294
2299
|
Blockchain["Pharos_Testnet"] = "Pharos_Testnet";
|
|
2300
|
+
Blockchain["Plasma"] = "Plasma";
|
|
2301
|
+
Blockchain["Plasma_Testnet"] = "Plasma_Testnet";
|
|
2295
2302
|
Blockchain["Polkadot_Asset_Hub"] = "Polkadot_Asset_Hub";
|
|
2296
2303
|
Blockchain["Polkadot_Westmint"] = "Polkadot_Westmint";
|
|
2297
2304
|
Blockchain["Plume"] = "Plume";
|
|
@@ -2361,6 +2368,7 @@ var BridgeChain;
|
|
|
2361
2368
|
BridgeChain["Morph"] = "Morph";
|
|
2362
2369
|
BridgeChain["Optimism"] = "Optimism";
|
|
2363
2370
|
BridgeChain["Pharos"] = "Pharos";
|
|
2371
|
+
BridgeChain["Plasma"] = "Plasma";
|
|
2364
2372
|
BridgeChain["Plume"] = "Plume";
|
|
2365
2373
|
BridgeChain["Polygon"] = "Polygon";
|
|
2366
2374
|
BridgeChain["Sei"] = "Sei";
|
|
@@ -2387,6 +2395,7 @@ var BridgeChain;
|
|
|
2387
2395
|
BridgeChain["Morph_Testnet"] = "Morph_Testnet";
|
|
2388
2396
|
BridgeChain["Optimism_Sepolia"] = "Optimism_Sepolia";
|
|
2389
2397
|
BridgeChain["Pharos_Testnet"] = "Pharos_Testnet";
|
|
2398
|
+
BridgeChain["Plasma_Testnet"] = "Plasma_Testnet";
|
|
2390
2399
|
BridgeChain["Plume_Testnet"] = "Plume_Testnet";
|
|
2391
2400
|
BridgeChain["Polygon_Amoy_Testnet"] = "Polygon_Amoy_Testnet";
|
|
2392
2401
|
BridgeChain["Sei_Testnet"] = "Sei_Testnet";
|
|
@@ -2833,6 +2842,8 @@ var EarnChain;
|
|
|
2833
2842
|
* This program handles minting operations for Gateway transactions
|
|
2834
2843
|
* on Solana devnet.
|
|
2835
2844
|
*/ const GATEWAY_MINTER_SOLANA_DEVNET = 'GATEmKK2ECL1brEngQZWCgMWPbvrEYqsV6u29dAaHavr';
|
|
2845
|
+
/** TokenMessengerWithFees address shared by enabled EVM mainnet sources. */ const TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET = '0x71f54F818671cD0D7ea140Da213e5C8b5C92a408';
|
|
2846
|
+
/** TokenMessengerWithFees address shared by enabled EVM testnet sources. */ const TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET = '0x8745D906D67C346E5eb1aEEED38Eb87F34DF0C0A';
|
|
2836
2847
|
/**
|
|
2837
2848
|
* Circle's fee recipient address for EVM chains.
|
|
2838
2849
|
*
|
|
@@ -2880,6 +2891,7 @@ var EarnChain;
|
|
|
2880
2891
|
v2: {
|
|
2881
2892
|
type: 'split',
|
|
2882
2893
|
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
2894
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
2883
2895
|
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
2884
2896
|
confirmations: 1,
|
|
2885
2897
|
fastConfirmations: 1
|
|
@@ -2947,6 +2959,7 @@ var EarnChain;
|
|
|
2947
2959
|
v2: {
|
|
2948
2960
|
type: 'split',
|
|
2949
2961
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
2962
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
2950
2963
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
2951
2964
|
confirmations: 65,
|
|
2952
2965
|
fastConfirmations: 1
|
|
@@ -3011,6 +3024,7 @@ var EarnChain;
|
|
|
3011
3024
|
v2: {
|
|
3012
3025
|
type: 'split',
|
|
3013
3026
|
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
3027
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
3014
3028
|
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
3015
3029
|
confirmations: 65,
|
|
3016
3030
|
fastConfirmations: 1
|
|
@@ -3075,6 +3089,7 @@ var EarnChain;
|
|
|
3075
3089
|
v2: {
|
|
3076
3090
|
type: 'split',
|
|
3077
3091
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
3092
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
3078
3093
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
3079
3094
|
confirmations: 1,
|
|
3080
3095
|
fastConfirmations: 1
|
|
@@ -3136,6 +3151,7 @@ var EarnChain;
|
|
|
3136
3151
|
v2: {
|
|
3137
3152
|
type: 'split',
|
|
3138
3153
|
tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
|
|
3154
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
3139
3155
|
messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
|
|
3140
3156
|
confirmations: 1,
|
|
3141
3157
|
fastConfirmations: 1
|
|
@@ -3203,6 +3219,7 @@ var EarnChain;
|
|
|
3203
3219
|
v2: {
|
|
3204
3220
|
type: 'split',
|
|
3205
3221
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
3222
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
3206
3223
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
3207
3224
|
confirmations: 65,
|
|
3208
3225
|
fastConfirmations: 1
|
|
@@ -3267,6 +3284,7 @@ var EarnChain;
|
|
|
3267
3284
|
v2: {
|
|
3268
3285
|
type: 'split',
|
|
3269
3286
|
tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
|
|
3287
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
3270
3288
|
messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
|
|
3271
3289
|
confirmations: 65,
|
|
3272
3290
|
fastConfirmations: 1
|
|
@@ -3377,6 +3395,7 @@ var EarnChain;
|
|
|
3377
3395
|
v2: {
|
|
3378
3396
|
type: 'split',
|
|
3379
3397
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
3398
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
3380
3399
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
3381
3400
|
confirmations: 65,
|
|
3382
3401
|
fastConfirmations: 1
|
|
@@ -3421,6 +3440,7 @@ var EarnChain;
|
|
|
3421
3440
|
v2: {
|
|
3422
3441
|
type: 'split',
|
|
3423
3442
|
tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
|
|
3443
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
3424
3444
|
messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
|
|
3425
3445
|
confirmations: 65,
|
|
3426
3446
|
fastConfirmations: 1
|
|
@@ -3652,6 +3672,7 @@ var EarnChain;
|
|
|
3652
3672
|
v2: {
|
|
3653
3673
|
type: 'split',
|
|
3654
3674
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
3675
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
3655
3676
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
3656
3677
|
confirmations: 65,
|
|
3657
3678
|
fastConfirmations: 2
|
|
@@ -3716,6 +3737,7 @@ var EarnChain;
|
|
|
3716
3737
|
v2: {
|
|
3717
3738
|
type: 'split',
|
|
3718
3739
|
tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
|
|
3740
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
3719
3741
|
messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
|
|
3720
3742
|
confirmations: 65,
|
|
3721
3743
|
fastConfirmations: 2
|
|
@@ -3826,6 +3848,7 @@ var EarnChain;
|
|
|
3826
3848
|
v2: {
|
|
3827
3849
|
type: 'split',
|
|
3828
3850
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
3851
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
3829
3852
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
3830
3853
|
confirmations: 1,
|
|
3831
3854
|
fastConfirmations: 1
|
|
@@ -3885,6 +3908,7 @@ var EarnChain;
|
|
|
3885
3908
|
v2: {
|
|
3886
3909
|
type: 'split',
|
|
3887
3910
|
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
3911
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
3888
3912
|
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
3889
3913
|
confirmations: 1,
|
|
3890
3914
|
fastConfirmations: 1
|
|
@@ -4039,6 +4063,7 @@ var EarnChain;
|
|
|
4039
4063
|
v2: {
|
|
4040
4064
|
type: 'split',
|
|
4041
4065
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
4066
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
4042
4067
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
4043
4068
|
confirmations: 65,
|
|
4044
4069
|
fastConfirmations: 1
|
|
@@ -4086,6 +4111,7 @@ var EarnChain;
|
|
|
4086
4111
|
v2: {
|
|
4087
4112
|
type: 'split',
|
|
4088
4113
|
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
4114
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
4089
4115
|
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
4090
4116
|
confirmations: 65,
|
|
4091
4117
|
fastConfirmations: 1
|
|
@@ -4130,6 +4156,7 @@ var EarnChain;
|
|
|
4130
4156
|
v2: {
|
|
4131
4157
|
type: 'split',
|
|
4132
4158
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
4159
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
4133
4160
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
4134
4161
|
confirmations: 1,
|
|
4135
4162
|
fastConfirmations: 1
|
|
@@ -4175,6 +4202,7 @@ var EarnChain;
|
|
|
4175
4202
|
v2: {
|
|
4176
4203
|
type: 'split',
|
|
4177
4204
|
tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
|
|
4205
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
4178
4206
|
messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
|
|
4179
4207
|
confirmations: 1,
|
|
4180
4208
|
fastConfirmations: 1
|
|
@@ -4221,6 +4249,7 @@ var EarnChain;
|
|
|
4221
4249
|
v2: {
|
|
4222
4250
|
type: 'split',
|
|
4223
4251
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
4252
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
4224
4253
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
4225
4254
|
confirmations: 1,
|
|
4226
4255
|
fastConfirmations: 1
|
|
@@ -4534,6 +4563,7 @@ var EarnChain;
|
|
|
4534
4563
|
v2: {
|
|
4535
4564
|
type: 'split',
|
|
4536
4565
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
4566
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
4537
4567
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
4538
4568
|
confirmations: 65,
|
|
4539
4569
|
fastConfirmations: 1
|
|
@@ -4598,6 +4628,7 @@ var EarnChain;
|
|
|
4598
4628
|
v2: {
|
|
4599
4629
|
type: 'split',
|
|
4600
4630
|
tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
|
|
4631
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
4601
4632
|
messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
|
|
4602
4633
|
confirmations: 65,
|
|
4603
4634
|
fastConfirmations: 1
|
|
@@ -4718,6 +4749,98 @@ var EarnChain;
|
|
|
4718
4749
|
}
|
|
4719
4750
|
});
|
|
4720
4751
|
|
|
4752
|
+
/**
|
|
4753
|
+
* Plasma Mainnet chain definition
|
|
4754
|
+
* @remarks
|
|
4755
|
+
* This represents the official production network for the Plasma blockchain.
|
|
4756
|
+
* Plasma is an EVM-equivalent Layer 1 blockchain purpose-built for global
|
|
4757
|
+
* stablecoin payments, with deterministic BFT finality (PlasmaBFT/Fast-HotStuff).
|
|
4758
|
+
*/ const Plasma = defineChain({
|
|
4759
|
+
type: 'evm',
|
|
4760
|
+
chain: Blockchain.Plasma,
|
|
4761
|
+
name: 'Plasma',
|
|
4762
|
+
title: 'Plasma Mainnet',
|
|
4763
|
+
nativeCurrency: {
|
|
4764
|
+
name: 'Plasma',
|
|
4765
|
+
symbol: 'XPL',
|
|
4766
|
+
decimals: 18
|
|
4767
|
+
},
|
|
4768
|
+
chainId: 9745,
|
|
4769
|
+
isTestnet: false,
|
|
4770
|
+
explorerUrl: 'https://plasmascan.to/tx/{hash}',
|
|
4771
|
+
rpcEndpoints: [
|
|
4772
|
+
'https://rpc.plasma.to'
|
|
4773
|
+
],
|
|
4774
|
+
eurcAddress: '0x3EE196E78d4d4248b849B8E1C7F44C5457FAFD2C',
|
|
4775
|
+
usdcAddress: '0x2d661C89D812261039AF9764eceaAee884f5F67F',
|
|
4776
|
+
usdtAddress: null,
|
|
4777
|
+
cctp: {
|
|
4778
|
+
domain: 33,
|
|
4779
|
+
contracts: {
|
|
4780
|
+
v2: {
|
|
4781
|
+
type: 'split',
|
|
4782
|
+
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
4783
|
+
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
4784
|
+
confirmations: 3,
|
|
4785
|
+
fastConfirmations: 1
|
|
4786
|
+
}
|
|
4787
|
+
},
|
|
4788
|
+
forwarderSupported: {
|
|
4789
|
+
source: false,
|
|
4790
|
+
destination: false
|
|
4791
|
+
}
|
|
4792
|
+
},
|
|
4793
|
+
kitContracts: {
|
|
4794
|
+
bridge: BRIDGE_CONTRACT_EVM_MAINNET
|
|
4795
|
+
}
|
|
4796
|
+
});
|
|
4797
|
+
|
|
4798
|
+
/**
|
|
4799
|
+
* Plasma Testnet chain definition
|
|
4800
|
+
* @remarks
|
|
4801
|
+
* This represents the official test network for the Plasma blockchain.
|
|
4802
|
+
* Plasma is an EVM-equivalent Layer 1 blockchain purpose-built for global
|
|
4803
|
+
* stablecoin payments, with deterministic BFT finality (PlasmaBFT/Fast-HotStuff).
|
|
4804
|
+
*/ const PlasmaTestnet = defineChain({
|
|
4805
|
+
type: 'evm',
|
|
4806
|
+
chain: Blockchain.Plasma_Testnet,
|
|
4807
|
+
name: 'Plasma Testnet',
|
|
4808
|
+
title: 'Plasma Testnet',
|
|
4809
|
+
nativeCurrency: {
|
|
4810
|
+
name: 'Plasma',
|
|
4811
|
+
symbol: 'XPL',
|
|
4812
|
+
decimals: 18
|
|
4813
|
+
},
|
|
4814
|
+
chainId: 9746,
|
|
4815
|
+
isTestnet: true,
|
|
4816
|
+
explorerUrl: 'https://testnet.plasmascan.to/tx/{hash}',
|
|
4817
|
+
rpcEndpoints: [
|
|
4818
|
+
'https://testnet-rpc.plasma.to'
|
|
4819
|
+
],
|
|
4820
|
+
eurcAddress: '0x98AfA0F93Dd993B736399f9074eDcEBD1985A330',
|
|
4821
|
+
usdcAddress: '0xE67Fb267022cBA8064Dd388CC2FED724F3120D9D',
|
|
4822
|
+
usdtAddress: null,
|
|
4823
|
+
cctp: {
|
|
4824
|
+
domain: 33,
|
|
4825
|
+
contracts: {
|
|
4826
|
+
v2: {
|
|
4827
|
+
type: 'split',
|
|
4828
|
+
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
4829
|
+
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
4830
|
+
confirmations: 3,
|
|
4831
|
+
fastConfirmations: 1
|
|
4832
|
+
}
|
|
4833
|
+
},
|
|
4834
|
+
forwarderSupported: {
|
|
4835
|
+
source: false,
|
|
4836
|
+
destination: false
|
|
4837
|
+
}
|
|
4838
|
+
},
|
|
4839
|
+
kitContracts: {
|
|
4840
|
+
bridge: BRIDGE_CONTRACT_EVM_TESTNET
|
|
4841
|
+
}
|
|
4842
|
+
});
|
|
4843
|
+
|
|
4721
4844
|
/**
|
|
4722
4845
|
* Plume Mainnet chain definition
|
|
4723
4846
|
* @remarks
|
|
@@ -4749,6 +4872,7 @@ var EarnChain;
|
|
|
4749
4872
|
v2: {
|
|
4750
4873
|
type: 'split',
|
|
4751
4874
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
4875
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
4752
4876
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
4753
4877
|
confirmations: 65,
|
|
4754
4878
|
fastConfirmations: 1
|
|
@@ -4795,6 +4919,7 @@ var EarnChain;
|
|
|
4795
4919
|
v2: {
|
|
4796
4920
|
type: 'split',
|
|
4797
4921
|
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
4922
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
4798
4923
|
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
4799
4924
|
confirmations: 65,
|
|
4800
4925
|
fastConfirmations: 1
|
|
@@ -4896,6 +5021,7 @@ var EarnChain;
|
|
|
4896
5021
|
v2: {
|
|
4897
5022
|
type: 'split',
|
|
4898
5023
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
5024
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
4899
5025
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
4900
5026
|
confirmations: 33,
|
|
4901
5027
|
fastConfirmations: 13
|
|
@@ -4961,6 +5087,7 @@ var EarnChain;
|
|
|
4961
5087
|
v2: {
|
|
4962
5088
|
type: 'split',
|
|
4963
5089
|
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
5090
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
4964
5091
|
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
4965
5092
|
confirmations: 33,
|
|
4966
5093
|
fastConfirmations: 13
|
|
@@ -5020,6 +5147,7 @@ var EarnChain;
|
|
|
5020
5147
|
v2: {
|
|
5021
5148
|
type: 'split',
|
|
5022
5149
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
5150
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
5023
5151
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
5024
5152
|
confirmations: 1,
|
|
5025
5153
|
fastConfirmations: 1
|
|
@@ -5079,6 +5207,7 @@ var EarnChain;
|
|
|
5079
5207
|
v2: {
|
|
5080
5208
|
type: 'split',
|
|
5081
5209
|
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
5210
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
5082
5211
|
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
5083
5212
|
confirmations: 1,
|
|
5084
5213
|
fastConfirmations: 1
|
|
@@ -5136,6 +5265,7 @@ var EarnChain;
|
|
|
5136
5265
|
v2: {
|
|
5137
5266
|
type: 'split',
|
|
5138
5267
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
5268
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
5139
5269
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
5140
5270
|
confirmations: 1,
|
|
5141
5271
|
fastConfirmations: 1
|
|
@@ -5194,6 +5324,7 @@ var EarnChain;
|
|
|
5194
5324
|
v2: {
|
|
5195
5325
|
type: 'split',
|
|
5196
5326
|
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
5327
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
5197
5328
|
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
5198
5329
|
confirmations: 1,
|
|
5199
5330
|
fastConfirmations: 1
|
|
@@ -5509,6 +5640,7 @@ var EarnChain;
|
|
|
5509
5640
|
v2: {
|
|
5510
5641
|
type: 'split',
|
|
5511
5642
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
5643
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
5512
5644
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
5513
5645
|
confirmations: 65,
|
|
5514
5646
|
fastConfirmations: 1
|
|
@@ -5573,6 +5705,7 @@ var EarnChain;
|
|
|
5573
5705
|
v2: {
|
|
5574
5706
|
type: 'split',
|
|
5575
5707
|
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
5708
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
5576
5709
|
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
5577
5710
|
confirmations: 65,
|
|
5578
5711
|
fastConfirmations: 1
|
|
@@ -5630,6 +5763,7 @@ var EarnChain;
|
|
|
5630
5763
|
v2: {
|
|
5631
5764
|
type: 'split',
|
|
5632
5765
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cF5d',
|
|
5766
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
5633
5767
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
5634
5768
|
confirmations: 65,
|
|
5635
5769
|
fastConfirmations: 1
|
|
@@ -5689,6 +5823,7 @@ var EarnChain;
|
|
|
5689
5823
|
v2: {
|
|
5690
5824
|
type: 'split',
|
|
5691
5825
|
tokenMessenger: '0x8fe6b999dc680ccfdd5bf7eb0974218be2542daa',
|
|
5826
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
5692
5827
|
messageTransmitter: '0xe737e5cebeeba77efe34d4aa090756590b1ce275',
|
|
5693
5828
|
confirmations: 65,
|
|
5694
5829
|
fastConfirmations: 1
|
|
@@ -5749,6 +5884,7 @@ var EarnChain;
|
|
|
5749
5884
|
v2: {
|
|
5750
5885
|
type: 'split',
|
|
5751
5886
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
5887
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
5752
5888
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
5753
5889
|
confirmations: 3,
|
|
5754
5890
|
fastConfirmations: 3
|
|
@@ -5794,6 +5930,7 @@ var EarnChain;
|
|
|
5794
5930
|
v2: {
|
|
5795
5931
|
type: 'split',
|
|
5796
5932
|
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
5933
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
5797
5934
|
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
5798
5935
|
confirmations: 3,
|
|
5799
5936
|
fastConfirmations: 1
|
|
@@ -6004,6 +6141,8 @@ var Chains = /*#__PURE__*/Object.freeze({
|
|
|
6004
6141
|
OptimismSepolia: OptimismSepolia,
|
|
6005
6142
|
Pharos: Pharos,
|
|
6006
6143
|
PharosTestnet: PharosTestnet,
|
|
6144
|
+
Plasma: Plasma,
|
|
6145
|
+
PlasmaTestnet: PlasmaTestnet,
|
|
6007
6146
|
Plume: Plume,
|
|
6008
6147
|
PlumeTestnet: PlumeTestnet,
|
|
6009
6148
|
PolkadotAssetHub: PolkadotAssetHub,
|
|
@@ -7969,6 +8108,7 @@ function parseOrThrow(value, schema, context) {
|
|
|
7969
8108
|
[Blockchain.Noble]: 'uusdc',
|
|
7970
8109
|
[Blockchain.Optimism]: '0x0b2c639c533813f4aa9d7837caf62653d097ff85',
|
|
7971
8110
|
[Blockchain.Pharos]: '0xC879C018dB60520F4355C26eD1a6D572cdAC1815',
|
|
8111
|
+
[Blockchain.Plasma]: '0x2d661C89D812261039AF9764eceaAee884f5F67F',
|
|
7972
8112
|
[Blockchain.Plume]: '0x222365EF19F7947e5484218551B56bb3965Aa7aF',
|
|
7973
8113
|
[Blockchain.Polkadot_Asset_Hub]: '1337',
|
|
7974
8114
|
[Blockchain.Polygon]: '0x3c499c542cef5e3811e1192ce70d8cc03d5c3359',
|
|
@@ -7989,6 +8129,7 @@ function parseOrThrow(value, schema, context) {
|
|
|
7989
8129
|
[Blockchain.Arbitrum_Sepolia]: '0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d',
|
|
7990
8130
|
[Blockchain.Avalanche_Fuji]: '0x5425890298aed601595a70AB815c96711a31Bc65',
|
|
7991
8131
|
[Blockchain.Base_Sepolia]: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',
|
|
8132
|
+
[Blockchain.Celo_Alfajores_Testnet]: '0x2F25deB3848C207fc8E0c34035B3Ba7fC157602B',
|
|
7992
8133
|
[Blockchain.Codex_Testnet]: '0x6d7f141b6819C2c9CC2f818e6ad549E7Ca090F8f',
|
|
7993
8134
|
[Blockchain.Cronos_Testnet]: '0xEb33dc5fac03833e132593659e1dE7256aB59794',
|
|
7994
8135
|
[Blockchain.Edge_Testnet]: '0x2d9F7CAD728051AA35Ecdc472a14cf8cDF5CFD6B',
|
|
@@ -8004,6 +8145,7 @@ function parseOrThrow(value, schema, context) {
|
|
|
8004
8145
|
[Blockchain.Noble_Testnet]: 'uusdc',
|
|
8005
8146
|
[Blockchain.Optimism_Sepolia]: '0x5fd84259d66Cd46123540766Be93DFE6D43130D7',
|
|
8006
8147
|
[Blockchain.Pharos_Testnet]: '0xcfC8330f4BCAB529c625D12781b1C19466A9Fc8B',
|
|
8148
|
+
[Blockchain.Plasma_Testnet]: '0xE67Fb267022cBA8064Dd388CC2FED724F3120D9D',
|
|
8007
8149
|
[Blockchain.Plume_Testnet]: '0xcB5f30e335672893c7eb944B374c196392C19D18',
|
|
8008
8150
|
[Blockchain.Polkadot_Westmint]: '31337',
|
|
8009
8151
|
[Blockchain.Polygon_Amoy_Testnet]: '0x41e94eb019c0762f9bfcf9fb1e58725bfb0e7582',
|
|
@@ -8066,6 +8208,7 @@ function parseOrThrow(value, schema, context) {
|
|
|
8066
8208
|
[Blockchain.Base]: '0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42',
|
|
8067
8209
|
[Blockchain.Cronos]: '0xA6dE01a2d62C6B5f3525d768f34d276652C554c8',
|
|
8068
8210
|
[Blockchain.Ethereum]: '0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c',
|
|
8211
|
+
[Blockchain.Plasma]: '0x3EE196E78d4d4248b849B8E1C7F44C5457FAFD2C',
|
|
8069
8212
|
[Blockchain.Solana]: 'HzwqbKZw8HxMN6bF2yFZNrht3c2iXXzpKcFu7uBEDKtr',
|
|
8070
8213
|
[Blockchain.World_Chain]: '0x1C60ba0A0eD1019e8Eb035E6daF4155A5cE2380B',
|
|
8071
8214
|
// =========================================================================
|
|
@@ -8074,7 +8217,8 @@ function parseOrThrow(value, schema, context) {
|
|
|
8074
8217
|
[Blockchain.Arc_Testnet]: '0x89B50855Aa3bE2F677cD6303Cec089B5F319D72a',
|
|
8075
8218
|
[Blockchain.Base_Sepolia]: '0x808456652fdb597867f38412077A9182bf77359F',
|
|
8076
8219
|
[Blockchain.Cronos_Testnet]: '0x31f7538adb53cF16350e6B0c89d03D91b7D12c46',
|
|
8077
|
-
[Blockchain.Ethereum_Sepolia]: '0x08210F9170F89Ab7658F0B5E3fF39b0E03C594D4'
|
|
8220
|
+
[Blockchain.Ethereum_Sepolia]: '0x08210F9170F89Ab7658F0B5E3fF39b0E03C594D4',
|
|
8221
|
+
[Blockchain.Plasma_Testnet]: '0x98AfA0F93Dd993B736399f9074eDcEBD1985A330'
|
|
8078
8222
|
}
|
|
8079
8223
|
};
|
|
8080
8224
|
|
|
@@ -8881,7 +9025,7 @@ function parseOrThrow(value, schema, context) {
|
|
|
8881
9025
|
}
|
|
8882
9026
|
|
|
8883
9027
|
var name = "@circle-fin/unified-balance-kit";
|
|
8884
|
-
var version = "1.
|
|
9028
|
+
var version = "1.5.0";
|
|
8885
9029
|
var pkg = {
|
|
8886
9030
|
name: name,
|
|
8887
9031
|
version: version};
|
|
@@ -9164,6 +9308,110 @@ var pkg = {
|
|
|
9164
9308
|
* ```
|
|
9165
9309
|
*/ const USDC_DECIMALS$1 = 6;
|
|
9166
9310
|
|
|
9311
|
+
/**
|
|
9312
|
+
* Canonical list of actions that do not prepare or submit transactions.
|
|
9313
|
+
*
|
|
9314
|
+
* @internal
|
|
9315
|
+
*/ const READ_ACTION_KEYS = [
|
|
9316
|
+
'token.allowance',
|
|
9317
|
+
'token.balanceOf',
|
|
9318
|
+
'token.name',
|
|
9319
|
+
'native.balanceOf',
|
|
9320
|
+
'usdc.allowance',
|
|
9321
|
+
'usdc.balanceOf',
|
|
9322
|
+
'usdc.name',
|
|
9323
|
+
'gateway.v1.isDelegate',
|
|
9324
|
+
'gateway.v1.withdrawingBalance',
|
|
9325
|
+
'gateway.v1.withdrawalBlock',
|
|
9326
|
+
'gateway.v1.signBurnIntents'
|
|
9327
|
+
];
|
|
9328
|
+
const READ_ACTION_KEY_SET = new Set(READ_ACTION_KEYS);
|
|
9329
|
+
/**
|
|
9330
|
+
* Check whether a runtime value identifies a read action.
|
|
9331
|
+
*
|
|
9332
|
+
* @param action - The value to classify.
|
|
9333
|
+
* @returns Whether the value is a registered read-action key.
|
|
9334
|
+
*
|
|
9335
|
+
* @example
|
|
9336
|
+
* ```typescript
|
|
9337
|
+
* import { isReadActionKey } from '@core/adapter'
|
|
9338
|
+
*
|
|
9339
|
+
* if (isReadActionKey(value)) {
|
|
9340
|
+
* await adapter.readAction(value, params, context)
|
|
9341
|
+
* }
|
|
9342
|
+
* ```
|
|
9343
|
+
*
|
|
9344
|
+
* @internal
|
|
9345
|
+
*/ function isReadActionKey(action) {
|
|
9346
|
+
return typeof action === 'string' && READ_ACTION_KEY_SET.has(action);
|
|
9347
|
+
}
|
|
9348
|
+
|
|
9349
|
+
/**
|
|
9350
|
+
* Create the standard error for a missing or non-read action.
|
|
9351
|
+
*
|
|
9352
|
+
* @param action - The unsupported action value.
|
|
9353
|
+
* @returns A fatal unsupported-action error.
|
|
9354
|
+
*
|
|
9355
|
+
* @internal
|
|
9356
|
+
*/ function createUnsupportedReadActionError(action) {
|
|
9357
|
+
return new KitError({
|
|
9358
|
+
...InputError.UNSUPPORTED_ACTION,
|
|
9359
|
+
recoverability: 'FATAL',
|
|
9360
|
+
message: `Read action "${String(action)}" is not registered in this adapter.`
|
|
9361
|
+
});
|
|
9362
|
+
}
|
|
9363
|
+
/**
|
|
9364
|
+
* Execute a read through the adapter's dedicated read seam when available.
|
|
9365
|
+
*
|
|
9366
|
+
* @remarks
|
|
9367
|
+
* Fall back to the legacy `prepareAction().execute()` contract so providers
|
|
9368
|
+
* remain runtime-compatible with adapter versions released before `readAction`.
|
|
9369
|
+
* Consumers must upgrade their adapter package for reads to bypass custom
|
|
9370
|
+
* `prepareAction` wrappers.
|
|
9371
|
+
*
|
|
9372
|
+
* @typeParam TAdapterCapabilities - The adapter capabilities type.
|
|
9373
|
+
* @typeParam TActionKey - The read action key.
|
|
9374
|
+
* @param adapter - The adapter that owns the read action.
|
|
9375
|
+
* @param action - The read action to execute.
|
|
9376
|
+
* @param params - The parameters for the read action.
|
|
9377
|
+
* @param ctx - The operation context.
|
|
9378
|
+
* @returns The raw read-action result.
|
|
9379
|
+
* @throws {KitError} When `action` is not a supported read-action key.
|
|
9380
|
+
*
|
|
9381
|
+
* @example
|
|
9382
|
+
* ```typescript
|
|
9383
|
+
* import { executeAdapterReadAction } from '@core/adapter'
|
|
9384
|
+
* import { Ethereum } from '@core/chains'
|
|
9385
|
+
*
|
|
9386
|
+
* const allowance = await executeAdapterReadAction(
|
|
9387
|
+
* adapter,
|
|
9388
|
+
* 'token.allowance',
|
|
9389
|
+
* { tokenAddress, delegate },
|
|
9390
|
+
* { chain: Ethereum },
|
|
9391
|
+
* )
|
|
9392
|
+
* ```
|
|
9393
|
+
*
|
|
9394
|
+
* @internal
|
|
9395
|
+
*/ async function executeAdapterReadAction(adapter, action, params, ctx) {
|
|
9396
|
+
if (!isReadActionKey(action)) {
|
|
9397
|
+
throw createUnsupportedReadActionError(action);
|
|
9398
|
+
}
|
|
9399
|
+
const runtimeAdapter = adapter;
|
|
9400
|
+
if (typeof runtimeAdapter.readAction === 'function') {
|
|
9401
|
+
return runtimeAdapter.readAction(action, params, ctx);
|
|
9402
|
+
}
|
|
9403
|
+
let request;
|
|
9404
|
+
try {
|
|
9405
|
+
request = await adapter.prepareAction(action, params, ctx);
|
|
9406
|
+
} catch (error) {
|
|
9407
|
+
if (error instanceof Error && error.message === `Action ${action} is not supported`) {
|
|
9408
|
+
throw createUnsupportedReadActionError(action);
|
|
9409
|
+
}
|
|
9410
|
+
throw error;
|
|
9411
|
+
}
|
|
9412
|
+
return request.execute();
|
|
9413
|
+
}
|
|
9414
|
+
|
|
9167
9415
|
/**
|
|
9168
9416
|
* Schema for validating hexadecimal strings with '0x' prefix.
|
|
9169
9417
|
*
|
|
@@ -9373,16 +9621,15 @@ var pkg = {
|
|
|
9373
9621
|
* ```
|
|
9374
9622
|
*/ const validateBalanceForTransaction = async (params)=>{
|
|
9375
9623
|
const { amount, adapter, token, tokenAddress, operationContext } = params;
|
|
9376
|
-
const
|
|
9624
|
+
const balance = await executeAdapterReadAction(adapter, 'usdc.balanceOf', {
|
|
9377
9625
|
walletAddress: operationContext.address
|
|
9378
9626
|
}, operationContext);
|
|
9379
|
-
|
|
9380
|
-
if (BigInt(balance) < BigInt(amount)) {
|
|
9627
|
+
if (BigInt(String(balance)) < BigInt(amount)) {
|
|
9381
9628
|
// Extract chain name from operationContext
|
|
9382
9629
|
const chainName = extractChainInfo(operationContext.chain).name;
|
|
9383
9630
|
// Create KitError with rich context in trace
|
|
9384
9631
|
throw createInsufficientTokenBalanceError(chainName, token, {
|
|
9385
|
-
balance: balance
|
|
9632
|
+
balance: String(balance),
|
|
9386
9633
|
amount,
|
|
9387
9634
|
tokenAddress,
|
|
9388
9635
|
walletAddress: operationContext.address
|
|
@@ -12354,6 +12601,23 @@ async function signUnits(group, signingUnits) {
|
|
|
12354
12601
|
}
|
|
12355
12602
|
return signedSets;
|
|
12356
12603
|
}
|
|
12604
|
+
/**
|
|
12605
|
+
* Fail loudly if a signing group carries an intent it does not own.
|
|
12606
|
+
*
|
|
12607
|
+
* Every intent in a group is signed by `group.address`, so that signer must own
|
|
12608
|
+
* each intent's `spec.sourceSigner`. If distinct spend sources ever collapse
|
|
12609
|
+
* into one group again (DEVX-3638), this throws before signing instead of
|
|
12610
|
+
* silently producing a wrong-signer signature. specs are bytes32 and
|
|
12611
|
+
* `group.address` is a native address, so normalize both before comparing.
|
|
12612
|
+
*/ function assertGroupSignerOwnsIntents(group) {
|
|
12613
|
+
if (group.address == null || group.address === '') return;
|
|
12614
|
+
const groupSigner = convertAddress(group.address, 'bytes32').toLowerCase();
|
|
12615
|
+
for (const intent of group.intents){
|
|
12616
|
+
if (intent.spec.sourceSigner.toLowerCase() !== groupSigner) {
|
|
12617
|
+
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.');
|
|
12618
|
+
}
|
|
12619
|
+
}
|
|
12620
|
+
}
|
|
12357
12621
|
/**
|
|
12358
12622
|
* Sign an EVM adapter group.
|
|
12359
12623
|
*
|
|
@@ -12396,22 +12660,42 @@ async function signUnits(group, signingUnits) {
|
|
|
12396
12660
|
// Validate the collection before doing bytecode reads or asking a wallet
|
|
12397
12661
|
// to sign. evmSigningData owns the canonical BurnIntent validation.
|
|
12398
12662
|
validateGroupIntents(group.intents);
|
|
12663
|
+
// Guard against a wrong-signer collapse: the group's signer must own every
|
|
12664
|
+
// intent it carries.
|
|
12665
|
+
assertGroupSignerOwnsIntents(group);
|
|
12399
12666
|
const chainsByDomain = collectChainsByDomain(group);
|
|
12400
12667
|
const signerTypeByDomain = await classifySignerTypes(group, chainsByDomain);
|
|
12401
12668
|
const signingUnits = createSigningUnits(group, signerTypeByDomain);
|
|
12402
12669
|
return await signUnits(group, signingUnits);
|
|
12403
12670
|
}
|
|
12404
12671
|
|
|
12672
|
+
// One adapter instance can serve several signer addresses (e.g. a single
|
|
12673
|
+
// dev-controlled adapter used for multiple wallets), so the group map must be
|
|
12674
|
+
// keyed on `(adapter, sourceSigner)` rather than the adapter reference alone.
|
|
12675
|
+
// Keying on the adapter alone collapsed two same-chain sources into one group,
|
|
12676
|
+
// signing the second wallet's intent with the first wallet (DEVX-3638 /
|
|
12677
|
+
// DEVX-3194). A Map needs a primitive key, so give each adapter instance a
|
|
12678
|
+
// stable token and combine it with the (case-normalized) signer address.
|
|
12679
|
+
const adapterTokens = new WeakMap();
|
|
12680
|
+
let nextAdapterToken = 0;
|
|
12681
|
+
function groupKey(alloc) {
|
|
12682
|
+
let token = adapterTokens.get(alloc.adapter);
|
|
12683
|
+
if (token === undefined) {
|
|
12684
|
+
token = nextAdapterToken++;
|
|
12685
|
+
adapterTokens.set(alloc.adapter, token);
|
|
12686
|
+
}
|
|
12687
|
+
return `${String(token)}:${alloc.sourceSigner.toLowerCase()}`;
|
|
12688
|
+
}
|
|
12405
12689
|
/**
|
|
12406
12690
|
* Add an EVM intent into the batched EVM group map.
|
|
12407
12691
|
*
|
|
12408
|
-
* On EVM, all intents for the same adapter are batched into a
|
|
12409
|
-
* group. The signing step uses `chainsByDomain` to preserve EOA batching
|
|
12692
|
+
* On EVM, all intents for the same adapter **and signer** are batched into a
|
|
12693
|
+
* single group. The signing step uses `chainsByDomain` to preserve EOA batching
|
|
12410
12694
|
* while signing ERC-1271 intents separately on their source chains.
|
|
12411
12695
|
*
|
|
12412
12696
|
* @param intent - The burn intent to group.
|
|
12413
12697
|
* @param alloc - The allocation that resolved to this intent.
|
|
12414
|
-
* @param evmGroups - Mutable map of adapter → EVM group.
|
|
12698
|
+
* @param evmGroups - Mutable map of `(adapter, sourceSigner)` key → EVM group.
|
|
12415
12699
|
*
|
|
12416
12700
|
* @example
|
|
12417
12701
|
* ```typescript
|
|
@@ -12421,12 +12705,13 @@ async function signUnits(group, signingUnits) {
|
|
|
12421
12705
|
* groupEvmIntents(intent, alloc, groups)
|
|
12422
12706
|
* ```
|
|
12423
12707
|
*/ function groupEvmIntents(intent, alloc, evmGroups) {
|
|
12424
|
-
const
|
|
12708
|
+
const key = groupKey(alloc);
|
|
12709
|
+
const existing = evmGroups.get(key);
|
|
12425
12710
|
if (existing) {
|
|
12426
12711
|
existing.intents.push(intent);
|
|
12427
12712
|
existing.chainsByDomain.set(alloc.chain.gateway.domain, alloc.chain);
|
|
12428
12713
|
} else {
|
|
12429
|
-
evmGroups.set(
|
|
12714
|
+
evmGroups.set(key, {
|
|
12430
12715
|
adapter: alloc.adapter,
|
|
12431
12716
|
chain: alloc.chain,
|
|
12432
12717
|
intents: [
|
|
@@ -13455,6 +13740,8 @@ const gatewayInfoSchema = z.object({
|
|
|
13455
13740
|
* Fetch Gateway info from the `/v1/info` endpoint.
|
|
13456
13741
|
*
|
|
13457
13742
|
* @param isTestnet - Whether to query the testnet or mainnet API.
|
|
13743
|
+
* @param config - Optional polling config overrides, including custom
|
|
13744
|
+
* `headers` forwarded with the request.
|
|
13458
13745
|
* @returns Parsed Gateway info including per-domain processed heights.
|
|
13459
13746
|
* @throws KitError on HTTP failure or invalid response.
|
|
13460
13747
|
*
|
|
@@ -13463,11 +13750,11 @@ const gatewayInfoSchema = z.object({
|
|
|
13463
13750
|
* const info = await fetchGatewayInfo(true)
|
|
13464
13751
|
* console.log(info.domains.map(d => `${d.chain}: ${d.processedHeight}`))
|
|
13465
13752
|
* ```
|
|
13466
|
-
*/ async function fetchGatewayInfo(isTestnet) {
|
|
13753
|
+
*/ async function fetchGatewayInfo(isTestnet, config) {
|
|
13467
13754
|
const apiBaseUrl = getGatewayApiBaseUrl(isTestnet);
|
|
13468
13755
|
const url = `${apiBaseUrl}/v1/info`;
|
|
13469
13756
|
try {
|
|
13470
|
-
return await pollApiGet(url, assertGatewayInfoResponse);
|
|
13757
|
+
return await pollApiGet(url, assertGatewayInfoResponse, config);
|
|
13471
13758
|
} catch (error) {
|
|
13472
13759
|
if (error instanceof KitError) {
|
|
13473
13760
|
throw error;
|
|
@@ -13493,6 +13780,8 @@ const gatewayInfoSchema = z.object({
|
|
|
13493
13780
|
*
|
|
13494
13781
|
* @param isTestnet - Whether to query the testnet or mainnet API.
|
|
13495
13782
|
* @param domain - The Gateway domain number (e.g. 0 = Ethereum, 6 = Base).
|
|
13783
|
+
* @param config - Optional polling config overrides, including custom
|
|
13784
|
+
* `headers` forwarded with the `/v1/info` request.
|
|
13496
13785
|
* @returns The processed height as a bigint.
|
|
13497
13786
|
* @throws KitError when the domain is not found in the response.
|
|
13498
13787
|
*
|
|
@@ -13501,10 +13790,10 @@ const gatewayInfoSchema = z.object({
|
|
|
13501
13790
|
* const height = await getProcessedHeight(true, 6) // Base Sepolia
|
|
13502
13791
|
* console.log(`Gateway processed up to block ${height}`)
|
|
13503
13792
|
* ```
|
|
13504
|
-
*/ async function getProcessedHeight(isTestnet, domain) {
|
|
13793
|
+
*/ async function getProcessedHeight(isTestnet, domain, config) {
|
|
13505
13794
|
// No caching in v1 — /v1/info is cheap and delegate status checks
|
|
13506
13795
|
// are infrequent. Revisit if rate-limit or latency issues appear.
|
|
13507
|
-
const info = await fetchGatewayInfo(isTestnet);
|
|
13796
|
+
const info = await fetchGatewayInfo(isTestnet, config);
|
|
13508
13797
|
const entry = info.domains.find((d)=>d.domain === domain);
|
|
13509
13798
|
if (!entry) {
|
|
13510
13799
|
throw new KitError({
|
|
@@ -13970,12 +14259,22 @@ function throwNetworkMismatch(expected, actual) {
|
|
|
13970
14259
|
* @param allocations - Normalized allocations used to map domain → adapter/chain.
|
|
13971
14260
|
* @returns Array of groups, each with adapter, chain, and intents to sign.
|
|
13972
14261
|
*/ function groupIntentsByAdapter(intents, allocations) {
|
|
14262
|
+
// Keyed by `(adapter, sourceSigner)` (see groupEvmIntents), not by adapter
|
|
14263
|
+
// alone: two spend sources on the same chain — including two addresses behind
|
|
14264
|
+
// one shared adapter — must stay in separate signing groups.
|
|
13973
14265
|
const evmGroups = new Map();
|
|
13974
14266
|
const solanaGroups = [];
|
|
13975
14267
|
for (const intent of intents){
|
|
13976
|
-
|
|
14268
|
+
// Match each intent back to its source allocation by BOTH Gateway domain
|
|
14269
|
+
// and signer. Two spend sources on the same chain share a domain, so
|
|
14270
|
+
// matching on domain alone always returned the FIRST allocation — folding
|
|
14271
|
+
// the second wallet's intent into the first wallet's signing group so it
|
|
14272
|
+
// was signed by the wrong wallet (DEVX-3638). specs carry sourceSigner as
|
|
14273
|
+
// bytes32 and allocations carry native addresses, so normalize both.
|
|
14274
|
+
const intentSigner = intent.spec.sourceSigner.toLowerCase();
|
|
14275
|
+
const alloc = allocations.find((a)=>a.chain.gateway.domain === intent.spec.sourceDomain && convertAddress(a.sourceSigner, 'bytes32').toLowerCase() === intentSigner);
|
|
13977
14276
|
if (!alloc) {
|
|
13978
|
-
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');
|
|
14277
|
+
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');
|
|
13979
14278
|
}
|
|
13980
14279
|
if (alloc.chain.type === 'solana') {
|
|
13981
14280
|
solanaGroups.push(groupSolanaIntents(intent, alloc));
|
|
@@ -17392,12 +17691,12 @@ const FORWARDER_POLL_TIMEOUT_MS = 300_000;
|
|
|
17392
17691
|
* exceeds the 5-minute timeout without reaching a terminal status.
|
|
17393
17692
|
* @throws KitError Propagated from {@link pollApiGet} if the HTTP
|
|
17394
17693
|
* request itself fails or returns a non-OK response.
|
|
17395
|
-
*/ async function pollForwarderCompletion(apiBaseUrl, transferId) {
|
|
17694
|
+
*/ async function pollForwarderCompletion(apiBaseUrl, transferId, requestConfig) {
|
|
17396
17695
|
const startTime = Date.now();
|
|
17397
17696
|
while(Date.now() - startTime < FORWARDER_POLL_TIMEOUT_MS){
|
|
17398
17697
|
let status;
|
|
17399
17698
|
try {
|
|
17400
|
-
status = await pollApiGet(`${apiBaseUrl}/v1/transfer/${transferId}`, assertGatewayTransferDetails);
|
|
17699
|
+
status = await pollApiGet(`${apiBaseUrl}/v1/transfer/${transferId}`, assertGatewayTransferDetails, requestConfig);
|
|
17401
17700
|
} catch (error) {
|
|
17402
17701
|
throwGatewayApiError(error);
|
|
17403
17702
|
}
|
|
@@ -17515,7 +17814,7 @@ const FORWARDER_POLL_TIMEOUT_MS = 300_000;
|
|
|
17515
17814
|
* @param params - Spend parameters (source(s) and token).
|
|
17516
17815
|
* @param destChain - Resolved destination chain (used for network type).
|
|
17517
17816
|
* @returns Confirmed balances tagged with their originating source index.
|
|
17518
|
-
*/ async function fetchChainBalances(params, destChain) {
|
|
17817
|
+
*/ async function fetchChainBalances(params, destChain, requestConfig) {
|
|
17519
17818
|
const rawSources = Array.isArray(params.from) ? params.from : [
|
|
17520
17819
|
params.from
|
|
17521
17820
|
];
|
|
@@ -17544,7 +17843,7 @@ const FORWARDER_POLL_TIMEOUT_MS = 300_000;
|
|
|
17544
17843
|
token: params.token,
|
|
17545
17844
|
sources: querySource,
|
|
17546
17845
|
networkType
|
|
17547
|
-
});
|
|
17846
|
+
}, requestConfig);
|
|
17548
17847
|
}));
|
|
17549
17848
|
const chainBalances = [];
|
|
17550
17849
|
for(let i = 0; i < balanceResults.length; i++){
|
|
@@ -17617,9 +17916,9 @@ const FORWARDER_POLL_TIMEOUT_MS = 300_000;
|
|
|
17617
17916
|
* @param recipientAddress - Resolved recipient address.
|
|
17618
17917
|
* @param useForwarder - Whether the Forwarding Service path is active.
|
|
17619
17918
|
* @returns Allocations, intents, and (auto-allocation only) confirmed balances.
|
|
17620
|
-
*/ async function resolveAllocationsAndIntents(params, destChain, recipientAddress, useForwarder) {
|
|
17919
|
+
*/ async function resolveAllocationsAndIntents(params, destChain, recipientAddress, useForwarder, requestConfig) {
|
|
17621
17920
|
if (params.amountIn) {
|
|
17622
|
-
const chainBalances = await fetchChainBalances(params, destChain);
|
|
17921
|
+
const chainBalances = await fetchChainBalances(params, destChain, requestConfig);
|
|
17623
17922
|
const { allocations, intents } = await buildAutoAllocatedFromBalances(params, destChain, recipientAddress, useForwarder, params.amountIn, chainBalances);
|
|
17624
17923
|
return {
|
|
17625
17924
|
allocations,
|
|
@@ -17642,11 +17941,11 @@ const FORWARDER_POLL_TIMEOUT_MS = 300_000;
|
|
|
17642
17941
|
* @param useForwarder - Whether the Forwarding Service path is active.
|
|
17643
17942
|
* @param allocations - Normalised allocations (forwarded to error handler).
|
|
17644
17943
|
* @returns Estimate entries and optional forwarding fee.
|
|
17645
|
-
*/ async function fetchEstimate(apiBaseUrl, estimateBody, useForwarder, allocations) {
|
|
17944
|
+
*/ async function fetchEstimate(apiBaseUrl, estimateBody, useForwarder, allocations, requestConfig) {
|
|
17646
17945
|
if (useForwarder) {
|
|
17647
17946
|
let fwdResponse;
|
|
17648
17947
|
try {
|
|
17649
|
-
fwdResponse = await pollApiPost(`${apiBaseUrl}/v1/estimate?enableForwarder=true`, estimateBody, assertGatewayForwarderEstimateResponse);
|
|
17948
|
+
fwdResponse = await pollApiPost(`${apiBaseUrl}/v1/estimate?enableForwarder=true`, estimateBody, assertGatewayForwarderEstimateResponse, requestConfig);
|
|
17650
17949
|
} catch (error) {
|
|
17651
17950
|
throwGatewayApiError(error, allocations);
|
|
17652
17951
|
}
|
|
@@ -17657,7 +17956,7 @@ const FORWARDER_POLL_TIMEOUT_MS = 300_000;
|
|
|
17657
17956
|
}
|
|
17658
17957
|
let entries;
|
|
17659
17958
|
try {
|
|
17660
|
-
entries = await pollApiPost(`${apiBaseUrl}/v1/estimate`, estimateBody, assertGatewayEstimateResponse);
|
|
17959
|
+
entries = await pollApiPost(`${apiBaseUrl}/v1/estimate`, estimateBody, assertGatewayEstimateResponse, requestConfig);
|
|
17661
17960
|
} catch (error) {
|
|
17662
17961
|
throwGatewayApiError(error, allocations);
|
|
17663
17962
|
}
|
|
@@ -17728,14 +18027,14 @@ const FORWARDER_POLL_TIMEOUT_MS = 300_000;
|
|
|
17728
18027
|
* @param destChain - Resolved destination chain with Gateway v1 config.
|
|
17729
18028
|
* @param useForwarder - Whether the Forwarding Service path is active.
|
|
17730
18029
|
* @returns Estimated intents (with real maxFee) and optional forwarding fee.
|
|
17731
|
-
*/ async function validateAndEstimate(allocations, intents, destChain, useForwarder) {
|
|
18030
|
+
*/ async function validateAndEstimate(allocations, intents, destChain, useForwarder, requestConfig) {
|
|
17732
18031
|
assertNetworkCompatibility(allocations, destChain);
|
|
17733
18032
|
if (useForwarder) {
|
|
17734
18033
|
assertForwarderRouteSupport(destChain, allocations);
|
|
17735
18034
|
}
|
|
17736
18035
|
const apiBaseUrl = getGatewayApiBaseUrl(destChain.isTestnet);
|
|
17737
18036
|
const estimateBody = buildEstimateRequestBody(intents);
|
|
17738
|
-
const { entries, forwardingFee } = await fetchEstimate(apiBaseUrl, estimateBody, useForwarder, allocations);
|
|
18037
|
+
const { entries, forwardingFee } = await fetchEstimate(apiBaseUrl, estimateBody, useForwarder, allocations, requestConfig);
|
|
17739
18038
|
const estimatedIntents = parseEstimateResponse(entries, intents);
|
|
17740
18039
|
return {
|
|
17741
18040
|
estimatedIntents,
|
|
@@ -17794,7 +18093,7 @@ const FORWARDER_POLL_TIMEOUT_MS = 300_000;
|
|
|
17794
18093
|
}
|
|
17795
18094
|
throw err;
|
|
17796
18095
|
}
|
|
17797
|
-
const { estimatedIntents, forwardingFee } = await validateAndEstimate(corrected.allocations, corrected.intents, opts.destChain, opts.useForwarder);
|
|
18096
|
+
const { estimatedIntents, forwardingFee } = await validateAndEstimate(corrected.allocations, corrected.intents, opts.destChain, opts.useForwarder, opts.requestConfig);
|
|
17798
18097
|
const stillOverdrawn = findOverdrawnChains(estimatedIntents, corrected.allocations, opts.chainBalances);
|
|
17799
18098
|
if (stillOverdrawn.length === 0) {
|
|
17800
18099
|
return {
|
|
@@ -17828,12 +18127,12 @@ const FORWARDER_POLL_TIMEOUT_MS = 300_000;
|
|
|
17828
18127
|
* @param recipientAddress - Resolved recipient address.
|
|
17829
18128
|
* @param useForwarder - Whether the Forwarding Service path is active.
|
|
17830
18129
|
* @returns Allocations, estimated intents, and optional forwarding fee.
|
|
17831
|
-
*/ async function resolveValidatedIntents(params, destChain, recipientAddress, useForwarder) {
|
|
18130
|
+
*/ async function resolveValidatedIntents(params, destChain, recipientAddress, useForwarder, requestConfig) {
|
|
17832
18131
|
if (useForwarder) {
|
|
17833
18132
|
assertForwarderRouteSupport(destChain);
|
|
17834
18133
|
}
|
|
17835
|
-
const { allocations, intents, chainBalances } = await resolveAllocationsAndIntents(params, destChain, recipientAddress, useForwarder);
|
|
17836
|
-
const { estimatedIntents, forwardingFee } = await validateAndEstimate(allocations, intents, destChain, useForwarder);
|
|
18134
|
+
const { allocations, intents, chainBalances } = await resolveAllocationsAndIntents(params, destChain, recipientAddress, useForwarder, requestConfig);
|
|
18135
|
+
const { estimatedIntents, forwardingFee } = await validateAndEstimate(allocations, intents, destChain, useForwarder, requestConfig);
|
|
17837
18136
|
if (params.amountIn && chainBalances) {
|
|
17838
18137
|
const overdrawn = findOverdrawnChains(estimatedIntents, allocations, chainBalances);
|
|
17839
18138
|
if (overdrawn.length > 0) {
|
|
@@ -17846,7 +18145,10 @@ const FORWARDER_POLL_TIMEOUT_MS = 300_000;
|
|
|
17846
18145
|
chainBalances,
|
|
17847
18146
|
estimatedIntents,
|
|
17848
18147
|
allocations,
|
|
17849
|
-
overdrawn
|
|
18148
|
+
overdrawn,
|
|
18149
|
+
...requestConfig ? {
|
|
18150
|
+
requestConfig
|
|
18151
|
+
} : {}
|
|
17850
18152
|
});
|
|
17851
18153
|
}
|
|
17852
18154
|
}
|
|
@@ -17890,10 +18192,10 @@ const FORWARDER_POLL_TIMEOUT_MS = 300_000;
|
|
|
17890
18192
|
attestationSignature: transferResponse.signature
|
|
17891
18193
|
};
|
|
17892
18194
|
}
|
|
17893
|
-
async function runSpendNormalPath(params, destChain, useForwarder, dispatcher, steps) {
|
|
18195
|
+
async function runSpendNormalPath(params, destChain, useForwarder, dispatcher, steps, requestConfig) {
|
|
17894
18196
|
const chainName = destChain.name;
|
|
17895
18197
|
const recipientAddress = await resolveRecipientAddress(params.to);
|
|
17896
|
-
const { allocations, estimatedIntents, forwardingFee: estimateFwdFee } = await resolveValidatedIntents(params, destChain, recipientAddress, useForwarder);
|
|
18198
|
+
const { allocations, estimatedIntents, forwardingFee: estimateFwdFee } = await resolveValidatedIntents(params, destChain, recipientAddress, useForwarder, requestConfig);
|
|
17897
18199
|
pushStep(steps, dispatcher, 'gateway.spend.step.buildBurnIntents', chainName, {
|
|
17898
18200
|
name: 'buildBurnIntents',
|
|
17899
18201
|
state: 'success',
|
|
@@ -17930,7 +18232,7 @@ async function runSpendNormalPath(params, destChain, useForwarder, dispatcher, s
|
|
|
17930
18232
|
const forwarderParam = useForwarder ? '?enableForwarder=true' : '';
|
|
17931
18233
|
let transferResponse;
|
|
17932
18234
|
try {
|
|
17933
|
-
transferResponse = await pollApiPost(`${transferApiBaseUrl}/v1/transfer${forwarderParam}`, transferBody, assertGatewayTransferResponse);
|
|
18235
|
+
transferResponse = await pollApiPost(`${transferApiBaseUrl}/v1/transfer${forwarderParam}`, transferBody, assertGatewayTransferResponse, requestConfig);
|
|
17934
18236
|
} catch (error) {
|
|
17935
18237
|
throwGatewayApiError(error, allocations);
|
|
17936
18238
|
}
|
|
@@ -18010,10 +18312,11 @@ function updateFeesWithActual(fees, completionStatus) {
|
|
|
18010
18312
|
amount: actual
|
|
18011
18313
|
} : f);
|
|
18012
18314
|
}
|
|
18013
|
-
async function resolveDestinationTxHash(
|
|
18315
|
+
async function resolveDestinationTxHash(opts) {
|
|
18316
|
+
const { params, destChain, forwarder, transferId, attestation, attestationSignature, fees, requestConfig } = opts;
|
|
18014
18317
|
if (forwarder && transferId) {
|
|
18015
18318
|
const apiBaseUrl = getGatewayApiBaseUrl(destChain.isTestnet);
|
|
18016
|
-
const completionStatus = await pollForwarderCompletion(apiBaseUrl, transferId);
|
|
18319
|
+
const completionStatus = await pollForwarderCompletion(apiBaseUrl, transferId, requestConfig);
|
|
18017
18320
|
if (!completionStatus.transactionHash) {
|
|
18018
18321
|
throw new KitError({
|
|
18019
18322
|
...OnchainError.TRANSACTION_REVERTED,
|
|
@@ -18096,9 +18399,20 @@ function buildSpendResult(recipientAddress, destChain, txHash, allocationResults
|
|
|
18096
18399
|
/**
|
|
18097
18400
|
* Execute the mint step, recording success/error as a spend step.
|
|
18098
18401
|
*/ async function executeMintStep(opts) {
|
|
18099
|
-
const { params, destChain, forwarder, transferId, attestation, attestationSignature, fees, steps, dispatcher } = opts;
|
|
18402
|
+
const { params, destChain, forwarder, transferId, attestation, attestationSignature, fees, steps, dispatcher, requestConfig } = opts;
|
|
18100
18403
|
try {
|
|
18101
|
-
const mintResult = await resolveDestinationTxHash(
|
|
18404
|
+
const mintResult = await resolveDestinationTxHash({
|
|
18405
|
+
params,
|
|
18406
|
+
destChain,
|
|
18407
|
+
forwarder,
|
|
18408
|
+
transferId,
|
|
18409
|
+
attestation,
|
|
18410
|
+
attestationSignature,
|
|
18411
|
+
fees,
|
|
18412
|
+
...requestConfig ? {
|
|
18413
|
+
requestConfig
|
|
18414
|
+
} : {}
|
|
18415
|
+
});
|
|
18102
18416
|
pushStep(steps, dispatcher, 'gateway.spend.step.mint', destChain.name, {
|
|
18103
18417
|
name: 'mint',
|
|
18104
18418
|
state: 'success',
|
|
@@ -18153,7 +18467,8 @@ function buildSpendResult(recipientAddress, destChain, txHash, allocationResults
|
|
|
18153
18467
|
assertSpendAddresses(params, destChain);
|
|
18154
18468
|
const forwarder = isForwarderEnabled(params.to);
|
|
18155
18469
|
const steps = [];
|
|
18156
|
-
const
|
|
18470
|
+
const requestConfig = options?.requestConfig;
|
|
18471
|
+
const context = params.config?.retry ? await resolveRetryContext(params) : await resolveNormalContext(params, destChain, forwarder, dispatcher, steps, requestConfig);
|
|
18157
18472
|
const fees = appendForwarderFee(context.fees, context.forwardingFee);
|
|
18158
18473
|
const mintResult = await executeMintStep({
|
|
18159
18474
|
params,
|
|
@@ -18164,7 +18479,10 @@ function buildSpendResult(recipientAddress, destChain, txHash, allocationResults
|
|
|
18164
18479
|
attestationSignature: context.attestationSignature,
|
|
18165
18480
|
fees,
|
|
18166
18481
|
steps,
|
|
18167
|
-
dispatcher
|
|
18482
|
+
dispatcher,
|
|
18483
|
+
...requestConfig ? {
|
|
18484
|
+
requestConfig
|
|
18485
|
+
} : {}
|
|
18168
18486
|
});
|
|
18169
18487
|
// A throwing `onBroadcast` must never strand the caller after a
|
|
18170
18488
|
// successful mint — the chain has moved. `safeInvokeCallback` swallows
|
|
@@ -18181,14 +18499,14 @@ function buildSpendResult(recipientAddress, destChain, txHash, allocationResults
|
|
|
18181
18499
|
/**
|
|
18182
18500
|
* Resolve the spend context via the normal (non-retry) path.
|
|
18183
18501
|
* Validates `from`, then delegates to `runSpendNormalPath`.
|
|
18184
|
-
*/ async function resolveNormalContext(params, destChain, forwarder, dispatcher, steps) {
|
|
18502
|
+
*/ async function resolveNormalContext(params, destChain, forwarder, dispatcher, steps, requestConfig) {
|
|
18185
18503
|
if (!params.from) {
|
|
18186
18504
|
throw createValidationFailedError$1('from', params.from, 'Source (from) is required when config.retry is not provided.');
|
|
18187
18505
|
}
|
|
18188
18506
|
return runSpendNormalPath({
|
|
18189
18507
|
...params,
|
|
18190
18508
|
from: params.from
|
|
18191
|
-
}, destChain, forwarder, dispatcher, steps);
|
|
18509
|
+
}, destChain, forwarder, dispatcher, steps, requestConfig);
|
|
18192
18510
|
}
|
|
18193
18511
|
/**
|
|
18194
18512
|
* Estimate fees for a Gateway spend without executing it.
|
|
@@ -18211,13 +18529,13 @@ function buildSpendResult(recipientAddress, destChain, txHash, allocationResults
|
|
|
18211
18529
|
* })
|
|
18212
18530
|
* fees.forEach((f) => console.log(f.type, f.amount, f.allocations))
|
|
18213
18531
|
* ```
|
|
18214
|
-
*/ async function estimateSpend$1(params) {
|
|
18532
|
+
*/ async function estimateSpend$1(params, requestConfig) {
|
|
18215
18533
|
const destChain = resolveChainIdentifier(params.to.chain);
|
|
18216
18534
|
assertGatewayV1(destChain);
|
|
18217
18535
|
assertSpendAddresses(params, destChain);
|
|
18218
18536
|
const forwarder = isForwarderEnabled(params.to);
|
|
18219
18537
|
const recipientAddress = await resolveRecipientAddress(params.to);
|
|
18220
|
-
const { allocations, estimatedIntents, forwardingFee } = await resolveValidatedIntents(params, destChain, recipientAddress, forwarder);
|
|
18538
|
+
const { allocations, estimatedIntents, forwardingFee } = await resolveValidatedIntents(params, destChain, recipientAddress, forwarder, requestConfig);
|
|
18221
18539
|
const fees = computeEstimateFees(estimatedIntents, allocations, params.config?.customFee);
|
|
18222
18540
|
if (forwardingFee) {
|
|
18223
18541
|
fees.push({
|
|
@@ -18341,6 +18659,9 @@ function assertNotSelfDelegation(chain, signerAddress, delegateAddress, action)
|
|
|
18341
18659
|
* the delegate is `'ready'` (finalized); otherwise it is `'pending'`.
|
|
18342
18660
|
*
|
|
18343
18661
|
* @param params - The adapter context (`from`), delegate address, and token.
|
|
18662
|
+
* @param requestConfig - Optional polling config overrides, including custom
|
|
18663
|
+
* `headers` forwarded with the `/v1/info` request used on the EVM finality
|
|
18664
|
+
* check.
|
|
18344
18665
|
* @returns Promise resolving to `'none'`, `'pending'`, or `'ready'`.
|
|
18345
18666
|
* @throws KitError if the chain is unsupported or `/v1/info` fails.
|
|
18346
18667
|
*
|
|
@@ -18360,7 +18681,7 @@ function assertNotSelfDelegation(chain, signerAddress, delegateAddress, action)
|
|
|
18360
18681
|
* const status = await getDelegateStatus(params)
|
|
18361
18682
|
* if (status === 'ready') { // safe to spend }
|
|
18362
18683
|
* ```
|
|
18363
|
-
*/ async function getDelegateStatus$1(params) {
|
|
18684
|
+
*/ async function getDelegateStatus$1(params, requestConfig) {
|
|
18364
18685
|
const { from, delegateAddress } = params;
|
|
18365
18686
|
const { adapter } = from;
|
|
18366
18687
|
const chain = resolveChainIdentifier(from.chain);
|
|
@@ -18376,8 +18697,7 @@ function assertNotSelfDelegation(chain, signerAddress, delegateAddress, action)
|
|
|
18376
18697
|
chain
|
|
18377
18698
|
};
|
|
18378
18699
|
// Step 1: Quick check at latest block (no HTTP call)
|
|
18379
|
-
const
|
|
18380
|
-
const latestResult = await latestRequest.execute();
|
|
18700
|
+
const latestResult = await executeAdapterReadAction(adapter, 'gateway.v1.isDelegate', baseActionParams, operationContext);
|
|
18381
18701
|
if (String(latestResult).toLowerCase() !== 'true') {
|
|
18382
18702
|
return 'none';
|
|
18383
18703
|
}
|
|
@@ -18386,13 +18706,12 @@ function assertNotSelfDelegation(chain, signerAddress, delegateAddress, action)
|
|
|
18386
18706
|
// Solana uses confirmed vs finalized commitment as a proxy for
|
|
18387
18707
|
// Gateway finality. This is conservative — can only over-report
|
|
18388
18708
|
// 'pending', never falsely report 'ready'.
|
|
18389
|
-
const finalizedRequest = await adapter.prepareAction('gateway.v1.isDelegate', {
|
|
18390
|
-
...baseActionParams,
|
|
18391
|
-
commitment: 'finalized'
|
|
18392
|
-
}, operationContext);
|
|
18393
18709
|
let finalizedResult;
|
|
18394
18710
|
try {
|
|
18395
|
-
finalizedResult = await
|
|
18711
|
+
finalizedResult = await executeAdapterReadAction(adapter, 'gateway.v1.isDelegate', {
|
|
18712
|
+
...baseActionParams,
|
|
18713
|
+
commitment: 'finalized'
|
|
18714
|
+
}, operationContext);
|
|
18396
18715
|
} catch (error) {
|
|
18397
18716
|
if (isBlockRangeError(error)) {
|
|
18398
18717
|
return 'pending';
|
|
@@ -18402,11 +18721,7 @@ function assertNotSelfDelegation(chain, signerAddress, delegateAddress, action)
|
|
|
18402
18721
|
return String(finalizedResult).toLowerCase() === 'true' ? 'ready' : 'pending';
|
|
18403
18722
|
}
|
|
18404
18723
|
// EVM: use processedHeight from /v1/info
|
|
18405
|
-
const processedHeight = await getProcessedHeight(chain.isTestnet, chain.gateway.domain);
|
|
18406
|
-
const finalizedRequest = await adapter.prepareAction('gateway.v1.isDelegate', {
|
|
18407
|
-
...baseActionParams,
|
|
18408
|
-
blockNumber: processedHeight
|
|
18409
|
-
}, operationContext);
|
|
18724
|
+
const processedHeight = await getProcessedHeight(chain.isTestnet, chain.gateway.domain, requestConfig);
|
|
18410
18725
|
// If the RPC node lags Gateway's indexer view, the historical read at
|
|
18411
18726
|
// processedHeight may throw a block-range error. This is safe to treat
|
|
18412
18727
|
// as 'pending' because processedHeight comes from Gateway's /v1/info
|
|
@@ -18415,7 +18730,10 @@ function assertNotSelfDelegation(chain, signerAddress, delegateAddress, action)
|
|
|
18415
18730
|
// Re-throw structural errors to avoid masking real bugs.
|
|
18416
18731
|
let finalizedResult;
|
|
18417
18732
|
try {
|
|
18418
|
-
finalizedResult = await
|
|
18733
|
+
finalizedResult = await executeAdapterReadAction(adapter, 'gateway.v1.isDelegate', {
|
|
18734
|
+
...baseActionParams,
|
|
18735
|
+
blockNumber: processedHeight
|
|
18736
|
+
}, operationContext);
|
|
18419
18737
|
} catch (error) {
|
|
18420
18738
|
if (isBlockRangeError(error)) {
|
|
18421
18739
|
return 'pending';
|
|
@@ -18476,8 +18794,8 @@ function parseAmountSafe(amount) {
|
|
|
18476
18794
|
chain
|
|
18477
18795
|
};
|
|
18478
18796
|
const [withdrawingRaw, withdrawalBlockRaw] = await Promise.all([
|
|
18479
|
-
adapter
|
|
18480
|
-
adapter
|
|
18797
|
+
executeAdapterReadAction(adapter, 'gateway.v1.withdrawingBalance', readParams, operationContext),
|
|
18798
|
+
executeAdapterReadAction(adapter, 'gateway.v1.withdrawalBlock', readParams, operationContext)
|
|
18481
18799
|
]);
|
|
18482
18800
|
const withdrawingValue = safeBigInt(String(withdrawingRaw), 'withdrawingBalance');
|
|
18483
18801
|
const withdrawalBlockValue = safeBigInt(String(withdrawalBlockRaw), 'withdrawalBlock');
|
|
@@ -18517,12 +18835,11 @@ function parseAmountSafe(amount) {
|
|
|
18517
18835
|
const tokenAddress = getTokenAddress(chain, params.token);
|
|
18518
18836
|
// Read the pending balance before withdrawing — the contract resets it to 0
|
|
18519
18837
|
// after withdraw() executes, so this is the only way to capture the amount.
|
|
18520
|
-
const
|
|
18838
|
+
const withdrawingRaw = await executeAdapterReadAction(adapter, 'gateway.v1.withdrawingBalance', {
|
|
18521
18839
|
token: tokenAddress,
|
|
18522
18840
|
depositor: signerAddress,
|
|
18523
18841
|
chain
|
|
18524
18842
|
}, operationContext);
|
|
18525
|
-
const withdrawingRaw = await withdrawingBalanceReq.execute();
|
|
18526
18843
|
const withdrawingValue = safeBigInt(String(withdrawingRaw), 'withdrawingBalance');
|
|
18527
18844
|
if (withdrawingValue === 0n) {
|
|
18528
18845
|
throw new KitError({
|
|
@@ -18622,6 +18939,35 @@ function dispatchEvent(dispatcher, opName, stage, chain, data) {
|
|
|
18622
18939
|
dispatchEvent(dispatcher, opName, 'failed', chain, extractErrorInfo(error));
|
|
18623
18940
|
}
|
|
18624
18941
|
|
|
18942
|
+
// ---------------------------------------------------------------------------
|
|
18943
|
+
// Config validation
|
|
18944
|
+
// ---------------------------------------------------------------------------
|
|
18945
|
+
function isPlainObject(value) {
|
|
18946
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
18947
|
+
return false;
|
|
18948
|
+
}
|
|
18949
|
+
const prototype = Object.getPrototypeOf(value);
|
|
18950
|
+
return prototype === Object.prototype || prototype === null;
|
|
18951
|
+
}
|
|
18952
|
+
function assertHeadersConfig(headers) {
|
|
18953
|
+
if (headers === undefined) {
|
|
18954
|
+
return;
|
|
18955
|
+
}
|
|
18956
|
+
if (!isPlainObject(headers)) {
|
|
18957
|
+
throw createValidationFailedError$1('config.headers', headers, 'config.headers must be a plain object with string header values when provided');
|
|
18958
|
+
}
|
|
18959
|
+
for (const [name, value] of Object.entries(headers)){
|
|
18960
|
+
if (typeof value !== 'string') {
|
|
18961
|
+
throw createValidationFailedError$1(`config.headers.${name}`, value, 'header values must be strings');
|
|
18962
|
+
}
|
|
18963
|
+
}
|
|
18964
|
+
}
|
|
18965
|
+
function assertGatewayV1Config(config) {
|
|
18966
|
+
if (!isPlainObject(config)) {
|
|
18967
|
+
throw createValidationFailedError$1('config', config, 'config must be a plain object when provided');
|
|
18968
|
+
}
|
|
18969
|
+
assertHeadersConfig(config['headers']);
|
|
18970
|
+
}
|
|
18625
18971
|
// ---------------------------------------------------------------------------
|
|
18626
18972
|
// Factory
|
|
18627
18973
|
// ---------------------------------------------------------------------------
|
|
@@ -18631,7 +18977,12 @@ function dispatchEvent(dispatcher, opName, stage, chain, data) {
|
|
|
18631
18977
|
* Returns a plain object that implements {@link IGatewayProvider} by
|
|
18632
18978
|
* delegating to the standalone functions in `operations/`.
|
|
18633
18979
|
*
|
|
18980
|
+
* @param config - Optional provider configuration. Supply `headers` to
|
|
18981
|
+
* forward custom HTTP headers with every Gateway API request. See
|
|
18982
|
+
* {@link GatewayV1Config}.
|
|
18634
18983
|
* @returns An {@link IGatewayProvider} instance.
|
|
18984
|
+
* @throws Throws when `config` or `config.headers` is not a plain object, or a
|
|
18985
|
+
* header value is not a string.
|
|
18635
18986
|
*
|
|
18636
18987
|
* @example
|
|
18637
18988
|
* ```typescript
|
|
@@ -18640,7 +18991,23 @@ function dispatchEvent(dispatcher, opName, stage, chain, data) {
|
|
|
18640
18991
|
* const provider = createGatewayV1Provider()
|
|
18641
18992
|
* const chains = provider.getSupportedChains()
|
|
18642
18993
|
* ```
|
|
18643
|
-
|
|
18994
|
+
*
|
|
18995
|
+
* @example
|
|
18996
|
+
* ```typescript
|
|
18997
|
+
* // Forward a custom header on every Gateway API request.
|
|
18998
|
+
* const provider = createGatewayV1Provider({
|
|
18999
|
+
* headers: { 'X-Access-Key': process.env.GATEWAY_ACCESS_KEY! },
|
|
19000
|
+
* })
|
|
19001
|
+
* ```
|
|
19002
|
+
*/ function createGatewayV1Provider(config = {}) {
|
|
19003
|
+
assertGatewayV1Config(config);
|
|
19004
|
+
// Captured once and threaded to every Gateway API call the operations make,
|
|
19005
|
+
// so a configured header reaches balances, estimate, transfer, forwarder
|
|
19006
|
+
// status, and /v1/info alike. Left undefined when no headers are configured
|
|
19007
|
+
// so the operations keep their existing defaults untouched.
|
|
19008
|
+
const requestConfig = config.headers ? {
|
|
19009
|
+
headers: config.headers
|
|
19010
|
+
} : undefined;
|
|
18644
19011
|
/**
|
|
18645
19012
|
* Execute an operation with started/succeeded/failed event dispatch.
|
|
18646
19013
|
*/ async function withEvents(opName, chain, startedData, params, fn) {
|
|
@@ -18671,21 +19038,25 @@ function dispatchEvent(dispatcher, opName, stage, chain, data) {
|
|
|
18671
19038
|
}, params, depositFor$1),
|
|
18672
19039
|
spend: async (params, options)=>{
|
|
18673
19040
|
const destChainName = extractChainInfo(params.to.chain).name;
|
|
19041
|
+
const mergedOptions = requestConfig ? {
|
|
19042
|
+
...options,
|
|
19043
|
+
requestConfig
|
|
19044
|
+
} : options;
|
|
18674
19045
|
return withEvents('spend', destChainName, {
|
|
18675
19046
|
destinationChain: destChainName,
|
|
18676
19047
|
token: params.token ?? 'USDC'
|
|
18677
|
-
}, params, async (p)=>spend$1(p, provider.actionDispatcher,
|
|
19048
|
+
}, params, async (p)=>spend$1(p, provider.actionDispatcher, mergedOptions));
|
|
18678
19049
|
},
|
|
18679
19050
|
estimateSpend: async (params)=>{
|
|
18680
19051
|
const destChainName = extractChainInfo(params.to.chain).name;
|
|
18681
19052
|
return withEvents('estimateSpend', destChainName, {
|
|
18682
19053
|
destinationChain: destChainName,
|
|
18683
19054
|
token: params.token ?? 'USDC'
|
|
18684
|
-
}, params, estimateSpend$1);
|
|
19055
|
+
}, params, async (p)=>estimateSpend$1(p, requestConfig));
|
|
18685
19056
|
},
|
|
18686
19057
|
getBalances: async (params)=>withEvents('getBalances', 'aggregate', {
|
|
18687
19058
|
token: params.token ?? 'USDC'
|
|
18688
|
-
}, params, getBalances$1),
|
|
19059
|
+
}, params, async (p)=>getBalances$1(p, requestConfig)),
|
|
18689
19060
|
addDelegate: async (params)=>withEvents('addDelegate', extractChainInfo(params.from.chain).name, {
|
|
18690
19061
|
delegateAddress: params.delegateAddress
|
|
18691
19062
|
}, params, addDelegate$1),
|
|
@@ -18703,7 +19074,9 @@ function dispatchEvent(dispatcher, opName, stage, chain, data) {
|
|
|
18703
19074
|
// in withEvents. getSupportedChains is synchronous. getDelegateStatus is a
|
|
18704
19075
|
// lightweight read that consumers treat as a utility check, unlike
|
|
18705
19076
|
// getBalances which involves API polling and benefits from lifecycle events.
|
|
18706
|
-
getDelegateStatus
|
|
19077
|
+
// getDelegateStatus is wrapped to forward the provider's request config to
|
|
19078
|
+
// its /v1/info call; getSupportedChains makes no API call.
|
|
19079
|
+
getDelegateStatus: async (params)=>getDelegateStatus$1(params, requestConfig),
|
|
18707
19080
|
getSupportedChains: getSupportedChains$1
|
|
18708
19081
|
};
|
|
18709
19082
|
return provider;
|
|
@@ -18713,6 +19086,7 @@ function dispatchEvent(dispatcher, opName, stage, chain, data) {
|
|
|
18713
19086
|
* The default providers that will be used in addition to the providers
|
|
18714
19087
|
* provided to the createUnifiedBalanceKitContext factory function.
|
|
18715
19088
|
*
|
|
19089
|
+
* @param config - Optional configuration forwarded to the default provider.
|
|
18716
19090
|
* @returns A readonly tuple with one element: the default Gateway v1 provider
|
|
18717
19091
|
* instance created via {@link createGatewayV1Provider}.
|
|
18718
19092
|
* @internal
|
|
@@ -18724,8 +19098,10 @@ function dispatchEvent(dispatcher, opName, stage, chain, data) {
|
|
|
18724
19098
|
* const { providers } = createUnifiedBalanceKitContext()
|
|
18725
19099
|
* // providers[0] is the default Gateway v1 instance from getDefaultProviders()
|
|
18726
19100
|
* ```
|
|
18727
|
-
*/ const getDefaultProviders = ()=>[
|
|
18728
|
-
createGatewayV1Provider(
|
|
19101
|
+
*/ const getDefaultProviders = (config = {})=>[
|
|
19102
|
+
createGatewayV1Provider(config.headers ? {
|
|
19103
|
+
headers: config.headers
|
|
19104
|
+
} : {})
|
|
18729
19105
|
];
|
|
18730
19106
|
function createUnifiedBalanceKitContext(config = {}) {
|
|
18731
19107
|
// Runtime guard: `excludeDefaultProviders: true` with no `providers` is
|
|
@@ -18739,7 +19115,10 @@ function createUnifiedBalanceKitContext(config = {}) {
|
|
|
18739
19115
|
// Initialize default providers — either the canonical singleton tuple or
|
|
18740
19116
|
// an empty list when the caller has opted out. Typed loosely here; each
|
|
18741
19117
|
// public overload narrows the return type for callers.
|
|
18742
|
-
const
|
|
19118
|
+
const defaultProvidersConfig = config.headers ? {
|
|
19119
|
+
headers: config.headers
|
|
19120
|
+
} : {};
|
|
19121
|
+
const defaultProviders = config.excludeDefaultProviders === true ? [] : getDefaultProviders(defaultProvidersConfig);
|
|
18743
19122
|
const providers = [
|
|
18744
19123
|
...defaultProviders,
|
|
18745
19124
|
...config.providers ?? []
|
|
@@ -19430,29 +19809,65 @@ function sumAllocationsFromSources(sources) {
|
|
|
19430
19809
|
}
|
|
19431
19810
|
});
|
|
19432
19811
|
|
|
19812
|
+
function normalizeAddressIdentity(value) {
|
|
19813
|
+
if (typeof value !== 'string') return undefined;
|
|
19814
|
+
try {
|
|
19815
|
+
return convertAddress(value, 'bytes32').toLowerCase();
|
|
19816
|
+
} catch {
|
|
19817
|
+
// Address validation below owns the structured error for invalid input.
|
|
19818
|
+
return value;
|
|
19819
|
+
}
|
|
19820
|
+
}
|
|
19433
19821
|
/**
|
|
19434
|
-
* Reject `from` arrays
|
|
19435
|
-
*
|
|
19436
|
-
*
|
|
19822
|
+
* Reject `from` arrays that describe the same spend source more than once.
|
|
19823
|
+
*
|
|
19824
|
+
* One adapter instance may legitimately be reused across distinct Gateway
|
|
19825
|
+
* source accounts. When `sourceAccount` is omitted, the signer address
|
|
19826
|
+
* identifies the source. Must run on the raw input (before Zod parsing)
|
|
19827
|
+
* because `z.object()` creates new wrapper objects and adapter identity
|
|
19828
|
+
* (`===`) is lost.
|
|
19437
19829
|
*
|
|
19438
19830
|
* @internal
|
|
19439
|
-
*/ function
|
|
19831
|
+
*/ function assertNoDuplicateSpendSources(params) {
|
|
19440
19832
|
if (params == null || typeof params !== 'object') return;
|
|
19441
19833
|
const from = params['from'];
|
|
19442
19834
|
if (!Array.isArray(from) || from.length < 2) return;
|
|
19443
|
-
const seen = new
|
|
19835
|
+
const seen = new Map();
|
|
19444
19836
|
for (const source of from){
|
|
19445
19837
|
if (source == null || typeof source !== 'object') continue;
|
|
19446
|
-
const
|
|
19838
|
+
const record = source;
|
|
19839
|
+
const adapter = record['adapter'];
|
|
19447
19840
|
if (adapter == null) continue;
|
|
19448
|
-
|
|
19841
|
+
const sourceAccount = normalizeAddressIdentity(record['sourceAccount']) ?? normalizeAddressIdentity(record['address']);
|
|
19842
|
+
let sourceAccounts = seen.get(adapter);
|
|
19843
|
+
if (sourceAccounts == null) {
|
|
19844
|
+
sourceAccounts = new Set();
|
|
19845
|
+
seen.set(adapter, sourceAccounts);
|
|
19846
|
+
}
|
|
19847
|
+
if (sourceAccounts.has(sourceAccount)) {
|
|
19449
19848
|
throw new KitError({
|
|
19450
19849
|
...InputError.VALIDATION_FAILED,
|
|
19451
19850
|
recoverability: 'FATAL',
|
|
19452
|
-
message: 'Duplicate
|
|
19851
|
+
message: 'Duplicate spend source detected in from array. The same adapter ' + 'and Gateway source account are reused more than once.'
|
|
19453
19852
|
});
|
|
19454
19853
|
}
|
|
19455
|
-
|
|
19854
|
+
sourceAccounts.add(sourceAccount);
|
|
19855
|
+
}
|
|
19856
|
+
}
|
|
19857
|
+
function assertSourceAddressContexts(from) {
|
|
19858
|
+
const sources = Array.isArray(from) ? from : [
|
|
19859
|
+
from
|
|
19860
|
+
];
|
|
19861
|
+
for (const raw of sources){
|
|
19862
|
+
if (raw == null || typeof raw !== 'object') continue;
|
|
19863
|
+
const source = raw;
|
|
19864
|
+
const addressContext = source.adapter?.capabilities?.addressContext;
|
|
19865
|
+
if (addressContext === 'developer-controlled' && (typeof source.address !== 'string' || source.address === '')) {
|
|
19866
|
+
throw createValidationFailedError$1('address', source.address, 'Address is required for developer-controlled adapters.');
|
|
19867
|
+
}
|
|
19868
|
+
if (addressContext === 'user-controlled' && source.address !== undefined) {
|
|
19869
|
+
throw createValidationFailedError$1('address', source.address, 'Address should not be provided for user-controlled adapters. ' + 'The address is automatically resolved from the connected wallet.');
|
|
19870
|
+
}
|
|
19456
19871
|
}
|
|
19457
19872
|
}
|
|
19458
19873
|
/**
|
|
@@ -19466,14 +19881,17 @@ function sumAllocationsFromSources(sources) {
|
|
|
19466
19881
|
* @throws \{KitError\} When validation fails; error code is
|
|
19467
19882
|
* {@link InputError.VALIDATION_FAILED}.
|
|
19468
19883
|
*/ function assertSpendParams(params) {
|
|
19469
|
-
|
|
19884
|
+
assertNoDuplicateSpendSources(params);
|
|
19885
|
+
if (params != null && typeof params === 'object' && 'from' in params) {
|
|
19886
|
+
assertSourceAddressContexts(params['from']);
|
|
19887
|
+
}
|
|
19470
19888
|
const result = spendParamsSchema.safeParse(params);
|
|
19471
19889
|
if (!result.success) {
|
|
19472
19890
|
throw convertZodErrorToStructured(result.error, params);
|
|
19473
19891
|
}
|
|
19474
19892
|
const data = result.data;
|
|
19475
19893
|
// Validate recipientAddress against the destination chain
|
|
19476
|
-
if (data.to.recipientAddress) {
|
|
19894
|
+
if (data.to.recipientAddress !== undefined && data.to.recipientAddress !== '') {
|
|
19477
19895
|
const toChain = data.to.chain;
|
|
19478
19896
|
if (!isValidAddressForChain(data.to.recipientAddress, toChain)) {
|
|
19479
19897
|
const chainInfo = extractChainInfo(toChain);
|
|
@@ -19481,7 +19899,7 @@ function sumAllocationsFromSources(sources) {
|
|
|
19481
19899
|
}
|
|
19482
19900
|
}
|
|
19483
19901
|
// Validate sourceAccount against each source's allocation chain
|
|
19484
|
-
if (data.from) {
|
|
19902
|
+
if (data.from !== undefined) {
|
|
19485
19903
|
assertSourceAccountAddresses(data.from);
|
|
19486
19904
|
}
|
|
19487
19905
|
}
|
|
@@ -19496,11 +19914,15 @@ function assertSourceAccountAddresses(from) {
|
|
|
19496
19914
|
from
|
|
19497
19915
|
];
|
|
19498
19916
|
for (const raw of sources){
|
|
19499
|
-
if (
|
|
19917
|
+
if (raw === null || typeof raw !== 'object' || !('sourceAccount' in raw)) {
|
|
19918
|
+
continue;
|
|
19919
|
+
}
|
|
19500
19920
|
const source = raw;
|
|
19501
|
-
if (
|
|
19921
|
+
if (source.sourceAccount === undefined || source.sourceAccount === '') {
|
|
19922
|
+
continue;
|
|
19923
|
+
}
|
|
19502
19924
|
const sourceChain = getSourceChainFromAllocations(source.allocations);
|
|
19503
|
-
if (
|
|
19925
|
+
if (sourceChain === undefined) continue;
|
|
19504
19926
|
if (!isValidAddressForChain(source.sourceAccount, sourceChain)) {
|
|
19505
19927
|
const chainInfo = extractChainInfo(sourceChain);
|
|
19506
19928
|
throw createInvalidAddressError(source.sourceAccount, String(chainInfo.name), chainInfo.expectedAddressFormat);
|