@ledgerhq/live-common 24.1.0 → 25.0.0-next.1

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 (235) hide show
  1. package/lib/apps/support.js +1 -1
  2. package/lib/apps/support.js.map +1 -1
  3. package/lib/bot/index.d.ts.map +1 -1
  4. package/lib/bot/index.js +4 -2
  5. package/lib/bot/index.js.map +1 -1
  6. package/lib/bot/specs.d.ts +1 -0
  7. package/lib/bot/specs.d.ts.map +1 -1
  8. package/lib/bot/specs.js +6 -1
  9. package/lib/bot/specs.js.map +1 -1
  10. package/lib/currencies/support.d.ts +1 -1
  11. package/lib/currencies/support.d.ts.map +1 -1
  12. package/lib/env.d.ts +15 -5
  13. package/lib/env.d.ts.map +1 -1
  14. package/lib/env.js +10 -0
  15. package/lib/env.js.map +1 -1
  16. package/lib/env.react.d.ts +1 -1
  17. package/lib/env.react.d.ts.map +1 -1
  18. package/lib/errors.d.ts +101 -306
  19. package/lib/errors.d.ts.map +1 -1
  20. package/lib/errors.js +3 -4
  21. package/lib/errors.js.map +1 -1
  22. package/lib/errors.test.d.ts +2 -0
  23. package/lib/errors.test.d.ts.map +1 -0
  24. package/lib/errors.test.js +20 -0
  25. package/lib/errors.test.js.map +1 -0
  26. package/lib/exchange/swap/utils/index.test.js +2 -2
  27. package/lib/exchange/swap/utils/index.test.js.map +1 -1
  28. package/lib/families/bitcoin/datasets/bitcoin.d.ts.map +1 -1
  29. package/lib/families/bitcoin/datasets/bitcoin.js +2 -4
  30. package/lib/families/bitcoin/datasets/bitcoin.js.map +1 -1
  31. package/lib/families/bitcoin/descriptor.d.ts.map +1 -1
  32. package/lib/families/bitcoin/descriptor.js +3 -1
  33. package/lib/families/bitcoin/descriptor.js.map +1 -1
  34. package/lib/families/bitcoin/errors.d.ts +1 -3
  35. package/lib/families/bitcoin/errors.d.ts.map +1 -1
  36. package/lib/families/bitcoin/exchange.js +1 -1
  37. package/lib/families/bitcoin/exchange.js.map +1 -1
  38. package/lib/families/bitcoin/hw-getAddress.d.ts +1 -1
  39. package/lib/families/bitcoin/hw-getAddress.d.ts.map +1 -1
  40. package/lib/families/bitcoin/js-synchronisation.d.ts.map +1 -1
  41. package/lib/families/bitcoin/js-synchronisation.js +20 -2
  42. package/lib/families/bitcoin/js-synchronisation.js.map +1 -1
  43. package/lib/families/bitcoin/wallet-btc/storage/index.d.ts +0 -36
  44. package/lib/families/bitcoin/wallet-btc/storage/index.d.ts.map +1 -1
  45. package/lib/families/bitcoin/wallet-btc/storage/index.js +14 -14
  46. package/lib/families/bitcoin/wallet-btc/storage/index.js.map +1 -1
  47. package/lib/families/bitcoin/wallet-btc/storage/types.d.ts +1 -0
  48. package/lib/families/bitcoin/wallet-btc/storage/types.d.ts.map +1 -1
  49. package/lib/families/bitcoin/xpub.txs.loadExport.unit.test.d.ts +2 -0
  50. package/lib/families/bitcoin/xpub.txs.loadExport.unit.test.d.ts.map +1 -0
  51. package/lib/families/bitcoin/xpub.txs.loadExport.unit.test.js +146 -0
  52. package/lib/families/bitcoin/xpub.txs.loadExport.unit.test.js.map +1 -0
  53. package/lib/families/cardano/errors.d.ts +1 -3
  54. package/lib/families/cardano/errors.d.ts.map +1 -1
  55. package/lib/families/crypto_org/errors.d.ts +3 -9
  56. package/lib/families/crypto_org/errors.d.ts.map +1 -1
  57. package/lib/families/ethereum/exchange.js +1 -1
  58. package/lib/families/ethereum/exchange.js.map +1 -1
  59. package/lib/families/ethereum/modules/index.d.ts +1 -1
  60. package/lib/families/ethereum/modules/index.d.ts.map +1 -1
  61. package/lib/families/ethereum/signOperation.js +2 -2
  62. package/lib/families/ethereum/signOperation.js.map +1 -1
  63. package/lib/families/ethereum/specs.d.ts +1 -1
  64. package/lib/families/ethereum/specs.js +5 -5
  65. package/lib/families/ethereum/specs.js.map +1 -1
  66. package/lib/families/polkadot/errors.d.ts +12 -36
  67. package/lib/families/polkadot/errors.d.ts.map +1 -1
  68. package/lib/families/ripple/exchange.js +1 -1
  69. package/lib/families/ripple/exchange.js.map +1 -1
  70. package/lib/families/solana/api/chain/instruction/token/types.d.ts +3 -3
  71. package/lib/families/solana/errors.d.ts +20 -60
  72. package/lib/families/solana/errors.d.ts.map +1 -1
  73. package/lib/families/stellar/api/horizon.d.ts +29 -7
  74. package/lib/families/stellar/api/horizon.d.ts.map +1 -1
  75. package/lib/families/stellar/api/horizon.js +114 -58
  76. package/lib/families/stellar/api/horizon.js.map +1 -1
  77. package/lib/families/stellar/api/index.d.ts +1 -1
  78. package/lib/families/stellar/api/index.d.ts.map +1 -1
  79. package/lib/families/stellar/api/index.js +5 -1
  80. package/lib/families/stellar/api/index.js.map +1 -1
  81. package/lib/families/stellar/bridge/mock.d.ts.map +1 -1
  82. package/lib/families/stellar/bridge/mock.js +4 -1
  83. package/lib/families/stellar/bridge/mock.js.map +1 -1
  84. package/lib/families/stellar/bridge.integration.test.js +12 -4
  85. package/lib/families/stellar/bridge.integration.test.js.map +1 -1
  86. package/lib/families/stellar/cli-transaction.d.ts +3 -1
  87. package/lib/families/stellar/cli-transaction.d.ts.map +1 -1
  88. package/lib/families/stellar/cli-transaction.js +48 -2
  89. package/lib/families/stellar/cli-transaction.js.map +1 -1
  90. package/lib/families/stellar/deviceTransactionConfig.d.ts +7 -1
  91. package/lib/families/stellar/deviceTransactionConfig.d.ts.map +1 -1
  92. package/lib/families/stellar/deviceTransactionConfig.js +12 -1
  93. package/lib/families/stellar/deviceTransactionConfig.js.map +1 -1
  94. package/lib/families/stellar/errors.d.ts +12 -0
  95. package/lib/families/stellar/errors.d.ts.map +1 -0
  96. package/lib/families/stellar/errors.js +16 -0
  97. package/lib/families/stellar/errors.js.map +1 -0
  98. package/lib/families/stellar/exchange.js +1 -1
  99. package/lib/families/stellar/exchange.js.map +1 -1
  100. package/lib/families/stellar/js-buildTransaction.d.ts.map +1 -1
  101. package/lib/families/stellar/js-buildTransaction.js +34 -16
  102. package/lib/families/stellar/js-buildTransaction.js.map +1 -1
  103. package/lib/families/stellar/js-createTransaction.d.ts.map +1 -1
  104. package/lib/families/stellar/js-createTransaction.js +4 -1
  105. package/lib/families/stellar/js-createTransaction.js.map +1 -1
  106. package/lib/families/stellar/js-estimateMaxSpendable.js +2 -1
  107. package/lib/families/stellar/js-estimateMaxSpendable.js.map +1 -1
  108. package/lib/families/stellar/js-getTransactionStatus.d.ts.map +1 -1
  109. package/lib/families/stellar/js-getTransactionStatus.js +127 -57
  110. package/lib/families/stellar/js-getTransactionStatus.js.map +1 -1
  111. package/lib/families/stellar/js-prepareTransaction.d.ts.map +1 -1
  112. package/lib/families/stellar/js-prepareTransaction.js +25 -7
  113. package/lib/families/stellar/js-prepareTransaction.js.map +1 -1
  114. package/lib/families/stellar/js-signOperation.d.ts.map +1 -1
  115. package/lib/families/stellar/js-signOperation.js +33 -6
  116. package/lib/families/stellar/js-signOperation.js.map +1 -1
  117. package/lib/families/stellar/js-synchronization.d.ts +1 -1
  118. package/lib/families/stellar/js-synchronization.d.ts.map +1 -1
  119. package/lib/families/stellar/js-synchronization.js +42 -16
  120. package/lib/families/stellar/js-synchronization.js.map +1 -1
  121. package/lib/families/stellar/logic.d.ts +21 -14
  122. package/lib/families/stellar/logic.d.ts.map +1 -1
  123. package/lib/families/stellar/logic.js +158 -57
  124. package/lib/families/stellar/logic.js.map +1 -1
  125. package/lib/families/stellar/specs.d.ts.map +1 -1
  126. package/lib/families/stellar/specs.js +182 -7
  127. package/lib/families/stellar/specs.js.map +1 -1
  128. package/lib/families/stellar/speculos-deviceActions.d.ts.map +1 -1
  129. package/lib/families/stellar/speculos-deviceActions.js +60 -28
  130. package/lib/families/stellar/speculos-deviceActions.js.map +1 -1
  131. package/lib/families/stellar/tokens.d.ts +11 -0
  132. package/lib/families/stellar/tokens.d.ts.map +1 -0
  133. package/lib/families/stellar/tokens.js +82 -0
  134. package/lib/families/stellar/tokens.js.map +1 -0
  135. package/lib/families/stellar/transaction.d.ts +2 -2
  136. package/lib/families/stellar/transaction.d.ts.map +1 -1
  137. package/lib/families/stellar/transaction.js +32 -6
  138. package/lib/families/stellar/transaction.js.map +1 -1
  139. package/lib/families/stellar/types.d.ts +45 -0
  140. package/lib/families/stellar/types.d.ts.map +1 -1
  141. package/lib/families/stellar/types.js +7 -1
  142. package/lib/families/stellar/types.js.map +1 -1
  143. package/lib/families/tezos/exchange.js +1 -1
  144. package/lib/families/tezos/exchange.js.map +1 -1
  145. package/lib/generated/cli-transaction.d.ts +1 -0
  146. package/lib/generated/cli-transaction.d.ts.map +1 -1
  147. package/lib/generated/specs.d.ts +1 -1
  148. package/lib/generated/transaction.d.ts +1 -1
  149. package/lib/hw/signMessage/index.d.ts +4 -3
  150. package/lib/hw/signMessage/index.d.ts.map +1 -1
  151. package/lib/hw/signMessage/index.js +25 -11
  152. package/lib/hw/signMessage/index.js.map +1 -1
  153. package/lib/hw/signMessage/index.test.d.ts +2 -0
  154. package/lib/hw/signMessage/index.test.d.ts.map +1 -0
  155. package/lib/hw/signMessage/index.test.js +126 -0
  156. package/lib/hw/signMessage/index.test.js.map +1 -0
  157. package/lib/load/speculos.d.ts.map +1 -1
  158. package/lib/load/speculos.js +1 -3
  159. package/lib/load/speculos.js.map +1 -1
  160. package/lib/mock/Btc.d.ts +1 -1
  161. package/lib/mock/Btc.d.ts.map +1 -1
  162. package/lib/performance.d.ts +10 -0
  163. package/lib/performance.d.ts.map +1 -0
  164. package/lib/performance.js +72 -0
  165. package/lib/performance.js.map +1 -0
  166. package/lib/performance.test.d.ts +2 -0
  167. package/lib/performance.test.d.ts.map +1 -0
  168. package/lib/performance.test.js +28 -0
  169. package/lib/performance.test.js.map +1 -0
  170. package/lib/platform/providers/RemoteLiveAppProvider/api/index.d.ts.map +1 -1
  171. package/lib/platform/providers/RemoteLiveAppProvider/api/index.js +28 -0
  172. package/lib/platform/providers/RemoteLiveAppProvider/api/index.js.map +1 -1
  173. package/lib/platform/providers/RemoteLiveAppProvider/api/mock.json +0 -31
  174. package/lib/types/currencies.d.ts +1 -1
  175. package/lib/types/currencies.d.ts.map +1 -1
  176. package/lib/walletconnect/Provider.d.ts.map +1 -1
  177. package/lib/walletconnect/Provider.js +1 -3
  178. package/lib/walletconnect/Provider.js.map +1 -1
  179. package/package.json +71 -19
  180. package/src/apps/support.ts +1 -1
  181. package/src/bot/index.ts +3 -1
  182. package/src/bot/specs.ts +7 -1
  183. package/src/currencies/__snapshots__/sortByMarketcap.test.ts.snap +34 -6
  184. package/src/currencies/support.ts +1 -1
  185. package/src/env.ts +10 -0
  186. package/src/errors.test.ts +21 -0
  187. package/src/errors.ts +1 -6
  188. package/src/exchange/swap/utils/index.test.ts +1 -1
  189. package/src/families/bitcoin/datasets/bitcoin.ts +0 -2
  190. package/src/families/bitcoin/descriptor.ts +4 -1
  191. package/src/families/bitcoin/exchange.ts +1 -1
  192. package/src/families/bitcoin/hw-getAddress.ts +1 -1
  193. package/src/families/bitcoin/js-synchronisation.ts +23 -1
  194. package/src/families/bitcoin/wallet-btc/storage/index.ts +17 -31
  195. package/src/families/bitcoin/wallet-btc/storage/types.ts +1 -0
  196. package/src/families/bitcoin/wallet-btc/wallet.ts +1 -1
  197. package/src/families/bitcoin/xpub.txs.loadExport.unit.test.ts +101 -0
  198. package/src/families/ethereum/exchange.ts +1 -1
  199. package/src/families/ethereum/modules/index.ts +1 -1
  200. package/src/families/ethereum/signOperation.ts +2 -2
  201. package/src/families/ethereum/specs.ts +5 -5
  202. package/src/families/ripple/exchange.ts +1 -1
  203. package/src/families/stellar/__snapshots__/bridge.integration.test.ts.snap +765 -339
  204. package/src/families/stellar/api/horizon.ts +115 -33
  205. package/src/families/stellar/api/index.ts +4 -0
  206. package/src/families/stellar/bridge/mock.ts +3 -0
  207. package/src/families/stellar/bridge.integration.test.ts +10 -2
  208. package/src/families/stellar/cli-transaction.ts +75 -2
  209. package/src/families/stellar/deviceTransactionConfig.ts +22 -0
  210. package/src/families/stellar/errors.ts +34 -0
  211. package/src/families/stellar/exchange.ts +1 -1
  212. package/src/families/stellar/js-buildTransaction.ts +56 -16
  213. package/src/families/stellar/js-createTransaction.ts +3 -0
  214. package/src/families/stellar/js-estimateMaxSpendable.ts +1 -1
  215. package/src/families/stellar/js-getTransactionStatus.ts +152 -60
  216. package/src/families/stellar/js-prepareTransaction.ts +4 -3
  217. package/src/families/stellar/js-signOperation.ts +37 -6
  218. package/src/families/stellar/js-synchronization.ts +53 -11
  219. package/src/families/stellar/logic.ts +198 -62
  220. package/src/families/stellar/specs.ts +227 -8
  221. package/src/families/stellar/speculos-deviceActions.ts +66 -22
  222. package/src/families/stellar/tokens.ts +118 -0
  223. package/src/families/stellar/transaction.ts +31 -3
  224. package/src/families/stellar/types.ts +52 -0
  225. package/src/families/tezos/exchange.ts +1 -1
  226. package/src/hw/signMessage/index.test.ts +128 -0
  227. package/src/hw/signMessage/index.ts +37 -15
  228. package/src/load/speculos.ts +1 -3
  229. package/src/mock/Btc.ts +1 -1
  230. package/src/performance.test.ts +26 -0
  231. package/src/performance.ts +61 -0
  232. package/src/platform/providers/RemoteLiveAppProvider/api/index.ts +6 -0
  233. package/src/platform/providers/RemoteLiveAppProvider/api/mock.json +1 -32
  234. package/src/types/currencies.ts +1 -1
  235. package/src/walletconnect/Provider.tsx +4 -5
