@chainlink/ccip-sdk 0.95.0 → 0.97.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/README.md +2 -2
  2. package/dist/all-chains.d.ts +23 -0
  3. package/dist/all-chains.d.ts.map +1 -0
  4. package/dist/all-chains.js +24 -0
  5. package/dist/all-chains.js.map +1 -0
  6. package/dist/api/index.d.ts +31 -19
  7. package/dist/api/index.d.ts.map +1 -1
  8. package/dist/api/index.js +46 -25
  9. package/dist/api/index.js.map +1 -1
  10. package/dist/api/types.d.ts +24 -30
  11. package/dist/api/types.d.ts.map +1 -1
  12. package/dist/aptos/exec.d.ts +2 -2
  13. package/dist/aptos/exec.d.ts.map +1 -1
  14. package/dist/aptos/exec.js.map +1 -1
  15. package/dist/aptos/hasher.d.ts.map +1 -1
  16. package/dist/aptos/hasher.js +1 -1
  17. package/dist/aptos/hasher.js.map +1 -1
  18. package/dist/aptos/index.d.ts +43 -15
  19. package/dist/aptos/index.d.ts.map +1 -1
  20. package/dist/aptos/index.js +112 -105
  21. package/dist/aptos/index.js.map +1 -1
  22. package/dist/aptos/types.d.ts +2 -19
  23. package/dist/aptos/types.d.ts.map +1 -1
  24. package/dist/aptos/types.js +0 -11
  25. package/dist/aptos/types.js.map +1 -1
  26. package/dist/chain.d.ts +734 -174
  27. package/dist/chain.d.ts.map +1 -1
  28. package/dist/chain.js +216 -31
  29. package/dist/chain.js.map +1 -1
  30. package/dist/commits.d.ts +4 -6
  31. package/dist/commits.d.ts.map +1 -1
  32. package/dist/commits.js +4 -4
  33. package/dist/commits.js.map +1 -1
  34. package/dist/errors/CCIPError.d.ts +33 -4
  35. package/dist/errors/CCIPError.d.ts.map +1 -1
  36. package/dist/errors/CCIPError.js +33 -4
  37. package/dist/errors/CCIPError.js.map +1 -1
  38. package/dist/errors/codes.d.ts +5 -0
  39. package/dist/errors/codes.d.ts.map +1 -1
  40. package/dist/errors/codes.js +5 -1
  41. package/dist/errors/codes.js.map +1 -1
  42. package/dist/errors/index.d.ts +2 -2
  43. package/dist/errors/index.d.ts.map +1 -1
  44. package/dist/errors/index.js +2 -2
  45. package/dist/errors/index.js.map +1 -1
  46. package/dist/errors/recovery.d.ts.map +1 -1
  47. package/dist/errors/recovery.js +6 -1
  48. package/dist/errors/recovery.js.map +1 -1
  49. package/dist/errors/specialized.d.ts +1702 -121
  50. package/dist/errors/specialized.d.ts.map +1 -1
  51. package/dist/errors/specialized.js +1729 -125
  52. package/dist/errors/specialized.js.map +1 -1
  53. package/dist/errors/utils.d.ts.map +1 -1
  54. package/dist/errors/utils.js +0 -1
  55. package/dist/errors/utils.js.map +1 -1
  56. package/dist/evm/abi/OffRamp_2_0.d.ts +764 -0
  57. package/dist/evm/abi/OffRamp_2_0.d.ts.map +1 -0
  58. package/dist/evm/abi/OffRamp_2_0.js +744 -0
  59. package/dist/evm/abi/OffRamp_2_0.js.map +1 -0
  60. package/dist/evm/abi/OnRamp_2_0.d.ts +925 -0
  61. package/dist/evm/abi/OnRamp_2_0.d.ts.map +1 -0
  62. package/dist/evm/abi/OnRamp_2_0.js +992 -0
  63. package/dist/evm/abi/OnRamp_2_0.js.map +1 -0
  64. package/dist/evm/const.d.ts +12 -2
  65. package/dist/evm/const.d.ts.map +1 -1
  66. package/dist/evm/const.js +8 -2
  67. package/dist/evm/const.js.map +1 -1
  68. package/dist/evm/errors.d.ts.map +1 -1
  69. package/dist/evm/errors.js +7 -2
  70. package/dist/evm/errors.js.map +1 -1
  71. package/dist/evm/extra-args.d.ts +25 -0
  72. package/dist/evm/extra-args.d.ts.map +1 -0
  73. package/dist/evm/extra-args.js +309 -0
  74. package/dist/evm/extra-args.js.map +1 -0
  75. package/dist/evm/gas.d.ts.map +1 -1
  76. package/dist/evm/gas.js +7 -12
  77. package/dist/evm/gas.js.map +1 -1
  78. package/dist/evm/hasher.d.ts.map +1 -1
  79. package/dist/evm/hasher.js +23 -13
  80. package/dist/evm/hasher.js.map +1 -1
  81. package/dist/evm/index.d.ts +140 -35
  82. package/dist/evm/index.d.ts.map +1 -1
  83. package/dist/evm/index.js +306 -226
  84. package/dist/evm/index.js.map +1 -1
  85. package/dist/evm/messages.d.ts +59 -5
  86. package/dist/evm/messages.d.ts.map +1 -1
  87. package/dist/evm/messages.js +210 -0
  88. package/dist/evm/messages.js.map +1 -1
  89. package/dist/evm/offchain.js.map +1 -1
  90. package/dist/evm/types.d.ts +7 -2
  91. package/dist/evm/types.d.ts.map +1 -1
  92. package/dist/evm/types.js +22 -1
  93. package/dist/evm/types.js.map +1 -1
  94. package/dist/execution.d.ts +62 -22
  95. package/dist/execution.d.ts.map +1 -1
  96. package/dist/execution.js +102 -51
  97. package/dist/execution.js.map +1 -1
  98. package/dist/extra-args.d.ts +113 -4
  99. package/dist/extra-args.d.ts.map +1 -1
  100. package/dist/extra-args.js +38 -3
  101. package/dist/extra-args.js.map +1 -1
  102. package/dist/gas.d.ts +31 -5
  103. package/dist/gas.d.ts.map +1 -1
  104. package/dist/gas.js +43 -9
  105. package/dist/gas.js.map +1 -1
  106. package/dist/index.d.ts +11 -10
  107. package/dist/index.d.ts.map +1 -1
  108. package/dist/index.js +8 -8
  109. package/dist/index.js.map +1 -1
  110. package/dist/requests.d.ts +101 -22
  111. package/dist/requests.d.ts.map +1 -1
  112. package/dist/requests.js +115 -24
  113. package/dist/requests.js.map +1 -1
  114. package/dist/selectors.d.ts.map +1 -1
  115. package/dist/selectors.js +24 -0
  116. package/dist/selectors.js.map +1 -1
  117. package/dist/shared/bcs-codecs.d.ts +61 -0
  118. package/dist/shared/bcs-codecs.d.ts.map +1 -0
  119. package/dist/shared/bcs-codecs.js +102 -0
  120. package/dist/shared/bcs-codecs.js.map +1 -0
  121. package/dist/shared/constants.d.ts +3 -0
  122. package/dist/shared/constants.d.ts.map +1 -0
  123. package/dist/shared/constants.js +3 -0
  124. package/dist/shared/constants.js.map +1 -0
  125. package/dist/solana/exec.d.ts +2 -2
  126. package/dist/solana/exec.d.ts.map +1 -1
  127. package/dist/solana/exec.js.map +1 -1
  128. package/dist/solana/index.d.ts +148 -30
  129. package/dist/solana/index.d.ts.map +1 -1
  130. package/dist/solana/index.js +137 -44
  131. package/dist/solana/index.js.map +1 -1
  132. package/dist/sui/hasher.d.ts.map +1 -1
  133. package/dist/sui/hasher.js +1 -1
  134. package/dist/sui/hasher.js.map +1 -1
  135. package/dist/sui/index.d.ts +49 -19
  136. package/dist/sui/index.d.ts.map +1 -1
  137. package/dist/sui/index.js +76 -43
  138. package/dist/sui/index.js.map +1 -1
  139. package/dist/sui/manuallyExec/encoder.d.ts +2 -2
  140. package/dist/sui/manuallyExec/encoder.d.ts.map +1 -1
  141. package/dist/sui/manuallyExec/encoder.js.map +1 -1
  142. package/dist/sui/manuallyExec/index.d.ts +2 -2
  143. package/dist/sui/manuallyExec/index.d.ts.map +1 -1
  144. package/dist/ton/exec.d.ts +2 -2
  145. package/dist/ton/exec.d.ts.map +1 -1
  146. package/dist/ton/exec.js.map +1 -1
  147. package/dist/ton/index.d.ts +66 -27
  148. package/dist/ton/index.d.ts.map +1 -1
  149. package/dist/ton/index.js +172 -47
  150. package/dist/ton/index.js.map +1 -1
  151. package/dist/ton/send.d.ts +52 -0
  152. package/dist/ton/send.d.ts.map +1 -0
  153. package/dist/ton/send.js +166 -0
  154. package/dist/ton/send.js.map +1 -0
  155. package/dist/ton/types.d.ts +2 -2
  156. package/dist/ton/types.d.ts.map +1 -1
  157. package/dist/ton/types.js.map +1 -1
  158. package/dist/types.d.ts +148 -12
  159. package/dist/types.d.ts.map +1 -1
  160. package/dist/types.js +6 -1
  161. package/dist/types.js.map +1 -1
  162. package/dist/utils.d.ts +79 -4
  163. package/dist/utils.d.ts.map +1 -1
  164. package/dist/utils.js +92 -7
  165. package/dist/utils.js.map +1 -1
  166. package/package.json +16 -11
  167. package/src/all-chains.ts +26 -0
  168. package/src/api/index.ts +58 -34
  169. package/src/api/types.ts +24 -31
  170. package/src/aptos/exec.ts +2 -2
  171. package/src/aptos/hasher.ts +1 -1
  172. package/src/aptos/index.ts +127 -129
  173. package/src/aptos/types.ts +2 -15
  174. package/src/chain.ts +837 -191
  175. package/src/commits.ts +9 -9
  176. package/src/errors/CCIPError.ts +33 -4
  177. package/src/errors/codes.ts +5 -1
  178. package/src/errors/index.ts +2 -1
  179. package/src/errors/recovery.ts +9 -1
  180. package/src/errors/specialized.ts +1745 -132
  181. package/src/errors/utils.ts +0 -1
  182. package/src/evm/abi/OffRamp_2_0.ts +743 -0
  183. package/src/evm/abi/OnRamp_2_0.ts +991 -0
  184. package/src/evm/const.ts +10 -3
  185. package/src/evm/errors.ts +6 -2
  186. package/src/evm/extra-args.ts +360 -0
  187. package/src/evm/gas.ts +14 -13
  188. package/src/evm/hasher.ts +30 -18
  189. package/src/evm/index.ts +376 -281
  190. package/src/evm/messages.ts +323 -11
  191. package/src/evm/offchain.ts +2 -2
  192. package/src/evm/types.ts +20 -2
  193. package/src/execution.ts +126 -71
  194. package/src/extra-args.ts +118 -4
  195. package/src/gas.ts +44 -11
  196. package/src/index.ts +14 -11
  197. package/src/requests.ts +128 -24
  198. package/src/selectors.ts +24 -0
  199. package/src/shared/bcs-codecs.ts +132 -0
  200. package/src/shared/constants.ts +2 -0
  201. package/src/solana/exec.ts +4 -4
  202. package/src/solana/index.ts +170 -82
  203. package/src/sui/hasher.ts +1 -1
  204. package/src/sui/index.ts +88 -56
  205. package/src/sui/manuallyExec/encoder.ts +2 -2
  206. package/src/sui/manuallyExec/index.ts +2 -2
  207. package/src/ton/exec.ts +2 -2
  208. package/src/ton/index.ts +220 -58
  209. package/src/ton/send.ts +222 -0
  210. package/src/ton/types.ts +2 -2
  211. package/src/types.ts +173 -30
  212. package/src/utils.ts +91 -7
  213. package/dist/aptos/utils.d.ts +0 -12
  214. package/dist/aptos/utils.d.ts.map +0 -1
  215. package/dist/aptos/utils.js +0 -15
  216. package/dist/aptos/utils.js.map +0 -1
  217. package/src/aptos/utils.ts +0 -24
