@ledgerhq/coin-stacks 0.1.1-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 (296) hide show
  1. package/.eslintrc.js +20 -0
  2. package/.turbo/turbo-build.log +4 -0
  3. package/.unimportedrc.json +31 -0
  4. package/CHANGELOG.md +11 -0
  5. package/LICENSE.txt +21 -0
  6. package/jest.config.js +8 -0
  7. package/lib/bridge/broadcast.d.ts +4 -0
  8. package/lib/bridge/broadcast.d.ts.map +1 -0
  9. package/lib/bridge/broadcast.js +28 -0
  10. package/lib/bridge/broadcast.js.map +1 -0
  11. package/lib/bridge/buildOptimisticOperation.d.ts +4 -0
  12. package/lib/bridge/buildOptimisticOperation.d.ts.map +1 -0
  13. package/lib/bridge/buildOptimisticOperation.js +34 -0
  14. package/lib/bridge/buildOptimisticOperation.js.map +1 -0
  15. package/lib/bridge/createTransaction.d.ts +4 -0
  16. package/lib/bridge/createTransaction.d.ts.map +1 -0
  17. package/lib/bridge/createTransaction.js +18 -0
  18. package/lib/bridge/createTransaction.js.map +1 -0
  19. package/lib/bridge/deviceTransactionConfig.d.ts +22 -0
  20. package/lib/bridge/deviceTransactionConfig.d.ts.map +1 -0
  21. package/lib/bridge/deviceTransactionConfig.js +34 -0
  22. package/lib/bridge/deviceTransactionConfig.js.map +1 -0
  23. package/lib/bridge/estimateMaxSpendable.d.ts +4 -0
  24. package/lib/bridge/estimateMaxSpendable.d.ts.map +1 -0
  25. package/lib/bridge/estimateMaxSpendable.js +46 -0
  26. package/lib/bridge/estimateMaxSpendable.js.map +1 -0
  27. package/lib/bridge/getTransactionStatus.d.ts +4 -0
  28. package/lib/bridge/getTransactionStatus.d.ts.map +1 -0
  29. package/lib/bridge/getTransactionStatus.js +60 -0
  30. package/lib/bridge/getTransactionStatus.js.map +1 -0
  31. package/lib/bridge/index.d.ts +11 -0
  32. package/lib/bridge/index.d.ts.map +1 -0
  33. package/lib/bridge/index.js +56 -0
  34. package/lib/bridge/index.js.map +1 -0
  35. package/lib/bridge/prepareTransaction.d.ts +4 -0
  36. package/lib/bridge/prepareTransaction.d.ts.map +1 -0
  37. package/lib/bridge/prepareTransaction.js +56 -0
  38. package/lib/bridge/prepareTransaction.js.map +1 -0
  39. package/lib/bridge/signOperation.d.ts +5 -0
  40. package/lib/bridge/signOperation.d.ts.map +1 -0
  41. package/lib/bridge/signOperation.js +85 -0
  42. package/lib/bridge/signOperation.js.map +1 -0
  43. package/lib/bridge/synchronization.d.ts +5 -0
  44. package/lib/bridge/synchronization.d.ts.map +1 -0
  45. package/lib/bridge/synchronization.js +62 -0
  46. package/lib/bridge/synchronization.js.map +1 -0
  47. package/lib/bridge/transaction.d.ts +14 -0
  48. package/lib/bridge/transaction.d.ts.map +1 -0
  49. package/lib/bridge/transaction.js +46 -0
  50. package/lib/bridge/transaction.js.map +1 -0
  51. package/lib/bridge/utils/addresses.d.ts +13 -0
  52. package/lib/bridge/utils/addresses.d.ts.map +1 -0
  53. package/lib/bridge/utils/addresses.js +15 -0
  54. package/lib/bridge/utils/addresses.js.map +1 -0
  55. package/lib/bridge/utils/misc.d.ts +15 -0
  56. package/lib/bridge/utils/misc.d.ts.map +1 -0
  57. package/lib/bridge/utils/misc.js +186 -0
  58. package/lib/bridge/utils/misc.js.map +1 -0
  59. package/lib/bridge/utils/misc.unit.test.d.ts +2 -0
  60. package/lib/bridge/utils/misc.unit.test.d.ts.map +1 -0
  61. package/lib/bridge/utils/misc.unit.test.js +230 -0
  62. package/lib/bridge/utils/misc.unit.test.js.map +1 -0
  63. package/lib/config.d.ts +14 -0
  64. package/lib/config.d.ts.map +1 -0
  65. package/lib/config.js +16 -0
  66. package/lib/config.js.map +1 -0
  67. package/lib/errors.d.ts +4 -0
  68. package/lib/errors.d.ts.map +1 -0
  69. package/lib/errors.js +6 -0
  70. package/lib/errors.js.map +1 -0
  71. package/lib/index.d.ts +4 -0
  72. package/lib/index.d.ts.map +1 -0
  73. package/lib/index.js +21 -0
  74. package/lib/index.js.map +1 -0
  75. package/lib/network/api.d.ts +11 -0
  76. package/lib/network/api.d.ts.map +1 -0
  77. package/lib/network/api.js +139 -0
  78. package/lib/network/api.js.map +1 -0
  79. package/lib/network/api.types.d.ts +168 -0
  80. package/lib/network/api.types.d.ts.map +1 -0
  81. package/lib/network/api.types.js +9 -0
  82. package/lib/network/api.types.js.map +1 -0
  83. package/lib/network/index.d.ts +3 -0
  84. package/lib/network/index.d.ts.map +1 -0
  85. package/lib/network/index.js +19 -0
  86. package/lib/network/index.js.map +1 -0
  87. package/lib/signer/getAddress.d.ts +6 -0
  88. package/lib/signer/getAddress.d.ts.map +1 -0
  89. package/lib/signer/getAddress.js +31 -0
  90. package/lib/signer/getAddress.js.map +1 -0
  91. package/lib/signer/index.d.ts +4 -0
  92. package/lib/signer/index.d.ts.map +1 -0
  93. package/lib/signer/index.js +23 -0
  94. package/lib/signer/index.js.map +1 -0
  95. package/lib/signer/signMessage.d.ts +12 -0
  96. package/lib/signer/signMessage.d.ts.map +1 -0
  97. package/lib/signer/signMessage.js +31 -0
  98. package/lib/signer/signMessage.js.map +1 -0
  99. package/lib/test/bot-deviceActions.d.ts +4 -0
  100. package/lib/test/bot-deviceActions.d.ts.map +1 -0
  101. package/lib/test/bot-deviceActions.js +48 -0
  102. package/lib/test/bot-deviceActions.js.map +1 -0
  103. package/lib/test/bot-specs.d.ts +7 -0
  104. package/lib/test/bot-specs.d.ts.map +1 -0
  105. package/lib/test/bot-specs.js +73 -0
  106. package/lib/test/bot-specs.js.map +1 -0
  107. package/lib/test/bridgeDatasetTest.d.ts +4 -0
  108. package/lib/test/bridgeDatasetTest.d.ts.map +1 -0
  109. package/lib/test/bridgeDatasetTest.js +129 -0
  110. package/lib/test/bridgeDatasetTest.js.map +1 -0
  111. package/lib/test/cli.d.ts +15 -0
  112. package/lib/test/cli.d.ts.map +1 -0
  113. package/lib/test/cli.js +27 -0
  114. package/lib/test/cli.js.map +1 -0
  115. package/lib/test/index.d.ts +6 -0
  116. package/lib/test/index.d.ts.map +1 -0
  117. package/lib/test/index.js +26 -0
  118. package/lib/test/index.js.map +1 -0
  119. package/lib/types/bridge.d.ts +35 -0
  120. package/lib/types/bridge.d.ts.map +1 -0
  121. package/lib/types/bridge.js +3 -0
  122. package/lib/types/bridge.js.map +1 -0
  123. package/lib/types/index.d.ts +3 -0
  124. package/lib/types/index.d.ts.map +1 -0
  125. package/lib/types/index.js +19 -0
  126. package/lib/types/index.js.map +1 -0
  127. package/lib/types/signer.d.ts +14 -0
  128. package/lib/types/signer.d.ts.map +1 -0
  129. package/lib/types/signer.js +3 -0
  130. package/lib/types/signer.js.map +1 -0
  131. package/lib/utils.d.ts +8 -0
  132. package/lib/utils.d.ts.map +1 -0
  133. package/lib/utils.js +26 -0
  134. package/lib/utils.js.map +1 -0
  135. package/lib-es/bridge/broadcast.d.ts +4 -0
  136. package/lib-es/bridge/broadcast.d.ts.map +1 -0
  137. package/lib-es/bridge/broadcast.js +21 -0
  138. package/lib-es/bridge/broadcast.js.map +1 -0
  139. package/lib-es/bridge/buildOptimisticOperation.d.ts +4 -0
  140. package/lib-es/bridge/buildOptimisticOperation.d.ts.map +1 -0
  141. package/lib-es/bridge/buildOptimisticOperation.js +27 -0
  142. package/lib-es/bridge/buildOptimisticOperation.js.map +1 -0
  143. package/lib-es/bridge/createTransaction.d.ts +4 -0
  144. package/lib-es/bridge/createTransaction.d.ts.map +1 -0
  145. package/lib-es/bridge/createTransaction.js +11 -0
  146. package/lib-es/bridge/createTransaction.js.map +1 -0
  147. package/lib-es/bridge/deviceTransactionConfig.d.ts +22 -0
  148. package/lib-es/bridge/deviceTransactionConfig.d.ts.map +1 -0
  149. package/lib-es/bridge/deviceTransactionConfig.js +32 -0
  150. package/lib-es/bridge/deviceTransactionConfig.js.map +1 -0
  151. package/lib-es/bridge/estimateMaxSpendable.d.ts +4 -0
  152. package/lib-es/bridge/estimateMaxSpendable.d.ts.map +1 -0
  153. package/lib-es/bridge/estimateMaxSpendable.js +39 -0
  154. package/lib-es/bridge/estimateMaxSpendable.js.map +1 -0
  155. package/lib-es/bridge/getTransactionStatus.d.ts +4 -0
  156. package/lib-es/bridge/getTransactionStatus.d.ts.map +1 -0
  157. package/lib-es/bridge/getTransactionStatus.js +53 -0
  158. package/lib-es/bridge/getTransactionStatus.js.map +1 -0
  159. package/lib-es/bridge/index.d.ts +11 -0
  160. package/lib-es/bridge/index.d.ts.map +1 -0
  161. package/lib-es/bridge/index.js +48 -0
  162. package/lib-es/bridge/index.js.map +1 -0
  163. package/lib-es/bridge/prepareTransaction.d.ts +4 -0
  164. package/lib-es/bridge/prepareTransaction.d.ts.map +1 -0
  165. package/lib-es/bridge/prepareTransaction.js +49 -0
  166. package/lib-es/bridge/prepareTransaction.js.map +1 -0
  167. package/lib-es/bridge/signOperation.d.ts +5 -0
  168. package/lib-es/bridge/signOperation.d.ts.map +1 -0
  169. package/lib-es/bridge/signOperation.js +78 -0
  170. package/lib-es/bridge/signOperation.js.map +1 -0
  171. package/lib-es/bridge/synchronization.d.ts +5 -0
  172. package/lib-es/bridge/synchronization.d.ts.map +1 -0
  173. package/lib-es/bridge/synchronization.js +55 -0
  174. package/lib-es/bridge/synchronization.js.map +1 -0
  175. package/lib-es/bridge/transaction.d.ts +14 -0
  176. package/lib-es/bridge/transaction.d.ts.map +1 -0
  177. package/lib-es/bridge/transaction.js +38 -0
  178. package/lib-es/bridge/transaction.js.map +1 -0
  179. package/lib-es/bridge/utils/addresses.d.ts +13 -0
  180. package/lib-es/bridge/utils/addresses.d.ts.map +1 -0
  181. package/lib-es/bridge/utils/addresses.js +11 -0
  182. package/lib-es/bridge/utils/addresses.js.map +1 -0
  183. package/lib-es/bridge/utils/misc.d.ts +15 -0
  184. package/lib-es/bridge/utils/misc.d.ts.map +1 -0
  185. package/lib-es/bridge/utils/misc.js +176 -0
  186. package/lib-es/bridge/utils/misc.js.map +1 -0
  187. package/lib-es/bridge/utils/misc.unit.test.d.ts +2 -0
  188. package/lib-es/bridge/utils/misc.unit.test.d.ts.map +1 -0
  189. package/lib-es/bridge/utils/misc.unit.test.js +228 -0
  190. package/lib-es/bridge/utils/misc.unit.test.js.map +1 -0
  191. package/lib-es/config.d.ts +14 -0
  192. package/lib-es/config.d.ts.map +1 -0
  193. package/lib-es/config.js +11 -0
  194. package/lib-es/config.js.map +1 -0
  195. package/lib-es/errors.d.ts +4 -0
  196. package/lib-es/errors.d.ts.map +1 -0
  197. package/lib-es/errors.js +3 -0
  198. package/lib-es/errors.js.map +1 -0
  199. package/lib-es/index.d.ts +4 -0
  200. package/lib-es/index.d.ts.map +1 -0
  201. package/lib-es/index.js +3 -0
  202. package/lib-es/index.js.map +1 -0
  203. package/lib-es/network/api.d.ts +11 -0
  204. package/lib-es/network/api.d.ts.map +1 -0
  205. package/lib-es/network/api.js +124 -0
  206. package/lib-es/network/api.js.map +1 -0
  207. package/lib-es/network/api.types.d.ts +168 -0
  208. package/lib-es/network/api.types.d.ts.map +1 -0
  209. package/lib-es/network/api.types.js +6 -0
  210. package/lib-es/network/api.types.js.map +1 -0
  211. package/lib-es/network/index.d.ts +3 -0
  212. package/lib-es/network/index.d.ts.map +1 -0
  213. package/lib-es/network/index.js +3 -0
  214. package/lib-es/network/index.js.map +1 -0
  215. package/lib-es/signer/getAddress.d.ts +6 -0
  216. package/lib-es/signer/getAddress.d.ts.map +1 -0
  217. package/lib-es/signer/getAddress.js +29 -0
  218. package/lib-es/signer/getAddress.js.map +1 -0
  219. package/lib-es/signer/index.d.ts +4 -0
  220. package/lib-es/signer/index.d.ts.map +1 -0
  221. package/lib-es/signer/index.js +4 -0
  222. package/lib-es/signer/index.js.map +1 -0
  223. package/lib-es/signer/signMessage.d.ts +12 -0
  224. package/lib-es/signer/signMessage.d.ts.map +1 -0
  225. package/lib-es/signer/signMessage.js +27 -0
  226. package/lib-es/signer/signMessage.js.map +1 -0
  227. package/lib-es/test/bot-deviceActions.d.ts +4 -0
  228. package/lib-es/test/bot-deviceActions.d.ts.map +1 -0
  229. package/lib-es/test/bot-deviceActions.js +45 -0
  230. package/lib-es/test/bot-deviceActions.js.map +1 -0
  231. package/lib-es/test/bot-specs.d.ts +7 -0
  232. package/lib-es/test/bot-specs.d.ts.map +1 -0
  233. package/lib-es/test/bot-specs.js +68 -0
  234. package/lib-es/test/bot-specs.js.map +1 -0
  235. package/lib-es/test/bridgeDatasetTest.d.ts +4 -0
  236. package/lib-es/test/bridgeDatasetTest.d.ts.map +1 -0
  237. package/lib-es/test/bridgeDatasetTest.js +126 -0
  238. package/lib-es/test/bridgeDatasetTest.js.map +1 -0
  239. package/lib-es/test/cli.d.ts +15 -0
  240. package/lib-es/test/cli.d.ts.map +1 -0
  241. package/lib-es/test/cli.js +21 -0
  242. package/lib-es/test/cli.js.map +1 -0
  243. package/lib-es/test/index.d.ts +6 -0
  244. package/lib-es/test/index.d.ts.map +1 -0
  245. package/lib-es/test/index.js +6 -0
  246. package/lib-es/test/index.js.map +1 -0
  247. package/lib-es/types/bridge.d.ts +35 -0
  248. package/lib-es/types/bridge.d.ts.map +1 -0
  249. package/lib-es/types/bridge.js +2 -0
  250. package/lib-es/types/bridge.js.map +1 -0
  251. package/lib-es/types/index.d.ts +3 -0
  252. package/lib-es/types/index.d.ts.map +1 -0
  253. package/lib-es/types/index.js +3 -0
  254. package/lib-es/types/index.js.map +1 -0
  255. package/lib-es/types/signer.d.ts +14 -0
  256. package/lib-es/types/signer.d.ts.map +1 -0
  257. package/lib-es/types/signer.js +2 -0
  258. package/lib-es/types/signer.js.map +1 -0
  259. package/lib-es/utils.d.ts +8 -0
  260. package/lib-es/utils.d.ts.map +1 -0
  261. package/lib-es/utils.js +17 -0
  262. package/lib-es/utils.js.map +1 -0
  263. package/package.json +136 -0
  264. package/src/bridge/broadcast.ts +18 -0
  265. package/src/bridge/buildOptimisticOperation.ts +34 -0
  266. package/src/bridge/createTransaction.ts +13 -0
  267. package/src/bridge/deviceTransactionConfig.ts +57 -0
  268. package/src/bridge/estimateMaxSpendable.ts +50 -0
  269. package/src/bridge/getTransactionStatus.ts +56 -0
  270. package/src/bridge/index.ts +64 -0
  271. package/src/bridge/prepareTransaction.ts +60 -0
  272. package/src/bridge/signOperation.ts +91 -0
  273. package/src/bridge/synchronization.ts +55 -0
  274. package/src/bridge/transaction.ts +75 -0
  275. package/src/bridge/utils/addresses.ts +23 -0
  276. package/src/bridge/utils/misc.ts +274 -0
  277. package/src/bridge/utils/misc.unit.test.ts +237 -0
  278. package/src/config.ts +26 -0
  279. package/src/errors.ts +3 -0
  280. package/src/index.ts +4 -0
  281. package/src/network/api.ts +173 -0
  282. package/src/network/api.types.ts +180 -0
  283. package/src/network/index.ts +2 -0
  284. package/src/signer/getAddress.ts +27 -0
  285. package/src/signer/index.ts +4 -0
  286. package/src/signer/signMessage.ts +26 -0
  287. package/src/test/bot-deviceActions.ts +47 -0
  288. package/src/test/bot-specs.ts +82 -0
  289. package/src/test/bridgeDatasetTest.ts +134 -0
  290. package/src/test/cli.ts +38 -0
  291. package/src/test/index.ts +5 -0
  292. package/src/types/bridge.ts +49 -0
  293. package/src/types/index.ts +2 -0
  294. package/src/types/signer.ts +16 -0
  295. package/src/utils.ts +24 -0
  296. package/tsconfig.json +14 -0
