@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
@@ -0,0 +1,145 @@
1
+ import { BigNumber } from "bignumber.js";
2
+ import { Observable } from "rxjs";
3
+ import { FeeNotLoaded } from "@ledgerhq/errors";
4
+ import Algorand from "@ledgerhq/hw-app-algorand";
5
+ import type { Account, Operation, SignOperationEvent } from "../../types";
6
+ import { withDevice } from "../../hw/deviceAccess";
7
+ import type { Transaction } from "./types";
8
+ import {
9
+ buildTransactionPayload,
10
+ encodeToSign,
11
+ encodeToBroadcast,
12
+ } from "./buildTransaction";
13
+
14
+ export const signOperation = ({
15
+ account,
16
+ transaction,
17
+ deviceId,
18
+ }: {
19
+ account: Account;
20
+ transaction: Transaction;
21
+ deviceId: any;
22
+ }): Observable<SignOperationEvent> =>
23
+ withDevice(deviceId)((transport) =>
24
+ Observable.create((o) => {
25
+ let cancelled;
26
+
27
+ async function main() {
28
+ if (!transaction.fees) {
29
+ throw new FeeNotLoaded();
30
+ }
31
+
32
+ const algoTx = await buildTransactionPayload(account, transaction);
33
+
34
+ const toSign = await encodeToSign(algoTx);
35
+
36
+ const hwApp = new Algorand(transport);
37
+ const { freshAddressPath } = account;
38
+
39
+ o.next({ type: "device-signature-requested" });
40
+
41
+ const { signature } = await hwApp.sign(freshAddressPath, toSign);
42
+
43
+ if (cancelled) return;
44
+
45
+ o.next({ type: "device-signature-granted" });
46
+
47
+ if (!signature) {
48
+ throw new Error("No signature");
49
+ }
50
+
51
+ const toBroadcast = await encodeToBroadcast(algoTx, signature);
52
+
53
+ const operation = buildOptimisticOperation(account, transaction);
54
+
55
+ o.next({
56
+ type: "signed",
57
+ signedOperation: {
58
+ operation,
59
+ signature: toBroadcast,
60
+ expirationDate: null,
61
+ },
62
+ });
63
+ }
64
+
65
+ main().then(
66
+ () => o.complete(),
67
+ (e) => o.error(e)
68
+ );
69
+
70
+ return () => {
71
+ cancelled = true;
72
+ };
73
+ })
74
+ );
75
+
76
+ const buildOptimisticOperation = (
77
+ account: Account,
78
+ transaction: Transaction
79
+ ): Operation => {
80
+ const { spendableBalance, id, freshAddress, subAccounts } = account;
81
+
82
+ const senders = [freshAddress];
83
+ const recipients = [transaction.recipient];
84
+ const { subAccountId, fees } = transaction;
85
+
86
+ if (!fees) {
87
+ throw new FeeNotLoaded();
88
+ }
89
+
90
+ const value = subAccountId
91
+ ? fees
92
+ : transaction.useAllAmount
93
+ ? spendableBalance
94
+ : transaction.amount.plus(fees);
95
+
96
+ const type = subAccountId
97
+ ? "FEES"
98
+ : transaction.mode === "optIn"
99
+ ? "OPT_IN"
100
+ : "OUT";
101
+
102
+ const op: Operation = {
103
+ id: `${id}--${type}`,
104
+ hash: "",
105
+ type,
106
+ value,
107
+ fee: fees,
108
+ blockHash: null,
109
+ blockHeight: null,
110
+ senders,
111
+ recipients,
112
+ accountId: id,
113
+ date: new Date(),
114
+ extra: {},
115
+ };
116
+
117
+ const tokenAccount = !subAccountId
118
+ ? null
119
+ : subAccounts && subAccounts.find((ta) => ta.id === subAccountId);
120
+
121
+ if (tokenAccount && subAccountId) {
122
+ op.subOperations = [
123
+ {
124
+ id: `${subAccountId}--OUT`,
125
+ hash: "",
126
+ type: "OUT",
127
+ value: transaction.useAllAmount
128
+ ? tokenAccount.balance
129
+ : transaction.amount,
130
+ fee: new BigNumber(0),
131
+ blockHash: null,
132
+ blockHeight: null,
133
+ senders,
134
+ recipients,
135
+ accountId: subAccountId,
136
+ date: new Date(),
137
+ extra: {},
138
+ },
139
+ ];
140
+ }
141
+
142
+ return op;
143
+ };
144
+
145
+ export default signOperation;
@@ -0,0 +1,433 @@
1
+ import { BigNumber } from "bignumber.js";
2
+ import type {
3
+ CryptoCurrency,
4
+ TokenCurrency,
5
+ Account,
6
+ TokenAccount,
7
+ Operation,
8
+ OperationType,
9
+ SyncConfig,
10
+ } from "../../types";
11
+ import { findTokenById, listTokensForCryptoCurrency } from "../../currencies";
12
+ import {
13
+ encodeAccountId,
14
+ emptyHistoryCache,
15
+ inferSubOperations,
16
+ } from "../../account";
17
+ import { encodeOperationId } from "../../operation";
18
+ import { promiseAllBatched } from "../../promise";
19
+ import type { GetAccountShape } from "../../bridge/jsHelpers";
20
+ import { makeSync, makeScanAccounts, mergeOps } from "../../bridge/jsHelpers";
21
+
22
+ import {
23
+ AlgoTransaction,
24
+ AlgoPaymentInfo,
25
+ AlgoAssetTransferInfo,
26
+ AlgoAsset,
27
+ } from "./api";
28
+ import { AlgoTransactionType, getAccount, getAccountTransactions } from "./api";
29
+ import { addPrefixToken, extractTokenId } from "./tokens";
30
+ import { computeAlgoMaxSpendable } from "./logic";
31
+
32
+ const getASAOperationAmount = (
33
+ transaction: AlgoTransaction,
34
+ accountAddress: string
35
+ ): BigNumber => {
36
+ let assetAmount = new BigNumber(0);
37
+ if (transaction.type === AlgoTransactionType.ASSET_TRANSFER) {
38
+ const details = transaction.details as AlgoAssetTransferInfo;
39
+ const assetSender = details.assetSenderAddress
40
+ ? details.assetSenderAddress
41
+ : transaction.senderAddress;
42
+
43
+ // Account is either sender or recipient (if both the balance is unchanged)
44
+ if (
45
+ (assetSender === accountAddress) !==
46
+ (details.assetRecipientAddress == accountAddress)
47
+ ) {
48
+ assetAmount = assetAmount.plus(details.assetAmount);
49
+ }
50
+ // Account is either sender or close-to, but not both
51
+ if (
52
+ (assetSender === accountAddress) !==
53
+ (details.assetCloseToAddress &&
54
+ details.assetCloseToAddress === accountAddress)
55
+ ) {
56
+ if (details.assetCloseAmount) {
57
+ assetAmount = assetAmount.plus(details.assetCloseAmount);
58
+ }
59
+ }
60
+ }
61
+ return assetAmount;
62
+ };
63
+
64
+ const getOperationAmounts = (
65
+ transaction: AlgoTransaction,
66
+ accountAddress: string
67
+ ): { amount: BigNumber; rewards: BigNumber } => {
68
+ let amount = new BigNumber(0);
69
+ let rewards = new BigNumber(0);
70
+
71
+ if (transaction.senderAddress === accountAddress) {
72
+ const senderRewards = transaction.senderRewards;
73
+ amount = amount.minus(senderRewards).plus(transaction.fee);
74
+ rewards = rewards.plus(senderRewards);
75
+ }
76
+
77
+ if (transaction.type === AlgoTransactionType.PAYMENT) {
78
+ const details = transaction.details as AlgoPaymentInfo;
79
+ if (transaction.senderAddress == details.recipientAddress) {
80
+ return {
81
+ amount,
82
+ rewards,
83
+ };
84
+ }
85
+ if (transaction.senderAddress === accountAddress) {
86
+ amount = amount.plus(details.amount);
87
+ }
88
+ if (details.recipientAddress == accountAddress) {
89
+ const recipientRewards = transaction.recipientRewards;
90
+ amount = amount.plus(details.amount).plus(recipientRewards);
91
+ rewards = rewards.plus(recipientRewards);
92
+ }
93
+ if (
94
+ transaction.closeRewards &&
95
+ details.closeAmount &&
96
+ details.closeToAddress === accountAddress
97
+ ) {
98
+ const closeRewards = transaction.closeRewards;
99
+ amount = amount.plus(details.closeAmount).plus(closeRewards);
100
+ rewards = rewards.plus(closeRewards);
101
+ }
102
+ }
103
+
104
+ return {
105
+ amount,
106
+ rewards,
107
+ };
108
+ };
109
+
110
+ const getASAOperationType = (
111
+ transaction: AlgoTransaction,
112
+ accountAddress: string
113
+ ): OperationType => {
114
+ return transaction.senderAddress === accountAddress ? "OUT" : "IN";
115
+ };
116
+
117
+ const getOperationType = (
118
+ transaction: AlgoTransaction,
119
+ accountAddress: string
120
+ ): OperationType => {
121
+ if (transaction.type === AlgoTransactionType.ASSET_TRANSFER) {
122
+ const details = transaction.details as AlgoAssetTransferInfo;
123
+ if (
124
+ details.assetAmount.isZero() &&
125
+ transaction.senderAddress == details.assetRecipientAddress
126
+ ) {
127
+ return "OPT_IN";
128
+ } else if (
129
+ details.assetCloseToAddress &&
130
+ transaction.senderAddress == accountAddress
131
+ ) {
132
+ return "OPT_OUT";
133
+ } else {
134
+ return "FEES";
135
+ }
136
+ }
137
+
138
+ return transaction.senderAddress === accountAddress ? "OUT" : "IN";
139
+ };
140
+
141
+ const getOperationSenders = (transaction: AlgoTransaction): string[] => {
142
+ return [transaction.senderAddress];
143
+ };
144
+
145
+ const getOperationRecipients = (transaction: AlgoTransaction): string[] => {
146
+ const recipients: string[] = [];
147
+ if (transaction.type === AlgoTransactionType.PAYMENT) {
148
+ const details = transaction.details as AlgoPaymentInfo;
149
+ recipients.push(details.recipientAddress);
150
+ if (details.closeToAddress) {
151
+ recipients.push(details.closeToAddress);
152
+ }
153
+ } else if (transaction.type === AlgoTransactionType.ASSET_TRANSFER) {
154
+ const details = transaction.details as AlgoAssetTransferInfo;
155
+
156
+ recipients.push(details.assetRecipientAddress);
157
+ if (details.assetCloseToAddress) {
158
+ recipients.push(details.assetCloseToAddress);
159
+ }
160
+ }
161
+ return recipients;
162
+ };
163
+
164
+ const getOperationAssetId = (
165
+ transaction: AlgoTransaction
166
+ ): string | undefined => {
167
+ if (transaction.type === AlgoTransactionType.ASSET_TRANSFER) {
168
+ const details = transaction.details as AlgoAssetTransferInfo;
169
+ return details.assetId;
170
+ }
171
+ };
172
+
173
+ const mapTransactionToOperation = (
174
+ tx: AlgoTransaction,
175
+ accountId: string,
176
+ accountAddress: string,
177
+ subAccounts?: TokenAccount[]
178
+ ): Partial<Operation> => {
179
+ const hash = tx.id;
180
+ const blockHeight = tx.round;
181
+ const date = new Date(parseInt(tx.timestamp) * 1000);
182
+ const fee = tx.fee;
183
+ const memo = tx.note;
184
+ const senders: string[] = getOperationSenders(tx);
185
+ const recipients: string[] = getOperationRecipients(tx);
186
+ const { amount, rewards } = getOperationAmounts(tx, accountAddress);
187
+ const type = getOperationType(tx, accountAddress);
188
+ const assetId = getOperationAssetId(tx);
189
+
190
+ const subOperations = subAccounts
191
+ ? inferSubOperations(tx.id, subAccounts)
192
+ : undefined;
193
+
194
+ return {
195
+ id: encodeOperationId(accountId, hash, type),
196
+ hash,
197
+ date,
198
+ type,
199
+ value: amount,
200
+ fee,
201
+ senders,
202
+ recipients,
203
+ blockHeight,
204
+ accountId,
205
+ subOperations,
206
+ extra: {
207
+ rewards,
208
+ memo,
209
+ assetId,
210
+ },
211
+ };
212
+ };
213
+
214
+ const mapTransactionToASAOperation = (
215
+ tx: AlgoTransaction,
216
+ accountId: string,
217
+ accountAddress: string
218
+ ): Partial<Operation> => {
219
+ const hash = tx.id;
220
+ const blockHeight = tx.round;
221
+ const date = new Date(parseInt(tx.timestamp) * 1000);
222
+ const fee = tx.fee;
223
+ const senders: string[] = getOperationSenders(tx);
224
+ const recipients: string[] = getOperationRecipients(tx);
225
+ const type = getASAOperationType(tx, accountAddress);
226
+ const amount = getASAOperationAmount(tx, accountAddress);
227
+
228
+ return {
229
+ id: encodeOperationId(accountId, hash, type),
230
+ hash,
231
+ date,
232
+ type,
233
+ value: amount,
234
+ fee,
235
+ senders,
236
+ recipients,
237
+ blockHeight,
238
+ accountId,
239
+ extra: {},
240
+ };
241
+ };
242
+
243
+ const getAccountShape: GetAccountShape = async (
244
+ info,
245
+ syncConfig
246
+ ): Promise<Partial<Account>> => {
247
+ const { address, initialAccount, currency, derivationMode } = info;
248
+ const oldOperations = initialAccount?.operations || [];
249
+ const startAt = oldOperations.length
250
+ ? (oldOperations[0].blockHeight || 0) + 1
251
+ : 0;
252
+ const accountId = encodeAccountId({
253
+ type: "js",
254
+ version: "2",
255
+ currencyId: currency.id,
256
+ xpubOrAddress: address,
257
+ derivationMode,
258
+ });
259
+
260
+ const { round, balance, pendingRewards, assets } = await getAccount(address);
261
+
262
+ const nbAssets = assets.length;
263
+
264
+ // NOTE Actual spendable amount depends on the transaction
265
+ const spendableBalance = computeAlgoMaxSpendable({
266
+ accountBalance: balance,
267
+ nbAccountAssets: nbAssets,
268
+ mode: "send",
269
+ });
270
+
271
+ const newTransactions: AlgoTransaction[] = await getAccountTransactions(
272
+ address,
273
+ startAt
274
+ );
275
+
276
+ const subAccounts = await buildSubAccounts({
277
+ currency,
278
+ accountId,
279
+ initialAccount,
280
+ initialAccountAddress: address,
281
+ assets,
282
+ newTransactions,
283
+ syncConfig,
284
+ });
285
+
286
+ const newOperations = newTransactions.map((tx) =>
287
+ mapTransactionToOperation(tx, accountId, address, subAccounts)
288
+ );
289
+
290
+ const operations = mergeOps(oldOperations, newOperations as Operation[]);
291
+
292
+ const shape = {
293
+ id: accountId,
294
+ blockHeight: round,
295
+ balance,
296
+ spendableBalance,
297
+ operations,
298
+ operationsCount: operations.length,
299
+ subAccounts,
300
+ algorandResources: {
301
+ rewards: pendingRewards,
302
+ nbAssets,
303
+ },
304
+ };
305
+
306
+ return shape;
307
+ };
308
+
309
+ async function buildSubAccount({
310
+ parentAccountId,
311
+ parentAccountAddress,
312
+ token,
313
+ initialTokenAccount,
314
+ newTransactions,
315
+ balance,
316
+ }: {
317
+ parentAccountId: string;
318
+ parentAccountAddress: string;
319
+ token: TokenCurrency;
320
+ initialTokenAccount: TokenAccount;
321
+ newTransactions: AlgoTransaction[];
322
+ balance: BigNumber;
323
+ }) {
324
+ const extractedId = extractTokenId(token.id);
325
+ const tokenAccountId = parentAccountId + "+" + extractedId;
326
+
327
+ const oldOperations = initialTokenAccount?.operations || [];
328
+
329
+ const newOperations = newTransactions
330
+ .filter((tx) => tx.type === AlgoTransactionType.ASSET_TRANSFER)
331
+ .filter((tx) => {
332
+ const details = tx.details as AlgoAssetTransferInfo;
333
+ return Number(details.assetId) === Number(extractedId);
334
+ })
335
+ .filter((tx) => getOperationType(tx, parentAccountAddress) != "OPT_IN")
336
+ .map((tx) =>
337
+ mapTransactionToASAOperation(tx, tokenAccountId, parentAccountAddress)
338
+ );
339
+
340
+ const operations = mergeOps(oldOperations, newOperations as Operation[]);
341
+
342
+ const tokenAccount: TokenAccount = {
343
+ type: "TokenAccount",
344
+ id: tokenAccountId,
345
+ parentId: parentAccountId,
346
+ starred: false,
347
+ token,
348
+ operationsCount: operations.length,
349
+ operations,
350
+ pendingOperations: [],
351
+ balance,
352
+ spendableBalance: balance,
353
+ swapHistory: [],
354
+ creationDate:
355
+ operations.length > 0
356
+ ? operations[operations.length - 1].date
357
+ : new Date(),
358
+ balanceHistoryCache: emptyHistoryCache,
359
+ };
360
+ return tokenAccount;
361
+ }
362
+
363
+ async function buildSubAccounts({
364
+ currency,
365
+ accountId,
366
+ initialAccount,
367
+ initialAccountAddress,
368
+ assets,
369
+ newTransactions,
370
+ syncConfig,
371
+ }: {
372
+ currency: CryptoCurrency;
373
+ accountId: string;
374
+ initialAccount: Account | null | undefined;
375
+ initialAccountAddress: string;
376
+ assets: AlgoAsset[];
377
+ newTransactions: AlgoTransaction[];
378
+ syncConfig: SyncConfig;
379
+ }): Promise<TokenAccount[] | undefined> {
380
+ const { blacklistedTokenIds = [] } = syncConfig;
381
+ if (listTokensForCryptoCurrency(currency).length === 0) return undefined;
382
+ const tokenAccounts: TokenAccount[] = [];
383
+ const existingAccountByTicker = {}; // used for fast lookup
384
+ const existingAccountTickers: string[] = []; // used to keep track of ordering
385
+
386
+ if (initialAccount && initialAccount.subAccounts) {
387
+ for (const existingSubAccount of initialAccount.subAccounts) {
388
+ if (existingSubAccount.type === "TokenAccount") {
389
+ const { ticker, id } = existingSubAccount.token;
390
+
391
+ if (!blacklistedTokenIds.includes(id)) {
392
+ existingAccountTickers.push(ticker);
393
+ existingAccountByTicker[ticker] = existingSubAccount;
394
+ }
395
+ }
396
+ }
397
+ }
398
+
399
+ // filter by token existence
400
+ await promiseAllBatched(3, assets, async (asset) => {
401
+ const token = findTokenById(addPrefixToken(asset.assetId));
402
+
403
+ if (token && !blacklistedTokenIds.includes(token.id)) {
404
+ const initialTokenAccount = existingAccountByTicker[token.ticker];
405
+ const tokenAccount = await buildSubAccount({
406
+ parentAccountId: accountId,
407
+ parentAccountAddress: initialAccountAddress,
408
+ initialTokenAccount,
409
+ token,
410
+ newTransactions,
411
+ balance: asset.balance,
412
+ });
413
+ if (tokenAccount) tokenAccounts.push(tokenAccount);
414
+ }
415
+ });
416
+ // Preserve order of tokenAccounts from the existing token accounts
417
+ tokenAccounts.sort((a, b) => {
418
+ const i = existingAccountTickers.indexOf(a.token.ticker);
419
+ const j = existingAccountTickers.indexOf(b.token.ticker);
420
+ if (i === j) return 0;
421
+ if (i < 0) return 1;
422
+ if (j < 0) return -1;
423
+ return i - j;
424
+ });
425
+ return tokenAccounts;
426
+ }
427
+
428
+ const postSync = (_initial: Account, parent: Account) => {
429
+ return parent;
430
+ };
431
+
432
+ export const scanAccounts = makeScanAccounts(getAccountShape);
433
+ export const sync = makeSync(getAccountShape, postSync);
@@ -2,7 +2,7 @@ import { FeeNotLoaded } from "@ledgerhq/errors";
2
2
  import type { Account } from "../../types";
