@unionlabs/payments 0.1.0 → 0.2.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 (393) hide show
  1. package/Abi/package.json +6 -0
  2. package/Attestor/package.json +6 -0
  3. package/Constants/package.json +6 -0
  4. package/Domain/package.json +6 -0
  5. package/Error/package.json +6 -0
  6. package/EvmPublicClient/package.json +6 -0
  7. package/EvmWalletClient/package.json +6 -0
  8. package/Payment/package.json +6 -0
  9. package/PaymentError/package.json +6 -0
  10. package/Prover/package.json +6 -0
  11. package/PublicClient/package.json +6 -0
  12. package/README.md +1 -0
  13. package/Schema/package.json +6 -0
  14. package/Utils/package.json +6 -0
  15. package/WalletClient/package.json +6 -0
  16. package/attestation/package.json +6 -0
  17. package/cli/commands/balance/package.json +6 -0
  18. package/cli/commands/deposit/package.json +6 -0
  19. package/cli/commands/export-verifier/package.json +6 -0
  20. package/cli/commands/generate/package.json +6 -0
  21. package/cli/commands/history/package.json +6 -0
  22. package/cli/commands/prove/package.json +6 -0
  23. package/cli/commands/redeem/package.json +6 -0
  24. package/cli/commands/update-client/package.json +6 -0
  25. package/cli/config/package.json +6 -0
  26. package/cli/package.json +6 -0
  27. package/cli/utils/package.json +6 -0
  28. package/constants/ibc-core-registry/package.json +6 -0
  29. package/constants/services/package.json +6 -0
  30. package/constants/z-asset-registry/package.json +6 -0
  31. package/dist/cjs/Abi.js +270 -0
  32. package/dist/cjs/Abi.js.map +1 -0
  33. package/dist/cjs/Attestor.js +76 -0
  34. package/dist/cjs/Attestor.js.map +1 -0
  35. package/dist/cjs/Constants.js +8 -0
  36. package/dist/cjs/Constants.js.map +1 -0
  37. package/dist/cjs/Domain.js +24 -0
  38. package/dist/cjs/Domain.js.map +1 -0
  39. package/dist/cjs/Error.js +100 -0
  40. package/dist/cjs/Error.js.map +1 -0
  41. package/dist/cjs/EvmPublicClient.js +301 -0
  42. package/dist/cjs/EvmPublicClient.js.map +1 -0
  43. package/dist/cjs/EvmWalletClient.js +670 -0
  44. package/dist/cjs/EvmWalletClient.js.map +1 -0
  45. package/dist/cjs/Payment.js +333 -0
  46. package/dist/cjs/Payment.js.map +1 -0
  47. package/dist/cjs/PaymentError.js +32 -0
  48. package/dist/cjs/PaymentError.js.map +1 -0
  49. package/dist/cjs/Prover.js +153 -0
  50. package/dist/cjs/Prover.js.map +1 -0
  51. package/dist/cjs/PublicClient.js +39 -0
  52. package/dist/cjs/PublicClient.js.map +1 -0
  53. package/dist/cjs/Schema.js +38 -0
  54. package/dist/cjs/Schema.js.map +1 -0
  55. package/dist/cjs/Utils.js +33 -0
  56. package/dist/cjs/Utils.js.map +1 -0
  57. package/dist/cjs/WalletClient.js +39 -0
  58. package/dist/cjs/WalletClient.js.map +1 -0
  59. package/dist/cjs/attestation.js +49 -0
  60. package/dist/cjs/attestation.js.map +1 -0
  61. package/dist/cjs/cli/commands/balance.js +60 -0
  62. package/dist/cjs/cli/commands/balance.js.map +1 -0
  63. package/dist/cjs/cli/commands/deposit.js +58 -0
  64. package/dist/cjs/cli/commands/deposit.js.map +1 -0
  65. package/dist/cjs/cli/commands/export-verifier.js +27 -0
  66. package/dist/cjs/cli/commands/export-verifier.js.map +1 -0
  67. package/dist/cjs/cli/commands/generate.js +41 -0
  68. package/dist/cjs/cli/commands/generate.js.map +1 -0
  69. package/dist/cjs/cli/commands/history.js +59 -0
  70. package/dist/cjs/cli/commands/history.js.map +1 -0
  71. package/dist/cjs/cli/commands/prove.js +82 -0
  72. package/dist/cjs/cli/commands/prove.js.map +1 -0
  73. package/dist/cjs/cli/commands/redeem.js +152 -0
  74. package/dist/cjs/cli/commands/redeem.js.map +1 -0
  75. package/dist/cjs/cli/commands/update-client.js +62 -0
  76. package/dist/cjs/cli/commands/update-client.js.map +1 -0
  77. package/dist/cjs/cli/config.js +32 -0
  78. package/dist/cjs/cli/config.js.map +1 -0
  79. package/dist/cjs/cli/utils.js +108 -0
  80. package/dist/cjs/cli/utils.js.map +1 -0
  81. package/dist/cjs/cli.js +24 -0
  82. package/dist/cjs/cli.js.map +1 -0
  83. package/dist/cjs/constants/ibc-core-registry.js +30 -0
  84. package/dist/cjs/constants/ibc-core-registry.js.map +1 -0
  85. package/dist/cjs/constants/services.js +9 -0
  86. package/dist/cjs/constants/services.js.map +1 -0
  87. package/dist/cjs/constants/z-asset-registry.js +32 -0
  88. package/dist/cjs/constants/z-asset-registry.js.map +1 -0
  89. package/dist/cjs/gen/prover_pb.js +81 -0
  90. package/dist/cjs/gen/prover_pb.js.map +1 -0
  91. package/dist/cjs/index.js +32 -0
  92. package/dist/cjs/index.js.map +1 -0
  93. package/dist/cjs/internal/evm.js +191 -0
  94. package/dist/cjs/internal/evm.js.map +1 -0
  95. package/dist/cjs/internal/evmWalletClient.js +6 -0
  96. package/dist/cjs/internal/evmWalletClient.js.map +1 -0
  97. package/dist/cjs/internal/publicClient.js +49 -0
  98. package/dist/cjs/internal/publicClient.js.map +1 -0
  99. package/dist/cjs/internal/walletClient.js +43 -0
  100. package/dist/cjs/internal/walletClient.js.map +1 -0
  101. package/dist/cjs/legacy/client.js +1222 -0
  102. package/dist/cjs/legacy/client.js.map +1 -0
  103. package/dist/cjs/legacy/prover.js +112 -0
  104. package/dist/cjs/legacy/prover.js.map +1 -0
  105. package/dist/cjs/poseidon2.js +226 -0
  106. package/dist/cjs/poseidon2.js.map +1 -0
  107. package/dist/cjs/promises/Attestor.js +23 -0
  108. package/dist/cjs/promises/Attestor.js.map +1 -0
  109. package/dist/cjs/promises/EvmPublicClient.js +34 -0
  110. package/dist/cjs/promises/EvmPublicClient.js.map +1 -0
  111. package/dist/cjs/promises/EvmWalletClient.js +51 -0
  112. package/dist/cjs/promises/EvmWalletClient.js.map +1 -0
  113. package/dist/cjs/promises/Payment.js +22 -0
  114. package/dist/cjs/promises/Payment.js.map +1 -0
  115. package/dist/cjs/promises/Prover.js +26 -0
  116. package/dist/cjs/promises/Prover.js.map +1 -0
  117. package/dist/cjs/promises/PublicClient.js +53 -0
  118. package/dist/cjs/promises/PublicClient.js.map +1 -0
  119. package/dist/cjs/promises/WalletClient.js +44 -0
  120. package/dist/cjs/promises/WalletClient.js.map +1 -0
  121. package/dist/cjs/promises/index.js +22 -0
  122. package/dist/cjs/promises/index.js.map +1 -0
  123. package/dist/cjs/rpc.js +867 -0
  124. package/dist/cjs/rpc.js.map +1 -0
  125. package/dist/cjs/types.js +6 -0
  126. package/dist/cjs/types.js.map +1 -0
  127. package/dist/dts/Abi.d.ts +220 -0
  128. package/dist/dts/Abi.d.ts.map +1 -0
  129. package/dist/dts/Attestor.d.ts +42 -0
  130. package/dist/dts/Attestor.d.ts.map +1 -0
  131. package/dist/dts/Constants.d.ts +3 -0
  132. package/dist/dts/Constants.d.ts.map +1 -0
  133. package/dist/dts/Domain.d.ts +141 -0
  134. package/dist/dts/Domain.d.ts.map +1 -0
  135. package/dist/dts/Error.d.ts +102 -0
  136. package/dist/dts/Error.d.ts.map +1 -0
  137. package/dist/dts/EvmPublicClient.d.ts +61 -0
  138. package/dist/dts/EvmPublicClient.d.ts.map +1 -0
  139. package/dist/dts/EvmWalletClient.d.ts +67 -0
  140. package/dist/dts/EvmWalletClient.d.ts.map +1 -0
  141. package/dist/dts/Payment.d.ts +128 -0
  142. package/dist/dts/Payment.d.ts.map +1 -0
  143. package/dist/dts/PaymentError.d.ts +21 -0
  144. package/dist/dts/PaymentError.d.ts.map +1 -0
  145. package/dist/dts/Prover.d.ts +87 -0
  146. package/dist/dts/Prover.d.ts.map +1 -0
  147. package/dist/dts/PublicClient.d.ts +146 -0
  148. package/dist/dts/PublicClient.d.ts.map +1 -0
  149. package/dist/dts/Schema.d.ts +16 -0
  150. package/dist/dts/Schema.d.ts.map +1 -0
  151. package/dist/dts/Utils.d.ts +11 -0
  152. package/dist/dts/Utils.d.ts.map +1 -0
  153. package/dist/dts/WalletClient.d.ts +123 -0
  154. package/dist/dts/WalletClient.d.ts.map +1 -0
  155. package/dist/dts/attestation.d.ts +13 -0
  156. package/dist/dts/attestation.d.ts.map +1 -0
  157. package/dist/dts/cli/commands/balance.d.ts +3 -0
  158. package/dist/dts/cli/commands/balance.d.ts.map +1 -0
  159. package/dist/dts/cli/commands/deposit.d.ts +3 -0
  160. package/dist/dts/cli/commands/deposit.d.ts.map +1 -0
  161. package/dist/dts/cli/commands/export-verifier.d.ts +3 -0
  162. package/dist/dts/cli/commands/export-verifier.d.ts.map +1 -0
  163. package/dist/dts/cli/commands/generate.d.ts +3 -0
  164. package/dist/dts/cli/commands/generate.d.ts.map +1 -0
  165. package/dist/dts/cli/commands/history.d.ts +3 -0
  166. package/dist/dts/cli/commands/history.d.ts.map +1 -0
  167. package/dist/dts/cli/commands/prove.d.ts +3 -0
  168. package/dist/dts/cli/commands/prove.d.ts.map +1 -0
  169. package/dist/dts/cli/commands/redeem.d.ts +3 -0
  170. package/dist/dts/cli/commands/redeem.d.ts.map +1 -0
  171. package/dist/dts/cli/commands/update-client.d.ts +3 -0
  172. package/dist/dts/cli/commands/update-client.d.ts.map +1 -0
  173. package/dist/dts/cli/config.d.ts +14 -0
  174. package/dist/dts/cli/config.d.ts.map +1 -0
  175. package/dist/dts/cli/utils.d.ts +11 -0
  176. package/dist/dts/cli/utils.d.ts.map +1 -0
  177. package/dist/dts/cli.d.ts +3 -0
  178. package/dist/dts/cli.d.ts.map +1 -0
  179. package/dist/dts/constants/ibc-core-registry.d.ts +11 -0
  180. package/dist/dts/constants/ibc-core-registry.d.ts.map +1 -0
  181. package/dist/dts/constants/services.d.ts +3 -0
  182. package/dist/dts/constants/services.d.ts.map +1 -0
  183. package/dist/dts/constants/z-asset-registry.d.ts +13 -0
  184. package/dist/dts/constants/z-asset-registry.d.ts.map +1 -0
  185. package/dist/dts/gen/prover_pb.d.ts +300 -0
  186. package/dist/dts/gen/prover_pb.d.ts.map +1 -0
  187. package/dist/dts/index.d.ts +21 -0
  188. package/dist/dts/index.d.ts.map +1 -0
  189. package/dist/dts/internal/evm.d.ts +250 -0
  190. package/dist/dts/internal/evm.d.ts.map +1 -0
  191. package/dist/dts/internal/evmWalletClient.d.ts +2 -0
  192. package/dist/dts/internal/evmWalletClient.d.ts.map +1 -0
  193. package/dist/dts/internal/publicClient.d.ts +2 -0
  194. package/dist/dts/internal/publicClient.d.ts.map +1 -0
  195. package/dist/dts/internal/walletClient.d.ts +2 -0
  196. package/dist/dts/internal/walletClient.d.ts.map +1 -0
  197. package/dist/dts/legacy/client.d.ts +313 -0
  198. package/dist/dts/legacy/client.d.ts.map +1 -0
  199. package/dist/dts/legacy/prover.d.ts +30 -0
  200. package/dist/dts/legacy/prover.d.ts.map +1 -0
  201. package/dist/dts/poseidon2.d.ts +18 -0
  202. package/dist/dts/poseidon2.d.ts.map +1 -0
  203. package/dist/dts/promises/Attestor.d.ts +17 -0
  204. package/dist/dts/promises/Attestor.d.ts.map +1 -0
  205. package/dist/dts/promises/EvmPublicClient.d.ts +3709 -0
  206. package/dist/dts/promises/EvmPublicClient.d.ts.map +1 -0
  207. package/dist/dts/promises/EvmWalletClient.d.ts +4502 -0
  208. package/dist/dts/promises/EvmWalletClient.d.ts.map +1 -0
  209. package/dist/dts/promises/Payment.d.ts +33 -0
  210. package/dist/dts/promises/Payment.d.ts.map +1 -0
  211. package/dist/dts/promises/Prover.d.ts +14 -0
  212. package/dist/dts/promises/Prover.d.ts.map +1 -0
  213. package/dist/dts/promises/PublicClient.d.ts +23 -0
  214. package/dist/dts/promises/PublicClient.d.ts.map +1 -0
  215. package/dist/dts/promises/WalletClient.d.ts +57 -0
  216. package/dist/dts/promises/WalletClient.d.ts.map +1 -0
  217. package/dist/dts/promises/index.d.ts +8 -0
  218. package/dist/dts/promises/index.d.ts.map +1 -0
  219. package/dist/dts/rpc.d.ts +148 -0
  220. package/dist/dts/rpc.d.ts.map +1 -0
  221. package/dist/dts/types.d.ts +263 -0
  222. package/dist/dts/types.d.ts.map +1 -0
  223. package/dist/esm/Abi.js +264 -0
  224. package/dist/esm/Abi.js.map +1 -0
  225. package/dist/esm/Attestor.js +68 -0
  226. package/dist/esm/Attestor.js.map +1 -0
  227. package/dist/esm/Constants.js +2 -0
  228. package/dist/esm/Constants.js.map +1 -0
  229. package/dist/esm/Domain.js +17 -0
  230. package/dist/esm/Domain.js.map +1 -0
  231. package/dist/esm/Error.js +89 -0
  232. package/dist/esm/Error.js.map +1 -0
  233. package/dist/esm/EvmPublicClient.js +292 -0
  234. package/dist/esm/EvmPublicClient.js.map +1 -0
  235. package/dist/esm/EvmWalletClient.js +659 -0
  236. package/dist/esm/EvmWalletClient.js.map +1 -0
  237. package/dist/esm/Payment.js +323 -0
  238. package/dist/esm/Payment.js.map +1 -0
  239. package/dist/esm/PaymentError.js +24 -0
  240. package/dist/esm/PaymentError.js.map +1 -0
  241. package/dist/esm/Prover.js +142 -0
  242. package/dist/esm/Prover.js.map +1 -0
  243. package/dist/esm/PublicClient.js +30 -0
  244. package/dist/esm/PublicClient.js.map +1 -0
  245. package/dist/esm/Schema.js +31 -0
  246. package/dist/esm/Schema.js.map +1 -0
  247. package/dist/esm/Utils.js +27 -0
  248. package/dist/esm/Utils.js.map +1 -0
  249. package/dist/esm/WalletClient.js +30 -0
  250. package/dist/esm/WalletClient.js.map +1 -0
  251. package/dist/esm/attestation.js +42 -0
  252. package/dist/esm/attestation.js.map +1 -0
  253. package/dist/esm/cli/commands/balance.js +54 -0
  254. package/dist/esm/cli/commands/balance.js.map +1 -0
  255. package/dist/esm/cli/commands/deposit.js +52 -0
  256. package/dist/esm/cli/commands/deposit.js.map +1 -0
  257. package/dist/esm/cli/commands/export-verifier.js +21 -0
  258. package/dist/esm/cli/commands/export-verifier.js.map +1 -0
  259. package/dist/esm/cli/commands/generate.js +35 -0
  260. package/dist/esm/cli/commands/generate.js.map +1 -0
  261. package/dist/esm/cli/commands/history.js +53 -0
  262. package/dist/esm/cli/commands/history.js.map +1 -0
  263. package/dist/esm/cli/commands/prove.js +76 -0
  264. package/dist/esm/cli/commands/prove.js.map +1 -0
  265. package/dist/esm/cli/commands/redeem.js +146 -0
  266. package/dist/esm/cli/commands/redeem.js.map +1 -0
  267. package/dist/esm/cli/commands/update-client.js +56 -0
  268. package/dist/esm/cli/commands/update-client.js.map +1 -0
  269. package/dist/esm/cli/config.js +26 -0
  270. package/dist/esm/cli/config.js.map +1 -0
  271. package/dist/esm/cli/utils.js +94 -0
  272. package/dist/esm/cli/utils.js.map +1 -0
  273. package/dist/esm/cli.js +22 -0
  274. package/dist/esm/cli.js.map +1 -0
  275. package/dist/esm/constants/ibc-core-registry.js +21 -0
  276. package/dist/esm/constants/ibc-core-registry.js.map +1 -0
  277. package/dist/esm/constants/services.js +3 -0
  278. package/dist/esm/constants/services.js.map +1 -0
  279. package/dist/esm/constants/z-asset-registry.js +23 -0
  280. package/dist/esm/constants/z-asset-registry.js.map +1 -0
  281. package/dist/esm/gen/prover_pb.js +74 -0
  282. package/dist/esm/gen/prover_pb.js.map +1 -0
  283. package/dist/esm/index.js +22 -0
  284. package/dist/esm/index.js.map +1 -0
  285. package/dist/esm/internal/evm.js +169 -0
  286. package/dist/esm/internal/evm.js.map +1 -0
  287. package/dist/esm/internal/evmWalletClient.js +2 -0
  288. package/dist/esm/internal/evmWalletClient.js.map +1 -0
  289. package/dist/esm/internal/publicClient.js +41 -0
  290. package/dist/esm/internal/publicClient.js.map +1 -0
  291. package/dist/esm/internal/walletClient.js +35 -0
  292. package/dist/esm/internal/walletClient.js.map +1 -0
  293. package/dist/esm/legacy/client.js +1212 -0
  294. package/dist/esm/legacy/client.js.map +1 -0
  295. package/dist/esm/legacy/prover.js +105 -0
  296. package/dist/esm/legacy/prover.js.map +1 -0
  297. package/dist/esm/package.json +4 -0
  298. package/dist/esm/poseidon2.js +218 -0
  299. package/dist/esm/poseidon2.js.map +1 -0
  300. package/dist/esm/promises/Attestor.js +14 -0
  301. package/dist/esm/promises/Attestor.js.map +1 -0
  302. package/dist/esm/promises/EvmPublicClient.js +26 -0
  303. package/dist/esm/promises/EvmPublicClient.js.map +1 -0
  304. package/dist/esm/promises/EvmWalletClient.js +43 -0
  305. package/dist/esm/promises/EvmWalletClient.js.map +1 -0
  306. package/dist/esm/promises/Payment.js +13 -0
  307. package/dist/esm/promises/Payment.js.map +1 -0
  308. package/dist/esm/promises/Prover.js +17 -0
  309. package/dist/esm/promises/Prover.js.map +1 -0
  310. package/dist/esm/promises/PublicClient.js +45 -0
  311. package/dist/esm/promises/PublicClient.js.map +1 -0
  312. package/dist/esm/promises/WalletClient.js +36 -0
  313. package/dist/esm/promises/WalletClient.js.map +1 -0
  314. package/dist/esm/promises/index.js +8 -0
  315. package/dist/esm/promises/index.js.map +1 -0
  316. package/dist/esm/rpc.js +850 -0
  317. package/dist/esm/rpc.js.map +1 -0
  318. package/dist/esm/types.js +2 -0
  319. package/dist/esm/types.js.map +1 -0
  320. package/gen/prover_pb/package.json +6 -0
  321. package/index/package.json +6 -0
  322. package/legacy/client/package.json +6 -0
  323. package/legacy/prover/package.json +6 -0
  324. package/package.json +397 -44
  325. package/poseidon2/package.json +6 -0
  326. package/promises/Attestor/package.json +6 -0
  327. package/promises/EvmPublicClient/package.json +6 -0
  328. package/promises/EvmWalletClient/package.json +6 -0
  329. package/promises/Payment/package.json +6 -0
  330. package/promises/Prover/package.json +6 -0
  331. package/promises/PublicClient/package.json +6 -0
  332. package/promises/WalletClient/package.json +6 -0
  333. package/promises/index/package.json +6 -0
  334. package/promises/package.json +6 -0
  335. package/rpc/package.json +6 -0
  336. package/src/Abi.ts +195 -0
  337. package/src/Attestor.ts +113 -0
  338. package/src/Constants.ts +4 -0
  339. package/src/Domain.ts +52 -0
  340. package/src/Error.ts +163 -0
  341. package/src/EvmPublicClient.ts +549 -0
  342. package/src/EvmWalletClient.ts +1034 -0
  343. package/src/Payment.ts +523 -0
  344. package/src/PaymentError.ts +39 -0
  345. package/src/Prover.ts +240 -0
  346. package/src/PublicClient.ts +196 -0
  347. package/src/Schema.ts +36 -0
  348. package/src/Utils.ts +43 -0
  349. package/src/WalletClient.ts +172 -0
  350. package/src/attestation.ts +69 -0
  351. package/src/cli/commands/balance.ts +88 -0
  352. package/src/cli/commands/deposit.ts +104 -0
  353. package/src/cli/commands/export-verifier.ts +28 -0
  354. package/src/cli/commands/generate.ts +86 -0
  355. package/src/cli/commands/history.ts +91 -0
  356. package/src/cli/commands/prove.ts +133 -0
  357. package/src/cli/commands/redeem.ts +277 -0
  358. package/src/cli/commands/update-client.ts +96 -0
  359. package/src/cli/config.ts +55 -0
  360. package/src/cli/utils.ts +136 -0
  361. package/src/cli.ts +31 -0
  362. package/src/constants/ibc-core-registry.ts +44 -0
  363. package/src/constants/services.ts +4 -0
  364. package/src/constants/z-asset-registry.ts +47 -0
  365. package/src/gen/prover_pb.ts +375 -0
  366. package/src/index.ts +23 -0
  367. package/src/internal/evm.ts +361 -0
  368. package/src/internal/evmWalletClient.ts +0 -0
  369. package/src/internal/publicClient.ts +57 -0
  370. package/src/internal/walletClient.ts +50 -0
  371. package/src/legacy/client.ts +1652 -0
  372. package/src/legacy/prover.ts +135 -0
  373. package/src/poseidon2.ts +246 -0
  374. package/src/promises/Attestor.ts +25 -0
  375. package/src/promises/EvmPublicClient.ts +39 -0
  376. package/src/promises/EvmWalletClient.ts +63 -0
  377. package/src/promises/Payment.ts +86 -0
  378. package/src/promises/Prover.ts +26 -0
  379. package/src/promises/PublicClient.ts +47 -0
  380. package/src/promises/WalletClient.ts +38 -0
  381. package/src/promises/index.ts +7 -0
  382. package/src/rpc.ts +994 -0
  383. package/src/types.ts +281 -0
  384. package/types/package.json +6 -0
  385. package/dist/LICENSE +0 -1
  386. package/dist/chunk-37PNLRA6.js +0 -2418
  387. package/dist/cli.cjs +0 -3031
  388. package/dist/cli.js +0 -675
  389. package/dist/index.cjs +0 -2451
  390. package/dist/index.js +0 -1
  391. package/dist/package.json +0 -18
  392. package/dist/payments.d.ts +0 -835
  393. /package/{dist → src}/tsdoc-metadata.json +0 -0
