@ledgerhq/live-common 27.2.0 → 27.3.0-nightly.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (219) hide show
  1. package/lib/bot/index.d.ts.map +1 -1
  2. package/lib/bot/index.js +8 -3
  3. package/lib/bot/index.js.map +1 -1
  4. package/lib/bot/specs.d.ts +9 -0
  5. package/lib/bot/specs.d.ts.map +1 -1
  6. package/lib/bot/specs.js +49 -1
  7. package/lib/bot/specs.js.map +1 -1
  8. package/lib/currencies/support.d.ts.map +1 -1
  9. package/lib/currencies/support.js +2 -1
  10. package/lib/currencies/support.js.map +1 -1
  11. package/lib/derivation.d.ts.map +1 -1
  12. package/lib/derivation.js +2 -4
  13. package/lib/derivation.js.map +1 -1
  14. package/lib/env.js +1 -1
  15. package/lib/exchange/swap/getExchangeRates.d.ts.map +1 -1
  16. package/lib/exchange/swap/getExchangeRates.js +1 -1
  17. package/lib/exchange/swap/getExchangeRates.js.map +1 -1
  18. package/lib/exchange/swap/getProviders.d.ts.map +1 -1
  19. package/lib/exchange/swap/getProviders.js +45 -5
  20. package/lib/exchange/swap/getProviders.js.map +1 -1
  21. package/lib/exchange/swap/getProviders.test.d.ts +2 -0
  22. package/lib/exchange/swap/getProviders.test.d.ts.map +1 -0
  23. package/lib/exchange/swap/getProviders.test.js +519 -0
  24. package/lib/exchange/swap/getProviders.test.js.map +1 -0
  25. package/lib/exchange/swap/hooks/useProviderRates.d.ts +1 -0
  26. package/lib/exchange/swap/hooks/useProviderRates.d.ts.map +1 -1
  27. package/lib/exchange/swap/hooks/useProviderRates.js +19 -4
  28. package/lib/exchange/swap/hooks/useProviderRates.js.map +1 -1
  29. package/lib/exchange/swap/hooks/useProviderRates.test.js +42 -0
  30. package/lib/exchange/swap/hooks/useProviderRates.test.js.map +1 -1
  31. package/lib/exchange/swap/hooks/useSwapTransaction.d.ts +1 -0
  32. package/lib/exchange/swap/hooks/useSwapTransaction.d.ts.map +1 -1
  33. package/lib/exchange/swap/hooks/useSwapTransaction.js +2 -1
  34. package/lib/exchange/swap/hooks/useSwapTransaction.js.map +1 -1
  35. package/lib/exchange/swap/index.d.ts +2 -1
  36. package/lib/exchange/swap/index.d.ts.map +1 -1
  37. package/lib/exchange/swap/index.js +11 -1
  38. package/lib/exchange/swap/index.js.map +1 -1
  39. package/lib/exchange/swap/index.test.js +22 -0
  40. package/lib/exchange/swap/index.test.js.map +1 -1
  41. package/lib/exchange/swap/mock.js +1 -1
  42. package/lib/exchange/swap/mock.js.map +1 -1
  43. package/lib/exchange/swap/types.d.ts +14 -0
  44. package/lib/exchange/swap/types.d.ts.map +1 -1
  45. package/lib/exchange/swap/utils/index.d.ts +1 -0
  46. package/lib/exchange/swap/utils/index.d.ts.map +1 -1
  47. package/lib/exchange/swap/utils/index.js +6 -1
  48. package/lib/exchange/swap/utils/index.js.map +1 -1
  49. package/lib/exchange/swap/utils/index.test.js +12 -0
  50. package/lib/exchange/swap/utils/index.test.js.map +1 -1
  51. package/lib/families/algorand/speculos-deviceActions.d.ts.map +1 -1
  52. package/lib/families/algorand/speculos-deviceActions.js +2 -29
  53. package/lib/families/algorand/speculos-deviceActions.js.map +1 -1
  54. package/lib/families/bitcoin/specs.d.ts.map +1 -1
  55. package/lib/families/bitcoin/specs.js +0 -1
  56. package/lib/families/bitcoin/specs.js.map +1 -1
  57. package/lib/families/bitcoin/speculos-deviceActions.d.ts.map +1 -1
  58. package/lib/families/bitcoin/speculos-deviceActions.js +2 -22
  59. package/lib/families/bitcoin/speculos-deviceActions.js.map +1 -1
  60. package/lib/families/cardano/specs.d.ts.map +1 -1
  61. package/lib/families/cardano/specs.js +4 -3
  62. package/lib/families/cardano/specs.js.map +1 -1
  63. package/lib/families/cardano/speculos-deviceActions.d.ts.map +1 -1
  64. package/lib/families/cardano/speculos-deviceActions.js +2 -10
  65. package/lib/families/cardano/speculos-deviceActions.js.map +1 -1
  66. package/lib/families/celo/speculos-deviceActions.d.ts.map +1 -1
  67. package/lib/families/celo/speculos-deviceActions.js +3 -10
  68. package/lib/families/celo/speculos-deviceActions.js.map +1 -1
  69. package/lib/families/elrond/speculos-deviceActions.d.ts.map +1 -1
  70. package/lib/families/elrond/speculos-deviceActions.js +3 -8
  71. package/lib/families/elrond/speculos-deviceActions.js.map +1 -1
  72. package/lib/families/ethereum/speculos-deviceActions.d.ts.map +1 -1
  73. package/lib/families/ethereum/speculos-deviceActions.js +10 -33
  74. package/lib/families/ethereum/speculos-deviceActions.js.map +1 -1
  75. package/lib/families/evm/specs.d.ts.map +1 -1
  76. package/lib/families/evm/specs.js +9 -5
  77. package/lib/families/evm/specs.js.map +1 -1
  78. package/lib/families/evm/speculos-deviceActions.d.ts.map +1 -1
  79. package/lib/families/evm/speculos-deviceActions.js +5 -25
  80. package/lib/families/evm/speculos-deviceActions.js.map +1 -1
  81. package/lib/families/filecoin/speculos-deviceActions.d.ts.map +1 -1
  82. package/lib/families/filecoin/speculos-deviceActions.js +6 -7
  83. package/lib/families/filecoin/speculos-deviceActions.js.map +1 -1
  84. package/lib/families/polkadot/speculos-deviceActions.d.ts.map +1 -1
  85. package/lib/families/polkadot/speculos-deviceActions.js +3 -10
  86. package/lib/families/polkadot/speculos-deviceActions.js.map +1 -1
  87. package/lib/families/ripple/speculos-deviceActions.d.ts.map +1 -1
  88. package/lib/families/ripple/speculos-deviceActions.js +2 -22
  89. package/lib/families/ripple/speculos-deviceActions.js.map +1 -1
  90. package/lib/families/solana/speculos-deviceActions.d.ts.map +1 -1
  91. package/lib/families/solana/speculos-deviceActions.js +5 -7
  92. package/lib/families/solana/speculos-deviceActions.js.map +1 -1
  93. package/lib/families/stellar/speculos-deviceActions.d.ts.map +1 -1
  94. package/lib/families/stellar/speculos-deviceActions.js +4 -8
  95. package/lib/families/stellar/speculos-deviceActions.js.map +1 -1
  96. package/lib/families/tezos/speculos-deviceActions.d.ts.map +1 -1
  97. package/lib/families/tezos/speculos-deviceActions.js +6 -11
  98. package/lib/families/tezos/speculos-deviceActions.js.map +1 -1
  99. package/lib/families/tron/speculos-deviceActions.d.ts.map +1 -1
  100. package/lib/families/tron/speculos-deviceActions.js +2 -14
  101. package/lib/families/tron/speculos-deviceActions.js.map +1 -1
  102. package/lib/featureFlags/defaultFeatures.d.ts.map +1 -1
  103. package/lib/featureFlags/defaultFeatures.js +3 -0
  104. package/lib/featureFlags/defaultFeatures.js.map +1 -1
  105. package/lib/hw/extractOnboardingState.d.ts +5 -1
  106. package/lib/hw/extractOnboardingState.d.ts.map +1 -1
  107. package/lib/hw/extractOnboardingState.js +17 -9
  108. package/lib/hw/extractOnboardingState.js.map +1 -1
  109. package/lib/hw/extractOnboardingState.test.js +21 -11
  110. package/lib/hw/extractOnboardingState.test.js.map +1 -1
  111. package/lib/postOnboarding/PostOnboardingProvider.d.ts +20 -0
  112. package/lib/postOnboarding/PostOnboardingProvider.d.ts.map +1 -0
  113. package/lib/postOnboarding/PostOnboardingProvider.js +33 -0
  114. package/lib/postOnboarding/PostOnboardingProvider.js.map +1 -0
  115. package/lib/postOnboarding/actions.d.ts +20 -0
  116. package/lib/postOnboarding/actions.d.ts.map +1 -0
  117. package/lib/postOnboarding/actions.js +37 -0
  118. package/lib/postOnboarding/actions.js.map +1 -0
  119. package/lib/postOnboarding/hooks/index.d.ts +6 -0
  120. package/lib/postOnboarding/hooks/index.d.ts.map +1 -0
  121. package/lib/postOnboarding/hooks/index.js +22 -0
  122. package/lib/postOnboarding/hooks/index.js.map +1 -0
  123. package/lib/postOnboarding/hooks/useAllPostOnboardingActionsCompleted.d.ts +8 -0
  124. package/lib/postOnboarding/hooks/useAllPostOnboardingActionsCompleted.d.ts.map +1 -0
  125. package/lib/postOnboarding/hooks/useAllPostOnboardingActionsCompleted.js +16 -0
  126. package/lib/postOnboarding/hooks/useAllPostOnboardingActionsCompleted.js.map +1 -0
  127. package/lib/postOnboarding/hooks/useAllPostOnboardingActionsCompleted.test.d.ts +2 -0
  128. package/lib/postOnboarding/hooks/useAllPostOnboardingActionsCompleted.test.d.ts.map +1 -0
  129. package/lib/postOnboarding/hooks/useAllPostOnboardingActionsCompleted.test.js +75 -0
  130. package/lib/postOnboarding/hooks/useAllPostOnboardingActionsCompleted.test.js.map +1 -0
  131. package/lib/postOnboarding/hooks/usePostOnboardingContext.d.ts +3 -0
  132. package/lib/postOnboarding/hooks/usePostOnboardingContext.d.ts.map +1 -0
  133. package/lib/postOnboarding/hooks/usePostOnboardingContext.js +10 -0
  134. package/lib/postOnboarding/hooks/usePostOnboardingContext.js.map +1 -0
  135. package/lib/postOnboarding/hooks/usePostOnboardingEntryPointVisibleOnWallet.d.ts +8 -0
  136. package/lib/postOnboarding/hooks/usePostOnboardingEntryPointVisibleOnWallet.d.ts.map +1 -0
  137. package/lib/postOnboarding/hooks/usePostOnboardingEntryPointVisibleOnWallet.js +20 -0
  138. package/lib/postOnboarding/hooks/usePostOnboardingEntryPointVisibleOnWallet.js.map +1 -0
  139. package/lib/postOnboarding/hooks/usePostOnboardingEntryPointVisibleOnWallet.test.d.ts +2 -0
  140. package/lib/postOnboarding/hooks/usePostOnboardingEntryPointVisibleOnWallet.test.d.ts.map +1 -0
  141. package/lib/postOnboarding/hooks/usePostOnboardingEntryPointVisibleOnWallet.test.js +64 -0
  142. package/lib/postOnboarding/hooks/usePostOnboardingEntryPointVisibleOnWallet.test.js.map +1 -0
  143. package/lib/postOnboarding/hooks/usePostOnboardingHubState.d.ts +12 -0
  144. package/lib/postOnboarding/hooks/usePostOnboardingHubState.d.ts.map +1 -0
  145. package/lib/postOnboarding/hooks/usePostOnboardingHubState.js +65 -0
  146. package/lib/postOnboarding/hooks/usePostOnboardingHubState.js.map +1 -0
  147. package/lib/postOnboarding/hooks/usePostOnboardingHubState.test.d.ts +2 -0
  148. package/lib/postOnboarding/hooks/usePostOnboardingHubState.test.d.ts.map +1 -0
  149. package/lib/postOnboarding/hooks/usePostOnboardingHubState.test.js +129 -0
  150. package/lib/postOnboarding/hooks/usePostOnboardingHubState.test.js.map +1 -0
  151. package/lib/postOnboarding/hooks/useStartPostOnboardingCallback.d.ts +13 -0
  152. package/lib/postOnboarding/hooks/useStartPostOnboardingCallback.d.ts.map +1 -0
  153. package/lib/postOnboarding/hooks/useStartPostOnboardingCallback.js +34 -0
  154. package/lib/postOnboarding/hooks/useStartPostOnboardingCallback.js.map +1 -0
  155. package/lib/postOnboarding/mock.d.ts +8 -0
  156. package/lib/postOnboarding/mock.d.ts.map +1 -0
  157. package/lib/postOnboarding/mock.js +46 -0
  158. package/lib/postOnboarding/mock.js.map +1 -0
  159. package/lib/postOnboarding/reducer.d.ts +22 -0
  160. package/lib/postOnboarding/reducer.d.ts.map +1 -0
  161. package/lib/postOnboarding/reducer.js +71 -0
  162. package/lib/postOnboarding/reducer.js.map +1 -0
  163. package/lib/postOnboarding/reducer.test.d.ts +2 -0
  164. package/lib/postOnboarding/reducer.test.d.ts.map +1 -0
  165. package/lib/postOnboarding/reducer.test.js +251 -0
  166. package/lib/postOnboarding/reducer.test.js.map +1 -0
  167. package/package.json +8 -4
  168. package/src/bot/index.ts +11 -12
  169. package/src/bot/specs.ts +45 -0
  170. package/src/currencies/__snapshots__/sortByMarketcap.test.ts.snap +1 -35
  171. package/src/currencies/support.ts +2 -1
  172. package/src/derivation.ts +2 -4
  173. package/src/env.ts +1 -1
  174. package/src/exchange/swap/getExchangeRates.ts +7 -3
  175. package/src/exchange/swap/getProviders.test.ts +450 -0
  176. package/src/exchange/swap/getProviders.ts +31 -8
  177. package/src/exchange/swap/hooks/useProviderRates.test.ts +43 -0
  178. package/src/exchange/swap/hooks/useProviderRates.ts +22 -3
  179. package/src/exchange/swap/hooks/useSwapTransaction.ts +3 -1
  180. package/src/exchange/swap/index.test.ts +36 -1
  181. package/src/exchange/swap/index.ts +15 -0
  182. package/src/exchange/swap/mock.ts +2 -2
  183. package/src/exchange/swap/types.ts +11 -0
  184. package/src/exchange/swap/utils/index.test.ts +19 -0
  185. package/src/exchange/swap/utils/index.ts +5 -0
  186. package/src/families/algorand/speculos-deviceActions.ts +4 -35
  187. package/src/families/bitcoin/specs.ts +0 -1
  188. package/src/families/bitcoin/speculos-deviceActions.ts +3 -26
  189. package/src/families/cardano/specs.ts +4 -3
  190. package/src/families/cardano/speculos-deviceActions.ts +3 -14
  191. package/src/families/celo/speculos-deviceActions.ts +6 -14
  192. package/src/families/elrond/speculos-deviceActions.ts +4 -9
  193. package/src/families/ethereum/speculos-deviceActions.ts +16 -46
  194. package/src/families/evm/specs.ts +12 -8
  195. package/src/families/evm/speculos-deviceActions.ts +7 -35
  196. package/src/families/filecoin/speculos-deviceActions.ts +7 -8
  197. package/src/families/polkadot/speculos-deviceActions.ts +5 -16
  198. package/src/families/ripple/speculos-deviceActions.ts +3 -28
  199. package/src/families/solana/speculos-deviceActions.ts +6 -8
  200. package/src/families/stellar/speculos-deviceActions.ts +5 -11
  201. package/src/families/tezos/speculos-deviceActions.ts +9 -16
  202. package/src/families/tron/speculos-deviceActions.ts +4 -12
  203. package/src/featureFlags/defaultFeatures.ts +3 -0
  204. package/src/hw/extractOnboardingState.test.ts +29 -12
  205. package/src/hw/extractOnboardingState.ts +17 -9
  206. package/src/postOnboarding/PostOnboardingProvider.tsx +49 -0
  207. package/src/postOnboarding/actions.ts +40 -0
  208. package/src/postOnboarding/hooks/index.ts +5 -0
  209. package/src/postOnboarding/hooks/useAllPostOnboardingActionsCompleted.test.ts +82 -0
  210. package/src/postOnboarding/hooks/useAllPostOnboardingActionsCompleted.ts +12 -0
  211. package/src/postOnboarding/hooks/usePostOnboardingContext.ts +9 -0
  212. package/src/postOnboarding/hooks/usePostOnboardingEntryPointVisibleOnWallet.test.ts +83 -0
  213. package/src/postOnboarding/hooks/usePostOnboardingEntryPointVisibleOnWallet.ts +22 -0
  214. package/src/postOnboarding/hooks/usePostOnboardingHubState.test.ts +184 -0
  215. package/src/postOnboarding/hooks/usePostOnboardingHubState.ts +56 -0
  216. package/src/postOnboarding/hooks/useStartPostOnboardingCallback.ts +38 -0
  217. package/src/postOnboarding/mock.ts +53 -0
  218. package/src/postOnboarding/reducer.test.ts +247 -0
  219. package/src/postOnboarding/reducer.ts +105 -0