@@ -3,26 +3,36 @@ import {
3
3
  AmountRequired,
4
4
  NotEnoughBalance,
5
5
  FeeNotLoaded,
6
- InvalidAddress,
7
6
  InvalidAddressBecauseDestinationIsAlsoSource,
8
7
  NotEnoughSpendableBalance,
9
8
  NotEnoughBalanceBecauseDestinationNotCreated,
10
9
  RecipientRequired,
10
+ InvalidAddress,
11
11
  } from "@ledgerhq/errors";
12
12
  import {
13
13
  StellarWrongMemoFormat,
14
- SourceHasMultiSign,
15
14
  AccountAwaitingSendPendingOperations,
15
+ StellarAssetRequired,
16
+ StellarAssetNotAccepted,
17
+ StellarAssetNotFound,
18
+ StellarNotEnoughNativeBalance,
19
+ StellarFeeSmallerThanRecommended,
20
+ StellarFeeSmallerThanBase,
21
+ StellarNotEnoughNativeBalanceToAddTrustline,
22
+ StellarMuxedAccountNotExist,
23
+ StellarSourceHasMultiSign,
16
24
  } from "../../errors";
25
+ import { findSubAccountById } from "../../account";
17
26
  import { formatCurrencyUnit } from "../../currencies";
18
- import type { Account } from "../../types";
27
+ import type { Account, TokenAccount } from "../../types";
19
28
  import type { Transaction } from "./types";