package/src/rpc.ts ADDED
@@ -0,0 +1,994 @@
1
+ import {
2
+ type Address,
3
+ type Block,
4
+ bytesToHex,
5
+ createPublicClient,
6
+ encodeAbiParameters,
7
+ encodePacked,
8
+ type GetProofReturnType,
9
+ type Hash,
10
+ type Hex,
11
+ hexToBigInt,
12
+ hexToBytes,
13
+ http,
14
+ keccak256,
15
+ type PublicClient,
16
+ padHex,
17
+ sha256,
18
+ toHex,
19
+ toRlp,
20
+ type WalletClient,
21
+ } from "viem";
22
+ import { sign } from "viem/accounts";
23
+ import type {
24
+ ConsensusState,
25
+ CounterpartyInfo,
26
+ DepositToZAssetResult,
27
+ LightClientData,
28
+ MptProofData,
29
+ ProofJSON,
30
+ RedeemParams,
31
+ RedemptionHistoryEntry,
32
+ UpdateLightClientResult,
33
+ } from "./types.js";
34
+
35
+ const ERC20_ABI = [
36
+ {
37
+ inputs: [{ name: "account", type: "address" }],
38
+ name: "balanceOf",
39
+ outputs: [{ name: "", type: "uint256" }],
40
+ stateMutability: "view",
41
+ type: "function",
42
+ },
43
+ {
44
+ inputs: [],
45
+ name: "decimals",
46
+ outputs: [{ name: "", type: "uint8" }],
47
+ stateMutability: "view",
48
+ type: "function",
49
+ },
50
+ {
51
+ inputs: [],
52
+ name: "symbol",
53
+ outputs: [{ name: "", type: "string" }],
54
+ stateMutability: "view",
55
+ type: "function",
56
+ },
57
+ {
58
+ inputs: [
59
+ { name: "spender", type: "address" },
60
+ { name: "amount", type: "uint256" },
61
+ ],
62
+ name: "approve",
63
+ outputs: [{ name: "", type: "bool" }],
64
+ stateMutability: "nonpayable",
65
+ type: "function",
66
+ },
67
+ {
68
+ inputs: [
69
+ { name: "to", type: "address" },
70
+ { name: "amount", type: "uint256" },
71
+ ],
72
+ name: "transfer",
73
+ outputs: [{ name: "", type: "bool" }],
74
+ stateMutability: "nonpayable",
75
+ type: "function",
76
+ },
77
+ {
78
+ inputs: [
79
+ { name: "from", type: "address" },
80
+ { name: "to", type: "address" },
81
+ { name: "amount", type: "uint256" },
82
+ ],
83
+ name: "transferFrom",
84
+ outputs: [{ name: "", type: "bool" }],
85
+ stateMutability: "nonpayable",
86
+ type: "function",
87
+ },
88
+ ] as const;
89
+
90
+ export const IBC_STORE_ABI = [
91
+ {
92
+ inputs: [{ name: "clientId", type: "uint32" }],
93
+ name: "getClient",
94
+ outputs: [{ name: "", type: "address" }],
95
+ stateMutability: "view",
96
+ type: "function",
97
+ },
98
+ ] as const;
99
+
100
+ const LIGHT_CLIENT_ABI = [
101
+ {
102
+ inputs: [{ name: "clientId", type: "uint32" }],
103
+ name: "getLatestHeight",
104
+ outputs: [{ name: "", type: "uint64" }],
105
+ stateMutability: "view",
106
+ type: "function",
107
+ },
108
+ {
109
+ inputs: [
110
+ { name: "clientId", type: "uint32" },
111
+ { name: "height", type: "uint64" },
112
+ ],
113
+ name: "getConsensusState",
114
+ outputs: [{ name: "", type: "bytes" }],
115
+ stateMutability: "view",
116
+ type: "function",
117
+ },
118
+ ] as const;
119
+
120
+ const ZASSET_ABI = [
121
+ {
122
+ inputs: [{ name: "nullifier", type: "uint256" }],
123
+ name: "nullifierBalance",
124
+ outputs: [{ name: "", type: "uint256" }],
125
+ stateMutability: "view",
126
+ type: "function",
127
+ },
128
+ {
129
+ inputs: [{ name: "clientId", type: "uint32" }],
130
+ name: "counterparty",
131
+ outputs: [
132
+ {
133
+ components: [
134
+ { name: "tokenAddressKey", type: "bytes32" },
135
+ { name: "balanceSlot", type: "bytes32" },
136
+ ],
137
+ type: "tuple",
138
+ },
139
+ ],
140
+ stateMutability: "view",
141
+ type: "function",
142
+ },
143
+ {
144
+ inputs: [],
145
+ name: "ibcHandler",
146
+ outputs: [{ name: "", type: "address" }],
147
+ stateMutability: "view",
148
+ type: "function",
149
+ },
150
+ {
151
+ inputs: [{ name: "clientId", type: "uint32" }],
152
+ name: "stateRootIndex",
153
+ outputs: [{ name: "", type: "uint256" }],
154
+ stateMutability: "view",
155
+ type: "function",
156
+ },
157
+ {
158
+ inputs: [],
159
+ name: "underlying",
160
+ outputs: [{ name: "", type: "address" }],
161
+ stateMutability: "view",
162
+ type: "function",
163
+ },
164
+ {
165
+ inputs: [{ name: "amount", type: "uint256" }],
166
+ name: "deposit",
167
+ outputs: [],
168
+ stateMutability: "nonpayable",
169
+ type: "function",
170
+ },
171
+ {
172
+ inputs: [
173
+ { name: "to", type: "address" },
174
+ { name: "amount", type: "uint256" },
175
+ ],
176
+ name: "transfer",
177
+ outputs: [{ name: "", type: "bool" }],
178
+ stateMutability: "nonpayable",
179
+ type: "function",
180
+ },
181
+ {
182
+ inputs: [
183
+ { name: "proof", type: "uint256[8]" },
184
+ { name: "commitments", type: "uint256[2]" },
185
+ { name: "commitmentPok", type: "uint256[2]" },
186
+ {
187
+ name: "lightClients",
188
+ type: "tuple[]",
189
+ components: [
190
+ { name: "clientId", type: "uint32" },
191
+ { name: "height", type: "uint64" },
192
+ ],
193
+ },
194
+ { name: "nullifier", type: "uint256" },
195
+ { name: "value", type: "uint256" },
196
+ { name: "beneficiary", type: "address" },
197
+ { name: "attestedMessage", type: "bytes32" },
198
+ { name: "signature", type: "bytes" },
199
+ ],
200
+ name: "redeem",
201
+ outputs: [],
202
+ stateMutability: "nonpayable",
203
+ type: "function",
204
+ },
205
+ {
206
+ anonymous: false,
207
+ inputs: [
208
+ { indexed: true, name: "from", type: "address" },
209
+ { indexed: true, name: "to", type: "address" },
210
+ { indexed: false, name: "value", type: "uint256" },
211
+ ],
212
+ name: "Transfer",
213
+ type: "event",
214
+ },
215
+ {
216
+ anonymous: false,
217
+ inputs: [
218
+ { indexed: true, name: "nullifier", type: "uint256" },
219
+ { indexed: true, name: "redeemAmount", type: "uint256" },
220
+ { indexed: true, name: "beneficiary", type: "address" },
221
+ ],
222
+ name: "Redeemed",
223
+ type: "event",
224
+ },
225
+ ] as const;
226
+
227
+ const IBC_HANDLER_ABI = [
228
+ {
229
+ inputs: [
230
+ {
231
+ components: [
232
+ { name: "clientId", type: "uint32" },
233
+ { name: "clientMessage", type: "bytes" },
234
+ { name: "relayer", type: "address" },
235
+ ],
236
+ name: "msg_",
237
+ type: "tuple",
238
+ },
239
+ ],
240
+ name: "updateClient",
241
+ outputs: [],
242
+ stateMutability: "nonpayable",
243
+ type: "function",
244
+ },
245
+ ] as const;
246
+
247
+ // @ts-expect-error
248
+ const MULTICALL3_ADDRESS =
249
+ "0xcA11bde05977b3631167028862bE2a173976CA11" as Address;
250
+
251
+ // @ts-expect-error
252
+ const MULTICALL3_ABI = [
253
+ {
254
+ inputs: [
255
+ {
256
+ name: "calls",
257
+ type: "tuple[]",
258
+ components: [
259
+ { name: "target", type: "address" },
260
+ { name: "allowFailure", type: "bool" },
261
+ { name: "callData", type: "bytes" },
262
+ ],
263
+ },
264
+ ],
265
+ name: "aggregate3",
266
+ outputs: [
267
+ {
268
+ name: "returnData",
269
+ type: "tuple[]",
270
+ components: [
271
+ { name: "success", type: "bool" },
272
+ { name: "returnData", type: "bytes" },
273
+ ],
274
+ },
275
+ ],
276
+ stateMutability: "payable",
277
+ type: "function",
278
+ },
279
+ ] as const;
280
+
281
+ /**
282
+ * @public
283
+ */
284
+ export class RpcClient {
285
+ private client: PublicClient;
286
+
287
+ constructor(rpcUrl: string) {
288
+ this.client = createPublicClient({
289
+ transport: http(rpcUrl),
290
+ });
291
+ }
292
+
293
+ getClient(): PublicClient {
294
+ return this.client;
295
+ }
296
+
297
+ async getChainId(): Promise<bigint> {
298
+ return BigInt(await this.client.getChainId());
299
+ }
300
+
301
+ async getLatestBlockNumber(): Promise<bigint> {
302
+ return this.client.getBlockNumber();
303
+ }
304
+
305
+ async getBalance(
306
+ tokenAddress: Address,
307
+ accountAddress: Address,
308
+ blockNumber?: bigint,
309
+ ): Promise<bigint> {
310
+ return this.client.readContract({
311
+ address: tokenAddress,
312
+ abi: ERC20_ABI,
313
+ functionName: "balanceOf",
314
+ args: [accountAddress],
315
+ blockNumber,
316
+ });
317
+ }
318
+
319
+ async getDecimals(tokenAddress: Address): Promise<number> {
320
+ return this.client.readContract({
321
+ address: tokenAddress,
322
+ abi: ERC20_ABI,
323
+ functionName: "decimals",
324
+ });
325
+ }
326
+
327
+ async getSymbol(tokenAddress: Address): Promise<string> {
328
+ return this.client.readContract({
329
+ address: tokenAddress,
330
+ abi: ERC20_ABI,
331
+ functionName: "symbol",
332
+ });
333
+ }
334
+
335
+ async getLightClientAddress(
336
+ ibcStoreAddress: Address,
337
+ clientId: number,
338
+ ): Promise<Address> {
339
+ return this.client.readContract({
340
+ address: ibcStoreAddress,
341
+ abi: IBC_STORE_ABI,
342
+ functionName: "getClient",
343
+ args: [clientId],
344
+ });
345
+ }
346
+
347
+ async getLatestHeight(
348
+ lightClientAddress: Address,
349
+ clientId: number,
350
+ ): Promise<bigint> {
351
+ return this.client.readContract({
352
+ address: lightClientAddress,
353
+ abi: LIGHT_CLIENT_ABI,
354
+ functionName: "getLatestHeight",
355
+ args: [clientId],
356
+ });
357
+ }
358
+
359
+ /**
360
+ * Get consensus state, extracting the state root at the given byte index
361
+ */
362
+ async getConsensusState(
363
+ lightClientAddress: Address,
364
+ clientId: number,
365
+ height: bigint,
366
+ stateRootIndex: bigint,
367
+ ): Promise<ConsensusState> {
368
+ const consensusBytes = await this.client.readContract({
369
+ address: lightClientAddress,
370
+ abi: LIGHT_CLIENT_ABI,
371
+ functionName: "getConsensusState",
372
+ args: [clientId, height],
373
+ });
374
+
375
+ const bytes: Uint8Array = hexToBytes(consensusBytes);
376
+ const idx = Number(stateRootIndex);
377
+ const stateRoot = bytesToHex(bytes.slice(idx, idx + 32)) as Hash;
378
+
379
+ return { stateRoot };
380
+ }
381
+
382
+ async getNullifierBalance(
383
+ zassetAddress: Address,
384
+ nullifier: bigint,
385
+ ): Promise<bigint> {
386
+ return this.client.readContract({
387
+ address: zassetAddress,
388
+ abi: ZASSET_ABI,
389
+ functionName: "nullifierBalance",
390
+ args: [nullifier],
391
+ });
392
+ }
393
+
394
+ async getCounterparty(
395
+ zassetAddress: Address,
396
+ clientId: number,
397
+ ): Promise<CounterpartyInfo> {
398
+ const result = await this.client.readContract({
399
+ address: zassetAddress,
400
+ abi: ZASSET_ABI,
401
+ functionName: "counterparty",
402
+ args: [clientId],
403
+ });
404
+
405
+ return {
406
+ tokenAddressKey: result.tokenAddressKey as Hash,
407
+ balanceSlot: result.balanceSlot as Hash,
408
+ };
409
+ }
410
+
411
+ async getIbcHandlerAddress(zassetAddress: Address): Promise<Address> {
412
+ return this.client.readContract({
413
+ address: zassetAddress,
414
+ abi: ZASSET_ABI,
415
+ functionName: "ibcHandler",
416
+ });
417
+ }
418
+
419
+ async getStateRootIndex(
420
+ zassetAddress: Address,
421
+ clientId: number,
422
+ ): Promise<bigint> {
423
+ return this.client.readContract({
424
+ address: zassetAddress,
425
+ abi: ZASSET_ABI,
426
+ functionName: "stateRootIndex",
427
+ args: [clientId],
428
+ });
429
+ }
430
+
431
+ async getProof(
432
+ address: Address,
433
+ storageKeys: Hex[],
434
+ blockNumber: bigint,
435
+ ): Promise<GetProofReturnType> {
436
+ return this.client.getProof({
437
+ address,
438
+ storageKeys,
439
+ blockNumber,
440
+ });
441
+ }
442
+
443
+ async getBlock(blockNumber: bigint) {
444
+ return this.client.getBlock({ blockNumber });
445
+ }
446
+
447
+ /**
448
+ * Get redemption history for a nullifier by querying Redeemed events
449
+ */
450
+ async getRedemptionHistory(
451
+ zassetAddress: Address,
452
+ nullifier: bigint,
453
+ fromBlock?: bigint,
454
+ toBlock?: bigint,
455
+ ): Promise<RedemptionHistoryEntry[]> {
456
+ const logs = await this.client.getLogs({
457
+ address: zassetAddress,
458
+ event: {
459
+ type: "event",
460
+ name: "Redeemed",
461
+ inputs: [
462
+ { indexed: true, name: "nullifier", type: "uint256" },
463
+ { indexed: true, name: "redeemAmount", type: "uint256" },
464
+ { indexed: true, name: "beneficiary", type: "address" },
465
+ ],
466
+ },
467
+ args: {
468
+ nullifier,
469
+ },
470
+ fromBlock: fromBlock ?? "earliest",
471
+ toBlock: toBlock ?? "latest",
472
+ });
473
+
474
+ return logs.map((log) => ({
475
+ txHash: log.transactionHash as Hash,
476
+ blockNumber: log.blockNumber,
477
+ redeemAmount: log.args.redeemAmount as bigint,
478
+ beneficiary: log.args.beneficiary as Address,
479
+ }));
480
+ }
481
+ }
482
+
483
+ /**
484
+ * Compute the storage slot for an ERC20 balance mapping: keccak256(abi.encode(address, slot))
485
+ * @public
486
+ */
487
+ export function computeStorageSlot(address: Address, mappingSlot: bigint): Hex {
488
+ const paddedAddress = padHex(address, { size: 32 });
489
+ const paddedSlot = padHex(toHex(mappingSlot), { size: 32 });
490
+ return keccak256(
491
+ encodePacked(["bytes32", "bytes32"], [paddedAddress, paddedSlot]),
492
+ );
493
+ }
494
+
495
+ /**
496
+ * @public
497
+ */
498
+ export async function fetchLightClients(
499
+ dstClient: RpcClient,
500
+ zassetAddress: Address,
501
+ clientIds: number[],
502
+ ): Promise<LightClientData[]> {
503
+ const ibcHandlerAddress = await dstClient.getIbcHandlerAddress(zassetAddress);
504
+ const results: LightClientData[] = [];
505
+
506
+ for (const clientId of clientIds) {
507
+ try {
508
+ const lightClientAddress = await dstClient.getLightClientAddress(
509
+ ibcHandlerAddress,
510
+ clientId,
511
+ );
512
+ const height = await dstClient.getLatestHeight(
513
+ lightClientAddress,
514
+ clientId,
515
+ );
516
+ const stateRootIndex = await dstClient.getStateRootIndex(
517
+ zassetAddress,
518
+ clientId,
519
+ );
520
+ const { stateRoot } = await dstClient.getConsensusState(
521
+ lightClientAddress,
522
+ clientId,
523
+ height,
524
+ stateRootIndex,
525
+ );
526
+
527
+ results.push({ clientId, height, stateRoot });
528
+ } catch {}
529
+ }
530
+
531
+ return results;
532
+ }
533
+
534
+ /**
535
+ * @public
536
+ */
537
+ export async function fetchMptProof(
538
+ srcClient: RpcClient,
539
+ tokenAddress: Address,
540
+ storageSlot: Hex,
541
+ blockNumber: bigint,
542
+ ): Promise<MptProofData> {
543
+ const proof = await srcClient.getProof(
544
+ tokenAddress,
545
+ [storageSlot],
546
+ blockNumber,
547
+ );
548
+
549
+ let storageProof: Hex[] = [];
550
+ let storageValue: Hex = "0x0";
551
+
552
+ if (proof.storageProof.length > 0 && proof.storageProof[0]) {
553
+ storageProof = proof.storageProof[0].proof as Hex[];
554
+ storageValue = toHex(proof.storageProof[0].value);
555
+ }
556
+
557
+ return {
558
+ accountProof: proof.accountProof as Hex[],
559
+ storageProof,
560
+ storageValue,
561
+ storageRoot: proof.storageHash,
562
+ };
563
+ }
564
+
565
+ /**
566
+ * Deterministically shuffle light clients using the secret as seed.
567
+ * Same secret always produces the same ordering for privacy.
568
+ * @public
569
+ */
570
+ export function deterministicShuffleClients(
571
+ clients: LightClientData[],
572
+ secret: Hex,
573
+ ): LightClientData[] {
574
+ if (clients.length <= 1) {
575
+ return [...clients];
576
+ }
577
+
578
+ // Seed = SHA256(secret || clientHeights as big-endian uint64s)
579
+ const secretBytes = hexToBytes(secret);
580
+ const heightsBytes = new Uint8Array(clients.length * 8);
581
+ for (let i = 0; i < clients.length; i++) {
582
+ const view = new DataView(heightsBytes.buffer, i * 8, 8);
583
+ view.setBigUint64(0, clients[i]!.height, false);
584
+ }
585
+
586
+ const combined = new Uint8Array(secretBytes.length + heightsBytes.length);
587
+ combined.set(secretBytes, 0);
588
+ combined.set(heightsBytes, secretBytes.length);
589
+ const seedHex = sha256(combined);
590
+ const seed = hexToBytes(seedHex);
591
+
592
+ // Fisher-Yates shuffle with deterministic PRNG
593
+ const shuffled = [...clients];
594
+ let seedIndex = 0;
595
+ for (let i = shuffled.length - 1; i > 0; i--) {
596
+ const randomByte = seed[seedIndex % seed.length]!;
597
+ seedIndex++;
598
+ const j = randomByte % (i + 1);
599
+ [shuffled[i], shuffled[j]] = [shuffled[j]!, shuffled[i]!];
600
+ }
601
+
602
+ return shuffled;
603
+ }
604
+
605
+ /**
606
+ * Sign an attested message with raw ECDSA (no EIP-191 prefix).
607
+ * Matches Go CLI's crypto.Sign behavior for SignatureCheckerLib verification.
608
+ * @public
609
+ */
610
+ export async function signAttestedMessage(
611
+ message: Hex,
612
+ privateKey: Hex,
613
+ ): Promise<Hex> {
614
+ const messageBytes = hexToBytes(message);
615
+ if (messageBytes.length !== 32) {
616
+ throw new Error(
617
+ `Invalid message length: expected 32 bytes, got ${messageBytes.length}`,
618
+ );
619
+ }
620
+
621
+ const signature = await sign({
622
+ hash: message,
623
+ privateKey,
624
+ to: "hex",
625
+ });
626
+
627
+ return signature;
628
+ }
629
+
630
+ /**
631
+ * @public
632
+ */
633
+ export function parseProofJson(proofJsonBytes: Uint8Array): ProofJSON {
634
+ const jsonStr = new TextDecoder().decode(proofJsonBytes);
635
+ const raw = JSON.parse(jsonStr);
636
+ const commitments = raw.commitments ?? ["0x0", "0x0"];
637
+
638
+ return {
639
+ proof: raw.proof as ProofJSON["proof"],
640
+ commitments: commitments as ProofJSON["commitments"],
641
+ commitmentPok: raw.commitmentPok as ProofJSON["commitmentPok"],
642
+ publicInputs: raw.publicInputs ?? [],
643
+ };
644
+ }
645
+
646
+ /**
647
+ * Client-side metadata for redeem (NOT from prover)
648
+ * @public
649
+ */
650
+ export interface RedeemMetadata {
651
+ lightClients: LightClientData[];
652
+ nullifier: bigint;
653
+ value: bigint;
654
+ beneficiary: Address;
655
+ attestedMessage: Hex;
656
+ signature: Hex;
657
+ }
658
+
659
+ /**
660
+ * @public
661
+ */
662
+ export function proofJsonToRedeemParams(
663
+ proofJson: ProofJSON,
664
+ metadata: RedeemMetadata,
665
+ ): RedeemParams {
666
+ const parseBigInt = (s: string): bigint => {
667
+ if (s.startsWith("0x")) {
668
+ return hexToBigInt(s as Hex);
669
+ }
670
+ return BigInt(s);
671
+ };
672
+
673
+ return {
674
+ proof: proofJson.proof.map(parseBigInt) as RedeemParams["proof"],
675
+ commitments: proofJson.commitments.map(
676
+ parseBigInt,
677
+ ) as RedeemParams["commitments"],
678
+ commitmentPok: proofJson.commitmentPok.map(
679
+ parseBigInt,
680
+ ) as RedeemParams["commitmentPok"],
681
+ lightClients: metadata.lightClients.map((lc) => ({
682
+ clientId: lc.clientId,
683
+ height: lc.height,
684
+ })),
685
+ nullifier: metadata.nullifier,
686
+ value: metadata.value,
687
+ beneficiary: metadata.beneficiary,
688
+ attestedMessage: metadata.attestedMessage,
689
+ signature: metadata.signature,
690
+ };
691
+ }
692
+
693
+ /**
694
+ * @public
695
+ */
696
+ export async function submitRedeem(
697
+ zassetAddress: Address,
698
+ params: RedeemParams,
699
+ walletClient: WalletClient,
700
+ ): Promise<Hash> {
701
+ if (!walletClient.account) {
702
+ throw new Error("WalletClient must have an account");
703
+ }
704
+ if (!walletClient.chain) {
705
+ throw new Error("WalletClient must have a chain configured");
706
+ }
707
+
708
+ const hash = await walletClient
709
+ .writeContractSync({
710
+ address: zassetAddress,
711
+ abi: ZASSET_ABI,
712
+ functionName: "redeem",
713
+ args: [
714
+ params.proof,
715
+ params.commitments,
716
+ params.commitmentPok,
717
+ params.lightClients,
718
+ params.nullifier,
719
+ params.value,
720
+ params.beneficiary,
721
+ params.attestedMessage,
722
+ params.signature,
723
+ ],
724
+ chain: walletClient.chain,
725
+ account: walletClient.account,
726
+ })
727
+ .then((x) => x.transactionHash);
728
+
729
+ return hash;
730
+ }
731
+
732
+ /**
733
+ * RLP encode an EVM block header for the loopback light client.
734
+ * The header fields must be in the exact order expected by the EVM.
735
+ * Verifies the encoding by checking that keccak256(rlp) == block.hash
736
+ */
737
+ function rlpEncodeBlockHeader(block: Block): Hex {
738
+ // Helper to convert bigint/number to minimal RLP hex encoding
739
+ // RLP requires no leading zeros, and 0 is encoded as empty string (0x80)
740
+ const toRlpHex = (value: bigint | number | null | undefined): Hex => {
741
+ if (value === undefined || value === null || value === 0n || value === 0) {
742
+ return "0x" as Hex;
743
+ }
744
+ let hex =
745
+ typeof value === "bigint" ? value.toString(16) : value.toString(16);
746
+ // Ensure even length for proper byte encoding
747
+ if (hex.length % 2 !== 0) {
748
+ hex = "0" + hex;
749
+ }
750
+ return `0x${hex}` as Hex;
751
+ };
752
+
753
+ // Build header fields in order (pre-merge + post-merge fields)
754
+ const headerFields: (Hex | Hex[])[] = [
755
+ block.parentHash,
756
+ block.sha3Uncles,
757
+ block.miner,
758
+ block.stateRoot,
759
+ block.transactionsRoot,
760
+ block.receiptsRoot,
761
+ block.logsBloom ?? (("0x" + "00".repeat(256)) as Hex),
762
+ toRlpHex(block.difficulty),
763
+ toRlpHex(block.number),
764
+ toRlpHex(block.gasLimit),
765
+ toRlpHex(block.gasUsed),
766
+ toRlpHex(block.timestamp),
767
+ block.extraData,
768
+ block.mixHash ??
769
+ ("0x0000000000000000000000000000000000000000000000000000000000000000" as Hex),
770
+ block.nonce ?? ("0x0000000000000000" as Hex),
771
+ ];
772
+
773
+ // Post-merge fields (EIP-1559, EIP-4895, EIP-4844, EIP-4788, EIP-7685)
774
+ if (block.baseFeePerGas !== undefined && block.baseFeePerGas !== null) {
775
+ headerFields.push(toRlpHex(block.baseFeePerGas));
776
+ }
777
+ if (block.withdrawalsRoot) {
778
+ headerFields.push(block.withdrawalsRoot);
779
+ }
780
+ if (block.blobGasUsed !== undefined && block.blobGasUsed !== null) {
781
+ headerFields.push(toRlpHex(block.blobGasUsed));
782
+ }
783
+ if (block.excessBlobGas !== undefined && block.excessBlobGas !== null) {
784
+ headerFields.push(toRlpHex(block.excessBlobGas));
785
+ }
786
+ if (block.parentBeaconBlockRoot) {
787
+ headerFields.push(block.parentBeaconBlockRoot);
788
+ }
789
+ // EIP-7685 requestsHash (Pectra upgrade) - not yet in viem types
790
+ const blockAny = block as Record<string, unknown>;
791
+ if (blockAny.requestsHash) {
792
+ headerFields.push(blockAny.requestsHash as Hex);
793
+ }
794
+
795
+ const rlpEncoded = toRlp(headerFields);
796
+
797
+ // Verify the encoding produces the correct block hash
798
+ const computedHash = keccak256(rlpEncoded);
799
+ if (computedHash !== block.hash) {
800
+ throw new Error(
801
+ `RLP encoding mismatch: computed hash ${computedHash} does not match block hash ${block.hash}. ` +
802
+ `Block number: ${block.number}, fields count: ${headerFields.length}`,
803
+ );
804
+ }
805
+
806
+ return rlpEncoded;
807
+ }
808
+
809
+ /**
810
+ * Update a loopback light client to a specific block height.
811
+ * The loopback client operates on the same chain, so only one RPC URL is needed.
812
+ *
813
+ * @param rpcUrl - RPC URL for the chain (same chain for fetching block and submitting tx)
814
+ * @param ibcHandlerAddress - Address of the IBCHandler contract
815
+ * @param clientId - The light client ID to update
816
+ * @param height - Block height to update to (bigint or 'latest')
817
+ * @param walletClient - viem WalletClient with account and chain configured
818
+ * @returns Transaction hash, block number, state root, and chain ID
819
+ * @public
820
+ */
821
+ export async function updateLoopbackClient(
822
+ rpcUrl: string,
823
+ ibcHandlerAddress: Address,
824
+ clientId: number,
825
+ height: bigint | "latest",
826
+ walletClient: WalletClient,
827
+ ): Promise<UpdateLightClientResult> {
828
+ if (!walletClient.account) {
829
+ throw new Error("WalletClient must have an account");
830
+ }
831
+ if (!walletClient.chain) {
832
+ throw new Error("WalletClient must have a chain configured");
833
+ }
834
+
835
+ // Create public client
836
+ const publicClient = createPublicClient({
837
+ transport: http(rpcUrl),
838
+ });
839
+
840
+ // Get chain ID from RPC
841
+ const chainId = await publicClient.getChainId();
842
+
843
+ // Get the block number
844
+ const blockNumber =
845
+ height === "latest" ? await publicClient.getBlockNumber() : height;
846
+
847
+ // Get the block for metadata
848
+ const block = await publicClient.getBlock({ blockNumber });
849
+
850
+ if (!block.number) {
851
+ throw new Error("Block number is null");
852
+ }
853
+
854
+ // RLP encode the block header and verify the hash matches
855
+ const rlpEncodedHeader = rlpEncodeBlockHeader(block);
856
+
857
+ // Encode the Header struct: (uint64 height, bytes encodedHeader)
858
+ const clientMessage = encodeAbiParameters(
859
+ [
860
+ { type: "uint64", name: "height" },
861
+ { type: "bytes", name: "encodedHeader" },
862
+ ],
863
+ [block.number, rlpEncodedHeader],
864
+ );
865
+
866
+ // Wait for the next block so the fetched block's hash is verifiable on-chain
867
+ let currentBlock = await publicClient.getBlockNumber();
868
+ while (currentBlock <= blockNumber) {
869
+ await new Promise((resolve) => setTimeout(resolve, 1000));
870
+ currentBlock = await publicClient.getBlockNumber();
871
+ }
872
+
873
+ // Submit the transaction
874
+ const txHash = await walletClient
875
+ .writeContractSync({
876
+ address: ibcHandlerAddress,
877
+ abi: IBC_HANDLER_ABI,
878
+ functionName: "updateClient",
879
+ args: [
880
+ {
881
+ clientId,
882
+ clientMessage,
883
+ relayer: walletClient.account.address,
884
+ },
885
+ ],
886
+ chain: walletClient.chain,
887
+ account: walletClient.account,
888
+ })
889
+ .then((x) => x.transactionHash);
890
+
891
+ return {
892
+ txHash,
893
+ blockNumber: block.number,
894
+ stateRoot: block.stateRoot,
895
+ chainId: BigInt(chainId),
896
+ };
897
+ }
898
+
899
+ /**
900
+ * Deposit underlying tokens to ZAsset and transfer to a deposit address.
901
+ * Executes 3 transactions: approve → deposit → transfer.
902
+ *
903
+ * @param rpcUrl - RPC URL for the chain
904
+ * @param zAssetAddress - Address of the ZAsset contract
905
+ * @param depositAddress - Address to receive the ZAsset tokens (derived from secret)
906
+ * @param amount - Amount to deposit (in underlying token's smallest unit)
907
+ * @param walletClient - viem WalletClient with account and chain configured
908
+ * @returns Transaction hash of the final transfer, underlying token address, and chain ID
909
+ * @public
910
+ */
911
+ export async function depositToZAsset(
912
+ rpcUrl: string,
913
+ zAssetAddress: Address,
914
+ depositAddress: Address,
915
+ amount: bigint,
916
+ walletClient: WalletClient,
917
+ ): Promise<DepositToZAssetResult> {
918
+ if (!walletClient.account) {
919
+ throw new Error("WalletClient must have an account");
920
+ }
921
+ if (!walletClient.chain) {
922
+ throw new Error("WalletClient must have a chain configured");
923
+ }
924
+
925
+ const publicClient = createPublicClient({
926
+ transport: http(rpcUrl),
927
+ });
928
+
929
+ const chainId = await publicClient.getChainId();
930
+
931
+ // Get underlying token address
932
+ const underlyingToken = (await publicClient.readContract({
933
+ address: zAssetAddress,
934
+ abi: ZASSET_ABI,
935
+ functionName: "underlying",
936
+ })) as Address;
937
+
938
+ if (underlyingToken === "0x0000000000000000000000000000000000000000") {
939
+ throw new Error(
940
+ "ZAsset is not a wrapped token (underlying is zero address)",
941
+ );
942
+ }
943
+
944
+ // 1. Approve ZAsset to spend underlying tokens
945
+ const approveReceipt = await walletClient.writeContractSync({
946
+ address: underlyingToken,
947
+ abi: ERC20_ABI,
948
+ functionName: "approve",
949
+ args: [zAssetAddress, amount],
950
+ chain: walletClient.chain,
951
+ account: walletClient.account,
952
+ });
953
+ if (approveReceipt.status === "reverted") {
954
+ throw new Error(
955
+ `Approve transaction reverted: ${approveReceipt.transactionHash}`,
956
+ );
957
+ }
958
+
959
+ // 2. Deposit underlying to get ZAsset
960
+ const depositReceipt = await walletClient.writeContractSync({
961
+ address: zAssetAddress,
962
+ abi: ZASSET_ABI,
963
+ functionName: "deposit",
964
+ args: [amount],
965
+ chain: walletClient.chain,
966
+ account: walletClient.account,
967
+ });
968
+ if (depositReceipt.status === "reverted") {
969
+ throw new Error(
970
+ `Deposit transaction reverted: ${depositReceipt.transactionHash}`,
971
+ );
972
+ }
973
+
974
+ // 3. Transfer ZAsset to deposit address
975
+ const transferReceipt = await walletClient.writeContractSync({
976
+ address: zAssetAddress,
977
+ abi: ZASSET_ABI,
978
+ functionName: "transfer",
979
+ args: [depositAddress, amount],
980
+ chain: walletClient.chain,
981
+ account: walletClient.account,
982
+ });
983
+ if (transferReceipt.status === "reverted") {
984
+ throw new Error(
985
+ `Transfer transaction reverted: ${transferReceipt.transactionHash}`,
986
+ );
987
+ }
988
+
989
+ return {
990
+ txHash: transferReceipt.transactionHash,
991
+ underlyingToken,
992
+ chainId: BigInt(chainId),
993
+ };
994
+ }