@ledgerhq/coin-cardano 0.1.0-next.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 (377) hide show
  1. package/.eslintrc.js +20 -0
  2. package/.turbo/turbo-build.log +4 -0
  3. package/.unimportedrc.json +35 -0
  4. package/CHANGELOG.md +19 -0
  5. package/LICENSE.txt +21 -0
  6. package/jest.config.js +8 -0
  7. package/lib/account.d.ts +7 -0
  8. package/lib/account.d.ts.map +1 -0
  9. package/lib/account.js +41 -0
  10. package/lib/account.js.map +1 -0
  11. package/lib/address.unit.test.d.ts +2 -0
  12. package/lib/address.unit.test.d.ts.map +1 -0
  13. package/lib/address.unit.test.js +21 -0
  14. package/lib/address.unit.test.js.map +1 -0
  15. package/lib/api/api-types.d.ts +106 -0
  16. package/lib/api/api-types.d.ts.map +1 -0
  17. package/lib/api/api-types.js +9 -0
  18. package/lib/api/api-types.js.map +1 -0
  19. package/lib/api/getDelegationInfo.d.ts +4 -0
  20. package/lib/api/getDelegationInfo.d.ts.map +1 -0
  21. package/lib/api/getDelegationInfo.js +48 -0
  22. package/lib/api/getDelegationInfo.js.map +1 -0
  23. package/lib/api/getNetworkInfo.d.ts +5 -0
  24. package/lib/api/getNetworkInfo.d.ts.map +1 -0
  25. package/lib/api/getNetworkInfo.js +46 -0
  26. package/lib/api/getNetworkInfo.js.map +1 -0
  27. package/lib/api/getPools.d.ts +5 -0
  28. package/lib/api/getPools.d.ts.map +1 -0
  29. package/lib/api/getPools.js +45 -0
  30. package/lib/api/getPools.js.map +1 -0
  31. package/lib/api/getTransactions.d.ts +10 -0
  32. package/lib/api/getTransactions.d.ts.map +1 -0
  33. package/lib/api/getTransactions.js +139 -0
  34. package/lib/api/getTransactions.js.map +1 -0
  35. package/lib/api/submitTransaction.d.ts +7 -0
  36. package/lib/api/submitTransaction.d.ts.map +1 -0
  37. package/lib/api/submitTransaction.js +34 -0
  38. package/lib/api/submitTransaction.js.map +1 -0
  39. package/lib/bridge/index.d.ts +11 -0
  40. package/lib/bridge/index.d.ts.map +1 -0
  41. package/lib/bridge/index.js +70 -0
  42. package/lib/bridge/index.js.map +1 -0
  43. package/lib/bridge.integration.test.d.ts +4 -0
  44. package/lib/bridge.integration.test.d.ts.map +1 -0
  45. package/lib/bridge.integration.test.js +113 -0
  46. package/lib/bridge.integration.test.js.map +1 -0
  47. package/lib/broadcast.d.ts +8 -0
  48. package/lib/broadcast.d.ts.map +1 -0
  49. package/lib/broadcast.js +28 -0
  50. package/lib/broadcast.js.map +1 -0
  51. package/lib/buildOptimisticOperation.d.ts +4 -0
  52. package/lib/buildOptimisticOperation.d.ts.map +1 -0
  53. package/lib/buildOptimisticOperation.js +125 -0
  54. package/lib/buildOptimisticOperation.js.map +1 -0
  55. package/lib/buildSubAccounts.d.ts +26 -0
  56. package/lib/buildSubAccounts.d.ts.map +1 -0
  57. package/lib/buildSubAccounts.js +124 -0
  58. package/lib/buildSubAccounts.js.map +1 -0
  59. package/lib/buildTransaction.d.ts +11 -0
  60. package/lib/buildTransaction.d.ts.map +1 -0
  61. package/lib/buildTransaction.js +342 -0
  62. package/lib/buildTransaction.js.map +1 -0
  63. package/lib/cli-transaction.d.ts +18 -0
  64. package/lib/cli-transaction.d.ts.map +1 -0
  65. package/lib/cli-transaction.js +66 -0
  66. package/lib/cli-transaction.js.map +1 -0
  67. package/lib/constants.d.ts +8 -0
  68. package/lib/constants.d.ts.map +1 -0
  69. package/lib/constants.js +12 -0
  70. package/lib/constants.js.map +1 -0
  71. package/lib/createTransaction.d.ts +9 -0
  72. package/lib/createTransaction.d.ts.map +1 -0
  73. package/lib/createTransaction.js +23 -0
  74. package/lib/createTransaction.js.map +1 -0
  75. package/lib/datasets/rawAccount.1.d.ts +3 -0
  76. package/lib/datasets/rawAccount.1.d.ts.map +1 -0
  77. package/lib/datasets/rawAccount.1.js +20 -0
  78. package/lib/datasets/rawAccount.1.js.map +1 -0
  79. package/lib/datasets/scanAccounts.d.ts +5 -0
  80. package/lib/datasets/scanAccounts.d.ts.map +1 -0
  81. package/lib/datasets/scanAccounts.js +27 -0
  82. package/lib/datasets/scanAccounts.js.map +1 -0
  83. package/lib/deviceTransactionConfig.d.ts +11 -0
  84. package/lib/deviceTransactionConfig.d.ts.map +1 -0
  85. package/lib/deviceTransactionConfig.js +106 -0
  86. package/lib/deviceTransactionConfig.js.map +1 -0
  87. package/lib/errors.d.ts +22 -0
  88. package/lib/errors.d.ts.map +1 -0
  89. package/lib/errors.js +18 -0
  90. package/lib/errors.js.map +1 -0
  91. package/lib/estimateMaxSpendable.d.ts +9 -0
  92. package/lib/estimateMaxSpendable.d.ts.map +1 -0
  93. package/lib/estimateMaxSpendable.js +53 -0
  94. package/lib/estimateMaxSpendable.js.map +1 -0
  95. package/lib/getTransactionStatus.d.ts +4 -0
  96. package/lib/getTransactionStatus.d.ts.map +1 -0
  97. package/lib/getTransactionStatus.js +214 -0
  98. package/lib/getTransactionStatus.js.map +1 -0
  99. package/lib/getTransactionStatus.unit.test.d.ts +2 -0
  100. package/lib/getTransactionStatus.unit.test.d.ts.map +1 -0
  101. package/lib/getTransactionStatus.unit.test.js +54 -0
  102. package/lib/getTransactionStatus.unit.test.js.map +1 -0
  103. package/lib/hw-getAddress.d.ts +6 -0
  104. package/lib/hw-getAddress.d.ts.map +1 -0
  105. package/lib/hw-getAddress.js +37 -0
  106. package/lib/hw-getAddress.js.map +1 -0
  107. package/lib/logic.d.ts +88 -0
  108. package/lib/logic.d.ts.map +1 -0
  109. package/lib/logic.js +264 -0
  110. package/lib/logic.js.map +1 -0
  111. package/lib/logic.unit.test.d.ts +2 -0
  112. package/lib/logic.unit.test.d.ts.map +1 -0
  113. package/lib/logic.unit.test.js +40 -0
  114. package/lib/logic.unit.test.js.map +1 -0
  115. package/lib/networks.d.ts +3 -0
  116. package/lib/networks.d.ts.map +1 -0
  117. package/lib/networks.js +36 -0
  118. package/lib/networks.js.map +1 -0
  119. package/lib/postSyncPatch.d.ts +6 -0
  120. package/lib/postSyncPatch.d.ts.map +1 -0
  121. package/lib/postSyncPatch.js +35 -0
  122. package/lib/postSyncPatch.js.map +1 -0
  123. package/lib/prepareTransaction.d.ts +10 -0
  124. package/lib/prepareTransaction.d.ts.map +1 -0
  125. package/lib/prepareTransaction.js +44 -0
  126. package/lib/prepareTransaction.js.map +1 -0
  127. package/lib/serialization.d.ts +7 -0
  128. package/lib/serialization.d.ts.map +1 -0
  129. package/lib/serialization.js +146 -0
  130. package/lib/serialization.js.map +1 -0
  131. package/lib/signOperation.d.ts +9 -0
  132. package/lib/signOperation.d.ts.map +1 -0
  133. package/lib/signOperation.js +71 -0
  134. package/lib/signOperation.js.map +1 -0
  135. package/lib/signer.d.ts +92 -0
  136. package/lib/signer.d.ts.map +1 -0
  137. package/lib/signer.js +3 -0
  138. package/lib/signer.js.map +1 -0
  139. package/lib/specs.d.ts +7 -0
  140. package/lib/specs.d.ts.map +1 -0
  141. package/lib/specs.js +218 -0
  142. package/lib/specs.js.map +1 -0
  143. package/lib/speculos-deviceActions.d.ts +4 -0
  144. package/lib/speculos-deviceActions.d.ts.map +1 -0
  145. package/lib/speculos-deviceActions.js +128 -0
  146. package/lib/speculos-deviceActions.js.map +1 -0
  147. package/lib/synchronisation.d.ts +6 -0
  148. package/lib/synchronisation.d.ts.map +1 -0
  149. package/lib/synchronisation.js +237 -0
  150. package/lib/synchronisation.js.map +1 -0
  151. package/lib/synchronisation.unit.test.d.ts +2 -0
  152. package/lib/synchronisation.unit.test.d.ts.map +1 -0
  153. package/lib/synchronisation.unit.test.js +129 -0
  154. package/lib/synchronisation.unit.test.js.map +1 -0
  155. package/lib/transaction.d.ts +15 -0
  156. package/lib/transaction.d.ts.map +1 -0
  157. package/lib/transaction.js +43 -0
  158. package/lib/transaction.js.map +1 -0
  159. package/lib/types.d.ts +188 -0
  160. package/lib/types.d.ts.map +1 -0
  161. package/lib/types.js +18 -0
  162. package/lib/types.js.map +1 -0
  163. package/lib/typhonSerializer.d.ts +17 -0
  164. package/lib/typhonSerializer.d.ts.map +1 -0
  165. package/lib/typhonSerializer.js +213 -0
  166. package/lib/typhonSerializer.js.map +1 -0
  167. package/lib/utils.d.ts +2 -0
  168. package/lib/utils.d.ts.map +1 -0
  169. package/lib/utils.js +8 -0
  170. package/lib/utils.js.map +1 -0
  171. package/lib-es/account.d.ts +7 -0
  172. package/lib-es/account.d.ts.map +1 -0
  173. package/lib-es/account.js +34 -0
  174. package/lib-es/account.js.map +1 -0
  175. package/lib-es/address.unit.test.d.ts +2 -0
  176. package/lib-es/address.unit.test.d.ts.map +1 -0
  177. package/lib-es/address.unit.test.js +19 -0
  178. package/lib-es/address.unit.test.js.map +1 -0
  179. package/lib-es/api/api-types.d.ts +106 -0
  180. package/lib-es/api/api-types.d.ts.map +1 -0
  181. package/lib-es/api/api-types.js +6 -0
  182. package/lib-es/api/api-types.js.map +1 -0
  183. package/lib-es/api/getDelegationInfo.d.ts +4 -0
  184. package/lib-es/api/getDelegationInfo.d.ts.map +1 -0
  185. package/lib-es/api/getDelegationInfo.js +41 -0
  186. package/lib-es/api/getDelegationInfo.js.map +1 -0
  187. package/lib-es/api/getNetworkInfo.d.ts +5 -0
  188. package/lib-es/api/getNetworkInfo.d.ts.map +1 -0
  189. package/lib-es/api/getNetworkInfo.js +39 -0
  190. package/lib-es/api/getNetworkInfo.js.map +1 -0
  191. package/lib-es/api/getPools.d.ts +5 -0
  192. package/lib-es/api/getPools.d.ts.map +1 -0
  193. package/lib-es/api/getPools.js +37 -0
  194. package/lib-es/api/getPools.js.map +1 -0
  195. package/lib-es/api/getTransactions.d.ts +10 -0
  196. package/lib-es/api/getTransactions.d.ts.map +1 -0
  197. package/lib-es/api/getTransactions.js +132 -0
  198. package/lib-es/api/getTransactions.js.map +1 -0
  199. package/lib-es/api/submitTransaction.d.ts +7 -0
  200. package/lib-es/api/submitTransaction.d.ts.map +1 -0
  201. package/lib-es/api/submitTransaction.js +27 -0
  202. package/lib-es/api/submitTransaction.js.map +1 -0
  203. package/lib-es/bridge/index.d.ts +11 -0
  204. package/lib-es/bridge/index.d.ts.map +1 -0
  205. package/lib-es/bridge/index.js +61 -0
  206. package/lib-es/bridge/index.js.map +1 -0
  207. package/lib-es/bridge.integration.test.d.ts +4 -0
  208. package/lib-es/bridge.integration.test.d.ts.map +1 -0
  209. package/lib-es/bridge.integration.test.js +107 -0
  210. package/lib-es/bridge.integration.test.js.map +1 -0
  211. package/lib-es/broadcast.d.ts +8 -0
  212. package/lib-es/broadcast.d.ts.map +1 -0
  213. package/lib-es/broadcast.js +24 -0
  214. package/lib-es/broadcast.js.map +1 -0
  215. package/lib-es/buildOptimisticOperation.d.ts +4 -0
  216. package/lib-es/buildOptimisticOperation.d.ts.map +1 -0
  217. package/lib-es/buildOptimisticOperation.js +118 -0
  218. package/lib-es/buildOptimisticOperation.js.map +1 -0
  219. package/lib-es/buildSubAccounts.d.ts +26 -0
  220. package/lib-es/buildSubAccounts.d.ts.map +1 -0
  221. package/lib-es/buildSubAccounts.js +114 -0
  222. package/lib-es/buildSubAccounts.js.map +1 -0
  223. package/lib-es/buildTransaction.d.ts +11 -0
  224. package/lib-es/buildTransaction.d.ts.map +1 -0
  225. package/lib-es/buildTransaction.js +335 -0
  226. package/lib-es/buildTransaction.js.map +1 -0
  227. package/lib-es/cli-transaction.d.ts +18 -0
  228. package/lib-es/cli-transaction.d.ts.map +1 -0
  229. package/lib-es/cli-transaction.js +60 -0
  230. package/lib-es/cli-transaction.js.map +1 -0
  231. package/lib-es/constants.d.ts +8 -0
  232. package/lib-es/constants.d.ts.map +1 -0
  233. package/lib-es/constants.js +9 -0
  234. package/lib-es/constants.js.map +1 -0
  235. package/lib-es/createTransaction.d.ts +9 -0
  236. package/lib-es/createTransaction.d.ts.map +1 -0
  237. package/lib-es/createTransaction.js +16 -0
  238. package/lib-es/createTransaction.js.map +1 -0
  239. package/lib-es/datasets/rawAccount.1.d.ts +3 -0
  240. package/lib-es/datasets/rawAccount.1.d.ts.map +1 -0
  241. package/lib-es/datasets/rawAccount.1.js +17 -0
  242. package/lib-es/datasets/rawAccount.1.js.map +1 -0
  243. package/lib-es/datasets/scanAccounts.d.ts +5 -0
  244. package/lib-es/datasets/scanAccounts.d.ts.map +1 -0
  245. package/lib-es/datasets/scanAccounts.js +24 -0
  246. package/lib-es/datasets/scanAccounts.js.map +1 -0
  247. package/lib-es/deviceTransactionConfig.d.ts +11 -0
  248. package/lib-es/deviceTransactionConfig.d.ts.map +1 -0
  249. package/lib-es/deviceTransactionConfig.js +101 -0
  250. package/lib-es/deviceTransactionConfig.js.map +1 -0
  251. package/lib-es/errors.d.ts +22 -0
  252. package/lib-es/errors.d.ts.map +1 -0
  253. package/lib-es/errors.js +15 -0
  254. package/lib-es/errors.js.map +1 -0
  255. package/lib-es/estimateMaxSpendable.d.ts +9 -0
  256. package/lib-es/estimateMaxSpendable.d.ts.map +1 -0
  257. package/lib-es/estimateMaxSpendable.js +49 -0
  258. package/lib-es/estimateMaxSpendable.js.map +1 -0
  259. package/lib-es/getTransactionStatus.d.ts +4 -0
  260. package/lib-es/getTransactionStatus.d.ts.map +1 -0
  261. package/lib-es/getTransactionStatus.js +210 -0
  262. package/lib-es/getTransactionStatus.js.map +1 -0
  263. package/lib-es/getTransactionStatus.unit.test.d.ts +2 -0
  264. package/lib-es/getTransactionStatus.unit.test.d.ts.map +1 -0
  265. package/lib-es/getTransactionStatus.unit.test.js +49 -0
  266. package/lib-es/getTransactionStatus.unit.test.js.map +1 -0
  267. package/lib-es/hw-getAddress.d.ts +6 -0
  268. package/lib-es/hw-getAddress.d.ts.map +1 -0
  269. package/lib-es/hw-getAddress.js +35 -0
  270. package/lib-es/hw-getAddress.js.map +1 -0
  271. package/lib-es/logic.d.ts +88 -0
  272. package/lib-es/logic.d.ts.map +1 -0
  273. package/lib-es/logic.js +236 -0
  274. package/lib-es/logic.js.map +1 -0
  275. package/lib-es/logic.unit.test.d.ts +2 -0
  276. package/lib-es/logic.unit.test.d.ts.map +1 -0
  277. package/lib-es/logic.unit.test.js +35 -0
  278. package/lib-es/logic.unit.test.js.map +1 -0
  279. package/lib-es/networks.d.ts +3 -0
  280. package/lib-es/networks.d.ts.map +1 -0
  281. package/lib-es/networks.js +32 -0
  282. package/lib-es/networks.js.map +1 -0
  283. package/lib-es/postSyncPatch.d.ts +6 -0
  284. package/lib-es/postSyncPatch.d.ts.map +1 -0
  285. package/lib-es/postSyncPatch.js +31 -0
  286. package/lib-es/postSyncPatch.js.map +1 -0
  287. package/lib-es/prepareTransaction.d.ts +10 -0
  288. package/lib-es/prepareTransaction.d.ts.map +1 -0
  289. package/lib-es/prepareTransaction.js +40 -0
  290. package/lib-es/prepareTransaction.js.map +1 -0
  291. package/lib-es/serialization.d.ts +7 -0
  292. package/lib-es/serialization.d.ts.map +1 -0
  293. package/lib-es/serialization.js +139 -0
  294. package/lib-es/serialization.js.map +1 -0
  295. package/lib-es/signOperation.d.ts +9 -0
  296. package/lib-es/signOperation.d.ts.map +1 -0
  297. package/lib-es/signOperation.js +64 -0
  298. package/lib-es/signOperation.js.map +1 -0
  299. package/lib-es/signer.d.ts +92 -0
  300. package/lib-es/signer.d.ts.map +1 -0
  301. package/lib-es/signer.js +2 -0
  302. package/lib-es/signer.js.map +1 -0
  303. package/lib-es/specs.d.ts +7 -0
  304. package/lib-es/specs.d.ts.map +1 -0
  305. package/lib-es/specs.js +213 -0
  306. package/lib-es/specs.js.map +1 -0
  307. package/lib-es/speculos-deviceActions.d.ts +4 -0
  308. package/lib-es/speculos-deviceActions.d.ts.map +1 -0
  309. package/lib-es/speculos-deviceActions.js +125 -0
  310. package/lib-es/speculos-deviceActions.js.map +1 -0
  311. package/lib-es/synchronisation.d.ts +6 -0
  312. package/lib-es/synchronisation.d.ts.map +1 -0
  313. package/lib-es/synchronisation.js +230 -0
  314. package/lib-es/synchronisation.js.map +1 -0
  315. package/lib-es/synchronisation.unit.test.d.ts +2 -0
  316. package/lib-es/synchronisation.unit.test.d.ts.map +1 -0
  317. package/lib-es/synchronisation.unit.test.js +124 -0
  318. package/lib-es/synchronisation.unit.test.js.map +1 -0
  319. package/lib-es/transaction.d.ts +15 -0
  320. package/lib-es/transaction.d.ts.map +1 -0
  321. package/lib-es/transaction.js +37 -0
  322. package/lib-es/transaction.js.map +1 -0
  323. package/lib-es/types.d.ts +188 -0
  324. package/lib-es/types.d.ts.map +1 -0
  325. package/lib-es/types.js +15 -0
  326. package/lib-es/types.js.map +1 -0
  327. package/lib-es/typhonSerializer.d.ts +17 -0
  328. package/lib-es/typhonSerializer.d.ts.map +1 -0
  329. package/lib-es/typhonSerializer.js +207 -0
  330. package/lib-es/typhonSerializer.js.map +1 -0
  331. package/lib-es/utils.d.ts +2 -0
  332. package/lib-es/utils.d.ts.map +1 -0
  333. package/lib-es/utils.js +5 -0
  334. package/lib-es/utils.js.map +1 -0
  335. package/package.json +91 -0
  336. package/src/account.ts +39 -0
  337. package/src/address.unit.test.ts +32 -0
  338. package/src/api/api-types.ts +115 -0
  339. package/src/api/getDelegationInfo.ts +39 -0
  340. package/src/api/getNetworkInfo.ts +34 -0
  341. package/src/api/getPools.ts +35 -0
  342. package/src/api/getTransactions.ts +218 -0
  343. package/src/api/submitTransaction.ts +24 -0
  344. package/src/bridge/index.ts +69 -0
  345. package/src/bridge.integration.test.ts +113 -0
  346. package/src/broadcast.ts +21 -0
  347. package/src/buildOptimisticOperation.ts +181 -0
  348. package/src/buildSubAccounts.ts +170 -0
  349. package/src/buildTransaction.ts +435 -0
  350. package/src/cli-transaction.ts +82 -0
  351. package/src/constants.ts +10 -0
  352. package/src/createTransaction.ts +18 -0
  353. package/src/datasets/rawAccount.1.ts +19 -0
  354. package/src/datasets/scanAccounts.ts +23 -0
  355. package/src/deviceTransactionConfig.ts +128 -0
  356. package/src/errors.ts +18 -0
  357. package/src/estimateMaxSpendable.ts +61 -0
  358. package/src/getTransactionStatus.ts +251 -0
  359. package/src/getTransactionStatus.unit.test.ts +45 -0
  360. package/src/hw-getAddress.ts +37 -0
  361. package/src/logic.ts +330 -0
  362. package/src/logic.unit.test.ts +39 -0
  363. package/src/networks.ts +33 -0
  364. package/src/postSyncPatch.ts +42 -0
  365. package/src/prepareTransaction.ts +41 -0
  366. package/src/serialization.ts +219 -0
  367. package/src/signOperation.ts +82 -0
  368. package/src/signer.ts +98 -0
  369. package/src/specs.ts +253 -0
  370. package/src/speculos-deviceActions.ts +132 -0
  371. package/src/synchronisation.ts +347 -0
  372. package/src/synchronisation.unit.test.ts +137 -0
  373. package/src/transaction.ts +66 -0
  374. package/src/types.ts +227 -0
  375. package/src/typhonSerializer.ts +259 -0
  376. package/src/utils.ts +4 -0
  377. package/tsconfig.json +12 -0
