@chainlink/ccip-sdk 0.95.0 → 0.97.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 +2 -2
- package/dist/all-chains.d.ts +23 -0
- package/dist/all-chains.d.ts.map +1 -0
- package/dist/all-chains.js +24 -0
- package/dist/all-chains.js.map +1 -0
- package/dist/api/index.d.ts +31 -19
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +46 -25
- package/dist/api/index.js.map +1 -1
- package/dist/api/types.d.ts +24 -30
- 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 +43 -15
- package/dist/aptos/index.d.ts.map +1 -1
- package/dist/aptos/index.js +112 -105
- package/dist/aptos/index.js.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 +734 -174
- package/dist/chain.d.ts.map +1 -1
- package/dist/chain.js +216 -31
- 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 +5 -0
- package/dist/errors/codes.d.ts.map +1 -1
- package/dist/errors/codes.js +5 -1
- package/dist/errors/codes.js.map +1 -1
- package/dist/errors/index.d.ts +2 -2
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +2 -2
- package/dist/errors/index.js.map +1 -1
- package/dist/errors/recovery.d.ts.map +1 -1
- package/dist/errors/recovery.js +6 -1
- package/dist/errors/recovery.js.map +1 -1
- package/dist/errors/specialized.d.ts +1702 -121
- package/dist/errors/specialized.d.ts.map +1 -1
- package/dist/errors/specialized.js +1729 -125
- 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 +25 -0
- package/dist/evm/extra-args.d.ts.map +1 -0
- package/dist/evm/extra-args.js +309 -0
- package/dist/evm/extra-args.js.map +1 -0
- package/dist/evm/gas.d.ts.map +1 -1
- package/dist/evm/gas.js +7 -12
- package/dist/evm/gas.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 +140 -35
- package/dist/evm/index.d.ts.map +1 -1
- package/dist/evm/index.js +306 -226
- package/dist/evm/index.js.map +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.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 +102 -51
- package/dist/execution.js.map +1 -1
- package/dist/extra-args.d.ts +113 -4
- package/dist/extra-args.d.ts.map +1 -1
- package/dist/extra-args.js +38 -3
- package/dist/extra-args.js.map +1 -1
- package/dist/gas.d.ts +31 -5
- package/dist/gas.d.ts.map +1 -1
- package/dist/gas.js +43 -9
- package/dist/gas.js.map +1 -1
- package/dist/index.d.ts +11 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -8
- package/dist/index.js.map +1 -1
- package/dist/requests.d.ts +101 -22
- package/dist/requests.d.ts.map +1 -1
- package/dist/requests.js +115 -24
- package/dist/requests.js.map +1 -1
- package/dist/selectors.d.ts.map +1 -1
- package/dist/selectors.js +24 -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/index.d.ts +148 -30
- package/dist/solana/index.d.ts.map +1 -1
- package/dist/solana/index.js +137 -44
- package/dist/solana/index.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 +49 -19
- package/dist/sui/index.d.ts.map +1 -1
- package/dist/sui/index.js +76 -43
- 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 +2 -2
- package/dist/ton/exec.d.ts.map +1 -1
- package/dist/ton/exec.js.map +1 -1
- package/dist/ton/index.d.ts +66 -27
- package/dist/ton/index.d.ts.map +1 -1
- package/dist/ton/index.js +172 -47
- package/dist/ton/index.js.map +1 -1
- package/dist/ton/send.d.ts +52 -0
- package/dist/ton/send.d.ts.map +1 -0
- package/dist/ton/send.js +166 -0
- package/dist/ton/send.js.map +1 -0
- package/dist/ton/types.d.ts +2 -2
- package/dist/ton/types.d.ts.map +1 -1
- package/dist/ton/types.js.map +1 -1
- package/dist/types.d.ts +148 -12
- 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 +79 -4
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +92 -7
- package/dist/utils.js.map +1 -1
- package/package.json +16 -11
- package/src/all-chains.ts +26 -0
- package/src/api/index.ts +58 -34
- package/src/api/types.ts +24 -31
- package/src/aptos/exec.ts +2 -2
- package/src/aptos/hasher.ts +1 -1
- package/src/aptos/index.ts +127 -129
- package/src/aptos/types.ts +2 -15
- package/src/chain.ts +837 -191
- package/src/commits.ts +9 -9
- package/src/errors/CCIPError.ts +33 -4
- package/src/errors/codes.ts +5 -1
- package/src/errors/index.ts +2 -1
- package/src/errors/recovery.ts +9 -1
- package/src/errors/specialized.ts +1745 -132
- 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 +360 -0
- package/src/evm/gas.ts +14 -13
- package/src/evm/hasher.ts +30 -18
- package/src/evm/index.ts +376 -281
- package/src/evm/messages.ts +323 -11
- package/src/evm/offchain.ts +2 -2
- package/src/evm/types.ts +20 -2
- package/src/execution.ts +126 -71
- package/src/extra-args.ts +118 -4
- package/src/gas.ts +44 -11
- package/src/index.ts +14 -11
- package/src/requests.ts +128 -24
- package/src/selectors.ts +24 -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/index.ts +170 -82
- package/src/sui/hasher.ts +1 -1
- package/src/sui/index.ts +88 -56
- package/src/sui/manuallyExec/encoder.ts +2 -2
- package/src/sui/manuallyExec/index.ts +2 -2
- package/src/ton/exec.ts +2 -2
- package/src/ton/index.ts +220 -58
- package/src/ton/send.ts +222 -0
- package/src/ton/types.ts +2 -2
- package/src/types.ts +173 -30
- package/src/utils.ts +91 -7
- 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,27 +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
|
-
concat,
|
|
17
|
-
dataSlice,
|
|
18
|
-
encodeBase58,
|
|
19
15
|
getAddress,
|
|
20
16
|
hexlify,
|
|
21
17
|
isBytesLike,
|
|
22
18
|
isHexString,
|
|
19
|
+
keccak256,
|
|
23
20
|
toBeHex,
|
|
24
|
-
toBigInt,
|
|
25
21
|
zeroPadValue,
|
|
26
22
|
} from 'ethers'
|
|
27
23
|
import type { TypedContract } from 'ethers-abitype'
|
|
@@ -37,43 +33,36 @@ import {
|
|
|
37
33
|
} from '../chain.ts'
|
|
38
34
|
import {
|
|
39
35
|
CCIPAddressInvalidEvmError,
|
|
36
|
+
CCIPApiClientNotAvailableError,
|
|
40
37
|
CCIPBlockNotFoundError,
|
|
41
38
|
CCIPContractNotRouterError,
|
|
42
39
|
CCIPContractTypeInvalidError,
|
|
43
40
|
CCIPDataFormatUnsupportedError,
|
|
44
41
|
CCIPExecTxNotConfirmedError,
|
|
45
42
|
CCIPExecTxRevertedError,
|
|
46
|
-
CCIPExtraArgsParseError,
|
|
47
43
|
CCIPHasherVersionUnsupportedError,
|
|
48
44
|
CCIPLogDataInvalidError,
|
|
49
|
-
|
|
45
|
+
CCIPNotImplementedError,
|
|
50
46
|
CCIPSourceChainUnsupportedError,
|
|
51
47
|
CCIPTokenNotConfiguredError,
|
|
48
|
+
CCIPTokenPoolChainConfigNotFoundError,
|
|
52
49
|
CCIPTransactionNotFoundError,
|
|
53
50
|
CCIPVersionFeatureUnavailableError,
|
|
54
51
|
CCIPVersionRequiresLaneError,
|
|
55
52
|
CCIPVersionUnsupportedError,
|
|
56
53
|
CCIPWalletInvalidError,
|
|
57
54
|
} from '../errors/index.ts'
|
|
58
|
-
import {
|
|
59
|
-
type EVMExtraArgsV1,
|
|
60
|
-
type EVMExtraArgsV2,
|
|
61
|
-
type ExtraArgs,
|
|
62
|
-
type SVMExtraArgsV1,
|
|
63
|
-
type SuiExtraArgsV1,
|
|
64
|
-
EVMExtraArgsV1Tag,
|
|
65
|
-
EVMExtraArgsV2Tag,
|
|
66
|
-
SVMExtraArgsV1Tag,
|
|
67
|
-
SuiExtraArgsV1Tag,
|
|
68
|
-
} from '../extra-args.ts'
|
|
55
|
+
import type { ExtraArgs } from '../extra-args.ts'
|
|
69
56
|
import type { LeafHasher } from '../hasher/common.ts'
|
|
70
57
|
import { supportedChains } from '../supported-chains.ts'
|
|
71
58
|
import {
|
|
72
59
|
type CCIPExecution,
|
|
73
60
|
type CCIPMessage,
|
|
74
61
|
type CCIPRequest,
|
|
62
|
+
type CCIPVerifications,
|
|
75
63
|
type ChainTransaction,
|
|
76
64
|
type CommitReport,
|
|
65
|
+
type ExecutionInput,
|
|
77
66
|
type ExecutionReceipt,
|
|
78
67
|
type ExecutionState,
|
|
79
68
|
type Lane,
|
|
@@ -100,56 +89,44 @@ import type TokenPool_ABI from './abi/LockReleaseTokenPool_1_6_1.ts'
|
|
|
100
89
|
import EVM2EVMOffRamp_1_2_ABI from './abi/OffRamp_1_2.ts'
|
|
101
90
|
import EVM2EVMOffRamp_1_5_ABI from './abi/OffRamp_1_5.ts'
|
|
102
91
|
import OffRamp_1_6_ABI from './abi/OffRamp_1_6.ts'
|
|
92
|
+
import OffRamp_2_0_ABI from './abi/OffRamp_2_0.ts'
|
|
103
93
|
import EVM2EVMOnRamp_1_2_ABI from './abi/OnRamp_1_2.ts'
|
|
104
94
|
import EVM2EVMOnRamp_1_5_ABI from './abi/OnRamp_1_5.ts'
|
|
105
|
-
import OnRamp_1_6_ABI from './abi/OnRamp_1_6.ts'
|
|
95
|
+
import type OnRamp_1_6_ABI from './abi/OnRamp_1_6.ts'
|
|
96
|
+
import type OnRamp_2_0_ABI from './abi/OnRamp_2_0.ts'
|
|
106
97
|
import type Router_ABI from './abi/Router.ts'
|
|
107
98
|
import type TokenAdminRegistry_1_5_ABI from './abi/TokenAdminRegistry_1_5.ts'
|
|
108
99
|
import {
|
|
109
|
-
|
|
100
|
+
CCV_INDEXER_URL,
|
|
101
|
+
VersionedContractABI,
|
|
110
102
|
commitsFragments,
|
|
111
|
-
defaultAbiCoder,
|
|
112
103
|
interfaces,
|
|
113
104
|
receiptsFragments,
|
|
114
105
|
requestsFragments,
|
|
115
106
|
} from './const.ts'
|
|
116
107
|
import { parseData } from './errors.ts'
|
|
108
|
+
import {
|
|
109
|
+
decodeExtraArgs as decodeExtraArgs_,
|
|
110
|
+
encodeExtraArgs as encodeExtraArgs_,
|
|
111
|
+
} from './extra-args.ts'
|
|
117
112
|
import { estimateExecGas } from './gas.ts'
|
|
118
113
|
import { getV12LeafHasher, getV16LeafHasher } from './hasher.ts'
|
|
119
114
|
import { getEvmLogs } from './logs.ts'
|
|
120
115
|
import {
|
|
121
116
|
type CCIPMessage_V1_6_EVM,
|
|
117
|
+
type CCIPMessage_V2_0,
|
|
122
118
|
type CleanAddressable,
|
|
123
|
-
|
|
119
|
+
type MessageV1,
|
|
120
|
+
type TokenTransferV1,
|
|
121
|
+
decodeMessageV1,
|
|
124
122
|
} from './messages.ts'
|
|
123
|
+
export { decodeMessageV1 }
|
|
124
|
+
export type { MessageV1, TokenTransferV1 }
|
|
125
125
|
import { encodeEVMOffchainTokenData, fetchEVMOffchainTokenData } from './offchain.ts'
|
|
126
|
-
import { buildMessageForDest, getMessagesInBatch } from '../requests.ts'
|
|
127
|
-
import type
|
|
126
|
+
import { buildMessageForDest, decodeMessage, getMessagesInBatch } from '../requests.ts'
|
|
127
|
+
import { type UnsignedEVMTx, resultToObject } from './types.ts'
|
|
128
128
|
export type { UnsignedEVMTx }
|
|
129
129
|
|
|
130
|
-
const VersionedContractABI = parseAbi(['function typeAndVersion() view returns (string)'])
|
|
131
|
-
|
|
132
|
-
const EVMExtraArgsV1 = 'tuple(uint256 gasLimit)'
|
|
133
|
-
const EVMExtraArgsV2 = 'tuple(uint256 gasLimit, bool allowOutOfOrderExecution)'
|
|
134
|
-
const SVMExtraArgsV1 =
|
|
135
|
-
'tuple(uint32 computeUnits, uint64 accountIsWritableBitmap, bool allowOutOfOrderExecution, bytes32 tokenReceiver, bytes32[] accounts)'
|
|
136
|
-
const SuiExtraArgsV1 =
|
|
137
|
-
'tuple(uint256 gasLimit, bool allowOutOfOrderExecution, bytes32 tokenReceiver, bytes32[] receiverObjectIds)'
|
|
138
|
-
|
|
139
|
-
function resultToObject<T>(o: T): T {
|
|
140
|
-
if (o instanceof Promise) return o.then(resultToObject) as T
|
|
141
|
-
if (!(o instanceof Result)) return o
|
|
142
|
-
if (o.length === 0) return o.toArray() as T
|
|
143
|
-
try {
|
|
144
|
-
const obj = o.toObject()
|
|
145
|
-
if (!Object.keys(obj).every((k) => /^_+\d*$/.test(k)))
|
|
146
|
-
return Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, resultToObject(v)])) as T
|
|
147
|
-
} catch (_) {
|
|
148
|
-
// fallthrough
|
|
149
|
-
}
|
|
150
|
-
return o.toArray().map(resultToObject) as T
|
|
151
|
-
}
|
|
152
|
-
|
|
153
130
|
/** typeguard for ethers Signer interface (used for `wallet`s) */
|
|
154
131
|
function isSigner(wallet: unknown): wallet is Signer {
|
|
155
132
|
return (
|
|
@@ -180,6 +157,26 @@ async function submitTransaction(
|
|
|
180
157
|
|
|
181
158
|
/**
|
|
182
159
|
* EVM chain implementation supporting Ethereum-compatible networks.
|
|
160
|
+
*
|
|
161
|
+
* Provides methods for sending CCIP cross-chain messages, querying message
|
|
162
|
+
* status, fetching fee quotes, and manually executing pending messages on
|
|
163
|
+
* Ethereum Virtual Machine compatible chains.
|
|
164
|
+
*
|
|
165
|
+
* @example Create from RPC URL
|
|
166
|
+
* ```typescript
|
|
167
|
+
* import { EVMChain } from '@chainlink/ccip-sdk'
|
|
168
|
+
*
|
|
169
|
+
* const chain = await EVMChain.fromUrl('https://rpc.sepolia.org')
|
|
170
|
+
* console.log(`Connected to: ${chain.network.name}`)
|
|
171
|
+
* ```
|
|
172
|
+
*
|
|
173
|
+
* @example Query messages in a transaction
|
|
174
|
+
* ```typescript
|
|
175
|
+
* const requests = await chain.getMessagesInTx('0xabc123...')
|
|
176
|
+
* for (const req of requests) {
|
|
177
|
+
* console.log(`Message ID: ${req.message.messageId}`)
|
|
178
|
+
* }
|
|
179
|
+
* ```
|
|
183
180
|
*/
|
|
184
181
|
export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
185
182
|
static {
|
|
@@ -190,6 +187,13 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
190
187
|
|
|
191
188
|
provider: JsonRpcApiProvider
|
|
192
189
|
readonly destroy$: Promise<void>
|
|
190
|
+
private noncesPromises: Record<string, Promise<unknown>>
|
|
191
|
+
/**
|
|
192
|
+
* Cache of current nonces per wallet address.
|
|
193
|
+
* Used internally by {@link sendMessage} and {@link execute} to manage transaction ordering.
|
|
194
|
+
* Can be inspected for debugging or manually adjusted if needed.
|
|
195
|
+
*/
|
|
196
|
+
nonces: Record<string, number>
|
|
193
197
|
|
|
194
198
|
/**
|
|
195
199
|
* Creates a new EVMChain instance.
|
|
@@ -199,6 +203,9 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
199
203
|
constructor(provider: JsonRpcApiProvider, network: NetworkInfo, ctx?: ChainContext) {
|
|
200
204
|
super(network, ctx)
|
|
201
205
|
|
|
206
|
+
this.noncesPromises = {}
|
|
207
|
+
this.nonces = {}
|
|
208
|
+
|
|
202
209
|
this.provider = provider
|
|
203
210
|
this.destroy$ = new Promise<void>((resolve) => (this.destroy = resolve))
|
|
204
211
|
void this.destroy$.finally(() => provider.destroy())
|
|
@@ -238,6 +245,22 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
238
245
|
return (await this.provider.listAccounts()).map(({ address }) => address)
|
|
239
246
|
}
|
|
240
247
|
|
|
248
|
+
/**
|
|
249
|
+
* Get the next nonce for a wallet address and increment the internal counter.
|
|
250
|
+
* Fetches from the network on first call, then uses cached value.
|
|
251
|
+
* @param address - Wallet address to get nonce for
|
|
252
|
+
* @returns The next available nonce
|
|
253
|
+
*/
|
|
254
|
+
async nextNonce(address: string): Promise<number> {
|
|
255
|
+
await (this.noncesPromises[address] ??= this.provider
|
|
256
|
+
.getTransactionCount(address)
|
|
257
|
+
.then((nonce) => {
|
|
258
|
+
this.nonces[address] = nonce
|
|
259
|
+
return nonce
|
|
260
|
+
}))
|
|
261
|
+
return this.nonces[address]!++
|
|
262
|
+
}
|
|
263
|
+
|
|
241
264
|
/**
|
|
242
265
|
* Creates a JSON-RPC provider from a URL.
|
|
243
266
|
* @param url - WebSocket (wss://) or HTTP (https://) endpoint URL.
|
|
@@ -282,9 +305,20 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
282
305
|
|
|
283
306
|
/**
|
|
284
307
|
* Creates an EVMChain instance from an RPC URL.
|
|
308
|
+
*
|
|
285
309
|
* @param url - WebSocket (wss://) or HTTP (https://) endpoint URL.
|
|
286
|
-
* @param ctx - context containing logger.
|
|
287
|
-
* @returns A new EVMChain instance.
|
|
310
|
+
* @param ctx - Optional context containing logger and API client configuration.
|
|
311
|
+
* @returns A new EVMChain instance connected to the specified network.
|
|
312
|
+
* @throws {@link CCIPChainNotFoundError} if chain cannot be identified from chainId
|
|
313
|
+
*
|
|
314
|
+
* @example
|
|
315
|
+
* ```typescript
|
|
316
|
+
* // HTTP connection
|
|
317
|
+
* const chain = await EVMChain.fromUrl('https://rpc.sepolia.org')
|
|
318
|
+
*
|
|
319
|
+
* // With custom logger
|
|
320
|
+
* const chain = await EVMChain.fromUrl(url, { logger: customLogger })
|
|
321
|
+
* ```
|
|
288
322
|
*/
|
|
289
323
|
static async fromUrl(url: string, ctx?: ChainContext): Promise<EVMChain> {
|
|
290
324
|
return this.fromProvider(await this._getProvider(url), ctx)
|
|
@@ -320,15 +354,15 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
320
354
|
}
|
|
321
355
|
|
|
322
356
|
/** {@inheritDoc Chain.getMessagesInBatch} */
|
|
323
|
-
getMessagesInBatch<
|
|
357
|
+
override getMessagesInBatch<
|
|
324
358
|
R extends PickDeep<
|
|
325
359
|
CCIPRequest,
|
|
326
360
|
'lane' | `log.${'topics' | 'address' | 'blockNumber'}` | 'message.sequenceNumber'
|
|
327
361
|
>,
|
|
328
362
|
>(
|
|
329
363
|
request: R,
|
|
330
|
-
|
|
331
|
-
opts?:
|
|
364
|
+
range: Pick<CommitReport, 'minSeqNr' | 'maxSeqNr'>,
|
|
365
|
+
opts?: Pick<LogFilter, 'page'>,
|
|
332
366
|
): Promise<R['message'][]> {
|
|
333
367
|
let opts_: Parameters<EVMChain['getLogs']>[0] | undefined
|
|
334
368
|
if (request.lane.version >= CCIPVersion.V1_6) {
|
|
@@ -338,7 +372,7 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
338
372
|
topics: [[request.log.topics[0]!], [toBeHex(request.lane.destChainSelector, 32)]],
|
|
339
373
|
}
|
|
340
374
|
}
|
|
341
|
-
return getMessagesInBatch(this, request,
|
|
375
|
+
return getMessagesInBatch(this, request, range, opts_)
|
|
342
376
|
}
|
|
343
377
|
|
|
344
378
|
/** {@inheritDoc Chain.typeAndVersion} */
|
|
@@ -348,13 +382,17 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
348
382
|
VersionedContractABI,
|
|
349
383
|
this.provider,
|
|
350
384
|
) as unknown as TypedContract<typeof VersionedContractABI>
|
|
351
|
-
|
|
385
|
+
const res = parseTypeAndVersion(await contract.typeAndVersion())
|
|
386
|
+
if (res[1].startsWith('1.7.')) res[1] = CCIPVersion.V2_0
|
|
387
|
+
return res
|
|
352
388
|
}
|
|
353
389
|
|
|
354
390
|
/**
|
|
355
391
|
* Decodes a CCIP message from a log event.
|
|
356
392
|
* @param log - Log event with topics and data.
|
|
357
393
|
* @returns Decoded CCIPMessage or undefined if not a valid CCIP message.
|
|
394
|
+
* @throws {@link CCIPLogDataInvalidError} if log data is not valid bytes
|
|
395
|
+
* @throws {@link CCIPMessageDecodeError} if message cannot be decoded
|
|
358
396
|
*/
|
|
359
397
|
static decodeMessage(log: {
|
|
360
398
|
topics?: readonly string[]
|
|
@@ -376,79 +414,16 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
376
414
|
const result = interfaces.OnRamp_v1_6.decodeEventLog(fragment, log.data, log.topics)
|
|
377
415
|
message = resultToObject(result) as Record<string, unknown>
|
|
378
416
|
if (message.message) message = message.message as Record<string, unknown> | undefined
|
|
417
|
+
else if (message.encodedMessage) {
|
|
418
|
+
Object.assign(message, decodeMessageV1(message.encodedMessage as BytesLike))
|
|
419
|
+
}
|
|
379
420
|
if (message) break
|
|
380
421
|
} catch (_) {
|
|
381
422
|
// try next fragment
|
|
382
423
|
}
|
|
383
424
|
}
|
|
384
425
|
if (!message) return
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
if (message.header) {
|
|
388
|
-
// CCIPMessage_V1_6
|
|
389
|
-
Object.assign(message, message.header)
|
|
390
|
-
delete message.header
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
const sourceFamily = networkInfo(
|
|
394
|
-
(message as { sourceChainSelector: bigint }).sourceChainSelector,
|
|
395
|
-
).family
|
|
396
|
-
let destFamily: ChainFamily = ChainFamily.EVM
|
|
397
|
-
if ((message as { destChainSelector?: bigint }).destChainSelector) {
|
|
398
|
-
destFamily = networkInfo((message as { destChainSelector: bigint }).destChainSelector).family
|
|
399
|
-
}
|
|
400
|
-
// conversions to make any message version be compatible with latest v1.6
|
|
401
|
-
message.tokenAmounts = (message.tokenAmounts as Record<string, string | bigint | number>[]).map(
|
|
402
|
-
(tokenAmount, i) => {
|
|
403
|
-
if ('sourceTokenData' in message) {
|
|
404
|
-
// CCIPMessage_V1_2_EVM
|
|
405
|
-
try {
|
|
406
|
-
tokenAmount = {
|
|
407
|
-
...parseSourceTokenData(
|
|
408
|
-
(message as { sourceTokenData: string[] }).sourceTokenData[i]!,
|
|
409
|
-
),
|
|
410
|
-
...tokenAmount,
|
|
411
|
-
}
|
|
412
|
-
} catch (_) {
|
|
413
|
-
// legacy sourceTokenData
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
if (typeof tokenAmount.destExecData === 'string' && tokenAmount.destGasAmount == null) {
|
|
417
|
-
// CCIPMessage_V1_6_EVM
|
|
418
|
-
tokenAmount.destGasAmount = toBigInt(getDataBytes(tokenAmount.destExecData))
|
|
419
|
-
}
|
|
420
|
-
// Can be undefined if the message is from before v1.5 and failed to parse sourceTokenData
|
|
421
|
-
if (tokenAmount.sourcePoolAddress) {
|
|
422
|
-
tokenAmount.sourcePoolAddress = decodeAddress(
|
|
423
|
-
tokenAmount.sourcePoolAddress as string,
|
|
424
|
-
sourceFamily,
|
|
425
|
-
)
|
|
426
|
-
}
|
|
427
|
-
if (tokenAmount.destTokenAddress) {
|
|
428
|
-
tokenAmount.destTokenAddress = decodeAddress(
|
|
429
|
-
tokenAmount.destTokenAddress as string,
|
|
430
|
-
destFamily,
|
|
431
|
-
)
|
|
432
|
-
}
|
|
433
|
-
return tokenAmount
|
|
434
|
-
},
|
|
435
|
-
)
|
|
436
|
-
message.sender = decodeAddress(message.sender, sourceFamily)
|
|
437
|
-
message.feeToken = decodeAddress(message.feeToken as string, sourceFamily)
|
|
438
|
-
message.receiver = decodeAddress(message.receiver as string, destFamily)
|
|
439
|
-
if (message.extraArgs) {
|
|
440
|
-
// v1.6+
|
|
441
|
-
const parsed = this.decodeExtraArgs(message.extraArgs as string)
|
|
442
|
-
if (!parsed) throw new CCIPExtraArgsParseError(message.extraArgs as string)
|
|
443
|
-
const { _tag, ...rest } = parsed
|
|
444
|
-
// merge parsed extraArgs to any family in message root object
|
|
445
|
-
Object.assign(message, rest)
|
|
446
|
-
} else if (message.nonce === 0n) {
|
|
447
|
-
// v1.2..v1.5 targets EVM only; extraArgs is not explicit, gasLimit is already in
|
|
448
|
-
// message body, allowOutOfOrderExecution (in v1.5) was present only as nonce=0
|
|
449
|
-
message.allowOutOfOrderExecution = true
|
|
450
|
-
}
|
|
451
|
-
return message as CCIPMessage
|
|
426
|
+
return decodeMessage(message)
|
|
452
427
|
}
|
|
453
428
|
|
|
454
429
|
/**
|
|
@@ -456,6 +431,8 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
456
431
|
* @param log - Log event with topics and data.
|
|
457
432
|
* @param lane - Lane info (required for CCIP v1.5 and earlier).
|
|
458
433
|
* @returns Array of CommitReport or undefined if not a valid commit event.
|
|
434
|
+
* @throws {@link CCIPLogDataInvalidError} if log data is not valid bytes
|
|
435
|
+
* @throws {@link CCIPVersionRequiresLaneError} if CCIP v1.5 event but no lane provided
|
|
459
436
|
*/
|
|
460
437
|
static decodeCommits(
|
|
461
438
|
log: { topics?: readonly string[]; data: unknown },
|
|
@@ -511,6 +488,7 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
511
488
|
* Decodes an execution receipt from a log event.
|
|
512
489
|
* @param log - Log event with topics and data.
|
|
513
490
|
* @returns ExecutionReceipt or undefined if not a valid execution event.
|
|
491
|
+
* @throws {@link CCIPLogDataInvalidError} if log data is not valid bytes
|
|
514
492
|
*/
|
|
515
493
|
static decodeReceipt(log: {
|
|
516
494
|
topics?: readonly string[]
|
|
@@ -542,43 +520,8 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
542
520
|
* @param extraArgs - Encoded extra arguments bytes.
|
|
543
521
|
* @returns Decoded extra arguments with tag, or undefined if unknown format.
|
|
544
522
|
*/
|
|
545
|
-
static decodeExtraArgs(
|
|
546
|
-
extraArgs
|
|
547
|
-
):
|
|
548
|
-
| (EVMExtraArgsV1 & { _tag: 'EVMExtraArgsV1' })
|
|
549
|
-
| (EVMExtraArgsV2 & { _tag: 'EVMExtraArgsV2' })
|
|
550
|
-
| (SVMExtraArgsV1 & { _tag: 'SVMExtraArgsV1' })
|
|
551
|
-
| (SuiExtraArgsV1 & { _tag: 'SuiExtraArgsV1' })
|
|
552
|
-
| undefined {
|
|
553
|
-
const data = getDataBytes(extraArgs),
|
|
554
|
-
tag = dataSlice(data, 0, 4)
|
|
555
|
-
switch (tag) {
|
|
556
|
-
case EVMExtraArgsV1Tag: {
|
|
557
|
-
const args = defaultAbiCoder.decode([EVMExtraArgsV1], dataSlice(data, 4))
|
|
558
|
-
return { ...(resultToObject(args[0]) as EVMExtraArgsV1), _tag: 'EVMExtraArgsV1' }
|
|
559
|
-
}
|
|
560
|
-
case EVMExtraArgsV2Tag: {
|
|
561
|
-
const args = defaultAbiCoder.decode([EVMExtraArgsV2], dataSlice(data, 4))
|
|
562
|
-
return { ...(resultToObject(args[0]) as EVMExtraArgsV2), _tag: 'EVMExtraArgsV2' }
|
|
563
|
-
}
|
|
564
|
-
case SVMExtraArgsV1Tag: {
|
|
565
|
-
const args = defaultAbiCoder.decode([SVMExtraArgsV1], dataSlice(data, 4))
|
|
566
|
-
const parsed = resultToObject(args[0]) as SVMExtraArgsV1
|
|
567
|
-
parsed.tokenReceiver = encodeBase58(parsed.tokenReceiver)
|
|
568
|
-
parsed.accounts = parsed.accounts.map((a: string) => encodeBase58(a))
|
|
569
|
-
return { ...parsed, _tag: 'SVMExtraArgsV1' }
|
|
570
|
-
}
|
|
571
|
-
case SuiExtraArgsV1Tag: {
|
|
572
|
-
const args = defaultAbiCoder.decode([SuiExtraArgsV1], dataSlice(data, 4))
|
|
573
|
-
const parsed = resultToObject(args[0]) as SuiExtraArgsV1
|
|
574
|
-
return {
|
|
575
|
-
...parsed,
|
|
576
|
-
_tag: 'SuiExtraArgsV1',
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
default:
|
|
580
|
-
return undefined
|
|
581
|
-
}
|
|
523
|
+
static decodeExtraArgs(extraArgs: BytesLike) {
|
|
524
|
+
return decodeExtraArgs_(extraArgs)
|
|
582
525
|
}
|
|
583
526
|
|
|
584
527
|
/**
|
|
@@ -587,48 +530,14 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
587
530
|
* @returns Encoded extra arguments as hex string.
|
|
588
531
|
*/
|
|
589
532
|
static encodeExtraArgs(args: ExtraArgs | undefined): string {
|
|
590
|
-
|
|
591
|
-
if ('computeUnits' in args) {
|
|
592
|
-
return concat([
|
|
593
|
-
SVMExtraArgsV1Tag,
|
|
594
|
-
defaultAbiCoder.encode(
|
|
595
|
-
[SVMExtraArgsV1],
|
|
596
|
-
[
|
|
597
|
-
{
|
|
598
|
-
...args,
|
|
599
|
-
tokenReceiver: getAddressBytes(args.tokenReceiver),
|
|
600
|
-
accounts: args.accounts.map((a) => getAddressBytes(a)),
|
|
601
|
-
},
|
|
602
|
-
],
|
|
603
|
-
),
|
|
604
|
-
])
|
|
605
|
-
} else if ('receiverObjectIds' in args) {
|
|
606
|
-
return concat([
|
|
607
|
-
SuiExtraArgsV1Tag,
|
|
608
|
-
defaultAbiCoder.encode(
|
|
609
|
-
[SuiExtraArgsV1],
|
|
610
|
-
[
|
|
611
|
-
{
|
|
612
|
-
...args,
|
|
613
|
-
tokenReceiver: zeroPadValue(getAddressBytes(args.tokenReceiver), 32),
|
|
614
|
-
receiverObjectIds: args.receiverObjectIds.map((a) => getDataBytes(a)),
|
|
615
|
-
},
|
|
616
|
-
],
|
|
617
|
-
),
|
|
618
|
-
])
|
|
619
|
-
} else if ('allowOutOfOrderExecution' in args) {
|
|
620
|
-
if ((args as Partial<typeof args>).gasLimit == null) args.gasLimit = DEFAULT_GAS_LIMIT
|
|
621
|
-
return concat([EVMExtraArgsV2Tag, defaultAbiCoder.encode([EVMExtraArgsV2], [args])])
|
|
622
|
-
} else if ((args as Partial<typeof args>).gasLimit != null) {
|
|
623
|
-
return concat([EVMExtraArgsV1Tag, defaultAbiCoder.encode([EVMExtraArgsV1], [args])])
|
|
624
|
-
}
|
|
625
|
-
return '0x'
|
|
533
|
+
return encodeExtraArgs_(args)
|
|
626
534
|
}
|
|
627
535
|
|
|
628
536
|
/**
|
|
629
537
|
* Converts bytes to a checksummed EVM address.
|
|
630
538
|
* @param bytes - Bytes to convert (must be 20 bytes or 32 bytes with leading zeros).
|
|
631
539
|
* @returns Checksummed EVM address.
|
|
540
|
+
* @throws {@link CCIPAddressInvalidEvmError} if bytes cannot be converted to a valid EVM address
|
|
632
541
|
*/
|
|
633
542
|
static getAddress(bytes: BytesLike): string {
|
|
634
543
|
if (isHexString(bytes, 20)) return getAddress(bytes)
|
|
@@ -655,6 +564,7 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
655
564
|
* Gets lane configuration from an OnRamp contract.
|
|
656
565
|
* @param onRamp - OnRamp contract address.
|
|
657
566
|
* @returns Lane configuration.
|
|
567
|
+
* @throws {@link CCIPContractTypeInvalidError} if contract doesn't have destChainSelector
|
|
658
568
|
*/
|
|
659
569
|
async getLaneForOnRamp(onRamp: string): Promise<Lane> {
|
|
660
570
|
const [, version] = await this.typeAndVersion(onRamp)
|
|
@@ -674,7 +584,10 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
674
584
|
}
|
|
675
585
|
}
|
|
676
586
|
|
|
677
|
-
/**
|
|
587
|
+
/**
|
|
588
|
+
* {@inheritDoc Chain.getRouterForOnRamp}
|
|
589
|
+
* @throws {@link CCIPVersionUnsupportedError} if OnRamp version is not supported
|
|
590
|
+
*/
|
|
678
591
|
async getRouterForOnRamp(onRamp: string, destChainSelector: bigint): Promise<string> {
|
|
679
592
|
const [, version] = await this.typeAndVersion(onRamp)
|
|
680
593
|
let onRampABI
|
|
@@ -691,19 +604,32 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
691
604
|
return router as string
|
|
692
605
|
}
|
|
693
606
|
case CCIPVersion.V1_6: {
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
607
|
+
const contract = new Contract(
|
|
608
|
+
onRamp,
|
|
609
|
+
interfaces.OnRamp_v1_6,
|
|
610
|
+
this.provider,
|
|
611
|
+
) as unknown as TypedContract<typeof OnRamp_1_6_ABI>
|
|
698
612
|
const [, , router] = await contract.getDestChainConfig(destChainSelector)
|
|
699
613
|
return router as string
|
|
700
614
|
}
|
|
615
|
+
case CCIPVersion.V2_0: {
|
|
616
|
+
const contract = new Contract(
|
|
617
|
+
onRamp,
|
|
618
|
+
interfaces.OnRamp_v2_0,
|
|
619
|
+
this.provider,
|
|
620
|
+
) as unknown as TypedContract<typeof OnRamp_2_0_ABI>
|
|
621
|
+
const { router } = await contract.getDestChainConfig(destChainSelector)
|
|
622
|
+
return router as string
|
|
623
|
+
}
|
|
701
624
|
default:
|
|
702
625
|
throw new CCIPVersionUnsupportedError(version)
|
|
703
626
|
}
|
|
704
627
|
}
|
|
705
628
|
|
|
706
|
-
/**
|
|
629
|
+
/**
|
|
630
|
+
* {@inheritDoc Chain.getRouterForOffRamp}
|
|
631
|
+
* @throws {@link CCIPVersionUnsupportedError} if OffRamp version is not supported
|
|
632
|
+
*/
|
|
707
633
|
async getRouterForOffRamp(offRamp: string, sourceChainSelector: bigint): Promise<string> {
|
|
708
634
|
const [, version] = await this.typeAndVersion(offRamp)
|
|
709
635
|
let offRampABI, router
|
|
@@ -721,8 +647,11 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
721
647
|
;({ router } = await contract.getDynamicConfig())
|
|
722
648
|
break
|
|
723
649
|
}
|
|
724
|
-
case CCIPVersion.V1_6:
|
|
650
|
+
case CCIPVersion.V1_6:
|
|
725
651
|
offRampABI = OffRamp_1_6_ABI
|
|
652
|
+
// falls through
|
|
653
|
+
case CCIPVersion.V2_0: {
|
|
654
|
+
offRampABI = OffRamp_2_0_ABI
|
|
726
655
|
const contract = new Contract(
|
|
727
656
|
offRamp,
|
|
728
657
|
offRampABI,
|
|
@@ -770,8 +699,11 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
770
699
|
return contract.getOnRamp(destChainSelector) as Promise<string>
|
|
771
700
|
}
|
|
772
701
|
|
|
773
|
-
/**
|
|
774
|
-
|
|
702
|
+
/**
|
|
703
|
+
* {@inheritDoc Chain.getOnRampsForOffRamp}
|
|
704
|
+
* @throws {@link CCIPVersionUnsupportedError} if OffRamp version is not supported
|
|
705
|
+
*/
|
|
706
|
+
async getOnRampsForOffRamp(offRamp: string, sourceChainSelector: bigint): Promise<string[]> {
|
|
775
707
|
const [, version] = await this.typeAndVersion(offRamp)
|
|
776
708
|
let offRampABI
|
|
777
709
|
switch (version) {
|
|
@@ -786,7 +718,7 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
786
718
|
this.provider,
|
|
787
719
|
) as unknown as TypedContract<typeof offRampABI>
|
|
788
720
|
const { onRamp } = await contract.getStaticConfig()
|
|
789
|
-
return onRamp as string
|
|
721
|
+
return [onRamp as string]
|
|
790
722
|
}
|
|
791
723
|
case CCIPVersion.V1_6: {
|
|
792
724
|
offRampABI = OffRamp_1_6_ABI
|
|
@@ -796,14 +728,40 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
796
728
|
this.provider,
|
|
797
729
|
) as unknown as TypedContract<typeof offRampABI>
|
|
798
730
|
const { onRamp } = await contract.getSourceChainConfig(sourceChainSelector)
|
|
799
|
-
|
|
731
|
+
if (!onRamp || onRamp.match(/^(0x)?0*$/i)) return []
|
|
732
|
+
return [decodeOnRampAddress(onRamp, networkInfo(sourceChainSelector).family)]
|
|
733
|
+
}
|
|
734
|
+
case CCIPVersion.V2_0: {
|
|
735
|
+
offRampABI = OffRamp_2_0_ABI
|
|
736
|
+
const contract = new Contract(
|
|
737
|
+
offRamp,
|
|
738
|
+
offRampABI,
|
|
739
|
+
this.provider,
|
|
740
|
+
) as unknown as TypedContract<typeof offRampABI>
|
|
741
|
+
const { onRamps } = await contract.getSourceChainConfig(sourceChainSelector)
|
|
742
|
+
const sourceFamily = networkInfo(sourceChainSelector).family
|
|
743
|
+
return onRamps.map((onRamp) => decodeOnRampAddress(onRamp, sourceFamily))
|
|
800
744
|
}
|
|
801
745
|
default:
|
|
802
746
|
throw new CCIPVersionUnsupportedError(version)
|
|
803
747
|
}
|
|
804
748
|
}
|
|
805
749
|
|
|
806
|
-
/**
|
|
750
|
+
/**
|
|
751
|
+
* Fetch the CommitStore set in OffRamp config (CCIP v1.5 and earlier).
|
|
752
|
+
* For CCIP v1.6 and later, it should return the offRamp address.
|
|
753
|
+
*
|
|
754
|
+
* @param offRamp - OffRamp contract address
|
|
755
|
+
* @returns Promise resolving to CommitStore address
|
|
756
|
+
*
|
|
757
|
+
* @example Get commit store
|
|
758
|
+
* ```typescript
|
|
759
|
+
* const commitStore = await dest.getCommitStoreForOffRamp(offRampAddress)
|
|
760
|
+
* // For v1.6+, commitStore === offRampAddress
|
|
761
|
+
* ```
|
|
762
|
+
* @throws {@link CCIPVersionUnsupportedError} if OffRamp version is not supported
|
|
763
|
+
* @internal
|
|
764
|
+
*/
|
|
807
765
|
async getCommitStoreForOffRamp(offRamp: string): Promise<string> {
|
|
808
766
|
const [, version] = await this.typeAndVersion(offRamp)
|
|
809
767
|
let offRampABI
|
|
@@ -821,11 +779,8 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
821
779
|
const { commitStore } = await contract.getStaticConfig()
|
|
822
780
|
return commitStore as string
|
|
823
781
|
}
|
|
824
|
-
case CCIPVersion.V1_6: {
|
|
825
|
-
return offRamp
|
|
826
|
-
}
|
|
827
782
|
default:
|
|
828
|
-
|
|
783
|
+
return offRamp
|
|
829
784
|
}
|
|
830
785
|
}
|
|
831
786
|
|
|
@@ -875,6 +830,8 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
875
830
|
* @param lane - Lane configuration.
|
|
876
831
|
* @param ctx - Context object containing logger.
|
|
877
832
|
* @returns Leaf hasher function.
|
|
833
|
+
* @throws {@link CCIPSourceChainUnsupportedError} if source chain is not EVM for v1.2/v1.5
|
|
834
|
+
* @throws {@link CCIPHasherVersionUnsupportedError} if lane version is not supported
|
|
878
835
|
*/
|
|
879
836
|
static getDestLeafHasher(
|
|
880
837
|
{ sourceChainSelector, destChainSelector, onRamp, version }: Lane,
|
|
@@ -911,7 +868,10 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
911
868
|
return this.getOnRampForRouter(router, networkInfo(someOtherNetwork).chainSelector)
|
|
912
869
|
}
|
|
913
870
|
|
|
914
|
-
/**
|
|
871
|
+
/**
|
|
872
|
+
* {@inheritDoc Chain.getTokenAdminRegistryFor}
|
|
873
|
+
* @throws {@link CCIPContractNotRouterError} if address is not a Router, OnRamp, or OffRamp
|
|
874
|
+
*/
|
|
915
875
|
async getTokenAdminRegistryFor(address: string): Promise<string> {
|
|
916
876
|
let [type, version, typeAndVersion] = await this.typeAndVersion(address)
|
|
917
877
|
if (type === 'TokenAdminRegistry') {
|
|
@@ -942,6 +902,8 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
942
902
|
* @internal
|
|
943
903
|
* @param address - Router or Ramp contract address.
|
|
944
904
|
* @returns FeeQuoter contract address.
|
|
905
|
+
* @throws {@link CCIPContractNotRouterError} if address is not a Router, OnRamp, or OffRamp
|
|
906
|
+
* @throws {@link CCIPVersionFeatureUnavailableError} if contract version is below v1.6
|
|
945
907
|
*/
|
|
946
908
|
async getFeeQuoterFor(address: string): Promise<string> {
|
|
947
909
|
let [type, version, typeAndVersion] = await this.typeAndVersion(address)
|
|
@@ -1064,7 +1026,10 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
1064
1026
|
}
|
|
1065
1027
|
}
|
|
1066
1028
|
|
|
1067
|
-
/**
|
|
1029
|
+
/**
|
|
1030
|
+
* {@inheritDoc Chain.sendMessage}
|
|
1031
|
+
* @throws {@link CCIPWalletInvalidError} if wallet is not a valid Signer
|
|
1032
|
+
*/
|
|
1068
1033
|
async sendMessage(opts: Parameters<Chain['sendMessage']>[0]): Promise<CCIPRequest> {
|
|
1069
1034
|
const wallet = opts.wallet
|
|
1070
1035
|
if (!isSigner(wallet)) throw new CCIPWalletInvalidError(wallet)
|
|
@@ -1075,27 +1040,37 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
1075
1040
|
let sendTx: TransactionRequest = txs.transactions[txs.transactions.length - 1]!
|
|
1076
1041
|
|
|
1077
1042
|
// approve all tokens (including feeToken, if needed) in parallel
|
|
1078
|
-
let nonce = await this.provider.getTransactionCount(sender)
|
|
1079
1043
|
const responses = await Promise.all(
|
|
1080
1044
|
approveTxs.map(async (tx: TransactionRequest) => {
|
|
1081
|
-
tx.nonce =
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1045
|
+
tx.nonce = await this.nextNonce(sender)
|
|
1046
|
+
try {
|
|
1047
|
+
tx = await wallet.populateTransaction(tx)
|
|
1048
|
+
tx.from = undefined
|
|
1049
|
+
const response = await submitTransaction(wallet, tx, this.provider)
|
|
1050
|
+
this.logger.debug('approve =>', response.hash)
|
|
1051
|
+
return response
|
|
1052
|
+
} catch (err) {
|
|
1053
|
+
this.nonces[sender]!--
|
|
1054
|
+
throw err
|
|
1055
|
+
}
|
|
1087
1056
|
}),
|
|
1088
1057
|
)
|
|
1089
1058
|
if (responses.length) await responses[responses.length - 1]!.wait(1, 60_000) // wait last tx nonce to be mined
|
|
1090
1059
|
|
|
1091
|
-
sendTx.nonce =
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1060
|
+
sendTx.nonce = await this.nextNonce(sender)
|
|
1061
|
+
let response
|
|
1062
|
+
try {
|
|
1063
|
+
// sendTx.gasLimit = await this.provider.estimateGas(sendTx)
|
|
1064
|
+
sendTx = await wallet.populateTransaction(sendTx)
|
|
1065
|
+
sendTx.from = undefined // some signers don't like receiving pre-populated `from`
|
|
1066
|
+
response = await submitTransaction(wallet, sendTx, this.provider)
|
|
1067
|
+
} catch (err) {
|
|
1068
|
+
this.nonces[sender]!--
|
|
1069
|
+
throw err
|
|
1070
|
+
}
|
|
1096
1071
|
this.logger.debug('ccipSend =>', response.hash)
|
|
1097
|
-
await response.wait(1, 60_000)
|
|
1098
|
-
return (await this.getMessagesInTx(await this.getTransaction(
|
|
1072
|
+
const tx = (await response.wait(1, 60_000))!
|
|
1073
|
+
return (await this.getMessagesInTx(await this.getTransaction(tx)))[0]!
|
|
1099
1074
|
}
|
|
1100
1075
|
|
|
1101
1076
|
/** {@inheritDoc Chain.getOffchainTokenData} */
|
|
@@ -1104,32 +1079,70 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
1104
1079
|
}
|
|
1105
1080
|
|
|
1106
1081
|
/**
|
|
1107
|
-
* {@inheritDoc Chain.
|
|
1082
|
+
* {@inheritDoc Chain.generateUnsignedExecute}
|
|
1108
1083
|
* @returns array containing one unsigned `manuallyExecute` TransactionRequest object
|
|
1084
|
+
* @throws {@link CCIPVersionUnsupportedError} if OffRamp version is not supported
|
|
1109
1085
|
*/
|
|
1110
|
-
async
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1086
|
+
async generateUnsignedExecute(
|
|
1087
|
+
opts: Parameters<Chain['generateUnsignedExecute']>[0],
|
|
1088
|
+
): Promise<UnsignedEVMTx> {
|
|
1089
|
+
let input: ExecutionInput, offRamp: string
|
|
1090
|
+
if (!('input' in opts)) {
|
|
1091
|
+
if (!this.apiClient) throw new CCIPApiClientNotAvailableError()
|
|
1092
|
+
;({ offRamp, ...input } = await this.apiClient.getExecutionInput(opts.messageId))
|
|
1093
|
+
} else {
|
|
1094
|
+
;({ offRamp, input } = opts)
|
|
1095
|
+
}
|
|
1096
|
+
if ('verifications' in input) {
|
|
1097
|
+
const contract = new Contract(
|
|
1098
|
+
offRamp,
|
|
1099
|
+
interfaces.OffRamp_v2_0,
|
|
1100
|
+
this.provider,
|
|
1101
|
+
) as unknown as TypedContract<typeof OffRamp_2_0_ABI>
|
|
1102
|
+
|
|
1103
|
+
const message = decodeMessageV1(input.encodedMessage)
|
|
1104
|
+
const messageId = keccak256(input.encodedMessage)
|
|
1105
|
+
// `execute` doesn't revert on failure, so we need to estimate using `executeSingleMessage`
|
|
1106
|
+
const txGasLimit = await contract.executeSingleMessage.estimateGas(
|
|
1107
|
+
{
|
|
1108
|
+
...message,
|
|
1109
|
+
executionGasLimit: BigInt(message.executionGasLimit),
|
|
1110
|
+
ccipReceiveGasLimit: BigInt(message.ccipReceiveGasLimit),
|
|
1111
|
+
finality: BigInt(message.finality),
|
|
1112
|
+
},
|
|
1113
|
+
messageId,
|
|
1114
|
+
input.verifications.map(({ destAddress }) => destAddress),
|
|
1115
|
+
input.verifications.map(({ ccvData }) => hexlify(ccvData)),
|
|
1116
|
+
BigInt(opts.gasLimit ?? 0),
|
|
1117
|
+
{ from: offRamp }, // internal method
|
|
1118
|
+
)
|
|
1119
|
+
const execTx = await contract.execute.populateTransaction(
|
|
1120
|
+
input.encodedMessage,
|
|
1121
|
+
input.verifications.map(({ destAddress }) => destAddress),
|
|
1122
|
+
input.verifications.map(({ ccvData }) => hexlify(ccvData)),
|
|
1123
|
+
BigInt(opts.gasLimit ?? 0),
|
|
1124
|
+
)
|
|
1125
|
+
execTx.gasLimit = txGasLimit + 40000n // plus `execute`'s overhead
|
|
1126
|
+
return { family: ChainFamily.EVM, transactions: [execTx] }
|
|
1127
|
+
}
|
|
1116
1128
|
|
|
1117
1129
|
let manualExecTx
|
|
1118
|
-
const
|
|
1130
|
+
const [_, version] = await this.typeAndVersion(offRamp)
|
|
1131
|
+
const offchainTokenData = input.offchainTokenData.map(encodeEVMOffchainTokenData)
|
|
1119
1132
|
|
|
1120
1133
|
switch (version) {
|
|
1121
1134
|
case CCIPVersion.V1_2: {
|
|
1122
1135
|
const contract = new Contract(
|
|
1123
1136
|
offRamp,
|
|
1124
|
-
|
|
1137
|
+
interfaces.EVM2EVMOffRamp_v1_2,
|
|
1125
1138
|
this.provider,
|
|
1126
1139
|
) as unknown as TypedContract<typeof EVM2EVMOffRamp_1_2_ABI>
|
|
1127
1140
|
const gasOverride = BigInt(opts.gasLimit ?? 0)
|
|
1128
1141
|
manualExecTx = await contract.manuallyExecute.populateTransaction(
|
|
1129
1142
|
{
|
|
1130
|
-
...
|
|
1131
|
-
proofs:
|
|
1132
|
-
messages: [
|
|
1143
|
+
...input,
|
|
1144
|
+
proofs: input.proofs.map((d) => hexlify(d)),
|
|
1145
|
+
messages: [input.message as CCIPMessage<typeof CCIPVersion.V1_2>],
|
|
1133
1146
|
offchainTokenData: [offchainTokenData],
|
|
1134
1147
|
},
|
|
1135
1148
|
[gasOverride],
|
|
@@ -1139,20 +1152,20 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
1139
1152
|
case CCIPVersion.V1_5: {
|
|
1140
1153
|
const contract = new Contract(
|
|
1141
1154
|
offRamp,
|
|
1142
|
-
|
|
1155
|
+
interfaces.EVM2EVMOffRamp_v1_5,
|
|
1143
1156
|
this.provider,
|
|
1144
1157
|
) as unknown as TypedContract<typeof EVM2EVMOffRamp_1_5_ABI>
|
|
1145
1158
|
manualExecTx = await contract.manuallyExecute.populateTransaction(
|
|
1146
1159
|
{
|
|
1147
|
-
...
|
|
1148
|
-
proofs:
|
|
1149
|
-
messages: [
|
|
1160
|
+
...input,
|
|
1161
|
+
proofs: input.proofs.map((d) => hexlify(d)),
|
|
1162
|
+
messages: [input.message as CCIPMessage<typeof CCIPVersion.V1_5>],
|
|
1150
1163
|
offchainTokenData: [offchainTokenData],
|
|
1151
1164
|
},
|
|
1152
1165
|
[
|
|
1153
1166
|
{
|
|
1154
1167
|
receiverExecutionGasLimit: BigInt(opts.gasLimit ?? 0),
|
|
1155
|
-
tokenGasOverrides:
|
|
1168
|
+
tokenGasOverrides: input.message.tokenAmounts.map(() =>
|
|
1156
1169
|
BigInt(opts.tokensGasLimit ?? opts.gasLimit ?? 0),
|
|
1157
1170
|
),
|
|
1158
1171
|
},
|
|
@@ -1162,30 +1175,32 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
1162
1175
|
}
|
|
1163
1176
|
case CCIPVersion.V1_6: {
|
|
1164
1177
|
// normalize message
|
|
1165
|
-
const
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1178
|
+
const senderBytes = getAddressBytes(input.message.sender)
|
|
1179
|
+
// Addresses ≤32 bytes (EVM 20B, Aptos/Solana/Sui 32B) are zero-padded to 32 bytes;
|
|
1180
|
+
// Addresses >32 bytes (e.g., TON 36B) are used as raw bytes without padding
|
|
1181
|
+
const sender =
|
|
1182
|
+
senderBytes.length <= 32 ? zeroPadValue(senderBytes, 32) : hexlify(senderBytes)
|
|
1183
|
+
const tokenAmounts = (input.message as CCIPMessage_V1_6_EVM).tokenAmounts.map((ta) => ({
|
|
1184
|
+
...ta,
|
|
1185
|
+
sourcePoolAddress: zeroPadValue(getAddressBytes(ta.sourcePoolAddress), 32),
|
|
1186
|
+
extraData: hexlify(getDataBytes(ta.extraData)),
|
|
1187
|
+
}))
|
|
1173
1188
|
const message = {
|
|
1174
|
-
...(
|
|
1189
|
+
...(input.message as CCIPMessage_V1_6_EVM),
|
|
1175
1190
|
sender,
|
|
1176
1191
|
tokenAmounts,
|
|
1177
1192
|
}
|
|
1178
1193
|
const contract = new Contract(
|
|
1179
1194
|
offRamp,
|
|
1180
|
-
|
|
1195
|
+
interfaces.OffRamp_v1_6,
|
|
1181
1196
|
this.provider,
|
|
1182
1197
|
) as unknown as TypedContract<typeof OffRamp_1_6_ABI>
|
|
1183
1198
|
manualExecTx = await contract.manuallyExecute.populateTransaction(
|
|
1184
1199
|
[
|
|
1185
1200
|
{
|
|
1186
|
-
...
|
|
1187
|
-
proofs:
|
|
1188
|
-
sourceChainSelector:
|
|
1201
|
+
...input,
|
|
1202
|
+
proofs: input.proofs.map((p) => hexlify(p)),
|
|
1203
|
+
sourceChainSelector: input.message.sourceChainSelector,
|
|
1189
1204
|
messages: [
|
|
1190
1205
|
{
|
|
1191
1206
|
...message,
|
|
@@ -1205,7 +1220,7 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
1205
1220
|
[
|
|
1206
1221
|
{
|
|
1207
1222
|
receiverExecutionGasLimit: BigInt(opts.gasLimit ?? 0),
|
|
1208
|
-
tokenGasOverrides:
|
|
1223
|
+
tokenGasOverrides: input.message.tokenAmounts.map(() =>
|
|
1209
1224
|
BigInt(opts.tokensGasLimit ?? opts.gasLimit ?? 0),
|
|
1210
1225
|
),
|
|
1211
1226
|
},
|
|
@@ -1220,19 +1235,29 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
1220
1235
|
return { family: ChainFamily.EVM, transactions: [manualExecTx] }
|
|
1221
1236
|
}
|
|
1222
1237
|
|
|
1223
|
-
/**
|
|
1224
|
-
|
|
1238
|
+
/**
|
|
1239
|
+
* {@inheritDoc Chain.execute}
|
|
1240
|
+
* @throws {@link CCIPWalletInvalidError} if wallet is not a valid Signer
|
|
1241
|
+
* @throws {@link CCIPExecTxNotConfirmedError} if execution transaction fails to confirm
|
|
1242
|
+
* @throws {@link CCIPExecTxRevertedError} if execution transaction reverts
|
|
1243
|
+
*/
|
|
1244
|
+
async execute(opts: Parameters<Chain['execute']>[0]) {
|
|
1225
1245
|
const wallet = opts.wallet
|
|
1226
1246
|
if (!isSigner(wallet)) throw new CCIPWalletInvalidError(wallet)
|
|
1227
1247
|
|
|
1228
|
-
const unsignedTxs = await this.
|
|
1248
|
+
const unsignedTxs = await this.generateUnsignedExecute({
|
|
1229
1249
|
...opts,
|
|
1230
1250
|
payer: await wallet.getAddress(),
|
|
1231
1251
|
})
|
|
1232
|
-
|
|
1233
|
-
unsignedTx
|
|
1234
|
-
|
|
1252
|
+
|
|
1253
|
+
const unsignedTx: TransactionRequest = unsignedTxs.transactions[0]!
|
|
1254
|
+
unsignedTx.nonce = await this.nextNonce(await wallet.getAddress())
|
|
1255
|
+
const populatedTx = await wallet.populateTransaction(unsignedTx)
|
|
1256
|
+
populatedTx.from = undefined // some signers don't like receiving pre-populated `from`
|
|
1257
|
+
|
|
1258
|
+
const response = await submitTransaction(wallet, populatedTx, this.provider)
|
|
1235
1259
|
this.logger.debug('manuallyExecute =>', response.hash)
|
|
1260
|
+
|
|
1236
1261
|
const receipt = await response.wait(1, 60_000)
|
|
1237
1262
|
if (!receipt?.hash) throw new CCIPExecTxNotConfirmedError(response.hash)
|
|
1238
1263
|
if (!receipt.status) throw new CCIPExecTxRevertedError(response.hash)
|
|
@@ -1272,7 +1297,10 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
1272
1297
|
return res as string[]
|
|
1273
1298
|
}
|
|
1274
1299
|
|
|
1275
|
-
/**
|
|
1300
|
+
/**
|
|
1301
|
+
* {@inheritDoc Chain.getRegistryTokenConfig}
|
|
1302
|
+
* @throws {@link CCIPTokenNotConfiguredError} if token is not configured in registry
|
|
1303
|
+
*/
|
|
1276
1304
|
async getRegistryTokenConfig(
|
|
1277
1305
|
registry: string,
|
|
1278
1306
|
token: string,
|
|
@@ -1301,8 +1329,8 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
1301
1329
|
}
|
|
1302
1330
|
}
|
|
1303
1331
|
|
|
1304
|
-
/** {@inheritDoc Chain.
|
|
1305
|
-
async
|
|
1332
|
+
/** {@inheritDoc Chain.getTokenPoolConfig} */
|
|
1333
|
+
async getTokenPoolConfig(tokenPool: string): Promise<{
|
|
1306
1334
|
token: string
|
|
1307
1335
|
router: string
|
|
1308
1336
|
typeAndVersion: string
|
|
@@ -1387,23 +1415,28 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
1387
1415
|
return Promise.all([supportedChains, remotePools, remoteInfo]).then(
|
|
1388
1416
|
([supportedChains, remotePools, remoteInfo]) =>
|
|
1389
1417
|
Object.fromEntries(
|
|
1390
|
-
supportedChains.map(
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1418
|
+
supportedChains.map((chain, i) => {
|
|
1419
|
+
const remoteTokenRaw = remoteInfo[i]![0]
|
|
1420
|
+
if (!remoteTokenRaw || remoteTokenRaw.match(/^(0x)?0*$/))
|
|
1421
|
+
throw new CCIPTokenPoolChainConfigNotFoundError(tokenPool, tokenPool, chain.name)
|
|
1422
|
+
return [
|
|
1423
|
+
chain.name,
|
|
1424
|
+
{
|
|
1425
|
+
remoteToken: decodeAddress(remoteTokenRaw, chain.family),
|
|
1426
|
+
remotePools: remotePools[i]!.map((pool) => decodeAddress(pool, chain.family)),
|
|
1427
|
+
inboundRateLimiterState: remoteInfo[i]![1].isEnabled ? remoteInfo[i]![1] : null,
|
|
1428
|
+
outboundRateLimiterState: remoteInfo[i]![2].isEnabled ? remoteInfo[i]![2] : null,
|
|
1429
|
+
},
|
|
1430
|
+
] as const
|
|
1431
|
+
}),
|
|
1402
1432
|
),
|
|
1403
1433
|
)
|
|
1404
1434
|
}
|
|
1405
1435
|
|
|
1406
|
-
/**
|
|
1436
|
+
/**
|
|
1437
|
+
* {@inheritDoc Chain.getFeeTokens}
|
|
1438
|
+
* @throws {@link CCIPVersionUnsupportedError} if OnRamp version is not supported
|
|
1439
|
+
*/
|
|
1407
1440
|
async getFeeTokens(router: string) {
|
|
1408
1441
|
const onRamp = await this._getSomeOnRampFor(router)
|
|
1409
1442
|
const [_, version] = await this.typeAndVersion(onRamp)
|
|
@@ -1456,6 +1489,64 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
1456
1489
|
)
|
|
1457
1490
|
}
|
|
1458
1491
|
|
|
1492
|
+
/** {@inheritDoc Chain.getVerifications} */
|
|
1493
|
+
override async getVerifications(
|
|
1494
|
+
opts: Parameters<Chain['getVerifications']>[0],
|
|
1495
|
+
): Promise<CCIPVerifications> {
|
|
1496
|
+
const { offRamp, request } = opts
|
|
1497
|
+
if (request.lane.version >= CCIPVersion.V2_0) {
|
|
1498
|
+
const message = request.message as CCIPMessage_V2_0
|
|
1499
|
+
if (!message.encodedMessage)
|
|
1500
|
+
throw new CCIPNotImplementedError(`CCIPAPIClient getMessageById v2 encodedMessage`)
|
|
1501
|
+
const contract = new Contract(
|
|
1502
|
+
offRamp,
|
|
1503
|
+
interfaces.OffRamp_v2_0,
|
|
1504
|
+
this.provider,
|
|
1505
|
+
) as unknown as TypedContract<typeof OffRamp_2_0_ABI>
|
|
1506
|
+
const ccvs = await contract.getCCVsForMessage(message.encodedMessage)
|
|
1507
|
+
const [requiredCCVs, optionalCCVs, optionalThreshold] = ccvs.map(
|
|
1508
|
+
resultToObject,
|
|
1509
|
+
) as unknown as CleanAddressable<typeof ccvs>
|
|
1510
|
+
const verificationPolicy = {
|
|
1511
|
+
requiredCCVs,
|
|
1512
|
+
optionalCCVs,
|
|
1513
|
+
optionalThreshold: Number(optionalThreshold),
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
if (this.apiClient) {
|
|
1517
|
+
const apiRes = await this.apiClient.getMessageById(request.message.messageId)
|
|
1518
|
+
if ('verifiers' in apiRes.message) {
|
|
1519
|
+
const verifiers = apiRes.message.verifiers as {
|
|
1520
|
+
items: {
|
|
1521
|
+
destAddress: string
|
|
1522
|
+
sourceAddress: string
|
|
1523
|
+
verification: { data: string; timestamp: string }
|
|
1524
|
+
}[]
|
|
1525
|
+
}
|
|
1526
|
+
return {
|
|
1527
|
+
verificationPolicy,
|
|
1528
|
+
verifications: verifiers.items.map((item) => ({
|
|
1529
|
+
destAddress: item.destAddress,
|
|
1530
|
+
sourceAddress: item.sourceAddress,
|
|
1531
|
+
ccvData: item.verification.data,
|
|
1532
|
+
timestamp: new Date(item.verification.timestamp).getTime() / 1e3,
|
|
1533
|
+
})),
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
|
|
1538
|
+
const url = `${CCV_INDEXER_URL}/v1/verifierresults/${request.message.messageId}`
|
|
1539
|
+
const res = await fetch(url)
|
|
1540
|
+
const json = await res.json()
|
|
1541
|
+
return json as CCIPVerifications
|
|
1542
|
+
} else if (request.lane.version < CCIPVersion.V1_6) {
|
|
1543
|
+
// v1.2..v1.5 EVM (only) have separate CommitStore
|
|
1544
|
+
opts.offRamp = await this.getCommitStoreForOffRamp(opts.offRamp)
|
|
1545
|
+
}
|
|
1546
|
+
// fallback <=v1.6
|
|
1547
|
+
return super.getVerifications(opts)
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1459
1550
|
/** {@inheritDoc Chain.getExecutionReceipts} */
|
|
1460
1551
|
override async *getExecutionReceipts(
|
|
1461
1552
|
opts: Parameters<Chain['getExecutionReceipts']>[0],
|
|
@@ -1475,10 +1566,14 @@ export class EVMChain extends Chain<typeof ChainFamily.EVM> {
|
|
|
1475
1566
|
// onlyFallback: false,
|
|
1476
1567
|
}
|
|
1477
1568
|
} else /* >= V1.6 */ {
|
|
1569
|
+
const topicHash =
|
|
1570
|
+
version === CCIPVersion.V1_6
|
|
1571
|
+
? interfaces.OffRamp_v1_6.getEvent('ExecutionStateChanged')!.topicHash
|
|
1572
|
+
: interfaces.OffRamp_v2_0.getEvent('ExecutionStateChanged')!.topicHash
|
|
1478
1573
|
opts_ = {
|
|
1479
1574
|
...opts,
|
|
1480
1575
|
topics: [
|
|
1481
|
-
|
|
1576
|
+
topicHash,
|
|
1482
1577
|
sourceChainSelector ? toBeHex(sourceChainSelector, 32) : null,
|
|
1483
1578
|
null,
|
|
1484
1579
|
messageId ?? null,
|