@@ -11,6 +11,7 @@ import {
11
11
  JSONRPCResponseError,
12
12
  NoIPHeaderError,
13
13
  NotImplementedError,
14
+ SwapGenericAPIError,
14
15
  TradeMethodNotSupportedError,
15
16
  UnexpectedError,
16
17
  ValidationError,
@@ -36,6 +37,19 @@ export const isSwapOperationPending: (status: string) => boolean = (status) =>
36
37
 
37
38
  const getSwapAPIBaseURL: () => string = () => getEnv("SWAP_API_BASE");
38
39
 
40
+ const SWAP_API_BASE_PATTERN = /.*\/v(?<version>\d+)\/*$/;
41
+ const getSwapAPIVersion: () => number = () => {
42
+ const version = Number(
43
+ getSwapAPIBaseURL().match(SWAP_API_BASE_PATTERN)?.groups?.version
44
+ );
45
+ if (version == null || isNaN(version)) {
46
+ throw new SwapGenericAPIError(
47
+ "Configured swap API base URL is invalid, should end with /v<number>"
48
+ );
49
+ }
50
+ return version;
51
+ };
52
+
39
53
  const ftx = {
40
54
  nameAndPubkey: Buffer.concat([
41
55
  Buffer.from([3]),
@@ -179,6 +193,7 @@ export const getSwapAPIError = (errorCode: number, errorMessage?: string) => {
179
193
 
180
194
  export {
181
195
  getSwapAPIBaseURL,
196
+ getSwapAPIVersion,
182
197
  getProviderConfig,
183
198
  getProviders,
184
199
  getExchangeRates,
@@ -7,7 +7,7 @@ import {
7
7
  SwapExchangeRateAmountTooHigh,
8
8
  SwapExchangeRateAmountTooLow,
9
9
  } from "../../errors";
10
- import { getSwapAPIBaseURL } from "./";
10
+ import { getSwapAPIVersion } from "./";
11
11
  import type {
12
12
  CheckQuote,
13
13
  Exchange,
@@ -129,7 +129,7 @@ export const mockInitSwap = (
129
129
  export const mockGetProviders: GetProviders = async () => {
130
130
  //Fake delay to show loading UI
131
131
  await new Promise((r) => setTimeout(r, 800));
132
- const usesV3 = getSwapAPIBaseURL().endsWith("v3");
132
+ const usesV3 = getSwapAPIVersion() >= 3;
133
133
 
134
134
  return usesV3
135
135
  ? [
@@ -83,6 +83,17 @@ export type AvailableProviderV3 = {
83
83
  pairs: Array<{ from: string; to: string; tradeMethod: string }>;
84
84
  };
85
85
 
86
+ type TradeMethodGroup = {
87
+ methods: TradeMethod[];
88
+ pairs: {
89
+ [currencyIndex: number]: number[];
90
+ };
91
+ };
92
+ export type ProvidersResponseV4 = {
93
+ currencies: { [currencyIndex: number]: string };
94
+ providers: { [providerName: string]: TradeMethodGroup[] };
95
+ };
96
+
86
97
  type CheckQuoteOkStatus = {
87
98
  codeName: "RATE_VALID";
88
99
  };
@@ -10,6 +10,7 @@ import { genAccount } from "../../../mock/account";
10
10
  import {
11
11
  getAccountTuplesForCurrency,
12
12
  getAvailableAccountsById,
13
+ isRegistrationRequired,
13
14
  getProviderName,
14
15
  KYCStatus,
15
16
  shouldShowKYCBanner,
@@ -303,6 +304,24 @@ describe("swap/utils/shouldShowKYCBanner", () => {
303
304
  });
304
305
  });
305
306
 
307
+ describe("swap/utils/isRegistrationRequired", () => {
308
+ test("should return registration is required for ftx", () => {
309
+ const expectedResult = true;
310
+
311
+ const result = isRegistrationRequired("ftx");
312
+
313
+ expect(result).toBe(expectedResult);
314
+ });
315
+
316
+ test("should return registration is not required for changelly", () => {
317
+ const expectedResult = false;
318
+
319
+ const result = isRegistrationRequired("changelly");
320
+
321
+ expect(result).toBe(expectedResult);
322
+ });
323
+ });
324
+
306
325
  describe("swap/utils/getProviderName", () => {
307
326
  test("should return uppercase provider name for ftx", () => {
308
327
  const expectedResult = "FTX";
@@ -172,6 +172,11 @@ export const shouldShowKYCBanner = ({
172
172
  return kycStatus !== KYC_STATUS.approved;
173
173
  };
174
174
 
175
+ export const isRegistrationRequired = (provider: string): boolean => {
176
+ const { needsBearerToken, needsKYC } = getProviderConfig(provider);
177
+ return needsBearerToken || needsKYC;
178
+ };
179
+
175
180
  export const getProviderName = (provider: string): string => {
176
181
  switch (provider) {
177
182
  case "ftx":
@@ -1,26 +1,10 @@
1
1
  import type { DeviceAction } from "../../bot/types";
2
2
  import type { AlgorandTransaction } from "./types";
3
- import { formatCurrencyUnit, findTokenById } from "../../currencies";
4
- import { deviceActionFlow } from "../../bot/specs";
3
+ import { findTokenById } from "../../currencies";
4
+ import { deviceActionFlow, formatDeviceAmount } from "../../bot/specs";
5
5
  import { extractTokenId, addPrefixToken } from "./tokens";
6
6
  import { displayTokenValue } from "./deviceTransactionConfig";
7
7
 
8
- // Will be useful when unit is gonna be algo
9
- const expectedAmount = ({ account, status }) =>
10
- formatCurrencyUnit(
11
- {
12
- ...account.unit,
13
- code: account.currency.deviceTicker || account.unit.code,
14
- prefixCode: true,
15
- },
16
- status.amount,
17
- {
18
- showCode: true,
19
- disableRounding: true,
20
- joinFragmentsSeparator: " ",
21
- }
22
- );
23
-
24
8
  export const acceptTransaction: DeviceAction<AlgorandTransaction, any> =
25
9
  deviceActionFlow({
26
10
  steps: [
@@ -42,19 +26,7 @@ export const acceptTransaction: DeviceAction<AlgorandTransaction, any> =
42
26
  title: "Fee",
43
27
  button: "Rr",
44
28
  expectedValue: ({ account, status }) =>
45
- formatCurrencyUnit(
46
- {
47
- ...account.unit,
48
- code: account.currency.deviceTicker || account.unit.code,
49
- prefixCode: true,
50
- },
51
- status.estimatedFees,
52
- {
53
- showCode: true,
54
- disableRounding: true,
55
- joinFragmentsSeparator: " ",
56
- }
57
- ),
29
+ formatDeviceAmount(account.currency, status.estimatedFees),
58
30
  },
59
31
  {
60
32
  title: "Asset ID",
@@ -95,10 +67,7 @@ export const acceptTransaction: DeviceAction<AlgorandTransaction, any> =
95
67
  expectedValue: ({ account, status, transaction }) =>
96
68
  transaction.mode === "claimReward"
97
69
  ? "0"
98
- : expectedAmount({
99
- account,
100
- status,
101
- }),
70
+ : formatDeviceAmount(account.currency, status.amount),
102
71
  },
103
72
  {
104
73
  title: "APPROVE",
@@ -310,7 +310,6 @@ const bitcoin: AppSpec<Transaction> = {
310
310
  mutations: bitcoinLikeMutations(),
311
311
  };
312
312
  const bitcoinTestnet: AppSpec<Transaction> = {
313
- multipleRuns: 2,
314
313
  name: "Bitcoin Testnet",
315
314
  currency: getCryptoCurrencyById("bitcoin_testnet"),
316
315
  dependency: "Bitcoin",
@@ -1,7 +1,6 @@
1
1
  import type { DeviceAction } from "../../bot/types";
2
2
  import type { Transaction } from "./types";
3
- import { formatCurrencyUnit } from "../../currencies";
4
- import { deviceActionFlow } from "../../bot/specs";
3
+ import { deviceActionFlow, formatDeviceAmount } from "../../bot/specs";
5
4
  import { perCoinLogic } from "./logic";
6
5
 
7
6
  export const acceptTransaction: DeviceAction<Transaction, any> =
@@ -11,37 +10,15 @@ export const acceptTransaction: DeviceAction<Transaction, any> =
11
10
  title: "Amount",
12
11
  button: "Rr",
13
12
  ignoreAssertionFailure: true,
14
- // https://ledgerhq.atlassian.net/browse/LLC-676
15
13
  expectedValue: ({ account, status }) =>
16
- formatCurrencyUnit(
17
- {
18
- ...account.unit,
19
- code: account.currency.deviceTicker || account.unit.code,
20
- },
21
- status.amount,
22
- {
23
- showCode: true,
24
- disableRounding: true,
25
- }
26
- ).replace(/\s/g, " "),
14
+ formatDeviceAmount(account.currency, status.amount),
27
15
  },
28
16
  {
29
17
  title: "Fees",
30
18
  button: "Rr",
31
19
  ignoreAssertionFailure: true,
32
- // https://ledgerhq.atlassian.net/browse/LLC-676
33
20
  expectedValue: ({ account, status }) =>
34
- formatCurrencyUnit(
35
- {
36
- ...account.unit,
37
- code: account.currency.deviceTicker || account.unit.code,
38
- },
39
- status.estimatedFees,
40
- {
41
- showCode: true,
42
- disableRounding: true,
43
- }
44
- ).replace(/\s/g, " "),
21
+ formatDeviceAmount(account.currency, status.estimatedFees),
45
22
  },
46
23
  {
47
24
  title: "Address",
@@ -12,6 +12,7 @@ import { parseCurrencyUnit } from "../../currencies";
12
12
  import { SubAccount } from "@ledgerhq/types-live";
13
13
  import { acceptTransaction } from "./speculos-deviceActions";
14
14
 
15
+ const maxAccounts = 5;
15
16
  const currency = getCryptoCurrencyById("cardano");
16
17
  const minBalanceRequired = parseCurrencyUnit(currency.units[0], "2.2");
17
18
  const minBalanceRequiredForMaxSend = parseCurrencyUnit(currency.units[0], "1");
@@ -35,7 +36,7 @@ const cardano: AppSpec<Transaction> = {
35
36
  maxRun: 1,
36
37
  transaction: ({ account, siblings, bridge, maxSpendable }) => {
37
38
  invariant(maxSpendable.gt(minBalanceRequired), "balance is too low");
38
- const sibling = pickSiblings(siblings, 3);
39
+ const sibling = pickSiblings(siblings, maxAccounts);
39
40
  const recipient = sibling.freshAddress;
40
41
  const transaction = bridge.createTransaction(account);
41
42
 
@@ -77,7 +78,7 @@ const cardano: AppSpec<Transaction> = {
77
78
  maxSpendable.gt(minBalanceRequiredForMaxSend),
78
79
  "balance is too low"
79
80
  );
80
- const sibling = pickSiblings(siblings, 3);
81
+ const sibling = pickSiblings(siblings, maxAccounts);
81
82
  const recipient = sibling.freshAddress;
82
83
  const transaction = bridge.createTransaction(account);
83
84
 
@@ -117,7 +118,7 @@ const cardano: AppSpec<Transaction> = {
117
118
  maxSpendable.gte(minSpendableRequiredForTokenTx),
118
119
  "balance is too low"
119
120
  );
120
- const sibling = pickSiblings(siblings, 3);
121
+ const sibling = pickSiblings(siblings, maxAccounts);
121
122
  const recipient = sibling.freshAddress;
122
123
  const transaction = bridge.createTransaction(account);
123
124
 
@@ -1,17 +1,6 @@
1
1
  import type { DeviceAction } from "../../bot/types";
2
2
  import type { Transaction } from "./types";
3
- import { formatCurrencyUnit } from "../../currencies";
4
- import { deviceActionFlow } from "../../bot/specs";
5
- import type { Unit } from "@ledgerhq/types-cryptoassets";
6
- import BigNumber from "bignumber.js";
7
-
8
- function expectedValue(unit: Unit, value: BigNumber) {
9
- return formatCurrencyUnit(unit, value, {
10
- showCode: true,
11
- disableRounding: true,
12
- showAllDigits: true,
13
- });
14
- }
3
+ import { deviceActionFlow, formatDeviceAmount } from "../../bot/specs";
15
4
 
16
5
  export const acceptTransaction: DeviceAction<Transaction, any> =
17
6
  deviceActionFlow({
@@ -38,7 +27,7 @@ export const acceptTransaction: DeviceAction<Transaction, any> =
38
27
  button: "LRlr",
39
28
  ignoreAssertionFailure: true,
40
29
  expectedValue: ({ account, status }) =>
41
- expectedValue(account.unit, status.amount),
30
+ formatDeviceAmount(account.currency, status.amount),
42
31
  },
43
32
  {
44
33
  title: "Asset fingerprint",
@@ -60,7 +49,7 @@ export const acceptTransaction: DeviceAction<Transaction, any> =
60
49
  button: "LRlr",
61
50
  ignoreAssertionFailure: true,
62
51
  expectedValue: ({ account, status }) =>
63
- expectedValue(account.unit, status.estimatedFees),
52
+ formatDeviceAmount(account.currency, status.estimatedFees),
64
53
  },
65
54
  {
66
55
  title: "Transaction TTL",
@@ -1,7 +1,7 @@
1
1
  import type { DeviceAction } from "../../bot/types";
2
2
  import type { Transaction } from "./types";
3
- import { deviceActionFlow } from "../../bot/specs";
4
- import { formatCurrencyUnit } from "../../currencies";
3
+ import { deviceActionFlow, formatDeviceAmount } from "../../bot/specs";
4
+
5
5
  const typeWording = {
6
6
  send: "Send",
7
7
  lock: "Lock",
@@ -23,18 +23,10 @@ export const acceptTransaction: DeviceAction<Transaction, any> =
23
23
  {
24
24
  title: "Amount",
25
25
  button: "Rr",
26
- expectedValue: ({ account, status }) => {
27
- const formattedValue =
28
- "CELO " +
29
- formatCurrencyUnit(account.unit, status.amount, {
30
- disableRounding: true,
31
- });
32
- if (!formattedValue.includes(".")) {
33
- // if the value is pure integer, in the app it will automatically add an .0
34
- return formattedValue + ".0";
35
- }
36
- return formattedValue;
37
- },
26
+ expectedValue: ({ account, status }) =>
27
+ formatDeviceAmount(account.currency, status.amount, {
28
+ forceFloating: true,
29
+ }),
38
30
  },
39
31
  {
40
32
  title: "Address",
@@ -1,7 +1,6 @@
1
1
  import type { DeviceAction } from "../../bot/types";
2
2
  import type { Transaction } from "./types";
3
- import { deviceActionFlow } from "../../bot/specs";
4
- import { formatCurrencyUnit } from "../../currencies";
3
+ import { deviceActionFlow, formatDeviceAmount } from "../../bot/specs";
5
4
 
6
5
  export const acceptTransaction: DeviceAction<Transaction, any> =
7
6
  deviceActionFlow({
@@ -15,13 +14,9 @@ export const acceptTransaction: DeviceAction<Transaction, any> =
15
14
  title: "Amount",
16
15
  button: "Rr",
17
16
  expectedValue: ({ account, transaction }) =>
18
- formatCurrencyUnit(account.unit, transaction.amount, {
19
- showCode: true,
20
- disableRounding: true,
21
- joinFragmentsSeparator: " ",
22
- })
23
- .replace(/\s+/g, " ")
24
- .replace("egld", "EGLD"), // FIXME
17
+ formatDeviceAmount(account.currency, transaction.amount, {
18
+ postfixCode: true,
19
+ }),
25
20
  },
26
21
  {
27
22
  title: "Fee",
@@ -1,7 +1,6 @@
1
1
  import type { DeviceAction } from "../../bot/types";
2
2
  import type { Transaction } from "./types";
3
- import { formatCurrencyUnit, findCompoundToken } from "../../currencies";
4
- import { deviceActionFlow } from "../../bot/specs";
3
+ import { deviceActionFlow, formatDeviceAmount } from "../../bot/specs";
5
4
 
6
5
  function subAccount(subAccountId, account) {
7
6
  const sub = (account.subAccounts || []).find((a) => a.id === subAccountId);
@@ -10,28 +9,8 @@ function subAccount(subAccountId, account) {
10
9
  return sub;
11
10
  }
12
11
 
13
- function expectedCompoundToken(t) {
14
- if (!t) {
15
- throw new Error("compound token was expected");
16
- }
17
-
18
- return t;
19
- }
20
-
21
12
  const maxFeesExpectedValue = ({ account, status }) =>
22
- formatCurrencyUnit(
23
- {
24
- ...account.unit,
25
- code: account.currency.deviceTicker || account.unit.code,
26
- prefixCode: true,
27
- },
28
- status.estimatedFees,
29
- {
30
- showCode: true,
31
- disableRounding: true,
32
- joinFragmentsSeparator: " ",
33
- }
34
- ).replace(/\s/g, " ");
13
+ formatDeviceAmount(account.currency, status.estimatedFees);
35
14
 
36
15
  export const acceptTransaction: DeviceAction<Transaction, any> =
37
16
  deviceActionFlow({
@@ -66,16 +45,6 @@ export const acceptTransaction: DeviceAction<Transaction, any> =
66
45
  return "Unlimited " + a.token.ticker;
67
46
  }
68
47
 
69
- const unit = !a
70
- ? {
71
- ...account.unit,
72
- code: account.currency.deviceTicker || account.unit.code,
73
- }
74
- : (transaction.mode === "compound.withdraw" &&
75
- transaction.useAllAmount
76
- ? expectedCompoundToken(findCompoundToken(a.token))
77
- : a.token
78
- ).units[0];
79
48
  const amount =
80
49
  a &&
81
50
  a.compoundBalance &&
@@ -83,19 +52,20 @@ export const acceptTransaction: DeviceAction<Transaction, any> =
83
52
  transaction.useAllAmount
84
53
  ? a.compoundBalance
85
54
  : status.amount;
86
- return formatCurrencyUnit(
87
- {
88
- ...unit,
89
- code: account.currency.deviceTicker || account.unit.code,
90
- prefixCode: true,
91
- },
92
- amount,
93
- {
94
- showCode: true,
95
- disableRounding: true,
96
- joinFragmentsSeparator: " ",
97
- }
98
- ).replace(/\s/g, " ");
55
+
56
+ if (
57
+ a &&
58
+ transaction.mode === "compound.withdraw" &&
59
+ transaction.useAllAmount
60
+ ) {
61
+ return formatDeviceAmount(a.compoundBalance, amount);
62
+ }
63
+
64
+ if (a) {
65
+ return formatDeviceAmount(a.token, amount);
66
+ }
67
+
68
+ return formatDeviceAmount(account.currency, amount);
99
69
  },
100
70
  },
101
71
  {
@@ -3,7 +3,7 @@ import invariant from "invariant";
3
3
  import { DeviceModelId } from "@ledgerhq/devices";
4
4
  import { getCryptoCurrencyById, parseCurrencyUnit } from "../../currencies";
5
5
  import { acceptTransaction } from "./speculos-deviceActions";
6
- import { pickSiblings } from "../../bot/specs";
6
+ import { botTest, pickSiblings } from "../../bot/specs";
7
7
  import type { AppSpec } from "../../bot/types";
8
8
  import type { Transaction } from "./types";
9
9
 
@@ -14,7 +14,7 @@ const transactionCheck =
14
14
  ({ maxSpendable }) => {
15
15
  invariant(
16
16
  maxSpendable.gt(
17
- parseCurrencyUnit(getCryptoCurrencyById(currencyId).units[0], "0.01")
17
+ parseCurrencyUnit(getCryptoCurrencyById(currencyId).units[0], "1")
18
18
  ),
19
19
  `${currencyId} balance is too low`
20
20
  );
@@ -45,13 +45,17 @@ const evmBasicMutations = ({ maxAccount }) => [
45
45
  "operation time to be older than 60s"
46
46
  );
47
47
  const estimatedGas = transaction.gasLimit.times(
48
- transaction.gasPrice || 0
48
+ transaction.gasPrice || transaction.maxFeePerGas || 0
49
49
  );
50
- expect(operation.fee.toNumber()).toBeLessThanOrEqual(
51
- estimatedGas.toNumber()
50
+ botTest("operation fee is not exceeding estimated gas", () =>
51
+ expect(operation.fee.toNumber()).toBeLessThanOrEqual(
52
+ estimatedGas.toNumber()
53
+ )
52
54
  );
53
- expect(account.balance.toString()).toBe(
54
- accountBeforeTransaction.balance.minus(operation.value).toString()
55
+ botTest("account balance moved with operation value", () =>
56
+ expect(account.balance.toString()).toBe(
57
+ accountBeforeTransaction.balance.minus(operation.value).toString()
58
+ )
55
59
  );
56
60
  },
57
61
  },
@@ -118,7 +122,7 @@ const songbird: AppSpec<Transaction> = {
118
122
  };
119
123
 
120
124
  const flare: AppSpec<Transaction> = {
121
- name: "Moonbeam",
125
+ name: "Flare",
122
126
  currency: getCryptoCurrencyById("flare"),
123
127
  appQuery: {
124
128
  model: DeviceModelId.nanoS,
@@ -1,7 +1,6 @@
1
1
  import type { DeviceAction } from "../../bot/types";
2
2
  import type { Transaction } from "./types";
3
- import { formatCurrencyUnit } from "../../currencies";
4
- import { deviceActionFlow } from "../../bot/specs";
3
+ import { deviceActionFlow, formatDeviceAmount } from "../../bot/specs";
5
4
 
6
5
  function subAccount(subAccountId, account) {
7
6
  const sub = (account.subAccounts || []).find((a) => a.id === subAccountId);
@@ -11,19 +10,7 @@ function subAccount(subAccountId, account) {
11
10
  }
12
11
 
13
12
  const maxFeesExpectedValue = ({ account, status }) =>
14
- formatCurrencyUnit(
15
- {
16
- ...account.unit,
17
- code: account.currency.deviceTicker || account.unit.code,
18
- prefixCode: true,
19
- },
20
- status.estimatedFees,
21
- {
22
- showCode: true,
23
- disableRounding: true,
24
- joinFragmentsSeparator: " ",
25
- }
26
- ).replace(/\s/g, " ");
13
+ formatDeviceAmount(account.currency, status.estimatedFees);
27
14
 
28
15
  export const acceptTransaction: DeviceAction<Transaction, any> =
29
16
  deviceActionFlow({
@@ -44,26 +31,11 @@ export const acceptTransaction: DeviceAction<Transaction, any> =
44
31
  ? subAccount(transaction.subAccountId, account)
45
32
  : null;
46
33
 
47
- const unit = !a
48
- ? {
49
- ...account.unit,
50
- code: account.currency.deviceTicker || account.unit.code,
51
- }
52
- : a.token.units[0];
53
- const amount = status.amount;
54
- return formatCurrencyUnit(
55
- {
56
- ...unit,
57
- code: account.currency.deviceTicker || account.unit.code,
58
- prefixCode: true,
59
- },
60
- amount,
61
- {
62
- showCode: true,
63
- disableRounding: true,
64
- joinFragmentsSeparator: " ",
65
- }
66
- ).replace(/\s/g, " ");
34
+ if (a) {
35
+ return formatDeviceAmount(a.token, status.amount);
36
+ }
37
+
38
+ return formatDeviceAmount(account.currency, status.amount);
67
39
  },
68
40
  },
69
41
  {
@@ -1,7 +1,6 @@
1
1
  import type { DeviceAction } from "../../bot/types";
2
2
  import type { Transaction } from "./types";
3
- import { deviceActionFlow } from "../../bot/specs";
4
- import { formatCurrencyUnit } from "../../currencies";
3
+ import { deviceActionFlow, formatDeviceAmount } from "../../bot/specs";
5
4
 
6
5
  export const acceptTransaction: DeviceAction<Transaction, any> =
7
6
  deviceActionFlow({
@@ -25,8 +24,8 @@ export const acceptTransaction: DeviceAction<Transaction, any> =
25
24
  title: "Value",
26
25
  button: "Rr",
27
26
  expectedValue: ({ account, status }) =>
28
- formatCurrencyUnit(account.unit, status.amount, {
29
- disableRounding: true,
27
+ formatDeviceAmount(account.currency, status.amount, {
28
+ hideCode: true,
30
29
  showAllDigits: true,
31
30
  }),
32
31
  },
@@ -39,8 +38,8 @@ export const acceptTransaction: DeviceAction<Transaction, any> =
39
38
  title: "Gas Premium",
40
39
  button: "Rr",
41
40
  expectedValue: ({ account, transaction }) =>
42
- formatCurrencyUnit(account.unit, transaction.gasPremium, {
43
- disableRounding: true,
41
+ formatDeviceAmount(account.currency, transaction.gasPremium, {
42
+ hideCode: true,
44
43
  showAllDigits: true,
45
44
  }),
46
45
  },
@@ -48,8 +47,8 @@ export const acceptTransaction: DeviceAction<Transaction, any> =
48
47
  title: "Gas Fee Cap",
49
48
  button: "Rr",
50
49
  expectedValue: ({ account, transaction }) =>
51
- formatCurrencyUnit(account.unit, transaction.gasFeeCap, {
52
- disableRounding: true,
50
+ formatDeviceAmount(account.currency, transaction.gasFeeCap, {
51
+ hideCode: true,
53
52
  showAllDigits: true,
54
53
  }),
55
54
  },
@@ -1,7 +1,6 @@
1
1
  import type { DeviceAction } from "../../bot/types";
2
2
  import type { PolkadotAccount, Transaction } from "./types";
3
- import { deviceActionFlow } from "../../bot/specs";
4
- import { formatCurrencyUnit } from "../../currencies";
3
+ import { deviceActionFlow, formatDeviceAmount } from "../../bot/specs";
5
4
 
6
5
  export const acceptTransaction: DeviceAction<Transaction, any> =
7
6
  deviceActionFlow({
@@ -22,20 +21,10 @@ export const acceptTransaction: DeviceAction<Transaction, any> =
22
21
  {
23
22
  title: "Amount",
24
23
  button: "Rr",
25
- expectedValue: ({ account, transaction }) => {
26
- const formattedValue =
27
- "DOT " +
28
- formatCurrencyUnit(account.unit, transaction.amount, {
29
- disableRounding: true,
30
- });
31
-
32
- if (!formattedValue.includes(".")) {
33
- // if the value is pure integer, in the app it will automatically add an .0
34
- return formattedValue + ".0";
35
- }
36
-
37
- return formattedValue;
38
- },
24
+ expectedValue: ({ account, transaction }) =>
25
+ formatDeviceAmount(account.currency, transaction.amount, {
26
+ forceFloating: true,
27
+ }),
39
28
  },
40
29
  {
41
30
  title: "Chain",