@chainlink/ccip-sdk 0.90.2 → 0.91.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 +35 -26
- package/dist/aptos/exec.d.ts +4 -5
- package/dist/aptos/exec.d.ts.map +1 -1
- package/dist/aptos/exec.js +5 -14
- package/dist/aptos/exec.js.map +1 -1
- package/dist/aptos/hasher.d.ts +18 -0
- package/dist/aptos/hasher.d.ts.map +1 -1
- package/dist/aptos/hasher.js +18 -0
- package/dist/aptos/hasher.js.map +1 -1
- package/dist/aptos/index.d.ts +127 -28
- package/dist/aptos/index.d.ts.map +1 -1
- package/dist/aptos/index.js +199 -70
- package/dist/aptos/index.js.map +1 -1
- package/dist/aptos/logs.d.ts +18 -0
- package/dist/aptos/logs.d.ts.map +1 -1
- package/dist/aptos/logs.js +21 -3
- package/dist/aptos/logs.js.map +1 -1
- package/dist/aptos/send.d.ts +22 -5
- package/dist/aptos/send.d.ts.map +1 -1
- package/dist/aptos/send.js +23 -15
- package/dist/aptos/send.js.map +1 -1
- package/dist/aptos/token.d.ts +6 -0
- package/dist/aptos/token.d.ts.map +1 -1
- package/dist/aptos/token.js +6 -0
- package/dist/aptos/token.js.map +1 -1
- package/dist/aptos/types.d.ts +16 -1
- package/dist/aptos/types.d.ts.map +1 -1
- package/dist/aptos/types.js +13 -0
- package/dist/aptos/types.js.map +1 -1
- package/dist/aptos/utils.d.ts +1 -1
- package/dist/aptos/utils.js +1 -1
- package/dist/chain.d.ts +185 -99
- package/dist/chain.d.ts.map +1 -1
- package/dist/chain.js +38 -15
- package/dist/chain.js.map +1 -1
- package/dist/commits.d.ts +4 -10
- package/dist/commits.d.ts.map +1 -1
- package/dist/commits.js +2 -1
- package/dist/commits.js.map +1 -1
- package/dist/evm/const.d.ts +5 -0
- package/dist/evm/const.d.ts.map +1 -1
- package/dist/evm/const.js +5 -0
- package/dist/evm/const.js.map +1 -1
- package/dist/evm/errors.d.ts +5 -0
- package/dist/evm/errors.d.ts.map +1 -1
- package/dist/evm/errors.js +6 -1
- package/dist/evm/errors.js.map +1 -1
- package/dist/evm/hasher.d.ts +16 -2
- package/dist/evm/hasher.d.ts.map +1 -1
- package/dist/evm/hasher.js +17 -3
- package/dist/evm/hasher.js.map +1 -1
- package/dist/evm/index.d.ts +176 -31
- package/dist/evm/index.d.ts.map +1 -1
- package/dist/evm/index.js +312 -154
- package/dist/evm/index.js.map +1 -1
- package/dist/evm/logs.d.ts +20 -0
- package/dist/evm/logs.d.ts.map +1 -0
- package/dist/evm/logs.js +194 -0
- package/dist/evm/logs.js.map +1 -0
- package/dist/evm/messages.d.ts +11 -2
- package/dist/evm/messages.d.ts.map +1 -1
- package/dist/evm/messages.js +4 -2
- package/dist/evm/messages.js.map +1 -1
- package/dist/evm/offchain.d.ts +7 -2
- package/dist/evm/offchain.d.ts.map +1 -1
- package/dist/evm/offchain.js +12 -7
- package/dist/evm/offchain.js.map +1 -1
- package/dist/execution.d.ts +19 -62
- package/dist/execution.d.ts.map +1 -1
- package/dist/execution.js +28 -31
- package/dist/execution.js.map +1 -1
- package/dist/extra-args.d.ts +35 -5
- package/dist/extra-args.d.ts.map +1 -1
- package/dist/extra-args.js +10 -5
- package/dist/extra-args.js.map +1 -1
- package/dist/gas.d.ts +6 -8
- package/dist/gas.d.ts.map +1 -1
- package/dist/gas.js +7 -9
- package/dist/gas.js.map +1 -1
- package/dist/hasher/common.d.ts +3 -2
- package/dist/hasher/common.d.ts.map +1 -1
- package/dist/hasher/common.js +2 -2
- package/dist/hasher/common.js.map +1 -1
- package/dist/hasher/hasher.d.ts +8 -2
- package/dist/hasher/hasher.d.ts.map +1 -1
- package/dist/hasher/hasher.js +8 -3
- package/dist/hasher/hasher.js.map +1 -1
- package/dist/hasher/merklemulti.d.ts +11 -9
- package/dist/hasher/merklemulti.d.ts.map +1 -1
- package/dist/hasher/merklemulti.js +17 -16
- package/dist/hasher/merklemulti.js.map +1 -1
- package/dist/index.d.ts +16 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -7
- package/dist/index.js.map +1 -1
- package/dist/requests.d.ts +39 -25
- package/dist/requests.d.ts.map +1 -1
- package/dist/requests.js +42 -35
- package/dist/requests.js.map +1 -1
- package/dist/selectors.d.ts +1 -1
- package/dist/solana/cleanup.d.ts +14 -10
- package/dist/solana/cleanup.d.ts.map +1 -1
- package/dist/solana/cleanup.js +35 -33
- package/dist/solana/cleanup.js.map +1 -1
- package/dist/solana/exec.d.ts +19 -11
- package/dist/solana/exec.d.ts.map +1 -1
- package/dist/solana/exec.js +86 -163
- package/dist/solana/exec.js.map +1 -1
- package/dist/solana/hasher.d.ts +7 -2
- package/dist/solana/hasher.d.ts.map +1 -1
- package/dist/solana/hasher.js +7 -2
- package/dist/solana/hasher.js.map +1 -1
- package/dist/solana/index.d.ts +202 -84
- package/dist/solana/index.d.ts.map +1 -1
- package/dist/solana/index.js +367 -252
- package/dist/solana/index.js.map +1 -1
- package/dist/solana/offchain.d.ts +8 -18
- package/dist/solana/offchain.d.ts.map +1 -1
- package/dist/solana/offchain.js +29 -83
- package/dist/solana/offchain.js.map +1 -1
- package/dist/solana/patchBorsh.d.ts +5 -1
- package/dist/solana/patchBorsh.d.ts.map +1 -1
- package/dist/solana/patchBorsh.js +57 -46
- package/dist/solana/patchBorsh.js.map +1 -1
- package/dist/solana/send.d.ts +28 -10
- package/dist/solana/send.d.ts.map +1 -1
- package/dist/solana/send.js +44 -77
- package/dist/solana/send.js.map +1 -1
- package/dist/solana/types.d.ts +22 -1
- package/dist/solana/types.d.ts.map +1 -1
- package/dist/solana/types.js +12 -1
- package/dist/solana/types.js.map +1 -1
- package/dist/solana/utils.d.ts +58 -4
- package/dist/solana/utils.d.ts.map +1 -1
- package/dist/solana/utils.js +110 -7
- package/dist/solana/utils.js.map +1 -1
- package/dist/sui/hasher.d.ts +18 -0
- package/dist/sui/hasher.d.ts.map +1 -1
- package/dist/sui/hasher.js +18 -0
- package/dist/sui/hasher.js.map +1 -1
- package/dist/sui/index.d.ts +99 -12
- package/dist/sui/index.d.ts.map +1 -1
- package/dist/sui/index.js +108 -19
- package/dist/sui/index.js.map +1 -1
- package/dist/sui/types.d.ts +6 -0
- package/dist/sui/types.d.ts.map +1 -1
- package/dist/sui/types.js +5 -0
- package/dist/sui/types.js.map +1 -1
- package/dist/supported-chains.d.ts +2 -1
- package/dist/supported-chains.d.ts.map +1 -1
- package/dist/supported-chains.js.map +1 -1
- package/dist/types.d.ts +127 -16
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +18 -0
- package/dist/types.js.map +1 -1
- package/dist/utils.d.ts +67 -46
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +143 -21
- package/dist/utils.js.map +1 -1
- package/package.json +13 -9
- package/src/aptos/exec.ts +7 -18
- package/src/aptos/hasher.ts +18 -0
- package/src/aptos/index.ts +288 -110
- package/src/aptos/logs.ts +21 -3
- package/src/aptos/send.ts +25 -22
- package/src/aptos/token.ts +6 -0
- package/src/aptos/types.ts +26 -2
- package/src/aptos/utils.ts +1 -1
- package/src/chain.ts +243 -108
- package/src/commits.ts +6 -7
- package/src/evm/const.ts +5 -0
- package/src/evm/errors.ts +6 -1
- package/src/evm/hasher.ts +20 -4
- package/src/evm/index.ts +416 -214
- package/src/evm/logs.ts +255 -0
- package/src/evm/messages.ts +11 -5
- package/src/evm/offchain.ts +13 -4
- package/src/execution.ts +40 -32
- package/src/extra-args.ts +38 -6
- package/src/gas.ts +7 -9
- package/src/hasher/common.ts +3 -2
- package/src/hasher/hasher.ts +12 -4
- package/src/hasher/merklemulti.ts +17 -16
- package/src/index.ts +29 -23
- package/src/requests.ts +64 -46
- package/src/selectors.ts +1 -1
- package/src/solana/cleanup.ts +49 -34
- package/src/solana/exec.ts +128 -272
- package/src/solana/hasher.ts +13 -4
- package/src/solana/index.ts +483 -356
- package/src/solana/offchain.ts +32 -102
- package/src/solana/patchBorsh.ts +65 -50
- package/src/solana/send.ts +52 -111
- package/src/solana/types.ts +44 -3
- package/src/solana/utils.ts +143 -19
- package/src/sui/hasher.ts +18 -0
- package/src/sui/index.ts +143 -31
- package/src/sui/types.ts +6 -0
- package/src/supported-chains.ts +2 -1
- package/src/types.ts +130 -18
- package/src/utils.ts +168 -26
- package/tsconfig.json +2 -1
package/src/hasher/hasher.ts
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
import { supportedChains } from '../supported-chains.ts'
|
|
2
|
-
import type { CCIPVersion, Lane } from '../types.ts'
|
|
2
|
+
import type { CCIPVersion, Lane, WithLogger } from '../types.ts'
|
|
3
3
|
import { networkInfo } from '../utils.ts'
|
|
4
4
|
import type { LeafHasher } from './common.ts'
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Factory function that returns the right encoder based on the version of the lane.
|
|
8
|
+
* @param lane - Lane configuration.
|
|
9
|
+
* @param ctx - Context object containing logger.
|
|
10
|
+
* @returns Leaf hasher function for the destination chain.
|
|
11
|
+
*/
|
|
12
|
+
export function getLeafHasher<V extends CCIPVersion = CCIPVersion>(
|
|
13
|
+
lane: Lane<V>,
|
|
14
|
+
ctx?: WithLogger,
|
|
15
|
+
): LeafHasher<V> {
|
|
8
16
|
const destFamily = networkInfo(lane.destChainSelector).family
|
|
9
17
|
const chain = supportedChains[destFamily]
|
|
10
18
|
if (!chain) throw new Error(`Unsupported chain family: ${destFamily}`)
|
|
11
|
-
return chain.getDestLeafHasher(lane) as LeafHasher<V>
|
|
19
|
+
return chain.getDestLeafHasher(lane, ctx) as LeafHasher<V>
|
|
12
20
|
}
|
|
@@ -13,12 +13,16 @@ interface SingleLayerProof {
|
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Proof represents a proof data structure with hashes and source flags.
|
|
16
|
-
* @template Hash The hash type.
|
|
17
16
|
*/
|
|
18
17
|
export class Proof {
|
|
19
18
|
hashes: Hash[] = []
|
|
20
19
|
sourceFlags: boolean[] = []
|
|
21
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Creates a new Proof instance.
|
|
23
|
+
* @param hashes - Proof hashes.
|
|
24
|
+
* @param sourceFlags - Source flags indicating leaf vs internal nodes.
|
|
25
|
+
*/
|
|
22
26
|
constructor(hashes: Hash[] = [], sourceFlags: boolean[] = []) {
|
|
23
27
|
this.hashes = hashes
|
|
24
28
|
this.sourceFlags = sourceFlags
|
|
@@ -26,7 +30,7 @@ export class Proof {
|
|
|
26
30
|
|
|
27
31
|
/**
|
|
28
32
|
* Counts the number of source flags that match the given boolean value.
|
|
29
|
-
* @param b The boolean value to count.
|
|
33
|
+
* @param b - The boolean value to count.
|
|
30
34
|
* @returns The count of source flags matching the provided boolean value.
|
|
31
35
|
*/
|
|
32
36
|
countSourceFlags(b: boolean): number {
|
|
@@ -41,9 +45,8 @@ export class Proof {
|
|
|
41
45
|
* It processes the `layer` to generate the next layer of hash values, pairing adjacent values
|
|
42
46
|
* and applying the hashing function provided by the context.
|
|
43
47
|
*
|
|
44
|
-
* @
|
|
45
|
-
* @
|
|
46
|
-
* @returns {[Hash[], Hash[]]} A tuple containing two arrays:
|
|
48
|
+
* @param layer - An array of hash values representing the current layer of the binary tree.
|
|
49
|
+
* @returns A tuple containing two arrays:
|
|
47
50
|
* - The first array contains the original input layer.
|
|
48
51
|
* - The second array contains the next layer of hash values generated by combining pairs of hashes.
|
|
49
52
|
*/
|
|
@@ -65,7 +68,7 @@ function computeNextLayer(layer: Hash[]): readonly [Hash[], Hash[]] {
|
|
|
65
68
|
|
|
66
69
|
/**
|
|
67
70
|
* Calculates the parent index of a given index in a binary tree.
|
|
68
|
-
* @param idx The index for which to calculate the parent index.
|
|
71
|
+
* @param idx - The index for which to calculate the parent index.
|
|
69
72
|
* @returns The parent index.
|
|
70
73
|
*/
|
|
71
74
|
function parentIndex(idx: number): number {
|
|
@@ -74,7 +77,7 @@ function parentIndex(idx: number): number {
|
|
|
74
77
|
|
|
75
78
|
/**
|
|
76
79
|
* Calculates the sibling index of a given index in a binary tree.
|
|
77
|
-
* @param idx The index for which to calculate the sibling index.
|
|
80
|
+
* @param idx - The index for which to calculate the sibling index.
|
|
78
81
|
* @returns The sibling index.
|
|
79
82
|
*/
|
|
80
83
|
function siblingIndex(idx: number): number {
|
|
@@ -83,8 +86,8 @@ function siblingIndex(idx: number): number {
|
|
|
83
86
|
|
|
84
87
|
/**
|
|
85
88
|
* Generates a single-layer Merkle proof for a given set of indices within a layer.
|
|
86
|
-
* @param layer The layer of data for which to generate the proof.
|
|
87
|
-
* @param indices The indices within the layer for which to generate the proof.
|
|
89
|
+
* @param layer - The layer of data for which to generate the proof.
|
|
90
|
+
* @param indices - The indices within the layer for which to generate the proof.
|
|
88
91
|
* @returns A single-layer proof object containing nextIndices, subProof, and sourceFlags.
|
|
89
92
|
*/
|
|
90
93
|
function proveSingleLayer(layer: Hash[], indices: number[]): SingleLayerProof {
|
|
@@ -131,14 +134,13 @@ function proveSingleLayer(layer: Hash[], indices: number[]): SingleLayerProof {
|
|
|
131
134
|
|
|
132
135
|
/**
|
|
133
136
|
* Represents a Merkle Tree data structure.
|
|
134
|
-
* @typeparam Hash The type of hash used in the tree.
|
|
135
137
|
*/
|
|
136
138
|
export class Tree {
|
|
137
139
|
layers: Hash[][]
|
|
138
140
|
|
|
139
141
|
/**
|
|
140
142
|
* Creates a new Merkle Tree using the provided context and leaf hashes.
|
|
141
|
-
* @param leafHashes An array of leaf hashes to construct the tree.
|
|
143
|
+
* @param leafHashes - An array of leaf hashes to construct the tree.
|
|
142
144
|
* @returns A new Merkle Tree instance.
|
|
143
145
|
* @throws Error if there are no leaf hashes provided.
|
|
144
146
|
*/
|
|
@@ -177,7 +179,7 @@ export class Tree {
|
|
|
177
179
|
|
|
178
180
|
/**
|
|
179
181
|
* Generates a Merkle proof for a set of indices in the tree.
|
|
180
|
-
* @param indices The indices for which to generate the proof.
|
|
182
|
+
* @param indices - The indices for which to generate the proof.
|
|
181
183
|
* @returns A proof object containing hashes and source flags.
|
|
182
184
|
*/
|
|
183
185
|
prove(indices: number[]): Proof {
|
|
@@ -197,7 +199,7 @@ export class Tree {
|
|
|
197
199
|
|
|
198
200
|
/**
|
|
199
201
|
* Converts an array of boolean proof flags to a BigNumber where each flag represents a bit.
|
|
200
|
-
* @param proofFlags An array of boolean proof flags.
|
|
202
|
+
* @param proofFlags - An array of boolean proof flags.
|
|
201
203
|
* @returns A BigNumber representing the encoded flags.
|
|
202
204
|
*/
|
|
203
205
|
export function proofFlagsToBits(proofFlags: boolean[]): bigint {
|
|
@@ -216,9 +218,8 @@ export function proofFlagsToBits(proofFlags: boolean[]): bigint {
|
|
|
216
218
|
|
|
217
219
|
/**
|
|
218
220
|
* Verifies and computes the Merkle root hash based on provided leaf hashes and a Merkle proof.
|
|
219
|
-
* @param
|
|
220
|
-
* @param
|
|
221
|
-
* @param proof The Merkle proof containing hashes and source flags.
|
|
221
|
+
* @param leafHashes - An array of leaf hashes.
|
|
222
|
+
* @param proof - The Merkle proof containing hashes and source flags.
|
|
222
223
|
* @returns The computed Merkle root hash.
|
|
223
224
|
*/
|
|
224
225
|
export function verifyComputeRoot(leafHashes: Hash[], proof: Proof): Hash {
|
package/src/index.ts
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
export {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
type TokenInfo,
|
|
10
|
-
type TokenPoolRemote,
|
|
11
|
-
ChainFamily,
|
|
1
|
+
export type {
|
|
2
|
+
Chain,
|
|
3
|
+
ChainGetter,
|
|
4
|
+
ChainStatic,
|
|
5
|
+
LogFilter,
|
|
6
|
+
RateLimiterState,
|
|
7
|
+
TokenInfo,
|
|
8
|
+
TokenPoolRemote,
|
|
12
9
|
} from './chain.ts'
|
|
13
|
-
export { EVMChain } from './evm/index.ts'
|
|
14
10
|
export { calculateManualExecProof, discoverOffRamp } from './execution.ts'
|
|
15
11
|
export {
|
|
16
12
|
type EVMExtraArgsV1,
|
|
@@ -22,30 +18,40 @@ export {
|
|
|
22
18
|
encodeExtraArgs,
|
|
23
19
|
} from './extra-args.ts'
|
|
24
20
|
export { estimateExecGasForRequest } from './gas.ts'
|
|
25
|
-
export {
|
|
26
|
-
decodeMessage,
|
|
27
|
-
fetchAllMessagesInBatch,
|
|
28
|
-
fetchCCIPMessageById,
|
|
29
|
-
fetchCCIPRequestsInTx,
|
|
30
|
-
fetchRequestsForSender,
|
|
31
|
-
sourceToDestTokenAmounts,
|
|
32
|
-
} from './requests.ts'
|
|
33
|
-
export { SolanaChain } from './solana/index.ts'
|
|
34
|
-
export { SuiChain } from './sui/index.ts'
|
|
35
|
-
export { supportedChains } from './supported-chains.ts'
|
|
21
|
+
export { decodeMessage, fetchRequestsForSender, sourceToDestTokenAmounts } from './requests.ts'
|
|
36
22
|
export {
|
|
37
23
|
type AnyMessage,
|
|
38
24
|
type CCIPCommit,
|
|
39
25
|
type CCIPExecution,
|
|
40
26
|
type CCIPMessage,
|
|
41
27
|
type CCIPRequest,
|
|
28
|
+
type ChainTransaction,
|
|
42
29
|
type CommitReport,
|
|
43
30
|
type ExecutionReceipt,
|
|
44
31
|
type ExecutionReport,
|
|
45
32
|
type Lane,
|
|
33
|
+
type Logger,
|
|
46
34
|
type NetworkInfo,
|
|
47
35
|
type OffchainTokenData,
|
|
36
|
+
type WithLogger,
|
|
48
37
|
CCIPVersion,
|
|
49
38
|
ExecutionState,
|
|
50
39
|
} from './types.ts'
|
|
51
40
|
export { bigIntReplacer, bigIntReviver, decodeAddress, getDataBytes, networkInfo } from './utils.ts'
|
|
41
|
+
|
|
42
|
+
// chains
|
|
43
|
+
import { AptosChain } from './aptos/index.ts'
|
|
44
|
+
import { EVMChain } from './evm/index.ts'
|
|
45
|
+
import { SolanaChain } from './solana/index.ts'
|
|
46
|
+
import { SuiChain } from './sui/index.ts'
|
|
47
|
+
import { ChainFamily } from './types.ts'
|
|
48
|
+
export { AptosChain, ChainFamily, EVMChain, SolanaChain, SuiChain }
|
|
49
|
+
// use `supportedChains` to override/register derived classes, if needed
|
|
50
|
+
export { supportedChains } from './supported-chains.ts'
|
|
51
|
+
// import `allSupportedChains` to get them all registered, in tree-shaken environments
|
|
52
|
+
export const allSupportedChains = {
|
|
53
|
+
[ChainFamily.EVM]: EVMChain,
|
|
54
|
+
[ChainFamily.Solana]: SolanaChain,
|
|
55
|
+
[ChainFamily.Aptos]: AptosChain,
|
|
56
|
+
[ChainFamily.Sui]: SuiChain,
|
|
57
|
+
}
|
package/src/requests.ts
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import util from 'util'
|
|
2
|
-
|
|
3
1
|
import { isBytesLike, toBigInt } from 'ethers'
|
|
2
|
+
import type { PickDeep } from 'type-fest'
|
|
4
3
|
import yaml from 'yaml'
|
|
5
4
|
|
|
6
|
-
import {
|
|
7
|
-
type Chain,
|
|
8
|
-
type ChainStatic,
|
|
9
|
-
type ChainTransaction,
|
|
10
|
-
type LogFilter,
|
|
11
|
-
ChainFamily,
|
|
12
|
-
} from './chain.ts'
|
|
5
|
+
import type { Chain, ChainStatic, LogFilter } from './chain.ts'
|
|
13
6
|
import type { EVMChain } from './evm/index.ts'
|
|
14
7
|
import { decodeExtraArgs } from './extra-args.ts'
|
|
15
8
|
import { supportedChains } from './supported-chains.ts'
|
|
16
|
-
import
|
|
17
|
-
|
|
9
|
+
import {
|
|
10
|
+
type CCIPMessage,
|
|
11
|
+
type CCIPRequest,
|
|
12
|
+
type CCIPVersion,
|
|
13
|
+
type ChainTransaction,
|
|
14
|
+
type Log_,
|
|
15
|
+
ChainFamily,
|
|
16
|
+
} from './types.ts'
|
|
17
|
+
import { convertKeysToCamelCase, decodeAddress, leToBigInt, networkInfo, util } from './utils.ts'
|
|
18
18
|
|
|
19
19
|
function decodeJsonMessage(data: Record<string, unknown>) {
|
|
20
20
|
if (!data || typeof data != 'object') throw new Error(`invalid msg: ${util.inspect(data)}`)
|
|
@@ -113,13 +113,15 @@ export function decodeMessage(data: string | Uint8Array | Record<string, unknown
|
|
|
113
113
|
|
|
114
114
|
/**
|
|
115
115
|
* Fetch all CCIP messages in a transaction
|
|
116
|
-
* @param
|
|
117
|
-
* @
|
|
116
|
+
* @param source - Chain
|
|
117
|
+
* @param tx - ChainTransaction to search in
|
|
118
|
+
* @returns CCIP requests (messages) in the transaction (at least one)
|
|
118
119
|
**/
|
|
119
|
-
export async function fetchCCIPRequestsInTx(
|
|
120
|
-
|
|
120
|
+
export async function fetchCCIPRequestsInTx(
|
|
121
|
+
source: Chain,
|
|
122
|
+
tx: ChainTransaction,
|
|
123
|
+
): Promise<CCIPRequest[]> {
|
|
121
124
|
const txHash = tx.hash
|
|
122
|
-
const timestamp = tx.timestamp
|
|
123
125
|
|
|
124
126
|
const requests: CCIPRequest[] = []
|
|
125
127
|
for (const log of tx.logs) {
|
|
@@ -139,7 +141,7 @@ export async function fetchCCIPRequestsInTx(tx: ChainTransaction): Promise<CCIPR
|
|
|
139
141
|
} else {
|
|
140
142
|
lane = await (source as EVMChain).getLaneForOnRamp(log.address)
|
|
141
143
|
}
|
|
142
|
-
requests.push({ lane, message, log, tx
|
|
144
|
+
requests.push({ lane, message, log, tx })
|
|
143
145
|
}
|
|
144
146
|
if (!requests.length) {
|
|
145
147
|
throw new Error(`Could not find any CCIPSendRequested message in tx: ${txHash}`)
|
|
@@ -149,23 +151,21 @@ export async function fetchCCIPRequestsInTx(tx: ChainTransaction): Promise<CCIPR
|
|
|
149
151
|
}
|
|
150
152
|
|
|
151
153
|
/**
|
|
152
|
-
* Fetch a CCIP message by its messageId
|
|
153
|
-
* Can be slow due to having to paginate backwards through logs
|
|
154
|
-
*
|
|
155
|
-
* @param
|
|
156
|
-
* @param
|
|
157
|
-
* @
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
export async function fetchCCIPMessageById(
|
|
154
|
+
* Fetch a CCIP message by its messageId.
|
|
155
|
+
* Can be slow due to having to paginate backwards through logs.
|
|
156
|
+
* @param source - Provider to fetch logs from.
|
|
157
|
+
* @param messageId - MessageId to search for.
|
|
158
|
+
* @param hints - Optional hints for pagination (e.g., `address` for onRamp, `page` for pagination size).
|
|
159
|
+
* @returns CCIPRequest with given messageId.
|
|
160
|
+
*/
|
|
161
|
+
export async function fetchCCIPRequestById(
|
|
161
162
|
source: Chain,
|
|
162
163
|
messageId: string,
|
|
163
|
-
hints?: { page?: number;
|
|
164
|
+
hints?: { page?: number; address?: string },
|
|
164
165
|
): Promise<CCIPRequest> {
|
|
165
166
|
for await (const log of source.getLogs({
|
|
166
|
-
...hints,
|
|
167
|
-
...(hints?.onRamp ? { address: hints.onRamp } : {}),
|
|
168
167
|
topics: ['CCIPSendRequested', 'CCIPMessageSent'],
|
|
168
|
+
...hints,
|
|
169
169
|
})) {
|
|
170
170
|
const message = (source.constructor as ChainStatic).decodeMessage(log)
|
|
171
171
|
if (message?.header.messageId !== messageId) continue
|
|
@@ -173,12 +173,10 @@ export async function fetchCCIPMessageById(
|
|
|
173
173
|
if ('destChainSelector' in message.header) {
|
|
174
174
|
destChainSelector = message.header.destChainSelector
|
|
175
175
|
;[, version] = await source.typeAndVersion(log.address)
|
|
176
|
-
} else if (source.network.family !== ChainFamily.EVM) {
|
|
177
|
-
throw new Error(`Unsupported network family: ${source.network.family}`)
|
|
178
176
|
} else {
|
|
179
177
|
;({ destChainSelector, version } = await (source as EVMChain).getLaneForOnRamp(log.address))
|
|
180
178
|
}
|
|
181
|
-
const tx = await source.getTransaction(log.transactionHash)
|
|
179
|
+
const tx = log.tx ?? (await source.getTransaction(log.transactionHash))
|
|
182
180
|
return {
|
|
183
181
|
lane: {
|
|
184
182
|
sourceChainSelector: source.network.chainSelector,
|
|
@@ -189,7 +187,6 @@ export async function fetchCCIPMessageById(
|
|
|
189
187
|
message,
|
|
190
188
|
log,
|
|
191
189
|
tx,
|
|
192
|
-
timestamp: tx.timestamp,
|
|
193
190
|
}
|
|
194
191
|
}
|
|
195
192
|
throw new Error('Could not find a CCIPSendRequested message with messageId: ' + messageId)
|
|
@@ -198,19 +195,33 @@ export async function fetchCCIPMessageById(
|
|
|
198
195
|
// Number of blocks to expand the search window for logs
|
|
199
196
|
const BLOCK_LOG_WINDOW_SIZE = 5000
|
|
200
197
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
198
|
+
/**
|
|
199
|
+
* Fetches all CCIP messages contained in a given commit batch.
|
|
200
|
+
* @param source - The source chain.
|
|
201
|
+
* @param request - The CCIP request containing lane and message info.
|
|
202
|
+
* @param seqNrRange - Object containing minSeqNr and maxSeqNr for the batch range.
|
|
203
|
+
* @param opts - Optional log filtering parameters.
|
|
204
|
+
* @returns Array of messages in the batch.
|
|
205
|
+
*/
|
|
206
|
+
export async function fetchAllMessagesInBatch<
|
|
207
|
+
C extends Chain,
|
|
208
|
+
R extends PickDeep<
|
|
209
|
+
CCIPRequest,
|
|
210
|
+
'lane' | `log.${'topics' | 'address' | 'blockNumber'}` | 'message.header.sequenceNumber'
|
|
211
|
+
>,
|
|
212
|
+
>(
|
|
213
|
+
source: C,
|
|
204
214
|
request: R,
|
|
205
215
|
{ minSeqNr, maxSeqNr }: { minSeqNr: bigint; maxSeqNr: bigint },
|
|
206
|
-
|
|
216
|
+
opts: Parameters<C['getLogs']>[0] = { page: BLOCK_LOG_WINDOW_SIZE },
|
|
207
217
|
): Promise<R['message'][]> {
|
|
208
218
|
if (minSeqNr === maxSeqNr) return [request.message]
|
|
209
219
|
|
|
210
|
-
const filter
|
|
211
|
-
page:
|
|
220
|
+
const filter = {
|
|
221
|
+
page: BLOCK_LOG_WINDOW_SIZE,
|
|
212
222
|
topics: [request.log.topics[0]],
|
|
213
223
|
address: request.log.address,
|
|
224
|
+
...opts,
|
|
214
225
|
}
|
|
215
226
|
if (request.message.header.sequenceNumber === maxSeqNr) filter.endBlock = request.log.blockNumber
|
|
216
227
|
else
|
|
@@ -219,7 +230,7 @@ export async function fetchAllMessagesInBatch<R extends Omit<CCIPRequest, 'tx' |
|
|
|
219
230
|
request.log.blockNumber -
|
|
220
231
|
Math.ceil(
|
|
221
232
|
(Number(request.message.header.sequenceNumber - minSeqNr) / Number(maxSeqNr - minSeqNr)) *
|
|
222
|
-
|
|
233
|
+
filter.page,
|
|
223
234
|
)
|
|
224
235
|
|
|
225
236
|
const messages: R['message'][] = []
|
|
@@ -270,6 +281,13 @@ export async function fetchAllMessagesInBatch<R extends Omit<CCIPRequest, 'tx' |
|
|
|
270
281
|
return messages
|
|
271
282
|
}
|
|
272
283
|
|
|
284
|
+
/**
|
|
285
|
+
* Fetches CCIP requests originated by a specific sender.
|
|
286
|
+
* @param source - Source chain instance.
|
|
287
|
+
* @param sender - Sender address.
|
|
288
|
+
* @param filter - Log filter options.
|
|
289
|
+
* @returns Async generator of CCIP requests.
|
|
290
|
+
*/
|
|
273
291
|
export async function* fetchRequestsForSender(
|
|
274
292
|
source: Chain,
|
|
275
293
|
sender: string,
|
|
@@ -306,12 +324,12 @@ export async function* fetchRequestsForSender(
|
|
|
306
324
|
}
|
|
307
325
|
|
|
308
326
|
/**
|
|
309
|
-
* Map source `token` to `sourcePoolAddress + destTokenAddress
|
|
310
|
-
* @param source -
|
|
311
|
-
* @param destChainSelector -
|
|
312
|
-
* @param onRamp -
|
|
313
|
-
* @param sourceTokenAmounts -
|
|
314
|
-
* @returns
|
|
327
|
+
* Map source `token` to `sourcePoolAddress + destTokenAddress`.
|
|
328
|
+
* @param source - Source chain.
|
|
329
|
+
* @param destChainSelector - Destination network selector.
|
|
330
|
+
* @param onRamp - Contract address.
|
|
331
|
+
* @param sourceTokenAmounts - Array of token amounts, usually containing `token` and `amount` properties.
|
|
332
|
+
* @returns Array of objects with `sourcePoolAddress`, `destTokenAddress`, and remaining properties.
|
|
315
333
|
*/
|
|
316
334
|
export async function sourceToDestTokenAmounts<S extends { token: string }>(
|
|
317
335
|
source: Chain,
|
package/src/selectors.ts
CHANGED
package/src/solana/cleanup.ts
CHANGED
|
@@ -1,37 +1,46 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { Buffer } from 'buffer'
|
|
2
|
+
|
|
3
|
+
import { type Wallet as AnchorWallet, AnchorProvider, Program } from '@coral-xyz/anchor'
|
|
4
|
+
import {
|
|
5
|
+
type Connection,
|
|
6
|
+
AddressLookupTableProgram,
|
|
7
|
+
PublicKey,
|
|
8
|
+
SystemProgram,
|
|
9
|
+
} from '@solana/web3.js'
|
|
3
10
|
import { dataSlice, hexlify } from 'ethers'
|
|
4
|
-
import
|
|
11
|
+
import { memoize } from 'micro-memoize'
|
|
5
12
|
|
|
6
13
|
import { sleep } from '../utils.ts'
|
|
7
14
|
import { IDL as CCIP_OFFRAMP_IDL } from './idl/1.6.0/CCIP_OFFRAMP.ts'
|
|
8
15
|
import type { SolanaChain } from './index.ts'
|
|
9
|
-
import {
|
|
16
|
+
import type { Wallet } from './types.ts'
|
|
17
|
+
import { simulateAndSendTxs } from './utils.ts'
|
|
18
|
+
import type { WithLogger } from '../types.ts'
|
|
10
19
|
|
|
11
20
|
/**
|
|
12
|
-
* Clean up and recycle buffers and
|
|
13
|
-
*
|
|
14
|
-
* @param
|
|
15
|
-
* @param getLogs - SolanaChain-compatible getLogs function (to scan for Buffers and ALTs)
|
|
16
|
-
* @param opts
|
|
17
|
-
* (513 slots) to pass before closing; by default, we deactivate (if needed)
|
|
18
|
-
*
|
|
21
|
+
* Clean up and recycle buffers and Address Lookup Tables owned by wallet.
|
|
22
|
+
* @param ctx - Context object containing the Solana connection instance and logger.
|
|
23
|
+
* @param wallet - Wallet instance to sign txs.
|
|
24
|
+
* @param getLogs - SolanaChain-compatible getLogs function (to scan for Buffers and ALTs).
|
|
25
|
+
* @param opts - Optional parameters. Set `waitDeactivation` to wait for lookup table deactivation
|
|
26
|
+
* cool down period (513 slots) to pass before closing; by default, we deactivate (if needed)
|
|
27
|
+
* and leave close to be done in the future.
|
|
19
28
|
*/
|
|
20
29
|
export async function cleanUpBuffers(
|
|
21
|
-
|
|
30
|
+
ctx: { connection: Connection } & WithLogger,
|
|
31
|
+
wallet: Wallet,
|
|
22
32
|
getLogs: SolanaChain['getLogs'],
|
|
23
|
-
opts?: {
|
|
33
|
+
opts?: { waitDeactivation?: boolean },
|
|
24
34
|
): Promise<void> {
|
|
25
|
-
const connection =
|
|
26
|
-
|
|
27
|
-
console.debug(
|
|
35
|
+
const { connection, logger = console } = ctx
|
|
36
|
+
logger.debug(
|
|
28
37
|
'Starting cleaning up buffers and lookup tables for account',
|
|
29
38
|
wallet.publicKey.toString(),
|
|
30
39
|
)
|
|
31
40
|
|
|
32
41
|
const seenAccs = new Set<string>()
|
|
33
42
|
const pendingPromises = []
|
|
34
|
-
const getCurrentSlot =
|
|
43
|
+
const getCurrentSlot = memoize(
|
|
35
44
|
async () => {
|
|
36
45
|
let lastErr
|
|
37
46
|
for (let i = 0; i < 10; i++) {
|
|
@@ -39,13 +48,13 @@ export async function cleanUpBuffers(
|
|
|
39
48
|
return await connection.getSlot()
|
|
40
49
|
} catch (err) {
|
|
41
50
|
lastErr = err
|
|
42
|
-
|
|
51
|
+
logger.warn('Failed to get current slot', i, err)
|
|
43
52
|
await sleep(500)
|
|
44
53
|
}
|
|
45
54
|
}
|
|
46
55
|
throw lastErr
|
|
47
56
|
},
|
|
48
|
-
{ maxAge: 1000,
|
|
57
|
+
{ maxAge: 1000, async: true },
|
|
49
58
|
)
|
|
50
59
|
|
|
51
60
|
const closeAlt = async (lookupTable: PublicKey, deactivationSlot: number) => {
|
|
@@ -54,8 +63,8 @@ export async function cleanUpBuffers(
|
|
|
54
63
|
while (!sig) {
|
|
55
64
|
const delta = deactivationSlot + 513 - (await getCurrentSlot())
|
|
56
65
|
if (delta > 0) {
|
|
57
|
-
if (opts?.
|
|
58
|
-
|
|
66
|
+
if (!opts?.waitDeactivation) {
|
|
67
|
+
logger.warn(
|
|
59
68
|
'Skipping: lookup table',
|
|
60
69
|
altAddr,
|
|
61
70
|
'not yet ready for close until',
|
|
@@ -64,7 +73,7 @@ export async function cleanUpBuffers(
|
|
|
64
73
|
)
|
|
65
74
|
return
|
|
66
75
|
}
|
|
67
|
-
|
|
76
|
+
logger.debug(
|
|
68
77
|
'Waiting for slot',
|
|
69
78
|
deactivationSlot + 513,
|
|
70
79
|
'to be reached in',
|
|
@@ -81,14 +90,14 @@ export async function cleanUpBuffers(
|
|
|
81
90
|
lookupTable,
|
|
82
91
|
})
|
|
83
92
|
try {
|
|
84
|
-
sig = await simulateAndSendTxs(
|
|
85
|
-
|
|
93
|
+
sig = await simulateAndSendTxs(ctx, wallet, { instructions: [closeIx] })
|
|
94
|
+
logger.info('🗑️ Closed lookup table', altAddr, ': tx =>', sig)
|
|
86
95
|
} catch (err) {
|
|
87
96
|
const info = await connection.getAddressLookupTable(lookupTable)
|
|
88
97
|
if (!info?.value) break
|
|
89
98
|
else if (info.value.state.deactivationSlot < 2n ** 63n)
|
|
90
99
|
deactivationSlot = Number(info.value.state.deactivationSlot)
|
|
91
|
-
|
|
100
|
+
logger.warn('Failed to close lookup table', altAddr, err)
|
|
92
101
|
}
|
|
93
102
|
}
|
|
94
103
|
}
|
|
@@ -114,7 +123,11 @@ export async function cleanUpBuffers(
|
|
|
114
123
|
.map(({ data }) => Buffer.from(data.subarray(8 + 4, 8 + 4 + 32)))
|
|
115
124
|
|
|
116
125
|
for (const bufferId of bufferIds) {
|
|
117
|
-
const offrampProgram = new Program(
|
|
126
|
+
const offrampProgram = new Program(
|
|
127
|
+
CCIP_OFFRAMP_IDL,
|
|
128
|
+
new PublicKey(log.address),
|
|
129
|
+
new AnchorProvider(connection, wallet as AnchorWallet, { commitment: 'confirmed' }),
|
|
130
|
+
)
|
|
118
131
|
|
|
119
132
|
const [executionReportBuffer] = PublicKey.findProgramAddressSync(
|
|
120
133
|
[Buffer.from('execution_report_buffer'), bufferId, wallet.publicKey.toBuffer()],
|
|
@@ -125,7 +138,7 @@ export async function cleanUpBuffers(
|
|
|
125
138
|
|
|
126
139
|
const accInfo = await connection.getAccountInfo(executionReportBuffer)
|
|
127
140
|
if (!accInfo) {
|
|
128
|
-
|
|
141
|
+
logger.debug(
|
|
129
142
|
'Buffer with bufferId',
|
|
130
143
|
hexlify(bufferId),
|
|
131
144
|
'at',
|
|
@@ -148,7 +161,7 @@ export async function cleanUpBuffers(
|
|
|
148
161
|
.closeExecutionReportBuffer(bufferId)
|
|
149
162
|
.accounts(bufferingAccounts)
|
|
150
163
|
.rpc()
|
|
151
|
-
|
|
164
|
+
logger.info(
|
|
152
165
|
'🗑️ Closed bufferId',
|
|
153
166
|
hexlify(bufferId),
|
|
154
167
|
'at',
|
|
@@ -157,7 +170,7 @@ export async function cleanUpBuffers(
|
|
|
157
170
|
sig,
|
|
158
171
|
)
|
|
159
172
|
} catch (err) {
|
|
160
|
-
|
|
173
|
+
logger.warn(
|
|
161
174
|
'Failed to close bufferId',
|
|
162
175
|
hexlify(bufferId),
|
|
163
176
|
'at',
|
|
@@ -177,9 +190,9 @@ export async function cleanUpBuffers(
|
|
|
177
190
|
const info = await connection.getAddressLookupTable(lookupTable)
|
|
178
191
|
if (!info?.value) {
|
|
179
192
|
alreadyClosed++ // assume we're done when we hit Nth closed ALT; maybe add an option to keep going?
|
|
180
|
-
|
|
193
|
+
logger.debug('Lookup table', lookupTable.toBase58(), 'already closed')
|
|
181
194
|
} else if (info.value.state.authority?.toBase58() !== wallet.publicKey.toBase58()) {
|
|
182
|
-
|
|
195
|
+
logger.debug(
|
|
183
196
|
'Lookup table',
|
|
184
197
|
lookupTable.toBase58(),
|
|
185
198
|
'not owned by us, but by',
|
|
@@ -199,11 +212,13 @@ export async function cleanUpBuffers(
|
|
|
199
212
|
})
|
|
200
213
|
|
|
201
214
|
try {
|
|
202
|
-
const sig = await simulateAndSendTxs(
|
|
203
|
-
|
|
215
|
+
const sig = await simulateAndSendTxs(ctx, wallet, {
|
|
216
|
+
instructions: [deactivateIx],
|
|
217
|
+
})
|
|
218
|
+
logger.info('⤵️ Deactivated lookup table', lookupTable.toBase58(), ': tx =>', sig)
|
|
204
219
|
pendingPromises.push(closeAlt(lookupTable, await getCurrentSlot()))
|
|
205
220
|
} catch (err) {
|
|
206
|
-
|
|
221
|
+
logger.warn('Failed to deactivate lookup table', lookupTable.toBase58(), err)
|
|
207
222
|
}
|
|
208
223
|
}
|
|
209
224
|
break // case
|