@chainlink/ccip-sdk 0.96.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (247) hide show
  1. package/README.md +12 -9
  2. package/dist/api/index.d.ts +21 -8
  3. package/dist/api/index.d.ts.map +1 -1
  4. package/dist/api/index.js +42 -13
  5. package/dist/api/index.js.map +1 -1
  6. package/dist/api/types.d.ts +0 -2
  7. package/dist/api/types.d.ts.map +1 -1
  8. package/dist/aptos/exec.d.ts +2 -2
  9. package/dist/aptos/exec.d.ts.map +1 -1
  10. package/dist/aptos/exec.js.map +1 -1
  11. package/dist/aptos/hasher.d.ts.map +1 -1
  12. package/dist/aptos/hasher.js +1 -1
  13. package/dist/aptos/hasher.js.map +1 -1
  14. package/dist/aptos/index.d.ts +17 -16
  15. package/dist/aptos/index.d.ts.map +1 -1
  16. package/dist/aptos/index.js +42 -73
  17. package/dist/aptos/index.js.map +1 -1
  18. package/dist/aptos/logs.d.ts +2 -2
  19. package/dist/aptos/logs.d.ts.map +1 -1
  20. package/dist/aptos/types.d.ts +2 -19
  21. package/dist/aptos/types.d.ts.map +1 -1
  22. package/dist/aptos/types.js +0 -11
  23. package/dist/aptos/types.js.map +1 -1
  24. package/dist/chain.d.ts +538 -158
  25. package/dist/chain.d.ts.map +1 -1
  26. package/dist/chain.js +132 -19
  27. package/dist/chain.js.map +1 -1
  28. package/dist/commits.d.ts +4 -6
  29. package/dist/commits.d.ts.map +1 -1
  30. package/dist/commits.js +4 -4
  31. package/dist/commits.js.map +1 -1
  32. package/dist/errors/CCIPError.d.ts +33 -4
  33. package/dist/errors/CCIPError.d.ts.map +1 -1
  34. package/dist/errors/CCIPError.js +33 -4
  35. package/dist/errors/CCIPError.js.map +1 -1
  36. package/dist/errors/codes.d.ts +3 -0
  37. package/dist/errors/codes.d.ts.map +1 -1
  38. package/dist/errors/codes.js +3 -1
  39. package/dist/errors/codes.js.map +1 -1
  40. package/dist/errors/index.d.ts +4 -4
  41. package/dist/errors/index.d.ts.map +1 -1
  42. package/dist/errors/index.js +4 -4
  43. package/dist/errors/index.js.map +1 -1
  44. package/dist/errors/recovery.d.ts.map +1 -1
  45. package/dist/errors/recovery.js +4 -1
  46. package/dist/errors/recovery.js.map +1 -1
  47. package/dist/errors/specialized.d.ts +1695 -120
  48. package/dist/errors/specialized.d.ts.map +1 -1
  49. package/dist/errors/specialized.js +1715 -123
  50. package/dist/errors/specialized.js.map +1 -1
  51. package/dist/errors/utils.d.ts.map +1 -1
  52. package/dist/errors/utils.js +0 -1
  53. package/dist/errors/utils.js.map +1 -1
  54. package/dist/evm/abi/OffRamp_2_0.d.ts +764 -0
  55. package/dist/evm/abi/OffRamp_2_0.d.ts.map +1 -0
  56. package/dist/evm/abi/OffRamp_2_0.js +744 -0
  57. package/dist/evm/abi/OffRamp_2_0.js.map +1 -0
  58. package/dist/evm/abi/OnRamp_2_0.d.ts +925 -0
  59. package/dist/evm/abi/OnRamp_2_0.d.ts.map +1 -0
  60. package/dist/evm/abi/OnRamp_2_0.js +992 -0
  61. package/dist/evm/abi/OnRamp_2_0.js.map +1 -0
  62. package/dist/evm/const.d.ts +12 -2
  63. package/dist/evm/const.d.ts.map +1 -1
  64. package/dist/evm/const.js +8 -2
  65. package/dist/evm/const.js.map +1 -1
  66. package/dist/evm/errors.d.ts.map +1 -1
  67. package/dist/evm/errors.js +7 -2
  68. package/dist/evm/errors.js.map +1 -1
  69. package/dist/evm/extra-args.d.ts.map +1 -1
  70. package/dist/evm/extra-args.js +5 -24
  71. package/dist/evm/extra-args.js.map +1 -1
  72. package/dist/evm/hasher.d.ts.map +1 -1
  73. package/dist/evm/hasher.js +23 -13
  74. package/dist/evm/hasher.js.map +1 -1
  75. package/dist/evm/index.d.ts +73 -16
  76. package/dist/evm/index.d.ts.map +1 -1
  77. package/dist/evm/index.js +241 -146
  78. package/dist/evm/index.js.map +1 -1
  79. package/dist/evm/logs.d.ts +1 -1
  80. package/dist/evm/logs.js +1 -1
  81. package/dist/evm/messages.d.ts +59 -5
  82. package/dist/evm/messages.d.ts.map +1 -1
  83. package/dist/evm/messages.js +210 -0
  84. package/dist/evm/messages.js.map +1 -1
  85. package/dist/evm/offchain.d.ts +1 -14
  86. package/dist/evm/offchain.d.ts.map +1 -1
  87. package/dist/evm/offchain.js +1 -133
  88. package/dist/evm/offchain.js.map +1 -1
  89. package/dist/evm/types.d.ts +7 -2
  90. package/dist/evm/types.d.ts.map +1 -1
  91. package/dist/evm/types.js +22 -1
  92. package/dist/evm/types.js.map +1 -1
  93. package/dist/execution.d.ts +62 -22
  94. package/dist/execution.d.ts.map +1 -1
  95. package/dist/execution.js +98 -61
  96. package/dist/execution.js.map +1 -1
  97. package/dist/extra-args.d.ts +13 -3
  98. package/dist/extra-args.d.ts.map +1 -1
  99. package/dist/extra-args.js +13 -3
  100. package/dist/extra-args.js.map +1 -1
  101. package/dist/gas.d.ts +25 -2
  102. package/dist/gas.d.ts.map +1 -1
  103. package/dist/gas.js +30 -4
  104. package/dist/gas.js.map +1 -1
  105. package/dist/index.d.ts +3 -2
  106. package/dist/index.d.ts.map +1 -1
  107. package/dist/index.js +2 -1
  108. package/dist/index.js.map +1 -1
  109. package/dist/offchain.d.ts +23 -6
  110. package/dist/offchain.d.ts.map +1 -1
  111. package/dist/offchain.js +92 -17
  112. package/dist/offchain.js.map +1 -1
  113. package/dist/requests.d.ts +85 -14
  114. package/dist/requests.d.ts.map +1 -1
  115. package/dist/requests.js +99 -17
  116. package/dist/requests.js.map +1 -1
  117. package/dist/selectors.d.ts.map +1 -1
  118. package/dist/selectors.js +12 -0
  119. package/dist/selectors.js.map +1 -1
  120. package/dist/shared/bcs-codecs.d.ts +61 -0
  121. package/dist/shared/bcs-codecs.d.ts.map +1 -0
  122. package/dist/shared/bcs-codecs.js +102 -0
  123. package/dist/shared/bcs-codecs.js.map +1 -0
  124. package/dist/shared/constants.d.ts +3 -0
  125. package/dist/shared/constants.d.ts.map +1 -0
  126. package/dist/shared/constants.js +3 -0
  127. package/dist/shared/constants.js.map +1 -0
  128. package/dist/solana/exec.d.ts +2 -2
  129. package/dist/solana/exec.d.ts.map +1 -1
  130. package/dist/solana/exec.js.map +1 -1
  131. package/dist/solana/idl/1.6.0/BASE_TOKEN_POOL.d.ts +1 -1
  132. package/dist/solana/idl/1.6.0/BASE_TOKEN_POOL.js +1 -1
  133. package/dist/solana/idl/1.6.0/BURN_MINT_TOKEN_POOL.d.ts +1 -1
  134. package/dist/solana/idl/1.6.0/BURN_MINT_TOKEN_POOL.js +1 -1
  135. package/dist/solana/idl/1.6.0/CCIP_CCTP_TOKEN_POOL.d.ts +1 -1
  136. package/dist/solana/idl/1.6.0/CCIP_CCTP_TOKEN_POOL.js +1 -1
  137. package/dist/solana/idl/1.6.0/CCIP_COMMON.d.ts +16 -1
  138. package/dist/solana/idl/1.6.0/CCIP_COMMON.d.ts.map +1 -1
  139. package/dist/solana/idl/1.6.0/CCIP_COMMON.js +16 -1
  140. package/dist/solana/idl/1.6.0/CCIP_COMMON.js.map +1 -1
  141. package/dist/solana/idl/1.6.0/CCIP_OFFRAMP.d.ts +1 -1
  142. package/dist/solana/idl/1.6.0/CCIP_OFFRAMP.js +1 -1
  143. package/dist/solana/idl/1.6.0/CCIP_ROUTER.d.ts +1 -1
  144. package/dist/solana/idl/1.6.0/CCIP_ROUTER.js +1 -1
  145. package/dist/solana/index.d.ts +85 -24
  146. package/dist/solana/index.d.ts.map +1 -1
  147. package/dist/solana/index.js +69 -37
  148. package/dist/solana/index.js.map +1 -1
  149. package/dist/solana/offchain.d.ts +1 -13
  150. package/dist/solana/offchain.d.ts.map +1 -1
  151. package/dist/solana/offchain.js +1 -66
  152. package/dist/solana/offchain.js.map +1 -1
  153. package/dist/solana/utils.d.ts +4 -4
  154. package/dist/solana/utils.d.ts.map +1 -1
  155. package/dist/solana/utils.js +1 -1
  156. package/dist/solana/utils.js.map +1 -1
  157. package/dist/sui/hasher.d.ts.map +1 -1
  158. package/dist/sui/hasher.js +1 -1
  159. package/dist/sui/hasher.js.map +1 -1
  160. package/dist/sui/index.d.ts +18 -18
  161. package/dist/sui/index.d.ts.map +1 -1
  162. package/dist/sui/index.js +38 -39
  163. package/dist/sui/index.js.map +1 -1
  164. package/dist/sui/manuallyExec/encoder.d.ts +2 -2
  165. package/dist/sui/manuallyExec/encoder.d.ts.map +1 -1
  166. package/dist/sui/manuallyExec/encoder.js.map +1 -1
  167. package/dist/sui/manuallyExec/index.d.ts +2 -2
  168. package/dist/sui/manuallyExec/index.d.ts.map +1 -1
  169. package/dist/ton/exec.d.ts +3 -3
  170. package/dist/ton/exec.d.ts.map +1 -1
  171. package/dist/ton/exec.js +1 -1
  172. package/dist/ton/exec.js.map +1 -1
  173. package/dist/ton/index.d.ts +14 -22
  174. package/dist/ton/index.d.ts.map +1 -1
  175. package/dist/ton/index.js +26 -35
  176. package/dist/ton/index.js.map +1 -1
  177. package/dist/ton/types.d.ts +3 -5
  178. package/dist/ton/types.d.ts.map +1 -1
  179. package/dist/ton/types.js.map +1 -1
  180. package/dist/types.d.ts +55 -20
  181. package/dist/types.d.ts.map +1 -1
  182. package/dist/types.js +6 -1
  183. package/dist/types.js.map +1 -1
  184. package/dist/utils.d.ts +65 -2
  185. package/dist/utils.d.ts.map +1 -1
  186. package/dist/utils.js +74 -2
  187. package/dist/utils.js.map +1 -1
  188. package/package.json +14 -10
  189. package/src/api/index.ts +53 -17
  190. package/src/api/types.ts +0 -2
  191. package/src/aptos/exec.ts +2 -2
  192. package/src/aptos/hasher.ts +1 -1
  193. package/src/aptos/index.ts +55 -100
  194. package/src/aptos/logs.ts +2 -2
  195. package/src/aptos/types.ts +2 -15
  196. package/src/chain.ts +594 -171
  197. package/src/commits.ts +9 -9
  198. package/src/errors/CCIPError.ts +33 -4
  199. package/src/errors/codes.ts +3 -1
  200. package/src/errors/index.ts +4 -0
  201. package/src/errors/recovery.ts +7 -1
  202. package/src/errors/specialized.ts +1726 -130
  203. package/src/errors/utils.ts +0 -1
  204. package/src/evm/abi/OffRamp_2_0.ts +743 -0
  205. package/src/evm/abi/OnRamp_2_0.ts +991 -0
  206. package/src/evm/const.ts +10 -3
  207. package/src/evm/errors.ts +6 -2
  208. package/src/evm/extra-args.ts +4 -21
  209. package/src/evm/hasher.ts +30 -18
  210. package/src/evm/index.ts +314 -176
  211. package/src/evm/logs.ts +1 -1
  212. package/src/evm/messages.ts +323 -11
  213. package/src/evm/offchain.ts +2 -191
  214. package/src/evm/types.ts +20 -2
  215. package/src/execution.ts +125 -86
  216. package/src/extra-args.ts +13 -3
  217. package/src/gas.ts +29 -3
  218. package/src/index.ts +10 -3
  219. package/src/offchain.ts +125 -28
  220. package/src/requests.ts +114 -19
  221. package/src/selectors.ts +12 -0
  222. package/src/shared/bcs-codecs.ts +132 -0
  223. package/src/shared/constants.ts +2 -0
  224. package/src/solana/exec.ts +4 -4
  225. package/src/solana/idl/1.6.0/BASE_TOKEN_POOL.ts +2 -2
  226. package/src/solana/idl/1.6.0/BURN_MINT_TOKEN_POOL.ts +2 -2
  227. package/src/solana/idl/1.6.0/CCIP_CCTP_TOKEN_POOL.ts +2 -2
  228. package/src/solana/idl/1.6.0/CCIP_COMMON.ts +32 -2
  229. package/src/solana/idl/1.6.0/CCIP_OFFRAMP.ts +2 -2
  230. package/src/solana/idl/1.6.0/CCIP_ROUTER.ts +2 -2
  231. package/src/solana/index.ts +110 -85
  232. package/src/solana/offchain.ts +3 -100
  233. package/src/solana/utils.ts +8 -5
  234. package/src/sui/hasher.ts +1 -1
  235. package/src/sui/index.ts +55 -59
  236. package/src/sui/manuallyExec/encoder.ts +2 -2
  237. package/src/sui/manuallyExec/index.ts +2 -2
  238. package/src/ton/exec.ts +4 -7
  239. package/src/ton/index.ts +45 -53
  240. package/src/ton/types.ts +4 -7
  241. package/src/types.ts +81 -37
  242. package/src/utils.ts +73 -2
  243. package/dist/aptos/utils.d.ts +0 -12
  244. package/dist/aptos/utils.d.ts.map +0 -1
  245. package/dist/aptos/utils.js +0 -15
  246. package/dist/aptos/utils.js.map +0 -1
  247. package/src/aptos/utils.ts +0 -24
