@circle-fin/app-kit 1.13.0 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +56 -0
- package/bridge.cjs +910 -47
- package/bridge.d.cts +55 -0
- package/bridge.d.mts +55 -0
- package/bridge.d.ts +55 -0
- package/bridge.mjs +911 -48
- package/chains.cjs +129 -10
- package/chains.d.cts +9 -0
- package/chains.d.mts +9 -0
- package/chains.d.ts +9 -0
- package/chains.mjs +129 -10
- package/context.d.cts +55 -0
- package/context.d.mts +55 -0
- package/context.d.ts +55 -0
- package/earn.cjs +432 -27
- package/earn.d.cts +55 -0
- package/earn.d.mts +55 -0
- package/earn.d.ts +55 -0
- package/earn.mjs +428 -27
- package/estimateBridge.cjs +910 -47
- package/estimateBridge.d.cts +61 -0
- package/estimateBridge.d.mts +61 -0
- package/estimateBridge.d.ts +61 -0
- package/estimateBridge.mjs +911 -48
- package/estimateSwap.cjs +428 -26
- package/estimateSwap.d.cts +55 -0
- package/estimateSwap.d.mts +55 -0
- package/estimateSwap.d.ts +55 -0
- package/estimateSwap.mjs +427 -26
- package/index.cjs +4613 -346
- package/index.d.cts +777 -216
- package/index.d.mts +777 -216
- package/index.d.ts +777 -216
- package/index.mjs +4614 -347
- package/package.json +6 -6
- package/swap.cjs +428 -26
- package/swap.d.cts +55 -0
- package/swap.d.mts +55 -0
- package/swap.d.ts +55 -0
- package/swap.mjs +427 -26
- package/unifiedBalance.cjs +20602 -8389
- package/unifiedBalance.d.cts +544 -160
- package/unifiedBalance.d.mts +544 -160
- package/unifiedBalance.d.ts +544 -160
- package/unifiedBalance.mjs +20603 -8391
package/estimateBridge.mjs
CHANGED
|
@@ -30,8 +30,8 @@ if (typeof window !== 'undefined' && typeof window.Buffer === 'undefined') {
|
|
|
30
30
|
import { z } from 'zod';
|
|
31
31
|
import pino from 'pino';
|
|
32
32
|
import { formatUnits as formatUnits$1, parseUnits as parseUnits$1 } from '@ethersproject/units';
|
|
33
|
-
import { hexlify, hexZeroPad, concat } from '@ethersproject/bytes';
|
|
34
|
-
import '@ethersproject/abi';
|
|
33
|
+
import { hexlify, hexZeroPad, isHexString, concat } from '@ethersproject/bytes';
|
|
34
|
+
import { Interface, defaultAbiCoder } from '@ethersproject/abi';
|
|
35
35
|
import { getAddress, isAddress } from '@ethersproject/address';
|
|
36
36
|
import bs58 from 'bs58';
|
|
37
37
|
import { PublicKey } from '@solana/web3.js';
|
|
@@ -3658,8 +3658,45 @@ var EarnChain;
|
|
|
3658
3658
|
* This program handles minting operations for Gateway transactions
|
|
3659
3659
|
* on Solana devnet.
|
|
3660
3660
|
*/ const GATEWAY_MINTER_SOLANA_DEVNET = 'GATEmKK2ECL1brEngQZWCgMWPbvrEYqsV6u29dAaHavr';
|
|
3661
|
-
/**
|
|
3662
|
-
|
|
3661
|
+
/**
|
|
3662
|
+
* The `TokenMessengerWithFees` proxy contract address for EVM mainnet networks
|
|
3663
|
+
* (all chains except Edge).
|
|
3664
|
+
*
|
|
3665
|
+
* Deployed at a CREATE3-derived address; identical across all mainnet EVM
|
|
3666
|
+
* source chains. Present on any chain that supports the prepaid FORWARD path
|
|
3667
|
+
* via `depositForBurnWithHookAndFees`.
|
|
3668
|
+
*/ const TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET = '0x71f54F818671cD0D7ea140Da213e5C8b5C92a408';
|
|
3669
|
+
/**
|
|
3670
|
+
* The `TokenMessengerWithFees` proxy contract address for EVM testnet networks.
|
|
3671
|
+
*
|
|
3672
|
+
* Identical across all testnet EVM source chains. Present on any testnet chain
|
|
3673
|
+
* that supports the prepaid FORWARD path via `depositForBurnWithHookAndFees`.
|
|
3674
|
+
*/ const TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET = '0x8745D906D67C346E5eb1aEEED38Eb87F34DF0C0A';
|
|
3675
|
+
/**
|
|
3676
|
+
* The `DepositForHandler` proxy contract address for EVM mainnet networks.
|
|
3677
|
+
*
|
|
3678
|
+
* The handler the GenericExecutor calls on a fast-deposit destination chain to
|
|
3679
|
+
* run a cross-chain deposit into the GatewayWallet. Deployed at the same
|
|
3680
|
+
* address across all mainnet EVM destination chains.
|
|
3681
|
+
*/ const DEPOSIT_FOR_HANDLER_EVM_MAINNET = '0x16529813203f77E036576666336554a1210dce4D';
|
|
3682
|
+
/**
|
|
3683
|
+
* The `DepositForHandler` proxy contract address for EVM testnet networks.
|
|
3684
|
+
*
|
|
3685
|
+
* Identical across all testnet EVM destination chains.
|
|
3686
|
+
*/ const DEPOSIT_FOR_HANDLER_EVM_TESTNET = '0xD05E7D2E7d30b92c5F17d7d0fC575fce231F1A48';
|
|
3687
|
+
/**
|
|
3688
|
+
* The `GenericExecutor` proxy contract address for EVM mainnet networks.
|
|
3689
|
+
*
|
|
3690
|
+
* The GenericExecutor is the `mintRecipient` and `destinationCaller` on the
|
|
3691
|
+
* destination chain for the CCTP v2 prepaid FORWARD path. It receives the CCTP
|
|
3692
|
+
* mint and calls the `DepositForHandler` to complete the fast deposit.
|
|
3693
|
+
* Deployed at the same address across all mainnet EVM destination chains.
|
|
3694
|
+
*/ const GENERIC_EXECUTOR_EVM_MAINNET = '0xFa7be2f04F3Ad4ca969260729c6d45B5625984A7';
|
|
3695
|
+
/**
|
|
3696
|
+
* The `GenericExecutor` proxy contract address for EVM testnet networks.
|
|
3697
|
+
*
|
|
3698
|
+
* Identical across all testnet EVM destination chains.
|
|
3699
|
+
*/ const GENERIC_EXECUTOR_EVM_TESTNET = '0xEdC81040756AcCfF070c21D37b265b9D0b5Ba45e';
|
|
3663
3700
|
|
|
3664
3701
|
/**
|
|
3665
3702
|
* Arc Testnet chain definition
|
|
@@ -3718,9 +3755,8 @@ var EarnChain;
|
|
|
3718
3755
|
v1: {
|
|
3719
3756
|
wallet: GATEWAY_WALLET_EVM_TESTNET,
|
|
3720
3757
|
minter: GATEWAY_MINTER_EVM_TESTNET,
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
depositForHandler: '0xD05E7D2E7d30b92c5F17d7d0fC575fce231F1A48'
|
|
3758
|
+
depositForHandler: DEPOSIT_FOR_HANDLER_EVM_TESTNET,
|
|
3759
|
+
genericExecutor: GENERIC_EXECUTOR_EVM_TESTNET
|
|
3724
3760
|
}
|
|
3725
3761
|
},
|
|
3726
3762
|
forwarderSupported: {
|
|
@@ -3915,7 +3951,9 @@ var EarnChain;
|
|
|
3915
3951
|
contracts: {
|
|
3916
3952
|
v1: {
|
|
3917
3953
|
wallet: GATEWAY_WALLET_EVM_MAINNET,
|
|
3918
|
-
minter: GATEWAY_MINTER_EVM_MAINNET
|
|
3954
|
+
minter: GATEWAY_MINTER_EVM_MAINNET,
|
|
3955
|
+
depositForHandler: DEPOSIT_FOR_HANDLER_EVM_MAINNET,
|
|
3956
|
+
genericExecutor: GENERIC_EXECUTOR_EVM_MAINNET
|
|
3919
3957
|
}
|
|
3920
3958
|
},
|
|
3921
3959
|
forwarderSupported: {
|
|
@@ -3979,7 +4017,9 @@ var EarnChain;
|
|
|
3979
4017
|
contracts: {
|
|
3980
4018
|
v1: {
|
|
3981
4019
|
wallet: GATEWAY_WALLET_EVM_TESTNET,
|
|
3982
|
-
minter: GATEWAY_MINTER_EVM_TESTNET
|
|
4020
|
+
minter: GATEWAY_MINTER_EVM_TESTNET,
|
|
4021
|
+
depositForHandler: DEPOSIT_FOR_HANDLER_EVM_TESTNET,
|
|
4022
|
+
genericExecutor: GENERIC_EXECUTOR_EVM_TESTNET
|
|
3983
4023
|
}
|
|
3984
4024
|
},
|
|
3985
4025
|
forwarderSupported: {
|
|
@@ -4292,6 +4332,7 @@ var EarnChain;
|
|
|
4292
4332
|
v2: {
|
|
4293
4333
|
type: 'split',
|
|
4294
4334
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
4335
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
4295
4336
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
4296
4337
|
confirmations: 1,
|
|
4297
4338
|
fastConfirmations: 1
|
|
@@ -4337,6 +4378,7 @@ var EarnChain;
|
|
|
4337
4378
|
v2: {
|
|
4338
4379
|
type: 'split',
|
|
4339
4380
|
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
4381
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
4340
4382
|
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
4341
4383
|
confirmations: 1,
|
|
4342
4384
|
fastConfirmations: 1
|
|
@@ -4382,6 +4424,7 @@ var EarnChain;
|
|
|
4382
4424
|
v2: {
|
|
4383
4425
|
type: 'split',
|
|
4384
4426
|
tokenMessenger: '0x98706A006bc632Df31CAdFCBD43F38887ce2ca5c',
|
|
4427
|
+
tokenMessengerWithFees: '0x3Ac96675F9a3E6922713e041645D82f3561d3686',
|
|
4385
4428
|
messageTransmitter: '0x5b61381Fc9e58E70EfC13a4A97516997019198ee',
|
|
4386
4429
|
confirmations: 65,
|
|
4387
4430
|
fastConfirmations: 1
|
|
@@ -4427,6 +4470,7 @@ var EarnChain;
|
|
|
4427
4470
|
v2: {
|
|
4428
4471
|
type: 'split',
|
|
4429
4472
|
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
4473
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
4430
4474
|
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
4431
4475
|
confirmations: 65,
|
|
4432
4476
|
fastConfirmations: 1
|
|
@@ -4775,6 +4819,7 @@ var EarnChain;
|
|
|
4775
4819
|
v2: {
|
|
4776
4820
|
type: 'split',
|
|
4777
4821
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
4822
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
4778
4823
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
4779
4824
|
confirmations: 1,
|
|
4780
4825
|
fastConfirmations: 1
|
|
@@ -4822,6 +4867,7 @@ var EarnChain;
|
|
|
4822
4867
|
v2: {
|
|
4823
4868
|
type: 'split',
|
|
4824
4869
|
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
4870
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
4825
4871
|
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
4826
4872
|
confirmations: 1,
|
|
4827
4873
|
fastConfirmations: 1
|
|
@@ -5103,6 +5149,7 @@ var EarnChain;
|
|
|
5103
5149
|
v2: {
|
|
5104
5150
|
type: 'split',
|
|
5105
5151
|
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
5152
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
5106
5153
|
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
5107
5154
|
confirmations: 1,
|
|
5108
5155
|
fastConfirmations: 1
|
|
@@ -5148,6 +5195,7 @@ var EarnChain;
|
|
|
5148
5195
|
v2: {
|
|
5149
5196
|
type: 'split',
|
|
5150
5197
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
5198
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
5151
5199
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
5152
5200
|
confirmations: 64,
|
|
5153
5201
|
fastConfirmations: 1
|
|
@@ -5193,6 +5241,7 @@ var EarnChain;
|
|
|
5193
5241
|
v2: {
|
|
5194
5242
|
type: 'split',
|
|
5195
5243
|
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
5244
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
5196
5245
|
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
5197
5246
|
confirmations: 64,
|
|
5198
5247
|
fastConfirmations: 1
|
|
@@ -5494,6 +5543,7 @@ var EarnChain;
|
|
|
5494
5543
|
v2: {
|
|
5495
5544
|
type: 'split',
|
|
5496
5545
|
tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
|
|
5546
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_MAINNET,
|
|
5497
5547
|
messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
|
|
5498
5548
|
confirmations: 1,
|
|
5499
5549
|
fastConfirmations: 1
|
|
@@ -5540,6 +5590,7 @@ var EarnChain;
|
|
|
5540
5590
|
v2: {
|
|
5541
5591
|
type: 'split',
|
|
5542
5592
|
tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
|
|
5593
|
+
tokenMessengerWithFees: TOKEN_MESSENGER_WITH_FEES_EVM_TESTNET,
|
|
5543
5594
|
messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
|
|
5544
5595
|
confirmations: 1,
|
|
5545
5596
|
fastConfirmations: 1
|
|
@@ -5847,7 +5898,9 @@ var EarnChain;
|
|
|
5847
5898
|
contracts: {
|
|
5848
5899
|
v1: {
|
|
5849
5900
|
wallet: GATEWAY_WALLET_EVM_MAINNET,
|
|
5850
|
-
minter: GATEWAY_MINTER_EVM_MAINNET
|
|
5901
|
+
minter: GATEWAY_MINTER_EVM_MAINNET,
|
|
5902
|
+
depositForHandler: DEPOSIT_FOR_HANDLER_EVM_MAINNET,
|
|
5903
|
+
genericExecutor: GENERIC_EXECUTOR_EVM_MAINNET
|
|
5851
5904
|
}
|
|
5852
5905
|
},
|
|
5853
5906
|
forwarderSupported: {
|
|
@@ -5912,7 +5965,9 @@ var EarnChain;
|
|
|
5912
5965
|
contracts: {
|
|
5913
5966
|
v1: {
|
|
5914
5967
|
wallet: GATEWAY_WALLET_EVM_TESTNET,
|
|
5915
|
-
minter: GATEWAY_MINTER_EVM_TESTNET
|
|
5968
|
+
minter: GATEWAY_MINTER_EVM_TESTNET,
|
|
5969
|
+
depositForHandler: DEPOSIT_FOR_HANDLER_EVM_TESTNET,
|
|
5970
|
+
genericExecutor: GENERIC_EXECUTOR_EVM_TESTNET
|
|
5916
5971
|
}
|
|
5917
5972
|
},
|
|
5918
5973
|
forwarderSupported: {
|
|
@@ -6998,18 +7053,48 @@ var Chains = /*#__PURE__*/Object.freeze({
|
|
|
6998
7053
|
return chain.cctp?.contracts.v2 !== undefined;
|
|
6999
7054
|
}
|
|
7000
7055
|
|
|
7056
|
+
/**
|
|
7057
|
+
* Chains the Fee Service accepts as a SOURCE for source-paid ("receive-exact")
|
|
7058
|
+
* CCTP v2 fees. An explicit allowlist is required because the
|
|
7059
|
+
* `TokenMessengerWithFees` wrapper address is now shared with the fast-deposit
|
|
7060
|
+
* forwarder path, so wrapper presence no longer implies source-fee support.
|
|
7061
|
+
* Keep in sync with backend coverage.
|
|
7062
|
+
*/ const SOURCE_FEE_SUPPORTED_ALLOWLIST = new Set([
|
|
7063
|
+
// Mainnet
|
|
7064
|
+
Blockchain.Ethereum,
|
|
7065
|
+
Blockchain.Base,
|
|
7066
|
+
Blockchain.Arbitrum,
|
|
7067
|
+
Blockchain.Unichain,
|
|
7068
|
+
Blockchain.Optimism,
|
|
7069
|
+
Blockchain.Codex,
|
|
7070
|
+
Blockchain.Ink,
|
|
7071
|
+
Blockchain.Plume,
|
|
7072
|
+
Blockchain.Linea,
|
|
7073
|
+
Blockchain.World_Chain,
|
|
7074
|
+
// Testnet counterparts
|
|
7075
|
+
Blockchain.Ethereum_Sepolia,
|
|
7076
|
+
Blockchain.Base_Sepolia,
|
|
7077
|
+
Blockchain.Arbitrum_Sepolia,
|
|
7078
|
+
Blockchain.Unichain_Sepolia,
|
|
7079
|
+
Blockchain.Optimism_Sepolia,
|
|
7080
|
+
Blockchain.Codex_Testnet,
|
|
7081
|
+
Blockchain.Ink_Testnet,
|
|
7082
|
+
Blockchain.Plume_Testnet,
|
|
7083
|
+
Blockchain.Linea_Sepolia,
|
|
7084
|
+
Blockchain.World_Chain_Sepolia
|
|
7085
|
+
]);
|
|
7001
7086
|
/**
|
|
7002
7087
|
* Check whether a chain supports source-paid ("receive-exact") CCTP v2 fees.
|
|
7003
7088
|
*
|
|
7004
|
-
* A chain
|
|
7005
|
-
*
|
|
7006
|
-
* `feePayment: 'source'` transfers through this wrapper via
|
|
7007
|
-
* `depositForBurnWithHookAndFees`, so a chain without the wrapper cannot be a
|
|
7008
|
-
* source for receive-exact bridging.
|
|
7089
|
+
* A chain qualifies when it supports CCTP v2, carries a `TokenMessengerWithFees`
|
|
7090
|
+
* wrapper, and is in {@link SOURCE_FEE_SUPPORTED_ALLOWLIST}.
|
|
7009
7091
|
*
|
|
7010
|
-
* @param chain - The chain definition to check.
|
|
7011
|
-
*
|
|
7012
|
-
*
|
|
7092
|
+
* @param chain - The chain definition to check. A nullish or non-object value
|
|
7093
|
+
* returns `false` rather than throwing, since consumers may call from plain
|
|
7094
|
+
* JavaScript.
|
|
7095
|
+
* @returns `true` when the chain supports CCTP v2, carries a
|
|
7096
|
+
* `TokenMessengerWithFees` wrapper, and is on the source-fee allowlist;
|
|
7097
|
+
* `false` otherwise.
|
|
7013
7098
|
*
|
|
7014
7099
|
* @example
|
|
7015
7100
|
* ```typescript
|
|
@@ -7019,11 +7104,18 @@ var Chains = /*#__PURE__*/Object.freeze({
|
|
|
7019
7104
|
* hasSourceFeeSupport(Chains.Solana) // false
|
|
7020
7105
|
* ```
|
|
7021
7106
|
*/ function hasSourceFeeSupport(chain) {
|
|
7107
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- runtime guard for nullish/non-object input from plain JS
|
|
7108
|
+
if (chain === null || typeof chain !== 'object') {
|
|
7109
|
+
return false;
|
|
7110
|
+
}
|
|
7022
7111
|
if (!isCCTPV2Supported(chain)) {
|
|
7023
7112
|
return false;
|
|
7024
7113
|
}
|
|
7025
7114
|
const wrapper = chain.cctp.contracts.v2.tokenMessengerWithFees;
|
|
7026
|
-
|
|
7115
|
+
if (typeof wrapper !== 'string' || wrapper.length === 0) {
|
|
7116
|
+
return false;
|
|
7117
|
+
}
|
|
7118
|
+
return SOURCE_FEE_SUPPORTED_ALLOWLIST.has(chain.chain);
|
|
7027
7119
|
}
|
|
7028
7120
|
|
|
7029
7121
|
/**
|
|
@@ -7076,6 +7168,73 @@ var Chains = /*#__PURE__*/Object.freeze({
|
|
|
7076
7168
|
return typeof contractAddress === 'string' && contractAddress.trim().length > 0;
|
|
7077
7169
|
}
|
|
7078
7170
|
|
|
7171
|
+
/**
|
|
7172
|
+
* Check whether a given chain supports Gateway protocol version 1.
|
|
7173
|
+
*
|
|
7174
|
+
* This type guard function examines a chain definition to determine if it has Gateway v1
|
|
7175
|
+
* contract configurations. It checks that the chain has a gateway object with a
|
|
7176
|
+
* `contracts.v1` entry present.
|
|
7177
|
+
*
|
|
7178
|
+
* @param chain - The chain definition to check for Gateway v1 support
|
|
7179
|
+
* @returns `true` if `chain.gateway?.contracts?.v1` is defined, `false` otherwise
|
|
7180
|
+
*
|
|
7181
|
+
* @example
|
|
7182
|
+
* ```typescript
|
|
7183
|
+
* import { isGatewayV1Supported, Base } from '@core/chains'
|
|
7184
|
+
*
|
|
7185
|
+
* if (isGatewayV1Supported(Base)) {
|
|
7186
|
+
* // TypeScript knows Base.gateway is defined here
|
|
7187
|
+
* console.log('Gateway domain:', Base.gateway.domain)
|
|
7188
|
+
* console.log('Wallet address:', Base.gateway.contracts.v1.wallet)
|
|
7189
|
+
* console.log('Minter address:', Base.gateway.contracts.v1.minter)
|
|
7190
|
+
* }
|
|
7191
|
+
* ```
|
|
7192
|
+
*
|
|
7193
|
+
* @example
|
|
7194
|
+
* ```typescript
|
|
7195
|
+
* // Usage in conditional flow
|
|
7196
|
+
* function getGatewayWalletAddress(chain: ChainDefinition): string | null {
|
|
7197
|
+
* if (isGatewayV1Supported(chain)) {
|
|
7198
|
+
* return chain.gateway.contracts.v1.wallet
|
|
7199
|
+
* }
|
|
7200
|
+
* return null
|
|
7201
|
+
* }
|
|
7202
|
+
* ```
|
|
7203
|
+
*/ function isGatewayV1Supported(chain) {
|
|
7204
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- JS consumers may pass a gateway object without contracts
|
|
7205
|
+
return chain.gateway?.contracts?.v1 !== undefined;
|
|
7206
|
+
}
|
|
7207
|
+
|
|
7208
|
+
/**
|
|
7209
|
+
* Temporary allowlist of chains permitted to initiate Gateway fast deposits.
|
|
7210
|
+
* Only chains keyed here are eligible; all others are rejected. Using the
|
|
7211
|
+
* {@link Blockchain} enum keeps entries type-safe and catches typos at compile
|
|
7212
|
+
* time. Remove this allowlist once roll-out is complete.
|
|
7213
|
+
*/ new Set([
|
|
7214
|
+
// Mainnet
|
|
7215
|
+
Blockchain.Ethereum,
|
|
7216
|
+
Blockchain.Base,
|
|
7217
|
+
Blockchain.Arbitrum,
|
|
7218
|
+
Blockchain.Unichain,
|
|
7219
|
+
Blockchain.Optimism,
|
|
7220
|
+
Blockchain.Codex,
|
|
7221
|
+
Blockchain.Ink,
|
|
7222
|
+
Blockchain.Plume,
|
|
7223
|
+
Blockchain.Linea,
|
|
7224
|
+
Blockchain.World_Chain,
|
|
7225
|
+
// Testnet counterparts
|
|
7226
|
+
Blockchain.Ethereum_Sepolia,
|
|
7227
|
+
Blockchain.Base_Sepolia,
|
|
7228
|
+
Blockchain.Arbitrum_Sepolia,
|
|
7229
|
+
Blockchain.Unichain_Sepolia,
|
|
7230
|
+
Blockchain.Optimism_Sepolia,
|
|
7231
|
+
Blockchain.Codex_Testnet,
|
|
7232
|
+
Blockchain.Ink_Testnet,
|
|
7233
|
+
Blockchain.Plume_Testnet,
|
|
7234
|
+
Blockchain.Linea_Sepolia,
|
|
7235
|
+
Blockchain.World_Chain_Sepolia
|
|
7236
|
+
]);
|
|
7237
|
+
|
|
7079
7238
|
/**
|
|
7080
7239
|
* Zod schema for validating Gateway v1 contract addresses.
|
|
7081
7240
|
*
|
|
@@ -7097,7 +7256,10 @@ var Chains = /*#__PURE__*/Object.freeze({
|
|
|
7097
7256
|
}).min(1, 'Gateway minter address cannot be empty.'),
|
|
7098
7257
|
depositForHandler: z.string({
|
|
7099
7258
|
invalid_type_error: 'Gateway depositForHandler address must be a string.'
|
|
7100
|
-
}).min(1, 'Gateway depositForHandler address cannot be empty.').optional()
|
|
7259
|
+
}).min(1, 'Gateway depositForHandler address cannot be empty.').optional(),
|
|
7260
|
+
genericExecutor: z.string({
|
|
7261
|
+
invalid_type_error: 'Gateway genericExecutor address must be a string.'
|
|
7262
|
+
}).min(1, 'Gateway genericExecutor address cannot be empty.').optional()
|
|
7101
7263
|
}).strict() // Reject any additional properties not defined in the schema
|
|
7102
7264
|
;
|
|
7103
7265
|
/**
|
|
@@ -9968,6 +10130,9 @@ const swapTokenEnumSchema = z.enum([
|
|
|
9968
10130
|
* The ASCII string "cctp-forward" (12 bytes) that identifies a forwarding request.
|
|
9969
10131
|
* This prefix is right-padded to 24 bytes in the final hookData.
|
|
9970
10132
|
*/ const CCTP_FORWARD_MAGIC_PREFIX = 'cctp-forward';
|
|
10133
|
+
/**
|
|
10134
|
+
* Maximum value of the 32-bit `version` field in a `cctp-forward` frame.
|
|
10135
|
+
*/ const MAX_UINT32 = 0xffffffff;
|
|
9971
10136
|
/**
|
|
9972
10137
|
* CCTP forwarding version number.
|
|
9973
10138
|
*
|
|
@@ -10044,6 +10209,76 @@ function buildForwardingHookData() {
|
|
|
10044
10209
|
cachedHookDataHex = '0x' + Array.from(buffer).map((b)=>b.toString(16).padStart(2, '0')).join('');
|
|
10045
10210
|
return cachedHookDataHex;
|
|
10046
10211
|
}
|
|
10212
|
+
/**
|
|
10213
|
+
* Build a `cctp-forward` hookData frame with a versioned header and an appended
|
|
10214
|
+
* opaque payload.
|
|
10215
|
+
*
|
|
10216
|
+
* Produces the 32-byte `cctp-forward` header (24-byte ASCII magic + `uint32`
|
|
10217
|
+
* version + `uint32` `dataLength = 0`) followed by `payload` appended verbatim.
|
|
10218
|
+
* Unlike {@link buildForwardingHookData} — which emits only the fixed,
|
|
10219
|
+
* version-0 empty frame — this lets the caller set the frame `version` and
|
|
10220
|
+
* carry an inner payload such as a GenericExecutor blob.
|
|
10221
|
+
*
|
|
10222
|
+
* @remarks
|
|
10223
|
+
* The forwarder reads only the 32-byte header to decide that a hook is
|
|
10224
|
+
* forwardable, then strips it before the inner payload is consumed downstream
|
|
10225
|
+
* (e.g. the GenericExecutor `abi.decode`s the appended blob, never the frame).
|
|
10226
|
+
* `dataLength` stays `0` because the appended bytes are opaque to the forwarder
|
|
10227
|
+
* — it is not the payload's length.
|
|
10228
|
+
*
|
|
10229
|
+
* @param version - The `uint32` frame version (e.g. `1` for the GenericExecutor
|
|
10230
|
+
* FORWARD path). Must be an integer in `[0, 0xFFFFFFFF]`.
|
|
10231
|
+
* @param payload - A 0x-prefixed hex string appended after the header (e.g. the
|
|
10232
|
+
* bare GenericExecutor blob from `buildDepositForGenericExecutorPayload`).
|
|
10233
|
+
* @returns A 0x-prefixed hex string: the 32-byte frame followed by `payload`.
|
|
10234
|
+
* @throws {KitError} If `version` is out of `uint32` range or `payload` is not
|
|
10235
|
+
* a 0x-prefixed hex string (INPUT_VALIDATION_FAILED).
|
|
10236
|
+
*
|
|
10237
|
+
* @example
|
|
10238
|
+
* ```typescript
|
|
10239
|
+
* import {
|
|
10240
|
+
* buildDepositForGenericExecutorPayload,
|
|
10241
|
+
* buildForwardingHookDataWithPayload,
|
|
10242
|
+
* padAddressToBytes32,
|
|
10243
|
+
* } from '@core/utils'
|
|
10244
|
+
*
|
|
10245
|
+
* const { hookData: geBlob } = buildDepositForGenericExecutorPayload({
|
|
10246
|
+
* dappId: 'gateway_deposit',
|
|
10247
|
+
* domainId: 26,
|
|
10248
|
+
* handler: '0xHandlerAddressOnDestinationChain',
|
|
10249
|
+
* params: [USDC_ARC, user, 0],
|
|
10250
|
+
* recoveryAddress: padAddressToBytes32(user),
|
|
10251
|
+
* })
|
|
10252
|
+
*
|
|
10253
|
+
* // Wrap for the prepaid Quote-API FORWARD path (frame version 1).
|
|
10254
|
+
* const hookData = buildForwardingHookDataWithPayload(1, geBlob)
|
|
10255
|
+
* ```
|
|
10256
|
+
*/ function buildForwardingHookDataWithPayload(version, payload) {
|
|
10257
|
+
if (!Number.isInteger(version) || version < 0 || version > MAX_UINT32) {
|
|
10258
|
+
throw createValidationFailedError$1('version', version, 'Expected an integer in the uint32 range [0, 4294967295]');
|
|
10259
|
+
}
|
|
10260
|
+
if (!isHexString(payload)) {
|
|
10261
|
+
throw createValidationFailedError$1('payload', payload, 'Expected a 0x-prefixed hex string');
|
|
10262
|
+
}
|
|
10263
|
+
// `isHexString` accepts odd-length hex (e.g. '0xabc'); catch it here so it
|
|
10264
|
+
// surfaces as a KitError rather than ethers' raw "hex data is odd-length"
|
|
10265
|
+
// from `concat` below.
|
|
10266
|
+
if (payload.length % 2 !== 0) {
|
|
10267
|
+
throw createValidationFailedError$1('payload', payload, 'Expected an even-length (whole-byte) hex string');
|
|
10268
|
+
}
|
|
10269
|
+
// 32-byte header: 24-byte magic + uint32 version + uint32 dataLength (0).
|
|
10270
|
+
const frame = new Uint8Array(32);
|
|
10271
|
+
frame.set(new TextEncoder().encode(CCTP_FORWARD_MAGIC_PREFIX), 0);
|
|
10272
|
+
const view = new DataView(frame.buffer);
|
|
10273
|
+
view.setUint32(24, version, false) // big-endian
|
|
10274
|
+
;
|
|
10275
|
+
view.setUint32(28, CCTP_FORWARD_PAYLOAD_LENGTH, false) // big-endian, 0
|
|
10276
|
+
;
|
|
10277
|
+
return hexlify(concat([
|
|
10278
|
+
frame,
|
|
10279
|
+
payload
|
|
10280
|
+
]));
|
|
10281
|
+
}
|
|
10047
10282
|
/**
|
|
10048
10283
|
* Build a `cctp-forward` hookData frame that instructs Circle's Orbit relayer to
|
|
10049
10284
|
* create the recipient's Associated Token Account (ATA) before minting on Solana.
|
|
@@ -10121,6 +10356,43 @@ function buildForwardingHookData() {
|
|
|
10121
10356
|
]));
|
|
10122
10357
|
}
|
|
10123
10358
|
|
|
10359
|
+
/**
|
|
10360
|
+
* `version` field of the GenericExecutor hookData, in both the
|
|
10361
|
+
* `circle-generic-executor` header (`uint32`) and the ABI tuple (`uint8`). The
|
|
10362
|
+
* executor reverts if it is not `1`.
|
|
10363
|
+
*
|
|
10364
|
+
* @see https://circlepay.atlassian.net/wiki/spaces/~712020cd79585b52ea4353b4720c277fbfcca6/pages/3049291839
|
|
10365
|
+
*/ const GENERIC_EXECUTOR_HOOK_DATA_VERSION = 1;
|
|
10366
|
+
/**
|
|
10367
|
+
* ASCII magic that prefixes a GenericExecutor hookData blob.
|
|
10368
|
+
*
|
|
10369
|
+
* The executor auto-detects its payload by this string. It is left-aligned and
|
|
10370
|
+
* zero-padded to 24 bytes in the header, mirroring the `cctp-forward` frame
|
|
10371
|
+
* layout (magic + `uint32` version + `uint32` dataLength).
|
|
10372
|
+
*/ const GENERIC_EXECUTOR_MAGIC_PREFIX = 'circle-generic-executor';
|
|
10373
|
+
/**
|
|
10374
|
+
* Prepend the 32-byte `circle-generic-executor` header to the ABI tuple.
|
|
10375
|
+
*
|
|
10376
|
+
* Header layout (mirrors the `cctp-forward` frame): 24-byte zero-padded ASCII
|
|
10377
|
+
* magic + `uint32` version + `uint32` dataLength. Unlike the `cctp-forward`
|
|
10378
|
+
* frame (which the forwarder strips and so carries `dataLength = 0`), this
|
|
10379
|
+
* header's dataLength is the byte length of the ABI tuple that follows, since
|
|
10380
|
+
* the executor consumes both.
|
|
10381
|
+
*/ function prependGenericExecutorHeader(abiTuple) {
|
|
10382
|
+
const header = new Uint8Array(32);
|
|
10383
|
+
header.set(new TextEncoder().encode(GENERIC_EXECUTOR_MAGIC_PREFIX), 0);
|
|
10384
|
+
// Byte length of the ABI tuple that the header announces.
|
|
10385
|
+
const tupleByteLength = (abiTuple.length - 2) / 2;
|
|
10386
|
+
const view = new DataView(header.buffer);
|
|
10387
|
+
view.setUint32(24, GENERIC_EXECUTOR_HOOK_DATA_VERSION, false) // big-endian
|
|
10388
|
+
;
|
|
10389
|
+
view.setUint32(28, tupleByteLength, false) // big-endian
|
|
10390
|
+
;
|
|
10391
|
+
return hexlify(concat([
|
|
10392
|
+
header,
|
|
10393
|
+
abiTuple
|
|
10394
|
+
]));
|
|
10395
|
+
}
|
|
10124
10396
|
/**
|
|
10125
10397
|
* Left-pad a 20-byte EVM address to a 32-byte (`bytes32`) hex string.
|
|
10126
10398
|
*
|
|
@@ -10146,6 +10418,309 @@ function buildForwardingHookData() {
|
|
|
10146
10418
|
// matches ABI-decoded output.
|
|
10147
10419
|
return hexZeroPad(getAddress(address), 32).toLowerCase();
|
|
10148
10420
|
}
|
|
10421
|
+
/**
|
|
10422
|
+
* Encode the bare GenericExecutor + DepositForHandler payload for a CCTP v2
|
|
10423
|
+
* fast-transfer deposit into a dApp.
|
|
10424
|
+
*
|
|
10425
|
+
* Builds the layers inner→outer:
|
|
10426
|
+
* 1. dApp calldata — the dApp function selector + ABI params, with each amount
|
|
10427
|
+
* slot left as the caller-supplied placeholder.
|
|
10428
|
+
* 2. handler calldata — `(depositContract, approvalTarget, depositCalldata, amountIndices)`
|
|
10429
|
+
* for `DepositForHandler`.
|
|
10430
|
+
* 3. ABI tuple — `(uint8 version, bytes32 recoveryAddress, address handler, bytes handlerCalldata)`.
|
|
10431
|
+
* No handler selector travels on the wire; the executor applies a fixed one.
|
|
10432
|
+
* 4. header — the 32-byte `circle-generic-executor` magic frame prepended to the
|
|
10433
|
+
* tuple, by which the executor auto-detects the payload.
|
|
10434
|
+
*
|
|
10435
|
+
* The returned `hookData` is the bare GenericExecutor blob (header ‖ tuple) — the
|
|
10436
|
+
* exact bytes the executor consumes. It carries no `cctp-forward` envelope. For
|
|
10437
|
+
* the prepaid Quote-API FORWARD path, wrap it with
|
|
10438
|
+
* {@link buildForwardingHookDataWithPayload}; the forwarder strips that envelope
|
|
10439
|
+
* before the executor reads the blob.
|
|
10440
|
+
*
|
|
10441
|
+
* @param options - See {@link BuildDepositForGenericExecutorPayloadParams}.
|
|
10442
|
+
* @returns The encoded {@link DepositForGenericExecutorPayload} layers.
|
|
10443
|
+
* @throws {KitError} If `options` is not an object, `dappId` is unknown,
|
|
10444
|
+
* `config.deployments` is not an array, neither `domainId` nor
|
|
10445
|
+
* `destinationChain` resolves a domain (or the two disagree), no deployment
|
|
10446
|
+
* exists for the resolved domain, the deposit contract cannot be resolved (a
|
|
10447
|
+
* built-in deployment supplied without a `destinationChain`), no `handler` is
|
|
10448
|
+
* supplied and it cannot be resolved from `destinationChain`,
|
|
10449
|
+
* `recoveryAddress`/`handler`/contract addresses are malformed,
|
|
10450
|
+
* `config.function` is not a valid Solidity function signature, `params`
|
|
10451
|
+
* length does not match the dApp signature, `params` values fail ABI encoding
|
|
10452
|
+
* (type mismatch), `config.dynamicAmountIndices` is not an array, or an amount
|
|
10453
|
+
* index is out of range (all INPUT_VALIDATION_FAILED).
|
|
10454
|
+
*
|
|
10455
|
+
* @example Encode a 1-click cross-chain Circle Gateway deposit
|
|
10456
|
+
* ```typescript
|
|
10457
|
+
* import { buildDepositForGenericExecutorPayload, padAddressToBytes32 } from '@core/utils'
|
|
10458
|
+
* import { ArcTestnet } from '@core/chains'
|
|
10459
|
+
*
|
|
10460
|
+
* const user = '0x75275Aff2D01699D922f045b69ed291311209738'
|
|
10461
|
+
* const usdcArc = '0x3600000000000000000000000000000000000000'
|
|
10462
|
+
* const { hookData } = buildDepositForGenericExecutorPayload({
|
|
10463
|
+
* dappId: 'gateway_deposit',
|
|
10464
|
+
* destinationChain: ArcTestnet, // resolves the GatewayWallet + DepositForHandler
|
|
10465
|
+
* // depositFor(address token, address depositor, uint256 value), amount idx [2]
|
|
10466
|
+
* params: [usdcArc, user, 0],
|
|
10467
|
+
* recoveryAddress: padAddressToBytes32(user),
|
|
10468
|
+
* })
|
|
10469
|
+
*
|
|
10470
|
+
* // Pass hookData straight into the CCTP v2 fast transfer.
|
|
10471
|
+
* console.log(hookData)
|
|
10472
|
+
* ```
|
|
10473
|
+
*/ function buildDepositForGenericExecutorPayload(options) {
|
|
10474
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- runtime guard for plain-JS callers
|
|
10475
|
+
if (options === null || typeof options !== 'object') {
|
|
10476
|
+
throw createValidationFailedError$1('options', options, 'Expected an options object');
|
|
10477
|
+
}
|
|
10478
|
+
const { dappId, params: dappParams } = options;
|
|
10479
|
+
const registry = options.config ?? DAPP_CONFIG;
|
|
10480
|
+
// Look up the dApp before resolving the deposit contract or handler, so an
|
|
10481
|
+
// unknown dApp reports the actionable "Unknown dApp" error rather than an
|
|
10482
|
+
// unresolved-handler error.
|
|
10483
|
+
const config = registry[dappId];
|
|
10484
|
+
if (config === undefined) {
|
|
10485
|
+
throw createValidationFailedError$1('dappId', dappId, `Unknown dApp. Known dApps: ${Object.keys(registry).join(', ')}`);
|
|
10486
|
+
}
|
|
10487
|
+
if (!Array.isArray(config.deployments)) {
|
|
10488
|
+
throw createValidationFailedError$1('deployments', config.deployments, `Expected an array of deployments for dApp '${dappId}'`);
|
|
10489
|
+
}
|
|
10490
|
+
// Array.isArray narrows to `any[]`; re-assert the concrete type.
|
|
10491
|
+
const deployments = config.deployments;
|
|
10492
|
+
// Destination CCTP domain: taken from `destinationChain` when supplied (the
|
|
10493
|
+
// chain is the (network, domain) key), else the explicit `domainId`.
|
|
10494
|
+
const domainId = resolveDomainId(options);
|
|
10495
|
+
const deployment = deployments.find((d)=>d.domainId === domainId);
|
|
10496
|
+
if (deployment === undefined) {
|
|
10497
|
+
throw createValidationFailedError$1('domainId', domainId, `No '${dappId}' deployment for domain ${String(domainId)}`);
|
|
10498
|
+
}
|
|
10499
|
+
if (!Array.isArray(dappParams)) {
|
|
10500
|
+
throw createValidationFailedError$1('params', dappParams, 'Expected an array of ABI-ordered parameters');
|
|
10501
|
+
}
|
|
10502
|
+
if (!isHexString(options.recoveryAddress, 32)) {
|
|
10503
|
+
throw createValidationFailedError$1('recoveryAddress', options.recoveryAddress, 'Expected a 0x-prefixed 32-byte (bytes32) hex string');
|
|
10504
|
+
}
|
|
10505
|
+
// Deposit contract: the deployment's own address, or — for the built-in
|
|
10506
|
+
// gateway_deposit deployment, which carries none — the destination chain's
|
|
10507
|
+
// GatewayWallet, so the address lives only in @core/chains.
|
|
10508
|
+
const resolvedDepositContract = resolveDepositContract(deployment, options, dappId);
|
|
10509
|
+
// Handler: an explicit `handler` always wins; otherwise resolve the
|
|
10510
|
+
// DepositForHandler from `destinationChain`. The chain is the (network, domain)
|
|
10511
|
+
// key, so a shared CCTP domain (Arc is 26 on both testnet and mainnet) can
|
|
10512
|
+
// never resolve the wrong network's handler and strand funds.
|
|
10513
|
+
const handler = resolveDepositForHandler(options, domainId);
|
|
10514
|
+
if (!isAddress(handler)) {
|
|
10515
|
+
throw createValidationFailedError$1('handler', handler, 'Expected a valid EVM address');
|
|
10516
|
+
}
|
|
10517
|
+
const depositContract = assertAddress(resolvedDepositContract, 'depositContract');
|
|
10518
|
+
const approvalTarget = assertAddress(deployment.approvalTarget ?? resolvedDepositContract, 'approvalTarget');
|
|
10519
|
+
// 1. dApp calldata: selector + ABI-encoded params (amount slots stay as placeholders).
|
|
10520
|
+
let dappInterface;
|
|
10521
|
+
try {
|
|
10522
|
+
dappInterface = new Interface([
|
|
10523
|
+
`function ${config.function}`
|
|
10524
|
+
]);
|
|
10525
|
+
} catch {
|
|
10526
|
+
throw createValidationFailedError$1('function', config.function, 'Expected a valid Solidity function signature');
|
|
10527
|
+
}
|
|
10528
|
+
const rawFragment = dappInterface.fragments[0];
|
|
10529
|
+
/* v8 ignore start -- defensive: guards against unexpected library behavior */ if (rawFragment === undefined || rawFragment.type !== 'function') {
|
|
10530
|
+
throw createValidationFailedError$1('function', config.function, 'Expected a valid Solidity function signature');
|
|
10531
|
+
}
|
|
10532
|
+
/* v8 ignore stop */ const fragment = rawFragment;
|
|
10533
|
+
if (dappParams.length !== fragment.inputs.length) {
|
|
10534
|
+
throw createValidationFailedError$1('params', dappParams, `'${config.function}' expects ${String(fragment.inputs.length)} params, got ${String(dappParams.length)}`);
|
|
10535
|
+
}
|
|
10536
|
+
let depositCalldata;
|
|
10537
|
+
try {
|
|
10538
|
+
depositCalldata = dappInterface.encodeFunctionData(fragment, dappParams);
|
|
10539
|
+
} catch {
|
|
10540
|
+
throw createValidationFailedError$1('params', dappParams, 'ABI encoding failed — check that each param matches the expected Solidity type');
|
|
10541
|
+
}
|
|
10542
|
+
if (!Array.isArray(config.dynamicAmountIndices)) {
|
|
10543
|
+
throw createValidationFailedError$1('dynamicAmountIndices', config.dynamicAmountIndices, `Expected an array of amount indices for dApp '${dappId}'`);
|
|
10544
|
+
}
|
|
10545
|
+
// Array.isArray narrows to `any[]`; re-assert the concrete type.
|
|
10546
|
+
const dynamicAmountIndices = config.dynamicAmountIndices;
|
|
10547
|
+
// Amount byte offsets in depositCalldata: 4 (selector) + paramIndex * 32.
|
|
10548
|
+
const amountIndices = dynamicAmountIndices.map((paramIndex)=>{
|
|
10549
|
+
if (!Number.isInteger(paramIndex) || paramIndex < 0 || paramIndex >= fragment.inputs.length) {
|
|
10550
|
+
throw createValidationFailedError$1('dynamicAmountIndices', paramIndex, `Index out of range for '${config.function}' (${String(fragment.inputs.length)} params)`);
|
|
10551
|
+
}
|
|
10552
|
+
return BigInt(4 + paramIndex * 32);
|
|
10553
|
+
});
|
|
10554
|
+
// 2. Handler layer.
|
|
10555
|
+
const handlerCalldata = defaultAbiCoder.encode([
|
|
10556
|
+
'address',
|
|
10557
|
+
'address',
|
|
10558
|
+
'bytes',
|
|
10559
|
+
'uint256[]'
|
|
10560
|
+
], [
|
|
10561
|
+
depositContract,
|
|
10562
|
+
approvalTarget,
|
|
10563
|
+
depositCalldata,
|
|
10564
|
+
amountIndices
|
|
10565
|
+
]);
|
|
10566
|
+
// 3. Executor ABI tuple. No handler selector travels on the wire — the
|
|
10567
|
+
// executor applies a fixed selector internally.
|
|
10568
|
+
const executorTuple = defaultAbiCoder.encode([
|
|
10569
|
+
'uint8',
|
|
10570
|
+
'bytes32',
|
|
10571
|
+
'address',
|
|
10572
|
+
'bytes'
|
|
10573
|
+
], [
|
|
10574
|
+
GENERIC_EXECUTOR_HOOK_DATA_VERSION,
|
|
10575
|
+
options.recoveryAddress,
|
|
10576
|
+
getAddress(handler),
|
|
10577
|
+
handlerCalldata
|
|
10578
|
+
]);
|
|
10579
|
+
// 4. Prepend the circle-generic-executor magic header; this is the final
|
|
10580
|
+
// bare GE blob the executor consumes.
|
|
10581
|
+
const hookData = prependGenericExecutorHeader(executorTuple);
|
|
10582
|
+
return {
|
|
10583
|
+
hookData,
|
|
10584
|
+
handlerCalldata,
|
|
10585
|
+
depositCalldata,
|
|
10586
|
+
amountIndices,
|
|
10587
|
+
depositContract,
|
|
10588
|
+
approvalTarget
|
|
10589
|
+
};
|
|
10590
|
+
}
|
|
10591
|
+
/**
|
|
10592
|
+
* Config key of the built-in Circle Gateway deposit dApp. Its deposit contract
|
|
10593
|
+
* is the destination chain's GatewayWallet, resolved from `destinationChain`
|
|
10594
|
+
* (not a hardcoded address), so this is the only dApp whose deployment may omit
|
|
10595
|
+
* `depositContract`.
|
|
10596
|
+
*/ const GATEWAY_DEPOSIT_DAPP_ID = 'gateway_deposit';
|
|
10597
|
+
/**
|
|
10598
|
+
* Built-in dApp registry. Adding a new `depositFor`-style dApp is a config entry
|
|
10599
|
+
* here (or via {@link BuildDepositForGenericExecutorPayloadParams.config}).
|
|
10600
|
+
*
|
|
10601
|
+
* @remarks
|
|
10602
|
+
* Only dApps with confirmed deployment addresses and active callers are included.
|
|
10603
|
+
* The built-in `gateway_deposit` entry omits `depositContract` — it is resolved
|
|
10604
|
+
* from the destination chain's GatewayWallet (`@core/chains`) rather than
|
|
10605
|
+
* duplicated here. Pass a custom registry via `config` for unlisted dApps.
|
|
10606
|
+
*/ const DAPP_CONFIG = {
|
|
10607
|
+
// Circle Gateway: depositFor(address token, address depositor, uint256 value)
|
|
10608
|
+
[GATEWAY_DEPOSIT_DAPP_ID]: {
|
|
10609
|
+
function: 'depositFor(address,address,uint256)',
|
|
10610
|
+
dynamicAmountIndices: [
|
|
10611
|
+
2
|
|
10612
|
+
],
|
|
10613
|
+
deployments: [
|
|
10614
|
+
// Arc Testnet (CCTP domain 26). The deposit contract is the chain's
|
|
10615
|
+
// GatewayWallet, resolved from `destinationChain` (@core/chains) rather
|
|
10616
|
+
// than duplicated here.
|
|
10617
|
+
{
|
|
10618
|
+
domainId: 26
|
|
10619
|
+
}
|
|
10620
|
+
]
|
|
10621
|
+
}
|
|
10622
|
+
};
|
|
10623
|
+
/**
|
|
10624
|
+
* Resolve the destination CCTP domain for an encode request.
|
|
10625
|
+
*
|
|
10626
|
+
* Prefers {@link BuildDepositForGenericExecutorPayloadParams.destinationChain}
|
|
10627
|
+
* (`chain.cctp.domain`) — the chain is the (network, domain) key. Falls back to
|
|
10628
|
+
* an explicit `domainId`. When both are supplied they must agree.
|
|
10629
|
+
*
|
|
10630
|
+
* @param options - The encode request.
|
|
10631
|
+
* @returns The destination CCTP domain.
|
|
10632
|
+
* @throws {KitError} If no domain is available, or `domainId` disagrees with
|
|
10633
|
+
* `destinationChain` (INPUT_VALIDATION_FAILED).
|
|
10634
|
+
* @internal
|
|
10635
|
+
*/ function resolveDomainId(options) {
|
|
10636
|
+
const chain = options.destinationChain;
|
|
10637
|
+
if (chain !== undefined) {
|
|
10638
|
+
const chainDomain = chain.cctp?.domain;
|
|
10639
|
+
if (chainDomain !== undefined) {
|
|
10640
|
+
if (options.domainId !== undefined && options.domainId !== chainDomain) {
|
|
10641
|
+
throw createValidationFailedError$1('domainId', options.domainId, `does not match destinationChain '${chain.name}' CCTP domain ` + String(chainDomain));
|
|
10642
|
+
}
|
|
10643
|
+
return chainDomain;
|
|
10644
|
+
}
|
|
10645
|
+
}
|
|
10646
|
+
if (options.domainId !== undefined) {
|
|
10647
|
+
return options.domainId;
|
|
10648
|
+
}
|
|
10649
|
+
throw createValidationFailedError$1('domainId', options.domainId, "Provide 'domainId', or a 'destinationChain' with a CCTP domain");
|
|
10650
|
+
}
|
|
10651
|
+
/**
|
|
10652
|
+
* Resolve the deposit contract the handler calls.
|
|
10653
|
+
*
|
|
10654
|
+
* Uses the deployment's own `depositContract` when present. Only the built-in
|
|
10655
|
+
* {@link GATEWAY_DEPOSIT_DAPP_ID} may omit it: its deposit contract is the
|
|
10656
|
+
* destination chain's Gateway v1 wallet, resolved from
|
|
10657
|
+
* {@link BuildDepositForGenericExecutorPayloadParams.destinationChain} so the
|
|
10658
|
+
* address is owned once in `@core/chains`. Any other dApp that omits
|
|
10659
|
+
* `depositContract` is a config error and fails here rather than silently
|
|
10660
|
+
* targeting the GatewayWallet.
|
|
10661
|
+
*
|
|
10662
|
+
* @param deployment - The resolved dApp deployment.
|
|
10663
|
+
* @param options - The encode request.
|
|
10664
|
+
* @param dappId - The dApp key, checked against {@link GATEWAY_DEPOSIT_DAPP_ID}.
|
|
10665
|
+
* @returns The deposit contract address (unvalidated; the caller checks it).
|
|
10666
|
+
* @throws {KitError} If a non-`gateway_deposit` deployment omits
|
|
10667
|
+
* `depositContract`, or if `gateway_deposit` has no Gateway v1
|
|
10668
|
+
* `destinationChain` to resolve one (INPUT_VALIDATION_FAILED).
|
|
10669
|
+
* @internal
|
|
10670
|
+
*/ function resolveDepositContract(deployment, options, dappId) {
|
|
10671
|
+
if (deployment.depositContract !== undefined) {
|
|
10672
|
+
return deployment.depositContract;
|
|
10673
|
+
}
|
|
10674
|
+
// Only gateway_deposit may omit its address (it targets the chain's
|
|
10675
|
+
// GatewayWallet). Any other addressless deployment is a config mistake and
|
|
10676
|
+
// must fail rather than silently resolve to the GatewayWallet.
|
|
10677
|
+
if (dappId !== GATEWAY_DEPOSIT_DAPP_ID) {
|
|
10678
|
+
throw createValidationFailedError$1('depositContract', dappId, `dApp '${dappId}' must declare a 'depositContract'; only the built-in ` + `'${GATEWAY_DEPOSIT_DAPP_ID}' resolves its address from the ` + "destination chain's GatewayWallet");
|
|
10679
|
+
}
|
|
10680
|
+
const chain = options.destinationChain;
|
|
10681
|
+
if (chain === undefined || !isGatewayV1Supported(chain)) {
|
|
10682
|
+
throw createValidationFailedError$1('depositContract', dappId, `'${GATEWAY_DEPOSIT_DAPP_ID}' needs a 'destinationChain' with Gateway v1 ` + 'support to resolve its GatewayWallet, or an explicit deployment address');
|
|
10683
|
+
}
|
|
10684
|
+
return chain.gateway.contracts.v1.wallet;
|
|
10685
|
+
}
|
|
10686
|
+
/**
|
|
10687
|
+
* Resolve the `DepositForHandler` address for an encode request.
|
|
10688
|
+
*
|
|
10689
|
+
* An explicit `options.handler` always wins. Otherwise the handler is resolved
|
|
10690
|
+
* from {@link BuildDepositForGenericExecutorPayloadParams.destinationChain}
|
|
10691
|
+
* (`chain.gateway.contracts.v1.depositForHandler`). The chain is the (network,
|
|
10692
|
+
* domain) key, so a CCTP domain shared across a chain's testnet and mainnet
|
|
10693
|
+
* cannot resolve the wrong network's handler; a missing chain or an unregistered
|
|
10694
|
+
* handler throws rather than guessing.
|
|
10695
|
+
*
|
|
10696
|
+
* @param options - The encode request.
|
|
10697
|
+
* @param domainId - The resolved destination domain, reported in the error.
|
|
10698
|
+
* @returns The resolved handler address (unvalidated; the caller checks it).
|
|
10699
|
+
* @throws {KitError} If `handler` is omitted and cannot be resolved
|
|
10700
|
+
* (INPUT_VALIDATION_FAILED).
|
|
10701
|
+
* @internal
|
|
10702
|
+
*/ function resolveDepositForHandler(options, domainId) {
|
|
10703
|
+
if (options.handler !== undefined) {
|
|
10704
|
+
return options.handler;
|
|
10705
|
+
}
|
|
10706
|
+
const chain = options.destinationChain;
|
|
10707
|
+
if (chain === undefined) {
|
|
10708
|
+
throw createValidationFailedError$1('handler', domainId, "No 'handler' supplied; pass 'handler' explicitly, or a " + "'destinationChain' whose Gateway config registers a DepositForHandler");
|
|
10709
|
+
}
|
|
10710
|
+
const registered = isGatewayV1Supported(chain) ? chain.gateway.contracts.v1.depositForHandler : undefined;
|
|
10711
|
+
if (registered === undefined) {
|
|
10712
|
+
throw createValidationFailedError$1('handler', domainId, `No DepositForHandler registered for domain ${String(domainId)} on ` + `chain '${chain.name}'; pass 'handler' explicitly`);
|
|
10713
|
+
}
|
|
10714
|
+
return registered;
|
|
10715
|
+
}
|
|
10716
|
+
/**
|
|
10717
|
+
* Validate and checksum an EVM address, throwing a consistent validation error.
|
|
10718
|
+
*/ function assertAddress(address, field) {
|
|
10719
|
+
if (!isAddress(address)) {
|
|
10720
|
+
throw createValidationFailedError$1(field, address, 'Expected a valid EVM address');
|
|
10721
|
+
}
|
|
10722
|
+
return getAddress(address);
|
|
10723
|
+
}
|
|
10149
10724
|
|
|
10150
10725
|
/**
|
|
10151
10726
|
* Configuration for {@link retryAsync}.
|
|
@@ -10235,7 +10810,7 @@ function resolveOptions(options) {
|
|
|
10235
10810
|
* allowlisted {@link ClientLogPayload} fields (and the allowlisted
|
|
10236
10811
|
* sub-fields of `errorDetails` / `clientContext`) are copied across.
|
|
10237
10812
|
* A regressing upstream mapper — or a plain-JS caller that bypasses the
|
|
10238
|
-
* type — therefore cannot exfiltrate stray properties (secrets,
|
|
10813
|
+
* type — therefore cannot exfiltrate stray properties (secrets,
|
|
10239
10814
|
* raw error stacks) through the analytics channel. Optional fields are
|
|
10240
10815
|
* only included when present so the serialised shape matches the
|
|
10241
10816
|
* server's strict schema.
|
|
@@ -10258,6 +10833,9 @@ function resolveOptions(options) {
|
|
|
10258
10833
|
if (payload.destinationChain !== undefined) safe['destinationChain'] = payload.destinationChain;
|
|
10259
10834
|
if (payload.tokenIn !== undefined) safe['tokenIn'] = payload.tokenIn;
|
|
10260
10835
|
if (payload.tokenOut !== undefined) safe['tokenOut'] = payload.tokenOut;
|
|
10836
|
+
if (payload.amountIn !== undefined) safe['amountIn'] = payload.amountIn;
|
|
10837
|
+
if (payload.durationMs !== undefined) safe['durationMs'] = payload.durationMs;
|
|
10838
|
+
if (payload.sourceAddress !== undefined) safe['sourceAddress'] = payload.sourceAddress;
|
|
10261
10839
|
if (payload.txHash !== undefined) safe['txHash'] = payload.txHash;
|
|
10262
10840
|
if (payload.correlationId !== undefined) safe['correlationId'] = payload.correlationId;
|
|
10263
10841
|
if (payload.errorDetails !== undefined) {
|
|
@@ -10454,14 +11032,28 @@ function resolveOptions(options) {
|
|
|
10454
11032
|
}
|
|
10455
11033
|
|
|
10456
11034
|
/**
|
|
10457
|
-
*
|
|
10458
|
-
*
|
|
11035
|
+
* Emit a stable console warning when building or emitting a telemetry payload
|
|
11036
|
+
* throws — for example, a buggy `TelemetryContextResolver`, a regression in
|
|
10459
11037
|
* `extractErrorDetails`, or a synchronous failure inside `emitAnalyticsLog`
|
|
10460
|
-
* before it could swallow the error itself.
|
|
10461
|
-
*
|
|
10462
|
-
*
|
|
11038
|
+
* before it could swallow the error itself. Uses a stable prefix so the
|
|
11039
|
+
* drop is discoverable via grep. Never re-throws: the caller's original
|
|
11040
|
+
* operation error must always win.
|
|
10463
11041
|
*
|
|
10464
11042
|
* @internal
|
|
11043
|
+
*
|
|
11044
|
+
* @param eventType - The telemetry event type that was being emitted.
|
|
11045
|
+
* @param cause - The error or value that caused the drop.
|
|
11046
|
+
*
|
|
11047
|
+
* @example
|
|
11048
|
+
* ```typescript
|
|
11049
|
+
* import { warnTelemetryDrop } from '@core/utils'
|
|
11050
|
+
*
|
|
11051
|
+
* try {
|
|
11052
|
+
* void emitAnalyticsLog(payload)
|
|
11053
|
+
* } catch (err) {
|
|
11054
|
+
* warnTelemetryDrop('my_event', err)
|
|
11055
|
+
* }
|
|
11056
|
+
* ```
|
|
10465
11057
|
*/ function warnTelemetryDrop(eventType, cause) {
|
|
10466
11058
|
try {
|
|
10467
11059
|
// Pass `cause` as the second console.warn argument rather than
|
|
@@ -10501,6 +11093,9 @@ function resolveOptions(options) {
|
|
|
10501
11093
|
...context?.tokenOut != null && {
|
|
10502
11094
|
tokenOut: context.tokenOut
|
|
10503
11095
|
},
|
|
11096
|
+
...context?.amountIn != null && {
|
|
11097
|
+
amountIn: context.amountIn
|
|
11098
|
+
},
|
|
10504
11099
|
...context?.txHash != null && {
|
|
10505
11100
|
txHash: context.txHash
|
|
10506
11101
|
},
|
|
@@ -10602,7 +11197,7 @@ function resolveOptions(options) {
|
|
|
10602
11197
|
const stepEntry = stepEventMap.find(([name])=>name === failedStep?.name);
|
|
10603
11198
|
// `failedStep.errorMessage` is intentionally **not** copied into the payload.
|
|
10604
11199
|
// Provider messages are unbounded and frequently contain operator data
|
|
10605
|
-
// (
|
|
11200
|
+
// (signatures, partial intent payloads, raw RPC responses). The
|
|
10606
11201
|
// step name plus the surrounding context fields already identify *which*
|
|
10607
11202
|
// phase failed; the *why* is left to the corresponding step-level logs that
|
|
10608
11203
|
// the provider emits separately. The thrown-error path (`extractErrorDetails`
|
|
@@ -10619,7 +11214,7 @@ function resolveOptions(options) {
|
|
|
10619
11214
|
}
|
|
10620
11215
|
|
|
10621
11216
|
var name$2 = "@circle-fin/bridge-kit";
|
|
10622
|
-
var version$3 = "1.14.
|
|
11217
|
+
var version$3 = "1.14.1";
|
|
10623
11218
|
var pkg$3 = {
|
|
10624
11219
|
name: name$2,
|
|
10625
11220
|
version: version$3};
|
|
@@ -12313,7 +12908,7 @@ var TransferSpeed;
|
|
|
12313
12908
|
* })
|
|
12314
12909
|
* ```
|
|
12315
12910
|
*/ function createLogger(options, stream) {
|
|
12316
|
-
const { redact, ...pinoOptions } = {};
|
|
12911
|
+
const { redact, ...pinoOptions } = options ?? {};
|
|
12317
12912
|
// Build redaction config
|
|
12318
12913
|
const redactConfig = buildRedactConfig(redact);
|
|
12319
12914
|
// Build final pino options, only include redact if defined
|
|
@@ -13667,6 +14262,8 @@ const CUSTOM_BURN_GAS_ESTIMATE_EVM = 201_525n // p99 and max are same here: 201_
|
|
|
13667
14262
|
;
|
|
13668
14263
|
const RECEIVE_MESSAGE_GAS_ESTIMATE_EVM = 237_401n // (99p: 163_963n + max: 310_839n) / 2 = 237_401n
|
|
13669
14264
|
;
|
|
14265
|
+
/** Gas units consumed by `depositForBurnWithHookAndFees` on an EVM chain (prepaid-FORWARD path). */ const DEPOSIT_FOR_BURN_WITH_FEES_GAS_ESTIMATE_EVM = 626_584n // avg of the last 10 txns
|
|
14266
|
+
;
|
|
13670
14267
|
// Gas FLOORS, not ceilings — kept separate from the fee-estimate averages
|
|
13671
14268
|
// above. `executePreparedChainRequest` submits
|
|
13672
14269
|
// max(estimate * buffer, floor), so a chain whose real cost exceeds the floor
|
|
@@ -15948,7 +16545,7 @@ const mockAttestationMessage = {
|
|
|
15948
16545
|
return step;
|
|
15949
16546
|
}
|
|
15950
16547
|
|
|
15951
|
-
var version$2 = "1.
|
|
16548
|
+
var version$2 = "1.13.0";
|
|
15952
16549
|
var pkg$2 = {
|
|
15953
16550
|
version: version$2};
|
|
15954
16551
|
|
|
@@ -16654,6 +17251,9 @@ var pkg$2 = {
|
|
|
16654
17251
|
}
|
|
16655
17252
|
}
|
|
16656
17253
|
|
|
17254
|
+
const logger = createLogger({
|
|
17255
|
+
name: 'provider-cctp-v2'
|
|
17256
|
+
});
|
|
16657
17257
|
function isPlainObject(value) {
|
|
16658
17258
|
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
16659
17259
|
return false;
|
|
@@ -17016,6 +17616,116 @@ function assertCCTPV2Config(config) {
|
|
|
17016
17616
|
return estimateResult;
|
|
17017
17617
|
}
|
|
17018
17618
|
/**
|
|
17619
|
+
* Estimate source-chain gas for a prepaid-FORWARD deposit burn via
|
|
17620
|
+
* `TokenMessengerWithFees.depositForBurnWithHookAndFees`.
|
|
17621
|
+
*
|
|
17622
|
+
* Builds a size-correct GenericExecutor hookData placeholder — using the
|
|
17623
|
+
* pre-validated `contracts.executor` and `contracts.depositForHandler` — so
|
|
17624
|
+
* the EVM calldata length matches production. Attempts a live
|
|
17625
|
+
* `eth_estimateGas` via the adapter's `cctp.v2.depositForBurnWithFees`
|
|
17626
|
+
* action and falls back to the static
|
|
17627
|
+
* {@link DEPOSIT_FOR_BURN_WITH_FEES_GAS_ESTIMATE_EVM} constant when the live
|
|
17628
|
+
* RPC call fails.
|
|
17629
|
+
*
|
|
17630
|
+
* Gateway eligibility is the caller's responsibility: validate the
|
|
17631
|
+
* destination chain with `resolveGatewayExecutorContracts` (UBK) before
|
|
17632
|
+
* calling this method.
|
|
17633
|
+
*
|
|
17634
|
+
* @param params - Estimation parameters including adapter, chains, amount,
|
|
17635
|
+
* the signed fee quote returned by the Quote API, and the pre-validated
|
|
17636
|
+
* Gateway executor contracts resolved by the caller.
|
|
17637
|
+
* @returns Promise resolving to the estimated (or fallback) gas cost.
|
|
17638
|
+
* @throws KitError `SERVICE_INTERNAL_ERROR` (FATAL) if `dstChain`'s
|
|
17639
|
+
* `usdcAddress` is `null`.
|
|
17640
|
+
*
|
|
17641
|
+
* @example
|
|
17642
|
+
* ```typescript
|
|
17643
|
+
* const contracts = resolveGatewayExecutorContracts(srcChain, dstChain)
|
|
17644
|
+
* const gasEstimate = await CCTPV2BridgingProvider.estimateDepositBurn({
|
|
17645
|
+
* adapter: evmAdapter,
|
|
17646
|
+
* srcChain: Ethereum,
|
|
17647
|
+
* dstChain: ArcTestnet,
|
|
17648
|
+
* amountMinorUnits: 100_000_000n,
|
|
17649
|
+
* refundAddress: '0xUserWallet',
|
|
17650
|
+
* signedQuote: quote.signedQuote,
|
|
17651
|
+
* feeToken: quote.feeToken,
|
|
17652
|
+
* feeTotalAmount: BigInt(quote.feeTotalAmount),
|
|
17653
|
+
* resolvedContext,
|
|
17654
|
+
* contracts,
|
|
17655
|
+
* })
|
|
17656
|
+
* ```
|
|
17657
|
+
*/ static async estimateDepositBurn(params) {
|
|
17658
|
+
const { adapter, srcChain, dstChain, amountMinorUnits, refundAddress, signedQuote, feeToken, feeTotalAmount, resolvedContext, contracts } = params;
|
|
17659
|
+
const { executor, depositForHandler } = contracts;
|
|
17660
|
+
if (dstChain.usdcAddress === null) {
|
|
17661
|
+
throw new KitError({
|
|
17662
|
+
...ServiceError.INTERNAL_ERROR,
|
|
17663
|
+
recoverability: 'FATAL',
|
|
17664
|
+
message: `Destination chain ${dstChain.name} has no USDC address configured`
|
|
17665
|
+
});
|
|
17666
|
+
}
|
|
17667
|
+
// Build a size-correct hookData for eth_estimateGas. The EVM uses calldata
|
|
17668
|
+
// length to compute gas, so the byte layout must match production even
|
|
17669
|
+
// though field values are not final.
|
|
17670
|
+
const { hookData: geBlob } = buildDepositForGenericExecutorPayload({
|
|
17671
|
+
dappId: 'gateway_deposit',
|
|
17672
|
+
destinationChain: dstChain,
|
|
17673
|
+
handler: depositForHandler,
|
|
17674
|
+
params: [
|
|
17675
|
+
dstChain.usdcAddress,
|
|
17676
|
+
refundAddress,
|
|
17677
|
+
0n
|
|
17678
|
+
],
|
|
17679
|
+
recoveryAddress: padAddressToBytes32(refundAddress),
|
|
17680
|
+
// Override deployments only — spread the canonical function signature
|
|
17681
|
+
// and amount indices from DAPP_CONFIG so they stay in sync.
|
|
17682
|
+
config: {
|
|
17683
|
+
gateway_deposit: {
|
|
17684
|
+
...DAPP_CONFIG.gateway_deposit,
|
|
17685
|
+
deployments: [
|
|
17686
|
+
{
|
|
17687
|
+
domainId: dstChain.cctp.domain
|
|
17688
|
+
}
|
|
17689
|
+
]
|
|
17690
|
+
}
|
|
17691
|
+
}
|
|
17692
|
+
});
|
|
17693
|
+
const hookData = buildForwardingHookDataWithPayload(GENERIC_EXECUTOR_HOOK_DATA_VERSION, geBlob);
|
|
17694
|
+
// Coupling guard: the prepaid FORWARD path always requests a FORWARD fee
|
|
17695
|
+
// item, so the hookData must carry a `cctp-forward` frame — matches the
|
|
17696
|
+
// assertion in `prepareDepositForBurn`.
|
|
17697
|
+
assertForwardHookData(hookData);
|
|
17698
|
+
try {
|
|
17699
|
+
const prepared = await adapter.prepareAction('cctp.v2.depositForBurnWithFees', {
|
|
17700
|
+
fromChain: srcChain,
|
|
17701
|
+
toChain: dstChain,
|
|
17702
|
+
amount: amountMinorUnits,
|
|
17703
|
+
mintRecipient: executor,
|
|
17704
|
+
destinationCaller: executor,
|
|
17705
|
+
claim: {
|
|
17706
|
+
signedQuote,
|
|
17707
|
+
refundAddress
|
|
17708
|
+
},
|
|
17709
|
+
feeToken,
|
|
17710
|
+
feeTotalAmount,
|
|
17711
|
+
hookData
|
|
17712
|
+
}, resolvedContext);
|
|
17713
|
+
return await prepared.estimate(undefined);
|
|
17714
|
+
} catch (err) {
|
|
17715
|
+
logger.debug('estimateDepositBurn: live eth_estimateGas failed, using static fallback', {
|
|
17716
|
+
err,
|
|
17717
|
+
chain: srcChain.name
|
|
17718
|
+
});
|
|
17719
|
+
try {
|
|
17720
|
+
return await adapter.calculateTransactionFee(DEPOSIT_FOR_BURN_WITH_FEES_GAS_ESTIMATE_EVM, undefined, srcChain);
|
|
17721
|
+
} catch (feeErr) {
|
|
17722
|
+
throw createRpcEndpointError(srcChain.name, {
|
|
17723
|
+
rawError: feeErr
|
|
17724
|
+
});
|
|
17725
|
+
}
|
|
17726
|
+
}
|
|
17727
|
+
}
|
|
17728
|
+
/**
|
|
17019
17729
|
* Extracts OperationContext from bridge parameters for a given wallet context.
|
|
17020
17730
|
*
|
|
17021
17731
|
* This method extracts the chain and address information from the wallet context
|
|
@@ -17642,6 +18352,99 @@ function assertCCTPV2Config(config) {
|
|
|
17642
18352
|
return await source.adapter.prepareAction('cctp.v2.depositForBurn', actionParams, resolvedContext);
|
|
17643
18353
|
}
|
|
17644
18354
|
/**
|
|
18355
|
+
* Prepare the source-chain `depositForBurnWithHookAndFees` call for the
|
|
18356
|
+
* GenericExecutor FORWARD path.
|
|
18357
|
+
*
|
|
18358
|
+
* Exposed as a public static method so the UBK fast-deposit flow can invoke
|
|
18359
|
+
* it directly without holding a provider instance. The byte layout mirrors
|
|
18360
|
+
* {@link CCTPV2BridgingProvider.estimateDepositBurn} so gas estimates and the
|
|
18361
|
+
* executed call agree.
|
|
18362
|
+
*
|
|
18363
|
+
* @typeParam TFromAdapterCapabilities - The source adapter's capabilities.
|
|
18364
|
+
* @param params - Burn parameters including adapter, chains, deposit action,
|
|
18365
|
+
* amount, signer address, signed fee quote, and pre-resolved adapter context.
|
|
18366
|
+
* @returns The prepared `depositForBurnWithHookAndFees` burn transaction.
|
|
18367
|
+
* @throws {KitError} `UNSUPPORTED_ROUTE` when `dstChain` lacks a
|
|
18368
|
+
* GenericExecutor or DepositForHandler, or the `deposit.dappId` is unknown.
|
|
18369
|
+
*
|
|
18370
|
+
* @example
|
|
18371
|
+
* ```typescript
|
|
18372
|
+
* import { CCTPV2BridgingProvider } from '@circle-fin/provider-cctp-v2'
|
|
18373
|
+
* import { Ethereum, ArcTestnet } from '@core/chains'
|
|
18374
|
+
*
|
|
18375
|
+
* const prepared = await CCTPV2BridgingProvider.prepareDepositForBurn({
|
|
18376
|
+
* adapter,
|
|
18377
|
+
* srcChain: Ethereum,
|
|
18378
|
+
* dstChain: ArcTestnet,
|
|
18379
|
+
* deposit: { dappId: 'gateway_deposit', params: [usdcAddress, recipient, 0n] },
|
|
18380
|
+
* amountMinorUnits: 100_000_000n,
|
|
18381
|
+
* refundAddress: '0xSender...',
|
|
18382
|
+
* signedQuote: quote.signedQuote,
|
|
18383
|
+
* feeToken: quote.feeToken,
|
|
18384
|
+
* feeTotalAmount: BigInt(quote.feeTotalAmount),
|
|
18385
|
+
* resolvedContext,
|
|
18386
|
+
* })
|
|
18387
|
+
* const txHash = await prepared.execute()
|
|
18388
|
+
* ```
|
|
18389
|
+
*/ static async prepareDepositForBurn(params) {
|
|
18390
|
+
const { adapter, srcChain, dstChain, deposit, amountMinorUnits, refundAddress, signedQuote, feeToken, feeTotalAmount, resolvedContext } = params;
|
|
18391
|
+
// Resolve executor and depositForHandler from the destination chain's
|
|
18392
|
+
// gateway config. Throw an unsupported-route error if either is absent.
|
|
18393
|
+
const executor = dstChain.gateway?.contracts?.v1?.genericExecutor;
|
|
18394
|
+
const depositForHandler = dstChain.gateway?.contracts?.v1?.depositForHandler;
|
|
18395
|
+
if (!executor || !depositForHandler) {
|
|
18396
|
+
throw createUnsupportedRouteError(srcChain.name, dstChain.name);
|
|
18397
|
+
}
|
|
18398
|
+
// Resolve the canonical dApp config (function signature + amount indices)
|
|
18399
|
+
// for THIS deposit's `dappId`. Reject an unknown `dappId` rather than
|
|
18400
|
+
// encoding the wrong ABI selector, which would burn on the source but
|
|
18401
|
+
// revert in the executor call on the destination.
|
|
18402
|
+
const dappConfig = DAPP_CONFIG[deposit.dappId];
|
|
18403
|
+
if (dappConfig === undefined) {
|
|
18404
|
+
throw createUnsupportedRouteError(srcChain.name, dstChain.name);
|
|
18405
|
+
}
|
|
18406
|
+
// Build the bare GenericExecutor payload, then wrap it in the `cctp-forward`
|
|
18407
|
+
// frame required by the prepaid-FORWARD wrapper.
|
|
18408
|
+
const { hookData: geBlob } = buildDepositForGenericExecutorPayload({
|
|
18409
|
+
dappId: deposit.dappId,
|
|
18410
|
+
destinationChain: dstChain,
|
|
18411
|
+
handler: depositForHandler,
|
|
18412
|
+
params: deposit.params,
|
|
18413
|
+
recoveryAddress: padAddressToBytes32(refundAddress),
|
|
18414
|
+
config: {
|
|
18415
|
+
[deposit.dappId]: {
|
|
18416
|
+
...dappConfig,
|
|
18417
|
+
deployments: [
|
|
18418
|
+
{
|
|
18419
|
+
domainId: dstChain.cctp.domain
|
|
18420
|
+
}
|
|
18421
|
+
]
|
|
18422
|
+
}
|
|
18423
|
+
}
|
|
18424
|
+
});
|
|
18425
|
+
const hookData = buildForwardingHookDataWithPayload(GENERIC_EXECUTOR_HOOK_DATA_VERSION, geBlob);
|
|
18426
|
+
// Coupling guard: the prepaid FORWARD path always requests a FORWARD fee
|
|
18427
|
+
// item, so the hookData must carry a `cctp-forward` frame; otherwise the
|
|
18428
|
+
// wrapper reverts `ForwardFeeWithoutHook`.
|
|
18429
|
+
assertForwardHookData(hookData);
|
|
18430
|
+
// Source-chain burn: `mintRecipient` AND `destinationCaller` are both the
|
|
18431
|
+
// executor; fees are prepaid against the signed quote.
|
|
18432
|
+
return adapter.prepareAction('cctp.v2.depositForBurnWithFees', {
|
|
18433
|
+
fromChain: srcChain,
|
|
18434
|
+
toChain: dstChain,
|
|
18435
|
+
amount: amountMinorUnits,
|
|
18436
|
+
mintRecipient: executor,
|
|
18437
|
+
destinationCaller: executor,
|
|
18438
|
+
hookData,
|
|
18439
|
+
claim: {
|
|
18440
|
+
signedQuote,
|
|
18441
|
+
refundAddress
|
|
18442
|
+
},
|
|
18443
|
+
feeToken,
|
|
18444
|
+
feeTotalAmount
|
|
18445
|
+
}, resolvedContext);
|
|
18446
|
+
}
|
|
18447
|
+
/**
|
|
17645
18448
|
* Prepare a prepaid-FORWARD burn through the `TokenMessengerWithFees` wrapper.
|
|
17646
18449
|
*
|
|
17647
18450
|
* Build the source-chain `depositForBurnWithHookAndFees` call. Fees are
|
|
@@ -17906,9 +18709,13 @@ function assertCCTPV2Config(config) {
|
|
|
17906
18709
|
|
|
17907
18710
|
/**
|
|
17908
18711
|
* Base URL for Circle's Quote API (hosted in Iris) on mainnet/production.
|
|
18712
|
+
*
|
|
18713
|
+
* @internal
|
|
17909
18714
|
*/ const IRIS_API_BASE_URL = 'https://iris-api.circle.com';
|
|
17910
18715
|
/**
|
|
17911
18716
|
* Base URL for Circle's Quote API (hosted in Iris) on testnet/sandbox.
|
|
18717
|
+
*
|
|
18718
|
+
* @internal
|
|
17912
18719
|
*/ const IRIS_API_SANDBOX_BASE_URL = 'https://iris-api-sandbox.circle.com';
|
|
17913
18720
|
/**
|
|
17914
18721
|
* Native fee-token sentinel (the zero address).
|
|
@@ -17916,19 +18723,25 @@ function assertCCTPV2Config(config) {
|
|
|
17916
18723
|
* When `feeToken` is the zero address the quote prices fees in the source
|
|
17917
18724
|
* chain's native gas token (paid as `msg.value` on-chain). Pass a USDC token
|
|
17918
18725
|
* address instead to denominate fees in USDC.
|
|
18726
|
+
*
|
|
18727
|
+
* @internal
|
|
17919
18728
|
*/ const NATIVE_FEE_TOKEN = '0x0000000000000000000000000000000000000000';
|
|
17920
18729
|
/**
|
|
17921
18730
|
* API path prefix for the CCTP v2 USDC burn quote endpoint.
|
|
17922
18731
|
*
|
|
17923
18732
|
* The full path is `${QUOTE_BURN_USDC_PATH}/{sourceDomain}/{destinationDomain}`;
|
|
17924
18733
|
* `usdc` is a fixed literal, not a token parameter.
|
|
18734
|
+
*
|
|
18735
|
+
* @internal
|
|
17925
18736
|
*/ const QUOTE_BURN_USDC_PATH = '/v2/quote/burn/usdc';
|
|
17926
18737
|
/**
|
|
17927
18738
|
* API path prefix for the CCTP v2 USDC quote validate endpoint.
|
|
17928
18739
|
*
|
|
17929
18740
|
* The full path is `${QUOTE_VALIDATE_USDC_PATH}/{sourceDomain}`; accepts a
|
|
17930
|
-
* `POST { abiSignature, args }` body and returns
|
|
17931
|
-
*
|
|
18741
|
+
* `POST { abiSignature, args }` body and returns `claimable`, `failedChecks`,
|
|
18742
|
+
* and the decoded `expiry`, `feeToken`, and `feeTotalAmount`.
|
|
18743
|
+
*
|
|
18744
|
+
* @internal
|
|
17932
18745
|
*/ const QUOTE_VALIDATE_USDC_PATH = '/v2/quote/validate/usdc';
|
|
17933
18746
|
/**
|
|
17934
18747
|
* Default polling configuration for Quote API calls.
|
|
@@ -17945,13 +18758,19 @@ function assertCCTPV2Config(config) {
|
|
|
17945
18758
|
* `Content-Type: application/json` and adds `User-Agent` in Node. Browser
|
|
17946
18759
|
* requests omit a user-agent header to avoid a CORS preflight, so duplicating
|
|
17947
18760
|
* either header here would be dead configuration.
|
|
18761
|
+
*
|
|
18762
|
+
* @internal
|
|
17948
18763
|
*/ const FEE_QUOTE_DEFAULT_CONFIG = {
|
|
17949
18764
|
timeout: 15_000,
|
|
17950
18765
|
maxRetries: 1,
|
|
17951
18766
|
retryDelay: 200
|
|
17952
18767
|
};
|
|
17953
18768
|
|
|
17954
|
-
/**
|
|
18769
|
+
/**
|
|
18770
|
+
* Decimal string in token minor units, constrained to be strictly positive.
|
|
18771
|
+
*
|
|
18772
|
+
* @internal
|
|
18773
|
+
*/ const positiveAmountSchema = z.string().regex(/^\d+$/, 'must be a non-negative integer string')// Re-check the digit shape here: zod still runs this refinement when the
|
|
17955
18774
|
// regex check above fails ("dirty"), so guard BigInt() against throwing on a
|
|
17956
18775
|
// non-numeric value before comparing.
|
|
17957
18776
|
.refine((value)=>/^\d+$/.test(value) && BigInt(value) > 0n, 'must be greater than zero');
|
|
@@ -17986,11 +18805,19 @@ const forwardRequestSchema = z.object({
|
|
|
17986
18805
|
const preFinalityRequestSchema = z.object({
|
|
17987
18806
|
type: z.literal('PRE_FINALITY')
|
|
17988
18807
|
}).strict();
|
|
17989
|
-
/**
|
|
18808
|
+
/**
|
|
18809
|
+
* A single quote request item (`FORWARD` or `PRE_FINALITY`).
|
|
18810
|
+
*
|
|
18811
|
+
* @internal
|
|
18812
|
+
*/ const feeQuoteRequestSchema = z.discriminatedUnion('type', [
|
|
17990
18813
|
forwardRequestSchema,
|
|
17991
18814
|
preFinalityRequestSchema
|
|
17992
18815
|
]);
|
|
17993
|
-
/**
|
|
18816
|
+
/**
|
|
18817
|
+
* A non-empty list of quote request items with unique types.
|
|
18818
|
+
*
|
|
18819
|
+
* @internal
|
|
18820
|
+
*/ const feeQuoteRequestsSchema = z.array(feeQuoteRequestSchema).min(1, 'at least one request item is required').refine((items)=>new Set(items.map((item)=>item.type)).size === items.length, 'request item types must be unique');
|
|
17994
18821
|
/**
|
|
17995
18822
|
* A structured `Partial<ApiPollingConfig>` polling override.
|
|
17996
18823
|
*
|
|
@@ -18018,6 +18845,8 @@ const preFinalityRequestSchema = z.object({
|
|
|
18018
18845
|
* it `undefined`, which is falsy and silently selects the production base URL.
|
|
18019
18846
|
* (`buildFeeQuoteUrl` independently re-validates the domains for standalone
|
|
18020
18847
|
* callers.)
|
|
18848
|
+
*
|
|
18849
|
+
* @internal
|
|
18021
18850
|
*/ const fetchFeeQuoteInputSchema = z.object({
|
|
18022
18851
|
sourceDomain: z.number().int().nonnegative(),
|
|
18023
18852
|
destinationDomain: z.number().int().nonnegative(),
|
|
@@ -18053,7 +18882,11 @@ const metadataSchema = z.object({
|
|
|
18053
18882
|
blockEstimatedAt: z.number().int().nonnegative().optional()
|
|
18054
18883
|
}).passthrough()
|
|
18055
18884
|
]);
|
|
18056
|
-
/**
|
|
18885
|
+
/**
|
|
18886
|
+
* Schema for a signed fee quote returned by the Quote API.
|
|
18887
|
+
*
|
|
18888
|
+
* @internal
|
|
18889
|
+
*/ const signedFeeQuoteSchema = z.object({
|
|
18057
18890
|
// The runtime YAML spec maps signedQuote to a looser `hex` (which allows
|
|
18058
18891
|
// an empty `0x`); we keep the stricter non-empty form. Do not relax
|
|
18059
18892
|
// without a reason.
|
|
@@ -18082,10 +18915,16 @@ const metadataSchema = z.object({
|
|
|
18082
18915
|
* console.log(payload.feeTotalAmount)
|
|
18083
18916
|
* }
|
|
18084
18917
|
* ```
|
|
18918
|
+
*
|
|
18919
|
+
* @internal
|
|
18085
18920
|
*/ function isSignedFeeQuote(value) {
|
|
18086
18921
|
return signedFeeQuoteSchema.safeParse(value).success;
|
|
18087
18922
|
}
|
|
18088
|
-
/**
|
|
18923
|
+
/**
|
|
18924
|
+
* Validates input to {@link validateQuote}.
|
|
18925
|
+
*
|
|
18926
|
+
* @internal
|
|
18927
|
+
*/ const validateQuoteInputSchema = z.object({
|
|
18089
18928
|
sourceDomain: z.number().int().nonnegative(),
|
|
18090
18929
|
abiSignature: z.string().min(1),
|
|
18091
18930
|
args: z.array(z.union([
|
|
@@ -18120,11 +18959,13 @@ const validateQuoteItemSchema = z.object({
|
|
|
18120
18959
|
computedArgsHash: bytes32Schema.optional()
|
|
18121
18960
|
}).passthrough();
|
|
18122
18961
|
/**
|
|
18123
|
-
* Schema for a
|
|
18962
|
+
* Schema for a validate-quote result returned by the Iris `/validate/usdc/:sourceDomain` endpoint.
|
|
18124
18963
|
*
|
|
18125
18964
|
* The endpoint takes the source domain as a URL path parameter and does not
|
|
18126
18965
|
* return it in the response body, so `sourceDomain` is intentionally not part
|
|
18127
18966
|
* of this schema.
|
|
18967
|
+
*
|
|
18968
|
+
* @internal
|
|
18128
18969
|
*/ const validateQuoteResultSchema = z.object({
|
|
18129
18970
|
signedQuote: nonEmptyHexSchema,
|
|
18130
18971
|
expiry: quoteExpiryStatusSchema,
|
|
@@ -18138,20 +18979,22 @@ const validateQuoteItemSchema = z.object({
|
|
|
18138
18979
|
items: z.array(validateQuoteItemSchema)
|
|
18139
18980
|
}).passthrough();
|
|
18140
18981
|
/**
|
|
18141
|
-
* Validate
|
|
18982
|
+
* Validate that an unknown value is a validate-quote result.
|
|
18142
18983
|
*
|
|
18143
|
-
* @param value - The unknown
|
|
18144
|
-
* @returns `true` when the value
|
|
18984
|
+
* @param value - The unknown value to validate.
|
|
18985
|
+
* @returns `true` when the value matches the validate-quote response shape.
|
|
18145
18986
|
*
|
|
18146
18987
|
* @example
|
|
18147
18988
|
* ```typescript
|
|
18148
18989
|
* import { isValidateQuoteResult } from '@circle-fin/provider-fee-v1'
|
|
18149
18990
|
*
|
|
18150
|
-
* declare const
|
|
18151
|
-
* if (isValidateQuoteResult(
|
|
18152
|
-
* console.log(
|
|
18991
|
+
* declare const payload: unknown
|
|
18992
|
+
* if (isValidateQuoteResult(payload)) {
|
|
18993
|
+
* console.log(payload.claimable, payload.failedChecks)
|
|
18153
18994
|
* }
|
|
18154
18995
|
* ```
|
|
18996
|
+
*
|
|
18997
|
+
* @internal
|
|
18155
18998
|
*/ function isValidateQuoteResult(value) {
|
|
18156
18999
|
return validateQuoteResultSchema.safeParse(value).success;
|
|
18157
19000
|
}
|
|
@@ -18200,6 +19043,8 @@ const validateQuoteItemSchema = z.object({
|
|
|
18200
19043
|
* })
|
|
18201
19044
|
* // => 'https://iris-api.circle.com/v2/quote/burn/usdc/3/26'
|
|
18202
19045
|
* ```
|
|
19046
|
+
*
|
|
19047
|
+
* @internal
|
|
18203
19048
|
*/ function buildFeeQuoteUrl(params) {
|
|
18204
19049
|
const { sourceDomain, destinationDomain, isTestnet, baseUrl } = params;
|
|
18205
19050
|
assertDomain(sourceDomain, 'sourceDomain');
|
|
@@ -18326,6 +19171,8 @@ const OPERATION$1 = 'getFeeQuote';
|
|
|
18326
19171
|
* })
|
|
18327
19172
|
* console.log(quote.feeTotalAmount, quote.expiry)
|
|
18328
19173
|
* ```
|
|
19174
|
+
*
|
|
19175
|
+
* @internal
|
|
18329
19176
|
*/ async function fetchFeeQuote(params) {
|
|
18330
19177
|
const { sourceDomain, destinationDomain, amount, requests, feeToken, isTestnet, baseUrl, config } = params;
|
|
18331
19178
|
const parsed = fetchFeeQuoteInputSchema.safeParse({
|
|
@@ -18400,7 +19247,13 @@ const OPERATION$1 = 'getFeeQuote';
|
|
|
18400
19247
|
const SERVICE = 'Quote API';
|
|
18401
19248
|
const OPERATION = 'validateQuote';
|
|
18402
19249
|
/**
|
|
18403
|
-
* Validate a signed quote against a
|
|
19250
|
+
* Validate a signed fee quote against a full on-chain call via Circle's Iris
|
|
19251
|
+
* `/v2/quote/validate/usdc/:sourceDomain` endpoint.
|
|
19252
|
+
*
|
|
19253
|
+
* POSTs the ABI function signature and the encoded call arguments to Iris,
|
|
19254
|
+
* which verifies the signature, checks expiry, confirms the argsHash committed
|
|
19255
|
+
* in the quote matches the submitted args, and returns `claimable` plus the
|
|
19256
|
+
* decoded `expiry`, `feeToken`, and `feeTotalAmount`.
|
|
18404
19257
|
*
|
|
18405
19258
|
* @param params - The source domain, ABI signature, call arguments, and environment.
|
|
18406
19259
|
* @returns The claimability, binding checks, and authoritative expiry status.
|
|
@@ -18427,7 +19280,12 @@ const OPERATION = 'validateQuote';
|
|
|
18427
19280
|
* isTestnet: false,
|
|
18428
19281
|
* })
|
|
18429
19282
|
* console.log(result.claimable, result.expiry.secondsRemaining)
|
|
19283
|
+
* if (!result.claimable) {
|
|
19284
|
+
* console.error('Quote rejected:', result.failedChecks)
|
|
19285
|
+
* }
|
|
18430
19286
|
* ```
|
|
19287
|
+
*
|
|
19288
|
+
* @internal
|
|
18431
19289
|
*/ async function validateQuote(params) {
|
|
18432
19290
|
const parsed = validateQuoteInputSchema.safeParse(params);
|
|
18433
19291
|
if (!parsed.success) {
|
|
@@ -18490,9 +19348,14 @@ function isQuoteNearEstimatedExpiry(quote) {
|
|
|
18490
19348
|
}
|
|
18491
19349
|
function assertSourceFeeRoute(params) {
|
|
18492
19350
|
const { source, destination, config } = params;
|
|
19351
|
+
// Keep these checks explicit so a successful assertion guarantees the CCTP
|
|
19352
|
+
// v2 narrowing; hasSourceFeeSupport returns a plain boolean.
|
|
18493
19353
|
if (source.chain.type !== 'evm' || destination.chain.type !== 'evm' || !isCCTPV2Supported(source.chain) || !isCCTPV2Supported(destination.chain)) {
|
|
18494
19354
|
throw createUnsupportedRouteError(source.chain.name, destination.chain.name);
|
|
18495
19355
|
}
|
|
19356
|
+
if (!hasSourceFeeSupport(source.chain)) {
|
|
19357
|
+
throw createValidationFailedError$1('config.feePayment', 'source', `Source-paid ("receive-exact") fees are not supported from ${source.chain.name}. ` + 'Use the default destination-paid fees for this source chain');
|
|
19358
|
+
}
|
|
18496
19359
|
const useForwarder = destination.useForwarder;
|
|
18497
19360
|
if (useForwarder !== true) {
|
|
18498
19361
|
throw createValidationFailedError$1('to.useForwarder', useForwarder, "feePayment: 'source' requires useForwarder: true");
|
|
@@ -19580,7 +20443,7 @@ registerKit(`${pkg$3.name}/${pkg$3.version}`);
|
|
|
19580
20443
|
};
|
|
19581
20444
|
|
|
19582
20445
|
var name$1 = "@circle-fin/swap-kit";
|
|
19583
|
-
var version$1 = "1.6.
|
|
20446
|
+
var version$1 = "1.6.1";
|
|
19584
20447
|
var pkg$1 = {
|
|
19585
20448
|
name: name$1,
|
|
19586
20449
|
version: version$1};
|
|
@@ -21602,7 +22465,7 @@ new Set(Object.values(Blockchain));
|
|
|
21602
22465
|
registerKit(`${pkg$1.name}/${pkg$1.version}`);
|
|
21603
22466
|
|
|
21604
22467
|
var name = "@circle-fin/earn-kit";
|
|
21605
|
-
var version = "1.6.
|
|
22468
|
+
var version = "1.6.1";
|
|
21606
22469
|
var pkg = {
|
|
21607
22470
|
name: name,
|
|
21608
22471
|
version: version};
|