@ledgerhq/coin-hedera 1.13.0-nightly.2 → 1.13.0-nightly.20251031023756

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 (386) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/.unimportedrc.json +1 -1
  3. package/CHANGELOG.md +16 -22
  4. package/jest.config.js +1 -1
  5. package/jest.integ.config.js +8 -0
  6. package/lib/api/index.d.ts +4 -0
  7. package/lib/api/index.d.ts.map +1 -0
  8. package/lib/api/index.js +119 -0
  9. package/lib/api/index.js.map +1 -0
  10. package/lib/bridge/broadcast.d.ts +1 -1
  11. package/lib/bridge/broadcast.d.ts.map +1 -1
  12. package/lib/bridge/broadcast.js +6 -9
  13. package/lib/bridge/broadcast.js.map +1 -1
  14. package/lib/bridge/buildOptimisticOperation.d.ts.map +1 -1
  15. package/lib/bridge/buildOptimisticOperation.js +14 -11
  16. package/lib/bridge/buildOptimisticOperation.js.map +1 -1
  17. package/lib/bridge/createTransaction.d.ts +1 -1
  18. package/lib/bridge/createTransaction.d.ts.map +1 -1
  19. package/lib/bridge/createTransaction.js +2 -0
  20. package/lib/bridge/createTransaction.js.map +1 -1
  21. package/lib/bridge/estimateMaxSpendable.d.ts.map +1 -1
  22. package/lib/bridge/estimateMaxSpendable.js +2 -2
  23. package/lib/bridge/estimateMaxSpendable.js.map +1 -1
  24. package/lib/bridge/getTransactionStatus.d.ts.map +1 -1
  25. package/lib/bridge/getTransactionStatus.js +11 -10
  26. package/lib/bridge/getTransactionStatus.js.map +1 -1
  27. package/lib/bridge/prepareTransaction.d.ts.map +1 -1
  28. package/lib/bridge/prepareTransaction.js +6 -5
  29. package/lib/bridge/prepareTransaction.js.map +1 -1
  30. package/lib/bridge/signOperation.d.ts +1 -1
  31. package/lib/bridge/signOperation.d.ts.map +1 -1
  32. package/lib/bridge/signOperation.js +53 -14
  33. package/lib/bridge/signOperation.js.map +1 -1
  34. package/lib/bridge/synchronisation.d.ts.map +1 -1
  35. package/lib/bridge/synchronisation.js +25 -12
  36. package/lib/bridge/synchronisation.js.map +1 -1
  37. package/lib/bridge/utils.d.ts +2 -14
  38. package/lib/bridge/utils.d.ts.map +1 -1
  39. package/lib/bridge/utils.js +26 -148
  40. package/lib/bridge/utils.js.map +1 -1
  41. package/lib/config.d.ts +8 -0
  42. package/lib/config.d.ts.map +1 -0
  43. package/lib/config.js +9 -0
  44. package/lib/config.js.map +1 -0
  45. package/lib/constants.d.ts +11 -8
  46. package/lib/constants.d.ts.map +1 -1
  47. package/lib/constants.js +17 -13
  48. package/lib/constants.js.map +1 -1
  49. package/lib/deviceTransactionConfig.d.ts +1 -1
  50. package/lib/deviceTransactionConfig.d.ts.map +1 -1
  51. package/lib/deviceTransactionConfig.js +3 -3
  52. package/lib/deviceTransactionConfig.js.map +1 -1
  53. package/lib/logic/broadcast.d.ts +3 -0
  54. package/lib/logic/broadcast.d.ts.map +1 -0
  55. package/lib/logic/broadcast.js +11 -0
  56. package/lib/logic/broadcast.js.map +1 -0
  57. package/lib/logic/combine.d.ts +2 -0
  58. package/lib/logic/combine.d.ts.map +1 -0
  59. package/lib/logic/combine.js +19 -0
  60. package/lib/logic/combine.js.map +1 -0
  61. package/lib/logic/craftTransaction.d.ts +8 -0
  62. package/lib/logic/craftTransaction.d.ts.map +1 -0
  63. package/lib/logic/craftTransaction.js +107 -0
  64. package/lib/logic/craftTransaction.js.map +1 -0
  65. package/lib/logic/estimateFees.d.ts +5 -0
  66. package/lib/logic/estimateFees.d.ts.map +1 -0
  67. package/lib/logic/estimateFees.js +25 -0
  68. package/lib/logic/estimateFees.js.map +1 -0
  69. package/lib/logic/getAssetFromToken.d.ts +4 -0
  70. package/lib/logic/getAssetFromToken.d.ts.map +1 -0
  71. package/lib/logic/getAssetFromToken.js +14 -0
  72. package/lib/logic/getAssetFromToken.js.map +1 -0
  73. package/lib/logic/getBalance.d.ts +4 -0
  74. package/lib/logic/getBalance.d.ts.map +1 -0
  75. package/lib/logic/getBalance.js +36 -0
  76. package/lib/logic/getBalance.js.map +1 -0
  77. package/lib/logic/getTokenFromAsset.d.ts +4 -0
  78. package/lib/logic/getTokenFromAsset.d.ts.map +1 -0
  79. package/lib/logic/getTokenFromAsset.js +13 -0
  80. package/lib/logic/getTokenFromAsset.js.map +1 -0
  81. package/lib/logic/index.d.ts +10 -0
  82. package/lib/logic/index.d.ts.map +1 -0
  83. package/lib/logic/index.js +22 -0
  84. package/lib/logic/index.js.map +1 -0
  85. package/lib/logic/lastBlock.d.ts +12 -0
  86. package/lib/logic/lastBlock.d.ts.map +1 -0
  87. package/lib/logic/lastBlock.js +25 -0
  88. package/lib/logic/lastBlock.js.map +1 -0
  89. package/lib/logic/listOperations.d.ts +19 -0
  90. package/lib/logic/listOperations.d.ts.map +1 -0
  91. package/lib/logic/listOperations.js +179 -0
  92. package/lib/logic/listOperations.js.map +1 -0
  93. package/lib/logic/utils.d.ts +55 -0
  94. package/lib/logic/utils.d.ts.map +1 -0
  95. package/lib/logic/utils.js +197 -0
  96. package/lib/logic/utils.js.map +1 -0
  97. package/lib/network/api.d.ts +24 -0
  98. package/lib/network/api.d.ts.map +1 -0
  99. package/lib/network/api.js +119 -0
  100. package/lib/network/api.js.map +1 -0
  101. package/lib/network/rpc.d.ts +12 -0
  102. package/lib/network/rpc.d.ts.map +1 -0
  103. package/lib/network/rpc.js +22 -0
  104. package/lib/network/rpc.js.map +1 -0
  105. package/lib/{api → network}/utils.d.ts +1 -5
  106. package/lib/network/utils.d.ts.map +1 -0
  107. package/lib/network/utils.js +52 -0
  108. package/lib/network/utils.js.map +1 -0
  109. package/lib/test/bridgeDatasetTest.d.ts.map +1 -1
  110. package/lib/test/bridgeDatasetTest.js +5 -1
  111. package/lib/test/bridgeDatasetTest.js.map +1 -1
  112. package/lib/test/fixtures/account.fixture.d.ts +17 -0
  113. package/lib/test/fixtures/account.fixture.d.ts.map +1 -1
  114. package/lib/test/fixtures/account.fixture.js +18 -1
  115. package/lib/test/fixtures/account.fixture.js.map +1 -1
  116. package/lib/test/fixtures/currency.fixture.d.ts.map +1 -1
  117. package/lib/test/fixtures/currency.fixture.js +1 -1
  118. package/lib/test/fixtures/currency.fixture.js.map +1 -1
  119. package/lib/test/fixtures/mirror.fixture.d.ts +1 -1
  120. package/lib/test/fixtures/mirror.fixture.d.ts.map +1 -1
  121. package/lib/test/fixtures/network.fixture.d.ts +3 -0
  122. package/lib/test/fixtures/network.fixture.d.ts.map +1 -0
  123. package/lib/test/fixtures/network.fixture.js +9 -0
  124. package/lib/test/fixtures/network.fixture.js.map +1 -0
  125. package/lib/test/fixtures/transaction.fixture.d.ts.map +1 -1
  126. package/lib/test/fixtures/transaction.fixture.js +3 -0
  127. package/lib/test/fixtures/transaction.fixture.js.map +1 -1
  128. package/lib/transaction.d.ts +1 -1
  129. package/lib/transaction.d.ts.map +1 -1
  130. package/lib/transaction.js +35 -6
  131. package/lib/transaction.js.map +1 -1
  132. package/lib/types/alpaca.d.ts +3 -0
  133. package/lib/types/alpaca.d.ts.map +1 -0
  134. package/lib/{api/types.js → types/alpaca.js} +1 -1
  135. package/lib/types/alpaca.js.map +1 -0
  136. package/lib/types/bridge.d.ts +28 -9
  137. package/lib/types/bridge.d.ts.map +1 -1
  138. package/lib/types/index.d.ts +2 -0
  139. package/lib/types/index.d.ts.map +1 -1
  140. package/lib/types/index.js +2 -0
  141. package/lib/types/index.js.map +1 -1
  142. package/lib/{api/types.d.ts → types/mirror.d.ts} +21 -2
  143. package/lib/types/mirror.d.ts.map +1 -0
  144. package/lib/types/mirror.js +3 -0
  145. package/lib/types/mirror.js.map +1 -0
  146. package/lib-es/api/index.d.ts +4 -0
  147. package/lib-es/api/index.d.ts.map +1 -0
  148. package/lib-es/api/index.js +112 -0
  149. package/lib-es/api/index.js.map +1 -0
  150. package/lib-es/bridge/broadcast.d.ts +1 -1
  151. package/lib-es/bridge/broadcast.d.ts.map +1 -1
  152. package/lib-es/bridge/broadcast.js +4 -7
  153. package/lib-es/bridge/broadcast.js.map +1 -1
  154. package/lib-es/bridge/buildOptimisticOperation.d.ts.map +1 -1
  155. package/lib-es/bridge/buildOptimisticOperation.js +12 -9
  156. package/lib-es/bridge/buildOptimisticOperation.js.map +1 -1
  157. package/lib-es/bridge/createTransaction.d.ts +1 -1
  158. package/lib-es/bridge/createTransaction.d.ts.map +1 -1
  159. package/lib-es/bridge/createTransaction.js +2 -0
  160. package/lib-es/bridge/createTransaction.js.map +1 -1
  161. package/lib-es/bridge/estimateMaxSpendable.d.ts.map +1 -1
  162. package/lib-es/bridge/estimateMaxSpendable.js +2 -2
  163. package/lib-es/bridge/estimateMaxSpendable.js.map +1 -1
  164. package/lib-es/bridge/getTransactionStatus.d.ts.map +1 -1
  165. package/lib-es/bridge/getTransactionStatus.js +7 -6
  166. package/lib-es/bridge/getTransactionStatus.js.map +1 -1
  167. package/lib-es/bridge/prepareTransaction.d.ts.map +1 -1
  168. package/lib-es/bridge/prepareTransaction.js +4 -3
  169. package/lib-es/bridge/prepareTransaction.js.map +1 -1
  170. package/lib-es/bridge/signOperation.d.ts +1 -1
  171. package/lib-es/bridge/signOperation.d.ts.map +1 -1
  172. package/lib-es/bridge/signOperation.js +53 -14
  173. package/lib-es/bridge/signOperation.js.map +1 -1
  174. package/lib-es/bridge/synchronisation.d.ts.map +1 -1
  175. package/lib-es/bridge/synchronisation.js +27 -14
  176. package/lib-es/bridge/synchronisation.js.map +1 -1
  177. package/lib-es/bridge/utils.d.ts +2 -14
  178. package/lib-es/bridge/utils.d.ts.map +1 -1
  179. package/lib-es/bridge/utils.js +22 -140
  180. package/lib-es/bridge/utils.js.map +1 -1
  181. package/lib-es/config.d.ts +8 -0
  182. package/lib-es/config.d.ts.map +1 -0
  183. package/lib-es/config.js +4 -0
  184. package/lib-es/config.js.map +1 -0
  185. package/lib-es/constants.d.ts +11 -8
  186. package/lib-es/constants.d.ts.map +1 -1
  187. package/lib-es/constants.js +13 -9
  188. package/lib-es/constants.js.map +1 -1
  189. package/lib-es/deviceTransactionConfig.d.ts +1 -1
  190. package/lib-es/deviceTransactionConfig.d.ts.map +1 -1
  191. package/lib-es/deviceTransactionConfig.js +1 -1
  192. package/lib-es/deviceTransactionConfig.js.map +1 -1
  193. package/lib-es/logic/broadcast.d.ts +3 -0
  194. package/lib-es/logic/broadcast.d.ts.map +1 -0
  195. package/lib-es/logic/broadcast.js +7 -0
  196. package/lib-es/logic/broadcast.js.map +1 -0
  197. package/lib-es/logic/combine.d.ts +2 -0
  198. package/lib-es/logic/combine.d.ts.map +1 -0
  199. package/lib-es/logic/combine.js +12 -0
  200. package/lib-es/logic/combine.js.map +1 -0
  201. package/lib-es/logic/craftTransaction.d.ts +8 -0
  202. package/lib-es/logic/craftTransaction.d.ts.map +1 -0
  203. package/lib-es/logic/craftTransaction.js +100 -0
  204. package/lib-es/logic/craftTransaction.js.map +1 -0
  205. package/lib-es/logic/estimateFees.d.ts +5 -0
  206. package/lib-es/logic/estimateFees.d.ts.map +1 -0
  207. package/lib-es/logic/estimateFees.js +18 -0
  208. package/lib-es/logic/estimateFees.js.map +1 -0
  209. package/lib-es/logic/getAssetFromToken.d.ts +4 -0
  210. package/lib-es/logic/getAssetFromToken.d.ts.map +1 -0
  211. package/lib-es/logic/getAssetFromToken.js +10 -0
  212. package/lib-es/logic/getAssetFromToken.js.map +1 -0
  213. package/lib-es/logic/getBalance.d.ts +4 -0
  214. package/lib-es/logic/getBalance.d.ts.map +1 -0
  215. package/lib-es/logic/getBalance.js +32 -0
  216. package/lib-es/logic/getBalance.js.map +1 -0
  217. package/lib-es/logic/getTokenFromAsset.d.ts +4 -0
  218. package/lib-es/logic/getTokenFromAsset.d.ts.map +1 -0
  219. package/lib-es/logic/getTokenFromAsset.js +9 -0
  220. package/lib-es/logic/getTokenFromAsset.js.map +1 -0
  221. package/lib-es/logic/index.d.ts +10 -0
  222. package/lib-es/logic/index.d.ts.map +1 -0
  223. package/lib-es/logic/index.js +10 -0
  224. package/lib-es/logic/index.js.map +1 -0
  225. package/lib-es/logic/lastBlock.d.ts +12 -0
  226. package/lib-es/logic/lastBlock.d.ts.map +1 -0
  227. package/lib-es/logic/lastBlock.js +21 -0
  228. package/lib-es/logic/lastBlock.js.map +1 -0
  229. package/lib-es/logic/listOperations.d.ts +19 -0
  230. package/lib-es/logic/listOperations.d.ts.map +1 -0
  231. package/lib-es/logic/listOperations.js +172 -0
  232. package/lib-es/logic/listOperations.js.map +1 -0
  233. package/lib-es/logic/utils.d.ts +55 -0
  234. package/lib-es/logic/utils.d.ts.map +1 -0
  235. package/lib-es/logic/utils.js +174 -0
  236. package/lib-es/logic/utils.js.map +1 -0
  237. package/lib-es/network/api.d.ts +24 -0
  238. package/lib-es/network/api.d.ts.map +1 -0
  239. package/lib-es/network/api.js +113 -0
  240. package/lib-es/network/api.js.map +1 -0
  241. package/lib-es/network/rpc.d.ts +12 -0
  242. package/lib-es/network/rpc.d.ts.map +1 -0
  243. package/lib-es/network/rpc.js +19 -0
  244. package/lib-es/network/rpc.js.map +1 -0
  245. package/lib-es/{api → network}/utils.d.ts +1 -5
  246. package/lib-es/network/utils.d.ts.map +1 -0
  247. package/lib-es/network/utils.js +45 -0
  248. package/lib-es/network/utils.js.map +1 -0
  249. package/lib-es/test/bridgeDatasetTest.d.ts.map +1 -1
  250. package/lib-es/test/bridgeDatasetTest.js +5 -1
  251. package/lib-es/test/bridgeDatasetTest.js.map +1 -1
  252. package/lib-es/test/fixtures/account.fixture.d.ts +17 -0
  253. package/lib-es/test/fixtures/account.fixture.d.ts.map +1 -1
  254. package/lib-es/test/fixtures/account.fixture.js +17 -0
  255. package/lib-es/test/fixtures/account.fixture.js.map +1 -1
  256. package/lib-es/test/fixtures/currency.fixture.d.ts.map +1 -1
  257. package/lib-es/test/fixtures/currency.fixture.js +1 -1
  258. package/lib-es/test/fixtures/currency.fixture.js.map +1 -1
  259. package/lib-es/test/fixtures/mirror.fixture.d.ts +1 -1
  260. package/lib-es/test/fixtures/mirror.fixture.d.ts.map +1 -1
  261. package/lib-es/test/fixtures/network.fixture.d.ts +3 -0
  262. package/lib-es/test/fixtures/network.fixture.d.ts.map +1 -0
  263. package/lib-es/test/fixtures/network.fixture.js +5 -0
  264. package/lib-es/test/fixtures/network.fixture.js.map +1 -0
  265. package/lib-es/test/fixtures/transaction.fixture.d.ts.map +1 -1
  266. package/lib-es/test/fixtures/transaction.fixture.js +3 -0
  267. package/lib-es/test/fixtures/transaction.fixture.js.map +1 -1
  268. package/lib-es/transaction.d.ts +1 -1
  269. package/lib-es/transaction.d.ts.map +1 -1
  270. package/lib-es/transaction.js +35 -6
  271. package/lib-es/transaction.js.map +1 -1
  272. package/lib-es/types/alpaca.d.ts +3 -0
  273. package/lib-es/types/alpaca.d.ts.map +1 -0
  274. package/lib-es/types/alpaca.js +2 -0
  275. package/lib-es/types/alpaca.js.map +1 -0
  276. package/lib-es/types/bridge.d.ts +28 -9
  277. package/lib-es/types/bridge.d.ts.map +1 -1
  278. package/lib-es/types/index.d.ts +2 -0
  279. package/lib-es/types/index.d.ts.map +1 -1
  280. package/lib-es/types/index.js +2 -0
  281. package/lib-es/types/index.js.map +1 -1
  282. package/lib-es/{api/types.d.ts → types/mirror.d.ts} +21 -2
  283. package/lib-es/types/mirror.d.ts.map +1 -0
  284. package/lib-es/types/mirror.js +2 -0
  285. package/lib-es/types/mirror.js.map +1 -0
  286. package/package.json +12 -13
  287. package/src/api/index.integ.test.ts +406 -0
  288. package/src/api/index.test.ts +30 -0
  289. package/src/api/index.ts +149 -0
  290. package/src/bridge/broadcast.ts +5 -10
  291. package/src/bridge/buildOptimisticOperation.integration.test.ts +8 -8
  292. package/src/bridge/buildOptimisticOperation.ts +13 -10
  293. package/src/bridge/createTransaction.ts +3 -1
  294. package/src/bridge/estimateMaxSpendable.ts +6 -3
  295. package/src/bridge/getTransactionStatus.test.ts +11 -10
  296. package/src/bridge/getTransactionStatus.ts +12 -11
  297. package/src/bridge/js-estimateMaxSpendable.integration.test.ts +6 -3
  298. package/src/bridge/prepareTransaction.test.ts +9 -17
  299. package/src/bridge/prepareTransaction.ts +5 -4
  300. package/src/bridge/serialization.test.ts +6 -6
  301. package/src/bridge/signOperation.ts +69 -16
  302. package/src/bridge/synchronisation.ts +26 -23
  303. package/src/bridge/utils.integration.test.ts +23 -269
  304. package/src/bridge/utils.ts +40 -207
  305. package/src/config.ts +7 -0
  306. package/src/constants.ts +15 -9
  307. package/src/deviceTransactionConfig.ts +2 -2
  308. package/src/logic/broadcast.test.ts +58 -0
  309. package/src/logic/broadcast.ts +8 -0
  310. package/src/logic/combine.test.ts +119 -0
  311. package/src/logic/combine.ts +14 -0
  312. package/src/logic/craftTransaction.test.ts +215 -0
  313. package/src/logic/craftTransaction.ts +175 -0
  314. package/src/logic/estimateFees.test.ts +99 -0
  315. package/src/logic/estimateFees.ts +28 -0
  316. package/src/logic/getAssetFromToken.test.ts +27 -0
  317. package/src/logic/getAssetFromToken.ts +12 -0
  318. package/src/logic/getBalance.test.ts +205 -0
  319. package/src/logic/getBalance.ts +42 -0
  320. package/src/logic/getTokenFromAsset.test.ts +33 -0
  321. package/src/logic/getTokenFromAsset.ts +17 -0
  322. package/src/logic/index.ts +9 -0
  323. package/src/logic/lastBlock.test.ts +23 -0
  324. package/src/logic/lastBlock.ts +23 -0
  325. package/src/logic/listOperations.test.ts +392 -0
  326. package/src/logic/listOperations.ts +247 -0
  327. package/src/logic/utils.test.ts +432 -0
  328. package/src/logic/utils.ts +255 -0
  329. package/src/{api/mirror.test.ts → network/api.test.ts} +81 -35
  330. package/src/network/api.ts +159 -0
  331. package/src/network/rpc.test.ts +68 -0
  332. package/src/network/rpc.ts +25 -0
  333. package/src/network/utils.test.ts +175 -0
  334. package/src/network/utils.ts +58 -0
  335. package/src/test/bridgeDatasetTest.ts +6 -2
  336. package/src/test/fixtures/account.fixture.ts +18 -0
  337. package/src/test/fixtures/currency.fixture.ts +1 -1
  338. package/src/test/fixtures/mirror.fixture.ts +1 -1
  339. package/src/test/fixtures/network.fixture.ts +6 -0
  340. package/src/test/fixtures/transaction.fixture.ts +5 -2
  341. package/src/transaction.ts +40 -9
  342. package/src/types/alpaca.ts +3 -0
  343. package/src/types/bridge.ts +36 -10
  344. package/src/types/index.ts +2 -0
  345. package/src/{api/types.ts → types/mirror.ts} +23 -1
  346. package/lib/api/mirror.d.ts +0 -6
  347. package/lib/api/mirror.d.ts.map +0 -1
  348. package/lib/api/mirror.js +0 -84
  349. package/lib/api/mirror.js.map +0 -1
  350. package/lib/api/network.d.ts +0 -11
  351. package/lib/api/network.d.ts.map +0 -1
  352. package/lib/api/network.js +0 -80
  353. package/lib/api/network.js.map +0 -1
  354. package/lib/api/types.d.ts.map +0 -1
  355. package/lib/api/types.js.map +0 -1
  356. package/lib/api/utils.d.ts.map +0 -1
  357. package/lib/api/utils.js +0 -132
  358. package/lib/api/utils.js.map +0 -1
  359. package/lib/logic.d.ts +0 -11
  360. package/lib/logic.d.ts.map +0 -1
  361. package/lib/logic.js +0 -37
  362. package/lib/logic.js.map +0 -1
  363. package/lib-es/api/mirror.d.ts +0 -6
  364. package/lib-es/api/mirror.d.ts.map +0 -1
  365. package/lib-es/api/mirror.js +0 -74
  366. package/lib-es/api/mirror.js.map +0 -1
  367. package/lib-es/api/network.d.ts +0 -11
  368. package/lib-es/api/network.d.ts.map +0 -1
  369. package/lib-es/api/network.js +0 -71
  370. package/lib-es/api/network.js.map +0 -1
  371. package/lib-es/api/types.d.ts.map +0 -1
  372. package/lib-es/api/types.js +0 -2
  373. package/lib-es/api/types.js.map +0 -1
  374. package/lib-es/api/utils.d.ts.map +0 -1
  375. package/lib-es/api/utils.js +0 -124
  376. package/lib-es/api/utils.js.map +0 -1
  377. package/lib-es/logic.d.ts +0 -11
  378. package/lib-es/logic.d.ts.map +0 -1
  379. package/lib-es/logic.js +0 -29
  380. package/lib-es/logic.js.map +0 -1
  381. package/src/api/mirror.ts +0 -91
  382. package/src/api/network.test.ts +0 -49
  383. package/src/api/network.ts +0 -125
  384. package/src/api/utils.ts +0 -150
  385. package/src/logic.test.ts +0 -152
  386. package/src/logic.ts +0 -66
