@ledgerhq/coin-tezos 0.4.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 (325) 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 +12 -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 +81 -0
  28. package/lib/api/tzkt.d.ts.map +1 -0
  29. package/lib/api/tzkt.js +52 -0
  30. package/lib/api/tzkt.js.map +1 -0
  31. package/lib/bridge/broadcast.d.ts +6 -0
  32. package/lib/bridge/broadcast.d.ts.map +1 -0
  33. package/lib/bridge/broadcast.js +22 -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 +40 -0
  38. package/lib/bridge/broadcast.test.js.map +1 -0
  39. package/lib/bridge/createTransaction.d.ts +3 -0
  40. package/lib/bridge/createTransaction.d.ts.map +1 -0
  41. package/lib/bridge/createTransaction.js +23 -0
  42. package/lib/bridge/createTransaction.js.map +1 -0
  43. package/lib/bridge/deviceTransactionConfig.d.ts +19 -0
  44. package/lib/bridge/deviceTransactionConfig.d.ts.map +1 -0
  45. package/lib/bridge/deviceTransactionConfig.js +44 -0
  46. package/lib/bridge/deviceTransactionConfig.js.map +1 -0
  47. package/lib/bridge/estimateMaxSpendable.d.ts +10 -0
  48. package/lib/bridge/estimateMaxSpendable.d.ts.map +1 -0
  49. package/lib/bridge/estimateMaxSpendable.js +29 -0
  50. package/lib/bridge/estimateMaxSpendable.js.map +1 -0
  51. package/lib/bridge/getAccountShape.d.ts +5 -0
  52. package/lib/bridge/getAccountShape.d.ts.map +1 -0
  53. package/lib/bridge/getAccountShape.js +253 -0
  54. package/lib/bridge/getAccountShape.js.map +1 -0
  55. package/lib/bridge/getAccountShape.test.d.ts +2 -0
  56. package/lib/bridge/getAccountShape.test.d.ts.map +1 -0
  57. package/lib/bridge/getAccountShape.test.js +33 -0
  58. package/lib/bridge/getAccountShape.test.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 +58 -0
  62. package/lib/bridge/index.js.map +1 -0
  63. package/lib/bridge/preload.d.ts +9 -0
  64. package/lib/bridge/preload.d.ts.map +1 -0
  65. package/lib/bridge/preload.js +32 -0
  66. package/lib/bridge/preload.js.map +1 -0
  67. package/lib/bridge/prepareTransaction.d.ts +9 -0
  68. package/lib/bridge/prepareTransaction.d.ts.map +1 -0
  69. package/lib/bridge/prepareTransaction.js +157 -0
  70. package/lib/bridge/prepareTransaction.js.map +1 -0
  71. package/lib/bridge/serialization.d.ts +7 -0
  72. package/lib/bridge/serialization.d.ts.map +1 -0
  73. package/lib/bridge/serialization.js +27 -0
  74. package/lib/bridge/serialization.js.map +1 -0
  75. package/lib/bridge/signOperation.d.ts +19 -0
  76. package/lib/bridge/signOperation.d.ts.map +1 -0
  77. package/lib/bridge/signOperation.js +147 -0
  78. package/lib/bridge/signOperation.js.map +1 -0
  79. package/lib/bridge/signOperation.test.d.ts +2 -0
  80. package/lib/bridge/signOperation.test.d.ts.map +1 -0
  81. package/lib/bridge/signOperation.test.js +223 -0
  82. package/lib/bridge/signOperation.test.js.map +1 -0
  83. package/lib/bridge/transaction.d.ts +15 -0
  84. package/lib/bridge/transaction.d.ts.map +1 -0
  85. package/lib/bridge/transaction.js +52 -0
  86. package/lib/bridge/transaction.js.map +1 -0
  87. package/lib/bridge/transactionStatus.d.ts +3 -0
  88. package/lib/bridge/transactionStatus.d.ts.map +1 -0
  89. package/lib/bridge/transactionStatus.js +114 -0
  90. package/lib/bridge/transactionStatus.js.map +1 -0
  91. package/lib/datasets/tezos.scanAccounts.1.d.ts +7 -0
  92. package/lib/datasets/tezos.scanAccounts.1.d.ts.map +1 -0
  93. package/lib/datasets/tezos.scanAccounts.1.js +38 -0
  94. package/lib/datasets/tezos.scanAccounts.1.js.map +1 -0
  95. package/lib/index.d.ts +3 -0
  96. package/lib/index.d.ts.map +1 -0
  97. package/lib/index.js +21 -0
  98. package/lib/index.js.map +1 -0
  99. package/lib/signer/getAddress.d.ts +6 -0
  100. package/lib/signer/getAddress.d.ts.map +1 -0
  101. package/lib/signer/getAddress.js +19 -0
  102. package/lib/signer/getAddress.js.map +1 -0
  103. package/lib/signer/index.d.ts +6 -0
  104. package/lib/signer/index.d.ts.map +1 -0
  105. package/lib/signer/index.js +11 -0
  106. package/lib/signer/index.js.map +1 -0
  107. package/lib/test/bot-deviceActions.d.ts +4 -0
  108. package/lib/test/bot-deviceActions.d.ts.map +1 -0
  109. package/lib/test/bot-deviceActions.js +74 -0
  110. package/lib/test/bot-deviceActions.js.map +1 -0
  111. package/lib/test/bot-specs.d.ts +7 -0
  112. package/lib/test/bot-specs.d.ts.map +1 -0
  113. package/lib/test/bot-specs.js +154 -0
  114. package/lib/test/bot-specs.js.map +1 -0
  115. package/lib/test/bridgeDatasetTest.d.ts +5 -0
  116. package/lib/test/bridgeDatasetTest.d.ts.map +1 -0
  117. package/lib/test/bridgeDatasetTest.js +99 -0
  118. package/lib/test/bridgeDatasetTest.js.map +1 -0
  119. package/lib/test/cli.d.ts +78 -0
  120. package/lib/test/cli.d.ts.map +1 -0
  121. package/lib/test/cli.js +97 -0
  122. package/lib/test/cli.js.map +1 -0
  123. package/lib/test/index.d.ts +2 -0
  124. package/lib/test/index.d.ts.map +1 -0
  125. package/lib/test/index.js +18 -0
  126. package/lib/test/index.js.map +1 -0
  127. package/lib/types/errors.d.ts +4 -0
  128. package/lib/types/errors.d.ts.map +1 -0
  129. package/lib/types/errors.js +6 -0
  130. package/lib/types/errors.js.map +1 -0
  131. package/lib/types/index.d.ts +4 -0
  132. package/lib/types/index.d.ts.map +1 -0
  133. package/lib/types/index.js +20 -0
  134. package/lib/types/index.js.map +1 -0
  135. package/lib/types/model.d.ts +92 -0
  136. package/lib/types/model.d.ts.map +1 -0
  137. package/lib/types/model.fixture.d.ts +5 -0
  138. package/lib/types/model.fixture.d.ts.map +1 -0
  139. package/lib/types/model.fixture.js +85 -0
  140. package/lib/types/model.fixture.js.map +1 -0
  141. package/lib/types/model.js +8 -0
  142. package/lib/types/model.js.map +1 -0
  143. package/lib/types/signer.d.ts +37 -0
  144. package/lib/types/signer.d.ts.map +1 -0
  145. package/lib/types/signer.js +3 -0
  146. package/lib/types/signer.js.map +1 -0
  147. package/lib-es/api/bakers.d.ts +14 -0
  148. package/lib-es/api/bakers.d.ts.map +1 -0
  149. package/lib-es/api/bakers.integration.test.d.ts +2 -0
  150. package/lib-es/api/bakers.integration.test.d.ts.map +1 -0
  151. package/lib-es/api/bakers.integration.test.js +56 -0
  152. package/lib-es/api/bakers.integration.test.js.map +1 -0
  153. package/lib-es/api/bakers.js +125 -0
  154. package/lib-es/api/bakers.js.map +1 -0
  155. package/lib-es/api/bakers.test.d.ts +2 -0
  156. package/lib-es/api/bakers.test.d.ts.map +1 -0
  157. package/lib-es/api/bakers.test.js +141 -0
  158. package/lib-es/api/bakers.test.js.map +1 -0
  159. package/lib-es/api/bakers.whitelist-default.d.ts +4 -0
  160. package/lib-es/api/bakers.whitelist-default.d.ts.map +1 -0
  161. package/lib-es/api/bakers.whitelist-default.js +31 -0
  162. package/lib-es/api/bakers.whitelist-default.js.map +1 -0
  163. package/lib-es/api/index.d.ts +3 -0
  164. package/lib-es/api/index.d.ts.map +1 -0
  165. package/lib-es/api/index.js +3 -0
  166. package/lib-es/api/index.js.map +1 -0
  167. package/lib-es/api/tzkt.d.ts +81 -0
  168. package/lib-es/api/tzkt.d.ts.map +1 -0
  169. package/lib-es/api/tzkt.js +47 -0
  170. package/lib-es/api/tzkt.js.map +1 -0
  171. package/lib-es/bridge/broadcast.d.ts +6 -0
  172. package/lib-es/bridge/broadcast.d.ts.map +1 -0
  173. package/lib-es/bridge/broadcast.js +20 -0
  174. package/lib-es/bridge/broadcast.js.map +1 -0
  175. package/lib-es/bridge/broadcast.test.d.ts +2 -0
  176. package/lib-es/bridge/broadcast.test.d.ts.map +1 -0
  177. package/lib-es/bridge/broadcast.test.js +35 -0
  178. package/lib-es/bridge/broadcast.test.js.map +1 -0
  179. package/lib-es/bridge/createTransaction.d.ts +3 -0
  180. package/lib-es/bridge/createTransaction.d.ts.map +1 -0
  181. package/lib-es/bridge/createTransaction.js +17 -0
  182. package/lib-es/bridge/createTransaction.js.map +1 -0
  183. package/lib-es/bridge/deviceTransactionConfig.d.ts +19 -0
  184. package/lib-es/bridge/deviceTransactionConfig.d.ts.map +1 -0
  185. package/lib-es/bridge/deviceTransactionConfig.js +42 -0
  186. package/lib-es/bridge/deviceTransactionConfig.js.map +1 -0
  187. package/lib-es/bridge/estimateMaxSpendable.d.ts +10 -0
  188. package/lib-es/bridge/estimateMaxSpendable.d.ts.map +1 -0
  189. package/lib-es/bridge/estimateMaxSpendable.js +24 -0
  190. package/lib-es/bridge/estimateMaxSpendable.js.map +1 -0
  191. package/lib-es/bridge/getAccountShape.d.ts +5 -0
  192. package/lib-es/bridge/getAccountShape.d.ts.map +1 -0
  193. package/lib-es/bridge/getAccountShape.js +245 -0
  194. package/lib-es/bridge/getAccountShape.js.map +1 -0
  195. package/lib-es/bridge/getAccountShape.test.d.ts +2 -0
  196. package/lib-es/bridge/getAccountShape.test.d.ts.map +1 -0
  197. package/lib-es/bridge/getAccountShape.test.js +31 -0
  198. package/lib-es/bridge/getAccountShape.test.js.map +1 -0
  199. package/lib-es/bridge/index.d.ts +8 -0
  200. package/lib-es/bridge/index.d.ts.map +1 -0
  201. package/lib-es/bridge/index.js +51 -0
  202. package/lib-es/bridge/index.js.map +1 -0
  203. package/lib-es/bridge/preload.d.ts +9 -0
  204. package/lib-es/bridge/preload.d.ts.map +1 -0
  205. package/lib-es/bridge/preload.js +26 -0
  206. package/lib-es/bridge/preload.js.map +1 -0
  207. package/lib-es/bridge/prepareTransaction.d.ts +9 -0
  208. package/lib-es/bridge/prepareTransaction.d.ts.map +1 -0
  209. package/lib-es/bridge/prepareTransaction.js +150 -0
  210. package/lib-es/bridge/prepareTransaction.js.map +1 -0
  211. package/lib-es/bridge/serialization.d.ts +7 -0
  212. package/lib-es/bridge/serialization.d.ts.map +1 -0
  213. package/lib-es/bridge/serialization.js +20 -0
  214. package/lib-es/bridge/serialization.js.map +1 -0
  215. package/lib-es/bridge/signOperation.d.ts +19 -0
  216. package/lib-es/bridge/signOperation.d.ts.map +1 -0
  217. package/lib-es/bridge/signOperation.js +143 -0
  218. package/lib-es/bridge/signOperation.js.map +1 -0
  219. package/lib-es/bridge/signOperation.test.d.ts +2 -0
  220. package/lib-es/bridge/signOperation.test.d.ts.map +1 -0
  221. package/lib-es/bridge/signOperation.test.js +195 -0
  222. package/lib-es/bridge/signOperation.test.js.map +1 -0
  223. package/lib-es/bridge/transaction.d.ts +15 -0
  224. package/lib-es/bridge/transaction.d.ts.map +1 -0
  225. package/lib-es/bridge/transaction.js +46 -0
  226. package/lib-es/bridge/transaction.js.map +1 -0
  227. package/lib-es/bridge/transactionStatus.d.ts +3 -0
  228. package/lib-es/bridge/transactionStatus.d.ts.map +1 -0
  229. package/lib-es/bridge/transactionStatus.js +107 -0
  230. package/lib-es/bridge/transactionStatus.js.map +1 -0
  231. package/lib-es/datasets/tezos.scanAccounts.1.d.ts +7 -0
  232. package/lib-es/datasets/tezos.scanAccounts.1.d.ts.map +1 -0
  233. package/lib-es/datasets/tezos.scanAccounts.1.js +36 -0
  234. package/lib-es/datasets/tezos.scanAccounts.1.js.map +1 -0
  235. package/lib-es/index.d.ts +3 -0
  236. package/lib-es/index.d.ts.map +1 -0
  237. package/lib-es/index.js +3 -0
  238. package/lib-es/index.js.map +1 -0
  239. package/lib-es/signer/getAddress.d.ts +6 -0
  240. package/lib-es/signer/getAddress.d.ts.map +1 -0
  241. package/lib-es/signer/getAddress.js +17 -0
  242. package/lib-es/signer/getAddress.js.map +1 -0
  243. package/lib-es/signer/index.d.ts +6 -0
  244. package/lib-es/signer/index.d.ts.map +1 -0
  245. package/lib-es/signer/index.js +6 -0
  246. package/lib-es/signer/index.js.map +1 -0
  247. package/lib-es/test/bot-deviceActions.d.ts +4 -0
  248. package/lib-es/test/bot-deviceActions.d.ts.map +1 -0
  249. package/lib-es/test/bot-deviceActions.js +71 -0
  250. package/lib-es/test/bot-deviceActions.js.map +1 -0
  251. package/lib-es/test/bot-specs.d.ts +7 -0
  252. package/lib-es/test/bot-specs.d.ts.map +1 -0
  253. package/lib-es/test/bot-specs.js +149 -0
  254. package/lib-es/test/bot-specs.js.map +1 -0
  255. package/lib-es/test/bridgeDatasetTest.d.ts +5 -0
  256. package/lib-es/test/bridgeDatasetTest.d.ts.map +1 -0
  257. package/lib-es/test/bridgeDatasetTest.js +93 -0
  258. package/lib-es/test/bridgeDatasetTest.js.map +1 -0
  259. package/lib-es/test/cli.d.ts +78 -0
  260. package/lib-es/test/cli.d.ts.map +1 -0
  261. package/lib-es/test/cli.js +91 -0
  262. package/lib-es/test/cli.js.map +1 -0
  263. package/lib-es/test/index.d.ts +2 -0
  264. package/lib-es/test/index.d.ts.map +1 -0
  265. package/lib-es/test/index.js +2 -0
  266. package/lib-es/test/index.js.map +1 -0
  267. package/lib-es/types/errors.d.ts +4 -0
  268. package/lib-es/types/errors.d.ts.map +1 -0
  269. package/lib-es/types/errors.js +3 -0
  270. package/lib-es/types/errors.js.map +1 -0
  271. package/lib-es/types/index.d.ts +4 -0
  272. package/lib-es/types/index.d.ts.map +1 -0
  273. package/lib-es/types/index.js +4 -0
  274. package/lib-es/types/index.js.map +1 -0
  275. package/lib-es/types/model.d.ts +92 -0
  276. package/lib-es/types/model.d.ts.map +1 -0
  277. package/lib-es/types/model.fixture.d.ts +5 -0
  278. package/lib-es/types/model.fixture.d.ts.map +1 -0
  279. package/lib-es/types/model.fixture.js +76 -0
  280. package/lib-es/types/model.fixture.js.map +1 -0
  281. package/lib-es/types/model.js +4 -0
  282. package/lib-es/types/model.js.map +1 -0
  283. package/lib-es/types/signer.d.ts +37 -0
  284. package/lib-es/types/signer.d.ts.map +1 -0
  285. package/lib-es/types/signer.js +2 -0
  286. package/lib-es/types/signer.js.map +1 -0
  287. package/package.json +116 -0
  288. package/src/README.md +29 -0
  289. package/src/api/bakers.integration.test.ts +61 -0
  290. package/src/api/bakers.test.ts +140 -0
  291. package/src/api/bakers.ts +139 -0
  292. package/src/api/bakers.whitelist-default.ts +33 -0
  293. package/src/api/index.ts +2 -0
  294. package/src/api/tzkt.ts +112 -0
  295. package/src/bridge/broadcast.test.ts +30 -0
  296. package/src/bridge/broadcast.ts +18 -0
  297. package/src/bridge/createTransaction.ts +18 -0
  298. package/src/bridge/deviceTransactionConfig.ts +74 -0
  299. package/src/bridge/estimateMaxSpendable.ts +32 -0
  300. package/src/bridge/getAccountShape.test.ts +22 -0
  301. package/src/bridge/getAccountShape.ts +289 -0
  302. package/src/bridge/index.ts +65 -0
  303. package/src/bridge/preload.ts +18 -0
  304. package/src/bridge/prepareTransaction.ts +160 -0
  305. package/src/bridge/serialization.ts +27 -0
  306. package/src/bridge/signOperation.test.ts +211 -0
  307. package/src/bridge/signOperation.ts +213 -0
  308. package/src/bridge/transaction.ts +94 -0
  309. package/src/bridge/transactionStatus.ts +130 -0
  310. package/src/datasets/tezos.scanAccounts.1.ts +35 -0
  311. package/src/index.ts +3 -0
  312. package/src/signer/getAddress.ts +13 -0
  313. package/src/signer/index.ts +7 -0
  314. package/src/test/bot-deviceActions.ts +79 -0
  315. package/src/test/bot-specs.ts +152 -0
  316. package/src/test/bridgeDatasetTest.ts +132 -0
  317. package/src/test/cli.ts +137 -0
  318. package/src/test/index.ts +1 -0
  319. package/src/types/errors.ts +5 -0
  320. package/src/types/index.ts +3 -0
  321. package/src/types/model.fixture.ts +89 -0
  322. package/src/types/model.ts +123 -0
  323. package/src/types/signer.ts +48 -0
  324. package/tsconfig.json +13 -0
  325. package/types/@taquito/ledger-signer/index.d.ts +3 -0
