@ledgerhq/coin-multiversx 0.2.0-nightly.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 (378) hide show
  1. package/.eslintrc.js +23 -0
  2. package/.turbo/turbo-build.log +4 -0
  3. package/.unimportedrc.json +31 -0
  4. package/CHANGELOG.md +392 -0
  5. package/LICENSE.txt +21 -0
  6. package/jest.config.js +8 -0
  7. package/lib/api/apiCalls.d.ts +22 -0
  8. package/lib/api/apiCalls.d.ts.map +1 -0
  9. package/lib/api/apiCalls.js +153 -0
  10. package/lib/api/apiCalls.js.map +1 -0
  11. package/lib/api/dtos/multiversx-account.d.ts +9 -0
  12. package/lib/api/dtos/multiversx-account.d.ts.map +1 -0
  13. package/lib/api/dtos/multiversx-account.js +17 -0
  14. package/lib/api/dtos/multiversx-account.js.map +1 -0
  15. package/lib/api/index.d.ts +2 -0
  16. package/lib/api/index.d.ts.map +1 -0
  17. package/lib/api/index.js +16 -0
  18. package/lib/api/index.js.map +1 -0
  19. package/lib/api/sdk.d.ts +29 -0
  20. package/lib/api/sdk.d.ts.map +1 -0
  21. package/lib/api/sdk.js +281 -0
  22. package/lib/api/sdk.js.map +1 -0
  23. package/lib/bridge/js.d.ts +11 -0
  24. package/lib/bridge/js.d.ts.map +1 -0
  25. package/lib/bridge/js.js +62 -0
  26. package/lib/bridge/js.js.map +1 -0
  27. package/lib/bridge.integration.test.d.ts +4 -0
  28. package/lib/bridge.integration.test.d.ts.map +1 -0
  29. package/lib/bridge.integration.test.js +142 -0
  30. package/lib/bridge.integration.test.js.map +1 -0
  31. package/lib/broadcast.d.ts +9 -0
  32. package/lib/broadcast.d.ts.map +1 -0
  33. package/lib/broadcast.js +16 -0
  34. package/lib/broadcast.js.map +1 -0
  35. package/lib/buildOptimisticOperation.d.ts +4 -0
  36. package/lib/buildOptimisticOperation.d.ts.map +1 -0
  37. package/lib/buildOptimisticOperation.js +100 -0
  38. package/lib/buildOptimisticOperation.js.map +1 -0
  39. package/lib/buildOptimisticOperation.test.d.ts +2 -0
  40. package/lib/buildOptimisticOperation.test.d.ts.map +1 -0
  41. package/lib/buildOptimisticOperation.test.js +78 -0
  42. package/lib/buildOptimisticOperation.test.js.map +1 -0
  43. package/lib/buildSubAccounts.d.ts +11 -0
  44. package/lib/buildSubAccounts.d.ts.map +1 -0
  45. package/lib/buildSubAccounts.js +117 -0
  46. package/lib/buildSubAccounts.js.map +1 -0
  47. package/lib/buildTransaction.d.ts +19 -0
  48. package/lib/buildTransaction.d.ts.map +1 -0
  49. package/lib/buildTransaction.js +49 -0
  50. package/lib/buildTransaction.js.map +1 -0
  51. package/lib/buildTransaction.unit.test.d.ts +2 -0
  52. package/lib/buildTransaction.unit.test.d.ts.map +1 -0
  53. package/lib/buildTransaction.unit.test.js +47 -0
  54. package/lib/buildTransaction.unit.test.js.map +1 -0
  55. package/lib/cli-transaction.d.ts +16 -0
  56. package/lib/cli-transaction.d.ts.map +1 -0
  57. package/lib/cli-transaction.js +35 -0
  58. package/lib/cli-transaction.js.map +1 -0
  59. package/lib/config.d.ts +14 -0
  60. package/lib/config.d.ts.map +1 -0
  61. package/lib/config.js +16 -0
  62. package/lib/config.js.map +1 -0
  63. package/lib/constants.d.ts +21 -0
  64. package/lib/constants.d.ts.map +1 -0
  65. package/lib/constants.js +27 -0
  66. package/lib/constants.js.map +1 -0
  67. package/lib/createTransaction.d.ts +9 -0
  68. package/lib/createTransaction.d.ts.map +1 -0
  69. package/lib/createTransaction.js +26 -0
  70. package/lib/createTransaction.js.map +1 -0
  71. package/lib/datasets/multiversx1.d.ts +3 -0
  72. package/lib/datasets/multiversx1.d.ts.map +1 -0
  73. package/lib/datasets/multiversx1.js +21 -0
  74. package/lib/datasets/multiversx1.js.map +1 -0
  75. package/lib/deviceTransactionConfig.d.ts +10 -0
  76. package/lib/deviceTransactionConfig.d.ts.map +1 -0
  77. package/lib/deviceTransactionConfig.js +60 -0
  78. package/lib/deviceTransactionConfig.js.map +1 -0
  79. package/lib/encode.d.ts +11 -0
  80. package/lib/encode.d.ts.map +1 -0
  81. package/lib/encode.js +39 -0
  82. package/lib/encode.js.map +1 -0
  83. package/lib/errors.d.ts +16 -0
  84. package/lib/errors.d.ts.map +1 -0
  85. package/lib/errors.js +10 -0
  86. package/lib/errors.js.map +1 -0
  87. package/lib/estimateMaxSpendable.d.ts +10 -0
  88. package/lib/estimateMaxSpendable.d.ts.map +1 -0
  89. package/lib/estimateMaxSpendable.js +35 -0
  90. package/lib/estimateMaxSpendable.js.map +1 -0
  91. package/lib/formatters.d.ts +11 -0
  92. package/lib/formatters.d.ts.map +1 -0
  93. package/lib/formatters.js +65 -0
  94. package/lib/formatters.js.map +1 -0
  95. package/lib/getTransactionStatus.d.ts +5 -0
  96. package/lib/getTransactionStatus.d.ts.map +1 -0
  97. package/lib/getTransactionStatus.js +107 -0
  98. package/lib/getTransactionStatus.js.map +1 -0
  99. package/lib/helpers/denominate.d.ts +9 -0
  100. package/lib/helpers/denominate.d.ts.map +1 -0
  101. package/lib/helpers/denominate.js +75 -0
  102. package/lib/helpers/denominate.js.map +1 -0
  103. package/lib/helpers/handleTransactionStatus.d.ts +7 -0
  104. package/lib/helpers/handleTransactionStatus.d.ts.map +1 -0
  105. package/lib/helpers/handleTransactionStatus.js +18 -0
  106. package/lib/helpers/handleTransactionStatus.js.map +1 -0
  107. package/lib/helpers/hasMinimumDelegableBalance.d.ts +3 -0
  108. package/lib/helpers/hasMinimumDelegableBalance.d.ts.map +1 -0
  109. package/lib/helpers/hasMinimumDelegableBalance.js +7 -0
  110. package/lib/helpers/hasMinimumDelegableBalance.js.map +1 -0
  111. package/lib/helpers/randomizeProviders.d.ts +7 -0
  112. package/lib/helpers/randomizeProviders.d.ts.map +1 -0
  113. package/lib/helpers/randomizeProviders.js +12 -0
  114. package/lib/helpers/randomizeProviders.js.map +1 -0
  115. package/lib/hw-getAddress.d.ts +6 -0
  116. package/lib/hw-getAddress.d.ts.map +1 -0
  117. package/lib/hw-getAddress.js +14 -0
  118. package/lib/hw-getAddress.js.map +1 -0
  119. package/lib/logic.d.ts +15 -0
  120. package/lib/logic.d.ts.map +1 -0
  121. package/lib/logic.js +77 -0
  122. package/lib/logic.js.map +1 -0
  123. package/lib/preload.d.ts +11 -0
  124. package/lib/preload.d.ts.map +1 -0
  125. package/lib/preload.js +94 -0
  126. package/lib/preload.js.map +1 -0
  127. package/lib/prepareTransaction.d.ts +10 -0
  128. package/lib/prepareTransaction.d.ts.map +1 -0
  129. package/lib/prepareTransaction.js +72 -0
  130. package/lib/prepareTransaction.js.map +1 -0
  131. package/lib/reconciliation.d.ts +3 -0
  132. package/lib/reconciliation.d.ts.map +1 -0
  133. package/lib/reconciliation.js +56 -0
  134. package/lib/reconciliation.js.map +1 -0
  135. package/lib/serialization.d.ts +9 -0
  136. package/lib/serialization.d.ts.map +1 -0
  137. package/lib/serialization.js +65 -0
  138. package/lib/serialization.js.map +1 -0
  139. package/lib/signOperation.d.ts +10 -0
  140. package/lib/signOperation.d.ts.map +1 -0
  141. package/lib/signOperation.js +65 -0
  142. package/lib/signOperation.js.map +1 -0
  143. package/lib/signer.d.ts +16 -0
  144. package/lib/signer.d.ts.map +1 -0
  145. package/lib/signer.js +3 -0
  146. package/lib/signer.js.map +1 -0
  147. package/lib/specs.d.ts +7 -0
  148. package/lib/specs.d.ts.map +1 -0
  149. package/lib/specs.js +286 -0
  150. package/lib/specs.js.map +1 -0
  151. package/lib/speculos-deviceActions.d.ts +16 -0
  152. package/lib/speculos-deviceActions.d.ts.map +1 -0
  153. package/lib/speculos-deviceActions.js +250 -0
  154. package/lib/speculos-deviceActions.js.map +1 -0
  155. package/lib/synchronisation.d.ts +5 -0
  156. package/lib/synchronisation.d.ts.map +1 -0
  157. package/lib/synchronisation.js +69 -0
  158. package/lib/synchronisation.js.map +1 -0
  159. package/lib/transaction.d.ts +15 -0
  160. package/lib/transaction.d.ts.map +1 -0
  161. package/lib/transaction.js +62 -0
  162. package/lib/transaction.js.map +1 -0
  163. package/lib/types.d.ts +188 -0
  164. package/lib/types.d.ts.map +1 -0
  165. package/lib/types.js +17 -0
  166. package/lib/types.js.map +1 -0
  167. package/lib/utils/binary.utils.d.ts +5 -0
  168. package/lib/utils/binary.utils.d.ts.map +1 -0
  169. package/lib/utils/binary.utils.js +16 -0
  170. package/lib/utils/binary.utils.js.map +1 -0
  171. package/lib-es/api/apiCalls.d.ts +22 -0
  172. package/lib-es/api/apiCalls.d.ts.map +1 -0
  173. package/lib-es/api/apiCalls.js +147 -0
  174. package/lib-es/api/apiCalls.js.map +1 -0
  175. package/lib-es/api/dtos/multiversx-account.d.ts +9 -0
  176. package/lib-es/api/dtos/multiversx-account.d.ts.map +1 -0
  177. package/lib-es/api/dtos/multiversx-account.js +13 -0
  178. package/lib-es/api/dtos/multiversx-account.js.map +1 -0
  179. package/lib-es/api/index.d.ts +2 -0
  180. package/lib-es/api/index.d.ts.map +1 -0
  181. package/lib-es/api/index.js +2 -0
  182. package/lib-es/api/index.js.map +1 -0
  183. package/lib-es/api/sdk.d.ts +29 -0
  184. package/lib-es/api/sdk.d.ts.map +1 -0
  185. package/lib-es/api/sdk.js +264 -0
  186. package/lib-es/api/sdk.js.map +1 -0
  187. package/lib-es/bridge/js.d.ts +11 -0
  188. package/lib-es/bridge/js.d.ts.map +1 -0
  189. package/lib-es/bridge/js.js +53 -0
  190. package/lib-es/bridge/js.js.map +1 -0
  191. package/lib-es/bridge.integration.test.d.ts +4 -0
  192. package/lib-es/bridge.integration.test.d.ts.map +1 -0
  193. package/lib-es/bridge.integration.test.js +139 -0
  194. package/lib-es/bridge.integration.test.js.map +1 -0
  195. package/lib-es/broadcast.d.ts +9 -0
  196. package/lib-es/broadcast.d.ts.map +1 -0
  197. package/lib-es/broadcast.js +12 -0
  198. package/lib-es/broadcast.js.map +1 -0
  199. package/lib-es/buildOptimisticOperation.d.ts +4 -0
  200. package/lib-es/buildOptimisticOperation.d.ts.map +1 -0
  201. package/lib-es/buildOptimisticOperation.js +93 -0
  202. package/lib-es/buildOptimisticOperation.js.map +1 -0
  203. package/lib-es/buildOptimisticOperation.test.d.ts +2 -0
  204. package/lib-es/buildOptimisticOperation.test.d.ts.map +1 -0
  205. package/lib-es/buildOptimisticOperation.test.js +73 -0
  206. package/lib-es/buildOptimisticOperation.test.js.map +1 -0
  207. package/lib-es/buildSubAccounts.d.ts +11 -0
  208. package/lib-es/buildSubAccounts.d.ts.map +1 -0
  209. package/lib-es/buildSubAccounts.js +112 -0
  210. package/lib-es/buildSubAccounts.js.map +1 -0
  211. package/lib-es/buildTransaction.d.ts +19 -0
  212. package/lib-es/buildTransaction.d.ts.map +1 -0
  213. package/lib-es/buildTransaction.js +44 -0
  214. package/lib-es/buildTransaction.js.map +1 -0
  215. package/lib-es/buildTransaction.unit.test.d.ts +2 -0
  216. package/lib-es/buildTransaction.unit.test.d.ts.map +1 -0
  217. package/lib-es/buildTransaction.unit.test.js +42 -0
  218. package/lib-es/buildTransaction.unit.test.js.map +1 -0
  219. package/lib-es/cli-transaction.d.ts +16 -0
  220. package/lib-es/cli-transaction.d.ts.map +1 -0
  221. package/lib-es/cli-transaction.js +29 -0
  222. package/lib-es/cli-transaction.js.map +1 -0
  223. package/lib-es/config.d.ts +14 -0
  224. package/lib-es/config.d.ts.map +1 -0
  225. package/lib-es/config.js +11 -0
  226. package/lib-es/config.js.map +1 -0
  227. package/lib-es/constants.d.ts +21 -0
  228. package/lib-es/constants.d.ts.map +1 -0
  229. package/lib-es/constants.js +21 -0
  230. package/lib-es/constants.js.map +1 -0
  231. package/lib-es/createTransaction.d.ts +9 -0
  232. package/lib-es/createTransaction.d.ts.map +1 -0
  233. package/lib-es/createTransaction.js +19 -0
  234. package/lib-es/createTransaction.js.map +1 -0
  235. package/lib-es/datasets/multiversx1.d.ts +3 -0
  236. package/lib-es/datasets/multiversx1.d.ts.map +1 -0
  237. package/lib-es/datasets/multiversx1.js +18 -0
  238. package/lib-es/datasets/multiversx1.js.map +1 -0
  239. package/lib-es/deviceTransactionConfig.d.ts +10 -0
  240. package/lib-es/deviceTransactionConfig.d.ts.map +1 -0
  241. package/lib-es/deviceTransactionConfig.js +55 -0
  242. package/lib-es/deviceTransactionConfig.js.map +1 -0
  243. package/lib-es/encode.d.ts +11 -0
  244. package/lib-es/encode.d.ts.map +1 -0
  245. package/lib-es/encode.js +35 -0
  246. package/lib-es/encode.js.map +1 -0
  247. package/lib-es/errors.d.ts +16 -0
  248. package/lib-es/errors.d.ts.map +1 -0
  249. package/lib-es/errors.js +7 -0
  250. package/lib-es/errors.js.map +1 -0
  251. package/lib-es/estimateMaxSpendable.d.ts +10 -0
  252. package/lib-es/estimateMaxSpendable.d.ts.map +1 -0
  253. package/lib-es/estimateMaxSpendable.js +31 -0
  254. package/lib-es/estimateMaxSpendable.js.map +1 -0
  255. package/lib-es/formatters.d.ts +11 -0
  256. package/lib-es/formatters.d.ts.map +1 -0
  257. package/lib-es/formatters.js +60 -0
  258. package/lib-es/formatters.js.map +1 -0
  259. package/lib-es/getTransactionStatus.d.ts +5 -0
  260. package/lib-es/getTransactionStatus.d.ts.map +1 -0
  261. package/lib-es/getTransactionStatus.js +100 -0
  262. package/lib-es/getTransactionStatus.js.map +1 -0
  263. package/lib-es/helpers/denominate.d.ts +9 -0
  264. package/lib-es/helpers/denominate.d.ts.map +1 -0
  265. package/lib-es/helpers/denominate.js +71 -0
  266. package/lib-es/helpers/denominate.js.map +1 -0
  267. package/lib-es/helpers/handleTransactionStatus.d.ts +7 -0
  268. package/lib-es/helpers/handleTransactionStatus.d.ts.map +1 -0
  269. package/lib-es/helpers/handleTransactionStatus.js +14 -0
  270. package/lib-es/helpers/handleTransactionStatus.js.map +1 -0
  271. package/lib-es/helpers/hasMinimumDelegableBalance.d.ts +3 -0
  272. package/lib-es/helpers/hasMinimumDelegableBalance.d.ts.map +1 -0
  273. package/lib-es/helpers/hasMinimumDelegableBalance.js +3 -0
  274. package/lib-es/helpers/hasMinimumDelegableBalance.js.map +1 -0
  275. package/lib-es/helpers/randomizeProviders.d.ts +7 -0
  276. package/lib-es/helpers/randomizeProviders.d.ts.map +1 -0
  277. package/lib-es/helpers/randomizeProviders.js +8 -0
  278. package/lib-es/helpers/randomizeProviders.js.map +1 -0
  279. package/lib-es/hw-getAddress.d.ts +6 -0
  280. package/lib-es/hw-getAddress.d.ts.map +1 -0
  281. package/lib-es/hw-getAddress.js +12 -0
  282. package/lib-es/hw-getAddress.js.map +1 -0
  283. package/lib-es/logic.d.ts +15 -0
  284. package/lib-es/logic.d.ts.map +1 -0
  285. package/lib-es/logic.js +65 -0
  286. package/lib-es/logic.js.map +1 -0
  287. package/lib-es/preload.d.ts +11 -0
  288. package/lib-es/preload.d.ts.map +1 -0
  289. package/lib-es/preload.js +85 -0
  290. package/lib-es/preload.js.map +1 -0
  291. package/lib-es/prepareTransaction.d.ts +10 -0
  292. package/lib-es/prepareTransaction.d.ts.map +1 -0
  293. package/lib-es/prepareTransaction.js +68 -0
  294. package/lib-es/prepareTransaction.js.map +1 -0
  295. package/lib-es/reconciliation.d.ts +3 -0
  296. package/lib-es/reconciliation.d.ts.map +1 -0
  297. package/lib-es/reconciliation.js +52 -0
  298. package/lib-es/reconciliation.js.map +1 -0
  299. package/lib-es/serialization.d.ts +9 -0
  300. package/lib-es/serialization.d.ts.map +1 -0
  301. package/lib-es/serialization.js +53 -0
  302. package/lib-es/serialization.js.map +1 -0
  303. package/lib-es/signOperation.d.ts +10 -0
  304. package/lib-es/signOperation.d.ts.map +1 -0
  305. package/lib-es/signOperation.js +61 -0
  306. package/lib-es/signOperation.js.map +1 -0
  307. package/lib-es/signer.d.ts +16 -0
  308. package/lib-es/signer.d.ts.map +1 -0
  309. package/lib-es/signer.js +2 -0
  310. package/lib-es/signer.js.map +1 -0
  311. package/lib-es/specs.d.ts +7 -0
  312. package/lib-es/specs.d.ts.map +1 -0
  313. package/lib-es/specs.js +281 -0
  314. package/lib-es/specs.js.map +1 -0
  315. package/lib-es/speculos-deviceActions.d.ts +16 -0
  316. package/lib-es/speculos-deviceActions.d.ts.map +1 -0
  317. package/lib-es/speculos-deviceActions.js +244 -0
  318. package/lib-es/speculos-deviceActions.js.map +1 -0
  319. package/lib-es/synchronisation.d.ts +5 -0
  320. package/lib-es/synchronisation.d.ts.map +1 -0
  321. package/lib-es/synchronisation.js +62 -0
  322. package/lib-es/synchronisation.js.map +1 -0
  323. package/lib-es/transaction.d.ts +15 -0
  324. package/lib-es/transaction.d.ts.map +1 -0
  325. package/lib-es/transaction.js +56 -0
  326. package/lib-es/transaction.js.map +1 -0
  327. package/lib-es/types.d.ts +188 -0
  328. package/lib-es/types.d.ts.map +1 -0
  329. package/lib-es/types.js +12 -0
  330. package/lib-es/types.js.map +1 -0
  331. package/lib-es/utils/binary.utils.d.ts +5 -0
  332. package/lib-es/utils/binary.utils.d.ts.map +1 -0
  333. package/lib-es/utils/binary.utils.js +12 -0
  334. package/lib-es/utils/binary.utils.js.map +1 -0
  335. package/package.json +86 -0
  336. package/src/__snapshots__/bridge.integration.test.ts.snap +181 -0
  337. package/src/api/apiCalls.ts +243 -0
  338. package/src/api/dtos/multiversx-account.ts +20 -0
  339. package/src/api/index.ts +13 -0
  340. package/src/api/sdk.ts +368 -0
  341. package/src/bridge/js.ts +77 -0
  342. package/src/bridge.integration.test.ts +147 -0
  343. package/src/broadcast.ts +16 -0
  344. package/src/buildOptimisticOperation.test.ts +88 -0
  345. package/src/buildOptimisticOperation.ts +120 -0
  346. package/src/buildSubAccounts.ts +153 -0
  347. package/src/buildTransaction.ts +67 -0
  348. package/src/buildTransaction.unit.test.ts +49 -0
  349. package/src/cli-transaction.ts +41 -0
  350. package/src/config.ts +26 -0
  351. package/src/constants.ts +24 -0
  352. package/src/createTransaction.ts +21 -0
  353. package/src/datasets/multiversx1.ts +19 -0
  354. package/src/deviceTransactionConfig.ts +74 -0
  355. package/src/encode.ts +46 -0
  356. package/src/errors.ts +19 -0
  357. package/src/estimateMaxSpendable.ts +43 -0
  358. package/src/formatters.ts +76 -0
  359. package/src/getTransactionStatus.ts +151 -0
  360. package/src/helpers/denominate.ts +95 -0
  361. package/src/helpers/handleTransactionStatus.ts +26 -0
  362. package/src/helpers/hasMinimumDelegableBalance.ts +6 -0
  363. package/src/helpers/randomizeProviders.ts +20 -0
  364. package/src/hw-getAddress.ts +19 -0
  365. package/src/logic.ts +83 -0
  366. package/src/preload.ts +95 -0
  367. package/src/prepareTransaction.ts +78 -0
  368. package/src/reconciliation.ts +64 -0
  369. package/src/serialization.ts +72 -0
  370. package/src/signOperation.ts +99 -0
  371. package/src/signer.ts +21 -0
  372. package/src/specs.ts +387 -0
  373. package/src/speculos-deviceActions.ts +269 -0
  374. package/src/synchronisation.ts +74 -0
  375. package/src/transaction.ts +76 -0
  376. package/src/types.ts +235 -0
  377. package/src/utils/binary.utils.ts +13 -0
  378. package/tsconfig.json +13 -0
