@ledgerhq/live-common 21.22.0 → 21.24.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 (262) 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/data/icons/react/index.d.ts +1 -0
  8. package/lib/data/icons/react/index.d.ts.map +1 -1
  9. package/lib/data/icons/react/index.js +4 -2
  10. package/lib/data/icons/react/index.js.map +1 -1
  11. package/lib/data/icons/react/sol.js +4 -2
  12. package/lib/data/icons/react/sol.js.map +1 -1
  13. package/lib/data/icons/react/ssv.d.ts +8 -0
  14. package/lib/data/icons/react/ssv.d.ts.map +1 -0
  15. package/lib/data/icons/react/ssv.js +31 -0
  16. package/lib/data/icons/react/ssv.js.map +1 -0
  17. package/lib/data/icons/reactNative/index.d.ts +1 -0
  18. package/lib/data/icons/reactNative/index.d.ts.map +1 -1
  19. package/lib/data/icons/reactNative/index.js +4 -2
  20. package/lib/data/icons/reactNative/index.js.map +1 -1
  21. package/lib/data/icons/reactNative/sol.js +4 -2
  22. package/lib/data/icons/reactNative/sol.js.map +1 -1
  23. package/lib/data/icons/reactNative/ssv.d.ts +8 -0
  24. package/lib/data/icons/reactNative/ssv.d.ts.map +1 -0
  25. package/lib/data/icons/reactNative/ssv.js +32 -0
  26. package/lib/data/icons/reactNative/ssv.js.map +1 -0
  27. package/lib/derivation.d.ts.map +1 -1
  28. package/lib/derivation.js +0 -3
  29. package/lib/derivation.js.map +1 -1
  30. package/lib/env.d.ts +10 -10
  31. package/lib/env.d.ts.map +1 -1
  32. package/lib/env.js +5 -5
  33. package/lib/env.js.map +1 -1
  34. package/lib/env.react.d.ts +1 -1
  35. package/lib/env.react.d.ts.map +1 -1
  36. package/lib/families/algorand/account.d.ts.map +1 -1
  37. package/lib/families/algorand/account.js +0 -4
  38. package/lib/families/algorand/account.js.map +1 -1
  39. package/lib/families/algorand/api/algodv2.d.ts +5 -0
  40. package/lib/families/algorand/api/algodv2.d.ts.map +1 -0
  41. package/lib/families/algorand/api/algodv2.js +118 -0
  42. package/lib/families/algorand/api/algodv2.js.map +1 -0
  43. package/lib/families/algorand/api/algodv2.types.d.ts +24 -0
  44. package/lib/families/algorand/api/algodv2.types.d.ts.map +1 -0
  45. package/lib/families/algorand/api/algodv2.types.js +3 -0
  46. package/lib/families/algorand/api/algodv2.types.js.map +1 -0
  47. package/lib/families/algorand/api/index.d.ts +5 -0
  48. package/lib/families/algorand/api/index.d.ts.map +1 -0
  49. package/lib/families/algorand/api/index.js +17 -0
  50. package/lib/families/algorand/api/index.js.map +1 -0
  51. package/lib/families/algorand/api/indexer.d.ts +3 -0
  52. package/lib/families/algorand/api/indexer.d.ts.map +1 -0
  53. package/lib/families/algorand/api/indexer.js +134 -0
  54. package/lib/families/algorand/api/indexer.js.map +1 -0
  55. package/lib/families/algorand/api/indexer.types.d.ts +35 -0
  56. package/lib/families/algorand/api/indexer.types.d.ts.map +1 -0
  57. package/lib/families/algorand/api/indexer.types.js +10 -0
  58. package/lib/families/algorand/api/indexer.types.js.map +1 -0
  59. package/lib/families/algorand/bridge/js.d.ts +8 -0
  60. package/lib/families/algorand/bridge/js.d.ts.map +1 -0
  61. package/lib/families/algorand/bridge/js.js +85 -0
  62. package/lib/families/algorand/bridge/js.js.map +1 -0
  63. package/lib/families/algorand/bridge/libcore.d.ts +3 -3
  64. package/lib/families/algorand/bridge/libcore.d.ts.map +1 -1
  65. package/lib/families/algorand/bridge/libcore.js.map +1 -1
  66. package/lib/families/algorand/bridge/mock.d.ts +2 -2
  67. package/lib/families/algorand/bridge/mock.d.ts.map +1 -1
  68. package/lib/families/algorand/bridge/mock.js.map +1 -1
  69. package/lib/families/algorand/buildTransaction.d.ts +8 -0
  70. package/lib/families/algorand/buildTransaction.d.ts.map +1 -0
  71. package/lib/families/algorand/buildTransaction.js +101 -0
  72. package/lib/families/algorand/buildTransaction.js.map +1 -0
  73. package/lib/families/algorand/cli-transaction.js +1 -1
  74. package/lib/families/algorand/cli-transaction.js.map +1 -1
  75. package/lib/families/algorand/deviceTransactionConfig.d.ts +2 -2
  76. package/lib/families/algorand/deviceTransactionConfig.d.ts.map +1 -1
  77. package/lib/families/algorand/deviceTransactionConfig.js +0 -13
  78. package/lib/families/algorand/deviceTransactionConfig.js.map +1 -1
  79. package/lib/families/algorand/hw-getAddress.d.ts.map +1 -1
  80. package/lib/families/algorand/hw-getAddress.js +2 -24
  81. package/lib/families/algorand/hw-getAddress.js.map +1 -1
  82. package/lib/families/algorand/js-broadcast.d.ts +9 -0
  83. package/lib/families/algorand/js-broadcast.d.ts.map +1 -0
  84. package/lib/families/algorand/js-broadcast.js +63 -0
  85. package/lib/families/algorand/js-broadcast.js.map +1 -0
  86. package/lib/families/algorand/js-estimateMaxSpendable.d.ts +9 -0
  87. package/lib/families/algorand/js-estimateMaxSpendable.d.ts.map +1 -0
  88. package/lib/families/algorand/js-estimateMaxSpendable.js +89 -0
  89. package/lib/families/algorand/js-estimateMaxSpendable.js.map +1 -0
  90. package/lib/families/algorand/js-getFeesForTransaction.d.ts +5 -0
  91. package/lib/families/algorand/js-getFeesForTransaction.d.ts.map +1 -0
  92. package/lib/families/algorand/js-getFeesForTransaction.js +69 -0
  93. package/lib/families/algorand/js-getFeesForTransaction.js.map +1 -0
  94. package/lib/families/algorand/js-getTransactionStatus.d.ts +11 -0
  95. package/lib/families/algorand/js-getTransactionStatus.d.ts.map +1 -0
  96. package/lib/families/algorand/js-getTransactionStatus.js +201 -0
  97. package/lib/families/algorand/js-getTransactionStatus.js.map +1 -0
  98. package/lib/families/algorand/js-prepareTransaction.d.ts +5 -0
  99. package/lib/families/algorand/js-prepareTransaction.d.ts.map +1 -0
  100. package/lib/families/algorand/js-prepareTransaction.js +101 -0
  101. package/lib/families/algorand/js-prepareTransaction.js.map +1 -0
  102. package/lib/families/algorand/js-signOperation.d.ts +10 -0
  103. package/lib/families/algorand/js-signOperation.d.ts.map +1 -0
  104. package/lib/families/algorand/js-signOperation.js +164 -0
  105. package/lib/families/algorand/js-signOperation.js.map +1 -0
  106. package/lib/families/algorand/js-synchronization.d.ts +10 -0
  107. package/lib/families/algorand/js-synchronization.d.ts.map +1 -0
  108. package/lib/families/algorand/js-synchronization.js +411 -0
  109. package/lib/families/algorand/js-synchronization.js.map +1 -0
  110. package/lib/families/algorand/libcore-buildTransaction.d.ts +2 -2
  111. package/lib/families/algorand/libcore-buildTransaction.d.ts.map +1 -1
  112. package/lib/families/algorand/libcore-getFeesForTransaction.d.ts +4 -4
  113. package/lib/families/algorand/libcore-getFeesForTransaction.d.ts.map +1 -1
  114. package/lib/families/algorand/libcore-getFeesForTransaction.js +2 -2
  115. package/lib/families/algorand/libcore-getFeesForTransaction.js.map +1 -1
  116. package/lib/families/algorand/libcore-postBuildAccount.d.ts.map +1 -1
  117. package/lib/families/algorand/libcore-postBuildAccount.js +5 -11
  118. package/lib/families/algorand/libcore-postBuildAccount.js.map +1 -1
  119. package/lib/families/algorand/libcore-signOperation.d.ts +2 -2
  120. package/lib/families/algorand/libcore-signOperation.d.ts.map +1 -1
  121. package/lib/families/algorand/libcore-signOperation.js.map +1 -1
  122. package/lib/families/algorand/logic.d.ts +10 -0
  123. package/lib/families/algorand/logic.d.ts.map +1 -1
  124. package/lib/families/algorand/logic.js +79 -1
  125. package/lib/families/algorand/logic.js.map +1 -1
  126. package/lib/families/algorand/mock.d.ts.map +1 -1
  127. package/lib/families/algorand/mock.js +4 -11
  128. package/lib/families/algorand/mock.js.map +1 -1
  129. package/lib/families/algorand/serialization.js +4 -4
  130. package/lib/families/algorand/serialization.js.map +1 -1
  131. package/lib/families/algorand/specs.d.ts +2 -2
  132. package/lib/families/algorand/specs.d.ts.map +1 -1
  133. package/lib/families/algorand/specs.js +8 -16
  134. package/lib/families/algorand/specs.js.map +1 -1
  135. package/lib/families/algorand/speculos-deviceActions.d.ts +2 -2
  136. package/lib/families/algorand/speculos-deviceActions.d.ts.map +1 -1
  137. package/lib/families/algorand/speculos-deviceActions.js +4 -0
  138. package/lib/families/algorand/speculos-deviceActions.js.map +1 -1
  139. package/lib/families/algorand/test-dataset.d.ts +2 -2
  140. package/lib/families/algorand/test-dataset.d.ts.map +1 -1
  141. package/lib/families/algorand/test-dataset.js +1 -2
  142. package/lib/families/algorand/test-dataset.js.map +1 -1
  143. package/lib/families/algorand/tokens.d.ts.map +1 -1
  144. package/lib/families/algorand/tokens.js.map +1 -1
  145. package/lib/families/algorand/transaction.d.ts +5 -5
  146. package/lib/families/algorand/transaction.d.ts.map +1 -1
  147. package/lib/families/algorand/transaction.js.map +1 -1
  148. package/lib/families/algorand/types.d.ts +7 -5
  149. package/lib/families/algorand/types.d.ts.map +1 -1
  150. package/lib/families/algorand/types.js.map +1 -1
  151. package/lib/families/bitcoin/js-prepareTransaction.d.ts.map +1 -1
  152. package/lib/families/bitcoin/js-prepareTransaction.js +3 -2
  153. package/lib/families/bitcoin/js-prepareTransaction.js.map +1 -1
  154. package/lib/families/bitcoin/js-synchronisation.d.ts.map +1 -1
  155. package/lib/families/bitcoin/js-synchronisation.js +13 -14
  156. package/lib/families/bitcoin/js-synchronisation.js.map +1 -1
  157. package/lib/families/bitcoin/wallet-btc/crypto/base.d.ts.map +1 -1
  158. package/lib/families/bitcoin/wallet-btc/crypto/base.js +30 -22
  159. package/lib/families/bitcoin/wallet-btc/crypto/base.js.map +1 -1
  160. package/lib/families/bitcoin/wallet-btc/crypto/bip32.d.ts +11 -0
  161. package/lib/families/bitcoin/wallet-btc/crypto/bip32.d.ts.map +1 -0
  162. package/lib/families/bitcoin/wallet-btc/crypto/bip32.js +32 -0
  163. package/lib/families/bitcoin/wallet-btc/crypto/bip32.js.map +1 -0
  164. package/lib/families/bitcoin/wallet-btc/crypto/decred.d.ts.map +1 -1
  165. package/lib/families/bitcoin/wallet-btc/crypto/decred.js +3 -115
  166. package/lib/families/bitcoin/wallet-btc/crypto/decred.js.map +1 -1
  167. package/lib/families/bitcoin/wallet-btc/storage/index.d.ts +24 -8
  168. package/lib/families/bitcoin/wallet-btc/storage/index.d.ts.map +1 -1
  169. package/lib/families/bitcoin/wallet-btc/storage/index.js +114 -128
  170. package/lib/families/bitcoin/wallet-btc/storage/index.js.map +1 -1
  171. package/lib/families/bitcoin/wallet-btc/storage/types.d.ts +8 -7
  172. package/lib/families/bitcoin/wallet-btc/storage/types.d.ts.map +1 -1
  173. package/lib/families/bitcoin/wallet-btc/xpub.d.ts.map +1 -1
  174. package/lib/families/bitcoin/wallet-btc/xpub.js +42 -63
  175. package/lib/families/bitcoin/wallet-btc/xpub.js.map +1 -1
  176. package/lib/families/tezos/bridge/js.d.ts.map +1 -1
  177. package/lib/families/tezos/bridge/js.js +38 -17
  178. package/lib/families/tezos/bridge/js.js.map +1 -1
  179. package/lib/families/tezos/signOperation.d.ts.map +1 -1
  180. package/lib/families/tezos/signOperation.js +9 -0
  181. package/lib/families/tezos/signOperation.js.map +1 -1
  182. package/lib/families/tezos/synchronisation.js +1 -1
  183. package/lib/families/tezos/synchronisation.js.map +1 -1
  184. package/lib/generated/bridge/js.d.ts +4 -0
  185. package/lib/generated/bridge/js.d.ts.map +1 -1
  186. package/lib/generated/bridge/js.js +26 -24
  187. package/lib/generated/bridge/js.js.map +1 -1
  188. package/lib/generated/bridge/libcore.d.ts +1 -1
  189. package/lib/generated/bridge/mock.d.ts +1 -1
  190. package/lib/generated/specs.d.ts +1 -1
  191. package/lib/generated/speculos-deviceActions.d.ts +1 -1
  192. package/lib/generated/test-dataset.d.ts +1 -1
  193. package/lib/generated/transaction.d.ts +3 -3
  194. package/lib/libcore/buildAccount/index.d.ts.map +1 -1
  195. package/lib/libcore/buildAccount/index.js +0 -1
  196. package/lib/libcore/buildAccount/index.js.map +1 -1
  197. package/lib/mock/account.js +21 -21
  198. package/lib/mock/account.js.map +1 -1
  199. package/lib/types/operation.d.ts +1 -1
  200. package/lib/types/operation.d.ts.map +1 -1
  201. package/package.json +4 -3
  202. package/src/__tests__/__snapshots__/all.libcore.ts.snap +7 -114
  203. package/src/account/formatters.ts +1 -0
  204. package/src/account/support.ts +1 -0
  205. package/src/data/icons/react/index.tsx +1 -0
  206. package/src/data/icons/react/sol.tsx +1 -1
  207. package/src/data/icons/react/ssv.tsx +12 -0
  208. package/src/data/icons/reactNative/index.tsx +1 -0
  209. package/src/data/icons/reactNative/sol.tsx +1 -1
  210. package/src/data/icons/reactNative/ssv.tsx +13 -0
  211. package/src/data/icons/svg/SOL.svg +1 -3
  212. package/src/data/icons/svg/SSV.svg +4 -0
  213. package/src/derivation.ts +0 -2
  214. package/src/env.ts +5 -5
  215. package/src/families/algorand/account.ts +0 -9
  216. package/src/families/algorand/api/algodv2.ts +68 -0
  217. package/src/families/algorand/api/algodv2.types.ts +27 -0
  218. package/src/families/algorand/api/index.ts +4 -0
  219. package/src/families/algorand/api/indexer.ts +99 -0
  220. package/src/families/algorand/api/indexer.types.ts +41 -0
  221. package/src/families/algorand/bridge/js.ts +46 -0
  222. package/src/families/algorand/bridge/libcore.ts +4 -4
  223. package/src/families/algorand/bridge/mock.ts +3 -3
  224. package/src/families/algorand/buildTransaction.ts +100 -0
  225. package/src/families/algorand/cli-transaction.ts +1 -1
  226. package/src/families/algorand/deviceTransactionConfig.ts +2 -16
  227. package/src/families/algorand/hw-getAddress.ts +1 -10
  228. package/src/families/algorand/js-broadcast.ts +17 -0
  229. package/src/families/algorand/js-estimateMaxSpendable.ts +51 -0
  230. package/src/families/algorand/js-getFeesForTransaction.ts +25 -0
  231. package/src/families/algorand/js-getTransactionStatus.ts +178 -0
  232. package/src/families/algorand/js-prepareTransaction.ts +42 -0
  233. package/src/families/algorand/js-signOperation.ts +145 -0
  234. package/src/families/algorand/js-synchronization.ts +433 -0
  235. package/src/families/algorand/libcore-buildTransaction.ts +2 -2
  236. package/src/families/algorand/libcore-getFeesForTransaction.ts +4 -4
  237. package/src/families/algorand/libcore-postBuildAccount.ts +2 -7
  238. package/src/families/algorand/libcore-signOperation.ts +2 -2
  239. package/src/families/algorand/logic.ts +47 -0
  240. package/src/families/algorand/mock.ts +2 -12
  241. package/src/families/algorand/serialization.ts +4 -4
  242. package/src/families/algorand/specs.ts +16 -22
  243. package/src/families/algorand/speculos-deviceActions.ts +87 -82
  244. package/src/families/algorand/test-dataset.ts +5 -6
  245. package/src/families/algorand/tokens.ts +1 -0
  246. package/src/families/algorand/transaction.ts +13 -4
  247. package/src/families/algorand/types.ts +10 -5
  248. package/src/families/bitcoin/js-prepareTransaction.ts +3 -2
  249. package/src/families/bitcoin/js-synchronisation.ts +17 -15
  250. package/src/families/bitcoin/wallet-btc/crypto/base.ts +33 -21
  251. package/src/families/bitcoin/wallet-btc/crypto/bip32.ts +36 -0
  252. package/src/families/bitcoin/wallet-btc/crypto/decred.ts +3 -155
  253. package/src/families/bitcoin/wallet-btc/storage/index.ts +23 -11
  254. package/src/families/bitcoin/wallet-btc/storage/types.ts +8 -10
  255. package/src/families/bitcoin/wallet-btc/xpub.ts +14 -10
  256. package/src/families/tezos/bridge/js.ts +43 -18
  257. package/src/families/tezos/signOperation.ts +12 -0
  258. package/src/families/tezos/synchronisation.ts +1 -1
  259. package/src/generated/bridge/js.ts +3 -0
  260. package/src/libcore/buildAccount/index.ts +1 -2
  261. package/src/mock/account.ts +27 -27
  262. package/src/types/operation.ts +9 -4