package/src/extra-args.ts CHANGED
@@ -8,6 +8,8 @@ import { ChainFamily } from './types.ts'
8
8
  export const EVMExtraArgsV1Tag = id('CCIP EVMExtraArgsV1').substring(0, 10) as '0x97a657c9'
9
9
  /** Tag identifier for EVMExtraArgsV2 encoding. */
10
10
  export const EVMExtraArgsV2Tag = id('CCIP EVMExtraArgsV2').substring(0, 10) as '0x181dcf10'
11
+ /** Tag identifier for GenericExtraArgsV3 encoding (tightly packed binary format). */
12
+ export const GenericExtraArgsV3Tag = id('CCIP GenericExtraArgsV3').substring(0, 10) as '0xa69dd4aa'
11
13
  /** Tag identifier for SVMExtraArgsV1 encoding. */
12
14
  export const SVMExtraArgsV1Tag = id('CCIP SVMExtraArgsV1').substring(0, 10) as '0x1f3b3aba'
13
15
  /** Tag identifier for SuiExtraArgsV1 encoding. */
@@ -15,6 +17,13 @@ export const SuiExtraArgsV1Tag = id('CCIP SuiExtraArgsV1').substring(0, 10) as '
15
17
 
16
18
  /**
17
19
  * EVM extra arguments version 1 with gas limit only.
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * const args: EVMExtraArgsV1 = {
24
+ * gasLimit: 200_000n,
25
+ * }
26
+ * ```
18
27
  */
