@chainlink/ccip-sdk 0.0.0 → 0.90.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 (319) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +109 -0
  3. package/dist/aptos/exec.d.ts +18 -0
  4. package/dist/aptos/exec.d.ts.map +1 -0
  5. package/dist/aptos/exec.js +55 -0
  6. package/dist/aptos/exec.js.map +1 -0
  7. package/dist/aptos/hasher.d.ts +11 -0
  8. package/dist/aptos/hasher.d.ts.map +1 -0
  9. package/dist/aptos/hasher.js +62 -0
  10. package/dist/aptos/hasher.js.map +1 -0
  11. package/dist/aptos/index.d.ts +92 -0
  12. package/dist/aptos/index.d.ts.map +1 -0
  13. package/dist/aptos/index.js +482 -0
  14. package/dist/aptos/index.js.map +1 -0
  15. package/dist/aptos/logs.d.ts +9 -0
  16. package/dist/aptos/logs.d.ts.map +1 -0
  17. package/dist/aptos/logs.js +167 -0
  18. package/dist/aptos/logs.js.map +1 -0
  19. package/dist/aptos/send.d.ts +11 -0
  20. package/dist/aptos/send.d.ts.map +1 -0
  21. package/dist/aptos/send.js +78 -0
  22. package/dist/aptos/send.js.map +1 -0
  23. package/dist/aptos/token.d.ts +4 -0
  24. package/dist/aptos/token.d.ts.map +1 -0
  25. package/dist/aptos/token.js +134 -0
  26. package/dist/aptos/token.js.map +1 -0
  27. package/dist/aptos/types.d.ts +78 -0
  28. package/dist/aptos/types.d.ts.map +1 -0
  29. package/dist/aptos/types.js +60 -0
  30. package/dist/aptos/types.js.map +1 -0
  31. package/dist/aptos/utils.d.ts +12 -0
  32. package/dist/aptos/utils.d.ts.map +1 -0
  33. package/dist/aptos/utils.js +15 -0
  34. package/dist/aptos/utils.js.map +1 -0
  35. package/dist/chain.d.ts +344 -0
  36. package/dist/chain.d.ts.map +1 -0
  37. package/dist/chain.js +41 -0
  38. package/dist/chain.js.map +1 -0
  39. package/dist/commits.d.ts +25 -0
  40. package/dist/commits.d.ts.map +1 -0
  41. package/dist/commits.js +29 -0
  42. package/dist/commits.js.map +1 -0
  43. package/dist/evm/abi/BurnMintERC677Token.d.ts +602 -0
  44. package/dist/evm/abi/BurnMintERC677Token.d.ts.map +1 -0
  45. package/dist/evm/abi/BurnMintERC677Token.js +488 -0
  46. package/dist/evm/abi/BurnMintERC677Token.js.map +1 -0
  47. package/dist/evm/abi/CommitStore_1_2.d.ts +688 -0
  48. package/dist/evm/abi/CommitStore_1_2.d.ts.map +1 -0
  49. package/dist/evm/abi/CommitStore_1_2.js +638 -0
  50. package/dist/evm/abi/CommitStore_1_2.js.map +1 -0
  51. package/dist/evm/abi/CommitStore_1_5.d.ts +708 -0
  52. package/dist/evm/abi/CommitStore_1_5.d.ts.map +1 -0
  53. package/dist/evm/abi/CommitStore_1_5.js +675 -0
  54. package/dist/evm/abi/CommitStore_1_5.js.map +1 -0
  55. package/dist/evm/abi/FeeQuoter_1_6.d.ts +1770 -0
  56. package/dist/evm/abi/FeeQuoter_1_6.d.ts.map +1 -0
  57. package/dist/evm/abi/FeeQuoter_1_6.js +1904 -0
  58. package/dist/evm/abi/FeeQuoter_1_6.js.map +1 -0
  59. package/dist/evm/abi/LockReleaseTokenPool_1_5.d.ts +1116 -0
  60. package/dist/evm/abi/LockReleaseTokenPool_1_5.d.ts.map +1 -0
  61. package/dist/evm/abi/LockReleaseTokenPool_1_5.js +1096 -0
  62. package/dist/evm/abi/LockReleaseTokenPool_1_5.js.map +1 -0
  63. package/dist/evm/abi/LockReleaseTokenPool_1_5_1.d.ts +1306 -0
  64. package/dist/evm/abi/LockReleaseTokenPool_1_5_1.d.ts.map +1 -0
  65. package/dist/evm/abi/LockReleaseTokenPool_1_5_1.js +1278 -0
  66. package/dist/evm/abi/LockReleaseTokenPool_1_5_1.js.map +1 -0
  67. package/dist/evm/abi/LockReleaseTokenPool_1_6_1.d.ts +1290 -0
  68. package/dist/evm/abi/LockReleaseTokenPool_1_6_1.d.ts.map +1 -0
  69. package/dist/evm/abi/LockReleaseTokenPool_1_6_1.js +1288 -0
  70. package/dist/evm/abi/LockReleaseTokenPool_1_6_1.js.map +1 -0
  71. package/dist/evm/abi/OffRamp_1_2.d.ts +1217 -0
  72. package/dist/evm/abi/OffRamp_1_2.d.ts.map +1 -0
  73. package/dist/evm/abi/OffRamp_1_2.js +1204 -0
  74. package/dist/evm/abi/OffRamp_1_2.js.map +1 -0
  75. package/dist/evm/abi/OffRamp_1_5.d.ts +1271 -0
  76. package/dist/evm/abi/OffRamp_1_5.d.ts.map +1 -0
  77. package/dist/evm/abi/OffRamp_1_5.js +1273 -0
  78. package/dist/evm/abi/OffRamp_1_5.js.map +1 -0
  79. package/dist/evm/abi/OffRamp_1_6.d.ts +1472 -0
  80. package/dist/evm/abi/OffRamp_1_6.d.ts.map +1 -0
  81. package/dist/evm/abi/OffRamp_1_6.js +1529 -0
  82. package/dist/evm/abi/OffRamp_1_6.js.map +1 -0
  83. package/dist/evm/abi/OnRamp_1_2.d.ts +1391 -0
  84. package/dist/evm/abi/OnRamp_1_2.d.ts.map +1 -0
  85. package/dist/evm/abi/OnRamp_1_2.js +1343 -0
  86. package/dist/evm/abi/OnRamp_1_2.js.map +1 -0
  87. package/dist/evm/abi/OnRamp_1_5.d.ts +1443 -0
  88. package/dist/evm/abi/OnRamp_1_5.d.ts.map +1 -0
  89. package/dist/evm/abi/OnRamp_1_5.js +1427 -0
  90. package/dist/evm/abi/OnRamp_1_5.js.map +1 -0
  91. package/dist/evm/abi/OnRamp_1_6.d.ts +796 -0
  92. package/dist/evm/abi/OnRamp_1_6.d.ts.map +1 -0
  93. package/dist/evm/abi/OnRamp_1_6.js +880 -0
  94. package/dist/evm/abi/OnRamp_1_6.js.map +1 -0
  95. package/dist/evm/abi/Router.d.ts +541 -0
  96. package/dist/evm/abi/Router.d.ts.map +1 -0
  97. package/dist/evm/abi/Router.js +508 -0
  98. package/dist/evm/abi/Router.js.map +1 -0
  99. package/dist/evm/abi/TokenAdminRegistry_1_5.d.ts +373 -0
  100. package/dist/evm/abi/TokenAdminRegistry_1_5.d.ts.map +1 -0
  101. package/dist/evm/abi/TokenAdminRegistry_1_5.js +333 -0
  102. package/dist/evm/abi/TokenAdminRegistry_1_5.js.map +1 -0
  103. package/dist/evm/const.d.ts +27 -0
  104. package/dist/evm/const.d.ts.map +1 -0
  105. package/dist/evm/const.js +63 -0
  106. package/dist/evm/const.js.map +1 -0
  107. package/dist/evm/errors.d.ts +36 -0
  108. package/dist/evm/errors.d.ts.map +1 -0
  109. package/dist/evm/errors.js +192 -0
  110. package/dist/evm/errors.js.map +1 -0
  111. package/dist/evm/hasher.d.ts +5 -0
  112. package/dist/evm/hasher.d.ts.map +1 -0
  113. package/dist/evm/hasher.js +116 -0
  114. package/dist/evm/hasher.js.map +1 -0
  115. package/dist/evm/index.d.ts +121 -0
  116. package/dist/evm/index.d.ts.map +1 -0
  117. package/dist/evm/index.js +904 -0
  118. package/dist/evm/index.js.map +1 -0
  119. package/dist/evm/messages.d.ts +35 -0
  120. package/dist/evm/messages.d.ts.map +1 -0
  121. package/dist/evm/messages.js +11 -0
  122. package/dist/evm/messages.js.map +1 -0
  123. package/dist/evm/offchain.d.ts +16 -0
  124. package/dist/evm/offchain.d.ts.map +1 -0
  125. package/dist/evm/offchain.js +142 -0
  126. package/dist/evm/offchain.js.map +1 -0
  127. package/dist/execution.d.ts +80 -0
  128. package/dist/execution.d.ts.map +1 -0
  129. package/dist/execution.js +91 -0
  130. package/dist/execution.js.map +1 -0
  131. package/dist/extra-args.d.ts +45 -0
  132. package/dist/extra-args.d.ts.map +1 -0
  133. package/dist/extra-args.js +44 -0
  134. package/dist/extra-args.js.map +1 -0
  135. package/dist/gas.d.ts +27 -0
  136. package/dist/gas.d.ts.map +1 -0
  137. package/dist/gas.js +80 -0
  138. package/dist/gas.js.map +1 -0
  139. package/dist/hasher/common.d.ts +12 -0
  140. package/dist/hasher/common.d.ts.map +1 -0
  141. package/dist/hasher/common.js +19 -0
  142. package/dist/hasher/common.js.map +1 -0
  143. package/dist/hasher/hasher.d.ts +4 -0
  144. package/dist/hasher/hasher.d.ts.map +1 -0
  145. package/dist/hasher/hasher.js +11 -0
  146. package/dist/hasher/hasher.js.map +1 -0
  147. package/dist/hasher/index.d.ts +4 -0
  148. package/dist/hasher/index.d.ts.map +1 -0
  149. package/dist/hasher/index.js +4 -0
  150. package/dist/hasher/index.js.map +1 -0
  151. package/dist/hasher/merklemulti.d.ts +58 -0
  152. package/dist/hasher/merklemulti.d.ts.map +1 -0
  153. package/dist/hasher/merklemulti.js +257 -0
  154. package/dist/hasher/merklemulti.js.map +1 -0
  155. package/dist/index.d.ts +13 -0
  156. package/dist/index.d.ts.map +1 -0
  157. package/dist/index.js +13 -0
  158. package/dist/index.js.map +1 -0
  159. package/dist/offchain.d.ts +20 -0
  160. package/dist/offchain.d.ts.map +1 -0
  161. package/dist/offchain.js +59 -0
  162. package/dist/offchain.js.map +1 -0
  163. package/dist/requests.d.ts +48 -0
  164. package/dist/requests.d.ts.map +1 -0
  165. package/dist/requests.js +286 -0
  166. package/dist/requests.js.map +1 -0
  167. package/dist/selectors.d.ts +9 -0
  168. package/dist/selectors.d.ts.map +1 -0
  169. package/dist/selectors.js +1330 -0
  170. package/dist/selectors.js.map +1 -0
  171. package/dist/solana/cleanup.d.ts +15 -0
  172. package/dist/solana/cleanup.d.ts.map +1 -0
  173. package/dist/solana/cleanup.js +159 -0
  174. package/dist/solana/cleanup.js.map +1 -0
  175. package/dist/solana/exec.d.ts +15 -0
  176. package/dist/solana/exec.d.ts.map +1 -0
  177. package/dist/solana/exec.js +417 -0
  178. package/dist/solana/exec.js.map +1 -0
  179. package/dist/solana/hasher.d.ts +4 -0
  180. package/dist/solana/hasher.d.ts.map +1 -0
  181. package/dist/solana/hasher.js +81 -0
  182. package/dist/solana/hasher.js.map +1 -0
  183. package/dist/solana/idl/1.6.0/BASE_TOKEN_POOL.d.ts +866 -0
  184. package/dist/solana/idl/1.6.0/BASE_TOKEN_POOL.d.ts.map +1 -0
  185. package/dist/solana/idl/1.6.0/BASE_TOKEN_POOL.js +866 -0
  186. package/dist/solana/idl/1.6.0/BASE_TOKEN_POOL.js.map +1 -0
  187. package/dist/solana/idl/1.6.0/BURN_MINT_TOKEN_POOL.d.ts +949 -0
  188. package/dist/solana/idl/1.6.0/BURN_MINT_TOKEN_POOL.d.ts.map +1 -0
  189. package/dist/solana/idl/1.6.0/BURN_MINT_TOKEN_POOL.js +949 -0
  190. package/dist/solana/idl/1.6.0/BURN_MINT_TOKEN_POOL.js.map +1 -0
  191. package/dist/solana/idl/1.6.0/CCIP_CCTP_TOKEN_POOL.d.ts +1374 -0
  192. package/dist/solana/idl/1.6.0/CCIP_CCTP_TOKEN_POOL.d.ts.map +1 -0
  193. package/dist/solana/idl/1.6.0/CCIP_CCTP_TOKEN_POOL.js +1374 -0
  194. package/dist/solana/idl/1.6.0/CCIP_CCTP_TOKEN_POOL.js.map +1 -0
  195. package/dist/solana/idl/1.6.0/CCIP_COMMON.d.ts +104 -0
  196. package/dist/solana/idl/1.6.0/CCIP_COMMON.d.ts.map +1 -0
  197. package/dist/solana/idl/1.6.0/CCIP_COMMON.js +104 -0
  198. package/dist/solana/idl/1.6.0/CCIP_COMMON.js.map +1 -0
  199. package/dist/solana/idl/1.6.0/CCIP_OFFRAMP.d.ts +2746 -0
  200. package/dist/solana/idl/1.6.0/CCIP_OFFRAMP.d.ts.map +1 -0
  201. package/dist/solana/idl/1.6.0/CCIP_OFFRAMP.js +2746 -0
  202. package/dist/solana/idl/1.6.0/CCIP_OFFRAMP.js.map +1 -0
  203. package/dist/solana/idl/1.6.0/CCIP_ROUTER.d.ts +2332 -0
  204. package/dist/solana/idl/1.6.0/CCIP_ROUTER.d.ts.map +1 -0
  205. package/dist/solana/idl/1.6.0/CCIP_ROUTER.js +2332 -0
  206. package/dist/solana/idl/1.6.0/CCIP_ROUTER.js.map +1 -0
  207. package/dist/solana/index.d.ts +205 -0
  208. package/dist/solana/index.d.ts.map +1 -0
  209. package/dist/solana/index.js +1085 -0
  210. package/dist/solana/index.js.map +1 -0
  211. package/dist/solana/offchain.d.ts +31 -0
  212. package/dist/solana/offchain.d.ts.map +1 -0
  213. package/dist/solana/offchain.js +152 -0
  214. package/dist/solana/offchain.js.map +1 -0
  215. package/dist/solana/patchBorsh.d.ts +2 -0
  216. package/dist/solana/patchBorsh.d.ts.map +1 -0
  217. package/dist/solana/patchBorsh.js +60 -0
  218. package/dist/solana/patchBorsh.js.map +1 -0
  219. package/dist/solana/send.d.ts +14 -0
  220. package/dist/solana/send.d.ts.map +1 -0
  221. package/dist/solana/send.js +272 -0
  222. package/dist/solana/send.js.map +1 -0
  223. package/dist/solana/types.d.ts +4 -0
  224. package/dist/solana/types.d.ts.map +1 -0
  225. package/dist/solana/types.js +2 -0
  226. package/dist/solana/types.js.map +1 -0
  227. package/dist/solana/utils.d.ts +58 -0
  228. package/dist/solana/utils.d.ts.map +1 -0
  229. package/dist/solana/utils.js +211 -0
  230. package/dist/solana/utils.js.map +1 -0
  231. package/dist/sui/hasher.d.ts +12 -0
  232. package/dist/sui/hasher.d.ts.map +1 -0
  233. package/dist/sui/hasher.js +63 -0
  234. package/dist/sui/hasher.js.map +1 -0
  235. package/dist/sui/index.d.ts +72 -0
  236. package/dist/sui/index.d.ts.map +1 -0
  237. package/dist/sui/index.js +128 -0
  238. package/dist/sui/index.js.map +1 -0
  239. package/dist/sui/types.d.ts +17 -0
  240. package/dist/sui/types.d.ts.map +1 -0
  241. package/dist/sui/types.js +17 -0
  242. package/dist/sui/types.js.map +1 -0
  243. package/dist/supported-chains.d.ts +5 -0
  244. package/dist/supported-chains.d.ts.map +1 -0
  245. package/dist/supported-chains.js +3 -0
  246. package/dist/supported-chains.js.map +1 -0
  247. package/dist/types.d.ts +118 -0
  248. package/dist/types.d.ts.map +1 -0
  249. package/dist/types.js +11 -0
  250. package/dist/types.js.map +1 -0
  251. package/dist/utils.d.ts +117 -0
  252. package/dist/utils.d.ts.map +1 -0
  253. package/dist/utils.js +336 -0
  254. package/dist/utils.js.map +1 -0
  255. package/package.json +66 -8
  256. package/src/aptos/exec.ts +69 -0
  257. package/src/aptos/hasher.ts +92 -0
  258. package/src/aptos/index.ts +660 -0
  259. package/src/aptos/logs.ts +210 -0
  260. package/src/aptos/send.ts +120 -0
  261. package/src/aptos/token.ts +150 -0
  262. package/src/aptos/types.ts +85 -0
  263. package/src/aptos/utils.ts +24 -0
  264. package/src/chain.ts +398 -0
  265. package/src/commits.ts +44 -0
  266. package/src/evm/abi/BurnMintERC677Token.ts +487 -0
  267. package/src/evm/abi/CommitStore_1_2.ts +637 -0
  268. package/src/evm/abi/CommitStore_1_5.ts +674 -0
  269. package/src/evm/abi/FeeQuoter_1_6.ts +1903 -0
  270. package/src/evm/abi/LockReleaseTokenPool_1_5.ts +1095 -0
  271. package/src/evm/abi/LockReleaseTokenPool_1_5_1.ts +1277 -0
  272. package/src/evm/abi/LockReleaseTokenPool_1_6_1.ts +1287 -0
  273. package/src/evm/abi/OffRamp_1_2.ts +1203 -0
  274. package/src/evm/abi/OffRamp_1_5.ts +1272 -0
  275. package/src/evm/abi/OffRamp_1_6.ts +1528 -0
  276. package/src/evm/abi/OnRamp_1_2.ts +1342 -0
  277. package/src/evm/abi/OnRamp_1_5.ts +1426 -0
  278. package/src/evm/abi/OnRamp_1_6.ts +879 -0
  279. package/src/evm/abi/Router.ts +507 -0
  280. package/src/evm/abi/TokenAdminRegistry_1_5.ts +332 -0
  281. package/src/evm/const.ts +69 -0
  282. package/src/evm/errors.ts +212 -0
  283. package/src/evm/hasher.ts +166 -0
  284. package/src/evm/index.ts +1262 -0
  285. package/src/evm/messages.ts +73 -0
  286. package/src/evm/offchain.ts +189 -0
  287. package/src/execution.ts +131 -0
  288. package/src/extra-args.ts +71 -0
  289. package/src/gas.ts +135 -0
  290. package/src/hasher/common.ts +23 -0
  291. package/src/hasher/hasher.ts +12 -0
  292. package/src/hasher/index.ts +3 -0
  293. package/src/hasher/merklemulti.ts +309 -0
  294. package/src/index.ts +51 -0
  295. package/src/offchain.ts +86 -0
  296. package/src/requests.ts +339 -0
  297. package/src/selectors.ts +1340 -0
  298. package/src/solana/cleanup.ts +216 -0
  299. package/src/solana/exec.ts +645 -0
  300. package/src/solana/hasher.ts +104 -0
  301. package/src/solana/idl/1.6.0/BASE_TOKEN_POOL.ts +1734 -0
  302. package/src/solana/idl/1.6.0/BURN_MINT_TOKEN_POOL.ts +1900 -0
  303. package/src/solana/idl/1.6.0/CCIP_CCTP_TOKEN_POOL.ts +2750 -0
  304. package/src/solana/idl/1.6.0/CCIP_COMMON.ts +210 -0
  305. package/src/solana/idl/1.6.0/CCIP_OFFRAMP.ts +5494 -0
  306. package/src/solana/idl/1.6.0/CCIP_ROUTER.ts +4671 -0
  307. package/src/solana/index.ts +1454 -0
  308. package/src/solana/offchain.ts +209 -0
  309. package/src/solana/patchBorsh.ts +67 -0
  310. package/src/solana/send.ts +436 -0
  311. package/src/solana/types.ts +6 -0
  312. package/src/solana/utils.ts +272 -0
  313. package/src/sui/hasher.ts +90 -0
  314. package/src/sui/index.ts +198 -0
  315. package/src/sui/types.ts +22 -0
  316. package/src/supported-chains.ts +4 -0
  317. package/src/types.ts +153 -0
  318. package/src/utils.ts +405 -0
  319. package/tsconfig.json +18 -0