@@ -0,0 +1,237 @@
1
+ import { mapPendingTxToOps, mapTxToOps } from "./misc";
2
+ import { encodeAccountId } from "@ledgerhq/coin-framework/account/index";
3
+ import { TransactionResponse, fetchFullTxs } from "../../network/index";
4
+ import { Operation } from "@ledgerhq/types-live";
5
+
6
+ const Address = "SP26AZ1JSFZQ82VH5W2NJSB2QW15EW5YKT6WMD69J";
7
+
8
+ const mempoolTransfer = {
9
+ tx_id: "0x628369d2c9b49f0ec95531fe1e6a39141573117f3dd047fca65ff5e4058fbc55",
10
+ nonce: 32,
11
+ fee_rate: "487",
12
+ sender_address: "SPNX9YY3T4GR4XDSNRVWB2MDQVCTJMP3BGT7VCZA",
13
+ sponsored: false,
14
+ post_condition_mode: "deny",
15
+ post_conditions: [],
16
+ anchor_mode: "any",
17
+ tx_status: "pending",
18
+ receipt_time: 1714554733,
19
+ receipt_time_iso: "2024-05-01T09:12:13.000Z",
20
+ tx_type: "token_transfer",
21
+ token_transfer: {
22
+ recipient_address: "SP26AZ1JSFZQ82VH5W2NJSB2QW15EW5YKT6WMD69J",
23
+ amount: "9523",
24
+ memo: "0x00000000000000000000000000000000000000000000000000000000000000000000",
25
+ },
26
+ };
27
+
28
+ const sendManyTransfer = {
29
+ tx: {
30
+ tx_id: "0x68bdba90cdbd4e2e112fd008c8c396bd4ca365e482dc68fe25c7aeb5d8eb4c3f",
31
+ nonce: 18,
32
+ fee_rate: "500000",
33
+ sender_address: "SP26AZ1JSFZQ82VH5W2NJSB2QW15EW5YKT6WMD69J",
34
+ sponsored: false,
35
+ post_condition_mode: "deny",
36
+ post_conditions: [
37
+ {
38
+ type: "stx",
39
+ condition_code: "sent_equal_to",
40
+ amount: "345000",
41
+ principal: {
42
+ type_id: "principal_standard",
43
+ address: "SP26AZ1JSFZQ82VH5W2NJSB2QW15EW5YKT6WMD69J",
44
+ },
45
+ },
46
+ ],
47
+ anchor_mode: "any",
48
+ is_unanchored: false,
49
+ block_hash: "0xc8dd294972d86b09d4226fe99f8bfcdf2c55a7280ca87b7dc8b0fd119a7059f1",
50
+ parent_block_hash: "0xc8f2c105e37544ce27a3a470651d950c6e8fe5f6c072aef653e7ea1fbd97a429",
51
+ block_height: 137791,
52
+ block_time: 1706802438,
53
+ block_time_iso: "2024-02-01T15:47:18.000Z",
54
+ burn_block_time: 1706802438,
55
+ burn_block_time_iso: "2024-02-01T15:47:18.000Z",
56
+ parent_burn_block_time: 1706801557,
57
+ parent_burn_block_time_iso: "2024-02-01T15:32:37.000Z",
58
+ canonical: true,
59
+ tx_index: 121,
60
+ tx_status: "success",
61
+ tx_result: {
62
+ hex: "0x0703",
63
+ repr: "(ok true)",
64
+ },
65
+ microblock_hash: "0x",
66
+ microblock_sequence: 2147483647,
67
+ microblock_canonical: true,
68
+ event_count: 6,
69
+ events: [],
70
+ execution_cost_read_count: 6,
71
+ execution_cost_read_length: 737,
72
+ execution_cost_runtime: 151010,
73
+ execution_cost_write_count: 3,
74
+ execution_cost_write_length: 3,
75
+ tx_type: "contract_call",
76
+ contract_call: {
77
+ contract_id: "SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.send-many-memo",
78
+ function_name: "send-many",
79
+ function_signature: "",
80
+ function_args: [
81
+ {
82
+ hex: "0x0b000000030c00000003046d656d6f020000000333333302746f05162bd4fbc3d1218275b9ae37c58a8dbed9a952c35c047573747801000000000000000000000000000027100c00000003046d656d6f020000000334343402746f051601a0369ffa2faa8fe74faada53e2e3d215b4d42a047573747801000000000000000000000000000088b80c00000003046d656d6f020000000335353502746f051660cc6b74d6d317918d0a7717069da56d775d817e047573747801000000000000000000000000000493e0",
83
+ repr: "(list (tuple (memo 0x333333) (to 'SPNX9YY3T4GR4XDSNRVWB2MDQVCTJMP3BGT7VCZA) (ustx u10000)) (tuple (memo 0x343434) (to 'SPT0DMZZ8QTN3Z79YNDMMZ2WF91BD6M59S9Z10Y) (ustx u35000)) (tuple (memo 0x353535) (to 'SP1GCRTVMTV9HF4CD19VHE1MXMNPQEQC1FT6YWF5Y) (ustx u300000)))",
84
+ name: "",
85
+ type: "(list 3 (tuple (memo (buff 3)) (to principal) (ustx uint)))",
86
+ },
87
+ ],
88
+ },
89
+ },
90
+ stx_sent: "845000",
91
+ stx_received: "0",
92
+ events: {
93
+ stx: {
94
+ transfer: 3,
95
+ mint: 0,
96
+ burn: 0,
97
+ },
98
+ ft: {
99
+ transfer: 0,
100
+ mint: 0,
101
+ burn: 0,
102
+ },
103
+ nft: {
104
+ transfer: 0,
105
+ mint: 0,
106
+ burn: 0,
107
+ },
108
+ },
109
+ };
110
+
111
+ const basicTransfer = {
112
+ tx: {
113
+ tx_id: "0x84254bb1e50b9e4f1dd48161ba5e87dff4ba8718117e8c364769067614dfb99a",
114
+ nonce: 22,
115
+ fee_rate: "125250",
116
+ sender_address: "SP26AZ1JSFZQ82VH5W2NJSB2QW15EW5YKT6WMD69J",
117
+ sponsored: false,
118
+ post_condition_mode: "deny",
119
+ post_conditions: [],
120
+ anchor_mode: "any",
121
+ is_unanchored: false,
122
+ block_hash: "0xd3272fbbc264eec8f8b7857541d7a5e6c043b54dd799274544a72d185dc34f1d",
123
+ parent_block_hash: "0x7bc3a3adae166f4a876697ad4c4f924d29dcea2c84607fc7765c0ed0855c3e90",
124
+ block_height: 151738,
125
+ block_time: 1716831904,
126
+ block_time_iso: "2024-05-27T17:45:04.000Z",
127
+ burn_block_time: 1716831849,
128
+ burn_block_time_iso: "2024-05-27T17:44:09.000Z",
129
+ parent_burn_block_time: 1716831377,
130
+ parent_burn_block_time_iso: "2024-05-27T17:36:17.000Z",
131
+ canonical: true,
132
+ tx_index: 29,
133
+ tx_status: "success",
134
+ tx_result: {
135
+ hex: "0x0703",
136
+ repr: "(ok true)",
137
+ },
138
+ microblock_hash: "0x",
139
+ microblock_sequence: 2147483647,
140
+ microblock_canonical: true,
141
+ event_count: 1,
142
+ events: [],
143
+ execution_cost_read_count: 0,
144
+ execution_cost_read_length: 0,
145
+ execution_cost_runtime: 0,
146
+ execution_cost_write_count: 0,
147
+ execution_cost_write_length: 0,
148
+ tx_type: "token_transfer",
149
+ token_transfer: {
150
+ recipient_address: "SPNX9YY3T4GR4XDSNRVWB2MDQVCTJMP3BGT7VCZA",
151
+ amount: "827695",
152
+ memo: "0x31323333333334000000000000000000000000000000000000000000000000000000",
153
+ },
154
+ },
155
+ stx_sent: "952945",
156
+ stx_received: "0",
157
+ events: {
158
+ stx: {
159
+ transfer: 1,
160
+ mint: 0,
161
+ burn: 0,
162
+ },
163
+ ft: {
164
+ transfer: 0,
165
+ mint: 0,
166
+ burn: 0,
167
+ },
168
+ nft: {
169
+ transfer: 0,
170
+ mint: 0,
171
+ burn: 0,
172
+ },
173
+ },
174
+ };
175
+
176
+ describe("operation building from raw", () => {
177
+ test("map raw transaction to op", async () => {
178
+ const accountId = encodeAccountId({
179
+ type: "js",
180
+ version: "2",
181
+ currencyId: "stacks",
182
+ xpubOrAddress: "",
183
+ derivationMode: "stacks_wallet",
184
+ });
185
+
186
+ // Contains operations for txn of type token_transfer
187
+ const operations = ([sendManyTransfer, basicTransfer] as any).flatMap(
188
+ mapTxToOps(accountId, Address),
189
+ );
190
+
191
+ expect(operations.length).toBe(2);
192
+
193
+ const opSenMany = operations[0];
194
+ const opBasic = operations[1];
195
+
196
+ expect(opSenMany.type).toBe("OUT");
197
+ expect(opSenMany.internalOperations).toHaveLength(3);
198
+ expect(opSenMany.senders).toHaveLength(1);
199
+ expect(opSenMany.recipients).toHaveLength(0);
200
+
201
+ expect(opBasic.type).toBe("OUT");
202
+ expect(opBasic.internalOperations).toBeUndefined();
203
+ expect(opBasic.senders).toHaveLength(1);
204
+ expect(opBasic.recipients).toHaveLength(1);
205
+ });
206
+ });
207
+
208
+ test("convert raw transactions to live operations", async () => {
209
+ const rawTxs: TransactionResponse[] = await fetchFullTxs(Address);
210
+ const operations: Operation[] = rawTxs.flatMap(mapTxToOps("dummyAccountID", Address));
211
+
212
+ expect(operations).toBeDefined();
213
+ expect(operations.length).toBeGreaterThan(0);
214
+ });
215
+
216
+ describe("operation building from mempool raw", () => {
217
+ test("map raw mempool transaction to op", async () => {
218
+ const accountId = encodeAccountId({
219
+ type: "js",
220
+ version: "2",
221
+ currencyId: "stacks",
222
+ xpubOrAddress: "",
223
+ derivationMode: "stacks_wallet",
224
+ });
225
+
226
+ const address = "SPNX9YY3T4GR4XDSNRVWB2MDQVCTJMP3BGT7VCZA";
227
+
228
+ // Contains operations for txn of type token_transfer
229
+ const operations = [mempoolTransfer].map(mapPendingTxToOps(accountId, address)).flat();
230
+
231
+ expect(operations.length).toBe(1);
232
+ expect(operations[0].type).toBe("OUT");
233
+ expect(operations[0].internalOperations).toBeUndefined();
234
+ expect(operations[0].senders).toHaveLength(1);
235
+ expect(operations[0].recipients).toHaveLength(1);
236
+ });
237
+ });
package/src/config.ts ADDED
@@ -0,0 +1,26 @@
1
+ import { CurrencyConfig } from "@ledgerhq/coin-framework/config";
2
+
3
+ export type StacksCoinConfig = () => CurrencyConfig & {
4
+ config_currency_stacks: {
5
+ type: "object";
6
+ default: {
7
+ status: {
8
+ type: "active";
9
+ };
10
+ };
11
+ };
12
+ };
13
+
14
+ let coinConfig: StacksCoinConfig | undefined;
15
+
16
+ export const setCoinConfig = (config: StacksCoinConfig): void => {
17
+ coinConfig = config;
18
+ };
19
+
20
+ export const getCoinConfig = (): ReturnType<StacksCoinConfig> => {
21
+ if (!coinConfig?.()) {
22
+ throw new Error("Stacks module config not set");
23
+ }
24
+
25
+ return coinConfig();
26
+ };
package/src/errors.ts ADDED
@@ -0,0 +1,3 @@
1
+ import { createCustomErrorClass } from "@ledgerhq/errors";
2
+
3
+ export const StacksMemoTooLong = createCustomErrorClass("StacksMemoTooLong");
package/src/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ export * from "./types";
2
+
3
+ export { createBridges } from "./bridge/index";
4
+ export type { StacksCoinConfig } from "./config";
@@ -0,0 +1,173 @@
1
+ import { AxiosRequestConfig, AxiosResponse } from "axios";
2
+
3
+ import { getEnv } from "@ledgerhq/live-env";
4
+ import network from "@ledgerhq/live-network/network";
5
+ import {
6
+ BalanceResponse,
7
+ BroadcastTransactionRequest,
8
+ BroadcastTransactionResponse,
9
+ EstimatedFeesRequest,
10
+ EstimatedFeesResponse,
11
+ GetNonceResponse,
12
+ MempoolResponse,
13
+ MempoolTransaction,
14
+ NetworkStatusResponse,
15
+ TransactionResponse,
16
+ TransactionsResponse,
17
+ } from "./api.types";
18
+
19
+ const getStacksURL = (path?: string): string => {
20
+ const baseUrl = getEnv("API_STACKS_ENDPOINT");
21
+ if (!baseUrl) throw new Error("API base URL not available");
22
+
23
+ return `${baseUrl}${path ? path : ""}`;
24
+ };
25
+
26
+ const fetch = async <T>(path: string) => {
27
+ const url = getStacksURL(path);
28
+
29
+ // We force data to this way as network func is not using the correct param type. Changing that func will generate errors in other implementations
30
+ const opts: AxiosRequestConfig = {
31
+ method: "GET",
32
+ url,
33
+ };
34
+ const rawResponse = await network(opts);
35
+
36
+ // We force data to this way as network func is not using the correct param type. Changing that func will generate errors in other implementations
37
+ const { data } = rawResponse as AxiosResponse<T>;
38
+
39
+ return data;
40
+ };
41
+
42
+ const send = async <T>(path: string, data: Record<string, any>) => {
43
+ const url = getStacksURL(path);
44
+
45
+ const opts: AxiosRequestConfig = {
46
+ method: "POST",
47
+ url,
48
+ data: JSON.stringify(data),
49
+ headers: { "Content-Type": "application/json" },
50
+ };
51
+
52
+ const rawResponse = await network(opts);
53
+
54
+ // We force data to this way as network func is not using generics. Changing that func will generate errors in other implementations
55
+ const { data: responseData } = rawResponse as AxiosResponse<T>;
56
+
57
+ return responseData;
58
+ };
59
+
60
+ const sendRaw = async <T>(path: string, data: Buffer) => {
61
+ const url = getStacksURL(path);
62
+
63
+ const opts: AxiosRequestConfig = {
64
+ method: "POST",
65
+ url,
66
+ data,
67
+ headers: { "Content-Type": "application/octet-stream" },
68
+ };
69
+
70
+ const rawResponse = await network(opts);
71
+
72
+ // We force data to this way as network func is not using generics. Changing that func will generate errors in other implementations
73
+ const { data: responseData } = rawResponse as AxiosResponse<T>;
74
+
75
+ return responseData;
76
+ };
77
+
78
+ export const fetchBalances = async (addr: string): Promise<BalanceResponse> => {
79
+ const data = await fetch<BalanceResponse>(`/extended/v1/address/${addr}/stx`);
80
+ return data; // TODO Validate if the response fits this interface
81
+ };
82
+
83
+ export const fetchEstimatedFees = async (
84
+ request: EstimatedFeesRequest,
85
+ ): Promise<EstimatedFeesResponse> => {
86
+ const feeRate = await send<EstimatedFeesResponse>(`/v2/fees/transfer`, request);
87
+ return feeRate; // TODO Validate if the response fits this interface
88
+ };
89
+
90
+ export const fetchBlockHeight = async (): Promise<NetworkStatusResponse> => {
91
+ const data = await fetch<NetworkStatusResponse>("/extended");
92
+ return data as NetworkStatusResponse; // TODO Validate if the response fits this interface
93
+ };
94
+
95
+ export const fetchTxs = async (addr: string, offset = 0): Promise<TransactionsResponse> => {
96
+ const limit = 50;
97
+ try {
98
+ const response = await fetch<TransactionsResponse>(
99
+ `/extended/v2/addresses/${addr}/transactions?offset=${offset}&limit=${limit}`,
100
+ );
101
+ return response; // TODO Validate if the response fits this interface
102
+ } catch (e) {
103
+ return { limit, offset, total: 0, results: [] };
104
+ }
105
+ };
106
+
107
+ export const fetchFullTxs = async (addr: string): Promise<TransactionResponse[]> => {
108
+ let qty,
109
+ offset = 0;
110
+ let txs: TransactionResponse[] = [];
111
+
112
+ do {
113
+ const { results, total, limit } = await fetchTxs(addr, offset);
114
+ txs = txs.concat(
115
+ results.filter(t => {
116
+ if (t.tx?.tx_type === "token_transfer") {
117
+ return true;
118
+ }
119
+
120
+ if (
121
+ t.tx?.tx_type === "contract_call" &&
122
+ t.tx?.contract_call?.function_name === "send-many"
123
+ ) {
124
+ return true;
125
+ }
126
+
127
+ return false;
128
+ }),
129
+ );
130
+
131
+ offset += limit;
132
+ qty = total;
133
+ } while (offset < qty);
134
+
135
+ return txs; // TODO Validate if the response fits this interface
136
+ };
137
+
138
+ export const broadcastTx = async (
139
+ message: BroadcastTransactionRequest,
140
+ ): Promise<BroadcastTransactionResponse> => {
141
+ let response = await sendRaw<BroadcastTransactionResponse>(`/v2/transactions`, message);
142
+
143
+ if (response != "") response = `0x${response}`;
144
+ return response; // TODO Validate if the response fits this interface
145
+ };
146
+
147
+ export const fetchMempoolTxs = async (addr: string, offset = 0): Promise<MempoolResponse> => {
148
+ const response = await fetch<MempoolResponse>(
149
+ `/extended/v1/tx/mempool?sender_address=${addr}&offset=${offset}`,
150
+ );
151
+ return response; // TODO Validate if the response fits this interface
152
+ };
153
+
154
+ export const fetchFullMempoolTxs = async (addr: string): Promise<MempoolTransaction[]> => {
155
+ let qty,
156
+ offset = 0;
157
+ let txs: MempoolTransaction[] = [];
158
+
159
+ do {
160
+ const { results, total, limit } = await fetchMempoolTxs(addr, offset);
161
+ txs = txs.concat(results);
162
+
163
+ offset += limit;
164
+ qty = total;
165
+ } while (offset < qty);
166
+
167
+ return txs; // TODO Validate if the response fits this interface
168
+ };
169
+
170
+ export const fetchNonce = async (addr: string): Promise<GetNonceResponse> => {
171
+ const response = await fetch<GetNonceResponse>(`/extended/v1/address/${addr}/nonces`);
172
+ return response; // TODO Validate if the response fits this interface
173
+ };
@@ -0,0 +1,180 @@
1
+ import { StacksMainnet, StacksTestnet } from "@stacks/network";
2
+
3
+ export const StacksNetwork = {
4
+ mainnet: new StacksMainnet(),
5
+ testnet: new StacksTestnet(),
6
+ };
7
+
8
+ export interface EstimatedFeesRequest {
9
+ to: string;
10
+ from: string;
11
+ }
12
+
13
+ export type EstimatedFeesResponse = number;
14
+
15
+ export interface TransactionsResponse {
16
+ limit: number;
17
+ offset: number;
18
+ total: number;
19
+ results: TransactionResponse[];
20
+ }
21
+
22
+ export interface TransactionResponse {
23
+ tx: {
24
+ tx_id: string;
25
+ nonce: number;
26
+ fee_rate: string;
27
+ sender_address: string;
28
+ sponsored: boolean;
29
+ post_condition_mode: string;
30
+ post_conditions: Array<{
31
+ type: string;
32
+ condition_code: string;
33
+ amount: string;
34
+ principal: {
35
+ type_id: string;
36
+ address: string;
37
+ };
38
+ }>;
39
+ anchor_mode: string;
40
+ is_unanchored: boolean;
41
+ block_hash: string;
42
+ parent_block_hash: string;
43
+ block_height: number;
44
+ block_time: number;
45
+ block_time_iso: string;
46
+ burn_block_time: number;
47
+ burn_block_time_iso: string;
48
+ parent_burn_block_time: number;
49
+ parent_burn_block_time_iso: string;
50
+ canonical: boolean;
51
+ tx_index: number;
52
+ tx_status: string;
53
+ tx_result: {
54
+ hex: string;
55
+ repr: string;
56
+ };
57
+ microblock_hash: string;
58
+ microblock_sequence: number;
59
+ microblock_canonical: boolean;
60
+ event_count: number;
61
+ events: Array<any>;
62
+ execution_cost_read_count: number;
63
+ execution_cost_read_length: number;
64
+ execution_cost_runtime: number;
65
+ execution_cost_write_count: number;
66
+ execution_cost_write_length: number;
67
+ tx_type: "token_transfer" | "contract_call";
68
+ token_transfer?: {
69
+ recipient_address: string;
70
+ amount: string;
71
+ memo: string;
72
+ };
73
+ smart_contract?: {
74
+ clarity_version: number;
75
+ contract_id: string;
76
+ source_code: string;
77
+ };
78
+ contract_call?: {
79
+ contract_id: string;
80
+ function_name: string;
81
+ function_signature: string;
82
+ function_args: Array<{
83
+ hex: string;
84
+ repr: string;
85
+ name: string;
86
+ type: string;
87
+ }>;
88
+ };
89
+ };
90
+ stx_sent: string;
91
+ stx_received: string;
92
+ events: {
93
+ stx: {
94
+ transfer: number;
95
+ mint: number;
96
+ burn: number;
97
+ };
98
+ ft: {
99
+ transfer: number;
100
+ mint: number;
101
+ burn: number;
102
+ };
103
+ nft: {
104
+ transfer: number;
105
+ mint: number;
106
+ burn: number;
107
+ };
108
+ };
109
+ }
110
+
111
+ export interface DecodedSendManyFunctionArgsCV {
112
+ type: string;
113
+ value: Array<{
114
+ type: string;
115
+ value: {
116
+ memo?: {
117
+ type: string;
118
+ value: string;
119
+ };
120
+ to: {
121
+ type: string;
122
+ value: string;
123
+ };
124
+ ustx: {
125
+ type: string;
126
+ value: string;
127
+ };
128
+ };
129
+ }>;
130
+ }
131
+
132
+ export interface MempoolTransaction {
133
+ tx_id: string;
134
+ nonce: number;
135
+ tx_status: string;
136
+ tx_type: string;
137
+ receipt_time: number;
138
+ receipt_time_iso: string;
139
+ fee_rate: string;
140
+ sender_address: string;
141
+ sponsored: boolean;
142
+ token_transfer: {
143
+ recipient_address: string;
144
+ amount: string;
145
+ memo: string;
146
+ };
147
+ }
148
+
149
+ export interface MempoolResponse {
150
+ limit: number;
151
+ offset: number;
152
+ total: number;
153
+ results: MempoolTransaction[];
154
+ }
155
+
156
+ export interface GetNonceResponse {
157
+ last_mempool_tx_nonce: number;
158
+ last_executed_tx_nonce: number;
159
+ possible_next_nonce: number;
160
+ detected_missing_nonces: number[];
161
+ }
162
+
163
+ export interface BalanceResponse {
164
+ balance: string;
165
+ }
166
+
167
+ export interface NetworkStatusResponse {
168
+ server_version: string;
169
+ status: string;
170
+ chain_tip: BlockIdentifier;
171
+ }
172
+
173
+ export type BroadcastTransactionRequest = Buffer;
174
+
175
+ export type BroadcastTransactionResponse = string;
176
+
177
+ interface BlockIdentifier {
178
+ block_height: number;
179
+ block_hash: string;
180
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./api";
2
+ export * from "./api.types";
@@ -0,0 +1,27 @@
1
+ import { GetAddressFn } from "@ledgerhq/coin-framework/bridge/getAddressWrapper";
2
+ import { GetAddressOptions } from "@ledgerhq/coin-framework/derivation";
3
+ import { SignerContext } from "@ledgerhq/coin-framework/signer";
4
+ import { AddressVersion } from "@stacks/transactions/dist";
5
+ import { StacksSigner } from "../types";
6
+ import { getPath, throwIfError } from "../utils";
7
+
8
+ const resolver = (signerContext: SignerContext<StacksSigner>): GetAddressFn => {
9
+ return async (deviceId: string, { path, verify }: GetAddressOptions) => {
10
+ const r = await signerContext(deviceId, async signer => {
11
+ const r = verify
12
+ ? await signer.showAddressAndPubKey(getPath(path), AddressVersion.MainnetSingleSig)
13
+ : await signer.getAddressAndPubKey(getPath(path), AddressVersion.MainnetSingleSig);
14
+ return r;
15
+ });
16
+
17
+ throwIfError(r);
18
+
19
+ return {
20
+ path,
21
+ address: r.address,
22
+ publicKey: r.publicKey.toString("hex"),
23
+ };
24
+ };
25
+ };
26
+
27
+ export default resolver;
@@ -0,0 +1,4 @@
1
+ import resolver from "./getAddress";
2
+
3
+ export * from "./signMessage";
4
+ export default resolver;
@@ -0,0 +1,26 @@
1
+ import { getBufferFromString, getPath, throwIfError } from "../utils";
2
+
3
+ import { SignerContext } from "@ledgerhq/coin-framework/signer";
4
+ import { Account, AnyMessage } from "@ledgerhq/types-live";
5
+ import { StacksSigner } from "../types";
6
+
7
+ export const signMessage =
8
+ (signerContext: SignerContext<StacksSigner>) =>
9
+ async (deviceId: string, account: Account, { message }: AnyMessage) => {
10
+ if (!message) throw new Error(`Message cannot be empty`);
11
+ if (typeof message !== "string") throw new Error(`Message must be string`);
12
+
13
+ const r = await signerContext(deviceId, signer =>
14
+ signer.sign(getPath(account.freshAddressPath), getBufferFromString(message)),
15
+ );
16
+ throwIfError(r);
17
+
18
+ return {
19
+ rsv: {
20
+ r: r.signatureCompact.slice(0, 32).toString("hex"),
21
+ s: r.signatureCompact.slice(32, 64).toString("hex"),
22
+ v: parseInt(r.signatureCompact.slice(64, 65).toString("hex"), 16),
23
+ },
24
+ signature: `0x${r.signatureVRS.toString("hex")}`,
25
+ };
26
+ };