@chainlink/ccip-sdk 0.96.0 → 1.0.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/README.md +12 -9
- package/dist/api/index.d.ts +21 -8
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +42 -13
- package/dist/api/index.js.map +1 -1
- package/dist/api/types.d.ts +0 -2
- package/dist/api/types.d.ts.map +1 -1
- package/dist/aptos/exec.d.ts +2 -2
- package/dist/aptos/exec.d.ts.map +1 -1
- package/dist/aptos/exec.js.map +1 -1
- package/dist/aptos/hasher.d.ts.map +1 -1
- package/dist/aptos/hasher.js +1 -1
- package/dist/aptos/hasher.js.map +1 -1
- package/dist/aptos/index.d.ts +17 -16
- package/dist/aptos/index.d.ts.map +1 -1
- package/dist/aptos/index.js +42 -73
- package/dist/aptos/index.js.map +1 -1
- package/dist/aptos/logs.d.ts +2 -2
- package/dist/aptos/logs.d.ts.map +1 -1
- package/dist/aptos/types.d.ts +2 -19
- package/dist/aptos/types.d.ts.map +1 -1
- package/dist/aptos/types.js +0 -11
- package/dist/aptos/types.js.map +1 -1
- package/dist/chain.d.ts +538 -158
- package/dist/chain.d.ts.map +1 -1
- package/dist/chain.js +132 -19
- package/dist/chain.js.map +1 -1
- package/dist/commits.d.ts +4 -6
- package/dist/commits.d.ts.map +1 -1
- package/dist/commits.js +4 -4
- package/dist/commits.js.map +1 -1
- package/dist/errors/CCIPError.d.ts +33 -4
- package/dist/errors/CCIPError.d.ts.map +1 -1
- package/dist/errors/CCIPError.js +33 -4
- package/dist/errors/CCIPError.js.map +1 -1
- package/dist/errors/codes.d.ts +3 -0
- package/dist/errors/codes.d.ts.map +1 -1
- package/dist/errors/codes.js +3 -1
- package/dist/errors/codes.js.map +1 -1
- package/dist/errors/index.d.ts +4 -4
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +4 -4
- package/dist/errors/index.js.map +1 -1
- package/dist/errors/recovery.d.ts.map +1 -1
- package/dist/errors/recovery.js +4 -1
- package/dist/errors/recovery.js.map +1 -1
- package/dist/errors/specialized.d.ts +1695 -120
- package/dist/errors/specialized.d.ts.map +1 -1
- package/dist/errors/specialized.js +1715 -123
- package/dist/errors/specialized.js.map +1 -1
- package/dist/errors/utils.d.ts.map +1 -1
- package/dist/errors/utils.js +0 -1
- package/dist/errors/utils.js.map +1 -1
- package/dist/evm/abi/OffRamp_2_0.d.ts +764 -0
- package/dist/evm/abi/OffRamp_2_0.d.ts.map +1 -0
- package/dist/evm/abi/OffRamp_2_0.js +744 -0
- package/dist/evm/abi/OffRamp_2_0.js.map +1 -0
- package/dist/evm/abi/OnRamp_2_0.d.ts +925 -0
- package/dist/evm/abi/OnRamp_2_0.d.ts.map +1 -0
- package/dist/evm/abi/OnRamp_2_0.js +992 -0
- package/dist/evm/abi/OnRamp_2_0.js.map +1 -0
- package/dist/evm/const.d.ts +12 -2
- package/dist/evm/const.d.ts.map +1 -1
- package/dist/evm/const.js +8 -2
- package/dist/evm/const.js.map +1 -1
- package/dist/evm/errors.d.ts.map +1 -1
- package/dist/evm/errors.js +7 -2
- package/dist/evm/errors.js.map +1 -1
- package/dist/evm/extra-args.d.ts.map +1 -1
- package/dist/evm/extra-args.js +5 -24
- package/dist/evm/extra-args.js.map +1 -1
- package/dist/evm/hasher.d.ts.map +1 -1
- package/dist/evm/hasher.js +23 -13
- package/dist/evm/hasher.js.map +1 -1
- package/dist/evm/index.d.ts +73 -16
- package/dist/evm/index.d.ts.map +1 -1
- package/dist/evm/index.js +241 -146
- package/dist/evm/index.js.map +1 -1
- package/dist/evm/logs.d.ts +1 -1
- package/dist/evm/logs.js +1 -1
- package/dist/evm/messages.d.ts +59 -5
- package/dist/evm/messages.d.ts.map +1 -1
- package/dist/evm/messages.js +210 -0
- package/dist/evm/messages.js.map +1 -1
- package/dist/evm/offchain.d.ts +1 -14
- package/dist/evm/offchain.d.ts.map +1 -1
- package/dist/evm/offchain.js +1 -133
- package/dist/evm/offchain.js.map +1 -1
- package/dist/evm/types.d.ts +7 -2
- package/dist/evm/types.d.ts.map +1 -1
- package/dist/evm/types.js +22 -1
- package/dist/evm/types.js.map +1 -1
- package/dist/execution.d.ts +62 -22
- package/dist/execution.d.ts.map +1 -1
- package/dist/execution.js +98 -61
- package/dist/execution.js.map +1 -1
- package/dist/extra-args.d.ts +13 -3
- package/dist/extra-args.d.ts.map +1 -1
- package/dist/extra-args.js +13 -3
- package/dist/extra-args.js.map +1 -1
- package/dist/gas.d.ts +25 -2
- package/dist/gas.d.ts.map +1 -1
- package/dist/gas.js +30 -4
- package/dist/gas.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/offchain.d.ts +23 -6
- package/dist/offchain.d.ts.map +1 -1
- package/dist/offchain.js +92 -17
- package/dist/offchain.js.map +1 -1
- package/dist/requests.d.ts +85 -14
- package/dist/requests.d.ts.map +1 -1
- package/dist/requests.js +99 -17
- package/dist/requests.js.map +1 -1
- package/dist/selectors.d.ts.map +1 -1
- package/dist/selectors.js +12 -0
- package/dist/selectors.js.map +1 -1
- package/dist/shared/bcs-codecs.d.ts +61 -0
- package/dist/shared/bcs-codecs.d.ts.map +1 -0
- package/dist/shared/bcs-codecs.js +102 -0
- package/dist/shared/bcs-codecs.js.map +1 -0
- package/dist/shared/constants.d.ts +3 -0
- package/dist/shared/constants.d.ts.map +1 -0
- package/dist/shared/constants.js +3 -0
- package/dist/shared/constants.js.map +1 -0
- package/dist/solana/exec.d.ts +2 -2
- package/dist/solana/exec.d.ts.map +1 -1
- package/dist/solana/exec.js.map +1 -1
- package/dist/solana/idl/1.6.0/BASE_TOKEN_POOL.d.ts +1 -1
- package/dist/solana/idl/1.6.0/BASE_TOKEN_POOL.js +1 -1
- package/dist/solana/idl/1.6.0/BURN_MINT_TOKEN_POOL.d.ts +1 -1
- package/dist/solana/idl/1.6.0/BURN_MINT_TOKEN_POOL.js +1 -1
- package/dist/solana/idl/1.6.0/CCIP_CCTP_TOKEN_POOL.d.ts +1 -1
- package/dist/solana/idl/1.6.0/CCIP_CCTP_TOKEN_POOL.js +1 -1
- package/dist/solana/idl/1.6.0/CCIP_COMMON.d.ts +16 -1
- package/dist/solana/idl/1.6.0/CCIP_COMMON.d.ts.map +1 -1
- package/dist/solana/idl/1.6.0/CCIP_COMMON.js +16 -1
- package/dist/solana/idl/1.6.0/CCIP_COMMON.js.map +1 -1
- package/dist/solana/idl/1.6.0/CCIP_OFFRAMP.d.ts +1 -1
- package/dist/solana/idl/1.6.0/CCIP_OFFRAMP.js +1 -1
- package/dist/solana/idl/1.6.0/CCIP_ROUTER.d.ts +1 -1
- package/dist/solana/idl/1.6.0/CCIP_ROUTER.js +1 -1
- package/dist/solana/index.d.ts +85 -24
- package/dist/solana/index.d.ts.map +1 -1
- package/dist/solana/index.js +69 -37
- package/dist/solana/index.js.map +1 -1
- package/dist/solana/offchain.d.ts +1 -13
- package/dist/solana/offchain.d.ts.map +1 -1
- package/dist/solana/offchain.js +1 -66
- package/dist/solana/offchain.js.map +1 -1
- package/dist/solana/utils.d.ts +4 -4
- package/dist/solana/utils.d.ts.map +1 -1
- package/dist/solana/utils.js +1 -1
- package/dist/solana/utils.js.map +1 -1
- package/dist/sui/hasher.d.ts.map +1 -1
- package/dist/sui/hasher.js +1 -1
- package/dist/sui/hasher.js.map +1 -1
- package/dist/sui/index.d.ts +18 -18
- package/dist/sui/index.d.ts.map +1 -1
- package/dist/sui/index.js +38 -39
- package/dist/sui/index.js.map +1 -1
- package/dist/sui/manuallyExec/encoder.d.ts +2 -2
- package/dist/sui/manuallyExec/encoder.d.ts.map +1 -1
- package/dist/sui/manuallyExec/encoder.js.map +1 -1
- package/dist/sui/manuallyExec/index.d.ts +2 -2
- package/dist/sui/manuallyExec/index.d.ts.map +1 -1
- package/dist/ton/exec.d.ts +3 -3
- package/dist/ton/exec.d.ts.map +1 -1
- package/dist/ton/exec.js +1 -1
- package/dist/ton/exec.js.map +1 -1
- package/dist/ton/index.d.ts +14 -22
- package/dist/ton/index.d.ts.map +1 -1
- package/dist/ton/index.js +26 -35
- package/dist/ton/index.js.map +1 -1
- package/dist/ton/types.d.ts +3 -5
- package/dist/ton/types.d.ts.map +1 -1
- package/dist/ton/types.js.map +1 -1
- package/dist/types.d.ts +55 -20
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +6 -1
- package/dist/types.js.map +1 -1
- package/dist/utils.d.ts +65 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +74 -2
- package/dist/utils.js.map +1 -1
- package/package.json +14 -10
- package/src/api/index.ts +53 -17
- package/src/api/types.ts +0 -2
- package/src/aptos/exec.ts +2 -2
- package/src/aptos/hasher.ts +1 -1
- package/src/aptos/index.ts +55 -100
- package/src/aptos/logs.ts +2 -2
- package/src/aptos/types.ts +2 -15
- package/src/chain.ts +594 -171
- package/src/commits.ts +9 -9
- package/src/errors/CCIPError.ts +33 -4
- package/src/errors/codes.ts +3 -1
- package/src/errors/index.ts +4 -0
- package/src/errors/recovery.ts +7 -1
- package/src/errors/specialized.ts +1726 -130
- package/src/errors/utils.ts +0 -1
- package/src/evm/abi/OffRamp_2_0.ts +743 -0
- package/src/evm/abi/OnRamp_2_0.ts +991 -0
- package/src/evm/const.ts +10 -3
- package/src/evm/errors.ts +6 -2
- package/src/evm/extra-args.ts +4 -21
- package/src/evm/hasher.ts +30 -18
- package/src/evm/index.ts +314 -176
- package/src/evm/logs.ts +1 -1
- package/src/evm/messages.ts +323 -11
- package/src/evm/offchain.ts +2 -191
- package/src/evm/types.ts +20 -2
- package/src/execution.ts +125 -86
- package/src/extra-args.ts +13 -3
- package/src/gas.ts +29 -3
- package/src/index.ts +10 -3
- package/src/offchain.ts +125 -28
- package/src/requests.ts +114 -19
- package/src/selectors.ts +12 -0
- package/src/shared/bcs-codecs.ts +132 -0
- package/src/shared/constants.ts +2 -0
- package/src/solana/exec.ts +4 -4
- package/src/solana/idl/1.6.0/BASE_TOKEN_POOL.ts +2 -2
- package/src/solana/idl/1.6.0/BURN_MINT_TOKEN_POOL.ts +2 -2
- package/src/solana/idl/1.6.0/CCIP_CCTP_TOKEN_POOL.ts +2 -2
- package/src/solana/idl/1.6.0/CCIP_COMMON.ts +32 -2
- package/src/solana/idl/1.6.0/CCIP_OFFRAMP.ts +2 -2
- package/src/solana/idl/1.6.0/CCIP_ROUTER.ts +2 -2
- package/src/solana/index.ts +110 -85
- package/src/solana/offchain.ts +3 -100
- package/src/solana/utils.ts +8 -5
- package/src/sui/hasher.ts +1 -1
- package/src/sui/index.ts +55 -59
- package/src/sui/manuallyExec/encoder.ts +2 -2
- package/src/sui/manuallyExec/index.ts +2 -2
- package/src/ton/exec.ts +4 -7
- package/src/ton/index.ts +45 -53
- package/src/ton/types.ts +4 -7
- package/src/types.ts +81 -37
- package/src/utils.ts +73 -2
- package/dist/aptos/utils.d.ts +0 -12
- package/dist/aptos/utils.d.ts.map +0 -1
- package/dist/aptos/utils.js +0 -15
- package/dist/aptos/utils.js.map +0 -1
- package/src/aptos/utils.ts +0 -24
package/src/evm/index.ts
CHANGED
|
@@ -1,24 +1,23 @@
|
|
|
1
|
-
import { parseAbi } from 'abitype'
|
|
2
1
|
import {
|
|
3
2
|
type BytesLike,
|
|
4
3
|
type Interface,
|
|
5
4
|
type JsonRpcApiProvider,
|
|
6
5
|
type Log,
|
|
6
|
+
type Result,
|
|
7
7
|
type Signer,
|
|
8
8
|
type TransactionReceipt,
|
|
9
9
|
type TransactionRequest,
|
|
10
10
|
type TransactionResponse,
|
|
11
11
|
Contract,
|
|
12
12
|
JsonRpcProvider,
|
|
13
|
-
Result,
|
|
14
13
|
WebSocketProvider,
|
|
15
14
|
ZeroAddress,
|
|
16
15
|
getAddress,
|
|
17
16
|
hexlify,
|
|
18
17
|
isBytesLike,
|
|
19
18
|
isHexString,
|
|
19
|
+
keccak256,
|
|
20
20
|
toBeHex,
|
|
21
|
-
toBigInt,
|
|
22
21
|
zeroPadValue,
|
|
23
22
|
} from 'ethers'
|
|
24
23
|
import type { TypedContract } from 'ethers-abitype'
|
|
@@ -34,16 +33,16 @@ import {
|
|
|
34
33
|
} from '../chain.ts'
|
|
35
34
|
import {
|
|
36
35
|
CCIPAddressInvalidEvmError,
|
|
36
|
+
CCIPApiClientNotAvailableError,
|
|
37
37
|
CCIPBlockNotFoundError,
|
|
38
38
|
CCIPContractNotRouterError,
|
|
39
39
|
CCIPContractTypeInvalidError,
|
|
40
40
|
CCIPDataFormatUnsupportedError,
|
|
41
41
|
CCIPExecTxNotConfirmedError,
|
|
42
42
|
CCIPExecTxRevertedError,
|
|
43
|
-
CCIPExtraArgsParseError,
|
|
44
43
|
CCIPHasherVersionUnsupportedError,
|
|
45
44
|
CCIPLogDataInvalidError,
|
|
46
|
-
|
|
45
|
+
CCIPNotImplementedError,
|
|
47
46
|
CCIPSourceChainUnsupportedError,
|
|
48
47
|
CCIPTokenNotConfiguredError,
|
|
49
48
|
CCIPTokenPoolChainConfigNotFoundError,
|
|
@@ -60,14 +59,15 @@ import {
|
|
|
60
59
|
type CCIPExecution,
|
|
61
60
|
type CCIPMessage,
|
|
62
61
|
type CCIPRequest,
|
|
62
|
+
type CCIPVerifications,
|
|
63
|
+
type ChainLog,
|
|
63
64
|
type ChainTransaction,
|
|
64
65
|
type CommitReport,
|
|
66
|
+
type ExecutionInput,
|
|
65
67
|
type ExecutionReceipt,
|
|
66
68
|
type ExecutionState,
|
|
67
69
|
type Lane,
|
|
68
|
-
type Log_,
|
|
69
70
|
type NetworkInfo,
|
|
70
|
-
type OffchainTokenData,
|
|
71
71
|
type WithLogger,
|
|
72
72
|
CCIPVersion,
|
|
73
73
|
ChainFamily,
|
|
@@ -88,12 +88,21 @@ import type TokenPool_ABI from './abi/LockReleaseTokenPool_1_6_1.ts'
|
|
|
88
88
|
import EVM2EVMOffRamp_1_2_ABI from './abi/OffRamp_1_2.ts'
|
|
89
89
|
import EVM2EVMOffRamp_1_5_ABI from './abi/OffRamp_1_5.ts'
|
|
90
90
|
import OffRamp_1_6_ABI from './abi/OffRamp_1_6.ts'
|
|
91
|
+
import OffRamp_2_0_ABI from './abi/OffRamp_2_0.ts'
|
|
91
92
|
import EVM2EVMOnRamp_1_2_ABI from './abi/OnRamp_1_2.ts'
|
|
92
93
|
import EVM2EVMOnRamp_1_5_ABI from './abi/OnRamp_1_5.ts'
|
|
93
|
-
import OnRamp_1_6_ABI from './abi/OnRamp_1_6.ts'
|
|
94
|
+
import type OnRamp_1_6_ABI from './abi/OnRamp_1_6.ts'
|
|
95
|
+
import type OnRamp_2_0_ABI from './abi/OnRamp_2_0.ts'
|
|
94
96
|
import type Router_ABI from './abi/Router.ts'
|
|
95
97
|
import type TokenAdminRegistry_1_5_ABI from './abi/TokenAdminRegistry_1_5.ts'
|
|
96
|
-
import {
|
|
98
|
+
import {
|
|
99
|
+
CCV_INDEXER_URL,
|
|
100
|
+
VersionedContractABI,
|
|
101
|
+
commitsFragments,
|
|
102
|
+
interfaces,
|
|
103
|
+
receiptsFragments,
|
|
104
|
+
requestsFragments,
|
|
105
|
+
} from './const.ts'
|
|
97
106
|
import { parseData } from './errors.ts'
|
|
98
107
|
import {
|
|
99
108
|
decodeExtraArgs as decodeExtraArgs_,
|
|
@@ -104,30 +113,19 @@ import { getV12LeafHasher, getV16LeafHasher } from './hasher.ts'
|
|
|
104
113
|
import { getEvmLogs } from './logs.ts'
|
|
105
114
|
import {
|
|
106
115
|
type CCIPMessage_V1_6_EVM,
|
|
116
|
+
type CCIPMessage_V2_0,
|
|
107
117
|
type CleanAddressable,
|
|
108
|
-
|
|
118
|
+
type MessageV1,
|
|
119
|
+
type TokenTransferV1,
|
|
120
|
+
decodeMessageV1,
|
|
109
121
|
} from './messages.ts'
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
import
|
|
122
|
+
export { decodeMessageV1 }
|
|
123
|
+
export type { MessageV1, TokenTransferV1 }
|
|
124
|
+
import { encodeEVMOffchainTokenData } from './offchain.ts'
|
|
125
|
+
import { buildMessageForDest, decodeMessage, getMessagesInBatch } from '../requests.ts'
|
|
126
|
+
import { type UnsignedEVMTx, resultToObject } from './types.ts'
|
|
113
127
|
export type { UnsignedEVMTx }
|
|
114
128
|
|
|
115
|
-
const VersionedContractABI = parseAbi(['function typeAndVersion() view returns (string)'])
|
|
116
|
-
|
|
117
|
-
function resultToObject<T>(o: T): T {
|
|
118
|
-
if (o instanceof Promise) return o.then(resultToObject) as T
|
|
119
|
-
if (!(o instanceof Result)) return o
|
|
120
|
-
if (o.length === 0) return o.toArray() as T
|
|
121
|
-
try {
|
|
122
|
-
const obj = o.toObject()
|
|
123
|
-
if (!Object.keys(obj).every((k) => /^_+\d*$/.test(k)))
|
|
124
|
-
return Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, resultToObject(v)])) as T
|
|
125
|
-
} catch (_) {
|
|
126
|
-
// fallthrough
|
|
127
|
-
}
|
|
128
|
-
return o.toArray().map(resultToObject) as T
|
|
129
|
-
}
|
|
130
|
-
|
|
131
129
|
/** typeguard for ethers Signer interface (used for `wallet`s) */
|
|
132
130
|
function isSigner(wallet: unknown): wallet is Signer {
|
|
133
131
|
return (
|
|
@@ -158,6 +156,26 @@ async function submitTransaction(
|
|
|
158
156
|
|
|
159
157
|
/**
|
|
160
158
|
* EVM chain implementation supporting Ethereum-compatible networks.
|
|
159
|
+
*
|
|
160
|
+
* Provides methods for sending CCIP cross-chain messages, querying message
|
|
161
|
+
* status, fetching fee quotes, and manually executing pending messages on
|
|
162
|
+
* Ethereum Virtual Machine compatible chains.
|
|
163
|
+
*
|
|
164
|
+
* @example Create from RPC URL
|
|
165
|
+
* ```typescript
|
|
166
|
+
* import { EVMChain } from '@chainlink/ccip-sdk'
|
|
167
|
+
*
|
|
168
|
+
* const chain = await EVMChain.fromUrl('https://rpc.sepolia.org')
|
|
169
|
+
* console.log(`Connected to: ${chain.network.name}`)
|
|
170
|
+
* ```
|
|
171
|
+
*
|
|
172
|
+
* @example Query messages in a transaction
|
|
173
|
+
* ```typescript
|
|
174
|
+
* const requests = await chain.getMessagesInTx('0xabc123...')
|
|
175
|
+
* for (const req of requests) {
|
|
176
|
+
* console.log(`Message ID: ${req.message.messageId}`)
|
|
177
|
+
* }
|
|
178
|
+
* ```
|
|
161
179
|
*/
|
|
162
180
|
export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
163
181
|
static {
|
|
@@ -168,6 +186,13 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
168
186
|
|
|
169
187
|
provider: JsonRpcApiProvider
|
|
170
188
|
readonly destroy$: Promise<void>
|
|
189
|
+
private noncesPromises: Record<string, Promise<unknown>>
|
|
190
|
+
/**
|
|
191
|
+
* Cache of current nonces per wallet address.
|
|
192
|
+
* Used internally by {@link sendMessage} and {@link execute} to manage transaction ordering.
|
|
193
|
+
* Can be inspected for debugging or manually adjusted if needed.
|
|
194
|
+
*/
|
|
195
|
+
nonces: Record<string, number>
|
|
171
196
|
|
|
172
197
|
/**
|
|
173
198
|
* Creates a new EVMChain instance.
|
|
@@ -177,6 +202,9 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
177
202
|
constructor(provider: JsonRpcApiProvider, network: NetworkInfo, ctx?: ChainContext) {
|
|
178
203
|
super(network, ctx)
|
|
179
204
|
|
|
205
|
+
this.noncesPromises = {}
|
|
206
|
+
this.nonces = {}
|
|
207
|
+
|
|
180
208
|
this.provider = provider
|
|
181
209
|
this.destroy$ = new Promise<void>((resolve) => (this.destroy = resolve))
|
|
182
210
|
void this.destroy$.finally(() => provider.destroy())
|
|
@@ -216,6 +244,22 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
216
244
|
return (await this.provider.listAccounts()).map(({ address }) => address)
|
|
217
245
|
}
|
|
218
246
|
|
|
247
|
+
/**
|
|
248
|
+
* Get the next nonce for a wallet address and increment the internal counter.
|
|
249
|
+
* Fetches from the network on first call, then uses cached value.
|
|
250
|
+
* @param address - Wallet address to get nonce for
|
|
251
|
+
* @returns The next available nonce
|
|
252
|
+
*/
|
|
253
|
+
async nextNonce(address: string): Promise<number> {
|
|
254
|
+
await (this.noncesPromises[address] ??= this.provider
|
|
255
|
+
.getTransactionCount(address)
|
|
256
|
+
.then((nonce) => {
|
|
257
|
+
this.nonces[address] = nonce
|
|
258
|
+
return nonce
|
|
259
|
+
}))
|
|
260
|
+
return this.nonces[address]!++
|
|
261
|
+
}
|
|
262
|
+
|
|
219
263
|
/**
|
|
220
264
|
* Creates a JSON-RPC provider from a URL.
|
|
221
265
|
* @param url - WebSocket (wss://) or HTTP (https://) endpoint URL.
|
|
@@ -260,9 +304,20 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
260
304
|
|
|
261
305
|
/**
|
|
262
306
|
* Creates an EVMChain instance from an RPC URL.
|
|
307
|
+
*
|
|
263
308
|
* @param url - WebSocket (wss://) or HTTP (https://) endpoint URL.
|
|
264
|
-
* @param ctx - context containing logger.
|
|
265
|
-
* @returns A new EVMChain instance.
|
|
309
|
+
* @param ctx - Optional context containing logger and API client configuration.
|
|
310
|
+
* @returns A new EVMChain instance connected to the specified network.
|
|
311
|
+
* @throws {@link CCIPChainNotFoundError} if chain cannot be identified from chainId
|
|
312
|
+
*
|
|
313
|
+
* @example
|
|
314
|
+
* ```typescript
|
|
315
|
+
* // HTTP connection
|
|
316
|
+
* const chain = await EVMChain.fromUrl('https://rpc.sepolia.org')
|
|
317
|
+
*
|
|
318
|
+
* // With custom logger
|
|
319
|
+
* const chain = await EVMChain.fromUrl(url, { logger: customLogger })
|
|
320
|
+
* ```
|
|
266
321
|
*/
|
|
267
322
|
static async fromUrl(url: string, ctx?: ChainContext): Promise<EVMChain> {
|
|
268
323
|
return this.fromProvider(await this._getProvider(url), ctx)
|
|
@@ -283,9 +338,9 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
283
338
|
const chainTx = {
|
|
284
339
|
...tx,
|
|
285
340
|
timestamp,
|
|
286
|
-
logs: [] as
|
|
341
|
+
logs: [] as ChainLog[],
|
|
287
342
|
}
|
|
288
|
-
const logs:
|
|
343
|
+
const logs: ChainLog[] = tx.logs.map((l) => Object.assign(l, { tx: chainTx }))
|
|
289
344
|
chainTx.logs = logs
|
|
290
345
|
return chainTx
|
|
291
346
|
}
|
|
@@ -298,15 +353,15 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
298
353
|
}
|
|
299
354
|
|
|
300
355
|
/** {@inheritDoc Chain.getMessagesInBatch} */
|
|
301
|
-
getMessagesInBatch<
|
|
356
|
+
override getMessagesInBatch<
|
|
302
357
|
R extends PickDeep<
|
|
303
358
|
CCIPRequest,
|
|
304
359
|
'lane' | `log.${'topics' | 'address' | 'blockNumber'}` | 'message.sequenceNumber'
|
|
305
360
|
>,
|
|
306
361
|
>(
|
|
307
362
|
request: R,
|
|
308
|
-
|
|
309
|
-
opts?:
|
|
363
|
+
range: Pick<CommitReport, 'minSeqNr' | 'maxSeqNr'>,
|
|
364
|
+
opts?: Pick<LogFilter, 'page'>,
|
|
310
365
|
): Promise<R['message'][]> {
|
|
311
366
|
let opts_: Parameters<EVMChain['getLogs']>[0] | undefined
|
|
312
367
|
if (request.lane.version >= CCIPVersion.V1_6) {
|
|
@@ -316,7 +371,7 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
316
371
|
topics: [[request.log.topics[0]!], [toBeHex(request.lane.destChainSelector, 32)]],
|
|
317
372
|
}
|
|
318
373
|
}
|
|
319
|
-
return getMessagesInBatch(this, request,
|
|
374
|
+
return getMessagesInBatch(this, request, range, opts_)
|
|
320
375
|
}
|
|
321
376
|
|
|
322
377
|
/** {@inheritDoc Chain.typeAndVersion} */
|
|
@@ -326,7 +381,9 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
326
381
|
VersionedContractABI,
|
|
327
382
|
this.provider,
|
|
328
383
|
) as unknown as TypedContract<typeof VersionedContractABI>
|
|
329
|
-
|
|
384
|
+
const res = parseTypeAndVersion(await contract.typeAndVersion())
|
|
385
|
+
if (res[1].startsWith('1.7.')) res[1] = CCIPVersion.V2_0
|
|
386
|
+
return res
|
|
330
387
|
}
|
|
331
388
|
|
|
332
389
|
/**
|
|
@@ -356,79 +413,16 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
356
413
|
const result = interfaces.OnRamp_v1_6.decodeEventLog(fragment, log.data, log.topics)
|
|
357
414
|
message = resultToObject(result) as Record<string, unknown>
|
|
358
415
|
if (message.message) message = message.message as Record<string, unknown> | undefined
|
|
416
|
+
else if (message.encodedMessage) {
|
|
417
|
+
Object.assign(message, decodeMessageV1(message.encodedMessage as BytesLike))
|
|
418
|
+
}
|
|
359
419
|
if (message) break
|
|
360
420
|
} catch (_) {
|
|
361
421
|
// try next fragment
|
|
362
422
|
}
|
|
363
423
|
}
|
|
364
424
|
if (!message) return
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
if (message.header) {
|
|
368
|
-
// CCIPMessage_V1_6
|
|
369
|
-
Object.assign(message, message.header)
|
|
370
|
-
delete message.header
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
const sourceFamily = networkInfo(
|
|
374
|
-
(message as { sourceChainSelector: bigint }).sourceChainSelector,
|
|
375
|
-
).family
|
|
376
|
-
let destFamily: ChainFamily = ChainFamily.EVM
|
|
377
|
-
if ((message as { destChainSelector?: bigint }).destChainSelector) {
|
|
378
|
-
destFamily = networkInfo((message as { destChainSelector: bigint }).destChainSelector).family
|
|
379
|
-
}
|
|
380
|
-
// conversions to make any message version be compatible with latest v1.6
|
|
381
|
-
message.tokenAmounts = (message.tokenAmounts as Record<string, string | bigint | number>[]).map(
|
|
382
|
-
(tokenAmount, i) => {
|
|
383
|
-
if ('sourceTokenData' in message) {
|
|
384
|
-
// CCIPMessage_V1_2_EVM
|
|
385
|
-
try {
|
|
386
|
-
tokenAmount = {
|
|
387
|
-
...parseSourceTokenData(
|
|
388
|
-
(message as { sourceTokenData: string[] }).sourceTokenData[i]!,
|
|
389
|
-
),
|
|
390
|
-
...tokenAmount,
|
|
391
|
-
}
|
|
392
|
-
} catch (_) {
|
|
393
|
-
// legacy sourceTokenData
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
if (typeof tokenAmount.destExecData === 'string' && tokenAmount.destGasAmount == null) {
|
|
397
|
-
// CCIPMessage_V1_6_EVM
|
|
398
|
-
tokenAmount.destGasAmount = toBigInt(getDataBytes(tokenAmount.destExecData))
|
|
399
|
-
}
|
|
400
|
-
// Can be undefined if the message is from before v1.5 and failed to parse sourceTokenData
|
|
401
|
-
if (tokenAmount.sourcePoolAddress) {
|
|
402
|
-
tokenAmount.sourcePoolAddress = decodeAddress(
|
|
403
|
-
tokenAmount.sourcePoolAddress as string,
|
|
404
|
-
sourceFamily,
|
|
405
|
-
)
|
|
406
|
-
}
|
|
407
|
-
if (tokenAmount.destTokenAddress) {
|
|
408
|
-
tokenAmount.destTokenAddress = decodeAddress(
|
|
409
|
-
tokenAmount.destTokenAddress as string,
|
|
410
|
-
destFamily,
|
|
411
|
-
)
|
|
412
|
-
}
|
|
413
|
-
return tokenAmount
|
|
414
|
-
},
|
|
415
|
-
)
|
|
416
|
-
message.sender = decodeAddress(message.sender, sourceFamily)
|
|
417
|
-
message.feeToken = decodeAddress(message.feeToken as string, sourceFamily)
|
|
418
|
-
message.receiver = decodeAddress(message.receiver as string, destFamily)
|
|
419
|
-
if (message.extraArgs) {
|
|
420
|
-
// v1.6+
|
|
421
|
-
const parsed = this.decodeExtraArgs(message.extraArgs as string)
|
|
422
|
-
if (!parsed) throw new CCIPExtraArgsParseError(message.extraArgs as string)
|
|
423
|
-
const { _tag, ...rest } = parsed
|
|
424
|
-
// merge parsed extraArgs to any family in message root object
|
|
425
|
-
Object.assign(message, rest)
|
|
426
|
-
} else if (message.nonce === 0n) {
|
|
427
|
-
// v1.2..v1.5 targets EVM only; extraArgs is not explicit, gasLimit is already in
|
|
428
|
-
// message body, allowOutOfOrderExecution (in v1.5) was present only as nonce=0
|
|
429
|
-
message.allowOutOfOrderExecution = true
|
|
430
|
-
}
|
|
431
|
-
return message as CCIPMessage
|
|
425
|
+
return decodeMessage(message)
|
|
432
426
|
}
|
|
433
427
|
|
|
434
428
|
/**
|
|
@@ -609,13 +603,23 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
609
603
|
return router as string
|
|
610
604
|
}
|
|
611
605
|
case CCIPVersion.V1_6: {
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
606
|
+
const contract = new Contract(
|
|
607
|
+
onRamp,
|
|
608
|
+
interfaces.OnRamp_v1_6,
|
|
609
|
+
this.provider,
|
|
610
|
+
) as unknown as TypedContract<typeof OnRamp_1_6_ABI>
|
|
616
611
|
const [, , router] = await contract.getDestChainConfig(destChainSelector)
|
|
617
612
|
return router as string
|
|
618
613
|
}
|
|
614
|
+
case CCIPVersion.V2_0: {
|
|
615
|
+
const contract = new Contract(
|
|
616
|
+
onRamp,
|
|
617
|
+
interfaces.OnRamp_v2_0,
|
|
618
|
+
this.provider,
|
|
619
|
+
) as unknown as TypedContract<typeof OnRamp_2_0_ABI>
|
|
620
|
+
const { router } = await contract.getDestChainConfig(destChainSelector)
|
|
621
|
+
return router as string
|
|
622
|
+
}
|
|
619
623
|
default:
|
|
620
624
|
throw new CCIPVersionUnsupportedError(version)
|
|
621
625
|
}
|
|
@@ -642,8 +646,11 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
642
646
|
;({ router } = await contract.getDynamicConfig())
|
|
643
647
|
break
|
|
644
648
|
}
|
|
645
|
-
case CCIPVersion.V1_6:
|
|
649
|
+
case CCIPVersion.V1_6:
|
|
646
650
|
offRampABI = OffRamp_1_6_ABI
|
|
651
|
+
// falls through
|
|
652
|
+
case CCIPVersion.V2_0: {
|
|
653
|
+
offRampABI = OffRamp_2_0_ABI
|
|
647
654
|
const contract = new Contract(
|
|
648
655
|
offRamp,
|
|
649
656
|
offRampABI,
|
|
@@ -692,10 +699,10 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
692
699
|
}
|
|
693
700
|
|
|
694
701
|
/**
|
|
695
|
-
* {@inheritDoc Chain.
|
|
702
|
+
* {@inheritDoc Chain.getOnRampsForOffRamp}
|
|
696
703
|
* @throws {@link CCIPVersionUnsupportedError} if OffRamp version is not supported
|
|
697
704
|
*/
|
|
698
|
-
async
|
|
705
|
+
async getOnRampsForOffRamp(offRamp: string, sourceChainSelector: bigint): Promise<string[]> {
|
|
699
706
|
const [, version] = await this.typeAndVersion(offRamp)
|
|
700
707
|
let offRampABI
|
|
701
708
|
switch (version) {
|
|
@@ -710,7 +717,7 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
710
717
|
this.provider,
|
|
711
718
|
) as unknown as TypedContract<typeof offRampABI>
|
|
712
719
|
const { onRamp } = await contract.getStaticConfig()
|
|
713
|
-
return onRamp as string
|
|
720
|
+
return [onRamp as string]
|
|
714
721
|
}
|
|
715
722
|
case CCIPVersion.V1_6: {
|
|
716
723
|
offRampABI = OffRamp_1_6_ABI
|
|
@@ -720,7 +727,19 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
720
727
|
this.provider,
|
|
721
728
|
) as unknown as TypedContract<typeof offRampABI>
|
|
722
729
|
const { onRamp } = await contract.getSourceChainConfig(sourceChainSelector)
|
|
723
|
-
|
|
730
|
+
if (!onRamp || onRamp.match(/^(0x)?0*$/i)) return []
|
|
731
|
+
return [decodeOnRampAddress(onRamp, networkInfo(sourceChainSelector).family)]
|
|
732
|
+
}
|
|
733
|
+
case CCIPVersion.V2_0: {
|
|
734
|
+
offRampABI = OffRamp_2_0_ABI
|
|
735
|
+
const contract = new Contract(
|
|
736
|
+
offRamp,
|
|
737
|
+
offRampABI,
|
|
738
|
+
this.provider,
|
|
739
|
+
) as unknown as TypedContract<typeof offRampABI>
|
|
740
|
+
const { onRamps } = await contract.getSourceChainConfig(sourceChainSelector)
|
|
741
|
+
const sourceFamily = networkInfo(sourceChainSelector).family
|
|
742
|
+
return onRamps.map((onRamp) => decodeOnRampAddress(onRamp, sourceFamily))
|
|
724
743
|
}
|
|
725
744
|
default:
|
|
726
745
|
throw new CCIPVersionUnsupportedError(version)
|
|
@@ -728,8 +747,19 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
728
747
|
}
|
|
729
748
|
|
|
730
749
|
/**
|
|
731
|
-
*
|
|
750
|
+
* Fetch the CommitStore set in OffRamp config (CCIP v1.5 and earlier).
|
|
751
|
+
* For CCIP v1.6 and later, it should return the offRamp address.
|
|
752
|
+
*
|
|
753
|
+
* @param offRamp - OffRamp contract address
|
|
754
|
+
* @returns Promise resolving to CommitStore address
|
|
755
|
+
*
|
|
756
|
+
* @example Get commit store
|
|
757
|
+
* ```typescript
|
|
758
|
+
* const commitStore = await dest.getCommitStoreForOffRamp(offRampAddress)
|
|
759
|
+
* // For v1.6+, commitStore === offRampAddress
|
|
760
|
+
* ```
|
|
732
761
|
* @throws {@link CCIPVersionUnsupportedError} if OffRamp version is not supported
|
|
762
|
+
* @internal
|
|
733
763
|
*/
|
|
734
764
|
async getCommitStoreForOffRamp(offRamp: string): Promise<string> {
|
|
735
765
|
const [, version] = await this.typeAndVersion(offRamp)
|
|
@@ -748,11 +778,8 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
748
778
|
const { commitStore } = await contract.getStaticConfig()
|
|
749
779
|
return commitStore as string
|
|
750
780
|
}
|
|
751
|
-
case CCIPVersion.V1_6: {
|
|
752
|
-
return offRamp
|
|
753
|
-
}
|
|
754
781
|
default:
|
|
755
|
-
|
|
782
|
+
return offRamp
|
|
756
783
|
}
|
|
757
784
|
}
|
|
758
785
|
|
|
@@ -1012,62 +1039,104 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
1012
1039
|
let sendTx: TransactionRequest = txs.transactions[txs.transactions.length - 1]!
|
|
1013
1040
|
|
|
1014
1041
|
// approve all tokens (including feeToken, if needed) in parallel
|
|
1015
|
-
let nonce = await this.provider.getTransactionCount(sender)
|
|
1016
1042
|
const responses = await Promise.all(
|
|
1017
1043
|
approveTxs.map(async (tx: TransactionRequest) => {
|
|
1018
|
-
tx.nonce =
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1044
|
+
tx.nonce = await this.nextNonce(sender)
|
|
1045
|
+
try {
|
|
1046
|
+
tx = await wallet.populateTransaction(tx)
|
|
1047
|
+
tx.from = undefined
|
|
1048
|
+
const response = await submitTransaction(wallet, tx, this.provider)
|
|
1049
|
+
this.logger.debug('approve =>', response.hash)
|
|
1050
|
+
return response
|
|
1051
|
+
} catch (err) {
|
|
1052
|
+
this.nonces[sender]!--
|
|
1053
|
+
throw err
|
|
1054
|
+
}
|
|
1024
1055
|
}),
|
|
1025
1056
|
)
|
|
1026
1057
|
if (responses.length) await responses[responses.length - 1]!.wait(1, 60_000) // wait last tx nonce to be mined
|
|
1027
1058
|
|
|
1028
|
-
sendTx.nonce =
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1059
|
+
sendTx.nonce = await this.nextNonce(sender)
|
|
1060
|
+
let response
|
|
1061
|
+
try {
|
|
1062
|
+
// sendTx.gasLimit = await this.provider.estimateGas(sendTx)
|
|
1063
|
+
sendTx = await wallet.populateTransaction(sendTx)
|
|
1064
|
+
sendTx.from = undefined // some signers don't like receiving pre-populated `from`
|
|
1065
|
+
response = await submitTransaction(wallet, sendTx, this.provider)
|
|
1066
|
+
} catch (err) {
|
|
1067
|
+
this.nonces[sender]!--
|
|
1068
|
+
throw err
|
|
1069
|
+
}
|
|
1033
1070
|
this.logger.debug('ccipSend =>', response.hash)
|
|
1034
|
-
await response.wait(1, 60_000)
|
|
1035
|
-
return (await this.getMessagesInTx(await this.getTransaction(
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1038
|
-
/** {@inheritDoc Chain.getOffchainTokenData} */
|
|
1039
|
-
getOffchainTokenData(request: CCIPRequest): Promise<OffchainTokenData[]> {
|
|
1040
|
-
return fetchEVMOffchainTokenData(request, this)
|
|
1071
|
+
const tx = (await response.wait(1, 60_000))!
|
|
1072
|
+
return (await this.getMessagesInTx(await this.getTransaction(tx)))[0]!
|
|
1041
1073
|
}
|
|
1042
1074
|
|
|
1043
1075
|
/**
|
|
1044
|
-
* {@inheritDoc Chain.
|
|
1076
|
+
* {@inheritDoc Chain.generateUnsignedExecute}
|
|
1045
1077
|
* @returns array containing one unsigned `manuallyExecute` TransactionRequest object
|
|
1046
1078
|
* @throws {@link CCIPVersionUnsupportedError} if OffRamp version is not supported
|
|
1047
1079
|
*/
|
|
1048
|
-
async
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1080
|
+
async generateUnsignedExecute(
|
|
1081
|
+
opts: Parameters<Chain['generateUnsignedExecute']>[0],
|
|
1082
|
+
): Promise<UnsignedEVMTx> {
|
|
1083
|
+
let input: ExecutionInput, offRamp: string
|
|
1084
|
+
if (!('input' in opts)) {
|
|
1085
|
+
if (!this.apiClient) throw new CCIPApiClientNotAvailableError()
|
|
1086
|
+
;({ offRamp, ...input } = await this.apiClient.getExecutionInput(opts.messageId))
|
|
1087
|
+
} else {
|
|
1088
|
+
;({ offRamp, input } = opts)
|
|
1089
|
+
}
|
|
1090
|
+
if ('verifications' in input) {
|
|
1091
|
+
const contract = new Contract(
|
|
1092
|
+
offRamp,
|
|
1093
|
+
interfaces.OffRamp_v2_0,
|
|
1094
|
+
this.provider,
|
|
1095
|
+
) as unknown as TypedContract<typeof OffRamp_2_0_ABI>
|
|
1096
|
+
|
|
1097
|
+
const message = decodeMessageV1(input.encodedMessage)
|
|
1098
|
+
const messageId = keccak256(input.encodedMessage)
|
|
1099
|
+
// `execute` doesn't revert on failure, so we need to estimate using `executeSingleMessage`
|
|
1100
|
+
const txGasLimit = await contract.executeSingleMessage.estimateGas(
|
|
1101
|
+
{
|
|
1102
|
+
...message,
|
|
1103
|
+
executionGasLimit: BigInt(message.executionGasLimit),
|
|
1104
|
+
ccipReceiveGasLimit: BigInt(message.ccipReceiveGasLimit),
|
|
1105
|
+
finality: BigInt(message.finality),
|
|
1106
|
+
},
|
|
1107
|
+
messageId,
|
|
1108
|
+
input.verifications.map(({ destAddress }) => destAddress),
|
|
1109
|
+
input.verifications.map(({ ccvData }) => hexlify(ccvData)),
|
|
1110
|
+
BigInt(opts.gasLimit ?? 0),
|
|
1111
|
+
{ from: offRamp }, // internal method
|
|
1112
|
+
)
|
|
1113
|
+
const execTx = await contract.execute.populateTransaction(
|
|
1114
|
+
input.encodedMessage,
|
|
1115
|
+
input.verifications.map(({ destAddress }) => destAddress),
|
|
1116
|
+
input.verifications.map(({ ccvData }) => hexlify(ccvData)),
|
|
1117
|
+
BigInt(opts.gasLimit ?? 0),
|
|
1118
|
+
)
|
|
1119
|
+
execTx.gasLimit = txGasLimit + 40000n // plus `execute`'s overhead
|
|
1120
|
+
return { family: ChainFamily.EVM, transactions: [execTx] }
|
|
1121
|
+
}
|
|
1054
1122
|
|
|
1055
1123
|
let manualExecTx
|
|
1056
|
-
const
|
|
1124
|
+
const [_, version] = await this.typeAndVersion(offRamp)
|
|
1125
|
+
const offchainTokenData = input.offchainTokenData.map(encodeEVMOffchainTokenData)
|
|
1057
1126
|
|
|
1058
1127
|
switch (version) {
|
|
1059
1128
|
case CCIPVersion.V1_2: {
|
|
1060
1129
|
const contract = new Contract(
|
|
1061
1130
|
offRamp,
|
|
1062
|
-
|
|
1131
|
+
interfaces.EVM2EVMOffRamp_v1_2,
|
|
1063
1132
|
this.provider,
|
|
1064
1133
|
) as unknown as TypedContract<typeof EVM2EVMOffRamp_1_2_ABI>
|
|
1065
1134
|
const gasOverride = BigInt(opts.gasLimit ?? 0)
|
|
1066
1135
|
manualExecTx = await contract.manuallyExecute.populateTransaction(
|
|
1067
1136
|
{
|
|
1068
|
-
...
|
|
1069
|
-
proofs:
|
|
1070
|
-
messages: [
|
|
1137
|
+
...input,
|
|
1138
|
+
proofs: input.proofs.map((d) => hexlify(d)),
|
|
1139
|
+
messages: [input.message as CCIPMessage<typeof CCIPVersion.V1_2>],
|
|
1071
1140
|
offchainTokenData: [offchainTokenData],
|
|
1072
1141
|
},
|
|
1073
1142
|
[gasOverride],
|
|
@@ -1077,20 +1146,20 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
1077
1146
|
case CCIPVersion.V1_5: {
|
|
1078
1147
|
const contract = new Contract(
|
|
1079
1148
|
offRamp,
|
|
1080
|
-
|
|
1149
|
+
interfaces.EVM2EVMOffRamp_v1_5,
|
|
1081
1150
|
this.provider,
|
|
1082
1151
|
) as unknown as TypedContract<typeof EVM2EVMOffRamp_1_5_ABI>
|
|
1083
1152
|
manualExecTx = await contract.manuallyExecute.populateTransaction(
|
|
1084
1153
|
{
|
|
1085
|
-
...
|
|
1086
|
-
proofs:
|
|
1087
|
-
messages: [
|
|
1154
|
+
...input,
|
|
1155
|
+
proofs: input.proofs.map((d) => hexlify(d)),
|
|
1156
|
+
messages: [input.message as CCIPMessage<typeof CCIPVersion.V1_5>],
|
|
1088
1157
|
offchainTokenData: [offchainTokenData],
|
|
1089
1158
|
},
|
|
1090
1159
|
[
|
|
1091
1160
|
{
|
|
1092
1161
|
receiverExecutionGasLimit: BigInt(opts.gasLimit ?? 0),
|
|
1093
|
-
tokenGasOverrides:
|
|
1162
|
+
tokenGasOverrides: input.message.tokenAmounts.map(() =>
|
|
1094
1163
|
BigInt(opts.tokensGasLimit ?? opts.gasLimit ?? 0),
|
|
1095
1164
|
),
|
|
1096
1165
|
},
|
|
@@ -1100,30 +1169,32 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
1100
1169
|
}
|
|
1101
1170
|
case CCIPVersion.V1_6: {
|
|
1102
1171
|
// normalize message
|
|
1103
|
-
const
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1172
|
+
const senderBytes = getAddressBytes(input.message.sender)
|
|
1173
|
+
// Addresses ≤32 bytes (EVM 20B, Aptos/Solana/Sui 32B) are zero-padded to 32 bytes;
|
|
1174
|
+
// Addresses >32 bytes (e.g., TON 36B) are used as raw bytes without padding
|
|
1175
|
+
const sender =
|
|
1176
|
+
senderBytes.length <= 32 ? zeroPadValue(senderBytes, 32) : hexlify(senderBytes)
|
|
1177
|
+
const tokenAmounts = (input.message as CCIPMessage_V1_6_EVM).tokenAmounts.map((ta) => ({
|
|
1178
|
+
...ta,
|
|
1179
|
+
sourcePoolAddress: zeroPadValue(getAddressBytes(ta.sourcePoolAddress), 32),
|
|
1180
|
+
extraData: hexlify(getDataBytes(ta.extraData)),
|
|
1181
|
+
}))
|
|
1111
1182
|
const message = {
|
|
1112
|
-
...(
|
|
1183
|
+
...(input.message as CCIPMessage_V1_6_EVM),
|
|
1113
1184
|
sender,
|
|
1114
1185
|
tokenAmounts,
|
|
1115
1186
|
}
|
|
1116
1187
|
const contract = new Contract(
|
|
1117
1188
|
offRamp,
|
|
1118
|
-
|
|
1189
|
+
interfaces.OffRamp_v1_6,
|
|
1119
1190
|
this.provider,
|
|
1120
1191
|
) as unknown as TypedContract<typeof OffRamp_1_6_ABI>
|
|
1121
1192
|
manualExecTx = await contract.manuallyExecute.populateTransaction(
|
|
1122
1193
|
[
|
|
1123
1194
|
{
|
|
1124
|
-
...
|
|
1125
|
-
proofs:
|
|
1126
|
-
sourceChainSelector:
|
|
1195
|
+
...input,
|
|
1196
|
+
proofs: input.proofs.map((p) => hexlify(p)),
|
|
1197
|
+
sourceChainSelector: input.message.sourceChainSelector,
|
|
1127
1198
|
messages: [
|
|
1128
1199
|
{
|
|
1129
1200
|
...message,
|
|
@@ -1143,7 +1214,7 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
1143
1214
|
[
|
|
1144
1215
|
{
|
|
1145
1216
|
receiverExecutionGasLimit: BigInt(opts.gasLimit ?? 0),
|
|
1146
|
-
tokenGasOverrides:
|
|
1217
|
+
tokenGasOverrides: input.message.tokenAmounts.map(() =>
|
|
1147
1218
|
BigInt(opts.tokensGasLimit ?? opts.gasLimit ?? 0),
|
|
1148
1219
|
),
|
|
1149
1220
|
},
|
|
@@ -1159,23 +1230,28 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
1159
1230
|
}
|
|
1160
1231
|
|
|
1161
1232
|
/**
|
|
1162
|
-
* {@inheritDoc Chain.
|
|
1233
|
+
* {@inheritDoc Chain.execute}
|
|
1163
1234
|
* @throws {@link CCIPWalletInvalidError} if wallet is not a valid Signer
|
|
1164
1235
|
* @throws {@link CCIPExecTxNotConfirmedError} if execution transaction fails to confirm
|
|
1165
1236
|
* @throws {@link CCIPExecTxRevertedError} if execution transaction reverts
|
|
1166
1237
|
*/
|
|
1167
|
-
async
|
|
1238
|
+
async execute(opts: Parameters<Chain['execute']>[0]) {
|
|
1168
1239
|
const wallet = opts.wallet
|
|
1169
1240
|
if (!isSigner(wallet)) throw new CCIPWalletInvalidError(wallet)
|
|
1170
1241
|
|
|
1171
|
-
const unsignedTxs = await this.
|
|
1242
|
+
const unsignedTxs = await this.generateUnsignedExecute({
|
|
1172
1243
|
...opts,
|
|
1173
1244
|
payer: await wallet.getAddress(),
|
|
1174
1245
|
})
|
|
1175
|
-
|
|
1176
|
-
unsignedTx
|
|
1177
|
-
|
|
1246
|
+
|
|
1247
|
+
const unsignedTx: TransactionRequest = unsignedTxs.transactions[0]!
|
|
1248
|
+
unsignedTx.nonce = await this.nextNonce(await wallet.getAddress())
|
|
1249
|
+
const populatedTx = await wallet.populateTransaction(unsignedTx)
|
|
1250
|
+
populatedTx.from = undefined // some signers don't like receiving pre-populated `from`
|
|
1251
|
+
|
|
1252
|
+
const response = await submitTransaction(wallet, populatedTx, this.provider)
|
|
1178
1253
|
this.logger.debug('manuallyExecute =>', response.hash)
|
|
1254
|
+
|
|
1179
1255
|
const receipt = await response.wait(1, 60_000)
|
|
1180
1256
|
if (!receipt?.hash) throw new CCIPExecTxNotConfirmedError(response.hash)
|
|
1181
1257
|
if (!receipt.status) throw new CCIPExecTxRevertedError(response.hash)
|
|
@@ -1407,6 +1483,64 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
1407
1483
|
)
|
|
1408
1484
|
}
|
|
1409
1485
|
|
|
1486
|
+
/** {@inheritDoc Chain.getVerifications} */
|
|
1487
|
+
override async getVerifications(
|
|
1488
|
+
opts: Parameters<Chain['getVerifications']>[0],
|
|
1489
|
+
): Promise<CCIPVerifications> {
|
|
1490
|
+
const { offRamp, request } = opts
|
|
1491
|
+
if (request.lane.version >= CCIPVersion.V2_0) {
|
|
1492
|
+
const message = request.message as CCIPMessage_V2_0
|
|
1493
|
+
if (!message.encodedMessage)
|
|
1494
|
+
throw new CCIPNotImplementedError(`CCIPAPIClient getMessageById v2 encodedMessage`)
|
|
1495
|
+
const contract = new Contract(
|
|
1496
|
+
offRamp,
|
|
1497
|
+
interfaces.OffRamp_v2_0,
|
|
1498
|
+
this.provider,
|
|
1499
|
+
) as unknown as TypedContract<typeof OffRamp_2_0_ABI>
|
|
1500
|
+
const ccvs = await contract.getCCVsForMessage(message.encodedMessage)
|
|
1501
|
+
const [requiredCCVs, optionalCCVs, optionalThreshold] = ccvs.map(
|
|
1502
|
+
resultToObject,
|
|
1503
|
+
) as unknown as CleanAddressable<typeof ccvs>
|
|
1504
|
+
const verificationPolicy = {
|
|
1505
|
+
requiredCCVs,
|
|
1506
|
+
optionalCCVs,
|
|
1507
|
+
optionalThreshold: Number(optionalThreshold),
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
if (this.apiClient) {
|
|
1511
|
+
const apiRes = await this.apiClient.getMessageById(request.message.messageId)
|
|
1512
|
+
if ('verifiers' in apiRes.message) {
|
|
1513
|
+
const verifiers = apiRes.message.verifiers as {
|
|
1514
|
+
items: {
|
|
1515
|
+
destAddress: string
|
|
1516
|
+
sourceAddress: string
|
|
1517
|
+
verification: { data: string; timestamp: string }
|
|
1518
|
+
}[]
|
|
1519
|
+
}
|
|
1520
|
+
return {
|
|
1521
|
+
verificationPolicy,
|
|
1522
|
+
verifications: verifiers.items.map((item) => ({
|
|
1523
|
+
destAddress: item.destAddress,
|
|
1524
|
+
sourceAddress: item.sourceAddress,
|
|
1525
|
+
ccvData: item.verification.data,
|
|
1526
|
+
timestamp: new Date(item.verification.timestamp).getTime() / 1e3,
|
|
1527
|
+
})),
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1532
|
+
const url = `${CCV_INDEXER_URL}/v1/verifierresults/${request.message.messageId}`
|
|
1533
|
+
const res = await fetch(url)
|
|
1534
|
+
const json = await res.json()
|
|
1535
|
+
return json as CCIPVerifications
|
|
1536
|
+
} else if (request.lane.version < CCIPVersion.V1_6) {
|
|
1537
|
+
// v1.2..v1.5 EVM (only) have separate CommitStore
|
|
1538
|
+
opts.offRamp = await this.getCommitStoreForOffRamp(opts.offRamp)
|
|
1539
|
+
}
|
|
1540
|
+
// fallback <=v1.6
|
|
1541
|
+
return super.getVerifications(opts)
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1410
1544
|
/** {@inheritDoc Chain.getExecutionReceipts} */
|
|
1411
1545
|
override async *getExecutionReceipts(
|
|
1412
1546
|
opts: Parameters<Chain['getExecutionReceipts']>[0],
|
|
@@ -1426,10 +1560,14 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
1426
1560
|
// onlyFallback: false,
|
|
1427
1561
|
}
|
|
1428
1562
|
} else /* >= V1.6 */ {
|
|
1563
|
+
const topicHash =
|
|
1564
|
+
version === CCIPVersion.V1_6
|
|
1565
|
+
? interfaces.OffRamp_v1_6.getEvent('ExecutionStateChanged')!.topicHash
|
|
1566
|
+
: interfaces.OffRamp_v2_0.getEvent('ExecutionStateChanged')!.topicHash
|
|
1429
1567
|
opts_ = {
|
|
1430
1568
|
...opts,
|
|
1431
1569
|
topics: [
|
|
1432
|
-
|
|
1570
|
+
topicHash,
|
|
1433
1571
|
sourceChainSelector ? toBeHex(sourceChainSelector, 32) : null,
|
|
1434
1572
|
null,
|
|
1435
1573
|
messageId ?? null,
|