@ledgerhq/live-common 21.21.3 → 21.23.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 (266) hide show
  1. package/lib/account/formatters.d.ts.map +1 -1
  2. package/lib/account/formatters.js +1 -0
  3. package/lib/account/formatters.js.map +1 -1
  4. package/lib/account/support.d.ts.map +1 -1
  5. package/lib/account/support.js +1 -0
  6. package/lib/account/support.js.map +1 -1
  7. package/lib/apps/polyfill.d.ts.map +1 -1
  8. package/lib/apps/polyfill.js +1 -0
  9. package/lib/apps/polyfill.js.map +1 -1
  10. package/lib/bot/engine.js +1 -1
  11. package/lib/bot/engine.js.map +1 -1
  12. package/lib/bot/specs.d.ts +1 -0
  13. package/lib/bot/specs.d.ts.map +1 -1
  14. package/lib/bot/specs.js +3 -1
  15. package/lib/bot/specs.js.map +1 -1
  16. package/lib/data/icons/react/sol.js +4 -2
  17. package/lib/data/icons/react/sol.js.map +1 -1
  18. package/lib/data/icons/reactNative/sol.js +4 -2
  19. package/lib/data/icons/reactNative/sol.js.map +1 -1
  20. package/lib/derivation.d.ts.map +1 -1
  21. package/lib/derivation.js +0 -3
  22. package/lib/derivation.js.map +1 -1
  23. package/lib/env.d.ts +5 -10
  24. package/lib/env.d.ts.map +1 -1
  25. package/lib/env.js +1 -6
  26. package/lib/env.js.map +1 -1
  27. package/lib/env.react.d.ts +1 -1
  28. package/lib/env.react.d.ts.map +1 -1
  29. package/lib/families/algorand/account.d.ts.map +1 -1
  30. package/lib/families/algorand/account.js +0 -4
  31. package/lib/families/algorand/account.js.map +1 -1
  32. package/lib/families/algorand/api/algodv2.d.ts +5 -0
  33. package/lib/families/algorand/api/algodv2.d.ts.map +1 -0
  34. package/lib/families/algorand/api/algodv2.js +118 -0
  35. package/lib/families/algorand/api/algodv2.js.map +1 -0
  36. package/lib/families/algorand/api/algodv2.types.d.ts +24 -0
  37. package/lib/families/algorand/api/algodv2.types.d.ts.map +1 -0
  38. package/lib/families/algorand/api/algodv2.types.js +3 -0
  39. package/lib/families/algorand/api/algodv2.types.js.map +1 -0
  40. package/lib/families/algorand/api/index.d.ts +5 -0
  41. package/lib/families/algorand/api/index.d.ts.map +1 -0
  42. package/lib/families/algorand/api/index.js +17 -0
  43. package/lib/families/algorand/api/index.js.map +1 -0
  44. package/lib/families/algorand/api/indexer.d.ts +3 -0
  45. package/lib/families/algorand/api/indexer.d.ts.map +1 -0
  46. package/lib/families/algorand/api/indexer.js +134 -0
  47. package/lib/families/algorand/api/indexer.js.map +1 -0
  48. package/lib/families/algorand/api/indexer.types.d.ts +35 -0
  49. package/lib/families/algorand/api/indexer.types.d.ts.map +1 -0
  50. package/lib/families/algorand/api/indexer.types.js +10 -0
  51. package/lib/families/algorand/api/indexer.types.js.map +1 -0
  52. package/lib/families/algorand/bridge/js.d.ts +8 -0
  53. package/lib/families/algorand/bridge/js.d.ts.map +1 -0
  54. package/lib/families/algorand/bridge/js.js +85 -0
  55. package/lib/families/algorand/bridge/js.js.map +1 -0
  56. package/lib/families/algorand/bridge/libcore.d.ts +3 -3
  57. package/lib/families/algorand/bridge/libcore.d.ts.map +1 -1
  58. package/lib/families/algorand/bridge/libcore.js.map +1 -1
  59. package/lib/families/algorand/bridge/mock.d.ts +2 -2
  60. package/lib/families/algorand/bridge/mock.d.ts.map +1 -1
  61. package/lib/families/algorand/bridge/mock.js.map +1 -1
  62. package/lib/families/algorand/buildTransaction.d.ts +8 -0
  63. package/lib/families/algorand/buildTransaction.d.ts.map +1 -0
  64. package/lib/families/algorand/buildTransaction.js +101 -0
  65. package/lib/families/algorand/buildTransaction.js.map +1 -0
  66. package/lib/families/algorand/cli-transaction.js +1 -1
  67. package/lib/families/algorand/cli-transaction.js.map +1 -1
  68. package/lib/families/algorand/deviceTransactionConfig.d.ts +2 -2
  69. package/lib/families/algorand/deviceTransactionConfig.d.ts.map +1 -1
  70. package/lib/families/algorand/deviceTransactionConfig.js +0 -13
  71. package/lib/families/algorand/deviceTransactionConfig.js.map +1 -1
  72. package/lib/families/algorand/hw-getAddress.d.ts.map +1 -1
  73. package/lib/families/algorand/hw-getAddress.js +2 -24
  74. package/lib/families/algorand/hw-getAddress.js.map +1 -1
  75. package/lib/families/algorand/js-broadcast.d.ts +9 -0
  76. package/lib/families/algorand/js-broadcast.d.ts.map +1 -0
  77. package/lib/families/algorand/js-broadcast.js +63 -0
  78. package/lib/families/algorand/js-broadcast.js.map +1 -0
  79. package/lib/families/algorand/js-estimateMaxSpendable.d.ts +9 -0
  80. package/lib/families/algorand/js-estimateMaxSpendable.d.ts.map +1 -0
  81. package/lib/families/algorand/js-estimateMaxSpendable.js +89 -0
  82. package/lib/families/algorand/js-estimateMaxSpendable.js.map +1 -0
  83. package/lib/families/algorand/js-getFeesForTransaction.d.ts +5 -0
  84. package/lib/families/algorand/js-getFeesForTransaction.d.ts.map +1 -0
  85. package/lib/families/algorand/js-getFeesForTransaction.js +69 -0
  86. package/lib/families/algorand/js-getFeesForTransaction.js.map +1 -0
  87. package/lib/families/algorand/js-getTransactionStatus.d.ts +11 -0
  88. package/lib/families/algorand/js-getTransactionStatus.d.ts.map +1 -0
  89. package/lib/families/algorand/js-getTransactionStatus.js +201 -0
  90. package/lib/families/algorand/js-getTransactionStatus.js.map +1 -0
  91. package/lib/families/algorand/js-prepareTransaction.d.ts +5 -0
  92. package/lib/families/algorand/js-prepareTransaction.d.ts.map +1 -0
  93. package/lib/families/algorand/js-prepareTransaction.js +101 -0
  94. package/lib/families/algorand/js-prepareTransaction.js.map +1 -0
  95. package/lib/families/algorand/js-signOperation.d.ts +10 -0
  96. package/lib/families/algorand/js-signOperation.d.ts.map +1 -0
  97. package/lib/families/algorand/js-signOperation.js +164 -0
  98. package/lib/families/algorand/js-signOperation.js.map +1 -0
  99. package/lib/families/algorand/js-synchronization.d.ts +10 -0
  100. package/lib/families/algorand/js-synchronization.d.ts.map +1 -0
  101. package/lib/families/algorand/js-synchronization.js +411 -0
  102. package/lib/families/algorand/js-synchronization.js.map +1 -0
  103. package/lib/families/algorand/libcore-buildTransaction.d.ts +2 -2
  104. package/lib/families/algorand/libcore-buildTransaction.d.ts.map +1 -1
  105. package/lib/families/algorand/libcore-getFeesForTransaction.d.ts +4 -4
  106. package/lib/families/algorand/libcore-getFeesForTransaction.d.ts.map +1 -1
  107. package/lib/families/algorand/libcore-getFeesForTransaction.js +2 -2
  108. package/lib/families/algorand/libcore-getFeesForTransaction.js.map +1 -1
  109. package/lib/families/algorand/libcore-postBuildAccount.d.ts.map +1 -1
  110. package/lib/families/algorand/libcore-postBuildAccount.js +5 -11
  111. package/lib/families/algorand/libcore-postBuildAccount.js.map +1 -1
  112. package/lib/families/algorand/libcore-signOperation.d.ts +2 -2
  113. package/lib/families/algorand/libcore-signOperation.d.ts.map +1 -1
  114. package/lib/families/algorand/libcore-signOperation.js.map +1 -1
  115. package/lib/families/algorand/logic.d.ts +10 -0
  116. package/lib/families/algorand/logic.d.ts.map +1 -1
  117. package/lib/families/algorand/logic.js +79 -1
  118. package/lib/families/algorand/logic.js.map +1 -1
  119. package/lib/families/algorand/mock.d.ts.map +1 -1
  120. package/lib/families/algorand/mock.js +4 -11
  121. package/lib/families/algorand/mock.js.map +1 -1
  122. package/lib/families/algorand/serialization.js +4 -4
  123. package/lib/families/algorand/serialization.js.map +1 -1
  124. package/lib/families/algorand/specs.d.ts +2 -2
  125. package/lib/families/algorand/specs.d.ts.map +1 -1
  126. package/lib/families/algorand/specs.js +8 -16
  127. package/lib/families/algorand/specs.js.map +1 -1
  128. package/lib/families/algorand/speculos-deviceActions.d.ts +2 -2
  129. package/lib/families/algorand/speculos-deviceActions.d.ts.map +1 -1
  130. package/lib/families/algorand/speculos-deviceActions.js +4 -0
  131. package/lib/families/algorand/speculos-deviceActions.js.map +1 -1
  132. package/lib/families/algorand/test-dataset.d.ts +2 -2
  133. package/lib/families/algorand/test-dataset.d.ts.map +1 -1
  134. package/lib/families/algorand/test-dataset.js +1 -2
  135. package/lib/families/algorand/test-dataset.js.map +1 -1
  136. package/lib/families/algorand/tokens.d.ts.map +1 -1
  137. package/lib/families/algorand/tokens.js.map +1 -1
  138. package/lib/families/algorand/transaction.d.ts +5 -5
  139. package/lib/families/algorand/transaction.d.ts.map +1 -1
  140. package/lib/families/algorand/transaction.js.map +1 -1
  141. package/lib/families/algorand/types.d.ts +7 -5
  142. package/lib/families/algorand/types.d.ts.map +1 -1
  143. package/lib/families/algorand/types.js.map +1 -1
  144. package/lib/families/bitcoin/js-prepareTransaction.d.ts.map +1 -1
  145. package/lib/families/bitcoin/js-prepareTransaction.js +3 -2
  146. package/lib/families/bitcoin/js-prepareTransaction.js.map +1 -1
  147. package/lib/families/bitcoin/js-synchronisation.d.ts.map +1 -1
  148. package/lib/families/bitcoin/js-synchronisation.js +3 -2
  149. package/lib/families/bitcoin/js-synchronisation.js.map +1 -1
  150. package/lib/families/bitcoin/wallet-btc/crypto/decred.d.ts.map +1 -1
  151. package/lib/families/bitcoin/wallet-btc/crypto/decred.js +3 -4
  152. package/lib/families/bitcoin/wallet-btc/crypto/decred.js.map +1 -1
  153. package/lib/families/tezos/bridge/js.d.ts.map +1 -1
  154. package/lib/families/tezos/bridge/js.js +90 -50
  155. package/lib/families/tezos/bridge/js.js.map +1 -1
  156. package/lib/families/tezos/bridge/libcore.d.ts.map +1 -1
  157. package/lib/families/tezos/bridge/libcore.js +2 -1
  158. package/lib/families/tezos/bridge/libcore.js.map +1 -1
  159. package/lib/families/tezos/bridge/mock.d.ts.map +1 -1
  160. package/lib/families/tezos/bridge/mock.js +2 -1
  161. package/lib/families/tezos/bridge/mock.js.map +1 -1
  162. package/lib/families/tezos/signOperation.d.ts.map +1 -1
  163. package/lib/families/tezos/signOperation.js +28 -19
  164. package/lib/families/tezos/signOperation.js.map +1 -1
  165. package/lib/families/tezos/specs.d.ts.map +1 -1
  166. package/lib/families/tezos/specs.js +8 -4
  167. package/lib/families/tezos/specs.js.map +1 -1
  168. package/lib/families/tezos/speculos-deviceActions.js +6 -7
  169. package/lib/families/tezos/speculos-deviceActions.js.map +1 -1
  170. package/lib/families/tezos/synchronisation.d.ts.map +1 -1
  171. package/lib/families/tezos/synchronisation.js +7 -4
  172. package/lib/families/tezos/synchronisation.js.map +1 -1
  173. package/lib/families/tezos/synchronisation.test.d.ts.map +1 -1
  174. package/lib/families/tezos/synchronisation.test.js +0 -3
  175. package/lib/families/tezos/synchronisation.test.js.map +1 -1
  176. package/lib/families/tezos/test-dataset.d.ts +2 -2
  177. package/lib/families/tezos/test-dataset.d.ts.map +1 -1
  178. package/lib/families/tezos/test-dataset.js +45 -319
  179. package/lib/families/tezos/test-dataset.js.map +1 -1
  180. package/lib/families/tezos/transaction.d.ts +2 -2
  181. package/lib/families/tezos/transaction.d.ts.map +1 -1
  182. package/lib/families/tezos/transaction.js +4 -4
  183. package/lib/families/tezos/transaction.js.map +1 -1
  184. package/lib/families/tezos/types.d.ts +2 -0
  185. package/lib/families/tezos/types.d.ts.map +1 -1
  186. package/lib/families/tezos/types.js.map +1 -1
  187. package/lib/generated/bridge/js.d.ts +4 -0
  188. package/lib/generated/bridge/js.d.ts.map +1 -1
  189. package/lib/generated/bridge/js.js +26 -24
  190. package/lib/generated/bridge/js.js.map +1 -1
  191. package/lib/generated/bridge/libcore.d.ts +1 -1
  192. package/lib/generated/bridge/mock.d.ts +1 -1
  193. package/lib/generated/specs.d.ts +1 -1
  194. package/lib/generated/speculos-deviceActions.d.ts +1 -1
  195. package/lib/generated/test-dataset.d.ts +1 -1
  196. package/lib/generated/transaction.d.ts +4 -4
  197. package/lib/libcore/buildAccount/index.d.ts.map +1 -1
  198. package/lib/libcore/buildAccount/index.js +0 -1
  199. package/lib/libcore/buildAccount/index.js.map +1 -1
  200. package/lib/mock/account.js +21 -21
  201. package/lib/mock/account.js.map +1 -1
  202. package/lib/types/operation.d.ts +1 -1
  203. package/lib/types/operation.d.ts.map +1 -1
  204. package/package.json +10 -9
  205. package/src/__tests__/__snapshots__/all.libcore.ts.snap +0 -107
  206. package/src/account/formatters.ts +1 -0
  207. package/src/account/support.ts +1 -0
  208. package/src/apps/polyfill.ts +1 -0
  209. package/src/bot/engine.ts +1 -1
  210. package/src/bot/specs.ts +7 -1
  211. package/src/data/icons/react/sol.tsx +1 -1
  212. package/src/data/icons/reactNative/sol.tsx +1 -1
  213. package/src/data/icons/svg/SOL.svg +1 -3
  214. package/src/derivation.ts +0 -2
  215. package/src/env.ts +1 -6
  216. package/src/families/algorand/account.ts +0 -9
  217. package/src/families/algorand/api/algodv2.ts +68 -0
  218. package/src/families/algorand/api/algodv2.types.ts +27 -0
  219. package/src/families/algorand/api/index.ts +4 -0
  220. package/src/families/algorand/api/indexer.ts +99 -0
  221. package/src/families/algorand/api/indexer.types.ts +41 -0
  222. package/src/families/algorand/bridge/js.ts +46 -0
  223. package/src/families/algorand/bridge/libcore.ts +4 -4
  224. package/src/families/algorand/bridge/mock.ts +3 -3
  225. package/src/families/algorand/buildTransaction.ts +100 -0
  226. package/src/families/algorand/cli-transaction.ts +1 -1
  227. package/src/families/algorand/deviceTransactionConfig.ts +2 -16
  228. package/src/families/algorand/hw-getAddress.ts +1 -10
  229. package/src/families/algorand/js-broadcast.ts +17 -0
  230. package/src/families/algorand/js-estimateMaxSpendable.ts +51 -0
  231. package/src/families/algorand/js-getFeesForTransaction.ts +25 -0
  232. package/src/families/algorand/js-getTransactionStatus.ts +178 -0
  233. package/src/families/algorand/js-prepareTransaction.ts +42 -0
  234. package/src/families/algorand/js-signOperation.ts +145 -0
  235. package/src/families/algorand/js-synchronization.ts +433 -0
  236. package/src/families/algorand/libcore-buildTransaction.ts +2 -2
  237. package/src/families/algorand/libcore-getFeesForTransaction.ts +4 -4
  238. package/src/families/algorand/libcore-postBuildAccount.ts +2 -7
  239. package/src/families/algorand/libcore-signOperation.ts +2 -2
  240. package/src/families/algorand/logic.ts +47 -0
  241. package/src/families/algorand/mock.ts +2 -12
  242. package/src/families/algorand/serialization.ts +4 -4
  243. package/src/families/algorand/specs.ts +16 -22
  244. package/src/families/algorand/speculos-deviceActions.ts +87 -82
  245. package/src/families/algorand/test-dataset.ts +5 -6
  246. package/src/families/algorand/tokens.ts +1 -0
  247. package/src/families/algorand/transaction.ts +13 -4
  248. package/src/families/algorand/types.ts +10 -5
  249. package/src/families/bitcoin/js-prepareTransaction.ts +3 -2
  250. package/src/families/bitcoin/js-synchronisation.ts +3 -2
  251. package/src/families/bitcoin/wallet-btc/crypto/decred.ts +3 -4
  252. package/src/families/tezos/bridge/js.ts +77 -36
  253. package/src/families/tezos/bridge/libcore.ts +1 -0
  254. package/src/families/tezos/bridge/mock.ts +1 -0
  255. package/src/families/tezos/signOperation.ts +19 -8
  256. package/src/families/tezos/specs.ts +16 -5
  257. package/src/families/tezos/speculos-deviceActions.ts +5 -5
  258. package/src/families/tezos/synchronisation.test.ts +0 -3
  259. package/src/families/tezos/synchronisation.ts +6 -3
  260. package/src/families/tezos/test-dataset.ts +33 -363
  261. package/src/families/tezos/transaction.ts +7 -1
  262. package/src/families/tezos/types.ts +2 -0
  263. package/src/generated/bridge/js.ts +3 -0
  264. package/src/libcore/buildAccount/index.ts +1 -2
  265. package/src/mock/account.ts +27 -27
  266. package/src/types/operation.ts +9 -4