@@ -1 +1,48 @@
1
+ import { BigNumber } from "bignumber.js";
2
+ import type { AlgorandOperationMode } from "./types";
3
+ import { getAccount } from "./api";
4
+
1
5
  export const ALGORAND_MAX_MEMO_SIZE = 32;
6
+ export const ALGORAND_MIN_ACCOUNT_BALANCE = 100000;
7
+
8
+ export const recipientHasAsset = async (
9
+ recipientAddress: string,
10
+ assetId: string
11
+ ): Promise<boolean> => {
12
+ const recipientAccount = await getAccount(recipientAddress);
13
+ return recipientAccount.assets.map((a) => a.assetId).includes(assetId);
14
+ };
15
+
16
+ export const isAmountValid = async (
17
+ recipientAddress: string,
18
+ amount: BigNumber
19
+ ): Promise<boolean> => {
20
+ const recipientAccount = await getAccount(recipientAddress);
21
+ return recipientAccount.balance.isZero()
22
+ ? amount.gte(ALGORAND_MIN_ACCOUNT_BALANCE)
23
+ : true;
24
+ };
25
+
26
+ export const computeAlgoMaxSpendable = ({
27
+ accountBalance,
28
+ nbAccountAssets,
29
+ mode,
30
+ }: {
31
+ accountBalance: BigNumber;
32
+ nbAccountAssets: number;
33
+ mode: AlgorandOperationMode;
34
+ }): BigNumber => {
35
+ const minBalance = computeMinimumAlgoBalance(mode, nbAccountAssets);
36
+ const maxSpendable = accountBalance.minus(minBalance);
37
+ return maxSpendable.gte(0) ? maxSpendable : new BigNumber(0);
38
+ };
39
+
40
+ const computeMinimumAlgoBalance = (
41
+ mode: AlgorandOperationMode,
42
+ nbAccountAssets: number
43
+ ): BigNumber => {
44
+ const base = 100000; // 0.1 algo = 100000 malgo
45
+ const currentAssets = nbAccountAssets;
46
+ const newAsset = mode === "optIn" ? 1 : 0;
47
+ return new BigNumber(base * (1 + currentAssets + newAsset));
48
+ };
@@ -7,7 +7,7 @@ function setAlgorandResources(account: Account): Account {
7
7
  /** format algorandResources given the new delegations */
8
8
  account.algorandResources = {
9
9
  rewards: account.balance.multipliedBy(0.01),
10
- rewardsAccumulated: account.balance.multipliedBy(0.1),
10
+ nbAssets: account.subAccounts?.length ?? 0,
11
11
  };
12
12
  return account;
13
13
  }
