@ledgerhq/coin-tezos 0.4.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (344) hide show
  1. package/.eslintrc.js +20 -0
  2. package/.turbo/turbo-build.log +4 -0
  3. package/.unimportedrc.json +39 -0
  4. package/CHANGELOG.md +23 -0
  5. package/LICENSE.txt +21 -0
  6. package/jest.config.js +6 -0
  7. package/lib/api/bakers.d.ts +14 -0
  8. package/lib/api/bakers.d.ts.map +1 -0
  9. package/lib/api/bakers.integration.test.d.ts +2 -0
  10. package/lib/api/bakers.integration.test.d.ts.map +1 -0
  11. package/lib/api/bakers.integration.test.js +61 -0
  12. package/lib/api/bakers.integration.test.js.map +1 -0
  13. package/lib/api/bakers.js +141 -0
  14. package/lib/api/bakers.js.map +1 -0
  15. package/lib/api/bakers.test.d.ts +2 -0
  16. package/lib/api/bakers.test.d.ts.map +1 -0
  17. package/lib/api/bakers.test.js +146 -0
  18. package/lib/api/bakers.test.js.map +1 -0
  19. package/lib/api/bakers.whitelist-default.d.ts +4 -0
  20. package/lib/api/bakers.whitelist-default.d.ts.map +1 -0
  21. package/lib/api/bakers.whitelist-default.js +34 -0
  22. package/lib/api/bakers.whitelist-default.js.map +1 -0
  23. package/lib/api/index.d.ts +3 -0
  24. package/lib/api/index.d.ts.map +1 -0
  25. package/lib/api/index.js +19 -0
  26. package/lib/api/index.js.map +1 -0
  27. package/lib/api/tzkt.d.ts +82 -0
  28. package/lib/api/tzkt.d.ts.map +1 -0
  29. package/lib/api/tzkt.js +74 -0
  30. package/lib/api/tzkt.js.map +1 -0
  31. package/lib/bridge/broadcast.d.ts +4 -0
  32. package/lib/bridge/broadcast.d.ts.map +1 -0
  33. package/lib/bridge/broadcast.js +23 -0
  34. package/lib/bridge/broadcast.js.map +1 -0
  35. package/lib/bridge/broadcast.test.d.ts +2 -0
  36. package/lib/bridge/broadcast.test.d.ts.map +1 -0
  37. package/lib/bridge/broadcast.test.js +37 -0
  38. package/lib/bridge/broadcast.test.js.map +1 -0
  39. package/lib/bridge/buildOptimisticOperation.d.ts +4 -0
  40. package/lib/bridge/buildOptimisticOperation.d.ts.map +1 -0
  41. package/lib/bridge/buildOptimisticOperation.js +28 -0
  42. package/lib/bridge/buildOptimisticOperation.js.map +1 -0
  43. package/lib/bridge/createTransaction.d.ts +4 -0
  44. package/lib/bridge/createTransaction.d.ts.map +1 -0
  45. package/lib/bridge/createTransaction.js +24 -0
  46. package/lib/bridge/createTransaction.js.map +1 -0
  47. package/lib/bridge/deviceTransactionConfig.d.ts +19 -0
  48. package/lib/bridge/deviceTransactionConfig.d.ts.map +1 -0
  49. package/lib/bridge/deviceTransactionConfig.js +44 -0
  50. package/lib/bridge/deviceTransactionConfig.js.map +1 -0
  51. package/lib/bridge/estimateMaxSpendable.d.ts +5 -0
  52. package/lib/bridge/estimateMaxSpendable.d.ts.map +1 -0
  53. package/lib/bridge/estimateMaxSpendable.js +28 -0
  54. package/lib/bridge/estimateMaxSpendable.js.map +1 -0
  55. package/lib/bridge/getTransactionStatus.d.ts +4 -0
  56. package/lib/bridge/getTransactionStatus.d.ts.map +1 -0
  57. package/lib/bridge/getTransactionStatus.js +113 -0
  58. package/lib/bridge/getTransactionStatus.js.map +1 -0
  59. package/lib/bridge/index.d.ts +8 -0
  60. package/lib/bridge/index.d.ts.map +1 -0
  61. package/lib/bridge/index.js +57 -0
  62. package/lib/bridge/index.js.map +1 -0
  63. package/lib/bridge/logic.d.ts +10 -0
  64. package/lib/bridge/logic.d.ts.map +1 -0
  65. package/lib/bridge/logic.js +160 -0
  66. package/lib/bridge/logic.js.map +1 -0
  67. package/lib/bridge/preload.d.ts +9 -0
  68. package/lib/bridge/preload.d.ts.map +1 -0
  69. package/lib/bridge/preload.js +32 -0
  70. package/lib/bridge/preload.js.map +1 -0
  71. package/lib/bridge/prepareTransaction.d.ts +10 -0
  72. package/lib/bridge/prepareTransaction.d.ts.map +1 -0
  73. package/lib/bridge/prepareTransaction.js +158 -0
  74. package/lib/bridge/prepareTransaction.js.map +1 -0
  75. package/lib/bridge/serialization.d.ts +7 -0
  76. package/lib/bridge/serialization.d.ts.map +1 -0
  77. package/lib/bridge/serialization.js +27 -0
  78. package/lib/bridge/serialization.js.map +1 -0
  79. package/lib/bridge/signOperation.d.ts +19 -0
  80. package/lib/bridge/signOperation.d.ts.map +1 -0
  81. package/lib/bridge/signOperation.js +129 -0
  82. package/lib/bridge/signOperation.js.map +1 -0
  83. package/lib/bridge/signOperation.test.d.ts +2 -0
  84. package/lib/bridge/signOperation.test.d.ts.map +1 -0
  85. package/lib/bridge/signOperation.test.js +223 -0
  86. package/lib/bridge/signOperation.test.js.map +1 -0
  87. package/lib/bridge/synchronization.d.ts +5 -0
  88. package/lib/bridge/synchronization.d.ts.map +1 -0
  89. package/lib/bridge/synchronization.js +108 -0
  90. package/lib/bridge/synchronization.js.map +1 -0
  91. package/lib/bridge/synchronization.test.d.ts +2 -0
  92. package/lib/bridge/synchronization.test.d.ts.map +1 -0
  93. package/lib/bridge/synchronization.test.js +33 -0
  94. package/lib/bridge/synchronization.test.js.map +1 -0
  95. package/lib/bridge/transaction.d.ts +15 -0
  96. package/lib/bridge/transaction.d.ts.map +1 -0
  97. package/lib/bridge/transaction.js +52 -0
  98. package/lib/bridge/transaction.js.map +1 -0
  99. package/lib/datasets/tezos.scanAccounts.1.d.ts +7 -0
  100. package/lib/datasets/tezos.scanAccounts.1.d.ts.map +1 -0
  101. package/lib/datasets/tezos.scanAccounts.1.js +38 -0
  102. package/lib/datasets/tezos.scanAccounts.1.js.map +1 -0
  103. package/lib/index.d.ts +3 -0
  104. package/lib/index.d.ts.map +1 -0
  105. package/lib/index.js +21 -0
  106. package/lib/index.js.map +1 -0
  107. package/lib/signer/getAddress.d.ts +6 -0
  108. package/lib/signer/getAddress.d.ts.map +1 -0
  109. package/lib/signer/getAddress.js +19 -0
  110. package/lib/signer/getAddress.js.map +1 -0
  111. package/lib/signer/index.d.ts +6 -0
  112. package/lib/signer/index.d.ts.map +1 -0
  113. package/lib/signer/index.js +11 -0
  114. package/lib/signer/index.js.map +1 -0
  115. package/lib/test/bot-deviceActions.d.ts +4 -0
  116. package/lib/test/bot-deviceActions.d.ts.map +1 -0
  117. package/lib/test/bot-deviceActions.js +74 -0
  118. package/lib/test/bot-deviceActions.js.map +1 -0
  119. package/lib/test/bot-specs.d.ts +7 -0
  120. package/lib/test/bot-specs.d.ts.map +1 -0
  121. package/lib/test/bot-specs.js +154 -0
  122. package/lib/test/bot-specs.js.map +1 -0
  123. package/lib/test/bridgeDatasetTest.d.ts +5 -0
  124. package/lib/test/bridgeDatasetTest.d.ts.map +1 -0
  125. package/lib/test/bridgeDatasetTest.js +99 -0
  126. package/lib/test/bridgeDatasetTest.js.map +1 -0
  127. package/lib/test/cli.d.ts +78 -0
  128. package/lib/test/cli.d.ts.map +1 -0
  129. package/lib/test/cli.js +97 -0
  130. package/lib/test/cli.js.map +1 -0
  131. package/lib/test/index.d.ts +2 -0
  132. package/lib/test/index.d.ts.map +1 -0
  133. package/lib/test/index.js +18 -0
  134. package/lib/test/index.js.map +1 -0
  135. package/lib/types/errors.d.ts +4 -0
  136. package/lib/types/errors.d.ts.map +1 -0
  137. package/lib/types/errors.js +6 -0
  138. package/lib/types/errors.js.map +1 -0
  139. package/lib/types/index.d.ts +4 -0
  140. package/lib/types/index.d.ts.map +1 -0
  141. package/lib/types/index.js +20 -0
  142. package/lib/types/index.js.map +1 -0
  143. package/lib/types/model.d.ts +92 -0
  144. package/lib/types/model.d.ts.map +1 -0
  145. package/lib/types/model.fixture.d.ts +5 -0
  146. package/lib/types/model.fixture.d.ts.map +1 -0
  147. package/lib/types/model.fixture.js +85 -0
  148. package/lib/types/model.fixture.js.map +1 -0
  149. package/lib/types/model.js +8 -0
  150. package/lib/types/model.js.map +1 -0
  151. package/lib/types/signer.d.ts +37 -0
  152. package/lib/types/signer.d.ts.map +1 -0
  153. package/lib/types/signer.js +3 -0
  154. package/lib/types/signer.js.map +1 -0
  155. package/lib-es/api/bakers.d.ts +14 -0
  156. package/lib-es/api/bakers.d.ts.map +1 -0
  157. package/lib-es/api/bakers.integration.test.d.ts +2 -0
  158. package/lib-es/api/bakers.integration.test.d.ts.map +1 -0
  159. package/lib-es/api/bakers.integration.test.js +56 -0
  160. package/lib-es/api/bakers.integration.test.js.map +1 -0
  161. package/lib-es/api/bakers.js +125 -0
  162. package/lib-es/api/bakers.js.map +1 -0
  163. package/lib-es/api/bakers.test.d.ts +2 -0
  164. package/lib-es/api/bakers.test.d.ts.map +1 -0
  165. package/lib-es/api/bakers.test.js +141 -0
  166. package/lib-es/api/bakers.test.js.map +1 -0
  167. package/lib-es/api/bakers.whitelist-default.d.ts +4 -0
  168. package/lib-es/api/bakers.whitelist-default.d.ts.map +1 -0
  169. package/lib-es/api/bakers.whitelist-default.js +31 -0
  170. package/lib-es/api/bakers.whitelist-default.js.map +1 -0
  171. package/lib-es/api/index.d.ts +3 -0
  172. package/lib-es/api/index.d.ts.map +1 -0
  173. package/lib-es/api/index.js +3 -0
  174. package/lib-es/api/index.js.map +1 -0
  175. package/lib-es/api/tzkt.d.ts +82 -0
  176. package/lib-es/api/tzkt.d.ts.map +1 -0
  177. package/lib-es/api/tzkt.js +67 -0
  178. package/lib-es/api/tzkt.js.map +1 -0
  179. package/lib-es/bridge/broadcast.d.ts +4 -0
  180. package/lib-es/bridge/broadcast.d.ts.map +1 -0
  181. package/lib-es/bridge/broadcast.js +19 -0
  182. package/lib-es/bridge/broadcast.js.map +1 -0
  183. package/lib-es/bridge/broadcast.test.d.ts +2 -0
  184. package/lib-es/bridge/broadcast.test.d.ts.map +1 -0
  185. package/lib-es/bridge/broadcast.test.js +35 -0
  186. package/lib-es/bridge/broadcast.test.js.map +1 -0
  187. package/lib-es/bridge/buildOptimisticOperation.d.ts +4 -0
  188. package/lib-es/bridge/buildOptimisticOperation.d.ts.map +1 -0
  189. package/lib-es/bridge/buildOptimisticOperation.js +21 -0
  190. package/lib-es/bridge/buildOptimisticOperation.js.map +1 -0
  191. package/lib-es/bridge/createTransaction.d.ts +4 -0
  192. package/lib-es/bridge/createTransaction.d.ts.map +1 -0
  193. package/lib-es/bridge/createTransaction.js +17 -0
  194. package/lib-es/bridge/createTransaction.js.map +1 -0
  195. package/lib-es/bridge/deviceTransactionConfig.d.ts +19 -0
  196. package/lib-es/bridge/deviceTransactionConfig.d.ts.map +1 -0
  197. package/lib-es/bridge/deviceTransactionConfig.js +42 -0
  198. package/lib-es/bridge/deviceTransactionConfig.js.map +1 -0
  199. package/lib-es/bridge/estimateMaxSpendable.d.ts +5 -0
  200. package/lib-es/bridge/estimateMaxSpendable.d.ts.map +1 -0
  201. package/lib-es/bridge/estimateMaxSpendable.js +24 -0
  202. package/lib-es/bridge/estimateMaxSpendable.js.map +1 -0
  203. package/lib-es/bridge/getTransactionStatus.d.ts +4 -0
  204. package/lib-es/bridge/getTransactionStatus.d.ts.map +1 -0
  205. package/lib-es/bridge/getTransactionStatus.js +106 -0
  206. package/lib-es/bridge/getTransactionStatus.js.map +1 -0
  207. package/lib-es/bridge/index.d.ts +8 -0
  208. package/lib-es/bridge/index.d.ts.map +1 -0
  209. package/lib-es/bridge/index.js +50 -0
  210. package/lib-es/bridge/index.js.map +1 -0
  211. package/lib-es/bridge/logic.d.ts +10 -0
  212. package/lib-es/bridge/logic.d.ts.map +1 -0
  213. package/lib-es/bridge/logic.js +150 -0
  214. package/lib-es/bridge/logic.js.map +1 -0
  215. package/lib-es/bridge/preload.d.ts +9 -0
  216. package/lib-es/bridge/preload.d.ts.map +1 -0
  217. package/lib-es/bridge/preload.js +26 -0
  218. package/lib-es/bridge/preload.js.map +1 -0
  219. package/lib-es/bridge/prepareTransaction.d.ts +10 -0
  220. package/lib-es/bridge/prepareTransaction.d.ts.map +1 -0
  221. package/lib-es/bridge/prepareTransaction.js +150 -0
  222. package/lib-es/bridge/prepareTransaction.js.map +1 -0
  223. package/lib-es/bridge/serialization.d.ts +7 -0
  224. package/lib-es/bridge/serialization.d.ts.map +1 -0
  225. package/lib-es/bridge/serialization.js +20 -0
  226. package/lib-es/bridge/serialization.js.map +1 -0
  227. package/lib-es/bridge/signOperation.d.ts +19 -0
  228. package/lib-es/bridge/signOperation.d.ts.map +1 -0
  229. package/lib-es/bridge/signOperation.js +124 -0
  230. package/lib-es/bridge/signOperation.js.map +1 -0
  231. package/lib-es/bridge/signOperation.test.d.ts +2 -0
  232. package/lib-es/bridge/signOperation.test.d.ts.map +1 -0
  233. package/lib-es/bridge/signOperation.test.js +195 -0
  234. package/lib-es/bridge/signOperation.test.js.map +1 -0
  235. package/lib-es/bridge/synchronization.d.ts +5 -0
  236. package/lib-es/bridge/synchronization.d.ts.map +1 -0
  237. package/lib-es/bridge/synchronization.js +78 -0
  238. package/lib-es/bridge/synchronization.js.map +1 -0
  239. package/lib-es/bridge/synchronization.test.d.ts +2 -0
  240. package/lib-es/bridge/synchronization.test.d.ts.map +1 -0
  241. package/lib-es/bridge/synchronization.test.js +31 -0
  242. package/lib-es/bridge/synchronization.test.js.map +1 -0
  243. package/lib-es/bridge/transaction.d.ts +15 -0
  244. package/lib-es/bridge/transaction.d.ts.map +1 -0
  245. package/lib-es/bridge/transaction.js +46 -0
  246. package/lib-es/bridge/transaction.js.map +1 -0
  247. package/lib-es/datasets/tezos.scanAccounts.1.d.ts +7 -0
  248. package/lib-es/datasets/tezos.scanAccounts.1.d.ts.map +1 -0
  249. package/lib-es/datasets/tezos.scanAccounts.1.js +36 -0
  250. package/lib-es/datasets/tezos.scanAccounts.1.js.map +1 -0
  251. package/lib-es/index.d.ts +3 -0
  252. package/lib-es/index.d.ts.map +1 -0
  253. package/lib-es/index.js +3 -0
  254. package/lib-es/index.js.map +1 -0
  255. package/lib-es/signer/getAddress.d.ts +6 -0
  256. package/lib-es/signer/getAddress.d.ts.map +1 -0
  257. package/lib-es/signer/getAddress.js +17 -0
  258. package/lib-es/signer/getAddress.js.map +1 -0
  259. package/lib-es/signer/index.d.ts +6 -0
  260. package/lib-es/signer/index.d.ts.map +1 -0
  261. package/lib-es/signer/index.js +6 -0
  262. package/lib-es/signer/index.js.map +1 -0
  263. package/lib-es/test/bot-deviceActions.d.ts +4 -0
  264. package/lib-es/test/bot-deviceActions.d.ts.map +1 -0
  265. package/lib-es/test/bot-deviceActions.js +71 -0
  266. package/lib-es/test/bot-deviceActions.js.map +1 -0
  267. package/lib-es/test/bot-specs.d.ts +7 -0
  268. package/lib-es/test/bot-specs.d.ts.map +1 -0
  269. package/lib-es/test/bot-specs.js +149 -0
  270. package/lib-es/test/bot-specs.js.map +1 -0
  271. package/lib-es/test/bridgeDatasetTest.d.ts +5 -0
  272. package/lib-es/test/bridgeDatasetTest.d.ts.map +1 -0
  273. package/lib-es/test/bridgeDatasetTest.js +93 -0
  274. package/lib-es/test/bridgeDatasetTest.js.map +1 -0
  275. package/lib-es/test/cli.d.ts +78 -0
  276. package/lib-es/test/cli.d.ts.map +1 -0
  277. package/lib-es/test/cli.js +91 -0
  278. package/lib-es/test/cli.js.map +1 -0
  279. package/lib-es/test/index.d.ts +2 -0
  280. package/lib-es/test/index.d.ts.map +1 -0
  281. package/lib-es/test/index.js +2 -0
  282. package/lib-es/test/index.js.map +1 -0
  283. package/lib-es/types/errors.d.ts +4 -0
  284. package/lib-es/types/errors.d.ts.map +1 -0
  285. package/lib-es/types/errors.js +3 -0
  286. package/lib-es/types/errors.js.map +1 -0
  287. package/lib-es/types/index.d.ts +4 -0
  288. package/lib-es/types/index.d.ts.map +1 -0
  289. package/lib-es/types/index.js +4 -0
  290. package/lib-es/types/index.js.map +1 -0
  291. package/lib-es/types/model.d.ts +92 -0
  292. package/lib-es/types/model.d.ts.map +1 -0
  293. package/lib-es/types/model.fixture.d.ts +5 -0
  294. package/lib-es/types/model.fixture.d.ts.map +1 -0
  295. package/lib-es/types/model.fixture.js +76 -0
  296. package/lib-es/types/model.fixture.js.map +1 -0
  297. package/lib-es/types/model.js +4 -0
  298. package/lib-es/types/model.js.map +1 -0
  299. package/lib-es/types/signer.d.ts +37 -0
  300. package/lib-es/types/signer.d.ts.map +1 -0
  301. package/lib-es/types/signer.js +2 -0
  302. package/lib-es/types/signer.js.map +1 -0
  303. package/package.json +117 -0
  304. package/please-add-coverage.test.ts +3 -0
  305. package/src/README.md +29 -0
  306. package/src/api/bakers.integration.test.ts +61 -0
  307. package/src/api/bakers.test.ts +140 -0
  308. package/src/api/bakers.ts +139 -0
  309. package/src/api/bakers.whitelist-default.ts +33 -0
  310. package/src/api/index.ts +2 -0
  311. package/src/api/tzkt.ts +134 -0
  312. package/src/bridge/broadcast.test.ts +30 -0
  313. package/src/bridge/broadcast.ts +17 -0
  314. package/src/bridge/buildOptimisticOperation.ts +28 -0
  315. package/src/bridge/createTransaction.ts +19 -0
  316. package/src/bridge/deviceTransactionConfig.ts +74 -0
  317. package/src/bridge/estimateMaxSpendable.ts +32 -0
  318. package/src/bridge/getTransactionStatus.ts +122 -0
  319. package/src/bridge/index.ts +65 -0
  320. package/src/bridge/logic.ts +175 -0
  321. package/src/bridge/preload.ts +18 -0
  322. package/src/bridge/prepareTransaction.ts +161 -0
  323. package/src/bridge/serialization.ts +27 -0
  324. package/src/bridge/signOperation.test.ts +211 -0
  325. package/src/bridge/signOperation.ts +191 -0
  326. package/src/bridge/synchronization.test.ts +22 -0
  327. package/src/bridge/synchronization.ts +99 -0
  328. package/src/bridge/transaction.ts +94 -0
  329. package/src/datasets/tezos.scanAccounts.1.ts +35 -0
  330. package/src/index.ts +3 -0
  331. package/src/signer/getAddress.ts +13 -0
  332. package/src/signer/index.ts +7 -0
  333. package/src/test/bot-deviceActions.ts +79 -0
  334. package/src/test/bot-specs.ts +152 -0
  335. package/src/test/bridgeDatasetTest.ts +132 -0
  336. package/src/test/cli.ts +137 -0
  337. package/src/test/index.ts +1 -0
  338. package/src/types/errors.ts +5 -0
  339. package/src/types/index.ts +3 -0
  340. package/src/types/model.fixture.ts +89 -0
  341. package/src/types/model.ts +123 -0
  342. package/src/types/signer.ts +48 -0
  343. package/tsconfig.json +13 -0
  344. package/types/@taquito/ledger-signer/index.d.ts +3 -0