@@ -1,6 +1,6 @@
1
1
  import expect from "expect";
2
2
  import invariant from "invariant";
3
- import type { Transaction } from "./types";
3
+ import type { AlgorandTransaction } from "./types";
4
4
  import { getCryptoCurrencyById, parseCurrencyUnit } from "../../currencies";
5
5
  import { isAccountEmpty } from "../../account";
6
6
  import { pickSiblings } from "../../bot/specs";
@@ -12,18 +12,9 @@ import { listTokensForCryptoCurrency } from "../../currencies";
12
12
  import { extractTokenId } from "./tokens";
13
13
  import { DeviceModelId } from "@ledgerhq/devices";
14
14
  const currency = getCryptoCurrencyById("algorand");
15
- // Minimum fees
16
- const minFees = parseCurrencyUnit(currency.units[0], "0.001");
17
15
  // Minimum balance required for a new non-ASA account
18
16
  const minBalanceNewAccount = parseCurrencyUnit(currency.units[0], "0.1");
19
17
 
20
- // Spendable balance for a non-ASA account
21
- const getSpendableBalance = (maxSpendable) => {
22
- maxSpendable = maxSpendable.minus(minFees);
23
- invariant(maxSpendable.gt(0), "Spendable balance is too low");
24
- return maxSpendable;
25
- };
26
-
27
18
  // Ensure that, when the recipient corresponds to an empty account,
