@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.
Files changed (202) hide show
  1. package/README.md +35 -26
  2. package/dist/aptos/exec.d.ts +4 -5
  3. package/dist/aptos/exec.d.ts.map +1 -1
  4. package/dist/aptos/exec.js +5 -14
  5. package/dist/aptos/exec.js.map +1 -1
  6. package/dist/aptos/hasher.d.ts +18 -0
  7. package/dist/aptos/hasher.d.ts.map +1 -1
  8. package/dist/aptos/hasher.js +18 -0
  9. package/dist/aptos/hasher.js.map +1 -1
  10. package/dist/aptos/index.d.ts +127 -28
  11. package/dist/aptos/index.d.ts.map +1 -1
  12. package/dist/aptos/index.js +199 -70
  13. package/dist/aptos/index.js.map +1 -1
  14. package/dist/aptos/logs.d.ts +18 -0
  15. package/dist/aptos/logs.d.ts.map +1 -1
  16. package/dist/aptos/logs.js +21 -3
  17. package/dist/aptos/logs.js.map +1 -1
  18. package/dist/aptos/send.d.ts +22 -5
  19. package/dist/aptos/send.d.ts.map +1 -1
  20. package/dist/aptos/send.js +23 -15
  21. package/dist/aptos/send.js.map +1 -1
  22. package/dist/aptos/token.d.ts +6 -0
  23. package/dist/aptos/token.d.ts.map +1 -1
  24. package/dist/aptos/token.js +6 -0
  25. package/dist/aptos/token.js.map +1 -1
  26. package/dist/aptos/types.d.ts +16 -1
  27. package/dist/aptos/types.d.ts.map +1 -1
  28. package/dist/aptos/types.js +13 -0
  29. package/dist/aptos/types.js.map +1 -1
  30. package/dist/aptos/utils.d.ts +1 -1
  31. package/dist/aptos/utils.js +1 -1
  32. package/dist/chain.d.ts +185 -99
  33. package/dist/chain.d.ts.map +1 -1
  34. package/dist/chain.js +38 -15
  35. package/dist/chain.js.map +1 -1
  36. package/dist/commits.d.ts +4 -10
  37. package/dist/commits.d.ts.map +1 -1
  38. package/dist/commits.js +2 -1
  39. package/dist/commits.js.map +1 -1
  40. package/dist/evm/const.d.ts +5 -0
  41. package/dist/evm/const.d.ts.map +1 -1
  42. package/dist/evm/const.js +5 -0
  43. package/dist/evm/const.js.map +1 -1
  44. package/dist/evm/errors.d.ts +5 -0
  45. package/dist/evm/errors.d.ts.map +1 -1
  46. package/dist/evm/errors.js +6 -1
  47. package/dist/evm/errors.js.map +1 -1
  48. package/dist/evm/hasher.d.ts +16 -2
  49. package/dist/evm/hasher.d.ts.map +1 -1
  50. package/dist/evm/hasher.js +17 -3
  51. package/dist/evm/hasher.js.map +1 -1
  52. package/dist/evm/index.d.ts +176 -31
  53. package/dist/evm/index.d.ts.map +1 -1
  54. package/dist/evm/index.js +312 -154
  55. package/dist/evm/index.js.map +1 -1
  56. package/dist/evm/logs.d.ts +20 -0
  57. package/dist/evm/logs.d.ts.map +1 -0
  58. package/dist/evm/logs.js +194 -0
  59. package/dist/evm/logs.js.map +1 -0
  60. package/dist/evm/messages.d.ts +11 -2
  61. package/dist/evm/messages.d.ts.map +1 -1
  62. package/dist/evm/messages.js +4 -2
  63. package/dist/evm/messages.js.map +1 -1
  64. package/dist/evm/offchain.d.ts +7 -2
  65. package/dist/evm/offchain.d.ts.map +1 -1
  66. package/dist/evm/offchain.js +12 -7
  67. package/dist/evm/offchain.js.map +1 -1
  68. package/dist/execution.d.ts +19 -62
  69. package/dist/execution.d.ts.map +1 -1
  70. package/dist/execution.js +28 -31
  71. package/dist/execution.js.map +1 -1
  72. package/dist/extra-args.d.ts +35 -5
  73. package/dist/extra-args.d.ts.map +1 -1
  74. package/dist/extra-args.js +10 -5
  75. package/dist/extra-args.js.map +1 -1
  76. package/dist/gas.d.ts +6 -8
  77. package/dist/gas.d.ts.map +1 -1
  78. package/dist/gas.js +7 -9
  79. package/dist/gas.js.map +1 -1
  80. package/dist/hasher/common.d.ts +3 -2
  81. package/dist/hasher/common.d.ts.map +1 -1
  82. package/dist/hasher/common.js +2 -2
  83. package/dist/hasher/common.js.map +1 -1
  84. package/dist/hasher/hasher.d.ts +8 -2
  85. package/dist/hasher/hasher.d.ts.map +1 -1
  86. package/dist/hasher/hasher.js +8 -3
  87. package/dist/hasher/hasher.js.map +1 -1
  88. package/dist/hasher/merklemulti.d.ts +11 -9
  89. package/dist/hasher/merklemulti.d.ts.map +1 -1
  90. package/dist/hasher/merklemulti.js +17 -16
  91. package/dist/hasher/merklemulti.js.map +1 -1
  92. package/dist/index.d.ts +16 -8
  93. package/dist/index.d.ts.map +1 -1
  94. package/dist/index.js +17 -7
  95. package/dist/index.js.map +1 -1
  96. package/dist/requests.d.ts +39 -25
  97. package/dist/requests.d.ts.map +1 -1
  98. package/dist/requests.js +42 -35
  99. package/dist/requests.js.map +1 -1
  100. package/dist/selectors.d.ts +1 -1
  101. package/dist/solana/cleanup.d.ts +14 -10
  102. package/dist/solana/cleanup.d.ts.map +1 -1
  103. package/dist/solana/cleanup.js +35 -33
  104. package/dist/solana/cleanup.js.map +1 -1
  105. package/dist/solana/exec.d.ts +19 -11
  106. package/dist/solana/exec.d.ts.map +1 -1
  107. package/dist/solana/exec.js +86 -163
  108. package/dist/solana/exec.js.map +1 -1
  109. package/dist/solana/hasher.d.ts +7 -2
  110. package/dist/solana/hasher.d.ts.map +1 -1
  111. package/dist/solana/hasher.js +7 -2
  112. package/dist/solana/hasher.js.map +1 -1
  113. package/dist/solana/index.d.ts +202 -84
  114. package/dist/solana/index.d.ts.map +1 -1
  115. package/dist/solana/index.js +367 -252
  116. package/dist/solana/index.js.map +1 -1
  117. package/dist/solana/offchain.d.ts +8 -18
  118. package/dist/solana/offchain.d.ts.map +1 -1
  119. package/dist/solana/offchain.js +29 -83
  120. package/dist/solana/offchain.js.map +1 -1
  121. package/dist/solana/patchBorsh.d.ts +5 -1
  122. package/dist/solana/patchBorsh.d.ts.map +1 -1
  123. package/dist/solana/patchBorsh.js +57 -46
  124. package/dist/solana/patchBorsh.js.map +1 -1
  125. package/dist/solana/send.d.ts +28 -10
  126. package/dist/solana/send.d.ts.map +1 -1
  127. package/dist/solana/send.js +44 -77
  128. package/dist/solana/send.js.map +1 -1
  129. package/dist/solana/types.d.ts +22 -1
  130. package/dist/solana/types.d.ts.map +1 -1
  131. package/dist/solana/types.js +12 -1
  132. package/dist/solana/types.js.map +1 -1
  133. package/dist/solana/utils.d.ts +58 -4
  134. package/dist/solana/utils.d.ts.map +1 -1
  135. package/dist/solana/utils.js +110 -7
  136. package/dist/solana/utils.js.map +1 -1
  137. package/dist/sui/hasher.d.ts +18 -0
  138. package/dist/sui/hasher.d.ts.map +1 -1
  139. package/dist/sui/hasher.js +18 -0
  140. package/dist/sui/hasher.js.map +1 -1
  141. package/dist/sui/index.d.ts +99 -12
  142. package/dist/sui/index.d.ts.map +1 -1
  143. package/dist/sui/index.js +108 -19
  144. package/dist/sui/index.js.map +1 -1
  145. package/dist/sui/types.d.ts +6 -0
  146. package/dist/sui/types.d.ts.map +1 -1
  147. package/dist/sui/types.js +5 -0
  148. package/dist/sui/types.js.map +1 -1
  149. package/dist/supported-chains.d.ts +2 -1
  150. package/dist/supported-chains.d.ts.map +1 -1
  151. package/dist/supported-chains.js.map +1 -1
  152. package/dist/types.d.ts +127 -16
  153. package/dist/types.d.ts.map +1 -1
  154. package/dist/types.js +18 -0
  155. package/dist/types.js.map +1 -1
  156. package/dist/utils.d.ts +67 -46
  157. package/dist/utils.d.ts.map +1 -1
  158. package/dist/utils.js +143 -21
  159. package/dist/utils.js.map +1 -1
  160. package/package.json +13 -9
  161. package/src/aptos/exec.ts +7 -18
  162. package/src/aptos/hasher.ts +18 -0
  163. package/src/aptos/index.ts +288 -110
  164. package/src/aptos/logs.ts +21 -3
  165. package/src/aptos/send.ts +25 -22
  166. package/src/aptos/token.ts +6 -0
  167. package/src/aptos/types.ts +26 -2
  168. package/src/aptos/utils.ts +1 -1
  169. package/src/chain.ts +243 -108
  170. package/src/commits.ts +6 -7
  171. package/src/evm/const.ts +5 -0
  172. package/src/evm/errors.ts +6 -1
  173. package/src/evm/hasher.ts +20 -4
  174. package/src/evm/index.ts +416 -214
  175. package/src/evm/logs.ts +255 -0
  176. package/src/evm/messages.ts +11 -5
  177. package/src/evm/offchain.ts +13 -4
  178. package/src/execution.ts +40 -32
  179. package/src/extra-args.ts +38 -6
  180. package/src/gas.ts +7 -9
  181. package/src/hasher/common.ts +3 -2
  182. package/src/hasher/hasher.ts +12 -4
  183. package/src/hasher/merklemulti.ts +17 -16
  184. package/src/index.ts +29 -23
  185. package/src/requests.ts +64 -46
  186. package/src/selectors.ts +1 -1
  187. package/src/solana/cleanup.ts +49 -34
  188. package/src/solana/exec.ts +128 -272
  189. package/src/solana/hasher.ts +13 -4
  190. package/src/solana/index.ts +483 -356
  191. package/src/solana/offchain.ts +32 -102
  192. package/src/solana/patchBorsh.ts +65 -50
  193. package/src/solana/send.ts +52 -111
  194. package/src/solana/types.ts +44 -3
  195. package/src/solana/utils.ts +143 -19
  196. package/src/sui/hasher.ts +18 -0
  197. package/src/sui/index.ts +143 -31
  198. package/src/sui/types.ts +6 -0
  199. package/src/supported-chains.ts +2 -1
  200. package/src/types.ts +130 -18
  201. package/src/utils.ts +168 -26
  202. package/tsconfig.json +2 -1