@@ -0,0 +1,18 @@
1
+ import BigNumber from "bignumber.js";
2
+ import { Transaction } from "../types";
3
+
4
+ export default function createTransaction(): Transaction {
5
+ return {
6
+ family: "tezos",
7
+ mode: "send",
8
+ amount: new BigNumber(0),
9
+ fees: null,
10
+ gasLimit: null,
11
+ storageLimit: null,
12
+ recipient: "",
13
+ networkInfo: null,
14
+ useAllAmount: false,
15
+ taquitoError: null,
16
+ estimatedFees: null,
17
+ };
18
+ }
@@ -0,0 +1,74 @@
1
+ import type { AccountLike, Account } from "@ledgerhq/types-live";
2
+ import type { CommonDeviceTransactionField } from "@ledgerhq/coin-framework/transaction/common";
3
+ import { getMainAccount } from "@ledgerhq/coin-framework/account/index";
4
+ import type { Transaction, TransactionStatus } from "../types";
5
+
6
+ export type ExtraDeviceTransactionField =
7
+ | {
8
+ type: "tezos.delegateValidator";
9
+ label: string;
10
+ }
11
+ | {
12
+ type: "tezos.storageLimit";
13
+ label: string;
14
+ };
15
+ type DeviceTransactionField = CommonDeviceTransactionField | ExtraDeviceTransactionField;
16
+
17
+ function getDeviceTransactionConfig({
18
+ account,
19
+ parentAccount,
20
+ transaction: { mode, recipient },
21
+ status: { amount, estimatedFees },
22
+ }: {
23
+ account: AccountLike;
24
+ parentAccount: Account | null | undefined;
25
+ transaction: Transaction;
26
+ status: TransactionStatus;
27
+ }): Array<DeviceTransactionField> {
28
+ const mainAccount = getMainAccount(account, parentAccount);
29
+ const source = mainAccount.freshAddress;
30
+ const isDelegateOperation = mode === "delegate";
31
+ const fields: Array<DeviceTransactionField> = [
32
+ {
33
+ type: "address",
34
+ label: "Source",
35
+ address: source,
36
+ },
37
+ ];
38
+
39
+ if (isDelegateOperation) {
40
+ fields.push(
41
+ {
42
+ type: "tezos.delegateValidator",
43
+ label: "Validator",
44
+ },
45
+ {
46
+ type: "address",
47
+ label: "Delegate",
48
+ address: recipient,
49
+ },
50
+ );
51
+ }
52
+
53
+ if (!amount.isZero()) {
54
+ fields.push({
55
+ type: "amount",
56
+ label: "Amount",
57
+ });
58
+ }
59
+
60
+ if (!estimatedFees.isZero()) {
61
+ fields.push({
62
+ type: "fees",
63
+ label: "Fees",
64
+ });
65
+ }
66
+
67
+ fields.push({
68
+ type: "tezos.storageLimit",
69
+ label: "Storage Limit",
70
+ });
71
+ return fields;
72
+ }
73
+
74
+ export default getDeviceTransactionConfig;
@@ -0,0 +1,32 @@
1
+ import BigNumber from "bignumber.js";
2
+ import { Account, AccountLike } from "@ledgerhq/types-live";
3
+ import { getMainAccount } from "@ledgerhq/coin-framework/account/index";
4
+ import { TezosAccount, Transaction } from "../types";
5
+ import prepareTransaction from "./prepareTransaction";
6
+ import createTransaction from "./createTransaction";
7
+ import { getTransactionStatus } from "./transactionStatus";
8
+
9
+ const TEZOS_BURN_ADDRESS = "tz1burnburnburnburnburnburnburjAYjjX";
10
+
11
+ const estimateMaxSpendable = async ({
12
+ account,
13
+ parentAccount,
14
+ transaction,
15
+ }: {
16
+ account: AccountLike;
17
+ parentAccount: Account | undefined;
18
+ transaction: Transaction;
19
+ }): Promise<BigNumber> => {
20
+ const mainAccount = getMainAccount(account, parentAccount) as TezosAccount;
21
+ const t = await prepareTransaction(mainAccount, {
22
+ ...createTransaction(),
23
+ ...transaction,
24
+ // estimate using a burn address that exists so we don't enter into NotEnoughBalanceBecauseDestinationNotCreated
25
+ recipient: transaction?.recipient || TEZOS_BURN_ADDRESS,
26
+ useAllAmount: true,
27
+ });
28
+ const s = await getTransactionStatus(mainAccount, t);
29
+ return s.amount;
30
+ };
31
+
32
+ export default estimateMaxSpendable;
@@ -0,0 +1,22 @@
1
+ import { getEnv, setEnv } from "@ledgerhq/live-env";
2
+ import { fetchAllTransactions } from "./getAccountShape";
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
+ });
@@ -0,0 +1,289 @@
1
+ import { BigNumber } from "bignumber.js";
2
+ import invariant from "invariant";
3
+ import bs58check from "bs58check";
4
+ import blake2b from "blake2b";
5
+ import { log } from "@ledgerhq/logs";
6
+ import { getEnv } from "@ledgerhq/live-env";
7
+ import type { Account, OperationType, TokenAccount } from "@ledgerhq/types-live";
8
+ import {
9
+ areAllOperationsLoaded,
10
+ decodeAccountId,
11
+ encodeAccountId,
12
+ } from "@ledgerhq/coin-framework/account/index";
13
+ import { GetAccountShape, mergeOps } from "@ledgerhq/coin-framework/bridge/jsHelpers";
14
+ import { encodeOperationId } from "@ledgerhq/coin-framework/operation";
15
+ import api, { type APIOperation } from "../api/tzkt";
16
+ import { TezosOperation } from "../types";
17
+
18
+ function reconciliatePublicKey(
19
+ publicKey: string | undefined,
20
+ initialAccount: Account | undefined,
21
+ ): string {
22
+ if (publicKey) return publicKey;
23
+ if (initialAccount) {
24
+ const { xpubOrAddress } = decodeAccountId(initialAccount.id);
25
+ return xpubOrAddress;
26
+ }
27
+ throw new Error("publicKey wasn't properly restored");
28
+ }
29
+
30
+ const encodeAddress = (publicKey: Buffer) => {
31
+ const curve = 0;
32
+ const curveData = {
33
+ pkB58Prefix: Buffer.from([13, 15, 37, 217]),
34
+ pkhB58Prefix: Buffer.from([6, 161, 159]),
35
+ compressPublicKey: (publicKey: Buffer, curve: number) => {
36
+ publicKey = publicKey.slice(0);
37
+ publicKey[0] = curve;
38
+ return publicKey;
39
+ },
40
+ };
41
+ const publicKeyBuf = curveData.compressPublicKey(publicKey, curve);
42
+ const key = publicKeyBuf.slice(1);
43
+ const keyHashSize = 20;
44
+ // eslint-disable-next-line prefer-const
45
+ const hash = Buffer.alloc(keyHashSize);
46
+ const blakHash = blake2b(keyHashSize);
47
+ blakHash.update(key);
48
+ blakHash.digest(hash);
49
+ const address = bs58check.encode(Buffer.concat([curveData.pkhB58Prefix, hash]));
50
+ return address;
51
+ };
52
+
53
+ function isStringHex(s: string): boolean {
54
+ for (let i = 0; i < s.length; i += 2) {
55
+ const ss = s.slice(i, i + 2);
56
+ const x = parseInt(ss, 16);
57
+ if (Number.isNaN(x)) {
58
+ return false;
59
+ }
60
+ }
61
+ return true;
62
+ }
63
+
64
+ export const getAccountShape: GetAccountShape = async infoInput => {
65
+ const { initialAccount, rest, currency, derivationMode } = infoInput;
66
+ const publicKey = reconciliatePublicKey(rest?.publicKey, initialAccount);
67
+ invariant(
68
+ isStringHex(publicKey),
69
+ `Invalid public key (${publicKey}). Please reimport your Tezos accounts`,
70
+ );
71
+ const hex = Buffer.from(publicKey, "hex");
72
+ const address = encodeAddress(hex);
73
+
74
+ const accountId = encodeAccountId({
75
+ type: "js",
76
+ version: "2",
77
+ currencyId: currency.id,
78
+ xpubOrAddress: publicKey,
79
+ derivationMode,
80
+ });
81
+
82
+ const initialStableOperations = (
83
+ initialAccount && initialAccount.id === accountId ? initialAccount.operations : []
84
+ ) as TezosOperation[];
85
+
86
+ // fetch transactions, incrementally if possible
87
+ const mostRecentStableOperation = initialStableOperations[0];
88
+
89
+ const lastId =
90
+ initialAccount && areAllOperationsLoaded(initialAccount) && mostRecentStableOperation
91
+ ? mostRecentStableOperation.extra.id || undefined
92
+ : undefined;
93
+
94
+ const apiAccountPromise = api.getAccountByAddress(address);
95
+ const blocksCountPromise = api.getBlockCount();
96
+
97
+ const [apiAccount, blockHeight] = await Promise.all([apiAccountPromise, blocksCountPromise]);
98
+
99
+ if (apiAccount.type === "empty") {
100
+ return {
101
+ id: accountId,
102
+ xpub: publicKey,
103
+ freshAddress: address,
104
+ blockHeight,
105
+ lastSyncDate: new Date(),
106
+ tezosResources: {
107
+ revealed: false,
108
+ counter: 0,
109
+ },
110
+ };
111
+ }
112
+
113
+ const fullySupported = apiAccount.type === "user";
114
+
115
+ const apiOperations = fullySupported ? await fetchAllTransactions(address, lastId) : [];
116
+
117
+ const { revealed, counter } = apiAccount;
118
+
119
+ const tezosResources = {
120
+ revealed,
121
+ counter,
122
+ };
123
+
124
+ const balance = new BigNumber(apiAccount.balance);
125
+ const subAccounts: TokenAccount[] = [];
126
+
127
+ const newOps = apiOperations
128
+ .map(txToOp({ address, accountId }))
129
+ .filter(Boolean) as unknown as TezosOperation[]; // force cast because `filter(Boolean)` remove undefined and null value
130
+
131
+ const operations = mergeOps(initialStableOperations, newOps);
132
+
133
+ const accountShape = {
134
+ id: accountId,
135
+ xpub: publicKey,
136
+ freshAddress: address,
137
+ operations,
138
+ balance,
139
+ subAccounts,
140
+ spendableBalance: balance,
141
+ blockHeight,
142
+ lastSyncDate: new Date(),
143
+ tezosResources,
144
+ };
145
+
146
+ return accountShape;
147
+ };
148
+
149
+ const txToOp =
150
+ ({ address, accountId }: { address: string; accountId: string }) =>
151
+ (tx: APIOperation): TezosOperation | null | undefined => {
152
+ let type: OperationType;
153
+ let maybeValue;
154
+ let senders: string[] = [];
155
+ let recipients: string[] = [];
156
+ const hasFailed = tx.status ? tx.status !== "applied" : false;
157
+
158
+ switch (tx.type) {
159
+ case "transaction": {
160
+ const initiator = tx.initiator?.address;
161
+ const from = tx.sender?.address;
162
+ const to = tx.target?.address;
163
+ if (from !== address && to !== address && initiator !== address) {
164
+ // failsafe for a case that shouldn't happen.
165
+ console.warn("found tx is unrelated to account! " + tx.hash);
166
+ return null;
167
+ }
168
+ senders = [from || initiator || ""];
169
+ recipients = [to || ""];
170
+ if (
171
+ (from === address && to === address) || // self tx
172
+ (from !== address && to !== address) // initiator but not in from/to
173
+ ) {
174
+ // we just pay fees in that case
175
+ type = "FEES";
176
+ } else {
177
+ type = to === address ? "IN" : "OUT";
178
+ if (!hasFailed) {
179
+ maybeValue = new BigNumber(tx.amount || 0);
180
+ if (maybeValue.eq(0)) {
181
+ type = "FEES";
182
+ }
183
+ }
184
+ }
185
+ break;
186
+ }
187
+ case "delegation":
188
+ type = tx.newDelegate ? "DELEGATE" : "UNDELEGATE";
189
+ senders = [address];
190
+ // convention was to use recipient for the new delegation address or "" if undelegation
191
+ recipients = [tx.newDelegate ? tx.newDelegate.address : ""];
192
+ break;
193
+ case "reveal":
194
+ type = "REVEAL";
195
+ senders = [address];
196
+ recipients = [address];
197
+ break;
198
+ case "migration":
199
+ type = tx.balanceChange < 0 ? "OUT" : "IN";
200
+ maybeValue = new BigNumber(Math.abs(tx.balanceChange || 0));
201
+ senders = [address];
202
+ recipients = [address];
203
+ break;
204
+ case "origination":
205
+ type = "CREATE";
206
+ maybeValue = new BigNumber(tx.contractBalance || 0);
207
+ senders = [address];
208
+ recipients = [tx.originatedContract?.address || ""];
209
+ break;
210
+ case "activation":
211
+ type = "IN";
212
+ senders = [address];
213
+ recipients = [address];
214
+ maybeValue = new BigNumber(tx.balance || 0);
215
+ break;
216
+ // TODO more type of tx
217
+ default:
218
+ console.warn("unsupported tx:", tx);
219
+ return null;
220
+ }
221
+
222
+ let { hash } = tx;
223
+ const {
224
+ id,
225
+ allocationFee,
226
+ bakerFee,
227
+ storageFee,
228
+ level: blockHeight,
229
+ block: blockHash,
230
+ timestamp,
231
+ } = tx;
232
+
233
+ if (!hash) {
234
+ // in migration case, there is no hash...
235
+ hash = "";
236
+ }
237
+
238
+ let value = maybeValue || new BigNumber(0);
239
+ if (type === "IN" && value.eq(0)) {
240
+ return; // not interesting op
241
+ }
242
+
243
+ let fee = new BigNumber(bakerFee || 0);
244
+
245
+ if (!hasFailed) {
246
+ fee = fee.plus(allocationFee || 0).plus(storageFee || 0);
247
+ }
248
+
249
+ if (type !== "IN") {
250
+ value = value.plus(fee);
251
+ }
252
+
253
+ return {
254
+ id: encodeOperationId(accountId, hash, type),
255
+ hash,
256
+ type,
257
+ value,
258
+ fee,
259
+ senders,
260
+ recipients,
261
+ blockHeight,
262
+ blockHash,
263
+ accountId,
264
+ date: new Date(timestamp),
265
+ extra: { id },
266
+ hasFailed,
267
+ };
268
+ };
269
+
270
+ export const fetchAllTransactions = async (
271
+ address: string,
272
+ lastId?: number,
273
+ ): Promise<APIOperation[]> => {
274
+ let txs: APIOperation[] = [];
275
+ let maxIteration = getEnv("TEZOS_MAX_TX_QUERIES");
276
+ do {
277
+ const r = await api.getAccountOperations(address, { lastId, sort: 0 });
278
+ if (r.length === 0) return txs;
279
+ txs = txs.concat(r);
280
+ const last = txs[txs.length - 1];
281
+ if (!last) return txs;
282
+ lastId = last.id;
283
+ if (!lastId) {
284
+ log("tezos", "id missing!");
285
+ return txs;
286
+ }
287
+ } while (--maxIteration);
288
+ return txs;
289
+ };
@@ -0,0 +1,65 @@
1
+ import type { CurrencyBridge, AccountBridge } from "@ledgerhq/types-live";
2
+ import getAddressWrapper from "@ledgerhq/coin-framework/bridge/getAddressWrapper";
3
+ import {
4
+ defaultUpdateTransaction,
5
+ makeAccountBridgeReceive,
6
+ makeScanAccounts,
7
+ makeSync,
8
+ } from "@ledgerhq/coin-framework/bridge/jsHelpers";
9
+ import { SignerContext } from "@ledgerhq/coin-framework/signer";
10
+ import type { TezosSigner, Transaction } from "../types";
11
+ import signerGetAddress from "../signer";
12
+ import { getAccountShape } from "./getAccountShape";
13
+ import buildSignOperation from "./signOperation";
14
+ import { assignFromAccountRaw, assignToAccountRaw } from "./serialization";
15
+ import { getPreloadStrategy, hydrate, preload } from "./preload";
16
+ import { getTransactionStatus } from "./transactionStatus";
17
+ import prepareTransaction from "./prepareTransaction";
18
+ import estimateMaxSpendable from "./estimateMaxSpendable";
19
+ import createTransaction from "./createTransaction";
20
+ import broadcast from "./broadcast";
21
+
22
+ function buildCurrencyBridge(signerContext: SignerContext<TezosSigner>): CurrencyBridge {
23
+ const getAddress = signerGetAddress(signerContext);
24
+
25
+ const scanAccounts = makeScanAccounts({
26
+ getAccountShape,
27
+ getAddressFn: getAddressWrapper(getAddress),
28
+ });
29
+
30
+ return {
31
+ getPreloadStrategy,
32
+ preload,
33
+ hydrate,
34
+ scanAccounts,
35
+ };
36
+ }
37
+
38
+ function buildAccountBridge(signerContext: SignerContext<TezosSigner>): AccountBridge<Transaction> {
39
+ const getAddress = signerGetAddress(signerContext);
40
+
41
+ const receive = makeAccountBridgeReceive(getAddressWrapper(getAddress));
42
+ const signOperation = buildSignOperation(signerContext);
43
+ const sync = makeSync({ getAccountShape });
44
+
45
+ return {
46
+ estimateMaxSpendable,
47
+ createTransaction,
48
+ updateTransaction: defaultUpdateTransaction,
49
+ getTransactionStatus,
50
+ prepareTransaction,
51
+ sync,
52
+ receive,
53
+ signOperation,
54
+ broadcast,
55
+ assignFromAccountRaw,
56
+ assignToAccountRaw,
57
+ };
58
+ }
59
+
60
+ export function createBridges(signerContext: SignerContext<TezosSigner>) {
61
+ return {
62
+ currencyBridge: buildCurrencyBridge(signerContext),
63
+ accountBridge: buildAccountBridge(signerContext),
64
+ };
65
+ }
@@ -0,0 +1,18 @@
1
+ import { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
2
+ import { fetchAllBakers, hydrateBakers } from "../api/bakers";
3
+
4
+ export const getPreloadStrategy = (_currency: CryptoCurrency) => ({
5
+ preloadMaxAge: 30 * 1000,
6
+ });
7
+
8
+ export const preload = async () => {
9
+ const bakers = await fetchAllBakers();
10
+ return { bakers };
11
+ };
12
+
13
+ export const hydrate = (data: any) => {
14
+ if (!data || typeof data !== "object") return;
15
+ const { bakers } = data;
16
+ if (!bakers || typeof bakers !== "object" || !Array.isArray(bakers)) return;
17
+ hydrateBakers(bakers);
18
+ };
@@ -0,0 +1,160 @@
1
+ import BigNumber from "bignumber.js";
2
+ import { DEFAULT_FEE, DEFAULT_STORAGE_LIMIT, Estimate, TezosToolkit } from "@taquito/taquito";
3
+ import { DerivationType } from "@taquito/ledger-signer";
4
+ import { compressPublicKey } from "@taquito/ledger-signer/dist/lib/utils";
5
+ import { b58cencode, prefix, Prefix, validateAddress, ValidationResult } from "@taquito/utils";
6
+ import { InvalidAddress, RecipientRequired } from "@ledgerhq/errors";
7
+ import { log } from "@ledgerhq/logs";
8
+ import { getEnv } from "@ledgerhq/live-env";
9
+ import type { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
10
+ import { TezosAccount, Transaction } from "../types";
11
+
12
+ function bnEq(a: BigNumber | null | undefined, b: BigNumber | null | undefined): boolean {
13
+ return !a && !b ? true : !a || !b ? false : a.eq(b);
14
+ }
15
+
16
+ export const validateRecipient = (currency: CryptoCurrency, recipient: string) => {
17
+ let recipientError: Error | null = null;
18
+ const recipientWarning = null;
19
+ if (!recipient) {
20
+ recipientError = new RecipientRequired("");
21
+ } else if (validateAddress(recipient) !== ValidationResult.VALID) {
22
+ recipientError = new InvalidAddress(undefined, {
23
+ currencyName: currency.name,
24
+ });
25
+ }
26
+ return Promise.resolve({ recipientError, recipientWarning });
27
+ };
28
+
29
+ const prepareTransaction = async (
30
+ account: TezosAccount,
31
+ transaction: Transaction,
32
+ ): Promise<Transaction> => {
33
+ const { tezosResources } = account;
34
+ if (!tezosResources) throw new Error("tezosResources is missing");
35
+
36
+ if (account.balance.lte(0)) {
37
+ return Promise.resolve(transaction);
38
+ }
39
+
40
+ // basic check to confirm the transaction is "complete"
41
+ if (transaction.mode !== "undelegate") {
42
+ if (!transaction.recipient) {
43
+ return Promise.resolve(transaction);
44
+ }
45
+
46
+ const { recipientError } = await validateRecipient(account.currency, transaction.recipient);
47
+ if (recipientError) {
48
+ return Promise.resolve(transaction);
49
+ }
50
+ }
51
+
52
+ const encodedPubKey = b58cencode(
53
+ compressPublicKey(Buffer.from(account.xpub || "", "hex"), DerivationType.ED25519),
54
+ prefix[Prefix.EDPK],
55
+ );
56
+
57
+ const tezos = new TezosToolkit(getEnv("API_TEZOS_NODE"));
58
+
59
+ tezos.setProvider({
60
+ signer: {
61
+ publicKeyHash: async () => account.freshAddress,
62
+ publicKey: async () => encodedPubKey,
63
+ sign: () => Promise.reject(new Error("unsupported")),
64
+ secretKey: () => Promise.reject(new Error("unsupported")),
65
+ },
66
+ });
67
+
68
+ const tx: Transaction = { ...transaction, taquitoError: null };
69
+
70
+ let amount = transaction.amount;
71
+ if (transaction.useAllAmount) {
72
+ amount = new BigNumber(1); // send max do a pre-estimation with minimum amount (taquito refuses 0)
73
+ }
74
+
75
+ try {
76
+ let estimate: Estimate;
77
+ switch (transaction.mode) {
78
+ case "send":
79
+ estimate = await tezos.estimate.transfer({
80
+ mutez: true,
81
+ to: transaction.recipient,
82
+ amount: amount.toNumber(),
83
+ storageLimit: DEFAULT_STORAGE_LIMIT.ORIGINATION, // https://github.com/TezTech/eztz/blob/master/PROTO_003_FEES.md for originating an account
84
+ });
85
+ break;
86
+ case "delegate":
87
+ estimate = await tezos.estimate.setDelegate({
88
+ source: account.freshAddress,
89
+ delegate: transaction.recipient,
90
+ });
91
+ break;
92
+ case "undelegate":
93
+ estimate = await tezos.estimate.setDelegate({
94
+ source: account.freshAddress,
95
+ });
96
+ break;
97
+ default:
98
+ throw new Error("unsupported mode=" + transaction.mode);
99
+ }
100
+
101
+ if (tx.useAllAmount) {
102
+ const totalFees = estimate.suggestedFeeMutez + estimate.burnFeeMutez;
103
+ const maxAmount = account.balance
104
+ .minus(totalFees + (tezosResources.revealed ? 0 : DEFAULT_FEE.REVEAL))
105
+ .toNumber();
106
+ // from https://github.com/ecadlabs/taquito/blob/a70c64c4b105381bb9f1d04c9c70e8ef26e9241c/integration-tests/contract-empty-implicit-account-into-new-implicit-account.spec.ts#L33
107
+ // Temporary fix, see https://gitlab.com/tezos/tezos/-/issues/1754
108
+ // we need to increase the gasLimit and fee returned by the estimation
109
+ const gasBuffer = 500;
110
+ const MINIMAL_FEE_PER_GAS_MUTEZ = 0.1;
111
+ const increasedFee = (gasBuffer: number, opSize: number) => {
112
+ return gasBuffer * MINIMAL_FEE_PER_GAS_MUTEZ + opSize;
113
+ };
114
+ const incr = increasedFee(gasBuffer, Number(estimate.opSize));
115
+ tx.fees = new BigNumber(estimate.suggestedFeeMutez + incr);
116
+ tx.gasLimit = new BigNumber(estimate.gasLimit + gasBuffer);
117
+ tx.amount = maxAmount - incr > 0 ? new BigNumber(maxAmount - incr) : new BigNumber(0);
118
+ } else {
119
+ tx.fees = new BigNumber(estimate.suggestedFeeMutez);
120
+ tx.gasLimit = new BigNumber(estimate.gasLimit);
121
+ tx.storageLimit = new BigNumber(estimate.storageLimit);
122
+ }
123
+
124
+ tx.storageLimit = new BigNumber(estimate.storageLimit);
125
+ tx.estimatedFees = tx.fees;
126
+ if (!tezosResources.revealed) {
127
+ tx.estimatedFees = tx.estimatedFees.plus(DEFAULT_FEE.REVEAL);
128
+ }
129
+ } catch (e) {
130
+ if (typeof e !== "object" || !e) throw e;
131
+ if ("id" in e) {
132
+ tx.taquitoError = (e as { id: string }).id;
133
+ log("taquito-error", "taquito got error " + tx.taquitoError);
134
+ } else if ("status" in e) {
135
+ // in case of http 400, log & ignore (more case to handle)
136
+ log("taquito-network-error", String((e as unknown as { message: string }).message || ""), {
137
+ transaction: tx,
138
+ });
139
+ throw e;
140
+ } else {
141
+ throw e;
142
+ }
143
+ }
144
+
145
+ // nothing changed
146
+ if (
147
+ bnEq(tx.estimatedFees, transaction.estimatedFees) &&
148
+ bnEq(tx.fees, transaction.fees) &&
149
+ bnEq(tx.gasLimit, transaction.gasLimit) &&
150
+ bnEq(tx.storageLimit, transaction.storageLimit) &&
151
+ bnEq(tx.amount, transaction.amount) &&
152
+ tx.taquitoError === transaction.taquitoError
153
+ ) {
154
+ return transaction;
155
+ }
156
+
157
+ return tx;
158
+ };
159
+
160
+ export default prepareTransaction;