package/src/types.ts ADDED
@@ -0,0 +1,153 @@
1
+ import type { AbiParametersToPrimitiveTypes, ExtractAbiEvent } from 'abitype'
2
+ import type { BytesLike, Log } from 'ethers'
3
+
4
+ import type { ChainFamily, ChainTransaction } from './chain.ts'
5
+ import type OffRamp_1_6_ABI from './evm/abi/OffRamp_1_6.ts'
6
+ import type { CCIPMessage_EVM, CCIPMessage_V1_6_EVM } from './evm/messages.ts'
7
+ import type { ExtraArgs } from './extra-args.ts'
8
+ import type { CCIPMessage_V1_6_Solana } from './solana/types.ts'
9
+ import type { CCIPMessage_V1_6_Sui } from './sui/types.ts'
10
+ // v1.6 Base type from EVM contains the intersection of all other CCIPMessage v1.6 types
11
+ export type { CCIPMessage_V1_6 } from './evm/messages.ts'
12
+
13
+ /**
14
+ * DeepReadonly is a type that recursively makes all properties of an object readonly.
15
+ */
16
+ export type DeepReadonly<T> = Readonly<{
17
+ [K in keyof T]: T[K] extends number | string | symbol // Is it a primitive? Then make it readonly
18
+ ? Readonly<T[K]>
19
+ : // Is it an array of items? Then make the array readonly and the item as well
20
+ T[K] extends Array<infer A>
21
+ ? Readonly<Array<DeepReadonly<A>>>
22
+ : // It is some other object, make it readonly as well
23
+ DeepReadonly<T[K]>
24
+ }>
25
+
26
+ /**
27
+ * "Fix" for deeply intersecting types containing arrays: A[] & B[] => (A & B)[]
28
+ * Usually, if you intersect { arr: A[] } & { arr: B[] }, arr will have type A[] & B[],
29
+ * i.e. all/each *index* of A[] and B[] should be present in the intersection, with quite undefined
30
+ * types of the elements themselves, oftentimes assigning only one of A or B to the element type;
31
+ * This converts deeply to (A & B)[], i.e. each *element* should have all properties of A & B
32
+ */
33
+ export type MergeArrayElements<T, U> = {
34
+ [K in keyof (T & U)]: K extends keyof T & keyof U
35
+ ? T[K] extends unknown[]
36
+ ? U[K] extends unknown[]
37
+ ? (T[K][number] & U[K][number])[] // Intersect element types, both rw: A[] & B[] => (A & B)[]
38
+ : U[K] extends readonly unknown[]
39
+ ? readonly (T[K][number] & U[K][number])[] // Intersect element types, 2nd ro
40
+ : never
41
+ : T[K] extends readonly unknown[]
42
+ ? U[K] extends readonly unknown[]
43
+ ? readonly (T[K][number] & U[K][number])[] // Intersect element types, 1st or both ro
44
+ : never
45
+ : U[K] extends readonly unknown[]
46
+ ? never
47
+ : MergeArrayElements<T[K], U[K]> // Recurse deeper
48
+ : K extends keyof T
49
+ ? T[K]
50
+ : K extends keyof U
51
+ ? U[K]
52
+ : never
53
+ }
54
+
55
+ export const CCIPVersion = {
56
+ V1_2: '1.2.0',
57
+ V1_5: '1.5.0',
58
+ V1_6: '1.6.0',
59
+ } as const
60
+ export type CCIPVersion = (typeof CCIPVersion)[keyof typeof CCIPVersion]
61
+
62
+ type ChainFamilyWithId<F extends ChainFamily> = F extends typeof ChainFamily.EVM
63
+ ? { readonly family: F; readonly chainId: number }
64
+ : F extends typeof ChainFamily.Solana
65
+ ? { readonly family: F; readonly chainId: string }
66
+ : F extends typeof ChainFamily.Aptos | typeof ChainFamily.Sui
67
+ ? { readonly family: F; readonly chainId: `${F}:${number}` }
68
+ : never
69
+
70
+ export type NetworkInfo<F extends ChainFamily = ChainFamily> = {
71
+ readonly chainSelector: bigint
72
+ readonly name: string
73
+ readonly isTestnet: boolean
74
+ } & ChainFamilyWithId<F>
75
+
76
+ export interface Lane<V extends CCIPVersion = CCIPVersion> {
77
+ sourceChainSelector: bigint
78
+ destChainSelector: bigint
79
+ onRamp: string
80
+ version: V
81
+ }
82
+
83
+ export type CCIPMessage<V extends CCIPVersion = CCIPVersion> = V extends
84
+ | typeof CCIPVersion.V1_2
85
+ | typeof CCIPVersion.V1_5
86
+ ? CCIPMessage_EVM<V>
87
+ : CCIPMessage_V1_6_EVM | CCIPMessage_V1_6_Solana | CCIPMessage_V1_6_Sui
88
+
89
+ export type Log_ = Pick<Log, 'topics' | 'index' | 'address' | 'blockNumber' | 'transactionHash'> & {
90
+ data: BytesLike | Record<string, unknown>
91
+ tx?: ChainTransaction
92
+ }
93
+
94
+ export interface CCIPRequest<V extends CCIPVersion = CCIPVersion> {
95
+ lane: Lane<V>
96
+ message: CCIPMessage<V>
97
+ log: Log_
98
+ tx: { logs: readonly Log_[]; from?: string; error?: unknown }
99
+ timestamp: number
100
+ }
101
+
102
+ export type CommitReport = AbiParametersToPrimitiveTypes<
103
+ ExtractAbiEvent<typeof OffRamp_1_6_ABI, 'CommitReportAccepted'>['inputs']
104
+ >[0][number]
105
+
106
+ export interface CCIPCommit {
107
+ report: CommitReport
108
+ log: Log_
109
+ }
110
+
111
+ export const ExecutionState = {
112
+ InProgress: 1,
113
+ Success: 2,
114
+ Failed: 3,
115
+ } as const
116
+ export type ExecutionState = (typeof ExecutionState)[keyof typeof ExecutionState]
117
+
118
+ export type ExecutionReceipt = {
119
+ messageId: string
120
+ sequenceNumber: bigint
121
+ state: ExecutionState
122
+ sourceChainSelector?: bigint
123
+ messageHash?: string
124
+ returnData?: BytesLike | Record<string, string>
125
+ gasUsed?: bigint
126
+ }
127
+
128
+ export interface CCIPExecution {
129
+ receipt: ExecutionReceipt
130
+ log: Log_
131
+ timestamp: number
132
+ }
133
+
134
+ export type OffchainTokenData = { _tag: string; [k: string]: BytesLike } | undefined
135
+
136
+ export type ExecutionReport<M extends CCIPMessage = CCIPMessage> = {
137
+ message: M
138
+ proofs: readonly BytesLike[]
139
+ proofFlagBits: bigint
140
+ merkleRoot: string
141
+ offchainTokenData: readonly OffchainTokenData[]
142
+ }
143
+
144
+ /**
145
+ * A message to be sent to another network
146
+ */
147
+ export type AnyMessage = {
148
+ receiver: BytesLike
149
+ data: BytesLike
150
+ extraArgs: ExtraArgs
151
+ tokenAmounts?: readonly { token: string; amount: bigint }[]
152
+ feeToken?: string
153
+ }
package/src/utils.ts ADDED
@@ -0,0 +1,405 @@
1
+ import util from 'util'
2
+
3
+ import bs58 from 'bs58'
4
+ import {
5
+ type BigNumberish,
6
+ type BytesLike,
7
+ type Numeric,
8
+ decodeBase64,
9
+ getBytes,
10
+ isBytesLike,
11
+ toBeHex,
12
+ toBigInt,
13
+ } from 'ethers'
14
+ import moize from 'moize'
15
+
16
+ import { type Chain, ChainFamily } from './chain.ts'
17
+ import SELECTORS from './selectors.ts'
18
+ import { supportedChains } from './supported-chains.ts'
19
+ import type { NetworkInfo } from './types.ts'
20
+
21
+ /**
22
+ * Returns *some* block number with timestamp prior to `timestamp`
23
+ *
24
+ * @param getBlockTimestamp - function to get block timestamp
25
+ * @param recentBlockNumber - a block guaranteed to be after `timestamp` (e.g. latest)
26
+ * @param timestamp - target timestamp
27
+ * @param precision - returned blockNumber should be within this many blocks before timestamp
28
+ * @returns blockNumber of a block at provider which is close but before target timestamp
29
+ **/
30
+ export async function getSomeBlockNumberBefore(
31
+ getBlockTimestamp: (blockNumber: number) => Promise<number>,
32
+ recentBlockNumber: number,
33
+ timestamp: number,
34
+ precision = 10,
35
+ ): Promise<number> {
36
+ let beforeBlockNumber = Math.max(1, recentBlockNumber - precision * 1000)
37
+ let beforeTimestamp = await getBlockTimestamp(beforeBlockNumber)
38
+
39
+ const now = Math.trunc(Date.now() / 1000)
40
+ let estimatedBlockTime = (now - beforeTimestamp) / (recentBlockNumber - beforeBlockNumber),
41
+ afterBlockNumber = recentBlockNumber,
42
+ afterTimestamp = now
43
+
44
+ // first, go back looking for a block prior to our target timestamp
45
+ for (let iter = 0; beforeBlockNumber > 1 && beforeTimestamp > timestamp; iter++) {
46
+ afterBlockNumber = beforeBlockNumber
47
+ afterTimestamp = beforeTimestamp
48
+ beforeBlockNumber = Math.max(
49
+ 1,
50
+ Math.trunc(beforeBlockNumber - (beforeTimestamp - timestamp) / estimatedBlockTime) -
51
+ 10 ** iter,
52
+ )
53
+ beforeTimestamp = await getBlockTimestamp(beforeBlockNumber)
54
+ estimatedBlockTime = (now - beforeTimestamp) / (recentBlockNumber - beforeBlockNumber)
55
+ }
56
+
57
+ if (beforeTimestamp > timestamp) {
58
+ throw new Error(`Could not find a block prior to timestamp=${timestamp}`)
59
+ }
60
+
61
+ // now, bin-search based on timestamp proportions, looking for
62
+ // a block at most N estimated blockTimes from our target timestamp
63
+ while (timestamp - beforeTimestamp >= 1 && afterBlockNumber - beforeBlockNumber > precision) {
64
+ const prop = (timestamp - beforeTimestamp) / (afterTimestamp - beforeTimestamp)
65
+ const delta =
66
+ prop > 0.5
67
+ ? Math.floor(prop * (afterBlockNumber - beforeBlockNumber))
68
+ : Math.ceil(prop * (afterBlockNumber - beforeBlockNumber))
69
+ let pivot = beforeBlockNumber + delta
70
+ if (pivot === afterBlockNumber) {
71
+ pivot--
72
+ }
73
+ const pivotTimestamp = await getBlockTimestamp(pivot)
74
+ if (pivotTimestamp > timestamp) {
75
+ afterBlockNumber = pivot
76
+ afterTimestamp = pivotTimestamp
77
+ } else {
78
+ beforeBlockNumber = pivot
79
+ beforeTimestamp = pivotTimestamp
80
+ }
81
+ console.debug('getSomeBlockNumberBefore: searching block before', {
82
+ beforeBlockNumber,
83
+ beforeTimestamp,
84
+ pivot,
85
+ pivotTimestamp,
86
+ afterBlockNumber,
87
+ afterTimestamp,
88
+ estimatedBlockTime,
89
+ timestamp,
90
+ diffNumber: afterBlockNumber - beforeBlockNumber,
91
+ })
92
+ }
93
+ return beforeBlockNumber
94
+ }
95
+
96
+ // memoized so we always output the same object for a given chainId
97
+ const networkInfoFromChainId = moize.default((chainId: NetworkInfo['chainId']): NetworkInfo => {
98
+ const sel = SELECTORS[chainId]
99
+ if (!sel?.name) throw new Error(`Chain not found: ${chainId}`)
100
+ return {
101
+ chainId: isNaN(+chainId) ? chainId : +chainId,
102
+ chainSelector: sel.selector,
103
+ name: sel.name,
104
+ family: sel.family,
105
+ isTestnet: !sel.name.includes('-mainnet'),
106
+ } as NetworkInfo
107
+ })
108
+
109
+ /**
110
+ * Converts a chain selector, chain ID, or chain name to complete network information
111
+ *
112
+ * @param selectorOrIdOrName - Can be:
113
+ * - Chain selector as bigint or numeric string
114
+ * - Chain ID as number, bigint or string (EVM: "1", Aptos: "aptos:1", Solana: genesisHash)
115
+ * - Chain name as string ("ethereum-mainnet")
116
+ * @returns Complete NetworkInfo object
117
+ */
118
+ export const networkInfo = moize.default(function networkInfo_(
119
+ selectorOrIdOrName: bigint | number | string,
120
+ ): NetworkInfo {
121
+ let chainId
122
+ if (typeof selectorOrIdOrName === 'number') {
123
+ chainId = selectorOrIdOrName
124
+ } else if (typeof selectorOrIdOrName === 'string' && selectorOrIdOrName.match(/^\d+$/)) {
125
+ selectorOrIdOrName = BigInt(selectorOrIdOrName)
126
+ }
127
+ if (typeof selectorOrIdOrName === 'bigint') {
128
+ // maybe we got a number deserialized as bigint
129
+ if (selectorOrIdOrName.toString() in SELECTORS) {
130
+ chainId = Number(selectorOrIdOrName)
131
+ } else {
132
+ for (const id in SELECTORS) {
133
+ if (SELECTORS[id].selector === selectorOrIdOrName) {
134
+ chainId = id
135
+ break
136
+ }
137
+ }
138
+ if (!chainId) throw new Error(`Selector not found: ${selectorOrIdOrName}`)
139
+ }
140
+ } else if (typeof selectorOrIdOrName === 'string') {
141
+ if (selectorOrIdOrName.includes('-')) {
142
+ for (const id in SELECTORS) {
143
+ if (SELECTORS[id].name === selectorOrIdOrName) {
144
+ chainId = id
145
+ break
146
+ }
147
+ }
148
+ }
149
+ chainId ??= selectorOrIdOrName
150
+ }
151
+ return networkInfoFromChainId(chainId as string | number)
152
+ })
153
+
154
+ const BLOCK_RANGE = 10_000
155
+ /**
156
+ * Generates exclusive block ranges [fromBlock, toBlock]
157
+ * If startBlock is given, moves forward from there (up to latestBlock),
158
+ * Otherwise, moves backwards down to genesis (you probably want to break/return before that)
159
+ **/
160
+ export function* blockRangeGenerator(
161
+ params: { page?: number } & ({ endBlock: number; startBlock?: number } | { singleBlock: number }),
162
+ ) {
163
+ const stepSize = params.page ?? BLOCK_RANGE
164
+ if ('singleBlock' in params) {
165
+ yield { fromBlock: params.singleBlock, toBlock: params.singleBlock }
166
+ } else if ('startBlock' in params && params.startBlock) {
167
+ for (let fromBlock = params.startBlock; fromBlock < params.endBlock; fromBlock += stepSize) {
168
+ yield {
169
+ fromBlock,
170
+ toBlock: Math.min(params.endBlock, fromBlock + stepSize - 1),
171
+ progress: `${Math.trunc(((fromBlock - params.startBlock) / (params.endBlock - params.startBlock)) * 10000) / 100}%`,
172
+ }
173
+ }
174
+ } else {
175
+ for (let toBlock = params.endBlock; toBlock > 1; toBlock -= stepSize) {
176
+ yield {
177
+ fromBlock: Math.max(1, toBlock - stepSize + 1),
178
+ toBlock,
179
+ }
180
+ }
181
+ }
182
+ }
183
+
184
+ export function bigIntReplacer(_key: string, value: unknown): unknown {
185
+ if (typeof value === 'bigint') {
186
+ return value.toString()
187
+ }
188
+ return value
189
+ }
190
+
191
+ export function bigIntReviver(_key: string, value: unknown): unknown {
192
+ if (typeof value === 'string' && /^\d+$/.test(value)) {
193
+ return BigInt(value)
194
+ }
195
+ return value
196
+ }
197
+
198
+ /**
199
+ * Decode address from a 32-byte hex string
200
+ **/
201
+ export function decodeAddress(address: BytesLike, family: ChainFamily = ChainFamily.EVM): string {
202
+ const chain = supportedChains[family]
203
+ if (!chain) throw new Error(`Unsupported chain family: ${family}`)
204
+ return chain.getAddress(getAddressBytes(address))
205
+ }
206
+
207
+ /**
208
+ * Version of decodeAddress which is aware of custom cross-chain OnRamp formats
209
+ **/
210
+ export function decodeOnRampAddress(
211
+ address: BytesLike,
212
+ family: ChainFamily = ChainFamily.EVM,
213
+ ): string {
214
+ let decoded = decodeAddress(address, family)
215
+ if (family === ChainFamily.Aptos) decoded += '::onramp'
216
+ return decoded
217
+ }
218
+
219
+ export function leToBigInt(data: BytesLike | readonly number[]): bigint {
220
+ if (Array.isArray(data)) data = new Uint8Array(data)
221
+ return toBigInt(getBytes(data as BytesLike).reverse())
222
+ }
223
+
224
+ export function toLeArray(value: BigNumberish, width?: Numeric): Uint8Array {
225
+ return getBytes(toBeHex(value, width)).reverse()
226
+ }
227
+
228
+ export function isBase64(data: unknown): data is string {
229
+ return (
230
+ typeof data === 'string' &&
231
+ /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/.test(data)
232
+ )
233
+ }
234
+
235
+ export function getDataBytes(data: BytesLike | readonly number[]): Uint8Array {
236
+ if (Array.isArray(data)) {
237
+ return new Uint8Array(data)
238
+ }
239
+ if (isBytesLike(data)) {
240
+ return getBytes(data)
241
+ } else if (isBase64(data)) {
242
+ return decodeBase64(data)
243
+ } else {
244
+ throw new Error(`Unsupported data format: ${util.inspect(data)}`)
245
+ }
246
+ }
247
+
248
+ export function getAddressBytes(address: BytesLike): Uint8Array {
249
+ let bytes: Uint8Array
250
+ if (isBytesLike(address)) {
251
+ bytes = getBytes(address)
252
+ } else {
253
+ bytes = bs58.decode(address)
254
+ }
255
+ if (bytes.length > 20) {
256
+ if (
257
+ bytes.slice(0, bytes.length - 20).every((b) => b === 0) &&
258
+ bytes.slice(-20).some((b) => b !== 0)
259
+ ) {
260
+ bytes = bytes.slice(-20)
261
+ }
262
+ }
263
+ return bytes
264
+ }
265
+
266
+ /**
267
+ * Converts snake_case strings to camelCase
268
+ */
269
+ export function snakeToCamel(str: string): string {
270
+ return str.replace(/_([a-zA-Z])/g, (_, letter: string) => letter.toUpperCase())
271
+ }
272
+
273
+ /**
274
+ * Recursively converts all snake_case keys in an object to camelCase
275
+ * Only converts keys that actually have snake_case format
276
+ */
277
+ export function convertKeysToCamelCase(
278
+ obj: unknown,
279
+ mapValues?: (value: unknown, key?: string) => unknown,
280
+ key?: string,
281
+ ): unknown {
282
+ if (Array.isArray(obj)) {
283
+ return obj.map((v) => convertKeysToCamelCase(v, mapValues, key))
284
+ }
285
+
286
+ if (obj == null || typeof obj !== 'object') return mapValues ? mapValues(obj, key) : obj
287
+
288
+ const record = obj as Record<string, unknown>
289
+ const converted: Record<string, unknown> = {}
290
+
291
+ for (const [name, value] of Object.entries(record)) {
292
+ const camelKey = snakeToCamel(name)
293
+ converted[camelKey] = convertKeysToCamelCase(value, mapValues, camelKey)
294
+ }
295
+ return converted
296
+ }
297
+
298
+ export const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))
299
+
300
+ export function parseTypeAndVersion(
301
+ typeAndVersion: string,
302
+ ): Awaited<ReturnType<Chain['typeAndVersion']>> {
303
+ const match = typeAndVersion.match(/^(\w.+\S)\s+v?(\d+\.\d+(?:\.\d+)?)([^\d.].*)?$/)
304
+ if (!match)
305
+ throw new Error(
306
+ `Invalid typeAndVersion: "${typeAndVersion}", len=${typeAndVersion.length}, hex=0x${Buffer.from(typeAndVersion).toString('hex')}`,
307
+ )
308
+ const [_, typeRaw, version] = match
309
+ // some string normalization
310
+ const type = typeRaw
311
+ .replaceAll(/-(\w)/g, (_, w: string) => w.toUpperCase()) // kebabToPascal
312
+ .replace(/ccip/gi, 'CCIP')
313
+ .replace(
314
+ /(o)(n|ff)(ramp)\b/gi,
315
+ (_, o: string, n: string, ramp: string) =>
316
+ `${o.toUpperCase()}${n.toLowerCase()}${ramp.charAt(0).toUpperCase()}${ramp.slice(1).toLowerCase()}`,
317
+ ) // ccipOfframp -> CCIPOffRamp
318
+ if (!match[3]) return [type, version, typeAndVersion]
319
+ else return [type, version, typeAndVersion, match[3]]
320
+ }
321
+
322
+ export function createRateLimitedFetch({
323
+ maxRequests = Number(process.env['RL_MAX_REQUESTS'] || 2),
324
+ windowMs = Number(process.env['RL_WINDOW_MS'] || 10000),
325
+ maxRetries = Number(process.env['RL_MAX_RETRIES'] || 5),
326
+ }: { maxRequests?: number; windowMs?: number; maxRetries?: number } = {}): typeof fetch {
327
+ // Custom fetch implementation with retry logic and rate limiting
328
+ // Per-instance state
329
+ const requestQueue: Array<{ timestamp: number }> = []
330
+
331
+ const isRateLimited = (): boolean => {
332
+ const now = Date.now()
333
+ // Remove old requests outside the window
334
+ while (requestQueue.length > 0 && now - requestQueue[0].timestamp > windowMs) {
335
+ requestQueue.shift()
336
+ }
337
+ return requestQueue.length >= maxRequests
338
+ }
339
+
340
+ const waitForRateLimit = async (): Promise<void> => {
341
+ while (isRateLimited()) {
342
+ const oldestRequest = requestQueue[0]
343
+ const waitTime = windowMs - (Date.now() - oldestRequest.timestamp)
344
+ if (waitTime > 0) {
345
+ await sleep(waitTime + 100) // Add small buffer
346
+ }
347
+ }
348
+ }
349
+
350
+ const recordRequest = (): void => {
351
+ requestQueue.push({ timestamp: Date.now() })
352
+ }
353
+
354
+ const isRateLimitError = (error: unknown): boolean => {
355
+ if (error instanceof Error) {
356
+ return !!error.message.match(/\b(429\b|rate.?limit)/i)
357
+ }
358
+ return false
359
+ }
360
+
361
+ return async (input, init?) => {
362
+ let lastError: Error | null = null
363
+
364
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
365
+ try {
366
+ // Wait for rate limit before making request
367
+ await waitForRateLimit()
368
+ recordRequest()
369
+ // console.debug('__fetching', input, init?.body)
370
+
371
+ const response = await fetch(input, init)
372
+
373
+ // If response is successful, return it
374
+ if (response.ok) {
375
+ console.debug('fetched', input, response.status, init?.body)
376
+ return response
377
+ }
378
+
379
+ // For 429 responses, throw an error to trigger retry
380
+ if (response.status === 429) {
381
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`)
382
+ }
383
+
384
+ // For other non-2xx responses, don't retry
385
+ console.debug('fetch non-retryable error', input, response.status, init?.body)
386
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`)
387
+ } catch (error) {
388
+ console.debug('fetch errored', attempt, error, input, init?.body)
389
+ lastError = error instanceof Error ? error : new Error(String(error))
390
+
391
+ // Only retry on rate limit errors
392
+ if (!isRateLimitError(lastError)) {
393
+ throw lastError
394
+ }
395
+
396
+ // Don't retry on the last attempt
397
+ if (attempt >= maxRetries) {
398
+ break
399
+ }
400
+ }
401
+ }
402
+
403
+ throw lastError || new Error('Request failed after all retries')
404
+ }
405
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "lib": ["ES2023"],
6
+ "strict": true,
7
+ "skipLibCheck": true,
8
+ "declaration": true,
9
+ "declarationMap": true,
10
+ "sourceMap": true,
11
+ "forceConsistentCasingInFileNames": true,
12
+ "allowImportingTsExtensions": true,
13
+ "rewriteRelativeImportExtensions": true,
14
+ "verbatimModuleSyntax": true,
15
+ "erasableSyntaxOnly": true,
16
+ "resolveJsonModule": true
17
+ }
18
+ }