package/src/specs.ts ADDED
@@ -0,0 +1,387 @@
1
+ import type {
2
+ MultiversXAccount,
3
+ MultiversXOperation,
4
+ MultiversXOperationRaw,
5
+ Transaction,
6
+ } from "./types";
7
+ import invariant from "invariant";
8
+ import { parseCurrencyUnit } from "@ledgerhq/coin-framework/currencies";
9
+ import { getCryptoCurrencyById } from "@ledgerhq/cryptoassets/currencies";
10
+ import { botTest, pickSiblings, genericTestDestination } from "@ledgerhq/coin-framework/bot/specs";
11
+ import type { AppSpec, TransactionTestInput } from "@ledgerhq/coin-framework/bot/types";
12
+ import { toOperationRaw } from "@ledgerhq/coin-framework/serialization";
13
+ import { DeviceModelId } from "@ledgerhq/devices";
14
+ import expect from "expect";
15
+ import {
16
+ acceptDelegateTransaction,
17
+ acceptEsdtTransferTransaction,
18
+ acceptMoveBalanceTransaction,
19
+ acceptUndelegateTransaction,
20
+ acceptWithdrawTransaction,
21
+ } from "./speculos-deviceActions";
22
+ import BigNumber from "bignumber.js";
23
+ import { MIN_DELEGATION_AMOUNT } from "./constants";
24
+ import { SubAccount } from "@ledgerhq/types-live";
25
+ import sample from "lodash/sample";
26
+
27
+ const currency = getCryptoCurrencyById("elrond");
28
+ const minimalAmount = parseCurrencyUnit(currency.units[0], "0.001");
29
+ const maxAccounts = 6;
30
+
31
+ const MULTIVERSX_MIN_ACTIVATION_SAFE = new BigNumber(10000);
32
+ const UNCAPPED_PROVIDER = "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqlhllllsr0pd0j";
33
+
34
+ function expectCorrectBalanceChange(input: TransactionTestInput<Transaction>) {
35
+ const { account, operation, accountBeforeTransaction } = input;
36
+
37
+ botTest("EGLD balance change is correct", () =>
38
+ expect(account.balance.toFixed()).toStrictEqual(
39
+ accountBeforeTransaction.balance.minus(operation.value).toFixed(),
40
+ ),
41
+ );
42
+ }
43
+
44
+ function expectCorrectEsdtBalanceChange(input: TransactionTestInput<Transaction>) {
45
+ const { account, operation, accountBeforeTransaction, transaction } = input;
46
+
47
+ const { subAccountId } = transaction;
48
+ const subAccounts = account.subAccounts ?? [];
49
+ const subAccountsBefore = accountBeforeTransaction.subAccounts ?? [];
50
+
51
+ const tokenAccount = subAccounts.find(ta => ta.id === subAccountId);
52
+ const tokenAccountBefore = subAccountsBefore.find(ta => ta.id === subAccountId);
53
+
54
+ const subOperation = operation.subOperations?.find(sa => sa.id === operation.id);
55
+
56
+ if (tokenAccount && tokenAccountBefore && subOperation) {
57
+ botTest("ESDT balance change is correct", () =>
58
+ expect(tokenAccount.balance.toFixed()).toStrictEqual(
59
+ tokenAccountBefore.balance.minus(subOperation.value).toFixed(),
60
+ ),
61
+ );
62
+ }
63
+ }
64
+
65
+ function expectCorrectOptimisticOperation(input: TransactionTestInput<Transaction>) {
66
+ const { operation, optimisticOperation, transaction } = input;
67
+
68
+ const opExpected: Partial<MultiversXOperationRaw> = toOperationRaw({
69
+ ...optimisticOperation,
70
+ }) as MultiversXOperationRaw;
71
+ delete opExpected.value;
72
+ delete opExpected.fee;
73
+ delete opExpected.date;
74
+ delete opExpected.blockHash;
75
+ delete opExpected.blockHeight;
76
+
77
+ if (operation.type !== "OUT") {
78
+ delete opExpected.senders;
79
+ delete opExpected.recipients;
80
+ delete opExpected.contract;
81
+ }
82
+
83
+ botTest("optimistic operation matches id", () =>
84
+ expect(operation.id).toStrictEqual(optimisticOperation.id),
85
+ );
86
+ botTest("optimistic operation matches hash", () =>
87
+ expect(operation.hash).toStrictEqual(optimisticOperation.hash),
88
+ );
89
+ botTest("optimistic operation matches accountId", () =>
90
+ expect(operation.accountId).toStrictEqual(optimisticOperation.accountId),
91
+ );
92
+
93
+ // On ESDT transactions the fee can decrease when the transaction is executed
94
+ if (!transaction.subAccountId) {
95
+ botTest("optimistic operation matches fee", () =>
96
+ expect(operation.fee.toFixed()).toStrictEqual(optimisticOperation.fee.toFixed()),
97
+ );
98
+ }
99
+
100
+ botTest("optimistic operation matches type", () =>
101
+ expect(operation.type).toStrictEqual(optimisticOperation.type),
102
+ );
103
+ if (operation.type === "OUT") {
104
+ botTest("optimistic operation matches contract", () =>
105
+ expect(operation.contract).toStrictEqual(optimisticOperation.contract),
106
+ );
107
+ botTest("optimistic operation matches senders", () =>
108
+ expect(operation.senders).toStrictEqual(optimisticOperation.senders),
109
+ );
110
+ botTest("optimistic operation matches recipients", () =>
111
+ expect(operation.recipients).toStrictEqual(optimisticOperation.recipients),
112
+ );
113
+ if (!transaction.subAccountId) {
114
+ botTest("optimistic operation matches value", () =>
115
+ expect(operation.value.toFixed()).toStrictEqual(optimisticOperation.value.toFixed()),
116
+ );
117
+ }
118
+ }
119
+
120
+ botTest("optimistic operation matches transactionSequenceNumber", () =>
121
+ expect(operation.transactionSequenceNumber).toStrictEqual(
122
+ optimisticOperation.transactionSequenceNumber,
123
+ ),
124
+ );
125
+ botTest("raw optimistic operation matches", () =>
126
+ expect(toOperationRaw(operation)).toMatchObject(opExpected),
127
+ );
128
+ }
129
+
130
+ function expectCorrectSpendableBalanceChange(input: TransactionTestInput<Transaction>) {
131
+ const { account, accountBeforeTransaction } = input;
132
+ const operation = input.operation as MultiversXOperation;
133
+ let value = operation.value;
134
+ if (operation.extra.amount) {
135
+ if (operation.type === "DELEGATE") {
136
+ value = value.plus(operation.extra.amount);
137
+ } else if (operation.type === "WITHDRAW_UNBONDED") {
138
+ value = value.minus(operation.extra.amount);
139
+ }
140
+ }
141
+
142
+ botTest("EGLD spendable balance change is correct", () =>
143
+ expect(account.spendableBalance.toFixed()).toStrictEqual(
144
+ accountBeforeTransaction.spendableBalance.minus(value).toFixed(),
145
+ ),
146
+ );
147
+ }
148
+
149
+ function expectCorrectBalanceFeeChange(input: TransactionTestInput<Transaction>) {
150
+ const { account, operation, accountBeforeTransaction } = input;
151
+ botTest("Only change on balance is fees", () =>
152
+ expect(account.balance.toFixed()).toStrictEqual(
153
+ accountBeforeTransaction.balance.minus(operation.fee).toFixed(),
154
+ ),
155
+ );
156
+ }
157
+
158
+ const multiversx: AppSpec<Transaction> = {
159
+ name: "MultiversX",
160
+ currency: getCryptoCurrencyById("elrond"),
161
+ appQuery: {
162
+ model: DeviceModelId.nanoS,
163
+ appName: "MultiversX",
164
+ },
165
+ genericDeviceAction: acceptMoveBalanceTransaction,
166
+ genericDeviceActionForSubAccountTransfers: acceptEsdtTransferTransaction,
167
+ testTimeout: 2 * 60 * 1000,
168
+ minViableAmount: minimalAmount,
169
+ transactionCheck: ({ maxSpendable }) => {
170
+ invariant(maxSpendable.gt(minimalAmount), "balance is too low");
171
+ },
172
+ test: input => {
173
+ expectCorrectOptimisticOperation(input);
174
+ },
175
+ mutations: [
176
+ {
177
+ name: "send 50%~",
178
+ feature: "send",
179
+ maxRun: 1,
180
+ deviceAction: acceptMoveBalanceTransaction,
181
+ transaction: ({ account, siblings, bridge }) => {
182
+ invariant(account.spendableBalance.gt(0), "balance is 0");
183
+ const sibling = pickSiblings(siblings, maxAccounts);
184
+ let amount = account.spendableBalance.div(1.9 + 0.2 * Math.random()).integerValue();
185
+
186
+ if (!sibling.used && amount.lt(MULTIVERSX_MIN_ACTIVATION_SAFE)) {
187
+ invariant(
188
+ account.spendableBalance.gt(MULTIVERSX_MIN_ACTIVATION_SAFE),
189
+ "send is too low to activate account",
190
+ );
191
+ amount = MULTIVERSX_MIN_ACTIVATION_SAFE;
192
+ }
193
+
194
+ return {
195
+ transaction: bridge.createTransaction(account),
196
+ updates: [
197
+ {
198
+ recipient: sibling.freshAddress,
199
+ },
200
+ {
201
+ amount,
202
+ },
203
+ ],
204
+ };
205
+ },
206
+ testDestination: genericTestDestination,
207
+ test: input => {
208
+ expectCorrectBalanceChange(input);
209
+ },
210
+ },
211
+ {
212
+ name: "send max",
213
+ feature: "sendMax",
214
+ maxRun: 1,
215
+ deviceAction: acceptMoveBalanceTransaction,
216
+ transaction: ({ account, siblings, bridge }) => {
217
+ invariant(account.spendableBalance.gt(0), "balance is 0");
218
+ const sibling = pickSiblings(siblings, maxAccounts);
219
+
220
+ if (!sibling.used) {
221
+ invariant(
222
+ account.spendableBalance.gt(MULTIVERSX_MIN_ACTIVATION_SAFE),
223
+ "send is too low to activate account",
224
+ );
225
+ }
226
+
227
+ return {
228
+ transaction: bridge.createTransaction(account),
229
+ updates: [
230
+ {
231
+ recipient: sibling.freshAddress,
232
+ },
233
+ {
234
+ useAllAmount: true,
235
+ },
236
+ ],
237
+ };
238
+ },
239
+ testDestination: genericTestDestination,
240
+ test: input => {
241
+ expectCorrectBalanceChange(input);
242
+ },
243
+ },
244
+ {
245
+ name: "move some ESDT",
246
+ feature: "tokens",
247
+ maxRun: 1,
248
+ deviceAction: acceptEsdtTransferTransaction,
249
+ transaction: ({ account, siblings, bridge }) => {
250
+ const esdtAccount: SubAccount | undefined = sample(
251
+ (account.subAccounts || []).filter(a => a.balance.gt(0)),
252
+ );
253
+ invariant(esdtAccount, "no esdt account");
254
+
255
+ invariant(esdtAccount?.balance.gt(0), "esdt balance is 0");
256
+
257
+ const sibling = pickSiblings(siblings, 2);
258
+ const recipient = sibling.freshAddress;
259
+
260
+ const amount = esdtAccount?.balance.times(Math.random()).integerValue();
261
+
262
+ return {
263
+ transaction: bridge.createTransaction(account),
264
+ updates: [
265
+ {
266
+ subAccountId: esdtAccount?.id,
267
+ },
268
+ {
269
+ recipient,
270
+ },
271
+ {
272
+ amount,
273
+ },
274
+ ],
275
+ };
276
+ },
277
+ test: input => {
278
+ expectCorrectEsdtBalanceChange(input);
279
+ expectCorrectBalanceFeeChange(input);
280
+ },
281
+ },
282
+ {
283
+ name: "delegate 1 EGLD",
284
+ feature: "staking",
285
+ maxRun: 1,
286
+ deviceAction: acceptDelegateTransaction,
287
+ transaction: ({ account, bridge }) => {
288
+ invariant(
289
+ account.spendableBalance.gt(MIN_DELEGATION_AMOUNT),
290
+ `spendable balance is less than minimum delegation amount`,
291
+ );
292
+
293
+ const amount = MIN_DELEGATION_AMOUNT;
294
+
295
+ return {
296
+ transaction: bridge.createTransaction(account),
297
+ updates: [
298
+ {
299
+ recipient: UNCAPPED_PROVIDER,
300
+ mode: "delegate",
301
+ amount,
302
+ },
303
+ ],
304
+ };
305
+ },
306
+ test: input => {
307
+ expectCorrectSpendableBalanceChange(input);
308
+ expectCorrectBalanceFeeChange(input);
309
+ },
310
+ },
311
+ {
312
+ name: "unDelegate 1 EGLD",
313
+ feature: "staking",
314
+ maxRun: 1,
315
+ deviceAction: acceptUndelegateTransaction,
316
+ transaction: ({ account, bridge }) => {
317
+ const delegations = (account as MultiversXAccount)?.multiversxResources?.delegations;
318
+ invariant(delegations?.length, "account doesn't have any delegations");
319
+ invariant(
320
+ delegations.some(d => new BigNumber(d.userActiveStake).gt(0)),
321
+ "no active stake for account",
322
+ );
323
+
324
+ const amount = MIN_DELEGATION_AMOUNT;
325
+
326
+ return {
327
+ transaction: bridge.createTransaction(account),
328
+ updates: [
329
+ {
330
+ recipient: UNCAPPED_PROVIDER,
331
+ mode: "unDelegate",
332
+ amount,
333
+ },
334
+ ],
335
+ };
336
+ },
337
+ test: input => {
338
+ expectCorrectSpendableBalanceChange(input);
339
+ expectCorrectBalanceFeeChange(input);
340
+ },
341
+ },
342
+ {
343
+ name: "withdraw all EGLD",
344
+ feature: "staking",
345
+ maxRun: 1,
346
+ deviceAction: acceptWithdrawTransaction,
347
+ transaction: ({ account, bridge }) => {
348
+ const delegations = (account as MultiversXAccount)?.multiversxResources?.delegations;
349
+ invariant(delegations?.length, "account doesn't have any delegations");
350
+ invariant(
351
+ // among all delegations
352
+ delegations.some(d =>
353
+ // among all undelegating amounts
354
+ d.userUndelegatedList?.some(
355
+ u =>
356
+ new BigNumber(u.amount).gt(0) && // the undelegation has a positive amount
357
+ new BigNumber(u.seconds).eq(0), // the undelegation period has ended
358
+ ),
359
+ ),
360
+ "no withdrawable stake for account",
361
+ );
362
+
363
+ return {
364
+ transaction: bridge.createTransaction(account),
365
+ updates: [
366
+ {
367
+ recipient: UNCAPPED_PROVIDER,
368
+ mode: "withdraw",
369
+ amount: new BigNumber(0),
370
+ },
371
+ ],
372
+ };
373
+ },
374
+ test: input => {
375
+ expectCorrectSpendableBalanceChange(input);
376
+ expectCorrectBalanceFeeChange(input);
377
+ },
378
+ },
379
+ // TODO
380
+ // "reDelegateRewards"
381
+ // "claimRewards"
382
+ ],
383
+ };
384
+
385
+ export default {
386
+ multiversx,
387
+ };
@@ -0,0 +1,269 @@
1
+ import BigNumber from "bignumber.js";
2
+ import type { DeviceAction } from "@ledgerhq/coin-framework/bot/types";
3
+ import type { Transaction } from "./types";
4
+ import { formatCurrencyUnit } from "@ledgerhq/coin-framework/currencies";
5
+ import {
6
+ deviceActionFlow,
7
+ formatDeviceAmount,
8
+ SpeculosButton,
9
+ } from "@ledgerhq/coin-framework/bot/specs";
10
+ import { decodeTokenAccountId } from "@ledgerhq/coin-framework/account";
11
+
12
+ export const acceptMoveBalanceTransaction: DeviceAction<Transaction, any> = deviceActionFlow({
13
+ steps: [
14
+ {
15
+ title: "Receiver",
16
+ button: SpeculosButton.RIGHT,
17
+ expectedValue: ({ transaction }) => transaction.recipient,
18
+ },
19
+ {
20
+ title: "Amount",
21
+ button: SpeculosButton.RIGHT,
22
+ expectedValue: ({ account, status }) => {
23
+ return formatDeviceAmount(account.currency, status.amount, {
24
+ postfixCode: true,
25
+ });
26
+ },
27
+ },
28
+ {
29
+ title: "Fee",
30
+ button: SpeculosButton.RIGHT,
31
+ expectedValue: ({ account, transaction }) =>
32
+ formatCurrencyUnit(account.currency.units[0], transaction.fees || new BigNumber(50000), {
33
+ showCode: true,
34
+ disableRounding: true,
35
+ joinFragmentsSeparator: " ",
36
+ }).replace(/\s+/g, " "),
37
+ },
38
+ {
39
+ title: "Data",
40
+ button: SpeculosButton.RIGHT,
41
+ },
42
+ {
43
+ title: "Sign",
44
+ button: SpeculosButton.BOTH,
45
+ final: true,
46
+ },
47
+ {
48
+ title: "Network",
49
+ button: SpeculosButton.RIGHT,
50
+ expectedValue: () => "Mainnet",
51
+ },
52
+ ],
53
+ });
54
+
55
+ export const acceptDelegateTransaction: DeviceAction<Transaction, any> = deviceActionFlow({
56
+ steps: [
57
+ {
58
+ title: "Receiver",
59
+ button: SpeculosButton.RIGHT,
60
+ expectedValue: ({ transaction }) => transaction.recipient,
61
+ },
62
+ {
63
+ title: "Amount",
64
+ button: SpeculosButton.RIGHT,
65
+ expectedValue: ({ account, transaction }) =>
66
+ formatCurrencyUnit(account.currency.units[0], transaction.amount, {
67
+ showCode: true,
68
+ disableRounding: true,
69
+ joinFragmentsSeparator: " ",
70
+ }).replace(/\s+/g, " "),
71
+ },
72
+ {
73
+ title: "Fee",
74
+ button: SpeculosButton.RIGHT,
75
+ expectedValue: ({ account, transaction }) =>
76
+ formatCurrencyUnit(account.currency.units[0], transaction.fees || new BigNumber(50000), {
77
+ showCode: true,
78
+ disableRounding: true,
79
+ joinFragmentsSeparator: " ",
80
+ }).replace(/\s+/g, " "),
81
+ },
82
+ {
83
+ title: "Data",
84
+ button: SpeculosButton.RIGHT,
85
+ expectedValue: () => "[Size: 8] delegate",
86
+ },
87
+ {
88
+ title: "Sign",
89
+ button: SpeculosButton.BOTH,
90
+ final: true,
91
+ },
92
+ {
93
+ title: "Network",
94
+ button: SpeculosButton.RIGHT,
95
+ expectedValue: () => "Mainnet",
96
+ },
97
+ ],
98
+ });
99
+
100
+ export const acceptUndelegateTransaction: DeviceAction<Transaction, any> = deviceActionFlow({
101
+ steps: [
102
+ {
103
+ title: "Receiver",
104
+ button: SpeculosButton.RIGHT,
105
+ expectedValue: ({ transaction }) => transaction.recipient,
106
+ },
107
+ {
108
+ title: "Amount",
109
+ button: SpeculosButton.RIGHT,
110
+ expectedValue: ({ account }) =>
111
+ formatCurrencyUnit(account.currency.units[0], new BigNumber(0), {
112
+ showCode: true,
113
+ disableRounding: true,
114
+ joinFragmentsSeparator: " ",
115
+ }).replace(/\s+/g, " "),
116
+ },
117
+ {
118
+ title: "Fee",
119
+ button: SpeculosButton.RIGHT,
120
+ expectedValue: ({ account, transaction }) =>
121
+ formatCurrencyUnit(account.currency.units[0], transaction.fees || new BigNumber(50000), {
122
+ showCode: true,
123
+ disableRounding: true,
124
+ joinFragmentsSeparator: " ",
125
+ }).replace(/\s+/g, " "),
126
+ },
127
+ {
128
+ title: "Data",
129
+ button: SpeculosButton.RIGHT,
130
+ },
131
+ {
132
+ title: "Sign",
133
+ button: SpeculosButton.BOTH,
134
+ final: true,
135
+ },
136
+ {
137
+ title: "Network",
138
+ button: SpeculosButton.RIGHT,
139
+ expectedValue: () => "Mainnet",
140
+ },
141
+ ],
142
+ });
143
+
144
+ export const acceptWithdrawTransaction: DeviceAction<Transaction, any> = deviceActionFlow({
145
+ steps: [
146
+ {
147
+ title: "Receiver",
148
+ button: SpeculosButton.RIGHT,
149
+ expectedValue: ({ transaction }) => transaction.recipient,
150
+ },
151
+ {
152
+ title: "Amount",
153
+ button: SpeculosButton.RIGHT,
154
+ expectedValue: ({ account }) =>
155
+ formatCurrencyUnit(account.currency.units[0], new BigNumber(0), {
156
+ showCode: true,
157
+ disableRounding: true,
158
+ joinFragmentsSeparator: " ",
159
+ }).replace(/\s+/g, " "),
160
+ },
161
+ {
162
+ title: "Fee",
163
+ button: SpeculosButton.RIGHT,
164
+ expectedValue: ({ account, transaction }) =>
165
+ formatCurrencyUnit(account.currency.units[0], transaction.fees || new BigNumber(50000), {
166
+ showCode: true,
167
+ disableRounding: true,
168
+ joinFragmentsSeparator: " ",
169
+ }).replace(/\s+/g, " "),
170
+ },
171
+ {
172
+ title: "Data",
173
+ button: SpeculosButton.RIGHT,
174
+ },
175
+ {
176
+ title: "Sign",
177
+ button: SpeculosButton.BOTH,
178
+ final: true,
179
+ },
180
+ {
181
+ title: "Network",
182
+ button: SpeculosButton.RIGHT,
183
+ expectedValue: () => "Mainnet",
184
+ },
185
+ ],
186
+ });
187
+
188
+ export const acceptEsdtTransferTransaction: DeviceAction<Transaction, any> = deviceActionFlow({
189
+ steps: [
190
+ {
191
+ title: "Token",
192
+ button: SpeculosButton.RIGHT,
193
+ expectedValue: ({ account, transaction }) => {
194
+ const { subAccounts } = account;
195
+ const { subAccountId } = transaction;
196
+ const tokenAccount = !subAccountId
197
+ ? null
198
+ : subAccounts && subAccounts.find(ta => ta.id === subAccountId);
199
+
200
+ if (!tokenAccount) {
201
+ throw new Error();
202
+ }
203
+
204
+ const { token } = decodeTokenAccountId(tokenAccount.id);
205
+
206
+ return token?.name ?? "";
207
+ },
208
+ },
209
+ {
210
+ title: "Value",
211
+ button: SpeculosButton.RIGHT,
212
+ expectedValue: ({ account, transaction }) => {
213
+ const { subAccounts } = account;
214
+ const { subAccountId } = transaction;
215
+ const tokenAccount = !subAccountId
216
+ ? null
217
+ : subAccounts && subAccounts.find(ta => ta.id === subAccountId);
218
+
219
+ if (!tokenAccount) {
220
+ throw new Error();
221
+ }
222
+
223
+ const { token } = decodeTokenAccountId(tokenAccount.id);
224
+ if (!token) {
225
+ throw new Error();
226
+ }
227
+
228
+ return formatCurrencyUnit(token.units[0], transaction.amount, {
229
+ showCode: true,
230
+ disableRounding: true,
231
+ joinFragmentsSeparator: " ",
232
+ }).replace(/\s+/g, " ");
233
+ },
234
+ },
235
+ {
236
+ title: "Receiver",
237
+ button: SpeculosButton.RIGHT,
238
+ expectedValue: ({ transaction }) => transaction.recipient,
239
+ },
240
+ {
241
+ title: "Fee",
242
+ button: SpeculosButton.RIGHT,
243
+ expectedValue: ({ account, transaction }) =>
244
+ formatCurrencyUnit(account.currency.units[0], transaction.fees || new BigNumber(50000), {
245
+ showCode: true,
246
+ disableRounding: true,
247
+ joinFragmentsSeparator: " ",
248
+ }).replace(/\s+/g, " "),
249
+ },
250
+ {
251
+ title: "Confirm transfer",
252
+ button: SpeculosButton.BOTH,
253
+ final: true,
254
+ },
255
+ {
256
+ title: "Network",
257
+ button: SpeculosButton.RIGHT,
258
+ expectedValue: () => "Mainnet",
259
+ },
260
+ ],
261
+ });
262
+
263
+ export default {
264
+ acceptMoveBalanceTransaction,
265
+ acceptEsdtTransferTransaction,
266
+ acceptDelegateTransaction,
267
+ acceptUndelegateTransaction,
268
+ acceptWithdrawTransaction,
269
+ };