19
28
  export type EVMExtraArgsV1 = {
20
29
  /** Gas limit for execution on the destination chain. */
@@ -24,14 +33,70 @@ export type EVMExtraArgsV1 = {
24
33
  /**
25
34
  * EVM extra arguments version 2 with out-of-order execution support.
26
35
  * Also known as GenericExtraArgsV2.
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * const args: EVMExtraArgsV2 = {
40
+ * gasLimit: 200_000n,
41
+ * allowOutOfOrderExecution: true,
42
+ * }
43
+ * ```
27
44
  */
28
45
  export type EVMExtraArgsV2 = EVMExtraArgsV1 & {
29
46
  /** Whether to allow out-of-order message execution. */
30
47
  allowOutOfOrderExecution: boolean
31
48
  }
32
49
 
50
+ /**
51
+ * Generic extra arguments version 3 with cross-chain verifiers and executor support.
52
+ * Uses tightly packed binary encoding (NOT ABI-encoded).
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * const args: GenericExtraArgsV3 = {
57
+ * gasLimit: 200_000n,
58
+ * blockConfirmations: 5,
59
+ * ccvs: ['0x1234...'],
60
+ * ccvArgs: ['0x010203'],
61
+ * executor: '0x5678...',
62
+ * executorArgs: '0x',
63
+ * tokenReceiver: '0xReceiverAddress...',
64
+ * tokenArgs: '0x',
65
+ * }
66
+ * ```
67
+ */
68
+ export type GenericExtraArgsV3 = {
69
+ /** Gas limit for execution on the destination chain (uint32). */
70
+ gasLimit: bigint
71
+ /** Number of block confirmations required. */
72
+ blockConfirmations: number
73
+ /** Cross-chain verifier addresses (EVM addresses). */
74
+ ccvs: string[]
75
+ /** Per-CCV arguments (BytesLike). */
76
+ ccvArgs: BytesLike[]
77
+ /** Executor address (EVM address or empty string for none). */
78
+ executor: string
79
+ /** Executor-specific arguments (BytesLike). */
80
+ executorArgs: BytesLike
81
+ /** Token receiver address (checksummed EVM address or hex string). */
82
+ tokenReceiver: string
83
+ /** Token pool-specific arguments (BytesLike). */
84
+ tokenArgs: BytesLike
85
+ }
86
+
33
87
  /**
34
88
  * Solana (SVM) extra arguments version 1.
89
+ *
90
+ * @example
91
+ * ```typescript
92
+ * const args: SVMExtraArgsV1 = {
93
+ * computeUnits: 200_000n,
94
+ * accountIsWritableBitmap: 0n,
95
+ * allowOutOfOrderExecution: true,
96
+ * tokenReceiver: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
97
+ * accounts: [],
98
+ * }
99
+ * ```
35
100
  */
36
101
  export type SVMExtraArgsV1 = {
37
102
  /** Compute units for Solana execution. */
@@ -48,6 +113,16 @@ export type SVMExtraArgsV1 = {
48
113
 
49
114
  /**
50
115
  * Sui extra arguments version 1.
116
+ *
117
+ * @example
118
+ * ```typescript
119
+ * const args: SuiExtraArgsV1 = {
120
+ * gasLimit: 200_000n,
121
+ * allowOutOfOrderExecution: true,
122
+ * tokenReceiver: '0x1234...abcd',
123
+ * receiverObjectIds: ['0xobject1...', '0xobject2...'],
124
+ * }
125
+ * ```
51
126
  */
52
127
  export type SuiExtraArgsV1 = EVMExtraArgsV2 & {
53
128
  /** Token receiver address on Sui. */
@@ -59,13 +134,36 @@ export type SuiExtraArgsV1 = EVMExtraArgsV2 & {
59
134
  /**
60
135
  * Union type of all supported extra arguments formats.
61
136
  */
62
- export type ExtraArgs = EVMExtraArgsV1 | EVMExtraArgsV2 | SVMExtraArgsV1 | SuiExtraArgsV1
137
+ export type ExtraArgs =
138
+ | EVMExtraArgsV1
139
+ | EVMExtraArgsV2
140
+ | GenericExtraArgsV3
141
+ | SVMExtraArgsV1
142
+ | SuiExtraArgsV1
63
143
 
64
144
  /**
65
145
  * Encodes extra arguments for CCIP messages.
66
- * The args are *to* a dest network, but are encoded as a message *from* this source chain
67
- * e.g. Solana uses Borsh to encode extraArgs in its produced requests, even those targetting EVM
68
- **/
146
+ * The args are *to* a dest network, but are encoded as a message *from* this source chain.
147
+ * E.g. Solana uses Borsh to encode extraArgs in its produced requests, even those targeting EVM.
148
+ *
149
+ * @param args - Extra arguments to encode
150
+ * @param from - Source chain family for encoding format (defaults to EVM)
151
+ * @returns Encoded extra arguments as hex string
152
+ * @throws {@link CCIPChainFamilyUnsupportedError} if chain family not supported
153
+ *
154
+ * @example
155
+ * ```typescript
156
+ * import { encodeExtraArgs } from '@chainlink/ccip-sdk'
157
+ *
158
+ * const encoded = encodeExtraArgs({
159
+ * gasLimit: 200_000n,
160
+ * allowOutOfOrderExecution: true,
161
+ * })
162
+ * console.log('Encoded:', encoded) // '0x181dcf10...'
163
+ * ```
164
+ *
165
+ * @see {@link decodeExtraArgs} - Decode extra arguments from bytes
166
+ */
69
167
  export function encodeExtraArgs(args: ExtraArgs, from: ChainFamily = ChainFamily.EVM): string {
70
168
  const chain = supportedChains[from]
71
169
  if (!chain) throw new CCIPChainFamilyUnsupportedError(from)
@@ -77,6 +175,21 @@ export function encodeExtraArgs(args: ExtraArgs, from: ChainFamily = ChainFamily
77
175
  * @param data - Extra arguments bytearray data.
78
176
  * @param from - Optional chain family to narrow decoding attempts.
79
177
  * @returns Extra arguments object if found, undefined otherwise.
178
+ * @throws {@link CCIPChainFamilyUnsupportedError} if specified chain family not supported
179
+ * @throws {@link CCIPExtraArgsParseError} if data cannot be parsed as valid extra args
180
+ *
181
+ * @example
182
+ * ```typescript
183
+ * import { decodeExtraArgs } from '@chainlink/ccip-sdk'
184
+ *
185
+ * const decoded = decodeExtraArgs('0x181dcf10...')
186
+ * if (decoded?._tag === 'EVMExtraArgsV2') {
187
+ * console.log('Gas limit:', decoded.gasLimit)
188
+ * console.log('Out of order:', decoded.allowOutOfOrderExecution)
189
+ * }
190
+ * ```
191
+ *
192
+ * @see {@link encodeExtraArgs} - Encode extra arguments to bytes
80
193
  */
81
194
  export function decodeExtraArgs(
82
195
  data: BytesLike,
@@ -84,6 +197,7 @@ export function decodeExtraArgs(
84
197
  ):
85
198
  | (EVMExtraArgsV1 & { _tag: 'EVMExtraArgsV1' })
86
199
  | (EVMExtraArgsV2 & { _tag: 'EVMExtraArgsV2' })
200
+ | (GenericExtraArgsV3 & { _tag: 'GenericExtraArgsV3' })
87
201
  | (SVMExtraArgsV1 & { _tag: 'SVMExtraArgsV1' })
88
202
  | (SuiExtraArgsV1 & { _tag: 'SuiExtraArgsV1' })
89
203
  | undefined {
package/src/gas.ts CHANGED
@@ -4,13 +4,14 @@ import type { Chain } from './chain.ts'
4
4
  import {
5
5
  CCIPContractTypeInvalidError,
6
6
  CCIPMethodUnsupportedError,
7
+ CCIPOnRampRequiredError,
7
8
  CCIPTokenDecimalsInsufficientError,
8
9
  } from './errors/index.ts'
9
10
  import { discoverOffRamp } from './execution.ts'
10
11
  import { sourceToDestTokenAddresses } from './requests.ts'
11
12
 
12
13
  /**
13
- * A subset of [[MessageInput]] for estimating receive execution gas.
14
+ * A subset of {@link MessageInput} for estimating receive execution gas.
14
15
  */
15
16
  export type EstimateMessageInput = {
16
17
  /** receiver contract address */
@@ -19,7 +20,7 @@ export type EstimateMessageInput = {
19
20
  messageId?: string
20
21
  /** optional sender: zero address will be used if omitted */
21
22
  sender?: string
22
- /** optional data: zero bytes will be used if ommitted */
23
+ /** optional data: zero bytes will be used if omitted */
23
24
  data?: BytesLike
24
25
  /**
25
26
  * optional tokenAmounts; `amount` with either source `token` (as in MessageInput) or
@@ -35,7 +36,7 @@ export type EstimateMessageInput = {
35
36
  }
36
37
 
37
38
  /**
38
- * Options for [[estimateReceiveExecution]] function.
39
+ * Options for {@link estimateReceiveExecution} function.
39
40
  */
40
41
  export type EstimateReceiveExecutionOpts = {
41
42
  /** Source chain instance (for token data retrieval) */
@@ -50,8 +51,34 @@ export type EstimateReceiveExecutionOpts = {
50
51
 
51
52
  /**
52
53
  * Estimate CCIP gasLimit needed to execute a request on a contract receiver.
53
- * @param opts - Options for estimation: source and dest chains, router or ramp address, and message
54
- * @returns Estimated gasLimit.
54
+ *
55
+ * @param opts - {@link EstimateReceiveExecutionOpts} for estimation
56
+ * @returns Estimated gasLimit
57
+ *
58
+ * @throws {@link CCIPMethodUnsupportedError} if dest chain doesn't support estimation
59
+ * @throws {@link CCIPContractTypeInvalidError} if routerOrRamp is not a valid contract type
60
+ * @throws {@link CCIPTokenDecimalsInsufficientError} if dest token has insufficient decimals
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * import { estimateReceiveExecution, EVMChain } from '@chainlink/ccip-sdk'
65
+ *
66
+ * const source = await EVMChain.fromUrl('https://rpc.sepolia.org')
67
+ * const dest = await EVMChain.fromUrl('https://rpc.fuji.avax.network')
68
+ *
69
+ * const gasLimit = await estimateReceiveExecution({
70
+ * source,
71
+ * dest,
72
+ * routerOrRamp: '0xRouter...',
73
+ * message: {
74
+ * sender: '0x...',
75
+ * receiver: '0x...',
76
+ * data: '0x...',
77
+ * tokenAmounts: [],
78
+ * },
79
+ * })
80
+ * console.log('Estimated gas:', gasLimit)
81
+ * ```
55
82
  */
56
83
  export async function estimateReceiveExecution({
57
84
  source,
@@ -69,12 +96,18 @@ export async function estimateReceiveExecution({
69
96
  onRamp = await source.getOnRampForRouter(routerOrRamp, dest.network.chainSelector)
70
97
  else onRamp = routerOrRamp
71
98
  offRamp = await discoverOffRamp(source, dest, onRamp, source)
72
- } catch {
73
- const tnv = await dest.typeAndVersion(routerOrRamp)
74
- if (!tnv[0].includes('OffRamp'))
75
- throw new CCIPContractTypeInvalidError(routerOrRamp, tnv[2], ['OffRamp'])
76
- offRamp = routerOrRamp
77
- onRamp = await dest.getOnRampForOffRamp(offRamp, source.network.chainSelector)
99
+ } catch (sourceErr) {
100
+ try {
101
+ const tnv = await dest.typeAndVersion(routerOrRamp)
102
+ if (!tnv[0].includes('OffRamp'))
103
+ throw new CCIPContractTypeInvalidError(routerOrRamp, tnv[2], ['OffRamp'])
104
+ offRamp = routerOrRamp
105
+ const onRamps = await dest.getOnRampsForOffRamp(offRamp, source.network.chainSelector)
106
+ if (!onRamps.length) throw new CCIPOnRampRequiredError()
107
+ onRamp = onRamps[onRamps.length - 1]!
108
+ } catch {
109
+ throw sourceErr // re-throw original error
110
+ }
78
111
  }
79
112
 
80
113
  const destTokenAmounts = await Promise.all(
package/src/index.ts CHANGED
@@ -1,5 +1,14 @@
1
+ /**
2
+ * \@chainlink/ccip-sdk - SDK for interacting with Chainlink CCIP (Cross-Chain Interoperability Protocol).
3
+ *
4
+ * This package provides tools for sending cross-chain messages, tracking message status,
5
+ * and executing manual message delivery across supported blockchain networks.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+
1
10
  export type {
2
- APICCIPRequest,
11
+ APICCIPRequestMetadata,
3
12
  APIErrorResponse,
4
13
  CCIPAPIClientContext,
5
14
  LaneLatencyResponse,
@@ -15,7 +24,9 @@ export type {
15
24
  GetBalanceOpts,
16
25
  LogFilter,
17
26
  RateLimiterState,
27
+ RegistryTokenConfig,
18
28
  TokenInfo,
29
+ TokenPoolConfig,
19
30
  TokenPoolRemote,
20
31
  } from './chain.ts'
21
32
  export { DEFAULT_API_RETRY_CONFIG } from './chain.ts'
@@ -32,14 +43,14 @@ export {
32
43
  export { estimateReceiveExecution } from './gas.ts'
33
44
  export { decodeMessage, getMessagesForSender, sourceToDestTokenAddresses } from './requests.ts'
34
45
  export {
35
- type CCIPCommit,
36
46
  type CCIPExecution,
37
47
  type CCIPMessage,
38
48
  type CCIPRequest,
49
+ type CCIPVerifications,
39
50
  type ChainTransaction,
40
51
  type CommitReport,
52
+ type ExecutionInput,
41
53
  type ExecutionReceipt,
42
- type ExecutionReport,
43
54
  type Lane,
44
55
  type Logger,
45
56
  type MessageInput,
@@ -87,11 +98,3 @@ import { ChainFamily, NetworkType } from './types.ts'
87
98
  export { AptosChain, ChainFamily, EVMChain, NetworkType, SolanaChain, SuiChain, TONChain }
88
99
  // use `supportedChains` to override/register derived classes, if needed
89
100
  export { supportedChains } from './supported-chains.ts'
90
- // import `allSupportedChains` to get them all registered, in tree-shaken environments
91
- export const allSupportedChains = {
92
- [ChainFamily.EVM]: EVMChain,
93
- [ChainFamily.Solana]: SolanaChain,
94
- [ChainFamily.Aptos]: AptosChain,
95
- [ChainFamily.Sui]: SuiChain,
96
- [ChainFamily.TON]: TONChain,
97
- }
package/src/requests.ts CHANGED
@@ -46,6 +46,14 @@ function decodeJsonMessage(data: Record<string, unknown> | undefined) {
46
46
  source_chain_selector?: string
47
47
  sourceChainSelector?: string
48
48
  extraArgs?: string | Record<string, unknown>
49
+ sequenceNumber?: bigint
50
+ messageNumber?: bigint
51
+ tokenTransfer?: {
52
+ destExecData: string
53
+ destGasAmount?: bigint
54
+ token?: string
55
+ sourceTokenAddress?: string
56
+ }[]
49
57
  tokenAmounts: {
50
58
  destExecData: string
51
59
  destGasAmount?: bigint
@@ -60,6 +68,7 @@ function decodeJsonMessage(data: Record<string, unknown> | undefined) {
60
68
  totalAmount: bigint
61
69
  }
62
70
  }
71
+ receipts?: { feeTokenAmount: bigint }[]
63
72
  sourceNetworkInfo?: { chainSelector: string }
64
73
  destNetworkInfo?: { chainSelector: string }
65
74
  }
@@ -82,7 +91,7 @@ function decodeJsonMessage(data: Record<string, unknown> | undefined) {
82
91
  ? BigInt(v as string | number | bigint)
83
92
  : k?.match(/(^dest.*address)|(receiver|offramp|accounts)/i)
84
93
  ? decodeAddress(v as BytesLike, destFamily)
85
- : k?.match(/((source.*address)|sender|origin|onramp|(feetoken$)|(token.*address$))/i)
94
+ : k?.match(/((source.*address)|sender|issuer|origin|onramp|(feetoken$)|(token.*address$))/i)
86
95
  ? decodeAddress(v as BytesLike, sourceFamily)
87
96
  : v instanceof Uint8Array ||
88
97
  (Array.isArray(v) && v.length >= 4 && v.every((e) => typeof e === 'number'))
@@ -90,6 +99,10 @@ function decodeJsonMessage(data: Record<string, unknown> | undefined) {
90
99
  : v,
91
100
  ) as typeof data_
92
101
 
102
+ if (data_.tokenTransfer) {
103
+ data_.tokenAmounts = data_.tokenTransfer
104
+ delete data_.tokenTransfer
105
+ }
93
106
  for (const ta of data_.tokenAmounts) {
94
107
  if (ta.token && !ta.sourceTokenAddress) ta.sourceTokenAddress = ta.token
95
108
  if (!ta.token && ta.sourceTokenAddress) ta.token = ta.sourceTokenAddress
@@ -121,14 +134,41 @@ function decodeJsonMessage(data: Record<string, unknown> | undefined) {
121
134
  data_.feeToken = data_.fees.fixedFeesDetails.tokenAddress
122
135
  data_.feeTokenAmount = data_.fees.fixedFeesDetails.totalAmount
123
136
  }
137
+ if (data_.sequenceNumber == null && data_.messageNumber != null) {
138
+ data_.sequenceNumber = data_.messageNumber
139
+ }
140
+ if (!data_.feeTokenAmount && data_.receipts) {
141
+ data_.feeTokenAmount = data_.receipts.reduce(
142
+ (acc, receipt) => acc + receipt.feeTokenAmount,
143
+ BigInt(0),
144
+ )
145
+ }
124
146
 
125
147
  return data_ as unknown as CCIPMessage
126
148
  }
127
149
 
128
150
  /**
129
- * Decodes hex strings, bytearrays, JSON strings and raw objects as CCIPMessages
130
- * Does minimal validation, but converts objects in the format expected by ccip-tools-ts
131
- **/
151
+ * Decodes hex strings, bytearrays, JSON strings and raw objects as CCIPMessages.
152
+ * Does minimal validation, but converts objects in the format expected by ccip-tools-ts.
153
+ *
154
+ * @param data - Data to decode (hex string, Uint8Array, JSON string, or object)
155
+ * @returns Decoded CCIPMessage
156
+ * @throws {@link CCIPMessageDecodeError} if data cannot be decoded as a valid message
157
+ * @throws {@link CCIPMessageInvalidError} if message structure is invalid or missing required fields
158
+ *
159
+ * @example
160
+ * ```typescript
161
+ * import { decodeMessage } from '@chainlink/ccip-sdk'
162
+ *
163
+ * // Decode from JSON string
164
+ * const message = decodeMessage('{"header":{"sourceChainSelector":"123",...}')
165
+ *
166
+ * // Decode from hex-encoded bytes
167
+ * const message = decodeMessage('0x...')
168
+ *
169
+ * console.log('Message ID:', message.messageId)
170
+ * ```
171
+ */
132
172
  export function decodeMessage(data: string | Uint8Array | Record<string, unknown>): CCIPMessage {
133
173
  if (
134
174
  (typeof data === 'string' && data.startsWith('{')) ||
@@ -151,10 +191,11 @@ export function decodeMessage(data: string | Uint8Array | Record<string, unknown
151
191
  }
152
192
 
153
193
  /**
154
- * Populates missing required fields (e.g. `extraArgs`) from AnyMessage
155
- * @param message - partial AnyMessage
156
- * @returns original message or shallow copy with defaults for required fields
157
- **/
194
+ * Populates missing required fields (e.g. `extraArgs`) from AnyMessage.
195
+ * @param message - Partial AnyMessage with at least receiver
196
+ * @param dest - Destination chain family to build message for
197
+ * @returns Original message or shallow copy with defaults for required fields
198
+ */
158
199
  export function buildMessageForDest(message: MessageInput, dest: ChainFamily): AnyMessage {
159
200
  const chain = supportedChains[dest] ?? Chain
160
201
  return chain.buildMessageForDest(message)
@@ -162,10 +203,14 @@ export function buildMessageForDest(message: MessageInput, dest: ChainFamily): A
162
203
 
163
204
  /**
164
205
  * Fetch all CCIP messages in a transaction.
165
- * @param source - Chain
206
+ * @param source - Source chain instance
166
207
  * @param tx - ChainTransaction to search in
167
208
  * @returns CCIP requests (messages) in the transaction (at least one)
168
- **/
209
+ * @throws {@link CCIPChainFamilyUnsupportedError} if chain family not supported for legacy messages
210
+ * @throws {@link CCIPMessageNotFoundInTxError} if no CCIP messages found in transaction
211
+ *
212
+ * @see {@link getMessageById} - Search by messageId when tx hash unknown
213
+ */
169
214
  export async function getMessagesInTx(source: Chain, tx: ChainTransaction): Promise<CCIPRequest[]> {
170
215
  // RPC fallback
171
216
  const requests: CCIPRequest[] = []
@@ -188,17 +233,36 @@ export async function getMessagesInTx(source: Chain, tx: ChainTransaction): Prom
188
233
  }
189
234
  requests.push({ lane, message, log, tx })
190
235
  }
191
- if (!requests.length) throw new CCIPMessageNotFoundInTxError(tx.hash)
236
+ if (!requests.length)
237
+ throw new CCIPMessageNotFoundInTxError(tx.hash, { context: { network: source.network.name } })
192
238
  return requests
193
239
  }
194
240
 
195
241
  /**
196
- * Fetch a CCIP message by its messageId from RPC (slow).
197
- * Should be called *after* generic Chain implementation, which fetches from API if available.
198
- * @param source - Provider to fetch logs from.
199
- * @param messageId - MessageId to search for.
200
- * @param opts - Optional hints for pagination (e.g., `address` for onRamp, `page` for pagination size).
201
- * @returns CCIPRequest with given messageId.
242
+ * Fetch a CCIP message by messageId from RPC logs (slow scan).
243
+ *
244
+ * This is the fallback implementation called by {@link Chain.getMessageById}
245
+ * when the API client is unavailable or fails.
246
+ *
247
+ * @param source - Source chain to scan logs from
248
+ * @param messageId - Message ID to search for
249
+ * @param opts - Optional hints (onRamp address narrows search, page controls batch size)
250
+ * @returns CCIPRequest matching the messageId
251
+ *
252
+ * @throws {@link CCIPMessageIdNotFoundError} if message not found after scanning all logs
253
+ *
254
+ * @example
255
+ *
256
+ * ```typescript
257
+ * import { getMessageById, EVMChain } from '@chainlink/ccip-sdk'
258
+ *
259
+ * const source = await EVMChain.fromUrl('https://rpc.sepolia.org')
260
+ * const request = await getMessageById(source, '0xabc123...', {
261
+ * onRamp: '0xOnRampAddress...',
262
+ * })
263
+ * console.log(`Found: seqNr=${request.message.sequenceNumber}`)
264
+ * ```
265
+ *
202
266
  * @internal
203
267
  */
204
268
  export async function getMessageById(
@@ -243,9 +307,10 @@ const BLOCK_LOG_WINDOW_SIZE = 5000
243
307
  * Fetches all CCIP messages contained in a given commit batch.
244
308
  * @param source - The source chain.
245
309
  * @param request - The CCIP request containing lane and message info.
246
- * @param seqNrRange - Object containing minSeqNr and maxSeqNr for the batch range.
310
+ * @param range - Object containing minSeqNr and maxSeqNr for the batch range.
247
311
  * @param opts - Optional log filtering parameters.
248
312
  * @returns Array of messages in the batch.
313
+ * @see {@link getVerifications} - Get commit report to determine batch range
249
314
  */
250
315
  export async function getMessagesInBatch<
251
316
  C extends Chain,
@@ -287,6 +352,7 @@ export async function getMessagesInBatch<
287
352
  const message = (source.constructor as ChainStatic).decodeMessage(log)
288
353
  if (
289
354
  !message ||
355
+ !('sequenceNumber' in message) ||
290
356
  ('destChainSelector' in message &&
291
357
  message.destChainSelector !== request.lane.destChainSelector)
292
358
  )
@@ -308,6 +374,7 @@ export async function getMessagesInBatch<
308
374
  const message = (source.constructor as ChainStatic).decodeMessage(log)
309
375
  if (
310
376
  !message ||
377
+ !('sequenceNumber' in message) ||
311
378
  ('destChainSelector' in message &&
312
379
  message.destChainSelector !== request.lane.destChainSelector)
313
380
  )
@@ -332,6 +399,22 @@ export async function getMessagesInBatch<
332
399
  * @param sender - Sender address.
333
400
  * @param filter - Log filter options.
334
401
  * @returns Async generator of CCIP requests.
402
+ * @throws {@link CCIPChainFamilyUnsupportedError} if chain family not supported for legacy messages
403
+ *
404
+ * @example
405
+ * ```typescript
406
+ * import { getMessagesForSender, EVMChain } from '@chainlink/ccip-sdk'
407
+ *
408
+ * const chain = await EVMChain.fromUrl('https://rpc.sepolia.org')
409
+ *
410
+ * for await (const request of getMessagesForSender(chain, '0xSenderAddress', {})) {
411
+ * console.log('Message ID:', request.message.messageId)
412
+ * console.log('Destination:', request.lane.destChainSelector)
413
+ * }
414
+ * ```
415
+ *
416
+ * @see {@link getMessagesInTx} - Fetch from specific transaction
417
+ * @see {@link getMessageById} - Search by messageId
335
418
  */
336
419
  export async function* getMessagesForSender(
337
420
  source: Chain,
@@ -369,12 +452,33 @@ export async function* getMessagesForSender(
369
452
  }
370
453
 
371
454
  /**
372
- * Map source `token` to `sourcePoolAddress + destTokenAddress`.
373
- * @param source - Source chain.
374
- * @param destChainSelector - Destination network selector.
375
- * @param onRamp - Contract address.
376
- * @param sourceTokenAmount - tokenAmount object, usually containing `token` and `amount` properties.
377
- * @returns tokenAmount object with `sourcePoolAddress`, `sourceTokenAddress`, `destTokenAddress`, and remaining properties.
455
+ * Map source token to its pool address and destination token address.
456
+ *
457
+ * Resolves token routing by querying the TokenAdminRegistry and TokenPool
458
+ * to find the corresponding destination chain token.
459
+ *
460
+ * @param source - Source chain instance
461
+ * @param destChainSelector - Destination chain selector
462
+ * @param onRamp - OnRamp contract address
463
+ * @param sourceTokenAmount - Token amount object containing `token` and `amount`
464
+ * @returns Extended token amount with `sourcePoolAddress`, `sourceTokenAddress`, and `destTokenAddress`
465
+ *
466
+ * @throws {@link CCIPTokenNotInRegistryError} if token is not registered in TokenAdminRegistry
467
+ *
468
+ * @example
469
+ * ```typescript
470
+ * import { sourceToDestTokenAddresses, EVMChain } from '@chainlink/ccip-sdk'
471
+ *
472
+ * const source = await EVMChain.fromUrl('https://rpc.sepolia.org')
473
+ * const tokenAmount = await sourceToDestTokenAddresses(
474
+ * source,
475
+ * destChainSelector,
476
+ * '0xOnRamp...',
477
+ * { token: '0xLINK...', amount: 1000000000000000000n }
478
+ * )
479
+ * console.log(`Pool: ${tokenAmount.sourcePoolAddress}`)
480
+ * console.log(`Dest token: ${tokenAmount.destTokenAddress}`)
481
+ * ```
378
482
  */
379
483
  export async function sourceToDestTokenAddresses<S extends { token: string }>(
380
484
  source: Chain,
package/src/selectors.ts CHANGED
@@ -721,6 +721,12 @@ const selectors: Selectors = {
721
721
  network_type: 'TESTNET',
722
722
  family: 'EVM',
723
723
  },
724
+ '3343': {
725
+ selector: 6325494908023253251n,
726
+ name: 'edge-mainnet',
727
+ network_type: 'MAINNET',
728
+ family: 'EVM',
729
+ },
724
730
  '3636': {
725
731
  selector: 1467223411771711614n,
726
732
  name: 'bitcoin-testnet-botanix',
@@ -1003,6 +1009,12 @@ const selectors: Selectors = {
1003
1009
  network_type: 'MAINNET',
1004
1010
  family: 'EVM',
1005
1011
  },
1012
+ '33431': {
1013
+ selector: 13222148116102326311n,
1014
+ name: 'edge-testnet',
1015
+ network_type: 'TESTNET',
1016
+ family: 'EVM',
1017
+ },
1006
1018
  '34443': {
1007
1019
  selector: 7264351850409363825n,
1008
1020
  name: 'ethereum-mainnet-mode-1',
@@ -1087,6 +1099,12 @@ const selectors: Selectors = {
1087
1099
  network_type: 'TESTNET',
1088
1100
  family: 'EVM',
1089
1101
  },
1102
+ '46630': {
1103
+ selector: 2032988798112970440n,
1104
+ name: 'robinhood-testnet',
1105
+ network_type: 'TESTNET',
1106
+ family: 'EVM',
1107
+ },
1090
1108
  '47763': {
1091
1109
  selector: 7222032299962346917n,
1092
1110
  name: 'neox-mainnet',
@@ -1337,6 +1355,12 @@ const selectors: Selectors = {
1337
1355
  network_type: 'MAINNET',
1338
1356
  family: 'EVM',
1339
1357
  },
1358
+ '202601': {
1359
+ selector: 1091131740251125869n,
1360
+ name: 'ethereum-testnet-sepolia-ronin-1',
1361
+ network_type: 'TESTNET',
1362
+ family: 'EVM',
1363
+ },
1340
1364
  '421613': {
1341
1365
  selector: 6101244977088475029n,
1342
1366
  name: 'ethereum-testnet-goerli-arbitrum-1',