@@ -73,19 +73,18 @@ import SELECTORS from '../selectors.ts'
73
73
  import { supportedChains } from '../supported-chains.ts'
74
74
  import {
75
75
  type AnyMessage,
76
- type CCIPCommit,
77
76
  type CCIPExecution,
78
77
  type CCIPMessage,
79
78
  type CCIPRequest,
79
+ type CCIPVerifications,
80
+ type ChainLog,
80
81
  type ChainTransaction,
81
82
  type CommitReport,
83
+ type ExecutionInput,
82
84
  type ExecutionReceipt,
83
- type ExecutionReport,
84
85
  type Lane,
85
- type Log_,
86
86
  type MergeArrayElements,
87
87
  type NetworkInfo,
88
- type OffchainTokenData,
89
88
  type WithLogger,
90
89
  CCIPVersion,
91
90
  ChainFamily,
@@ -96,6 +95,7 @@ import {
96
95
  createRateLimitedFetch,
97
96
  decodeAddress,
98
97
  decodeOnRampAddress,
98
+ getAddressBytes,
99
99
  getDataBytes,
100
100
  leToBigInt,
101
101
  networkInfo,
@@ -112,7 +112,6 @@ import { IDL as CCIP_CCTP_TOKEN_POOL } from './idl/1.6.0/CCIP_CCTP_TOKEN_POOL.ts
112
112
  import { IDL as CCIP_OFFRAMP_IDL } from './idl/1.6.0/CCIP_OFFRAMP.ts'
113
113
  import { IDL as CCIP_ROUTER_IDL } from './idl/1.6.0/CCIP_ROUTER.ts'
114
114
  import { getTransactionsForAddress } from './logs.ts'
115
- import { fetchSolanaOffchainTokenData } from './offchain.ts'
116
115
  import { generateUnsignedCcipSend, getFee } from './send.ts'
117
116
  import { type CCIPMessage_V1_6_Solana, type UnsignedSolanaTx, isWallet } from './types.ts'
118
117
  import {
@@ -126,7 +125,7 @@ import {
126
125
  } from './utils.ts'
127
126
  import { buildMessageForDest, getMessagesInBatch } from '../requests.ts'
128
127
  import { patchBorsh } from './patchBorsh.ts'
129
- import { DEFAULT_GAS_LIMIT } from '../evm/const.ts'
128
+ import { DEFAULT_GAS_LIMIT } from '../shared/constants.ts'
130
129
  export type { UnsignedSolanaTx }
131
130
 
132
131
  const routerCoder = new BorshCoder(CCIP_ROUTER_IDL)
@@ -159,7 +158,7 @@ const unknownTokens: { [mint: string]: string } = {
159
158
  }
160
159
 
161
160
  /** Solana-specific log structure with transaction reference and log level. */
162
- export type SolanaLog = Log_ & { tx: SolanaTransaction; data: string; level: number }
161
+ export type SolanaLog = ChainLog & { tx: SolanaTransaction; data: string; level: number }
163
162
  /** Solana-specific transaction structure with versioned transaction response. */
164
163
  export type SolanaTransaction = MergeArrayElements<
165
164
  ChainTransaction,
@@ -171,6 +170,29 @@ export type SolanaTransaction = MergeArrayElements<
171
170
 
172
171
  /**
173
172
  * Solana chain implementation supporting Solana networks.
173
+ *
174
+ * Provides methods for sending CCIP cross-chain messages, querying message
175
+ * status, fetching fee quotes, and manually executing pending messages on
176
+ * Solana networks.
177
+ *
178
+ * @remarks
179
+ * Solana uses CCIP v1.6+ protocol only.
180
+ *
181
+ * @example Create from RPC URL
182
+ * ```typescript
183
+ * import { SolanaChain } from '@chainlink/ccip-sdk'
184
+ *
185
+ * const chain = await SolanaChain.fromUrl('https://api.devnet.solana.com')
186
+ * console.log(`Connected to: ${chain.network.name}`)
187
+ * ```
188
+ *
189
+ * @example Query messages in a transaction
190
+ * ```typescript
191
+ * const requests = await chain.getMessagesInTx('5abc123...')
192
+ * for (const req of requests) {
193
+ * console.log(`Message ID: ${req.message.messageId}`)
194
+ * }
195
+ * ```
174
196
  */
175
197
  export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
176
198
  static {
@@ -284,9 +306,20 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
284
306
 
285
307
  /**
286
308
  * Creates a SolanaChain instance from an RPC URL.
287
- * @param url - RPC endpoint URL.
288
- * @param ctx - context containing logger.
289
- * @returns A new SolanaChain instance.
309
+ *
310
+ * @param url - RPC endpoint URL (https://, http://, wss://, or ws://).
311
+ * @param ctx - Optional context containing logger and API client configuration.
312
+ * @returns A new SolanaChain instance connected to the specified network.
313
+ * @throws {@link CCIPChainNotFoundError} if chain cannot be identified from genesis hash
314
+ *
315
+ * @example
316
+ * ```typescript
317
+ * // Create from devnet URL
318
+ * const chain = await SolanaChain.fromUrl('https://api.devnet.solana.com')
319
+ *
320
+ * // With custom logger
321
+ * const chain = await SolanaChain.fromUrl(url, { logger: customLogger })
322
+ * ```
290
323
  */
291
324
  static async fromUrl(url: string, ctx?: ChainContext): Promise<SolanaChain> {
292
325
  const connection = this._getConnection(url, ctx)
@@ -395,13 +428,13 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
395
428
  * - `watch`: Watch for new logs
396
429
  * - `programs`: Special option to allow querying by address of interest, but yielding matching
397
430
  * logs from specific (string address) program or any (true)
398
- * @returns AsyncIterableIterator of parsed Log_ objects.
431
+ * @returns AsyncIterableIterator of parsed ChainLog objects.
399
432
  * @throws {@link CCIPLogsAddressRequiredError} if address is not provided
400
433
  * @throws {@link CCIPTopicsInvalidError} if topics contain invalid values
401
434
  */
402
435
  async *getLogs(
403
436
  opts: LogFilter & { programs?: string[] | true },
404
- ): AsyncGenerator<Log_ & { tx: SolanaTransaction }> {
437
+ ): AsyncGenerator<ChainLog & { tx: SolanaTransaction }> {
405
438
  let programs: true | string[]
406
439
  if (!opts.address) {
407
440
  throw new CCIPLogsAddressRequiredError()
@@ -442,15 +475,15 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
442
475
  }
443
476
 
444
477
  /** {@inheritDoc Chain.getMessagesInBatch} */
445
- async getMessagesInBatch<
478
+ override async getMessagesInBatch<
446
479
  R extends PickDeep<
447
480
  CCIPRequest,
448
481
  'lane' | `log.${'topics' | 'address' | 'blockNumber'}` | 'message.sequenceNumber'
449
482
  >,
450
483
  >(
451
484
  request: R,
452
- commit: Pick<CommitReport, 'minSeqNr' | 'maxSeqNr'>,
453
- opts?: { page?: number },
485
+ range: Pick<CommitReport, 'minSeqNr' | 'maxSeqNr'>,
486
+ opts?: Pick<LogFilter, 'page'>,
454
487
  ): Promise<R['message'][]> {
455
488
  const [destChainStatePda] = PublicKey.findProgramAddressSync(
456
489
  [Buffer.from('dest_chain_state'), toLeArray(request.lane.destChainSelector, 8)],
@@ -463,7 +496,7 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
463
496
  programs: [request.log.address],
464
497
  address: destChainStatePda.toBase58(),
465
498
  }
466
- return getMessagesInBatch(this, request, commit, opts_)
499
+ return getMessagesInBatch(this, request, range, opts_)
467
500
  }
468
501
 
469
502
  /** {@inheritDoc Chain.typeAndVersion} */
@@ -548,8 +581,8 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
548
581
  return Promise.resolve(router) // solana's Router is also the OnRamp
549
582
  }
550
583
 
551
- /** {@inheritDoc Chain.getOnRampForOffRamp} */
552
- async getOnRampForOffRamp(offRamp: string, sourceChainSelector: bigint): Promise<string> {
584
+ /** {@inheritDoc Chain.getOnRampsForOffRamp} */
585
+ async getOnRampsForOffRamp(offRamp: string, sourceChainSelector: bigint): Promise<string[]> {
553
586
  const program = new Program(CCIP_OFFRAMP_IDL, new PublicKey(offRamp), {
554
587
  connection: this.connection,
555
588
  })
@@ -563,15 +596,12 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
563
596
  const {
564
597
  config: { onRamp },
565
598
  } = await program.account.sourceChain.fetch(statePda)
566
- return decodeAddress(
567
- new Uint8Array(onRamp.bytes.slice(0, onRamp.len)),
568
- networkInfo(sourceChainSelector).family,
569
- )
570
- }
571
-
572
- /** {@inheritDoc Chain.getCommitStoreForOffRamp} */
573
- getCommitStoreForOffRamp(offRamp: string): Promise<string> {
574
- return Promise.resolve(offRamp) // Solana supports only CCIP>=1.6, for which OffRamp and CommitStore are the same
599
+ return [
600
+ decodeAddress(
601
+ getAddressBytes(onRamp.bytes).subarray(0, onRamp.len),
602
+ networkInfo(sourceChainSelector).family,
603
+ ),
604
+ ]
575
605
  }
576
606
 
577
607
  /**
@@ -863,7 +893,7 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
863
893
  * @throws {@link CCIPLogDataMissingError} if log data is missing
864
894
  */
865
895
  static decodeCommits(
866
- log: Pick<Log_, 'data'>,
896
+ log: Pick<ChainLog, 'data'>,
867
897
  lane?: Omit<Lane, 'destChainSelector'>,
868
898
  ): CommitReport[] | undefined {
869
899
  // Check if this is a CommitReportAccepted event by looking at the discriminant
@@ -918,7 +948,7 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
918
948
  * @throws {@link CCIPLogDataMissingError} if log data is missing
919
949
  * @throws {@link CCIPExecutionStateInvalidError} if execution state is invalid
920
950
  */
921
- static decodeReceipt(log: Pick<Log_, 'data' | 'tx' | 'index'>): ExecutionReceipt | undefined {
951
+ static decodeReceipt(log: Pick<ChainLog, 'data' | 'tx' | 'index'>): ExecutionReceipt | undefined {
922
952
  // Check if this is a ExecutionStateChanged event by looking at the discriminant
923
953
  if (!log.data || typeof log.data !== 'string') {
924
954
  throw new CCIPLogDataMissingError()
@@ -951,7 +981,7 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
951
981
  } else throw new CCIPExecutionStateInvalidError(util.inspect(decoded.data.state))
952
982
 
953
983
  let returnData
954
- if (log.tx) {
984
+ if (log.tx?.logs) {
955
985
  // use only last receipt per tx+message (i.e. skip intermediary InProgress=1 states for Solana)
956
986
  const laterReceiptLog = log.tx.logs
957
987
  .filter((l) => l.index > log.index)
@@ -1075,13 +1105,8 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
1075
1105
  return (await this.getMessagesInTx(await this.getTransaction(hash)))[0]!
1076
1106
  }
1077
1107
 
1078
- /** {@inheritDoc Chain.getOffchainTokenData} */
1079
- async getOffchainTokenData(request: CCIPRequest): Promise<OffchainTokenData[]> {
1080
- return fetchSolanaOffchainTokenData(request, this)
1081
- }
1082
-
1083
1108
  /**
1084
- * {@inheritDoc Chain.generateUnsignedExecuteReport}
1109
+ * {@inheritDoc Chain.generateUnsignedExecute}
1085
1110
  * @returns instructions - array of instructions to execute the report
1086
1111
  * lookupTables - array of lookup tables for `manuallyExecute` call
1087
1112
  * mainIndex - index of the `manuallyExecute` instruction in the array; last unless
@@ -1089,15 +1114,14 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
1089
1114
  * second to last
1090
1115
  * @throws {@link CCIPExecutionReportChainMismatchError} if message is not a Solana message
1091
1116
  */
1092
- async generateUnsignedExecuteReport({
1117
+ async generateUnsignedExecute({
1093
1118
  payer,
1094
- offRamp,
1095
- execReport,
1096
1119
  ...opts
1097
- }: Parameters<Chain['generateUnsignedExecuteReport']>[0]): Promise<UnsignedSolanaTx> {
1098
- if (!('computeUnits' in execReport.message))
1120
+ }: Parameters<Chain['generateUnsignedExecute']>[0]): Promise<UnsignedSolanaTx> {
1121
+ if (!('input' in opts) || !('message' in opts.input) || !('computeUnits' in opts.input.message))
1099
1122
  throw new CCIPExecutionReportChainMismatchError('Solana')
1100
- const execReport_ = execReport as ExecutionReport<CCIPMessage_V1_6_Solana>
1123
+ const { offRamp, input } = opts
1124
+ const execReport_ = input as ExecutionInput<CCIPMessage_V1_6_Solana>
1101
1125
  return generateUnsignedExecuteReport(
1102
1126
  this,
1103
1127
  new PublicKey(payer),
@@ -1108,11 +1132,11 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
1108
1132
  }
1109
1133
 
1110
1134
  /**
1111
- * {@inheritDoc Chain.executeReport}
1135
+ * {@inheritDoc Chain.execute}
1112
1136
  * @throws {@link CCIPWalletInvalidError} if wallet is not a valid Solana wallet
1113
1137
  */
1114
- async executeReport(
1115
- opts: Parameters<Chain['executeReport']>[0] & {
1138
+ async execute(
1139
+ opts: Parameters<Chain['execute']>[0] & {
1116
1140
  // when cleaning leftover LookUp Tables, wait deactivation grace period (~513 slots) then close ALT
1117
1141
  waitDeactivation?: boolean
1118
1142
  },
@@ -1123,7 +1147,7 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
1123
1147
  let hash
1124
1148
  do {
1125
1149
  try {
1126
- const unsigned = await this.generateUnsignedExecuteReport({
1150
+ const unsigned = await this.generateUnsignedExecute({
1127
1151
  ...opts,
1128
1152
  payer: wallet.publicKey.toBase58(),
1129
1153
  })
@@ -1178,13 +1202,13 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
1178
1202
  if (Array.isArray(data)) {
1179
1203
  if (data.every((e) => typeof e === 'string')) return getErrorFromLogs(data)
1180
1204
  else if (data.every((e) => typeof e === 'object' && 'data' in e && 'address' in e))
1181
- return getErrorFromLogs(data as Log_[])
1205
+ return getErrorFromLogs(data as ChainLog[])
1182
1206
  } else if (typeof data === 'object') {
1183
1207
  if ('transactionLogs' in data && 'transactionMessage' in data) {
1184
- const parsed = getErrorFromLogs(data.transactionLogs as Log_[] | string[])
1208
+ const parsed = getErrorFromLogs(data.transactionLogs as ChainLog[] | string[])
1185
1209
  if (parsed) return { message: data.transactionMessage, ...parsed }
1186
1210
  }
1187
- if ('logs' in data) return getErrorFromLogs(data.logs as Log_[] | string[])
1211
+ if ('logs' in data) return getErrorFromLogs(data.logs as ChainLog[] | string[])
1188
1212
  } else if (typeof data === 'string') {
1189
1213
  const parsedExtraArgs = this.decodeExtraArgs(getDataBytes(data))
1190
1214
  if (parsedExtraArgs) return parsedExtraArgs
@@ -1199,39 +1223,36 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
1199
1223
  /**
1200
1224
  * Solana specialization: use getProgramAccounts to fetch commit reports from PDAs
1201
1225
  */
1202
- override async getCommitReport(
1203
- opts: Parameters<Chain['getCommitReport']>[0],
1204
- ): Promise<CCIPCommit> {
1205
- const { commitStore, request } = opts
1206
- const commitsAroundSeqNum = await this.connection.getProgramAccounts(
1207
- new PublicKey(commitStore),
1208
- {
1209
- filters: [
1210
- {
1211
- // commit report account discriminator filter
1212
- memcmp: {
1213
- offset: 0,
1214
- bytes: encodeBase58(BorshAccountsCoder.accountDiscriminator('CommitReport')),
1215
- },
1226
+ override async getVerifications(
1227
+ opts: Parameters<Chain['getVerifications']>[0],
1228
+ ): Promise<CCIPVerifications> {
1229
+ const { offRamp, request } = opts
1230
+ const commitsAroundSeqNum = await this.connection.getProgramAccounts(new PublicKey(offRamp), {
1231
+ filters: [
1232
+ {
1233
+ // commit report account discriminator filter
1234
+ memcmp: {
1235
+ offset: 0,
1236
+ bytes: encodeBase58(BorshAccountsCoder.accountDiscriminator('CommitReport')),
1216
1237
  },
1217
- {
1218
- // sourceChainSelector filter
1219
- memcmp: {
1220
- offset: 8 + 1,
1221
- bytes: encodeBase58(toLeArray(request.lane.sourceChainSelector, 8)),
1222
- },
1238
+ },
1239
+ {
1240
+ // sourceChainSelector filter
1241
+ memcmp: {
1242
+ offset: 8 + 1,
1243
+ bytes: encodeBase58(toLeArray(request.lane.sourceChainSelector, 8)),
1223
1244
  },
1224
- // memcmp report.min with msg.sequenceNumber's without least-significant byte;
1225
- // this should be ~256 around seqNum, i.e. big chance of a match; requires PDAs not to have been closed
1226
- {
1227
- memcmp: {
1228
- offset: 8 + 1 + 8 + 32 + 8 + /*skip byte*/ 1,
1229
- bytes: encodeBase58(toLeArray(request.message.sequenceNumber, 8).slice(1)),
1230
- },
1245
+ },
1246
+ // memcmp report.min with msg.sequenceNumber's without least-significant byte;
1247
+ // this should be ~256 around seqNum, i.e. big chance of a match; requires PDAs not to have been closed
1248
+ {
1249
+ memcmp: {
1250
+ offset: 8 + 1 + 8 + 32 + 8 + /*skip byte*/ 1,
1251
+ bytes: encodeBase58(toLeArray(request.message.sequenceNumber, 8).slice(1)),
1231
1252
  },
1232
- ],
1233
- },
1234
- )
1253
+ },
1254
+ ],
1255
+ })
1235
1256
  for (const acc of commitsAroundSeqNum) {
1236
1257
  // const merkleRoot = acc.account.data.subarray(8 + 1 + 8, 8 + 1 + 8 + 32)
1237
1258
  const minSeqNr = acc.account.data.readBigUInt64LE(8 + 1 + 8 + 32 + 8)
@@ -1241,7 +1262,7 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
1241
1262
  // we have all the commit report info, but we also need log details (txHash, etc)
1242
1263
  for await (const log of this.getLogs({
1243
1264
  startTime: 1, // just to force getting the oldest log first
1244
- programs: [commitStore],
1265
+ programs: [offRamp],
1245
1266
  address: acc.pubkey.toBase58(),
1246
1267
  topics: ['CommitReportAccepted'],
1247
1268
  })) {
@@ -1254,23 +1275,23 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
1254
1275
  }
1255
1276
  }
1256
1277
  // in case we can't find it, fallback to generic iterating txs
1257
- return super.getCommitReport(opts)
1278
+ return super.getVerifications(opts)
1258
1279
  }
1259
1280
 
1260
1281
  /** {@inheritDoc Chain.getExecutionReceipts} */
1261
1282
  override async *getExecutionReceipts(
1262
1283
  opts: Parameters<Chain['getExecutionReceipts']>[0],
1263
1284
  ): AsyncIterableIterator<CCIPExecution> {
1264
- const { offRamp, sourceChainSelector, commit } = opts
1285
+ const { offRamp, sourceChainSelector, verifications } = opts
1265
1286
  let opts_: Parameters<Chain['getExecutionReceipts']>[0] &
1266
1287
  Parameters<SolanaChain['getLogs']>[0] = opts
1267
- if (commit && sourceChainSelector) {
1288
+ if (sourceChainSelector && verifications && 'report' in verifications) {
1268
1289
  // if we know of commit, use `commit_report` PDA as more specialized address
1269
1290
  const [commitReportPda] = PublicKey.findProgramAddressSync(
1270
1291
  [
1271
1292
  Buffer.from('commit_report'),
1272
1293
  toLeArray(sourceChainSelector, 8),
1273
- bytesToBuffer(commit.report.merkleRoot),
1294
+ bytesToBuffer(verifications.report.merkleRoot),
1274
1295
  ],
1275
1296
  new PublicKey(offRamp),
1276
1297
  )
@@ -1559,7 +1580,11 @@ export class SolanaChain extends Chain<typeof ChainFamily.Solana> {
1559
1580
  }
1560
1581
 
1561
1582
  /**
1562
- * {@inheritDoc ChainStatic.buildMessageForDest}
1583
+ * Returns a copy of a message, populating missing fields like `extraArgs` with defaults.
1584
+ * It's expected to return a message suitable at least for basic token transfers.
1585
+ *
1586
+ * @param message - AnyMessage (from source), containing at least `receiver`
1587
+ * @returns A message suitable for `sendMessage` to this destination chain family
1563
1588
  * @throws {@link CCIPArgumentInvalidError} if tokenReceiver missing when sending tokens with data
1564
1589
  */
1565
1590
  static override buildMessageForDest(
@@ -1,29 +1,10 @@
1
- import { type BN, BorshCoder } from '@coral-xyz/anchor'
2
- import type { PublicKey } from '@solana/web3.js'
1
+ import { BorshCoder } from '@coral-xyz/anchor'
3
2
  import { hexlify } from 'ethers'
4
3
 
5
- import {
6
- CCIPCctpDecodeError,
7
- CCIPCctpMultipleEventsError,
8
- CCIPDataFormatUnsupportedError,
9
- } from '../errors/index.ts'
10
- import { getUsdcAttestation } from '../offchain.ts'
11
- import type { CCIPMessage, CCIPRequest, OffchainTokenData, WithLogger } from '../types.ts'
12
- import { bytesToBuffer, networkInfo, util } from '../utils.ts'
4
+ import type { OffchainTokenData } from '../types.ts'
5
+ import { bytesToBuffer } from '../utils.ts'
13
6
  import { IDL as BASE_TOKEN_POOL } from './idl/1.6.0/BASE_TOKEN_POOL.ts'
14
7
  import { IDL as CCTP_TOKEN_POOL } from './idl/1.6.0/CCIP_CCTP_TOKEN_POOL.ts'
15
- import type { SolanaLog, SolanaTransaction } from './index.ts'
16
- import { hexDiscriminator } from './utils.ts'
17
-
18
- interface CcipCctpMessageSentEvent {
19
- originalSender: PublicKey
20
- remoteChainSelector: BN
21
- msgTotalNonce: BN
22
- eventAddress: PublicKey
23
- sourceDomain: number
24
- cctpNonce: BN
25
- messageSentBytes: Uint8Array
26
- }
27
8
 
28
9
  interface CcipCctpMessageAndAttestation {
29
10
  message: {
@@ -38,84 +19,6 @@ const cctpTokenPoolCoder = new BorshCoder({
38
19
  errors: [...BASE_TOKEN_POOL.errors, ...CCTP_TOKEN_POOL.errors],
39
20
  })
40
21
 
41
- /**
42
- * Analyzes a Solana transaction to extract CcipCctpMessageSentEvent, fetch Circle attestation,
43
- * and encode the data in the format required by the destination chain.
44
- * @param request - CCIP request containing transaction data and chain routing info.
45
- * @param logger - Logger instance for logging messages.
46
- * @returns Array of encoded offchain token data (only one supported for Solana right now).
47
- * @throws Error if transaction hash is missing or CcipCctpMessageSentEvent parsing fails.
48
- */
49
- export async function fetchSolanaOffchainTokenData(
50
- request: Pick<CCIPRequest, 'tx' | 'lane'> & {
51
- message: CCIPMessage
52
- log: Pick<CCIPRequest['log'], 'topics' | 'index' | 'transactionHash' | 'address'>
53
- },
54
- { logger = console }: WithLogger = {},
55
- ): Promise<OffchainTokenData[]> {
56
- if (!request.message.tokenAmounts.length) {
57
- return []
58
- }
59
-
60
- if (request.message.tokenAmounts.length > 1) {
61
- throw new CCIPDataFormatUnsupportedError(
62
- `Expected at most 1 token transfer, found ${request.message.tokenAmounts.length}`,
63
- )
64
- }
65
-
66
- const { networkType } = networkInfo(request.lane.sourceChainSelector)
67
- const txSignature = request.log.transactionHash
68
-
69
- // Parse Solana transaction to find CCTP event
70
- const tx = request.tx as SolanaTransaction
71
- const log = request.log as SolanaLog
72
- const logMessages = tx.tx.meta!.logMessages!
73
- // there may have multiple ccipSend calls in same tx;
74
- // use `invoke [level]` to filter only logs inside this call
75
- const requestInvokeIdx = logMessages.findLastIndex(
76
- (l, i) => i < log.index && l === `Program ${request.log.address} invoke [${log.level}]`,
77
- )
78
- const cctpEvents = []
79
- for (const l of tx.logs) {
80
- if (requestInvokeIdx >= l.index || l.index >= log.index) continue
81
- if (l.topics[0] !== hexDiscriminator('CcipCctpMessageSentEvent')) continue
82
- const decoded = cctpTokenPoolCoder.events.decode(l.data)
83
- if (!decoded) throw new CCIPCctpDecodeError(util.inspect(l))
84
- cctpEvents.push(decoded.data as unknown as CcipCctpMessageSentEvent)
85
- }
86
- const offchainTokenData: OffchainTokenData[] = request.message.tokenAmounts.map(() => undefined)
87
-
88
- // If no CcipCctpMessageSentEvent found, return defaults so we don't block execution
89
- if (cctpEvents.length === 0) {
90
- logger.debug('No USDC/CCTP events found')
91
- return offchainTokenData
92
- }
93
-
94
- // Currently, we only support ONE token per transfer
95
- if (cctpEvents.length > 1) {
96
- throw new CCIPCctpMultipleEventsError(cctpEvents.length, txSignature)
97
- }
98
-
99
- // NOTE: assuming USDC token is the first (and only) token in the CCIP message, we will process the CCTP event.
100
- // If later multi-token transfers support is added, we need to add more info in order to match each token with it's event and offchainTokenData.
101
- const cctpEvent = cctpEvents[0]
102
- if (cctpEvent) {
103
- const message = hexlify(cctpEvent.messageSentBytes)
104
- try {
105
- // Extract message bytes to fetch circle's attestation and then encode offchainTokenData.
106
- const attestation = await getUsdcAttestation(message, networkType)
107
-
108
- offchainTokenData[0] = { _tag: 'usdc', message, attestation }
109
- } catch (error) {
110
- logger.warn(`❌ Solana CCTP: Failed to fetch attestation for ${txSignature}:`, message, error)
111
- }
112
- }
113
-
114
- logger.debug('Got Solana offchain token data', offchainTokenData)
115
-
116
- return offchainTokenData
117
- }
118
-
119
22
  /**
120
23
  * Encodes CCTP message and attestation
121
24
  *
@@ -26,7 +26,7 @@ import {
26
26
  CCIPTokenMintNotFoundError,
27
27
  CCIPTransactionNotFinalizedError,
28
28
  } from '../errors/index.ts'
29
- import type { Log_, WithLogger } from '../types.ts'
29
+ import type { ChainLog, WithLogger } from '../types.ts'
30
30
  import { getDataBytes, sleep } from '../utils.ts'
31
31
  import type { IDL as BASE_TOKEN_POOL_IDL } from './idl/1.6.0/BASE_TOKEN_POOL.ts'
32
32
  import type { UnsignedSolanaTx, Wallet } from './types.ts'
@@ -143,7 +143,7 @@ export function camelToSnakeCase(str: string): string {
143
143
  .replace(/^_/, '')
144
144
  }
145
145
 
146
- type ParsedLog = Pick<Log_, 'topics' | 'index' | 'address' | 'data'> & {
146
+ type ParsedLog = Pick<ChainLog, 'topics' | 'index' | 'address' | 'data'> & {
147
147
  data: string
148
148
  level: number
149
149
  }
@@ -160,7 +160,7 @@ type ParsedLog = Pick<Log_, 'topics' | 'index' | 'address' | 'data'> & {
160
160
  * This function:
161
161
  * 1. Tracks the program call stack to determine which program emitted each log
162
162
  * 2. Extracts the first 8 bytes from base64 "Program data:" logs as topics (event discriminants)
163
- * 3. Converts logs to EVM-compatible Log_ format for CCIP compatibility
163
+ * 3. Converts logs to EVM-compatible ChainLog format for CCIP compatibility
164
164
  * 4. Returns ALL logs from the transaction - filtering should be done by the caller
165
165
  *
166
166
  * @param logs - Array of logMessages from Solana transaction
@@ -215,7 +215,10 @@ export function parseSolanaLogs(logs: readonly string[]): ParsedLog[] {
215
215
  * @returns Parsed error info with program and error details.
216
216
  */
217
217
  export function getErrorFromLogs(
218
- logs_: readonly string[] | readonly Pick<Log_, 'address' | 'index' | 'data' | 'topics'>[] | null,
218
+ logs_:
219
+ | readonly string[]
220
+ | readonly Pick<ChainLog, 'address' | 'index' | 'data' | 'topics'>[]
221
+ | null,
219
222
  ): { program: string; [k: string]: string } | undefined {
220
223
  if (!logs_?.length) return
221
224
  let logs
@@ -229,7 +232,7 @@ export function getErrorFromLogs(
229
232
  (acc, l) =>
230
233
  // if acc is empty (i.e. on last log), or it is emitted by the same program and not a Program data:
231
234
  !acc.length || (l.address === acc[0]!.address && !l.topics.length) ? [l, ...acc] : acc,
232
- [] as Pick<Log_, 'address' | 'index' | 'data'>[],
235
+ [] as Pick<ChainLog, 'address' | 'index' | 'data'>[],
233
236
  )
234
237
  .map(({ data }) => data as string)
235
238
  .reduceRight(
package/src/sui/hasher.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  import { concat, id, keccak256, zeroPadValue } from 'ethers'
2
2
 
3
- import { encodeNumber, encodeRawBytes } from '../aptos/utils.ts'
4
3
  import { CCIPExtraArgsInvalidError, CCIPSuiHasherVersionUnsupportedError } from '../errors/index.ts'
5
4
  import { decodeExtraArgs } from '../extra-args.ts'
6
5
  import { type LeafHasher, LEAF_DOMAIN_SEPARATOR } from '../hasher/common.ts'
7
6
  import { type CCIPMessage, type CCIPMessage_V1_6, CCIPVersion } from '../types.ts'
8
7
  import type { CCIPMessage_V1_6_Sui } from './types.ts'
8
+ import { encodeNumber, encodeRawBytes } from '../shared/bcs-codecs.ts'
9
9
 
10
10
  /**
11
11
  * Creates a leaf hasher for Sui CCIP messages.