@@ -0,0 +1,435 @@
1
+ import {
2
+ Transaction as TyphonTransaction,
3
+ types as TyphonTypes,
4
+ utils as TyphonUtils,
5
+ } from "@stricahq/typhonjs";
6
+ import BigNumber from "bignumber.js";
7
+ import type { TokenAccount } from "@ledgerhq/types-live";
8
+ import { RewardAddress } from "@stricahq/typhonjs/dist/address";
9
+ import { getAccountStakeCredential, getBaseAddress, getTTL, mergeTokens, isTestnet } from "./logic";
10
+ import { decodeTokenAssetId, decodeTokenCurrencyId, getTokenAssetId } from "./buildSubAccounts";
11
+ import { getNetworkParameters } from "./networks";
12
+ import {
13
+ CardanoAccount,
14
+ CardanoOutput,
15
+ CardanoResources,
16
+ PaymentCredential,
17
+ Token,
18
+ Transaction,
19
+ } from "./types";
20
+
21
+ function getTyphonInputFromUtxo(utxo: CardanoOutput): TyphonTypes.Input {
22
+ const address = TyphonUtils.getAddressFromHex(utxo.address) as TyphonTypes.ShelleyAddress;
23
+ if (address.paymentCredential.type === TyphonTypes.HashType.ADDRESS) {
24
+ address.paymentCredential.bipPath = utxo.paymentCredential.path;
25
+ }
26
+
27
+ return {
28
+ txId: utxo.hash,
29
+ index: utxo.index,
30
+ amount: new BigNumber(utxo.amount),
31
+ tokens: utxo.tokens,
32
+ address: address,
33
+ };
34
+ }
35
+
36
+ function getRewardWithdrawalCertificate(account: CardanoAccount): TyphonTypes.Withdrawal | null {
37
+ if (!account.cardanoResources.delegation?.rewards.gt(0)) {
38
+ return null;
39
+ }
40
+
41
+ const stakeCredential = getAccountStakeCredential(account.xpub as string, account.index);
42
+ const stakeKeyHashCredential: TyphonTypes.HashCredential = {
43
+ hash: stakeCredential.key,
44
+ type: TyphonTypes.HashType.ADDRESS,
45
+ bipPath: stakeCredential.path,
46
+ };
47
+
48
+ const networkId = isTestnet(account.currency)
49
+ ? TyphonTypes.NetworkId.TESTNET
50
+ : TyphonTypes.NetworkId.MAINNET;
51
+ const rewardAddress = new RewardAddress(networkId, stakeKeyHashCredential);
52
+ const rewardsWithdrawalCertificate: TyphonTypes.Withdrawal = {
53
+ rewardAccount: rewardAddress,
54
+ amount: account.cardanoResources.delegation.rewards,
55
+ };
56
+
57
+ return rewardsWithdrawalCertificate;
58
+ }
59
+
60
+ const buildSendTokenTransaction = async ({
61
+ account,
62
+ transaction,
63
+ tokenAccount,
64
+ typhonTx,
65
+ receiverAddress,
66
+ changeAddress,
67
+ }: {
68
+ account: CardanoAccount;
69
+ transaction: Transaction;
70
+ tokenAccount: TokenAccount;
71
+ typhonTx: TyphonTransaction;
72
+ receiverAddress: TyphonTypes.CardanoAddress;
73
+ changeAddress: TyphonTypes.CardanoAddress;
74
+ }): Promise<TyphonTransaction> => {
75
+ const cardanoResources = account.cardanoResources as CardanoResources;
76
+
77
+ const { assetId } = decodeTokenCurrencyId(tokenAccount.token.id);
78
+ const { policyId, assetName } = decodeTokenAssetId(assetId);
79
+ const transactionAmount = transaction.useAllAmount ? tokenAccount.balance : transaction.amount;
80
+
81
+ const tokensToSend = [
82
+ {
83
+ policyId,
84
+ assetName,
85
+ amount: transactionAmount,
86
+ },
87
+ ];
88
+ const tokenUtxos: Array<CardanoOutput> = [];
89
+ const otherUtxos: Array<CardanoOutput> = [];
90
+
91
+ cardanoResources.utxos.forEach(u => {
92
+ if (u.tokens.some(t => getTokenAssetId(t) === assetId)) {
93
+ tokenUtxos.push(u);
94
+ } else {
95
+ otherUtxos.push(u);
96
+ }
97
+ });
98
+ const sortedTokenUtxo = tokenUtxos.sort((a, b) => {
99
+ const sendingTokenA = a.tokens.find(t => getTokenAssetId(t) === assetId) as Token;
100
+ const sendingTokenB = b.tokens.find(t => getTokenAssetId(t) === assetId) as Token;
101
+ const diff = sendingTokenB.amount.minus(sendingTokenA.amount);
102
+ return diff.eq(0) ? 0 : diff.lt(0) ? -1 : 1;
103
+ });
104
+ const sortedOtherUtxos = otherUtxos.sort((a, b) => {
105
+ const diff = b.amount.minus(a.amount);
106
+ return diff.eq(0) ? 0 : diff.lt(0) ? -1 : 1;
107
+ });
108
+
109
+ const totalAddedTokenAmount = new BigNumber(0);
110
+ const requiredMinAdaForTokens = TyphonUtils.calculateMinUtxoAmount(
111
+ tokensToSend,
112
+ new BigNumber(cardanoResources.protocolParams.lovelacePerUtxoWord),
113
+ );
114
+ // Add enough utxo to cover token amount
115
+ for (let i = 0; i < sortedTokenUtxo.length; i++) {
116
+ const u = sortedTokenUtxo[i];
117
+ const sendingToken = u.tokens.find(t => getTokenAssetId(t) === assetId) as Token;
118
+ typhonTx.addInput(getTyphonInputFromUtxo(u));
119
+ totalAddedTokenAmount.plus(sendingToken.amount);
120
+ if (totalAddedTokenAmount.gte(transactionAmount)) break;
121
+ }
122
+
123
+ const requiredInputAmount = requiredMinAdaForTokens.plus(10e6);
124
+ // Add enough utxos to cover the transaction fees
125
+ for (let i = 0; i < sortedOtherUtxos.length; i++) {
126
+ const u = sortedOtherUtxos[i];
127
+ if (typhonTx.getInputAmount().ada.gte(requiredInputAmount)) {
128
+ break;
129
+ }
130
+ typhonTx.addInput(getTyphonInputFromUtxo(u));
131
+ }
132
+
133
+ const rewardsWithdrawalCertificate = getRewardWithdrawalCertificate(account);
134
+ if (rewardsWithdrawalCertificate) typhonTx.addWithdrawal(rewardsWithdrawalCertificate);
135
+
136
+ typhonTx.addOutput({
137
+ address: receiverAddress,
138
+ amount: requiredMinAdaForTokens,
139
+ tokens: tokensToSend,
140
+ });
141
+
142
+ return typhonTx.prepareTransaction({
143
+ inputs: [],
144
+ changeAddress,
145
+ });
146
+ };
147
+
148
+ const buildSendAdaTransaction = async ({
149
+ account,
150
+ transaction,
151
+ typhonTx,
152
+ receiverAddress,
153
+ changeAddress,
154
+ }: {
155
+ account: CardanoAccount;
156
+ transaction: Transaction;
157
+ typhonTx: TyphonTransaction;
158
+ receiverAddress: TyphonTypes.CardanoAddress;
159
+ changeAddress: TyphonTypes.CardanoAddress;
160
+ }): Promise<TyphonTransaction> => {
161
+ const cardanoResources = account.cardanoResources as CardanoResources;
162
+ const protocolParams = cardanoResources.protocolParams;
163
+
164
+ if (transaction.useAllAmount) {
165
+ // add all utxo as input
166
+ cardanoResources.utxos.forEach(u => typhonTx.addInput(getTyphonInputFromUtxo(u)));
167
+
168
+ const tokenBalance = mergeTokens(cardanoResources.utxos.map(u => u.tokens).flat());
169
+
170
+ // if account holds any tokens then add it to changeAddress,
171
+ // with minimum required ADA to spend those tokens
172
+ if (tokenBalance.length) {
173
+ const minAmountToSpendTokens = TyphonUtils.calculateMinUtxoAmount(
174
+ tokenBalance,
175
+ new BigNumber(protocolParams.lovelacePerUtxoWord),
176
+ false,
177
+ );
178
+ typhonTx.addOutput({
179
+ address: changeAddress,
180
+ amount: minAmountToSpendTokens,
181
+ tokens: tokenBalance,
182
+ });
183
+ }
184
+
185
+ const rewardsWithdrawalCertificate = getRewardWithdrawalCertificate(account);
186
+ if (rewardsWithdrawalCertificate) typhonTx.addWithdrawal(rewardsWithdrawalCertificate);
187
+
188
+ return typhonTx.prepareTransaction({
189
+ inputs: [],
190
+ changeAddress: receiverAddress,
191
+ });
192
+ }
193
+
194
+ // sorting utxo from higher to lower ADA value
195
+ // to minimize the number of utxo use in transaction
196
+ const sortedUtxos = cardanoResources.utxos.sort((a, b) => {
197
+ const diff = b.amount.minus(a.amount);
198
+ return diff.eq(0) ? 0 : diff.lt(0) ? -1 : 1;
199
+ });
200
+
201
+ const transactionInputs: Array<TyphonTypes.Input> = [];
202
+ const usedUtxoAdaAmount = new BigNumber(0);
203
+ // Add 10 ADA as buffer for utxo selection to cover the transaction fees.
204
+ const requiredInputAmount = transaction.amount.plus(10e6);
205
+ for (let i = 0; i < sortedUtxos.length && usedUtxoAdaAmount.lte(requiredInputAmount); i++) {
206
+ const utxo = sortedUtxos[i];
207
+ const transactionInput = getTyphonInputFromUtxo(utxo);
208
+ transactionInputs.push(transactionInput);
209
+ usedUtxoAdaAmount.plus(transactionInput.amount);
210
+ }
211
+
212
+ const rewardsWithdrawalCertificate = getRewardWithdrawalCertificate(account);
213
+ if (rewardsWithdrawalCertificate) typhonTx.addWithdrawal(rewardsWithdrawalCertificate);
214
+
215
+ typhonTx.addOutput({
216
+ address: receiverAddress,
217
+ amount: transaction.amount,
218
+ tokens: [],
219
+ });
220
+
221
+ return typhonTx.prepareTransaction({
222
+ inputs: transactionInputs,
223
+ changeAddress,
224
+ });
225
+ };
226
+
227
+ const buildDelegateTransaction = async ({
228
+ account,
229
+ transaction,
230
+ typhonTx,
231
+ changeAddress,
232
+ }: {
233
+ account: CardanoAccount;
234
+ transaction: Transaction;
235
+ typhonTx: TyphonTransaction;
236
+ changeAddress: TyphonTypes.CardanoAddress;
237
+ }): Promise<TyphonTransaction> => {
238
+ const cardanoResources = account.cardanoResources as CardanoResources;
239
+
240
+ const stakeCredential = getAccountStakeCredential(account.xpub as string, account.index);
241
+ const stakeKeyHashCredential: TyphonTypes.HashCredential = {
242
+ hash: stakeCredential.key,
243
+ type: TyphonTypes.HashType.ADDRESS,
244
+ bipPath: stakeCredential.path,
245
+ };
246
+
247
+ if (!cardanoResources.delegation || !cardanoResources.delegation.status) {
248
+ const stakeRegistrationCert: TyphonTypes.StakeRegistrationCertificate = {
249
+ certType: TyphonTypes.CertificateType.STAKE_REGISTRATION,
250
+ stakeCredential: stakeKeyHashCredential,
251
+ };
252
+ typhonTx.addCertificate(stakeRegistrationCert);
253
+ }
254
+
255
+ const delegationCert: TyphonTypes.StakeDelegationCertificate = {
256
+ certType: TyphonTypes.CertificateType.STAKE_DELEGATION,
257
+ stakeCredential: stakeKeyHashCredential,
258
+ poolHash: transaction.poolId as string,
259
+ };
260
+ typhonTx.addCertificate(delegationCert);
261
+
262
+ // sorting utxo from higher to lower ADA value
263
+ // to minimize the number of utxo use in transaction
264
+ const sortedUtxos = cardanoResources.utxos.sort((a, b) => {
265
+ const diff = b.amount.minus(a.amount);
266
+ return diff.eq(0) ? 0 : diff.lt(0) ? -1 : 1;
267
+ });
268
+
269
+ const transactionInputs: Array<TyphonTypes.Input> = [];
270
+ const usedUtxoAdaAmount = new BigNumber(0);
271
+ // Add 10 ADA as buffer for utxo selection to cover the transaction fees.
272
+ const requiredInputAmount = transaction.amount.plus(10e6);
273
+ for (let i = 0; i < sortedUtxos.length && usedUtxoAdaAmount.lte(requiredInputAmount); i++) {
274
+ const utxo = sortedUtxos[i];
275
+ const transactionInput = getTyphonInputFromUtxo(utxo);
276
+ transactionInputs.push(transactionInput);
277
+ usedUtxoAdaAmount.plus(transactionInput.amount);
278
+ }
279
+
280
+ const rewardsWithdrawalCertificate = getRewardWithdrawalCertificate(account);
281
+ if (rewardsWithdrawalCertificate) typhonTx.addWithdrawal(rewardsWithdrawalCertificate);
282
+
283
+ return typhonTx.prepareTransaction({
284
+ inputs: transactionInputs,
285
+ changeAddress,
286
+ });
287
+ };
288
+
289
+ const buildUndelegateTransaction = async ({
290
+ account,
291
+ transaction,
292
+ typhonTx,
293
+ changeAddress,
294
+ }: {
295
+ account: CardanoAccount;
296
+ transaction: Transaction;
297
+ typhonTx: TyphonTransaction;
298
+ changeAddress: TyphonTypes.CardanoAddress;
299
+ }): Promise<TyphonTransaction> => {
300
+ const cardanoResources = account.cardanoResources as CardanoResources;
301
+
302
+ const stakeCredential = getAccountStakeCredential(account.xpub as string, account.index);
303
+ const stakeKeyHashCredential: TyphonTypes.HashCredential = {
304
+ hash: stakeCredential.key,
305
+ type: TyphonTypes.HashType.ADDRESS,
306
+ bipPath: stakeCredential.path,
307
+ };
308
+
309
+ if (!cardanoResources.delegation || !cardanoResources.delegation.status) {
310
+ throw new Error("StakeKey is not registered");
311
+ }
312
+
313
+ const rewardsWithdrawalCertificate = getRewardWithdrawalCertificate(account);
314
+ if (rewardsWithdrawalCertificate) typhonTx.addWithdrawal(rewardsWithdrawalCertificate);
315
+
316
+ const stakeKeyDeRegistrationCertificate: TyphonTypes.StakeDeRegistrationCertificate = {
317
+ certType: TyphonTypes.CertificateType.STAKE_DE_REGISTRATION,
318
+ stakeCredential: stakeKeyHashCredential,
319
+ };
320
+ typhonTx.addCertificate(stakeKeyDeRegistrationCertificate);
321
+
322
+ // sorting utxo from higher to lower ADA value
323
+ // to minimize the number of utxo use in transaction
324
+ const sortedUtxos = cardanoResources.utxos.sort((a, b) => {
325
+ const diff = b.amount.minus(a.amount);
326
+ return diff.eq(0) ? 0 : diff.lt(0) ? -1 : 1;
327
+ });
328
+
329
+ const transactionInputs: Array<TyphonTypes.Input> = [];
330
+ const usedUtxoAdaAmount = new BigNumber(0);
331
+ // Add 10 ADA as buffer for utxo selection to cover the transaction fees.
332
+ const requiredInputAmount = transaction.amount.plus(10e6);
333
+ for (let i = 0; i < sortedUtxos.length && usedUtxoAdaAmount.lte(requiredInputAmount); i++) {
334
+ const utxo = sortedUtxos[i];
335
+ const transactionInput = getTyphonInputFromUtxo(utxo);
336
+ transactionInputs.push(transactionInput);
337
+ usedUtxoAdaAmount.plus(transactionInput.amount);
338
+ }
339
+
340
+ return typhonTx.prepareTransaction({
341
+ inputs: transactionInputs,
342
+ changeAddress,
343
+ });
344
+ };
345
+
346
+ /**
347
+ *
348
+ * @param {CardanoAccount} account
349
+ * @param {Transaction} transaction
350
+ *
351
+ * @returns {TyphonTransaction}
352
+ */
353
+ export const buildTransaction = async (
354
+ account: CardanoAccount,
355
+ transaction: Transaction,
356
+ ): Promise<TyphonTransaction> => {
357
+ const cardanoResources = account.cardanoResources as CardanoResources;
358
+ const protocolParams = cardanoResources.protocolParams;
359
+
360
+ const typhonTx = new TyphonTransaction({
361
+ protocolParams: {
362
+ minFeeA: new BigNumber(protocolParams.minFeeA),
363
+ minFeeB: new BigNumber(protocolParams.minFeeB),
364
+ stakeKeyDeposit: new BigNumber(protocolParams.stakeKeyDeposit),
365
+ lovelacePerUtxoWord: new BigNumber(protocolParams.lovelacePerUtxoWord),
366
+ collateralPercent: new BigNumber(protocolParams.collateralPercent),
367
+ priceSteps: new BigNumber(protocolParams.priceSteps),
368
+ priceMem: new BigNumber(protocolParams.priceMem),
369
+ languageView: protocolParams.languageView,
370
+ },
371
+ });
372
+ const ttl = getTTL(account.currency.id);
373
+ typhonTx.setTTL(ttl);
374
+
375
+ const metadata: Array<TyphonTypes.Metadata> = [];
376
+ if (transaction.memo) {
377
+ metadata.push({
378
+ label: 674,
379
+ data: new Map([["msg", [transaction.memo]]]),
380
+ });
381
+ }
382
+ if (metadata.length) {
383
+ typhonTx.setAuxiliaryData({ metadata });
384
+ }
385
+
386
+ const networkParams = getNetworkParameters(account.currency.id);
387
+ const unusedInternalCred = cardanoResources.internalCredentials.find(
388
+ cred => !cred.isUsed,
389
+ ) as PaymentCredential;
390
+
391
+ const changeAddress = getBaseAddress({
392
+ networkId: networkParams.networkId,
393
+ paymentCred: unusedInternalCred,
394
+ stakeCred: getAccountStakeCredential(account.xpub as string, account.index),
395
+ });
396
+
397
+ if (transaction.mode === "send") {
398
+ const receiverAddress = TyphonUtils.getAddressFromBech32(transaction.recipient);
399
+ if (transaction.subAccountId) {
400
+ // Token Transaction
401
+ const tokenAccount = account.subAccounts
402
+ ? account.subAccounts.find(a => {
403
+ return a.id === transaction.subAccountId;
404
+ })
405
+ : undefined;
406
+
407
+ if (!tokenAccount || tokenAccount.type !== "TokenAccount") {
408
+ throw new Error("TokenAccount not found");
409
+ }
410
+
411
+ return buildSendTokenTransaction({
412
+ account,
413
+ transaction,
414
+ tokenAccount,
415
+ typhonTx,
416
+ receiverAddress,
417
+ changeAddress,
418
+ });
419
+ }
420
+ // Normal ADA Transaction
421
+ return buildSendAdaTransaction({
422
+ account,
423
+ transaction,
424
+ typhonTx,
425
+ receiverAddress,
426
+ changeAddress,
427
+ });
428
+ } else if (transaction.mode === "delegate") {
429
+ return buildDelegateTransaction({ account, transaction, typhonTx, changeAddress });
430
+ } else if (transaction.mode === "undelegate") {
431
+ return buildUndelegateTransaction({ account, transaction, typhonTx, changeAddress });
432
+ } else {
433
+ throw new Error("Invalid transaction mode");
434
+ }
435
+ };
@@ -0,0 +1,82 @@
1
+ import { Account, AccountLike, TokenAccount } from "@ledgerhq/types-live";
2
+ import invariant from "invariant";
3
+ import flatMap from "lodash/flatMap";
4
+ import { getAccountCurrency } from "@ledgerhq/coin-framework/account/index";
5
+ import { CardanoAccount, Transaction } from "./types";
6
+
7
+ const options = [
8
+ {
9
+ name: "mode",
10
+ type: String,
11
+ desc: "mode of transaction: send, delegate, undelegate",
12
+ },
13
+ {
14
+ name: "token",
15
+ type: String,
16
+ desc: "uses subAccount(TokenAccount) of the account",
17
+ },
18
+ {
19
+ name: "poolId",
20
+ type: String,
21
+ desc: "Cardano stake pool id to delegate",
22
+ },
23
+ ];
24
+
25
+ function inferAccounts(account: Account, opts: Record<string, any>): Account[] | TokenAccount[] {
26
+ invariant(account.currency.family === "cardano", "cardano family");
27
+
28
+ if (!opts.token) {
29
+ const accounts: Account[] = [account];
30
+ return accounts;
31
+ }
32
+
33
+ return opts.token.map((token: any) => {
34
+ const subAccounts = account.subAccounts || [];
35
+
36
+ const subAccount = subAccounts.find(a => {
37
+ const currency = getAccountCurrency(a);
38
+ return token.toLowerCase() === currency.id.toLowerCase();
39
+ });
40
+
41
+ if (!subAccount) {
42
+ throw new Error(
43
+ "token account '" +
44
+ token +
45
+ "' not found. Available: " +
46
+ subAccounts.map(t => t.id).join("\n"),
47
+ );
48
+ }
49
+
50
+ return subAccount;
51
+ });
52
+ }
53
+
54
+ function inferTransactions(
55
+ transactions: Array<{ account: AccountLike; transaction: Transaction }>,
56
+ opts: Record<string, any>,
57
+ ): Transaction[] {
58
+ return flatMap(transactions, ({ transaction, account }) => {
59
+ if (transaction.family !== "cardano") {
60
+ throw new Error("transaction is not of type cardano");
61
+ }
62
+
63
+ if (account.type === "Account" && !(account as CardanoAccount).cardanoResources) {
64
+ throw new Error("unactivated account");
65
+ }
66
+
67
+ return {
68
+ ...transaction,
69
+ mode: opts.mode || "send",
70
+ subAccountId: account.type === "TokenAccount" ? account.id : undefined,
71
+ poolId: opts.poolId || "",
72
+ };
73
+ });
74
+ }
75
+
76
+ export default function makeCliTools() {
77
+ return {
78
+ options,
79
+ inferAccounts,
80
+ inferTransactions,
81
+ };
82
+ }
@@ -0,0 +1,10 @@
1
+ import { getEnv } from "@ledgerhq/live-env";
2
+
3
+ export const STAKING_ADDRESS_INDEX = 0;
4
+ export const TTL_GAP = 7200;
5
+ export const CARDANO_PURPOSE = 1852;
6
+ export const CARDANO_COIN_TYPE = 1815;
7
+ export const MEMO_LABEL = 674;
8
+
9
+ export const CARDANO_API_ENDPOINT = getEnv("CARDANO_API_ENDPOINT");
10
+ export const CARDANO_TESTNET_API_ENDPOINT = getEnv("CARDANO_TESTNET_API_ENDPOINT");
@@ -0,0 +1,18 @@
1
+ import BigNumber from "bignumber.js";
2
+ import { AccountBridge } from "@ledgerhq/types-live";
3
+ import { Transaction } from "./types";
4
+
5
+ /**
6
+ * Create an empty transaction
7
+ *
8
+ * @returns {Transaction}
9
+ */
10
+ export const createTransaction: AccountBridge<Transaction>["createTransaction"] = () => ({
11
+ family: "cardano",
12
+ mode: "send",
13
+ amount: new BigNumber(0),
14
+ recipient: "",
15
+ useAllAmount: false,
16
+ fees: new BigNumber(0),
17
+ poolId: undefined,
18
+ });
@@ -0,0 +1,19 @@
1
+ import type { AccountRaw } from "@ledgerhq/types-live";
2
+
3
+ export const cardanoRawAccount1: AccountRaw = {
4
+ id: "js:2:cardano_testnet:806499588e0c4a58f4119f7e6e096bf42c3f774a528d2acec9e82ceebf87d1ceb3d4f3622dd2c77c65cc89c123f79337db22cf8a69f122e36dab1bf5083bf82d:cardano",
5
+ seedIdentifier: "bea94629d5cf776b8374a00afa15686f0b0742dd0330f86804c61202",
6
+ name: "Cardano (Testnet) 1",
7
+ derivationMode: "cardano",
8
+ index: 0,
9
+ freshAddress:
10
+ "addr_test1qpj84xm4jlpcsvmrnldj86zz7g4mwzr7qg90wdjpn64uea44mcsd3mzvmr9qhfscxkyla3aqnzttwepay9mt3fz84smqyjvhh4",
11
+ freshAddressPath: "1852'/1815'/0'/0/2",
12
+ blockHeight: 0,
13
+ operations: [],
14
+ pendingOperations: [],
15
+ currencyId: "cardano_testnet",
16
+ lastSyncDate: "",
17
+ balance: "10098829375",
18
+ xpub: "806499588e0c4a58f4119f7e6e096bf42c3f774a528d2acec9e82ceebf87d1ceb3d4f3622dd2c77c65cc89c123f79337db22cf8a69f122e36dab1bf5083bf82d",
19
+ };
@@ -0,0 +1,23 @@
1
+ export const cardanoScanAccounts = [
2
+ {
3
+ name: "cardano_testnet seed 1",
4
+ apdus: `
5
+ => d700000000
6
+ <= 050000009000
7
+ => d71101002d0000058000073c8000071780000000000000000000000022058000073c80000717800000000000000200000000
8
+ <= 00bea94629d5cf776b8374a00afa15686f0b0742dd0330f86804c61202b5de20d8ec4cd8ca0ba6183589fec7a09896b7643d2176b8a447ac369000
9
+ => d700000000
10
+ <= 050000009000
11
+ => d71000000d038000073c8000071780000000
12
+ <= 806499588e0c4a58f4119f7e6e096bf42c3f774a528d2acec9e82ceebf87d1ceb3d4f3622dd2c77c65cc89c123f79337db22cf8a69f122e36dab1bf5083bf82d9000
13
+ => d700000000
14
+ <= 050000009000
15
+ => d71101002d0000058000073c8000071780000001000000000000000022058000073c80000717800000010000000200000000
16
+ <= 0009457d98f405191765830c1afe91cc32b5f45c193a9aad4b606f8f5dd599d97135c125c5633d3d4431be87a9cff26ec08d388833bfcc530f9000
17
+ => d700000000
18
+ <= 050000009000
19
+ => d71000000d038000073c8000071780000001
20
+ <= ed5e0d059cb2eed53ea30b9ba84bb3aaa6c2364c6305a0c9a7e8944aa439884a642cc2f06e601808926e14b6e27417be0b0323d5a5149f1eebab8fc4e1fe14d49000
21
+ `,
22
+ },
23
+ ];