@@ -70,15 +70,6 @@ function addOptOut(account: Account, rng: Prando): Account {
70
70
  return account;
71
71
  }
72
72
 
73
- function addCloseAccount(account: Account, rng: Prando): Account {
74
- /** select position on the operation stack where we will insert the new claim rewards */
75
- const opIndex = rng.next(0, 10);
76
- const opt = genBaseOperation(account, rng, "CLOSE_ACCOUNT", opIndex);
77
- account.operations.splice(opIndex, 0, opt);
78
- account.operationsCount++;
79
- return account;
80
- }
81
-
82
73
  /**
83
74
  * add in specific algorand operations
84
75
  * @memberof algorand/mock
@@ -88,7 +79,6 @@ function addCloseAccount(account: Account, rng: Prando): Account {
88
79
  function genAccountEnhanceOperations(account: Account, rng: Prando): Account {
89
80
  addOptIn(account, rng);
90
81
  addOptOut(account, rng);
91
- addCloseAccount(account, rng);
92
82
  setAlgorandResources(account);
93
83
  return account;
94
84
  }
@@ -122,7 +112,7 @@ function postScanAccount(
122
112
  if (isEmpty) {
123
113
  account.algorandResources = {
124
114
  rewards: new BigNumber(0),
125
- rewardsAccumulated: new BigNumber(0),
115
+ nbAssets: account.subAccounts?.length ?? 0,
126
116
  };
127
117
  account.operations = [];
128
118
  account.subAccounts = [];
@@ -3,18 +3,18 @@ import type { AlgorandResourcesRaw, AlgorandResources } from "./types";
3
3
  export function toAlgorandResourcesRaw(
4
4
  r: AlgorandResources
5
5
  ): AlgorandResourcesRaw {
6
- const { rewards, rewardsAccumulated } = r;
6
+ const { rewards, nbAssets } = r;
7
7
  return {
8
8
  rewards: rewards.toString(),
9
- rewardsAccumulated: rewardsAccumulated.toString(),
9
+ nbAssets,
10
10
  };
11
11
  }
12
12
  export function fromAlgorandResourcesRaw(
13
13
  r: AlgorandResourcesRaw
14
14
  ): AlgorandResources {
15
- const { rewards, rewardsAccumulated } = r;
15
+ const { rewards, nbAssets } = r;
16
16
  return {
17
17
  rewards: new BigNumber(rewards),
18
- rewardsAccumulated: new BigNumber(rewardsAccumulated),
18
+ nbAssets,
19
19
  };
20
20
  }
@@ -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;
@@ -91,8 +91,8 @@ const mapTxToOperations = (
91
91
  tx: TX,
92
92
  currencyId: string,
93
93
  accountId: string,
94
- accountAddresses: string[],
95
- changeAddresses: string[]
94
+ accountAddresses: Set<string>,
95
+ changeAddresses: Set<string>
96
96
  ): $Shape<Operation[]> => {
97
97
  const operations: Operation[] = [];
98
98
  const hash = tx.hash;
@@ -116,7 +116,7 @@ const mapTxToOperations = (
116
116
  );
117
117
 
118
118
  if (input.value) {
119
- if (accountAddresses.includes(input.address)) {
119
+ if (accountAddresses.has(input.address)) {
120
120
  // This address is part of the account
121
121
  value = value.plus(input.value);
122
122
  accountInputs.push(input);
@@ -137,11 +137,12 @@ const mapTxToOperations = (
137
137
 
138
138
  for (const output of tx.outputs) {
139
139
  if (output.address) {
140
- if (!accountAddresses.includes(output.address)) {
140
+ if (!accountAddresses.has(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
@@ -153,7 +154,7 @@ const mapTxToOperations = (
153
154
  // The output belongs to this account
154
155
  accountOutputs.push(output);
155
156
 
156
- if (!changeAddresses.includes(output.address)) {
157
+ if (!changeAddresses.has(output.address)) {
157
158
  // The output isn't a change output of this account
158
159
  recipients.push(
159
160
  syncReplaceAddress
@@ -182,7 +183,7 @@ const mapTxToOperations = (
182
183
  if (accountInputs.length > 0) {
183
184
  // It's a SEND operation
184
185
  for (const output of accountOutputs) {
185
- if (changeAddresses.includes(output.address)) {
186
+ if (changeAddresses.has(output.address)) {
186
187
  value = value.minus(output.value);
187
188
  }
188
189
  }
@@ -213,7 +214,7 @@ const mapTxToOperations = (
213
214
  let finalAmount = new BigNumber(0);
214
215
 
215
216
  for (const output of accountOutputs) {
216
- if (!filterChangeAddresses || !changeAddresses.includes(output.address)) {
217
+ if (!filterChangeAddresses || !changeAddresses.has(output.address)) {
217
218
  finalAmount = finalAmount.plus(output.value);
218
219
  accountOutputCount += 1;
219
220
  }
@@ -323,17 +324,18 @@ const getAccountShape: GetAccountShape = async (info) => {
323
324
  const { txs: transactions } = await wallet.getAccountTransactions(
324
325
  walletAccount
325
326
  );
327
+
328
+ const accountAddresses: Set<string> = new Set<string>();
326
329
  const accountAddressesWithInfo = await walletAccount.xpub.getXpubAddresses();
327
- const accountAddresses = accountAddressesWithInfo
328
- ? accountAddressesWithInfo.map((a) => a.address)
329
- : [];
330
+ accountAddressesWithInfo.forEach((a) => accountAddresses.add(a.address));
331
+
332
+ const changeAddresses: Set<string> = new Set<string>();
330
333
  const changeAddressesWithInfo =
331
334
  await walletAccount.xpub.storage.getUniquesAddresses({
332
335
  account: 1,
333
336
  });
334
- const changeAddresses = changeAddressesWithInfo
335
- ? changeAddressesWithInfo.map((a) => a.address)
336
- : [];
337
+ changeAddressesWithInfo.forEach((a) => changeAddresses.add(a.address));
338
+
337
339
  const newOperations = transactions
338
340
  ?.map((tx) =>
339
341
  mapTxToOperations(