28
19
  // the amount to send is greater or equal to the required minimum
29
20
  // balance for such a recipient
@@ -74,7 +65,7 @@ const getRandomAssetId = (account) => {
74
65
  return sample(diff);
75
66
  };
76
67
 
77
- const algorand: AppSpec<Transaction> = {
68
+ const algorand: AppSpec<AlgorandTransaction> = {
78
69
  name: "Algorand",
79
70
  currency,
80
71
  appQuery: {
@@ -86,11 +77,11 @@ const algorand: AppSpec<Transaction> = {
86
77
  name: "move ~50%",
87
78
  maxRun: 2,
88
79
  transaction: ({ account, siblings, bridge, maxSpendable }) => {
89
- const spendableBalance = getSpendableBalance(maxSpendable);
80
+ invariant(maxSpendable.gt(0), "Spendable balance is too low");
90
81
  const sibling = pickSiblings(siblings, 4);
91
82
  const recipient = sibling.freshAddress;
92
83
  const transaction = bridge.createTransaction(account);
93
- const amount = spendableBalance
84
+ const amount = maxSpendable
94
85
  .div(1.9 + 0.2 * Math.random())
95
86
  .integerValue();
96
87
  checkSendableToEmptyAccount(amount, sibling);
@@ -119,10 +110,10 @@ const algorand: AppSpec<Transaction> = {
119
110
  name: "send max",
120
111
  maxRun: 1,
121
112
  transaction: ({ account, siblings, bridge, maxSpendable }) => {
122
- const spendableBalance = getSpendableBalance(maxSpendable);
113
+ invariant(maxSpendable.gt(0), "Spendable balance is too low");
123
114
  const sibling = pickSiblings(siblings, 4);
124
115
  // Send the full spendable balance
125
- const amount = spendableBalance;
116
+ const amount = maxSpendable;
126
117
  checkSendableToEmptyAccount(amount, sibling);
127
118
  return {
128
119
  transaction: bridge.createTransaction(account),
@@ -147,7 +138,7 @@ const algorand: AppSpec<Transaction> = {
147
138
  name: "send ASA ~50%",
148
139
  maxRun: 2,
149
140
  transaction: ({ account, siblings, bridge, maxSpendable }) => {
150
- invariant(maxSpendable.gt(minFees), "Spendable balance is too low");
141
+ invariant(maxSpendable.gt(0), "Spendable balance is too low");
151
142
  const subAccount = sample(getAssetsWithBalance(account));
152
143
  invariant(
153
144
  subAccount && subAccount.type === "TokenAccount",
@@ -161,7 +152,7 @@ const algorand: AppSpec<Transaction> = {
161
152
  const amount = subAccount.balance
162
153
  .div(1.9 + 0.2 * Math.random())
163
154
  .integerValue();
164
- const updates: Array<Partial<Transaction>> = [
155
+ const updates: Array<Partial<AlgorandTransaction>> = [
165
156
  {
166
157
  mode,
167
158
  subAccountId: subAccount.id,
@@ -196,10 +187,13 @@ const algorand: AppSpec<Transaction> = {
196
187
  name: "opt-In ASA available",
197
188
  maxRun: 1,
198
189
  transaction: ({ account, bridge, maxSpendable }) => {
199
- // maxSpendable is expected to be greater than 100,000 micro-Algos (+ 1,000 for fees)
190
+ // maxSpendable is expected to be greater than 100,000 micro-Algos
200
191
  // corresponding to the requirement that the main account will have
201
192
  // one more ASA after the opt-in; its minimum balance is updated accordingly
202
- invariant(maxSpendable.gt(new BigNumber(101000)), "balance is too low");
193
+ invariant(
194
+ maxSpendable.gt(new BigNumber(100000)),
195
+ "Spendable balance is too low"
196
+ );
203
197
  const transaction = bridge.createTransaction(account);
204
198
  const mode = "optIn";
205
199
  const assetId = getRandomAssetId(account);
@@ -207,7 +201,7 @@ const algorand: AppSpec<Transaction> = {
207
201
  ? account.subAccounts.find((a) => a.id.includes(assetId as string))
208
202
  : null;
209
203
  invariant(!subAccount, "already opt-in");
210
- const updates: Array<Partial<Transaction>> = [
204
+ const updates: Array<Partial<AlgorandTransaction>> = [
211
205
  {
212
206
  mode,
213
207
  },
@@ -241,10 +235,10 @@ const algorand: AppSpec<Transaction> = {
241
235
  invariant(rewards && rewards.gt(0), "No pending rewards");
242
236
  // Ensure that the rewards can effectively be claimed
243
237
  // (fees have to be paid in order to claim the rewards)
244
- invariant(maxSpendable.gt(minFees), "Spendable balance is too low");
238
+ invariant(maxSpendable.gt(0), "Spendable balance is too low");
245
239
  const transaction = bridge.createTransaction(account);
246
240
  const mode = "claimReward";
247
- const updates: Array<Partial<Transaction>> = [
241
+ const updates: Array<Partial<AlgorandTransaction>> = [
248
242
  {
249
243
  mode,
250
244
  },
@@ -1,5 +1,5 @@
1
1
  import type { DeviceAction } from "../../bot/types";
2
- import type { Transaction } from "./types";
2
+ import type { AlgorandTransaction } from "./types";
3
3
  import { formatCurrencyUnit, findTokenById } from "../../currencies";
4
4
  import { deviceActionFlow } from "../../bot/specs";
5
5
  import { extractTokenId, addPrefixToken } from "./tokens";
@@ -11,88 +11,93 @@ const expectedAmount = ({ account, status }) =>
11
11
  disableRounding: true,
12
12
  });
13
13
 
14
- const acceptTransaction: DeviceAction<Transaction, any> = deviceActionFlow({
15
- steps: [
16
- {
17
- title: "Txn Type",
18
- button: "Rr",
19
- expectedValue: ({ transaction }) =>
20
- transaction.subAccountId ? "Asset xfer" : "Payment",
21
- },
22
- {
23
- title: "Asset xfer",
24
- button: "Rr",
25
- },
26
- {
27
- title: "Payment",
28
- button: "Rr",
29
- },
30
- {
31
- title: "Fee",
32
- button: "Rr",
33
- expectedValue: ({ account, status }) =>
34
- formatCurrencyUnit(account.unit, status.estimatedFees, {
35
- disableRounding: true,
36
- }),
37
- },
38
- {
39
- title: "Asset ID",
40
- button: "Rr",
41
- expectedValue: ({ transaction }) => {
42
- const id = transaction.assetId
43
- ? extractTokenId(transaction.assetId)
44
- : transaction.subAccountId
45
- ? extractTokenId(transaction.subAccountId)
46
- : "";
47
- const token = findTokenById(addPrefixToken(id));
48
- return token ? displayTokenValue(token) : `#${id}`;
14
+ const acceptTransaction: DeviceAction<AlgorandTransaction, any> =
15
+ deviceActionFlow({
16
+ steps: [
17
+ {
18
+ title: "Txn Type",
19
+ button: "Rr",
20
+ expectedValue: ({ transaction }) =>
21
+ transaction.subAccountId ? "Asset xfer" : "Payment",
49
22
  },
50
- },
51
- {
52
- title: "Asset amt",
53
- button: "Rr",
54
- expectedValue: ({ transaction, status }) =>
55
- transaction.mode === "optIn" ? "0" : status.amount.toString(),
56
- },
57
- {
58
- title: "Receiver",
59
- button: "Rr",
60
- expectedValue: ({ transaction }) => transaction.recipient,
61
- },
62
- {
63
- title: "Asset dst",
64
- button: "Rr",
65
- expectedValue: ({ transaction }) => transaction.recipient,
66
- },
67
- {
68
- title: "Amount",
69
- button: "Rr",
70
- expectedValue: ({ account, status, transaction }) =>
71
- transaction.mode === "claimReward"
72
- ? "0"
73
- : expectedAmount({
74
- account,
75
- status,
76
- }),
77
- },
78
- {
79
- title: "Sign",
80
- button: "LRlr",
81
- },
82
- {
83
- title: "Review",
84
- button: "Rr",
85
- },
86
- {
87
- title: "Genesis ID",
88
- button: "Rr",
89
- }, // Only on testnet
90
- {
91
- title: "Genesis hash",
92
- button: "Rr",
93
- }, // Only on testnet
94
- ],
95
- });
23
+ {
24
+ title: "Asset xfer",
25
+ button: "Rr",
26
+ },
27
+ {
28
+ title: "Payment",
29
+ button: "Rr",
30
+ },
31
+ {
32
+ title: "Fee",
33
+ button: "Rr",
34
+ expectedValue: ({ account, status }) =>
35
+ formatCurrencyUnit(account.unit, status.estimatedFees, {
36
+ disableRounding: true,
37
+ }),
38
+ },
39
+ {
40
+ title: "Asset ID",
41
+ button: "Rr",
42
+ expectedValue: ({ transaction }) => {
43
+ const id = transaction.assetId
44
+ ? extractTokenId(transaction.assetId)
45
+ : transaction.subAccountId
46
+ ? extractTokenId(transaction.subAccountId)
47
+ : "";
48
+ const token = findTokenById(addPrefixToken(id));
49
+ return token ? displayTokenValue(token) : `#${id}`;
50
+ },
51
+ },
52
+ {
53
+ title: "Asset amt",
54
+ button: "Rr",
55
+ expectedValue: ({ transaction, status }) =>
56
+ transaction.mode === "optIn" ? "0" : status.amount.toString(),
57
+ },
58
+ {
59
+ title: "Sender",
60
+ button: "Rr",
61
+ },
62
+ {
63
+ title: "Receiver",
64
+ button: "Rr",
65
+ expectedValue: ({ transaction }) => transaction.recipient,
66
+ },
67
+ {
68
+ title: "Asset dst",
69
+ button: "Rr",
70
+ expectedValue: ({ transaction }) => transaction.recipient,
71
+ },
72
+ {
73
+ title: "Amount",
74
+ button: "Rr",
75
+ expectedValue: ({ account, status, transaction }) =>
76
+ transaction.mode === "claimReward"
77
+ ? "0"
78
+ : expectedAmount({
79
+ account,
80
+ status,
81
+ }),
82
+ },
83
+ {
84
+ title: "Sign",
85
+ button: "LRlr",
86
+ },
87
+ {
88
+ title: "Review",
89
+ button: "Rr",
90
+ },
91
+ {
92
+ title: "Genesis ID",
93
+ button: "Rr",
94
+ }, // Only on testnet
95
+ {
96
+ title: "Genesis hash",
97
+ button: "Rr",
98
+ }, // Only on testnet
99
+ ],
100
+ });
96
101
  export default {
97
102
  acceptTransaction,
98
103
  };
@@ -6,19 +6,18 @@ import {
6
6
  NotEnoughBalanceBecauseDestinationNotCreated,
7
7
  } from "@ledgerhq/errors";
8
8
  import { AlgorandASANotOptInInRecipient } from "../../errors";
9
- import type { Transaction } from "./types";
9
+ import type { AlgorandTransaction } from "./types";
10
10
  // const notCreatedAlgorandAddress =
11
11
  // "ZBILW5BPM7AQU54YQZICSGS4J7KJ2XV6OC3DFUQ7BB4DVLYKKUEVWDDBGM";
12
- const dataset: DatasetTest<Transaction> = {
12
+ const dataset: DatasetTest<AlgorandTransaction> = {
13
13
  implementations: ["libcore"],
14
14
  // test disabled. FIXME ctx LL-5485
15
15
  currencies: {} || {
16
16
  algorand: {
17
17
  FIXME_ignoreAccountFields: [
18
- "algorandResources.rewards", // We cant keep track of this since it's always move
19
- "algorandResources.rewardsAccumulated", // same
20
- "balance", // I think rewards are included
21
- "spendableBalance", // same since the rewards are included here
18
+ "algorandResources.rewards", // We cant keep track of this since it's always moving
19
+ "balance", // Rewards are included, same as above
20
+ "spendableBalance", // Same since the rewards are included here too
22
21
  ],
23
22
  scanAccounts: [
24
23
  {
@@ -1,4 +1,5 @@
1
1
  export const addPrefixToken = (tokenId: string) => `algorand/asa/${tokenId}`;
2
+
2
3
  export const extractTokenId = (tokenId: string) => {
3
4
  return tokenId.split("/")[2];
4
5
  };
@@ -1,5 +1,5 @@
1
1
  import { BigNumber } from "bignumber.js";
2
- import type { Transaction, TransactionRaw } from "./types";
2
+ import type { AlgorandTransaction, AlgorandTransactionRaw } from "./types";
3
3
  import {
4
4
  fromTransactionCommonRaw,
5
5
  toTransactionCommonRaw,
@@ -8,7 +8,14 @@ import type { Account } from "../../types";
8
8
  import { getAccountUnit } from "../../account";
9
9
  import { formatCurrencyUnit } from "../../currencies";
10
10
  export const formatTransaction = (
11
- { mode, subAccountId, amount, recipient, fees, useAllAmount }: Transaction,
11
+ {
12
+ mode,
13
+ subAccountId,
14
+ amount,
15
+ recipient,
16
+ fees,
17
+ useAllAmount,
18
+ }: AlgorandTransaction,
12
19
  mainAccount: Account
13
20
  ): string => {
14
21
  const account =
@@ -41,7 +48,9 @@ export const formatTransaction = (
41
48
  }`;
42
49
  };
43
50
 
44
- const fromTransactionRaw = (tr: TransactionRaw): Transaction => {
51
+ const fromTransactionRaw = (
52
+ tr: AlgorandTransactionRaw
53
+ ): AlgorandTransaction => {
45
54
  const common = fromTransactionCommonRaw(tr);
46
55
  return {
47
56
  ...common,
@@ -53,7 +62,7 @@ const fromTransactionRaw = (tr: TransactionRaw): Transaction => {
53
62
  };
54
63
  };
55
64
 
56
- const toTransactionRaw = (t: Transaction): TransactionRaw => {
65
+ const toTransactionRaw = (t: AlgorandTransaction): AlgorandTransactionRaw => {
57
66
  const common = toTransactionCommonRaw(t);
58
67
  return {
59
68
  ...common,
@@ -95,34 +95,39 @@ declare class CoreAlgorandOperation {
95
95
  }
96
96
 
97
97
  export type CoreCurrencySpecifics = Record<string, never>;
98
+
98
99
  export type AlgorandResources = {
99
100
  rewards: BigNumber;
100
- rewardsAccumulated: BigNumber;
101
+ // Ledger Live only supports a limited list of ASA (defined here https://github.com/LedgerHQ/ledgerjs/blob/master/packages/cryptoassets/data/asa.js)
102
+ // This is the actual number of ASA opted-in for the Algo account
103
+ nbAssets: number;
101
104
  };
102
105
  export type AlgorandResourcesRaw = {
103
106
  rewards: string;
104
- rewardsAccumulated: string;
107
+ nbAssets: number;
105
108
  };
106
- export type AlgorandOperationMode = "send" | "optIn" | "claimReward" | "optOut";
109
+ export type AlgorandOperationMode = "send" | "optIn" | "claimReward";
107
110
  export type {
108
111
  CoreAlgorandOperation,
109
112
  CoreAlgorandAccount,
110
113
  CoreAlgorandTransaction,
111
114
  };
112
- export type Transaction = TransactionCommon & {
115
+ export type AlgorandTransaction = TransactionCommon & {
113
116
  family: "algorand";
114
117
  mode: AlgorandOperationMode;
115
118
  fees: BigNumber | null | undefined;
116
119
  assetId: string | null | undefined;
117
120
  memo: string | null | undefined;
118
121
  };
119
- export type TransactionRaw = TransactionCommonRaw & {
122
+ export type AlgorandTransactionRaw = TransactionCommonRaw & {
120
123
  family: "algorand";
121
124
  mode: AlgorandOperationMode;
122
125
  fees: string | null | undefined;
123
126
  assetId: string | null | undefined;
124
127
  memo: string | null | undefined;
125
128
  };
129
+ export type Transaction = AlgorandTransaction;
130
+ export type TransactionRaw = AlgorandTransactionRaw;
126
131
  export type AlgorandOperation = Operation & {
127
132
  extra: AlgorandExtraTxInfo;
128
133
  };
@@ -18,8 +18,9 @@ const prepareTransaction = async (
18
18
  const feePerByte = inferFeePerByte(t, networkInfo);
19
19
 
20
20
  if (
21
- t.networkInfo === networkInfo &&
22
- (feePerByte === t.feePerByte || feePerByte.eq(t.feePerByte || 0))
21
+ (t.networkInfo === networkInfo &&
22
+ (feePerByte === t.feePerByte || feePerByte.eq(t.feePerByte || 0))) ||
23
+ t.feesStrategy === "custom"
23
24
  ) {
24
25
  // nothing changed
25
26
  return t;
@@ -140,8 +140,9 @@ const mapTxToOperations = (
140
140
  if (!accountAddresses.includes(output.address)) {
141
141
  // The output doesn't belong to this account
142
142
  if (
143
- tx.outputs.length === 1 || // The transaction has only 1 output
144
- output.output_index < changeOutputIndex // The output isn't the change output
143
+ accountInputs.length > 0 && // It's a SEND operation
144
+ (tx.outputs.length === 1 || // The transaction has only 1 output
145
+ output.output_index < changeOutputIndex) // The output isn't the change output
145
146
  ) {
146
147
  recipients.push(
147
148
  syncReplaceAddress
@@ -60,12 +60,11 @@ class BIP32 {
60
60
  hmacSHA512(key, data) {
61
61
  return createHmac("sha512", key).update(data).digest();
62
62
  }
63
- hash160(buffer) {
64
- const sha256Hash = createHash("sha256").update(buffer).digest();
65
- return createHash("rmd160").update(sha256Hash).digest();
63
+ hashSHA256(buffer) {
64
+ return createHash("sha256").update(buffer).digest();
66
65
  }
67
66
  fingerprint() {
68
- return this.hash160(this.pk()).slice(0, 4);
67
+ return this.hashSHA256(this.pk()).slice(0, 4);
69
68
  }
70
69
 
71
70
  toBase58() {
@@ -6,7 +6,6 @@ import {
6
6
  NotEnoughBalance,
7
7
  NotEnoughBalanceToDelegate,
8
8
  FeeTooHigh,
9
- NotSupportedLegacyAddress,
10
9
  InvalidAddressBecauseDestinationIsAlsoSource,
11
10
  RecommendUndelegation,
12
11
  } from "@ledgerhq/errors";
@@ -45,6 +44,7 @@ const createTransaction: () => Transaction = () => ({
45
44
  networkInfo: null,
46
45
  useAllAmount: false,
47
46
  taquitoError: null,
47
+ estimatedFees: null,
48
48
  });
49
49
 
50
50
  const updateTransaction = (t, patch) => ({ ...t, ...patch });
@@ -65,7 +65,7 @@ const getTransactionStatus = async (
65
65
  recipient?: Error;
66
66
  } = {};
67
67
 
68
- let estimatedFees = new BigNumber(t.fees || 0);
68
+ const estimatedFees = t.estimatedFees || new BigNumber(0);
69
69
 
70
70
  const { tezosResources } = account;
71
71
  if (!tezosResources) throw new Error("tezosResources is missing");
@@ -90,17 +90,6 @@ const getTransactionStatus = async (
90
90
  }
91
91
  }
92
92
 
93
- if (t.recipient.startsWith("KT") && !errors.recipient) {
94
- errors.recipient = new NotSupportedLegacyAddress();
95
- }
96
-
97
- // no fee / not enough balance already handled by taquitoError
98
- if (!tezosResources.revealed) {
99
- // FIXME
100
- // https://github.com/ecadlabs/taquito/commit/48a11cfaffe4c6bdfa6f04ebbd0b756f4b135865#diff-3b138622526cbaa55605b79011aa411652367136a3e92e43faecc654da3854e7
101
- estimatedFees = estimatedFees.plus(374 || DEFAULT_FEE.REVEAL);
102
- }
103
-
104
93
  if (t.mode === "send") {
105
94
  if (!errors.amount && t.amount.eq(0)) {
106
95
  errors.amount = new AmountRequired();
@@ -120,7 +109,11 @@ const getTransactionStatus = async (
120
109
  .lt(thresholdWarning)
121
110
  ) {
122
111
  if (isAccountDelegating(account)) {
123
- warnings.amount = new RecommendUndelegation();
112
+ if (t.useAllAmount) {
113
+ errors.amount = new RecommendUndelegation();
114
+ } else {
115
+ warnings.amount = new RecommendUndelegation();
116
+ }
124
117
  }
125
118
  }
126
119
  }
@@ -128,15 +121,22 @@ const getTransactionStatus = async (
128
121
  log("taquitoerror", String(t.taquitoError));
129
122
 
130
123
  // remap taquito errors
131
- if (t.taquitoError === "proto.010-PtGRANAD.contract.balance_too_low") {
124
+ if (t.taquitoError.endsWith("balance_too_low")) {
132
125
  if (t.mode === "send") {
133
126
  errors.amount = new NotEnoughBalance();
134
127
  } else {
135
128
  errors.amount = new NotEnoughBalanceToDelegate();
136
129
  }
130
+ } else {
131
+ // unidentified error case
132
+ errors.amount = new Error(t.taquitoError);
137
133
  }
138
134
  }
139
135
 
136
+ if (!errors.amount && account.balance.lte(0)) {
137
+ errors.amount = new NotEnoughBalance();
138
+ }
139
+
140
140
  const result = {
141
141
  errors,
142
142
  warnings,
@@ -154,8 +154,25 @@ const prepareTransaction = async (
154
154
  const { tezosResources } = account;
155
155
  if (!tezosResources) throw new Error("tezosResources is missing");
156
156
 
157
- const tezos = new TezosToolkit(getEnv("API_TEZOS_NODE"));
157
+ if (account.balance.lte(0)) {
158
+ return Promise.resolve(transaction);
159
+ }
158
160
 
161
+ // basic check to confirm the transaction is "complete"
162
+ if (transaction.mode !== "undelegate") {
163
+ if (!transaction.recipient) {
164
+ return Promise.resolve(transaction);
165
+ }
166
+ const { recipientError } = await validateRecipient(
167
+ account.currency,
168
+ transaction.recipient
169
+ );
170
+ if (recipientError) {
171
+ return Promise.resolve(transaction);
172
+ }
173
+ }
174
+
175
+ const tezos = new TezosToolkit(getEnv("API_TEZOS_NODE"));
159
176
  tezos.setProvider({
160
177
  signer: {
161
178
  publicKeyHash: async () => account.freshAddress,
@@ -165,20 +182,21 @@ const prepareTransaction = async (
165
182
  },
166
183
  });
167
184
 
168
- try {
169
- if (transaction.useAllAmount) {
170
- // taquito does not accept 0, so we do 1
171
- // only failing case is when the account precisely has fees + 1. which is
172
- // unlikely
173
- transaction.amount = new BigNumber(1);
174
- }
185
+ if (transaction.useAllAmount) {
186
+ // taquito does not accept 0, so we do 1
187
+ // only failing case is when the account precisely has fees + 1. which is
188
+ // unlikely
189
+ transaction.amount = new BigNumber(1);
190
+ }
175
191
 
192
+ try {
176
193
  let out;
177
194
  switch (transaction.mode) {
178
195
  case "send":
179
196
  out = await tezos.estimate.transfer({
197
+ mutez: true,
180
198
  to: transaction.recipient,
181
- amount: transaction.amount.div(10 ** 6).toNumber(),
199
+ amount: transaction.amount.toNumber(),
182
200
  });
183
201
  break;
184
202
  case "delegate":
@@ -193,14 +211,15 @@ const prepareTransaction = async (
193
211
  });
194
212
  break;
195
213
  default:
196
- throw "unsuported";
214
+ throw new Error("unsupported mode=" + transaction.mode);
197
215
  }
198
216
 
199
- transaction.fees = new BigNumber(out.suggestedFeeMutez);
200
- transaction.gasLimit = new BigNumber(out.gasLimit);
201
- transaction.storageLimit = new BigNumber(out.storageLimit);
202
-
203
217
  if (transaction.useAllAmount) {
218
+ const totalFees = out.suggestedFeeMutez + out.burnFeeMutez;
219
+ const maxAmount = account.balance
220
+ .minus(totalFees + (tezosResources.revealed ? 0 : DEFAULT_FEE.REVEAL))
221
+ .toNumber();
222
+ // from https://github.com/ecadlabs/taquito/blob/a70c64c4b105381bb9f1d04c9c70e8ef26e9241c/integration-tests/contract-empty-implicit-account-into-new-implicit-account.spec.ts#L33
204
223
  // Temporary fix, see https://gitlab.com/tezos/tezos/-/issues/1754
205
224
  // we need to increase the gasLimit and fee returned by the estimation
206
225
  const gasBuffer = 500;
@@ -208,15 +227,37 @@ const prepareTransaction = async (
208
227
  const increasedFee = (gasBuffer: number, opSize: number) => {
209
228
  return gasBuffer * MINIMAL_FEE_PER_GAS_MUTEZ + opSize;
210
229
  };
211
- transaction.fees = transaction.fees.plus(
212
- increasedFee(gasBuffer, Number(out.opSize))
230
+ const incr = increasedFee(gasBuffer, Number(out.opSize));
231
+ transaction.fees = new BigNumber(out.suggestedFeeMutez + incr);
232
+ transaction.gasLimit = new BigNumber(out.gasLimit + gasBuffer);
233
+ transaction.amount = new BigNumber(maxAmount - incr);
234
+ } else {
235
+ transaction.fees = new BigNumber(out.suggestedFeeMutez);
236
+ transaction.gasLimit = new BigNumber(out.gasLimit);
237
+ transaction.storageLimit = new BigNumber(out.storageLimit);
238
+ }
239
+
240
+ transaction.storageLimit = new BigNumber(out.storageLimit);
241
+ transaction.estimatedFees = transaction.fees;
242
+ if (!tezosResources.revealed) {
243
+ transaction.estimatedFees = transaction.estimatedFees.plus(
244
+ DEFAULT_FEE.REVEAL
245
+ );
246
+ }
247
+ } catch (e) {
248
+ if (typeof e !== "object" || !e) throw e;
249
+ if ("id" in e) {
250
+ transaction.taquitoError = (e as { id: string }).id;
251
+ } else if ("status" in e) {
252
+ // in case of http 400, log & ignore (more case to handle)
253
+ log(
254
+ "taquito-network-error",
255
+ String((e as { message: string }).message || ""),
256
+ { transaction }
213
257
  );
214
- transaction.gasLimit = transaction.gasLimit.plus(gasBuffer);
215
- const s = await getTransactionStatus(account, transaction);
216
- transaction.amount = account.balance.minus(s.estimatedFees);
258
+ } else {
259
+ throw e;
217
260
  }
218
- } catch (e: any) {
219
- transaction.taquitoError = e.id;
220
261
  }
221
262
 
222
263
  return transaction;
@@ -90,6 +90,7 @@ const createTransaction = (): Transaction => ({
90
90
  networkInfo: null,
91
91
  useAllAmount: false,
92
92
  taquitoError: null,
93
+ estimatedFees: null,
93
94
  });
94
95
 
95
96
  const updateTransaction = (t, patch) => ({ ...t, ...patch });