@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/solana/utils.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { Buffer } from 'buffer'
|
|
2
|
+
|
|
3
|
+
import { eventDiscriminator } from '@coral-xyz/anchor'
|
|
1
4
|
import {
|
|
2
5
|
type AddressLookupTableAccount,
|
|
3
6
|
type Connection,
|
|
@@ -13,13 +16,35 @@ import {
|
|
|
13
16
|
} from '@solana/web3.js'
|
|
14
17
|
import { type BytesLike, dataLength, dataSlice, hexlify } from 'ethers'
|
|
15
18
|
|
|
16
|
-
import type { Log_ } from '../types.ts'
|
|
19
|
+
import type { Log_, WithLogger } from '../types.ts'
|
|
17
20
|
import { getDataBytes, sleep } from '../utils.ts'
|
|
21
|
+
import type { UnsignedSolanaTx, Wallet } from './types.ts'
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Generates a hex-encoded discriminator for a Solana event.
|
|
25
|
+
* @param eventName - Name of the event.
|
|
26
|
+
* @returns Hex-encoded discriminator string.
|
|
27
|
+
*/
|
|
28
|
+
export function hexDiscriminator(eventName: string): string {
|
|
29
|
+
return hexlify(eventDiscriminator(eventName))
|
|
30
|
+
}
|
|
18
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Converts bytes to a Node.js Buffer.
|
|
34
|
+
* @param bytes - Bytes to convert.
|
|
35
|
+
* @returns Node.js Buffer.
|
|
36
|
+
*/
|
|
19
37
|
export function bytesToBuffer(bytes: BytesLike): Buffer {
|
|
20
38
|
return Buffer.from(getDataBytes(bytes).buffer)
|
|
21
39
|
}
|
|
22
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Waits for a Solana transaction to reach finalized status.
|
|
43
|
+
* @param connection - Solana connection instance.
|
|
44
|
+
* @param signature - Transaction signature to wait for.
|
|
45
|
+
* @param intervalMs - Polling interval in milliseconds.
|
|
46
|
+
* @param maxAttempts - Maximum polling attempts before timeout.
|
|
47
|
+
*/
|
|
23
48
|
export async function waitForFinalization(
|
|
24
49
|
connection: Connection,
|
|
25
50
|
signature: string,
|
|
@@ -39,6 +64,11 @@ export async function waitForFinalization(
|
|
|
39
64
|
throw new Error(`Transaction ${signature} not finalized after timeout`)
|
|
40
65
|
}
|
|
41
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Converts a camelCase string to snake_case.
|
|
69
|
+
* @param str - String to convert.
|
|
70
|
+
* @returns snake_case formatted string.
|
|
71
|
+
*/
|
|
42
72
|
export function camelToSnakeCase(str: string): string {
|
|
43
73
|
return str
|
|
44
74
|
.replace(/([A-Z]+)([A-Z][a-z]|$)/g, (_, p1: string, p2: string) => {
|
|
@@ -52,7 +82,10 @@ export function camelToSnakeCase(str: string): string {
|
|
|
52
82
|
.replace(/^_/, '')
|
|
53
83
|
}
|
|
54
84
|
|
|
55
|
-
type ParsedLog = Pick<Log_, 'topics' | 'index' | 'address' | 'data'> & {
|
|
85
|
+
type ParsedLog = Pick<Log_, 'topics' | 'index' | 'address' | 'data'> & {
|
|
86
|
+
data: string
|
|
87
|
+
level: number
|
|
88
|
+
}
|
|
56
89
|
|
|
57
90
|
/**
|
|
58
91
|
* Utility function to parse Solana logs with proper address and topic extraction.
|
|
@@ -107,6 +140,7 @@ export function parseSolanaLogs(logs: readonly string[]): ParsedLog[] {
|
|
|
107
140
|
index: i,
|
|
108
141
|
address: currentProgram,
|
|
109
142
|
data: logData,
|
|
143
|
+
level: programStack.length,
|
|
110
144
|
})
|
|
111
145
|
}
|
|
112
146
|
}
|
|
@@ -114,6 +148,11 @@ export function parseSolanaLogs(logs: readonly string[]): ParsedLog[] {
|
|
|
114
148
|
return results
|
|
115
149
|
}
|
|
116
150
|
|
|
151
|
+
/**
|
|
152
|
+
* Extracts error information from Solana transaction logs.
|
|
153
|
+
* @param logs_ - Raw log strings or parsed log objects.
|
|
154
|
+
* @returns Parsed error info with program and error details.
|
|
155
|
+
*/
|
|
117
156
|
export function getErrorFromLogs(
|
|
118
157
|
logs_: readonly string[] | readonly Pick<Log_, 'address' | 'index' | 'data' | 'topics'>[] | null,
|
|
119
158
|
): { program: string; [k: string]: string } | undefined {
|
|
@@ -176,17 +215,23 @@ export function getErrorFromLogs(
|
|
|
176
215
|
}
|
|
177
216
|
}
|
|
178
217
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
connection: Connection
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
218
|
+
/**
|
|
219
|
+
* Simulates a Solana transaction to estimate compute units.
|
|
220
|
+
* @param params - Simulation parameters including connection and payer.
|
|
221
|
+
* @returns Simulation result with estimated compute units.
|
|
222
|
+
*/
|
|
223
|
+
export async function simulateTransaction(
|
|
224
|
+
{ connection, logger = console }: { connection: Connection } & WithLogger,
|
|
225
|
+
{
|
|
226
|
+
payerKey,
|
|
227
|
+
computeUnitsOverride,
|
|
228
|
+
...rest
|
|
229
|
+
}: {
|
|
230
|
+
payerKey: PublicKey
|
|
231
|
+
computeUnitsOverride?: number
|
|
232
|
+
addressLookupTableAccounts?: AddressLookupTableAccount[]
|
|
233
|
+
} & ({ instructions: TransactionInstruction[] } | { tx: Transaction | VersionedTransaction }),
|
|
234
|
+
) {
|
|
190
235
|
// Add max compute units for simulation
|
|
191
236
|
const maxComputeUnits = 1_400_000
|
|
192
237
|
const recentBlockhash = '11111111111111111111111111111112'
|
|
@@ -228,7 +273,7 @@ export async function simulateTransaction({
|
|
|
228
273
|
const result = await connection.simulateTransaction(tx, config)
|
|
229
274
|
|
|
230
275
|
if (result.value.err) {
|
|
231
|
-
|
|
276
|
+
logger.debug('Simulation results:', {
|
|
232
277
|
logs: result.value.logs,
|
|
233
278
|
unitsConsumed: result.value.unitsConsumed,
|
|
234
279
|
returnData: result.value.returnData,
|
|
@@ -249,24 +294,103 @@ export async function simulateTransaction({
|
|
|
249
294
|
/**
|
|
250
295
|
* Used as `provider` in anchor's `Program` constructor, to support `.view()` simulations
|
|
251
296
|
* without * requiring a full AnchorProvider with wallet
|
|
252
|
-
* @param
|
|
297
|
+
* @param ctx - Context object containing connection and logger
|
|
253
298
|
* @param feePayer - Fee payer for the simulated transaction
|
|
254
299
|
* @returns Value returned by the simulated method
|
|
255
300
|
*/
|
|
256
301
|
export function simulationProvider(
|
|
257
|
-
connection: Connection,
|
|
302
|
+
ctx: { connection: Connection } & WithLogger,
|
|
258
303
|
feePayer: PublicKey = new PublicKey('11111111111111111111111111111112'),
|
|
259
304
|
) {
|
|
260
305
|
return {
|
|
261
|
-
connection,
|
|
306
|
+
connection: ctx.connection,
|
|
262
307
|
wallet: {
|
|
263
308
|
publicKey: feePayer,
|
|
264
309
|
},
|
|
265
310
|
simulate: async (tx: Transaction | VersionedTransaction, _signers?: Signer[]) =>
|
|
266
|
-
simulateTransaction({
|
|
267
|
-
connection,
|
|
311
|
+
simulateTransaction(ctx, {
|
|
268
312
|
payerKey: feePayer,
|
|
269
313
|
tx,
|
|
270
314
|
}),
|
|
271
315
|
}
|
|
272
316
|
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Sign, simulate, send and confirm as many instructions as possible on each transaction
|
|
320
|
+
* @param ctx - Context object containing connection and logger
|
|
321
|
+
* @param wallet - Wallet to sign and pay for txs
|
|
322
|
+
* @param unsignedTx - instructions to sign and send
|
|
323
|
+
* - instructions - Instructions to send; they may not fit all in a single transaction,
|
|
324
|
+
* in which case they will be split into multiple transactions
|
|
325
|
+
* - mainIndex - Index of the main instruction
|
|
326
|
+
* - lookupTables - lookupTables to be used for main instruction
|
|
327
|
+
* @param computeUnits - max computeUnits limit to be used for main instruction
|
|
328
|
+
* @returns - signature of successful transaction including main instruction
|
|
329
|
+
*/
|
|
330
|
+
export async function simulateAndSendTxs(
|
|
331
|
+
ctx: { connection: Connection } & WithLogger,
|
|
332
|
+
wallet: Wallet,
|
|
333
|
+
{ instructions, mainIndex, lookupTables }: Omit<UnsignedSolanaTx, 'family'>,
|
|
334
|
+
computeUnits?: number,
|
|
335
|
+
): Promise<string> {
|
|
336
|
+
const { connection } = ctx
|
|
337
|
+
let mainHash: string
|
|
338
|
+
for (
|
|
339
|
+
let [start, end] = [0, instructions.length];
|
|
340
|
+
start < instructions.length;
|
|
341
|
+
[start, end] = [end, instructions.length]
|
|
342
|
+
) {
|
|
343
|
+
let computeUnitLimit, lastErr, addressLookupTableAccounts, ixs, includesMain
|
|
344
|
+
do {
|
|
345
|
+
ixs = instructions.slice(start, end)
|
|
346
|
+
includesMain = mainIndex != null && start <= mainIndex && mainIndex < end
|
|
347
|
+
addressLookupTableAccounts = includesMain ? lookupTables : undefined
|
|
348
|
+
|
|
349
|
+
try {
|
|
350
|
+
const simulated =
|
|
351
|
+
(
|
|
352
|
+
await simulateTransaction(ctx, {
|
|
353
|
+
payerKey: wallet.publicKey,
|
|
354
|
+
instructions: ixs,
|
|
355
|
+
addressLookupTableAccounts,
|
|
356
|
+
})
|
|
357
|
+
).unitsConsumed || 0
|
|
358
|
+
|
|
359
|
+
if (simulated <= 200000) {
|
|
360
|
+
computeUnitLimit = undefined
|
|
361
|
+
} else if (!includesMain || computeUnits == null || simulated <= computeUnits) {
|
|
362
|
+
computeUnitLimit = Math.ceil(simulated * 1.1)
|
|
363
|
+
} else {
|
|
364
|
+
throw new Error(
|
|
365
|
+
`Main simulation exceeds specified computeUnits limit. simulated=${simulated}, limit=${computeUnits}`,
|
|
366
|
+
)
|
|
367
|
+
}
|
|
368
|
+
break
|
|
369
|
+
} catch (err) {
|
|
370
|
+
lastErr = err
|
|
371
|
+
end-- // truncate until finding a slice which fits (both computeUnits and tx size limits)
|
|
372
|
+
}
|
|
373
|
+
} while (end > start)
|
|
374
|
+
if (end <= start) throw lastErr
|
|
375
|
+
|
|
376
|
+
const blockhash = await connection.getLatestBlockhash('confirmed')
|
|
377
|
+
const txMsg = new TransactionMessage({
|
|
378
|
+
payerKey: wallet.publicKey,
|
|
379
|
+
recentBlockhash: blockhash.blockhash,
|
|
380
|
+
instructions: [
|
|
381
|
+
...(computeUnitLimit
|
|
382
|
+
? [ComputeBudgetProgram.setComputeUnitLimit({ units: computeUnitLimit })]
|
|
383
|
+
: []),
|
|
384
|
+
...ixs,
|
|
385
|
+
],
|
|
386
|
+
})
|
|
387
|
+
const messageV0 = txMsg.compileToV0Message(addressLookupTableAccounts)
|
|
388
|
+
const tx = new VersionedTransaction(messageV0)
|
|
389
|
+
|
|
390
|
+
const signed = await wallet.signTransaction(tx)
|
|
391
|
+
const signature = await connection.sendTransaction(signed)
|
|
392
|
+
await connection.confirmTransaction({ signature, ...blockhash }, 'confirmed')
|
|
393
|
+
if (includesMain) mainHash = signature
|
|
394
|
+
}
|
|
395
|
+
return mainHash!
|
|
396
|
+
}
|
package/src/sui/hasher.ts
CHANGED
|
@@ -6,6 +6,11 @@ import { type LeafHasher, LEAF_DOMAIN_SEPARATOR } from '../hasher/common.ts'
|
|
|
6
6
|
import { type CCIPMessage, type CCIPMessage_V1_6, CCIPVersion } from '../types.ts'
|
|
7
7
|
import type { CCIPMessage_V1_6_Sui } from './types.ts'
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Creates a leaf hasher for Sui CCIP messages.
|
|
11
|
+
* @param lane - Lane configuration with selectors and onRamp.
|
|
12
|
+
* @returns Leaf hasher function for the specified version.
|
|
13
|
+
*/
|
|
9
14
|
export function getSuiLeafHasher<V extends CCIPVersion = CCIPVersion>({
|
|
10
15
|
sourceChainSelector,
|
|
11
16
|
destChainSelector,
|
|
@@ -28,6 +33,12 @@ export function getSuiLeafHasher<V extends CCIPVersion = CCIPVersion>({
|
|
|
28
33
|
}
|
|
29
34
|
}
|
|
30
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Computes the leaf hash for a v1.6 Sui CCIP message.
|
|
38
|
+
* @param message - CCIP message to hash.
|
|
39
|
+
* @param metadataHash - Pre-computed metadata hash for the lane.
|
|
40
|
+
* @returns Keccak256 hash of the message.
|
|
41
|
+
*/
|
|
31
42
|
export function hashV16SuiMessage(
|
|
32
43
|
message: CCIPMessage_V1_6 | CCIPMessage_V1_6_Sui,
|
|
33
44
|
metadataHash: string,
|
|
@@ -76,6 +87,13 @@ export function hashV16SuiMessage(
|
|
|
76
87
|
return keccak256(outerHash)
|
|
77
88
|
}
|
|
78
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Computes the metadata hash for Sui CCIP lane.
|
|
92
|
+
* @param sourceChainSelector - Source chain selector.
|
|
93
|
+
* @param destChainSelector - Destination chain selector.
|
|
94
|
+
* @param onRamp - OnRamp address.
|
|
95
|
+
* @returns Keccak256 hash of the lane metadata.
|
|
96
|
+
*/
|
|
79
97
|
export const hashSuiMetadata = (
|
|
80
98
|
sourceChainSelector: bigint,
|
|
81
99
|
destChainSelector: bigint,
|
package/src/sui/index.ts
CHANGED
|
@@ -1,56 +1,93 @@
|
|
|
1
1
|
import { type BytesLike, isBytesLike } from 'ethers'
|
|
2
|
+
import type { PickDeep } from 'type-fest'
|
|
2
3
|
|
|
3
4
|
import { AptosChain } from '../aptos/index.ts'
|
|
4
|
-
import { type
|
|
5
|
+
import { type LogFilter, Chain } from '../chain.ts'
|
|
5
6
|
import type { EVMExtraArgsV2, ExtraArgs, SVMExtraArgsV1 } from '../extra-args.ts'
|
|
7
|
+
import { getSuiLeafHasher } from './hasher.ts'
|
|
6
8
|
import type { LeafHasher } from '../hasher/common.ts'
|
|
7
9
|
import { supportedChains } from '../supported-chains.ts'
|
|
8
|
-
import
|
|
9
|
-
AnyMessage,
|
|
10
|
-
CCIPRequest,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
10
|
+
import {
|
|
11
|
+
type AnyMessage,
|
|
12
|
+
type CCIPRequest,
|
|
13
|
+
type ChainTransaction,
|
|
14
|
+
type CommitReport,
|
|
15
|
+
type ExecutionReceipt,
|
|
16
|
+
type ExecutionReport,
|
|
17
|
+
type Lane,
|
|
18
|
+
type Log_,
|
|
19
|
+
type NetworkInfo,
|
|
20
|
+
type OffchainTokenData,
|
|
21
|
+
type WithLogger,
|
|
22
|
+
ChainFamily,
|
|
18
23
|
} from '../types.ts'
|
|
19
24
|
import type { CCIPMessage_V1_6_Sui } from './types.ts'
|
|
20
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Sui chain implementation supporting Sui networks.
|
|
28
|
+
* Note: This implementation is currently a placeholder.
|
|
29
|
+
*/
|
|
21
30
|
export class SuiChain extends Chain<typeof ChainFamily.Sui> {
|
|
31
|
+
static {
|
|
32
|
+
supportedChains[ChainFamily.Sui] = SuiChain
|
|
33
|
+
}
|
|
22
34
|
static readonly family = ChainFamily.Sui
|
|
23
35
|
static readonly decimals = 8
|
|
24
36
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Creates a new SuiChain instance.
|
|
39
|
+
* @param network - Sui network configuration.
|
|
40
|
+
*/
|
|
41
|
+
constructor(network: NetworkInfo<typeof ChainFamily.Sui>, ctx?: WithLogger) {
|
|
42
|
+
super(network, ctx)
|
|
30
43
|
}
|
|
31
44
|
|
|
32
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Creates a SuiChain instance from an RPC URL.
|
|
47
|
+
* @param _url - RPC endpoint URL.
|
|
48
|
+
* @returns A new SuiChain instance.
|
|
49
|
+
*/
|
|
50
|
+
static async fromUrl(_url: string, _ctx?: WithLogger): Promise<SuiChain> {
|
|
33
51
|
return Promise.reject(new Error('Not implemented'))
|
|
34
52
|
}
|
|
35
53
|
|
|
36
|
-
|
|
37
|
-
// Nothing to cleanup for Aptos implementation
|
|
38
|
-
}
|
|
39
|
-
|
|
54
|
+
/** {@inheritDoc Chain.getBlockTimestamp} */
|
|
40
55
|
async getBlockTimestamp(_version: number | 'finalized'): Promise<number> {
|
|
41
56
|
return Promise.reject(new Error('Not implemented'))
|
|
42
57
|
}
|
|
43
58
|
|
|
59
|
+
/** {@inheritDoc Chain.getTransaction} */
|
|
44
60
|
async getTransaction(_hash: string | number): Promise<ChainTransaction> {
|
|
45
61
|
return Promise.reject(new Error('Not implemented'))
|
|
46
62
|
}
|
|
47
63
|
|
|
64
|
+
/** {@inheritDoc Chain.getLogs} */
|
|
48
65
|
// eslint-disable-next-line require-yield
|
|
49
66
|
async *getLogs(_opts: LogFilter & { versionAsHash?: boolean }) {
|
|
50
67
|
await Promise.resolve()
|
|
51
68
|
throw new Error('Not implemented')
|
|
52
69
|
}
|
|
53
70
|
|
|
71
|
+
/** {@inheritDoc Chain.fetchRequestsInTx} */
|
|
72
|
+
override async fetchRequestsInTx(_tx: string | ChainTransaction): Promise<CCIPRequest[]> {
|
|
73
|
+
return Promise.reject(new Error('Not implemented'))
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** {@inheritDoc Chain.fetchAllMessagesInBatch} */
|
|
77
|
+
override async fetchAllMessagesInBatch<
|
|
78
|
+
R extends PickDeep<
|
|
79
|
+
CCIPRequest,
|
|
80
|
+
'lane' | `log.${'topics' | 'address' | 'blockNumber'}` | 'message.header.sequenceNumber'
|
|
81
|
+
>,
|
|
82
|
+
>(
|
|
83
|
+
_request: R,
|
|
84
|
+
_commit: Pick<CommitReport, 'minSeqNr' | 'maxSeqNr'>,
|
|
85
|
+
_opts?: { page?: number },
|
|
86
|
+
): Promise<R['message'][]> {
|
|
87
|
+
return Promise.reject(new Error('Not implemented'))
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** {@inheritDoc Chain.typeAndVersion} */
|
|
54
91
|
async typeAndVersion(
|
|
55
92
|
_address: string,
|
|
56
93
|
): Promise<
|
|
@@ -60,55 +97,71 @@ export class SuiChain extends Chain<typeof ChainFamily.Sui> {
|
|
|
60
97
|
return Promise.reject(new Error('Not implemented'))
|
|
61
98
|
}
|
|
62
99
|
|
|
100
|
+
/** {@inheritDoc Chain.getRouterForOnRamp} */
|
|
63
101
|
getRouterForOnRamp(_onRamp: string, _destChainSelector: bigint): Promise<string> {
|
|
64
102
|
return Promise.reject(new Error('Not implemented'))
|
|
65
103
|
}
|
|
66
104
|
|
|
105
|
+
/** {@inheritDoc Chain.getRouterForOffRamp} */
|
|
67
106
|
getRouterForOffRamp(_offRamp: string, _sourceChainSelector: bigint): Promise<string> {
|
|
68
107
|
return Promise.reject(new Error('Not implemented'))
|
|
69
108
|
}
|
|
70
109
|
|
|
110
|
+
/** {@inheritDoc Chain.getNativeTokenForRouter} */
|
|
71
111
|
getNativeTokenForRouter(_router: string): Promise<string> {
|
|
72
112
|
return Promise.reject(new Error('Not implemented'))
|
|
73
113
|
}
|
|
74
114
|
|
|
115
|
+
/** {@inheritDoc Chain.getOffRampsForRouter} */
|
|
75
116
|
getOffRampsForRouter(_router: string, _sourceChainSelector: bigint): Promise<string[]> {
|
|
76
117
|
return Promise.reject(new Error('Not implemented'))
|
|
77
118
|
}
|
|
78
119
|
|
|
120
|
+
/** {@inheritDoc Chain.getOnRampForRouter} */
|
|
79
121
|
getOnRampForRouter(_router: string, _destChainSelector: bigint): Promise<string> {
|
|
80
122
|
return Promise.reject(new Error('Not implemented'))
|
|
81
123
|
}
|
|
82
124
|
|
|
125
|
+
/** {@inheritDoc Chain.getOnRampForOffRamp} */
|
|
83
126
|
async getOnRampForOffRamp(_offRamp: string, _sourceChainSelector: bigint): Promise<string> {
|
|
84
127
|
return Promise.reject(new Error('Not implemented'))
|
|
85
128
|
}
|
|
86
129
|
|
|
130
|
+
/** {@inheritDoc Chain.getCommitStoreForOffRamp} */
|
|
87
131
|
getCommitStoreForOffRamp(_offRamp: string): Promise<string> {
|
|
88
132
|
return Promise.reject(new Error('Not implemented'))
|
|
89
133
|
}
|
|
90
134
|
|
|
135
|
+
/** {@inheritDoc Chain.getTokenForTokenPool} */
|
|
91
136
|
async getTokenForTokenPool(_tokenPool: string): Promise<string> {
|
|
92
137
|
return Promise.reject(new Error('Not implemented'))
|
|
93
138
|
}
|
|
94
139
|
|
|
140
|
+
/** {@inheritDoc Chain.getTokenInfo} */
|
|
95
141
|
async getTokenInfo(_token: string): Promise<{ symbol: string; decimals: number }> {
|
|
96
142
|
return Promise.reject(new Error('Not implemented'))
|
|
97
143
|
}
|
|
98
144
|
|
|
145
|
+
/** {@inheritDoc Chain.getTokenAdminRegistryFor} */
|
|
99
146
|
getTokenAdminRegistryFor(_address: string): Promise<string> {
|
|
100
147
|
return Promise.reject(new Error('Not implemented'))
|
|
101
148
|
}
|
|
102
149
|
|
|
103
|
-
async getWalletAddress(_opts?: { wallet?: unknown }): Promise<string> {
|
|
104
|
-
return Promise.reject(new Error('Not implemented'))
|
|
105
|
-
}
|
|
106
|
-
|
|
107
150
|
// Static methods for decoding
|
|
151
|
+
/**
|
|
152
|
+
* Decodes a CCIP message from a Sui log event.
|
|
153
|
+
* @param _log - Log event data.
|
|
154
|
+
* @returns Decoded CCIPMessage or undefined if not valid.
|
|
155
|
+
*/
|
|
108
156
|
static decodeMessage(_log: Log_): CCIPMessage_V1_6_Sui | undefined {
|
|
109
157
|
throw new Error('Not implemented')
|
|
110
158
|
}
|
|
111
159
|
|
|
160
|
+
/**
|
|
161
|
+
* Decodes extra arguments from Sui CCIP messages.
|
|
162
|
+
* @param extraArgs - Encoded extra arguments bytes.
|
|
163
|
+
* @returns Decoded extra arguments or undefined if unknown format.
|
|
164
|
+
*/
|
|
112
165
|
static decodeExtraArgs(
|
|
113
166
|
extraArgs: BytesLike,
|
|
114
167
|
):
|
|
@@ -118,39 +171,79 @@ export class SuiChain extends Chain<typeof ChainFamily.Sui> {
|
|
|
118
171
|
return AptosChain.decodeExtraArgs(extraArgs)
|
|
119
172
|
}
|
|
120
173
|
|
|
174
|
+
/**
|
|
175
|
+
* Encodes extra arguments for Sui CCIP messages.
|
|
176
|
+
* @param extraArgs - Extra arguments to encode.
|
|
177
|
+
* @returns Encoded extra arguments as hex string.
|
|
178
|
+
*/
|
|
121
179
|
static encodeExtraArgs(extraArgs: ExtraArgs): string {
|
|
122
180
|
return AptosChain.encodeExtraArgs(extraArgs)
|
|
123
181
|
}
|
|
124
182
|
|
|
183
|
+
/**
|
|
184
|
+
* Decodes commit reports from a Sui log event.
|
|
185
|
+
* @param _log - Log event data.
|
|
186
|
+
* @param _lane - Lane info for filtering.
|
|
187
|
+
* @returns Array of CommitReport or undefined if not valid.
|
|
188
|
+
*/
|
|
125
189
|
static decodeCommits(_log: Log_, _lane?: Lane): CommitReport[] | undefined {
|
|
126
190
|
throw new Error('Not implemented')
|
|
127
191
|
}
|
|
128
192
|
|
|
193
|
+
/**
|
|
194
|
+
* Decodes an execution receipt from a Sui log event.
|
|
195
|
+
* @param _log - Log event data.
|
|
196
|
+
* @returns ExecutionReceipt or undefined if not valid.
|
|
197
|
+
*/
|
|
129
198
|
static decodeReceipt(_log: Log_): ExecutionReceipt | undefined {
|
|
130
199
|
throw new Error('Not implemented')
|
|
131
200
|
}
|
|
132
201
|
|
|
202
|
+
/**
|
|
203
|
+
* Converts bytes to a Sui address.
|
|
204
|
+
* @param bytes - Bytes to convert.
|
|
205
|
+
* @returns Sui address.
|
|
206
|
+
*/
|
|
133
207
|
static getAddress(bytes: BytesLike): string {
|
|
134
208
|
return AptosChain.getAddress(bytes)
|
|
135
209
|
}
|
|
136
210
|
|
|
137
|
-
|
|
138
|
-
|
|
211
|
+
/**
|
|
212
|
+
* Gets the leaf hasher for Sui destination chains.
|
|
213
|
+
* @param lane - Lane configuration.
|
|
214
|
+
* @returns Leaf hasher function.
|
|
215
|
+
*/
|
|
216
|
+
static getDestLeafHasher(lane: Lane, _ctx?: WithLogger): LeafHasher {
|
|
217
|
+
return getSuiLeafHasher(lane)
|
|
139
218
|
}
|
|
140
219
|
|
|
220
|
+
/** {@inheritDoc Chain.getFee} */
|
|
141
221
|
async getFee(_router: string, _destChainSelector: bigint, _message: AnyMessage): Promise<bigint> {
|
|
142
222
|
return Promise.reject(new Error('Not implemented'))
|
|
143
223
|
}
|
|
144
224
|
|
|
225
|
+
/** {@inheritDoc Chain.generateUnsignedSendMessage} */
|
|
226
|
+
override generateUnsignedSendMessage(
|
|
227
|
+
_sender: string,
|
|
228
|
+
_router: string,
|
|
229
|
+
_destChainSelector: bigint,
|
|
230
|
+
_message: AnyMessage & { fee?: bigint },
|
|
231
|
+
_opts?: { approveMax?: boolean },
|
|
232
|
+
): Promise<never> {
|
|
233
|
+
return Promise.reject(new Error('Not implemented'))
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/** {@inheritDoc Chain.sendMessage} */
|
|
145
237
|
async sendMessage(
|
|
146
238
|
_router: string,
|
|
147
239
|
_destChainSelector: bigint,
|
|
148
240
|
_message: AnyMessage & { fee: bigint },
|
|
149
241
|
_opts?: { wallet?: unknown; approveMax?: boolean },
|
|
150
|
-
): Promise<
|
|
242
|
+
): Promise<CCIPRequest> {
|
|
151
243
|
return Promise.reject(new Error('Not implemented'))
|
|
152
244
|
}
|
|
153
245
|
|
|
246
|
+
/** {@inheritDoc Chain.fetchOffchainTokenData} */
|
|
154
247
|
fetchOffchainTokenData(request: CCIPRequest): Promise<OffchainTokenData[]> {
|
|
155
248
|
if (!('receiverObjectIds' in request.message)) {
|
|
156
249
|
throw new Error('Invalid message, not v1.6 Sui')
|
|
@@ -159,6 +252,17 @@ export class SuiChain extends Chain<typeof ChainFamily.Sui> {
|
|
|
159
252
|
return Promise.resolve(request.message.tokenAmounts.map(() => undefined))
|
|
160
253
|
}
|
|
161
254
|
|
|
255
|
+
/** {@inheritDoc Chain.generateUnsignedExecuteReport} */
|
|
256
|
+
override generateUnsignedExecuteReport(
|
|
257
|
+
_payer: string,
|
|
258
|
+
_offRamp: string,
|
|
259
|
+
_execReport: ExecutionReport,
|
|
260
|
+
_opts: object,
|
|
261
|
+
): Promise<never> {
|
|
262
|
+
return Promise.reject(new Error('Not implemented'))
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/** {@inheritDoc Chain.executeReport} */
|
|
162
266
|
async executeReport(
|
|
163
267
|
_offRamp: string,
|
|
164
268
|
_execReport: ExecutionReport,
|
|
@@ -167,6 +271,11 @@ export class SuiChain extends Chain<typeof ChainFamily.Sui> {
|
|
|
167
271
|
return Promise.reject(new Error('Not implemented'))
|
|
168
272
|
}
|
|
169
273
|
|
|
274
|
+
/**
|
|
275
|
+
* Parses raw Sui data into typed structures.
|
|
276
|
+
* @param data - Raw data to parse.
|
|
277
|
+
* @returns Parsed data or undefined.
|
|
278
|
+
*/
|
|
170
279
|
static parse(data: unknown) {
|
|
171
280
|
if (isBytesLike(data)) {
|
|
172
281
|
const parsedExtraArgs = this.decodeExtraArgs(data)
|
|
@@ -174,25 +283,28 @@ export class SuiChain extends Chain<typeof ChainFamily.Sui> {
|
|
|
174
283
|
}
|
|
175
284
|
}
|
|
176
285
|
|
|
286
|
+
/** {@inheritDoc Chain.getSupportedTokens} */
|
|
177
287
|
async getSupportedTokens(_address: string): Promise<string[]> {
|
|
178
288
|
return Promise.reject(new Error('Not implemented'))
|
|
179
289
|
}
|
|
180
290
|
|
|
291
|
+
/** {@inheritDoc Chain.getRegistryTokenConfig} */
|
|
181
292
|
async getRegistryTokenConfig(_address: string, _tokenName: string): Promise<never> {
|
|
182
293
|
return Promise.reject(new Error('Not implemented'))
|
|
183
294
|
}
|
|
184
295
|
|
|
296
|
+
/** {@inheritDoc Chain.getTokenPoolConfigs} */
|
|
185
297
|
async getTokenPoolConfigs(_tokenPool: string): Promise<never> {
|
|
186
298
|
return Promise.reject(new Error('Not implemented'))
|
|
187
299
|
}
|
|
188
300
|
|
|
301
|
+
/** {@inheritDoc Chain.getTokenPoolRemotes} */
|
|
189
302
|
async getTokenPoolRemotes(_tokenPool: string): Promise<never> {
|
|
190
303
|
return Promise.reject(new Error('Not implemented'))
|
|
191
304
|
}
|
|
192
305
|
|
|
193
|
-
|
|
306
|
+
/** {@inheritDoc Chain.getFeeTokens} */
|
|
307
|
+
async getFeeTokens(_router: string): Promise<never> {
|
|
194
308
|
return Promise.reject(new Error('Not implemented'))
|
|
195
309
|
}
|
|
196
310
|
}
|
|
197
|
-
|
|
198
|
-
supportedChains[ChainFamily.Sui] = SuiChain
|
package/src/sui/types.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { type SuiExtraArgsV1, SuiExtraArgsV1Tag } from '../extra-args.ts'
|
|
|
5
5
|
import type { CCIPMessage_V1_6 } from '../types.ts'
|
|
6
6
|
import { getAddressBytes, getDataBytes } from '../utils.ts'
|
|
7
7
|
|
|
8
|
+
/** Sui-specific CCIP v1.6 message type with Sui extra args. */
|
|
8
9
|
export type CCIPMessage_V1_6_Sui = CCIPMessage_V1_6 & SuiExtraArgsV1
|
|
9
10
|
|
|
10
11
|
export const SuiExtraArgsV1Codec = bcs.struct('SuiExtraArgsV1', {
|
|
@@ -14,6 +15,11 @@ export const SuiExtraArgsV1Codec = bcs.struct('SuiExtraArgsV1', {
|
|
|
14
15
|
receiverObjectIds: bcs.vector(bcs.vector(bcs.u8())),
|
|
15
16
|
})
|
|
16
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Encodes Sui v1 extra arguments using BCS encoding.
|
|
20
|
+
* @param args - Sui extra arguments to encode.
|
|
21
|
+
* @returns Encoded bytes with tag prefix.
|
|
22
|
+
*/
|
|
17
23
|
export function encodeSuiExtraArgsV1(args: SuiExtraArgsV1): string {
|
|
18
24
|
const tokenReceiver = getAddressBytes(args.tokenReceiver)
|
|
19
25
|
const receiverObjectIds = args.receiverObjectIds.map((id) => getDataBytes(id))
|
package/src/supported-chains.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ChainStatic } from './chain.ts'
|
|
2
|
+
import type { ChainFamily } from './types.ts'
|
|
2
3
|
|
|
3
4
|
// global record; can be mutated when implementing or extending a Chain family support
|
|
4
5
|
export const supportedChains: Partial<{ [F in ChainFamily]: ChainStatic<F> }> = {}
|