3
3
  import { libcoreAmountToBigNumber } from "../../libcore/buildBigNumber";
4
4
  import type { Core, CoreAccount } from "../../libcore/types";
5
- import type { CoreAlgorandTransaction, Transaction } from "./types";
5
+ import type { CoreAlgorandTransaction, AlgorandTransaction } from "./types";
6
6
  import { extractTokenId } from "./tokens";
7
7
 
8
8
  const setInfo = async (
@@ -64,7 +64,7 @@ export async function algorandBuildTransaction({
64
64
  account: Account;
65
65
  core: Core;
66
66
  coreAccount: CoreAccount;
67
- transaction: Transaction;
67
+ transaction: AlgorandTransaction;
68
68
  isPartial: boolean;
69
69
  isCancelled: () => boolean;
70
70
  }): Promise<CoreAlgorandTransaction | null | undefined> {
@@ -1,15 +1,15 @@
1
1
  import type { Account } from "../../types";
2
2
  import type { Core, CoreCurrency, CoreAccount } from "../../libcore/types";
3
- import type { Transaction } from "./types";
3
+ import type { AlgorandTransaction } from "./types";
4
4
  import buildTransaction from "./libcore-buildTransaction";
5
5
  import { BigNumber } from "bignumber.js";
6
6
 
7
- async function cosmos(args: {
7
+ async function algorand(args: {
8
8
  account: Account;
9
9
  core: Core;
10
10
  coreAccount: CoreAccount;
11
11
  coreCurrency: CoreCurrency;
12
- transaction: Transaction;
12
+ transaction: AlgorandTransaction;
13
13
  isPartial: boolean;
14
14
  isCancelled: () => boolean;
15
15
  }) {
@@ -22,4 +22,4 @@ async function cosmos(args: {
22
22
  };
23
23
  }
24
24
 
25
- export default cosmos;
25
+ export default algorand;
@@ -5,19 +5,14 @@ import type { AlgorandResources } from "./types";
5
5
  import { AlgorandOperationTypeEnum } from "./types";
6
6
 
7
7
  const getAlgorandResources = async (
8
- account: Account,
9
8
  coreAccount
10
9
  ): Promise<AlgorandResources> => {
11
10
  const algorandAccount = await coreAccount.asAlgorandAccount();
12
11
  const rewardsBigInt = await algorandAccount.getPendingRewards();
13
- const rewardsAccumulatedBigInt = await algorandAccount.getTotalRewards();
14
12
  const rewards = await libcoreAmountToBigNumber(rewardsBigInt);
15
- const rewardsAccumulated = await libcoreAmountToBigNumber(
16
- rewardsAccumulatedBigInt
17
- );
18
13
  return {
19
14
  rewards,
20
- rewardsAccumulated,
15
+ nbAssets: 0, // unused in libcore implem
21
16
  };
22
17
  };
23
18
 
@@ -39,7 +34,7 @@ const postBuildAccount = async ({
39
34
  account: Account;
40
35
  coreAccount: CoreAccount;
41
36
  }): Promise<Account> => {
42
- account.algorandResources = await getAlgorandResources(account, coreAccount);
37
+ account.algorandResources = await getAlgorandResources(coreAccount);
43
38
  account.spendableBalance = await getAlgorandSpendableBalance(coreAccount);
44
39
  return account;
45
40
  };
@@ -1,7 +1,7 @@
1
1
  import Algorand from "@ledgerhq/hw-app-algorand";
2
2
  import { makeSignOperation } from "../../libcore/signOperation";
3
3
  import buildTransaction from "./libcore-buildTransaction";
4
- import type { Transaction, CoreAlgorandTransaction } from "./types";
4
+ import type { AlgorandTransaction, CoreAlgorandTransaction } from "./types";
5
5
  import type { Operation } from "../../types";
6
6
  import { BigNumber } from "bignumber.js";
7
7
 
@@ -98,7 +98,7 @@ async function signTransaction({
98
98
  };
99
99
  }
100
100
 
101
- export default makeSignOperation<Transaction, CoreAlgorandTransaction>({
101
+ export default makeSignOperation<AlgorandTransaction, CoreAlgorandTransaction>({
102
102
  buildTransaction,
103
103
  signTransaction,
104
104
  });