@@ -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'> & { data: string }
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
- export async function simulateTransaction({
180
- connection,
181
- payerKey,
182
- computeUnitsOverride,
183
- ...rest
184
- }: {
185
- connection: Connection
186
- payerKey: PublicKey
187
- computeUnitsOverride?: number
188
- addressLookupTableAccounts?: AddressLookupTableAccount[]
189
- } & ({ instructions: TransactionInstruction[] } | { tx: Transaction | VersionedTransaction })) {
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
- console.debug('Simulation results:', {
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 connection - Connection to the Solana network
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 ChainTransaction, type LogFilter, Chain, ChainFamily } from '../chain.ts'
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 type {
9
- AnyMessage,
10
- CCIPRequest,
11
- CommitReport,
12
- ExecutionReceipt,
13
- ExecutionReport,
14
- Lane,
15
- Log_,
16
- NetworkInfo,
17
- OffchainTokenData,
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
- readonly network: NetworkInfo<typeof ChainFamily.Sui>
26
-
27
- constructor() {
28
- super()
29
- throw new Error('Not implemented')
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
- static async fromUrl(_url: string): Promise<SuiChain> {
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
- async destroy(): Promise<void> {
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
- static getDestLeafHasher(_lane: Lane): LeafHasher {
138
- throw new Error('Not implemented')
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<ChainTransaction> {
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
- async listFeeTokens(_router: string): Promise<never> {
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))
@@ -1,4 +1,5 @@
1
- import type { ChainFamily, ChainStatic } from './chain.ts'
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> }> = {}