@@ -1,16 +1,5 @@
1
1
  import BigNumber from "bignumber.js";
2
- import murmurhash from "imurmurhash";
3
- import invariant from "invariant";
4
- import { AccountId } from "@hashgraph/sdk";
5
- import { InvalidAddress } from "@ledgerhq/errors";
6
2
  import type { Account, Operation, TokenAccount } from "@ledgerhq/types-live";
7
- import cvsApi from "@ledgerhq/live-countervalues/api/index";
8
- import {
9
- findCryptoCurrencyById,
10
- findTokenByAddressInCurrency,
11
- getFiatCurrencyByTicker,
12
- listTokensForCryptoCurrency,
13
- } from "@ledgerhq/cryptoassets";
14
3
  import {
15
4
  decodeTokenAccountId,
16
5
  emptyHistoryCache,
@@ -19,63 +8,14 @@ import {
19
8
  isTokenAccount,
20
9
  } from "@ledgerhq/coin-framework/account";
21
10
  import { encodeOperationId } from "@ledgerhq/coin-framework/operation";
22
- import type { CryptoCurrency, Currency, TokenCurrency } from "@ledgerhq/types-cryptoassets";
11
+ import type { TokenCurrency } from "@ledgerhq/types-cryptoassets";
23
12
  import { mergeOps } from "@ledgerhq/coin-framework/bridge/jsHelpers";
24
- import { makeLRUCache, seconds } from "@ledgerhq/live-network/cache";
13
+ import { getCryptoAssetsStore } from "@ledgerhq/coin-framework/crypto-assets/index";
14
+ import { HEDERA_OPERATION_TYPES } from "../constants";
25
15
  import { estimateMaxSpendable } from "./estimateMaxSpendable";
26
- import type { HederaOperationExtra, Transaction } from "../types";
27
- import { getAccount } from "../api/mirror";
28
- import { getHederaClient } from "../api/network";
29
- import type { HederaMirrorToken } from "../api/types";
30
- import { HederaRecipientInvalidChecksum } from "../errors";
31
- import { isTokenAssociateTransaction, isValidExtra } from "../logic";
32
- import { BASE_USD_FEE_BY_OPERATION_TYPE, HEDERA_OPERATION_TYPES } from "../constants";
33
-
34
- const ESTIMATED_FEE_SAFETY_RATE = 2;
35
-
36
- // note: this is currently called frequently by getTransactionStatus; LRU cache prevents duplicated requests
37
- export const getCurrencyToUSDRate = makeLRUCache(
38
- async (currency: Currency) => {
39
- try {
40
- const [rate] = await cvsApi.fetchLatest([
41
- {
42
- from: currency,
43
- to: getFiatCurrencyByTicker("USD"),
44
- startDate: new Date(),
45
- },
46
- ]);
47
-
48
- invariant(rate, "no value returned from cvs api");
49
-
50
- return new BigNumber(rate);
51
- } catch {
52
- return null;
53
- }
54
- },
55
- currency => currency.ticker,
56
- seconds(3),
57
- );
58
-
59
- export const getEstimatedFees = async (
60
- account: Account,
61
- operationType: HEDERA_OPERATION_TYPES,
62
- ): Promise<BigNumber> => {
63
- try {
64
- const usdRate = await getCurrencyToUSDRate(account.currency);
65
-
66
- if (usdRate) {
67
- return new BigNumber(BASE_USD_FEE_BY_OPERATION_TYPE[operationType])
68
- .dividedBy(new BigNumber(usdRate))
69
- .integerValue(BigNumber.ROUND_CEIL)
70
- .multipliedBy(ESTIMATED_FEE_SAFETY_RATE);
71
- }
72
- // eslint-disable-next-line no-empty
73
- } catch {}
74
-
75
- // as fees are based on a currency conversion, we stay
76
- // on the safe side here and double the estimate for "max spendable"
77
- return new BigNumber("150200").multipliedBy(ESTIMATED_FEE_SAFETY_RATE); // 0.001502 ℏ (as of 2023-03-14)
78
- };
16
+ import { estimateFees } from "../logic/estimateFees";
17
+ import { isTokenAssociateTransaction, isValidExtra } from "../logic/utils";
18
+ import type { HederaOperationExtra, Transaction, HederaMirrorToken } from "../types";
79
19
 
80
20
  interface CalculateAmountResult {
81
21
  amount: BigNumber;
@@ -91,7 +31,7 @@ const calculateCoinAmount = async ({
91
31
  transaction: Transaction;
92
32
  operationType: HEDERA_OPERATION_TYPES;
93
33
  }): Promise<CalculateAmountResult> => {
94
- const estimatedFees = await getEstimatedFees(account, operationType);
34
+ const estimatedFees = await estimateFees(account.currency, operationType);
95
35
  const amount = transaction.useAllAmount
96
36
  ? await estimateMaxSpendable({ account, transaction })
97
37
  : transaction.amount;
@@ -142,62 +82,30 @@ export const calculateAmount = ({
142
82
  return calculateCoinAmount({ account, transaction, operationType });
143
83
  };
144
84
 
145
- // NOTE: convert from the non-url-safe version of base64 to the url-safe version (that the explorer uses)
146
- export function base64ToUrlSafeBase64(data: string): string {
147
- // Might be nice to use this alternative if .nvmrc changes to >= Node v14.18.0
148
- // base64url encoding option isn't supported until then
149
- // Buffer.from(data, "base64").toString("base64url");
150
-
151
- return data.replace(/\//g, "_").replace(/\+/g, "-");
152
- }
153
-
154
- const simpleSyncHashMemoize: Record<string, string> = {};
155
-
156
- export const getSyncHash = (
157
- currency: CryptoCurrency,
158
- blacklistedTokenIds: string[] = [],
159
- ): string => {
160
- const tokens = listTokensForCryptoCurrency(currency);
161
-
162
- const stringToHash =
163
- currency.id +
164
- tokens.map(token => token.id + token.contractAddress + token.name + token.ticker).join("") +
165
- blacklistedTokenIds.join("");
166
-
167
- if (!simpleSyncHashMemoize[stringToHash]) {
168
- simpleSyncHashMemoize[stringToHash] = `0x${murmurhash(stringToHash).result().toString(16)}`;
169
- }
170
-
171
- return simpleSyncHashMemoize[stringToHash];
172
- };
173
-
174
85
  export const getSubAccounts = async (
175
86
  accountId: string,
176
87
  lastTokenOperations: Operation[],
177
88
  mirrorTokens: HederaMirrorToken[],
178
89
  ): Promise<TokenAccount[]> => {
179
90
  // Creating a Map of Operations by TokenCurrencies in order to know which TokenAccounts should be synced as well
180
- const operationsByToken = lastTokenOperations.reduce<Map<TokenCurrency, Operation[]>>(
181
- (acc, tokenOperation) => {
182
- const { token } = decodeTokenAccountId(tokenOperation.accountId);
183
- if (!token) return acc;
184
-
185
- const isTokenListedInCAL = findTokenByAddressInCurrency(
186
- token.contractAddress,
187
- token.parentCurrency.id,
188
- );
189
- if (!isTokenListedInCAL) return acc;
190
-
191
- if (!acc.has(token)) {
192
- acc.set(token, []);
193
- }
91
+ const operationsByToken = new Map<TokenCurrency, Operation[]>();
194
92
 
195
- acc.get(token)?.push(tokenOperation);
93
+ for (const tokenOperation of lastTokenOperations) {
94
+ const { token } = await decodeTokenAccountId(tokenOperation.accountId);
95
+ if (!token) continue;
96
+
97
+ const isTokenListedInCAL = await getCryptoAssetsStore().findTokenByAddressInCurrency(
98
+ token.contractAddress,
99
+ token.parentCurrency.id,
100
+ );
101
+ if (!isTokenListedInCAL) continue;
196
102
 
197
- return acc;
198
- },
199
- new Map<TokenCurrency, Operation[]>(),
200
- );
103
+ if (!operationsByToken.has(token)) {
104
+ operationsByToken.set(token, []);
105
+ }
106
+
107
+ operationsByToken.get(token)?.push(tokenOperation);
108
+ }
201
109
 
202
110
  const subAccounts: TokenAccount[] = [];
203
111
 
@@ -234,7 +142,10 @@ export const getSubAccounts = async (
234
142
  const parentAccountId = accountId;
235
143
  const rawBalance = rawToken.balance;
236
144
  const balance = new BigNumber(rawBalance);
237
- const token = findTokenByAddressInCurrency(rawToken.token_id, "hedera");
145
+ const token = await getCryptoAssetsStore().findTokenByAddressInCurrency(
146
+ rawToken.token_id,
147
+ "hedera",
148
+ );
238
149
 
239
150
  if (!token) {
240
151
  continue;
@@ -265,14 +176,15 @@ export const getSubAccounts = async (
265
176
  return subAccounts;
266
177
  };
267
178
 
268
- type CoinOperationForOrphanChildOperation = Operation & Required<Pick<Operation, "subOperations">>;
179
+ type CoinOperationForOrphanChildOperation = Operation<HederaOperationExtra> &
180
+ Required<Pick<Operation, "subOperations">>;
269
181
 
270
182
  // create NONE coin operation that will be a parent of an orphan child operation
271
- const makeCoinOperationForOrphanChildOperation = (
272
- childOperation: Operation,
273
- ): CoinOperationForOrphanChildOperation => {
183
+ const makeCoinOperationForOrphanChildOperation = async (
184
+ childOperation: Operation<HederaOperationExtra>,
185
+ ): Promise<CoinOperationForOrphanChildOperation> => {
274
186
  const type = "NONE";
275
- const { accountId } = decodeTokenAccountId(childOperation.accountId);
187
+ const { accountId } = await decodeTokenAccountId(childOperation.accountId);
276
188
  const id = encodeOperationId(accountId, childOperation.hash, type);
277
189
 
278
190
  return {
@@ -298,34 +210,16 @@ const makeCoinOperationForOrphanChildOperation = (
298
210
  // this util handles:
299
211
  // - linking sub operations with coin operations, e.g. token transfer with fee payment
300
212
  // - if possible, assigning `extra.associatedTokenId = mirrorToken.tokenId` based on operation's consensus timestamp
301
- export const prepareOperations = (
302
- coinOperations: Operation[],
303
- tokenOperations: Operation[],
304
- mirrorTokens: HederaMirrorToken[],
305
- ): Operation[] => {
213
+ export const prepareOperations = async (
214
+ coinOperations: Operation<HederaOperationExtra>[],
215
+ tokenOperations: Operation<HederaOperationExtra>[],
216
+ ): Promise<Operation<HederaOperationExtra>[]> => {
306
217
  const preparedCoinOperations = coinOperations.map(op => ({ ...op }));
307
218
  const preparedTokenOperations = tokenOperations.map(op => ({ ...op }));
308
219
 
309
- // loop through coin operations to:
310
- // - enrich ASSOCIATE_TOKEN operations with extra.associatedTokenId
311
- // - prepare a map of hash => operations
220
+ // loop through coin operations to prepare a map of hash => operations
312
221
  const coinOperationsByHash: Record<string, CoinOperationForOrphanChildOperation[]> = {};
313
222
  preparedCoinOperations.forEach(op => {
314
- const extra = isValidExtra(op.extra) ? op.extra : null;
315
-
316
- if (op.type === "ASSOCIATE_TOKEN" && extra?.consensusTimestamp) {
317
- const relatedMirrorToken = mirrorTokens.find(t => {
318
- return t.created_timestamp === extra.consensusTimestamp;
319
- });
320
-
321
- if (relatedMirrorToken) {
322
- op.extra = {
323
- ...extra,
324
- associatedTokenId: relatedMirrorToken.token_id,
325
- } satisfies HederaOperationExtra;
326
- }
327
- }
328
-
329
223
  if (!coinOperationsByHash[op.hash]) {
330
224
  coinOperationsByHash[op.hash] = [];
331
225
  }
@@ -336,13 +230,13 @@ export const prepareOperations = (
336
230
 
337
231
  // loop through token operations to potentially copy them as a child operation of a coin operation
338
232
  for (const tokenOperation of preparedTokenOperations) {
339
- const { token } = decodeTokenAccountId(tokenOperation.accountId);
233
+ const { token } = await decodeTokenAccountId(tokenOperation.accountId);
340
234
  if (!token) continue;
341
235
 
342
236
  let mainOperations = coinOperationsByHash[tokenOperation.hash];
343
237
 
344
238
  if (!mainOperations?.length) {
345
- const noneOperation = makeCoinOperationForOrphanChildOperation(tokenOperation);
239
+ const noneOperation = await makeCoinOperationForOrphanChildOperation(tokenOperation);
346
240
  mainOperations = [noneOperation];
347
241
  preparedCoinOperations.push(noneOperation);
348
242
  }
@@ -456,64 +350,3 @@ export function patchOperationWithExtra(
456
350
  nftOperations: (operation.nftOperations ?? []).map(op => ({ ...op, extra })),
457
351
  };
458
352
  }
459
-
460
- export const checkAccountTokenAssociationStatus = makeLRUCache(
461
- async (address: string, tokenId: string) => {
462
- const [parsingError, parsingResult] = safeParseAccountId(address);
463
-
464
- if (parsingError) {
465
- throw parsingError;
466
- }
467
-
468
- const addressWithoutChecksum = parsingResult.accountId;
469
- const mirrorAccount = await getAccount(addressWithoutChecksum);
470
-
471
- // auto association is enabled
472
- if (mirrorAccount.max_automatic_token_associations === -1) {
473
- return true;
474
- }
475
-
476
- const isTokenAssociated = mirrorAccount.balance.tokens.some(token => {
477
- return token.token_id === tokenId;
478
- });
479
-
480
- return isTokenAssociated;
481
- },
482
- (accountId, tokenId) => `${accountId}-${tokenId}`,
483
- seconds(30),
484
- );
485
-
486
- export const safeParseAccountId = (
487
- address: string,
488
- ): [Error, null] | [null, { accountId: string; checksum: string | null }] => {
489
- const currency = findCryptoCurrencyById("hedera");
490
- const currencyName = currency?.name ?? "Hedera";
491
-
492
- try {
493
- const accountId = AccountId.fromString(address);
494
-
495
- // verify checksum if present
496
- // FIXME: migrate to EntityIdHelper methods once SDK is upgraded:
497
- // https://github.com/hiero-ledger/hiero-sdk-js/blob/main/src/EntityIdHelper.js#L197
498
- // https://github.com/hiero-ledger/hiero-sdk-js/blob/main/src/EntityIdHelper.js#L446
499
- const checksum: string | null = address.split("-")[1] ?? null;
500
- if (checksum) {
501
- const client = getHederaClient();
502
- const recipientWithChecksum = accountId.toStringWithChecksum(client);
503
- const expectedChecksum = recipientWithChecksum.split("-")[1];
504
-
505
- if (checksum !== expectedChecksum) {
506
- return [new HederaRecipientInvalidChecksum(), null];
507
- }
508
- }
509
-
510
- const result = {
511
- accountId: accountId.toString(),
512
- checksum,
513
- };
514
-
515
- return [null, result];
516
- } catch (err) {
517
- return [new InvalidAddress("", { currencyName }), null];
518
- }
519
- };
package/src/config.ts ADDED
@@ -0,0 +1,7 @@
1
+ import buildCoinConfig, { type CurrencyConfig } from "@ledgerhq/coin-framework/config";
2
+
3
+ export type HederaCoinConfig = CurrencyConfig;
4
+
5
+ const coinConfig = buildCoinConfig<HederaCoinConfig>();
6
+
7
+ export default coinConfig;
package/src/constants.ts CHANGED
@@ -1,12 +1,11 @@
1
1
  /**
2
- * Internal types used to distinguish custom Hedera transaction behaviors.
3
- * These can be stored in transaction.properties.name and used to route specific preparation logic.
2
+ * Internal types to distinguish custom Hedera transaction behaviors.
3
+ * These can be used in transaction.mode and used to route specific preparation logic.
4
4
  */
5
- export const HEDERA_TRANSACTION_KINDS = {
6
- TokenAssociate: {
7
- name: "tokenAssociate",
8
- },
9
- } as const satisfies Record<string, Record<string, unknown> & { name: string }>;
5
+ export enum HEDERA_TRANSACTION_MODES {
6
+ Send = "send",
7
+ TokenAssociate = "token-associate",
8
+ }
10
9
 
11
10
  /**
12
11
  * Enum representing the supported Hedera operation types for fee estimation
@@ -17,7 +16,14 @@ export enum HEDERA_OPERATION_TYPES {
17
16
  TokenAssociate = "TokenAssociate",
18
17
  }
19
18
 
20
- const TINYBAR_SCALE = 8;
19
+ export const TINYBAR_SCALE = 8;
20
+
21
+ export const ESTIMATED_FEE_SAFETY_RATE = 2;
22
+
23
+ // old value moved from https://github.com/LedgerHQ/ledger-live/blob/8447b68b7c6f1e7ccd4aa9db4da0e6c8de36a88e/libs/coin-modules/coin-hedera/src/bridge/utils.ts#L77
24
+ export const DEFAULT_TINYBAR_FEE = 150200;
25
+
26
+ export const SYNTHETIC_BLOCK_WINDOW_SECONDS = 10;
21
27
 
22
28
  /**
23
29
  * https://docs.hedera.com/hedera/networks/mainnet/fees
@@ -25,7 +31,7 @@ const TINYBAR_SCALE = 8;
25
31
  * These are Hedera's estimated fee costs in USD, scaled to tinybars (1 HBAR = 10^8 tinybars),
26
32
  * so they can be converted into actual HBAR amounts based on current USD/crypto rates.
27
33
  *
28
- * Used in fee estimation logic (getEstimatedFees function) to determine whether an account
34
+ * Used in fee estimation logic (estimateFees function) to determine whether an account
29
35
  * has sufficient balance to cover the cost of a transaction (e.g. token association).
30
36
  */
31
37
  export const BASE_USD_FEE_BY_OPERATION_TYPE = {
@@ -1,7 +1,7 @@
1
1
  import type { AccountLike, Account } from "@ledgerhq/types-live";
2
- import type { Transaction, TransactionStatus } from "./types";
3
2
  import type { CommonDeviceTransactionField as DeviceTransactionField } from "@ledgerhq/coin-framework/transaction/common";
4
- import { isTokenAssociateTransaction } from "./logic";
3
+ import { isTokenAssociateTransaction } from "./logic/utils";
4
+ import type { Transaction, TransactionStatus } from "./types";
5
5
 
6
6
  async function getDeviceTransactionConfig({
7
7
  transaction,
@@ -0,0 +1,58 @@
1
+ import { broadcast } from "./broadcast";
2
+ import { rpcClient } from "../network/rpc";
3
+ import { deserializeTransaction } from "./utils";
4
+
5
+ jest.mock("../network/rpc");
6
+ jest.mock("./utils");
7
+
8
+ describe("broadcast", () => {
9
+ beforeEach(() => {
10
+ jest.clearAllMocks();
11
+ });
12
+
13
+ it("should deserialize and broadcast a transaction successfully", async () => {
14
+ const txWithSignature = "serialized-transaction-with-signature";
15
+ const mockDeserializedTx = { someProperty: "mockTransaction" } as any;
16
+ const mockResponse = { transactionId: "mock-transaction-id" } as any;
17
+
18
+ (deserializeTransaction as jest.Mock).mockReturnValue(mockDeserializedTx);
19
+ (rpcClient.broadcastTransaction as jest.Mock).mockResolvedValue(mockResponse);
20
+
21
+ const result = await broadcast(txWithSignature);
22
+
23
+ expect(deserializeTransaction).toHaveBeenCalledTimes(1);
24
+ expect(deserializeTransaction).toHaveBeenCalledWith(txWithSignature);
25
+ expect(rpcClient.broadcastTransaction).toHaveBeenCalledTimes(1);
26
+ expect(rpcClient.broadcastTransaction).toHaveBeenCalledWith(mockDeserializedTx);
27
+ expect(result).toBe(mockResponse);
28
+ });
29
+
30
+ it("should propagate errors from deserializeTransaction", async () => {
31
+ const txWithSignature = "serialized-transaction-with-signature";
32
+ const error = new Error("Deserialization error");
33
+
34
+ (deserializeTransaction as jest.Mock).mockImplementation(() => {
35
+ throw error;
36
+ });
37
+
38
+ await expect(broadcast(txWithSignature)).rejects.toThrow(error);
39
+ expect(deserializeTransaction).toHaveBeenCalledTimes(1);
40
+ expect(deserializeTransaction).toHaveBeenCalledWith(txWithSignature);
41
+ expect(rpcClient.broadcastTransaction).not.toHaveBeenCalled();
42
+ });
43
+
44
+ it("should propagate errors from broadcastTransaction", async () => {
45
+ const txWithSignature = "serialized-transaction-with-signature";
46
+ const mockDeserializedTx = { someProperty: "mockTransaction" } as any;
47
+ const error = new Error("Network error");
48
+
49
+ (deserializeTransaction as jest.Mock).mockReturnValue(mockDeserializedTx);
50
+ (rpcClient.broadcastTransaction as jest.Mock).mockRejectedValue(error);
51
+
52
+ await expect(broadcast(txWithSignature)).rejects.toThrow(error);
53
+ expect(deserializeTransaction).toHaveBeenCalledTimes(1);
54
+ expect(deserializeTransaction).toHaveBeenCalledWith(txWithSignature);
55
+ expect(rpcClient.broadcastTransaction).toHaveBeenCalledTimes(1);
56
+ expect(rpcClient.broadcastTransaction).toHaveBeenCalledWith(mockDeserializedTx);
57
+ });
58
+ });
@@ -0,0 +1,8 @@
1
+ import type { TransactionResponse } from "@hashgraph/sdk";
2
+ import { rpcClient } from "../network/rpc";
3
+ import { deserializeTransaction } from "./utils";
4
+
5
+ export const broadcast = async (txWithSignature: string): Promise<TransactionResponse> => {
6
+ const hederaTransaction = deserializeTransaction(txWithSignature);
7
+ return await rpcClient.broadcastTransaction(hederaTransaction);
8
+ };
@@ -0,0 +1,119 @@
1
+ import { PublicKey } from "@hashgraph/sdk";
2
+ import { combine } from "./combine";
3
+ import { deserializeSignature, deserializeTransaction, serializeTransaction } from "./utils";
4
+
5
+ jest.mock("./utils");
6
+ jest.mock("@hashgraph/sdk");
7
+
8
+ describe("combine", () => {
9
+ beforeEach(() => {
10
+ jest.clearAllMocks();
11
+ });
12
+
13
+ it("should combine transaction with signature successfully", () => {
14
+ const tx = "serialized-transaction";
15
+ const signature = "serialized-signature";
16
+ const publicKey = "public-key-string";
17
+
18
+ const mockDeserializedTx = { addSignature: jest.fn() } as any;
19
+ const mockBufferSignature = Buffer.from("mock-signature");
20
+ const mockBufferPublicKey = { key: "mock-public-key" } as any;
21
+ const mockSerializedTxWithSignature = "serialized-transaction-with-signature";
22
+
23
+ (deserializeTransaction as jest.Mock).mockReturnValue(mockDeserializedTx);
24
+ (deserializeSignature as jest.Mock).mockReturnValue(mockBufferSignature);
25
+ (PublicKey.fromString as jest.Mock).mockReturnValue(mockBufferPublicKey);
26
+ (serializeTransaction as jest.Mock).mockReturnValue(mockSerializedTxWithSignature);
27
+
28
+ const result = combine(tx, signature, publicKey);
29
+
30
+ expect(deserializeTransaction).toHaveBeenCalledTimes(1);
31
+ expect(deserializeTransaction).toHaveBeenCalledWith(tx);
32
+ expect(deserializeSignature).toHaveBeenCalledTimes(1);
33
+ expect(deserializeSignature).toHaveBeenCalledWith(signature);
34
+ expect(PublicKey.fromString).toHaveBeenCalledTimes(1);
35
+ expect(PublicKey.fromString).toHaveBeenCalledWith(publicKey);
36
+ expect(mockDeserializedTx.addSignature).toHaveBeenCalledTimes(1);
37
+ expect(mockDeserializedTx.addSignature).toHaveBeenCalledWith(
38
+ mockBufferPublicKey,
39
+ mockBufferSignature,
40
+ );
41
+ expect(serializeTransaction).toHaveBeenCalledTimes(1);
42
+ expect(serializeTransaction).toHaveBeenCalledWith(mockDeserializedTx);
43
+ expect(result).toBe(mockSerializedTxWithSignature);
44
+ });
45
+
46
+ it("should throw an error when public key is not provided", () => {
47
+ const tx = "serialized-transaction";
48
+ const signature = "serialized-signature";
49
+
50
+ expect(() => combine(tx, signature, undefined)).toThrow();
51
+ expect(deserializeTransaction).not.toHaveBeenCalled();
52
+ expect(deserializeSignature).not.toHaveBeenCalled();
53
+ expect(PublicKey.fromString).not.toHaveBeenCalled();
54
+ expect(serializeTransaction).not.toHaveBeenCalled();
55
+ });
56
+
57
+ it("should propagate errors from deserializeTransaction", () => {
58
+ const tx = "serialized-transaction";
59
+ const signature = "serialized-signature";
60
+ const publicKey = "public-key-string";
61
+ const error = new Error("Deserialization error");
62
+
63
+ (deserializeTransaction as jest.Mock).mockImplementation(() => {
64
+ throw error;
65
+ });
66
+
67
+ expect(() => combine(tx, signature, publicKey)).toThrow(error);
68
+ expect(deserializeTransaction).toHaveBeenCalledTimes(1);
69
+ expect(deserializeTransaction).toHaveBeenCalledWith(tx);
70
+ expect(deserializeSignature).not.toHaveBeenCalled();
71
+ expect(PublicKey.fromString).not.toHaveBeenCalled();
72
+ expect(serializeTransaction).not.toHaveBeenCalled();
73
+ });
74
+
75
+ it("should propagate errors from deserializeSignature", () => {
76
+ const tx = "serialized-transaction";
77
+ const signature = "serialized-signature";
78
+ const publicKey = "public-key-string";
79
+ const mockDeserializedTx = { addSignature: jest.fn() } as any;
80
+ const error = new Error("Signature deserialization error");
81
+
82
+ (deserializeTransaction as jest.Mock).mockReturnValue(mockDeserializedTx);
83
+ (deserializeSignature as jest.Mock).mockImplementation(() => {
84
+ throw error;
85
+ });
86
+
87
+ expect(() => combine(tx, signature, publicKey)).toThrow(error);
88
+ expect(deserializeTransaction).toHaveBeenCalledTimes(1);
89
+ expect(deserializeTransaction).toHaveBeenCalledWith(tx);
90
+ expect(deserializeSignature).toHaveBeenCalledTimes(1);
91
+ expect(deserializeSignature).toHaveBeenCalledWith(signature);
92
+ expect(PublicKey.fromString).not.toHaveBeenCalled();
93
+ expect(serializeTransaction).not.toHaveBeenCalled();
94
+ });
95
+
96
+ it("should propagate errors from PublicKey.fromString", () => {
97
+ const tx = "serialized-transaction";
98
+ const signature = "serialized-signature";
99
+ const publicKey = "invalid-public-key";
100
+ const mockDeserializedTx = { addSignature: jest.fn() } as any;
101
+ const mockBufferSignature = Buffer.from("mock-signature");
102
+ const error = new Error("Invalid public key");
103
+
104
+ (deserializeTransaction as jest.Mock).mockReturnValue(mockDeserializedTx);
105
+ (deserializeSignature as jest.Mock).mockReturnValue(mockBufferSignature);
106
+ (PublicKey.fromString as jest.Mock).mockImplementation(() => {
107
+ throw error;
108
+ });
109
+
110
+ expect(() => combine(tx, signature, publicKey)).toThrow(error);
111
+ expect(deserializeTransaction).toHaveBeenCalledTimes(1);
112
+ expect(deserializeTransaction).toHaveBeenCalledWith(tx);
113
+ expect(deserializeSignature).toHaveBeenCalledTimes(1);
114
+ expect(deserializeSignature).toHaveBeenCalledWith(signature);
115
+ expect(PublicKey.fromString).toHaveBeenCalledTimes(1);
116
+ expect(PublicKey.fromString).toHaveBeenCalledWith(publicKey);
117
+ expect(serializeTransaction).not.toHaveBeenCalled();
118
+ });
119
+ });
@@ -0,0 +1,14 @@
1
+ import invariant from "invariant";
2
+ import { PublicKey } from "@hashgraph/sdk";
3
+ import { deserializeSignature, deserializeTransaction, serializeTransaction } from "./utils";
4
+
5
+ export function combine(tx: string, signature: string, publicKey?: string): string {
6
+ invariant(publicKey, "hedera: public key is required to combine the transaction");
7
+
8
+ const hederaTransaction = deserializeTransaction(tx);
9
+ const bufferSignature = deserializeSignature(signature);
10
+ const bufferPublicKey = PublicKey.fromString(publicKey);
11
+ hederaTransaction.addSignature(bufferPublicKey, bufferSignature);
12
+
13
+ return serializeTransaction(hederaTransaction);
14
+ }