@@ -0,0 +1,161 @@
1
+ import BigNumber from "bignumber.js";
2
+ import { log } from "@ledgerhq/logs";
3
+ import { getEnv } from "@ledgerhq/live-env";
4
+ import { AccountBridge } from "@ledgerhq/types-live";
5
+ import { DerivationType } from "@taquito/ledger-signer";
6
+ import type { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
7
+ import { InvalidAddress, RecipientRequired } from "@ledgerhq/errors";
8
+ import { compressPublicKey } from "@taquito/ledger-signer/dist/lib/utils";
9
+ import { b58cencode, prefix, Prefix, validateAddress, ValidationResult } from "@taquito/utils";
10
+ import { DEFAULT_FEE, DEFAULT_STORAGE_LIMIT, Estimate, TezosToolkit } from "@taquito/taquito";
11
+ import { TezosAccount, Transaction } from "../types";
12
+
13
+ function bnEq(a: BigNumber | null | undefined, b: BigNumber | null | undefined): boolean {
14
+ return !a && !b ? true : !a || !b ? false : a.eq(b);
15
+ }
16
+
17
+ export const validateRecipient = (currency: CryptoCurrency, recipient: string) => {
18
+ let recipientError: Error | null = null;
19
+ const recipientWarning = null;
20
+ if (!recipient) {
21
+ recipientError = new RecipientRequired("");
22
+ } else if (validateAddress(recipient) !== ValidationResult.VALID) {
23
+ recipientError = new InvalidAddress(undefined, {
24
+ currencyName: currency.name,
25
+ });
26
+ }
27
+ return Promise.resolve({ recipientError, recipientWarning });
28
+ };
29
+
30
+ export const prepareTransaction: AccountBridge<
31
+ Transaction,
32
+ TezosAccount
33
+ >["prepareTransaction"] = async (account, transaction) => {
34
+ const { tezosResources } = account;
35
+ if (!tezosResources) throw new Error("tezosResources is missing");
36
+
37
+ if (account.balance.lte(0)) {
38
+ return Promise.resolve(transaction);
39
+ }
40
+
41
+ // basic check to confirm the transaction is "complete"
42
+ if (transaction.mode !== "undelegate") {
43
+ if (!transaction.recipient) {
44
+ return Promise.resolve(transaction);
45
+ }
46
+
47
+ const { recipientError } = await validateRecipient(account.currency, transaction.recipient);
48
+ if (recipientError) {
49
+ return Promise.resolve(transaction);
50
+ }
51
+ }
52
+
53
+ const encodedPubKey = b58cencode(
54
+ compressPublicKey(Buffer.from(account.xpub || "", "hex"), DerivationType.ED25519),
55
+ prefix[Prefix.EDPK],
56
+ );
57
+
58
+ const tezos = new TezosToolkit(getEnv("API_TEZOS_NODE"));
59
+
60
+ tezos.setProvider({
61
+ signer: {
62
+ publicKeyHash: async () => account.freshAddress,
63
+ publicKey: async () => encodedPubKey,
64
+ sign: () => Promise.reject(new Error("unsupported")),
65
+ secretKey: () => Promise.reject(new Error("unsupported")),
66
+ },
67
+ });
68
+
69
+ const tx: Transaction = { ...transaction, taquitoError: null };
70
+
71
+ let amount = transaction.amount;
72
+ if (transaction.useAllAmount) {
73
+ amount = new BigNumber(1); // send max do a pre-estimation with minimum amount (taquito refuses 0)
74
+ }
75
+
76
+ try {
77
+ let estimate: Estimate;
78
+ switch (transaction.mode) {
79
+ case "send":
80
+ estimate = await tezos.estimate.transfer({
81
+ mutez: true,
82
+ to: transaction.recipient,
83
+ amount: amount.toNumber(),
84
+ storageLimit: DEFAULT_STORAGE_LIMIT.ORIGINATION, // https://github.com/TezTech/eztz/blob/master/PROTO_003_FEES.md for originating an account
85
+ });
86
+ break;
87
+ case "delegate":
88
+ estimate = await tezos.estimate.setDelegate({
89
+ source: account.freshAddress,
90
+ delegate: transaction.recipient,
91
+ });
92
+ break;
93
+ case "undelegate":
94
+ estimate = await tezos.estimate.setDelegate({
95
+ source: account.freshAddress,
96
+ });
97
+ break;
98
+ default:
99
+ throw new Error("unsupported mode=" + transaction.mode);
100
+ }
101
+
102
+ if (tx.useAllAmount) {
103
+ const totalFees = estimate.suggestedFeeMutez + estimate.burnFeeMutez;
104
+ const maxAmount = account.balance
105
+ .minus(totalFees + (tezosResources.revealed ? 0 : DEFAULT_FEE.REVEAL))
106
+ .toNumber();
107
+ // from https://github.com/ecadlabs/taquito/blob/a70c64c4b105381bb9f1d04c9c70e8ef26e9241c/integration-tests/contract-empty-implicit-account-into-new-implicit-account.spec.ts#L33
108
+ // Temporary fix, see https://gitlab.com/tezos/tezos/-/issues/1754
109
+ // we need to increase the gasLimit and fee returned by the estimation
110
+ const gasBuffer = 500;
111
+ const MINIMAL_FEE_PER_GAS_MUTEZ = 0.1;
112
+ const increasedFee = (gasBuffer: number, opSize: number) => {
113
+ return gasBuffer * MINIMAL_FEE_PER_GAS_MUTEZ + opSize;
114
+ };
115
+ const incr = increasedFee(gasBuffer, Number(estimate.opSize));
116
+ tx.fees = new BigNumber(estimate.suggestedFeeMutez + incr);
117
+ tx.gasLimit = new BigNumber(estimate.gasLimit + gasBuffer);
118
+ tx.amount = maxAmount - incr > 0 ? new BigNumber(maxAmount - incr) : new BigNumber(0);
119
+ } else {
120
+ tx.fees = new BigNumber(estimate.suggestedFeeMutez);
121
+ tx.gasLimit = new BigNumber(estimate.gasLimit);
122
+ tx.storageLimit = new BigNumber(estimate.storageLimit);
123
+ }
124
+
125
+ tx.storageLimit = new BigNumber(estimate.storageLimit);
126
+ tx.estimatedFees = tx.fees;
127
+ if (!tezosResources.revealed) {
128
+ tx.estimatedFees = tx.estimatedFees.plus(DEFAULT_FEE.REVEAL);
129
+ }
130
+ } catch (e) {
131
+ if (typeof e !== "object" || !e) throw e;
132
+ if ("id" in e) {
133
+ tx.taquitoError = (e as { id: string }).id;
134
+ log("taquito-error", "taquito got error " + tx.taquitoError);
135
+ } else if ("status" in e) {
136
+ // in case of http 400, log & ignore (more case to handle)
137
+ log("taquito-network-error", String((e as unknown as { message: string }).message || ""), {
138
+ transaction: tx,
139
+ });
140
+ throw e;
141
+ } else {
142
+ throw e;
143
+ }
144
+ }
145
+
146
+ // nothing changed
147
+ if (
148
+ bnEq(tx.estimatedFees, transaction.estimatedFees) &&
149
+ bnEq(tx.fees, transaction.fees) &&
150
+ bnEq(tx.gasLimit, transaction.gasLimit) &&
151
+ bnEq(tx.storageLimit, transaction.storageLimit) &&
152
+ bnEq(tx.amount, transaction.amount) &&
153
+ tx.taquitoError === transaction.taquitoError
154
+ ) {
155
+ return transaction;
156
+ }
157
+
158
+ return tx;
159
+ };
160
+
161
+ export default prepareTransaction;
@@ -0,0 +1,27 @@
1
+ import type { TezosAccount, TezosAccountRaw, TezosResources, TezosResourcesRaw } from "../types";
2
+ import { Account, AccountRaw } from "@ledgerhq/types-live";
3
+
4
+ export function toTezosResourcesRaw(r: TezosResources): TezosResourcesRaw {
5
+ const { revealed, counter } = r;
6
+ return { revealed, counter };
7
+ }
8
+
9
+ export function fromTezosResourcesRaw(r: TezosResourcesRaw): TezosResources {
10
+ const { revealed, counter } = r;
11
+ return { revealed, counter };
12
+ }
13
+
14
+ export function assignToAccountRaw(account: Account, accountRaw: AccountRaw) {
15
+ const tezosAccount = account as TezosAccount;
16
+ if (tezosAccount.tezosResources) {
17
+ (accountRaw as TezosAccountRaw).tezosResources = toTezosResourcesRaw(
18
+ tezosAccount.tezosResources,
19
+ );
20
+ }
21
+ }
22
+
23
+ export function assignFromAccountRaw(accountRaw: AccountRaw, account: Account) {
24
+ const tezosResourcesRaw = (accountRaw as TezosAccountRaw).tezosResources;
25
+ if (tezosResourcesRaw)
26
+ (account as TezosAccount).tezosResources = fromTezosResourcesRaw(tezosResourcesRaw);
27
+ }
@@ -0,0 +1,211 @@
1
+ import BigNumber from "bignumber.js";
2
+ import { OpKind, TezosToolkit } from "@taquito/taquito";
3
+ import { SignOperationEvent } from "@ledgerhq/types-live";
4
+ import buildSignOperation, { getOperationContents } from "./signOperation";
5
+ import { TezosSigner } from "../types";
6
+ import { createFixtureAccount, createFixtureTransaction } from "../types/model.fixture";
7
+
8
+ const mockForgeOperations = jest.fn().mockResolvedValue("FORGED_OP");
9
+ jest.mock("@taquito/taquito", () => ({
10
+ ...jest.requireActual("@taquito/taquito"),
11
+ TezosToolkit: jest.fn().mockReturnValue({
12
+ setProvider: jest.fn(),
13
+ rpc: {
14
+ getBlock: jest.fn().mockResolvedValue({ hash: "hash" }),
15
+ getContract: jest.fn().mockResolvedValue({ counter: "12" }),
16
+ forgeOperations: () => mockForgeOperations(),
17
+ },
18
+ }),
19
+ }));
20
+
21
+ describe("signOperation", () => {
22
+ const mockSign = jest.fn().mockResolvedValue({
23
+ bytes: "SIG_BYTES",
24
+ sig: "SIG",
25
+ prefixSig: "PREFIX_SIG",
26
+ sbytes: "03SBYTES",
27
+ });
28
+ const fakeSigner = {
29
+ getAddress: jest.fn(),
30
+ signOperation: jest.fn(),
31
+ createLedgerSigner: () => ({
32
+ publicKey: () => Promise.resolve("PUBKEY"),
33
+ publicKeyHash: () => Promise.resolve("PUBKEYHASH"),
34
+ sign: () => mockSign(),
35
+ secretKey: () => Promise.resolve(undefined),
36
+ }),
37
+ };
38
+ const signerContext = <T>(_deviceId: string, fn: (signer: TezosSigner) => Promise<T>) =>
39
+ fn(fakeSigner);
40
+ const signOperation = buildSignOperation(signerContext);
41
+ const deviceId = "dummyDeviceId";
42
+
43
+ afterEach(() => {
44
+ mockForgeOperations.mockClear();
45
+ mockSign.mockClear();
46
+ });
47
+
48
+ it("returns events in the right order", done => {
49
+ // GIVEN
50
+ const account = createFixtureAccount();
51
+ const transaction = createFixtureTransaction({ fees: BigNumber(0) });
52
+
53
+ // WHEN & THEN
54
+ const expectedEvent = [
55
+ {
56
+ type: "device-signature-requested",
57
+ },
58
+ {
59
+ type: "device-signature-granted",
60
+ },
61
+ {
62
+ type: "signed",
63
+ },
64
+ ];
65
+ let eventIdx = 0;
66
+ signOperation({ account, deviceId, transaction }).forEach(e => {
67
+ try {
68
+ expect(e.type).toEqual(expectedEvent[eventIdx].type);
69
+ eventIdx++;
70
+
71
+ if (eventIdx === expectedEvent.length) {
72
+ done();
73
+ }
74
+ } catch (err) {
75
+ done(err);
76
+ }
77
+ });
78
+ });
79
+
80
+ it("returns signature value from LedgerSigner", done => {
81
+ // GIVEN
82
+ const account = createFixtureAccount();
83
+ const transaction = createFixtureTransaction({ fees: new BigNumber(0) });
84
+
85
+ // WHEN & THEN
86
+ const subscriber = signOperation({ account, deviceId, transaction }).subscribe(
87
+ (e: SignOperationEvent) => {
88
+ if (e.type === "signed") {
89
+ const signature = e.signedOperation.signature;
90
+ expect(signature).toEqual("SBYTES");
91
+ expect(mockSign).toHaveBeenCalledTimes(1);
92
+ expect(mockForgeOperations).toHaveBeenCalledTimes(1);
93
+
94
+ // Cleanup
95
+ subscriber.unsubscribe();
96
+ done();
97
+ }
98
+ },
99
+ );
100
+ });
101
+ });
102
+
103
+ describe("getOperationContents - revealed account", () => {
104
+ const tezos = new TezosToolkit("MOCK_API_KEY");
105
+ const account = createFixtureAccount({ freshAddress: "tz1addr" });
106
+
107
+ it("mode - send", async () => {
108
+ const transaction = createFixtureTransaction({
109
+ family: "tezos",
110
+ amount: new BigNumber(0),
111
+ recipient: "RECIPIENT_ADD",
112
+ fees: new BigNumber(0),
113
+ mode: "send",
114
+ gasLimit: new BigNumber(0),
115
+ storageLimit: new BigNumber(0),
116
+ });
117
+
118
+ const { type, contents } = await getOperationContents({
119
+ account,
120
+ transaction,
121
+ tezos,
122
+ counter: 0,
123
+ public_key: "pk",
124
+ public_key_hash: "pkh",
125
+ });
126
+
127
+ expect(type).toBe("OUT");
128
+ expect(contents.length).toEqual(1);
129
+ expect(contents).toStrictEqual([
130
+ {
131
+ kind: OpKind.TRANSACTION,
132
+ amount: transaction.amount.toString(),
133
+ destination: transaction.recipient,
134
+ source: "tz1addr",
135
+ counter: "1",
136
+ fee: new BigNumber(0).toString(),
137
+ gas_limit: new BigNumber(0).toString(),
138
+ storage_limit: new BigNumber(0).toString(),
139
+ },
140
+ ]);
141
+ });
142
+
143
+ it("mode - delegate", async () => {
144
+ const transaction = createFixtureTransaction({
145
+ family: "tezos",
146
+ amount: new BigNumber(0),
147
+ recipient: "RECIPIENT_ADD",
148
+ fees: new BigNumber(0),
149
+ mode: "delegate",
150
+ gasLimit: new BigNumber(0),
151
+ storageLimit: new BigNumber(0),
152
+ });
153
+
154
+ const { type, contents } = await getOperationContents({
155
+ account,
156
+ transaction,
157
+ tezos,
158
+ counter: 0,
159
+ public_key: "pk",
160
+ public_key_hash: "pkh",
161
+ });
162
+
163
+ expect(type).toBe("DELEGATE");
164
+ expect(contents.length).toEqual(1);
165
+ expect(contents).toStrictEqual([
166
+ {
167
+ kind: OpKind.DELEGATION,
168
+ source: "tz1addr",
169
+ counter: "1",
170
+ fee: new BigNumber(0).toString(),
171
+ gas_limit: new BigNumber(0).toString(),
172
+ storage_limit: new BigNumber(0).toString(),
173
+ delegate: transaction.recipient,
174
+ },
175
+ ]);
176
+ });
177
+
178
+ it("mode - undelegate", async () => {
179
+ const transaction = createFixtureTransaction({
180
+ family: "tezos",
181
+ amount: new BigNumber(0),
182
+ recipient: "",
183
+ fees: new BigNumber(0),
184
+ mode: "undelegate",
185
+ gasLimit: new BigNumber(0),
186
+ storageLimit: new BigNumber(0),
187
+ });
188
+
189
+ const { type, contents } = await getOperationContents({
190
+ account,
191
+ transaction,
192
+ tezos,
193
+ counter: 0,
194
+ public_key: "pk",
195
+ public_key_hash: "pkh",
196
+ });
197
+
198
+ expect(type).toBe("UNDELEGATE");
199
+ expect(contents.length).toEqual(1);
200
+ expect(contents).toStrictEqual([
201
+ {
202
+ kind: OpKind.DELEGATION,
203
+ source: "tz1addr",
204
+ counter: "1",
205
+ fee: new BigNumber(0).toString(),
206
+ gas_limit: new BigNumber(0).toString(),
207
+ storage_limit: new BigNumber(0).toString(),
208
+ },
209
+ ]);
210
+ });
211
+ });
@@ -0,0 +1,191 @@
1
+ import { Observable } from "rxjs";
2
+ import { getEnv } from "@ledgerhq/live-env";
3
+ import { FeeNotLoaded } from "@ledgerhq/errors";
4
+ import { type OperationContents } from "@taquito/rpc";
5
+ import { SignerContext } from "@ledgerhq/coin-framework/signer";
6
+ import { DEFAULT_FEE, OpKind, TezosToolkit } from "@taquito/taquito";
7
+ import type { OperationType, SignOperationEvent, AccountBridge } from "@ledgerhq/types-live";
8
+ import type { TezosAccount, TezosSigner, Transaction, TransactionStatus } from "../types";
9
+ import { buildOptimisticOperation } from "./buildOptimisticOperation";
10
+
11
+ export async function getOperationContents({
12
+ account,
13
+ transaction,
14
+ tezos,
15
+ counter,
16
+ public_key,
17
+ public_key_hash,
18
+ }: {
19
+ account: TezosAccount;
20
+ transaction: Transaction;
21
+ tezos: TezosToolkit;
22
+ counter: number;
23
+ public_key: string;
24
+ public_key_hash: string;
25
+ }) {
26
+ let type: OperationType = "NONE";
27
+ const { freshAddress } = account;
28
+
29
+ const transactionFees = {
30
+ fee: (transaction.fees || 0).toString(),
31
+ gas_limit: (transaction.gasLimit || 0).toString(),
32
+ storage_limit: (transaction.storageLimit || 0).toString(),
33
+ };
34
+
35
+ const contents: OperationContents[] = [];
36
+
37
+ if (!account.tezosResources.revealed) {
38
+ const revealFees = await tezos.estimate.reveal();
39
+
40
+ contents.push({
41
+ kind: OpKind.REVEAL,
42
+ fee: DEFAULT_FEE.REVEAL.toString(),
43
+ gas_limit: (revealFees?.gasLimit || 0).toString(),
44
+ storage_limit: (revealFees?.storageLimit || 0).toString(),
45
+ source: public_key_hash,
46
+ counter: (counter + 1).toString(),
47
+ public_key,
48
+ });
49
+ }
50
+
51
+ switch (transaction.mode) {
52
+ case "send": {
53
+ type = "OUT";
54
+
55
+ contents.push({
56
+ kind: OpKind.TRANSACTION,
57
+ amount: transaction.amount.toString(),
58
+ destination: transaction.recipient,
59
+ source: freshAddress,
60
+ counter: (counter + 1 + contents.length).toString(),
61
+ ...transactionFees,
62
+ });
63
+
64
+ break;
65
+ }
66
+ case "delegate": {
67
+ type = "DELEGATE";
68
+
69
+ contents.push({
70
+ kind: OpKind.DELEGATION,
71
+ source: freshAddress,
72
+ counter: (counter + 1 + contents.length).toString(),
73
+ delegate: transaction.recipient,
74
+ ...transactionFees,
75
+ });
76
+
77
+ break;
78
+ }
79
+ case "undelegate": {
80
+ type = "UNDELEGATE";
81
+
82
+ // we undelegate as there's no "delegate" field
83
+ // OpKind is still "DELEGATION"
84
+ contents.push({
85
+ kind: OpKind.DELEGATION,
86
+ source: freshAddress,
87
+ counter: (counter + 1 + contents.length).toString(),
88
+ ...transactionFees,
89
+ });
90
+
91
+ break;
92
+ }
93
+ default:
94
+ throw new Error("not supported");
95
+ }
96
+
97
+ return { type, contents };
98
+ }
99
+
100
+ export const buildSignOperation =
101
+ (
102
+ signerContext: SignerContext<TezosSigner>,
103
+ ): AccountBridge<Transaction, TezosAccount, TransactionStatus>["signOperation"] =>
104
+ ({ account, deviceId, transaction }): Observable<SignOperationEvent> =>
105
+ new Observable(o => {
106
+ let cancelled = false;
107
+
108
+ async function main() {
109
+ const { fees } = transaction;
110
+ if (!fees) throw new FeeNotLoaded();
111
+
112
+ const { freshAddressPath, freshAddress } = account;
113
+
114
+ const tezos = new TezosToolkit(getEnv("API_TEZOS_NODE"));
115
+
116
+ const signedInfo = await signerContext(deviceId, async signer => {
117
+ const ledgerSigner = signer.createLedgerSigner(freshAddressPath, false, 0);
118
+
119
+ tezos.setProvider({ signer: ledgerSigner });
120
+
121
+ const publicKey = await ledgerSigner.publicKey();
122
+ const publicKeyHash = await ledgerSigner.publicKeyHash();
123
+
124
+ const { rpc } = tezos;
125
+ const block = await rpc.getBlock();
126
+ const sourceData = await rpc.getContract(freshAddress);
127
+
128
+ o.next({ type: "device-signature-requested" });
129
+
130
+ if (cancelled) {
131
+ return;
132
+ }
133
+
134
+ const { type, contents } = await getOperationContents({
135
+ account,
136
+ transaction,
137
+ tezos,
138
+ counter: Number(sourceData.counter),
139
+ public_key: publicKey,
140
+ public_key_hash: publicKeyHash,
141
+ });
142
+
143
+ const forgedBytes = await rpc.forgeOperations({
144
+ branch: block.hash,
145
+ contents,
146
+ });
147
+
148
+ // 0x03 is a conventional prefix (aka a watermark) for tezos transactions
149
+ const signature = await ledgerSigner.sign(
150
+ Buffer.concat([Buffer.from("03", "hex"), Buffer.from(forgedBytes, "hex")]).toString(
151
+ "hex",
152
+ ),
153
+ );
154
+
155
+ return {
156
+ type,
157
+ signature,
158
+ };
159
+ });
160
+
161
+ if (!signedInfo) {
162
+ return;
163
+ }
164
+
165
+ o.next({ type: "device-signature-granted" });
166
+
167
+ const { type, signature } = signedInfo;
168
+ const operation = buildOptimisticOperation(account, transaction, type);
169
+
170
+ o.next({
171
+ type: "signed",
172
+ signedOperation: {
173
+ operation,
174
+ // we slice the signature to remove the `03` prefix
175
+ // which souldn't be included in the signature
176
+ signature: signature.sbytes.slice(2),
177
+ },
178
+ });
179
+ }
180
+
181
+ main().then(
182
+ () => o.complete(),
183
+ e => o.error(e),
184
+ );
185
+
186
+ return () => {
187
+ cancelled = true;
188
+ };
189
+ });
190
+
191
+ export default buildSignOperation;
@@ -0,0 +1,22 @@
1
+ import { getEnv, setEnv } from "@ledgerhq/live-env";
2
+ import { fetchAllTransactions } from "../api/tzkt";
3
+
4
+ jest.setTimeout(2 * 60 * 1000);
5
+
6
+ describe("TEZOS_MAX_TX_QUERIES", () => {
7
+ const bigAccount = "tz1boBHAVpwcvKkNFAQHYr7mjxAz1PpVgKq7";
8
+ test("default have more than 100 txs", async () => {
9
+ const txs = await fetchAllTransactions(bigAccount);
10
+ expect(txs.length).toBeGreaterThan(100);
11
+ });
12
+ test("lowering it to 1 will only fetch a few txs", async () => {
13
+ const cur = getEnv("TEZOS_MAX_TX_QUERIES");
14
+ setEnv("TEZOS_MAX_TX_QUERIES", 1);
15
+ try {
16
+ const txs = await fetchAllTransactions(bigAccount);
17
+ expect(txs.length).toBeLessThanOrEqual(100);
18
+ } finally {
19
+ setEnv("TEZOS_MAX_TX_QUERIES", cur);
20
+ }
21
+ });
22
+ });