20
29
  import {
21
30
  isAddressValid,
22
- checkRecipientExist,
23
31
  isAccountMultiSign,
24
32
  isMemoValid,
33
+ getRecipientAccount,
25
34
  } from "./logic";
35
+ import { BASE_RESERVE, MIN_BALANCE } from "./api";
26
36
 
27
37
  const getTransactionStatus = async (
28
38
  a: Account,
@@ -38,81 +48,163 @@ const getTransactionStatus = async (
38
48
  const warnings: Record<string, Error> = {};
39
49
  const useAllAmount = !!t.useAllAmount;
40
50
 
51
+ const destinationNotExistMessage =
52
+ new NotEnoughBalanceBecauseDestinationNotCreated("", {
53
+ minimalAmount: `${MIN_BALANCE} XLM`,
54
+ });
55
+
41
56
  if (a.pendingOperations.length > 0) {
42
57
  throw new AccountAwaitingSendPendingOperations();
43
58
  }
44
59
 
45
- if (!t.recipient) {
46
- errors.recipient = new RecipientRequired("");
47
- } else if (a.freshAddress === t.recipient) {
48
- errors.recipient = new InvalidAddressBecauseDestinationIsAlsoSource();
49
- } else if (!isAddressValid(t.recipient)) {
50
- errors.recipient = new InvalidAddress("");
51
- }
52
-
53
- if (await isAccountMultiSign(a)) {
54
- errors.recipient = new SourceHasMultiSign("", {
55
- currencyName: a.currency.name,
56
- });
57
- }
58
-
59
60
  if (!t.fees || !t.baseReserve) {
60
61
  errors.fees = new FeeNotLoaded();
61
62
  }
62
63
 
63
64
  const estimatedFees = !t.fees ? new BigNumber(0) : t.fees;
64
65
  const baseReserve = !t.baseReserve ? new BigNumber(0) : t.baseReserve;
65
- let amount = !useAllAmount
66
- ? t.amount
67
- : a.balance.minus(baseReserve).minus(estimatedFees);
68
- let totalSpent = !useAllAmount
69
- ? amount.plus(estimatedFees)
70
- : a.balance.minus(baseReserve);
71
-
72
- if (totalSpent.gt(a.balance.minus(baseReserve))) {
73
- errors.amount = new NotEnoughSpendableBalance(undefined, {
74
- minimumAmount: formatCurrencyUnit(a.currency.units[0], baseReserve, {
75
- disableRounding: true,
76
- showCode: true,
77
- }),
78
- });
79
- }
66
+ const isAssetPayment = t.subAccountId && t.assetCode && t.assetIssuer;
67
+ const nativeBalance = a.balance;
68
+ const nativeAmountAvailable = a.spendableBalance.minus(estimatedFees);
80
69
 
81
- if (
82
- !errors.amount &&
83
- amount.plus(estimatedFees).plus(baseReserve).gt(a.balance)
84
- ) {
85
- errors.amount = new NotEnoughBalance();
86
- }
70
+ let amount = new BigNumber(0);
71
+ let maxAmount = new BigNumber(0);
72
+ let totalSpent = new BigNumber(0);
87
73
 
88
- if (
89
- !errors.recipient &&
90
- !errors.amount &&
91
- (amount.lt(0) || totalSpent.gt(a.balance))
92
- ) {
93
- errors.amount = new NotEnoughBalance();
94
- totalSpent = new BigNumber(0);
95
- amount = new BigNumber(0);
74
+ // Enough native balance to cover transaction (with required reserve + fees)
75
+ if (!errors.amount && nativeAmountAvailable.lt(0)) {
76
+ errors.amount = new StellarNotEnoughNativeBalance();
96
77
  }
97
78
 
98
- if (!errors.amount && amount.eq(0)) {
99
- errors.amount = new AmountRequired();
79
+ // Entered fee is smaller than base fee
80
+ if (estimatedFees.lt(t.networkInfo?.baseFee || 0)) {
81
+ errors.transaction = new StellarFeeSmallerThanBase();
82
+ // Entered fee is smaller than recommended
83
+ } else if (estimatedFees.lt(t.networkInfo?.fees || 0)) {
84
+ warnings.transaction = new StellarFeeSmallerThanRecommended();
100
85
  }
101
86
 
102
- // if amount < 1.0 you can't send to an empty address
103
- if (
104
- !errors.recipient &&
105
- t.recipient &&
106
- !errors.amount &&
107
- !(await checkRecipientExist({
87
+ // Operation specific checks
88
+ if (t.mode === "changeTrust") {
89
+ // Check asset provided
90
+ if (!t.assetCode || !t.assetIssuer) {
91
+ // This is unlikely
92
+ errors.transaction = new StellarAssetRequired("");
93
+ }
94
+
95
+ // Has enough native balance to add new trustline
96
+ if (nativeAmountAvailable.minus(BASE_RESERVE).lt(0)) {
97
+ errors.amount = new StellarNotEnoughNativeBalanceToAddTrustline();
98
+ }
99
+ } else {
100
+ // Payment
101
+ // Check recipient address
102
+ if (!t.recipient) {
103
+ errors.recipient = new RecipientRequired("");
104
+ } else if (!isAddressValid(t.recipient)) {
105
+ errors.recipient = new InvalidAddress("");
106
+ } else if (a.freshAddress === t.recipient) {
107
+ errors.recipient = new InvalidAddressBecauseDestinationIsAlsoSource();
108
+ }
109
+
110
+ const recipientAccount = await getRecipientAccount({
108
111
  account: a,
109
112
  recipient: t.recipient,
110
- })) &&
111
- amount.lt(10000000)
112
- ) {
113
- errors.amount = new NotEnoughBalanceBecauseDestinationNotCreated("", {
114
- minimalAmount: "1 XLM",
115
113
  });
114
+
115
+ // Check recipient account
116
+ if (!recipientAccount?.id && !errors.recipient && !warnings.recipient) {
117
+ if (recipientAccount?.isMuxedAccount) {
118
+ errors.recipient = new StellarMuxedAccountNotExist();
119
+ } else {
120
+ if (isAssetPayment) {
121
+ errors.recipient = destinationNotExistMessage;
122
+ } else {
123
+ warnings.recipient = destinationNotExistMessage;
124
+ }
125
+ }
126
+ }
127
+
128
+ // Asset payment
129
+ if (isAssetPayment) {
130
+ const asset = findSubAccountById(a, t.subAccountId || "") as TokenAccount;
131
+
132
+ if (asset === null) {
133
+ // This is unlikely
134
+ throw new StellarAssetNotFound();
135
+ }
136
+
137
+ // Check recipient account accepts asset
138
+ if (
139
+ recipientAccount?.id &&
140
+ !errors.recipient &&
141
+ !warnings.recipient &&
142
+ !recipientAccount.assetIds.includes(`${t.assetCode}:${t.assetIssuer}`)
143
+ ) {
144
+ errors.recipient = new StellarAssetNotAccepted("", {
145
+ assetCode: t.assetCode,
146
+ });
147
+ }
148
+
149
+ const assetBalance = asset?.balance || new BigNumber(0);
150
+
151
+ maxAmount = asset?.spendableBalance || assetBalance;
152
+ amount = useAllAmount ? maxAmount : t.amount;
153
+ totalSpent = amount;
154
+
155
+ if (!errors.amount && amount.gt(assetBalance)) {
156
+ errors.amount = new NotEnoughBalance();
157
+ }
158
+ } else {
159
+ // Native payment
160
+ maxAmount = nativeAmountAvailable;
161
+ amount = useAllAmount ? maxAmount : t.amount || 0;
162
+
163
+ if (amount.gt(maxAmount)) {
164
+ errors.amount = new NotEnoughBalance();
165
+ }
166
+
167
+ totalSpent = useAllAmount
168
+ ? nativeAmountAvailable
169
+ : t.amount.plus(estimatedFees);
170
+
171
+ // Need to send at least 1 XLM to create an account
172
+ if (
173
+ !errors.recipient &&
174
+ !recipientAccount?.id &&
175
+ !errors.amount &&
176
+ amount.lt(10000000)
177
+ ) {
178
+ errors.amount = destinationNotExistMessage;
179
+ }
180
+
181
+ if (totalSpent.gt(nativeBalance.minus(baseReserve))) {
182
+ errors.amount = new NotEnoughSpendableBalance(undefined, {
183
+ minimumAmount: formatCurrencyUnit(a.currency.units[0], baseReserve, {
184
+ disableRounding: true,
185
+ showCode: true,
186
+ }),
187
+ });
188
+ }
189
+
190
+ if (
191
+ !errors.recipient &&
192
+ !errors.amount &&
193
+ (amount.lt(0) || totalSpent.gt(nativeBalance))
194
+ ) {
195
+ errors.amount = new NotEnoughBalance();
196
+ totalSpent = new BigNumber(0);
197
+ amount = new BigNumber(0);
198
+ }
199
+
200
+ if (!errors.amount && amount.eq(0)) {
201
+ errors.amount = new AmountRequired();
202
+ }
203
+ }
204
+ }
205
+
206
+ if (await isAccountMultiSign(a)) {
207
+ errors.recipient = new StellarSourceHasMultiSign();
116
208
  }
117
209
 
118
210
  if (t.memoType && t.memoValue && !isMemoValid(t.memoType, t.memoValue)) {
@@ -1,7 +1,7 @@
1
1
  import invariant from "invariant";
2
2
  import { fetchAccountNetworkInfo } from "./api";
3
3
  import type { Account } from "../../types";
4
-
4
+ import { getAssetCodeIssuer } from "./logic";
5
5
  import type { Transaction } from "./types";
6
6
 
7
7
  const prepareTransaction = async (
@@ -12,16 +12,17 @@ const prepareTransaction = async (
12
12
  invariant(networkInfo.family === "stellar", "stellar networkInfo expected");
13
13
  const fees = t.fees || networkInfo.fees;
14
14
  const baseReserve = t.baseReserve || networkInfo.baseReserve;
15
+ const [assetCode, assetIssuer] = getAssetCodeIssuer(t);
15
16
 
16
17
  if (
17
18
  t.networkInfo !== networkInfo ||
18
19
  t.fees !== fees ||
19
20
  t.baseReserve !== baseReserve
20
21
  ) {
21
- return { ...t, networkInfo, fees, baseReserve };
22
+ return { ...t, networkInfo, fees, baseReserve, assetCode, assetIssuer };
22
23
  }
23
24
 
24
- return t;
25
+ return { ...t, assetCode, assetIssuer };
25
26
  };
26
27
 
27
28
  export default prepareTransaction;
@@ -7,6 +7,7 @@ import { withDevice } from "../../hw/deviceAccess";
7
7
  import type { Transaction } from "./types";
8
8
  import { buildTransaction } from "./js-buildTransaction";
9
9
  import { fetchSequence } from "./api";
10
+ import { getAmountValue } from "./logic";
10
11
 
11
12
  const buildOptimisticOperation = async (
12
13
  account: Account,
@@ -14,14 +15,15 @@ const buildOptimisticOperation = async (
14
15
  ): Promise<Operation> => {
15
16
  const transactionSequenceNumber = await fetchSequence(account);
16
17
  const fees = transaction.fees ?? new BigNumber(0);
18
+ const type = transaction.mode === "changeTrust" ? "OPT_IN" : "OUT";
19
+
17
20
  const operation: Operation = {
18
- id: `${account.id}--OUT`,
21
+ id: `${account.id}--${type}`,
19
22
  hash: "",
20
- type: "OUT",
21
- value:
22
- transaction.useAllAmount && transaction.networkInfo
23
- ? account.balance.minus(transaction.networkInfo.baseReserve).minus(fees)
24
- : transaction.amount.plus(fees),
23
+ type,
24
+ value: transaction.subAccountId
25
+ ? fees
26
+ : getAmountValue(account, transaction, fees),
25
27
  fee: fees,
26
28
  blockHash: null,
27
29
  blockHeight: null,
@@ -33,6 +35,35 @@ const buildOptimisticOperation = async (
33
35
  transactionSequenceNumber: transactionSequenceNumber?.plus(1).toNumber(),
34
36
  extra: {},
35
37
  };
38
+
39
+ const { subAccountId } = transaction;
40
+ const { subAccounts } = account;
41
+
42
+ const tokenAccount = !subAccountId
43
+ ? null
44
+ : subAccounts && subAccounts.find((ta) => ta.id === subAccountId);
45
+
46
+ if (tokenAccount && subAccountId) {
47
+ operation.subOperations = [
48
+ {
49
+ id: `${subAccountId}--OUT`,
50
+ hash: "",
51
+ type: "OUT",
52
+ value: transaction.useAllAmount
53
+ ? tokenAccount.balance
54
+ : transaction.amount,
55
+ fee: new BigNumber(0),
56
+ blockHash: null,
57
+ blockHeight: null,
58
+ senders: [account.freshAddress],
59
+ recipients: [transaction.recipient],
60
+ accountId: subAccountId,
61
+ date: new Date(),
62
+ extra: {},
63
+ },
64
+ ];
65
+ }
66
+
36
67
  return operation;
37
68
  };
38
69
 
@@ -1,10 +1,13 @@
1
+ import type { Operation } from "../../types";
1
2
  import { encodeAccountId } from "../../account";
2
3
  import type { GetAccountShape } from "../../bridge/jsHelpers";
3
4
  import { makeScanAccounts, makeSync, mergeOps } from "../../bridge/jsHelpers";
4
5
  import { fetchAccount, fetchOperations } from "./api";
6
+ import { buildSubAccounts } from "./tokens";
7
+ import { inferSubOperations } from "../../account";
5
8
 
6
- const getAccountShape: GetAccountShape = async (info) => {
7
- const { address, initialAccount, currency, derivationMode } = info;
9
+ const getAccountShape: GetAccountShape = async (info, syncConfig) => {
10
+ const { address, currency, initialAccount, derivationMode } = info;
8
11
  const accountId = encodeAccountId({
9
12
  type: "js",
10
13
  version: "2",
@@ -12,23 +15,62 @@ const getAccountShape: GetAccountShape = async (info) => {
12
15
  xpubOrAddress: address,
13
16
  derivationMode,
14
17
  });
15
- const oldOperations = initialAccount?.operations || [];
16
- const startAt = oldOperations.length
17
- ? (oldOperations[0].blockHeight || 0) + 1
18
- : 0;
19
- const { blockHeight, balance, spendableBalance } = await fetchAccount(
18
+ const { blockHeight, balance, spendableBalance, assets } = await fetchAccount(
20
19
  address
21
20
  );
22
- const newOperations = await fetchOperations(accountId, address, startAt);
23
- const operations = mergeOps(oldOperations, newOperations);
21
+
22
+ const oldOperations = initialAccount?.operations || [];
23
+ const lastPagingToken = oldOperations[0]?.extra?.pagingToken || 0;
24
+
25
+ const newOperations =
26
+ (await fetchOperations({
27
+ accountId,
28
+ addr: address,
29
+ order: "asc",
30
+ cursor: lastPagingToken,
31
+ })) || [];
32
+
33
+ const allOperations = mergeOps(oldOperations, newOperations);
34
+ const assetOperations: Operation[] = [];
35
+
36
+ allOperations.forEach((op) => {
37
+ if (
38
+ op?.extra?.assetCode &&
39
+ op?.extra?.assetIssuer &&
40
+ !["OPT_IN", "OPT_OUT"].includes(op.type)
41
+ ) {
42
+ assetOperations.push(op);
43
+ }
44
+ });
45
+
46
+ const subAccounts =
47
+ buildSubAccounts({
48
+ currency,
49
+ accountId,
50
+ assets,
51
+ syncConfig,
52
+ operations: assetOperations,
53
+ }) || [];
54
+
24
55
  const shape = {
25
56
  id: accountId,
26
57
  balance,
27
58
  spendableBalance,
28
- operationsCount: operations.length,
59
+ operationsCount: allOperations.length,
29
60
  blockHeight,
61
+ subAccounts,
62
+ };
63
+ return {
64
+ ...shape,
65
+ operations: allOperations.map((op) => {
66
+ const subOperations = inferSubOperations(op.hash, subAccounts);
67
+
68
+ return {
69
+ ...op,
70
+ subOperations,
71
+ };
72
+ }),
30
73
  };
31
- return { ...shape, operations };
32
74
  };
33
75
 
34
76
  export const sync = makeSync({ getAccountShape });