@ledgerhq/live-common 34.42.1 → 34.43.0-nightly.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 (229) hide show
  1. package/lib/__tests__/migration/account-migration.js +3 -0
  2. package/lib/__tests__/migration/account-migration.js.map +1 -1
  3. package/lib/__tests__/test-helpers/environment.js +3 -0
  4. package/lib/__tests__/test-helpers/environment.js.map +1 -1
  5. package/lib/bridge/crypto-assets/index.d.ts +4 -0
  6. package/lib/bridge/crypto-assets/index.d.ts.map +1 -0
  7. package/lib/bridge/crypto-assets/index.js +52 -0
  8. package/lib/bridge/crypto-assets/index.js.map +1 -0
  9. package/lib/bridge/crypto-assets/index.test.d.ts +2 -0
  10. package/lib/bridge/crypto-assets/index.test.d.ts.map +1 -0
  11. package/lib/bridge/crypto-assets/index.test.js +85 -0
  12. package/lib/bridge/crypto-assets/index.test.js.map +1 -0
  13. package/lib/bridge/generic-alpaca/alpaca/network/network-alpaca.d.ts +3 -1
  14. package/lib/bridge/generic-alpaca/alpaca/network/network-alpaca.d.ts.map +1 -1
  15. package/lib/bridge/generic-alpaca/alpaca/network/network-alpaca.js +6 -0
  16. package/lib/bridge/generic-alpaca/alpaca/network/network-alpaca.js.map +1 -1
  17. package/lib/bridge/impl.d.ts +2 -0
  18. package/lib/bridge/impl.d.ts.map +1 -1
  19. package/lib/bridge/impl.js +8 -1
  20. package/lib/bridge/impl.js.map +1 -1
  21. package/lib/bridge/useBridgeTransaction.test.js +1 -1
  22. package/lib/bridge/useBridgeTransaction.test.js.map +1 -1
  23. package/lib/e2e/families/osmosis.d.ts +3 -0
  24. package/lib/e2e/families/osmosis.d.ts.map +1 -0
  25. package/lib/e2e/families/osmosis.js +19 -0
  26. package/lib/e2e/families/osmosis.js.map +1 -0
  27. package/lib/e2e/index.d.ts +9 -0
  28. package/lib/e2e/index.d.ts.map +1 -1
  29. package/lib/e2e/speculos.d.ts.map +1 -1
  30. package/lib/e2e/speculos.js +50 -17
  31. package/lib/e2e/speculos.js.map +1 -1
  32. package/lib/e2e/speculosCI.d.ts.map +1 -1
  33. package/lib/e2e/speculosCI.js +22 -4
  34. package/lib/e2e/speculosCI.js.map +1 -1
  35. package/lib/env.react.d.ts +1 -1
  36. package/lib/env.react.d.ts.map +1 -1
  37. package/lib/exchange/error.d.ts +2 -1
  38. package/lib/exchange/error.d.ts.map +1 -1
  39. package/lib/exchange/error.js +5 -3
  40. package/lib/exchange/error.js.map +1 -1
  41. package/lib/exchange/swap/completeExchange.js +2 -2
  42. package/lib/exchange/swap/completeExchange.js.map +1 -1
  43. package/lib/families/evm/config.d.ts.map +1 -1
  44. package/lib/families/evm/config.js +51 -0
  45. package/lib/families/evm/config.js.map +1 -1
  46. package/lib/families/evm/walletApiAdapter.js +1 -1
  47. package/lib/families/solana/bridge/mock-data.d.ts.map +1 -1
  48. package/lib/families/solana/bridge/mock-data.js +46 -316
  49. package/lib/families/solana/bridge/mock-data.js.map +1 -1
  50. package/lib/families/solana/bridge/mock.js +2 -2
  51. package/lib/families/solana/bridge/mock.js.map +1 -1
  52. package/lib/featureFlags/defaultFeatures.d.ts +3 -0
  53. package/lib/featureFlags/defaultFeatures.d.ts.map +1 -1
  54. package/lib/featureFlags/defaultFeatures.js +4 -0
  55. package/lib/featureFlags/defaultFeatures.js.map +1 -1
  56. package/lib/featureFlags/useFeature.d.ts +1 -1
  57. package/lib/featureFlags/useFeature.d.ts.map +1 -1
  58. package/lib/modularDrawer/__mocks__/accounts.mock.d.ts +18 -0
  59. package/lib/modularDrawer/__mocks__/accounts.mock.d.ts.map +1 -0
  60. package/lib/modularDrawer/__mocks__/accounts.mock.js +48 -0
  61. package/lib/modularDrawer/__mocks__/accounts.mock.js.map +1 -0
  62. package/lib/modularDrawer/__mocks__/currencies.mock.d.ts +17 -0
  63. package/lib/modularDrawer/__mocks__/currencies.mock.d.ts.map +1 -0
  64. package/lib/modularDrawer/__mocks__/currencies.mock.js +60 -0
  65. package/lib/modularDrawer/__mocks__/currencies.mock.js.map +1 -0
  66. package/lib/modularDrawer/__mocks__/useGroupedCurrenciesByProvider.mock.d.ts +22 -0
  67. package/lib/modularDrawer/__mocks__/useGroupedCurrenciesByProvider.mock.d.ts.map +1 -0
  68. package/lib/modularDrawer/__mocks__/useGroupedCurrenciesByProvider.mock.js +41 -0
  69. package/lib/modularDrawer/__mocks__/useGroupedCurrenciesByProvider.mock.js.map +1 -0
  70. package/lib/modularDrawer/utils/__tests__/haveOneCommonProvider.test.d.ts +2 -0
  71. package/lib/modularDrawer/utils/__tests__/haveOneCommonProvider.test.d.ts.map +1 -0
  72. package/lib/modularDrawer/utils/__tests__/haveOneCommonProvider.test.js +28 -0
  73. package/lib/modularDrawer/utils/__tests__/haveOneCommonProvider.test.js.map +1 -0
  74. package/lib/modularDrawer/utils/haveOneCommonProvider.d.ts +11 -0
  75. package/lib/modularDrawer/utils/haveOneCommonProvider.d.ts.map +1 -0
  76. package/lib/modularDrawer/utils/haveOneCommonProvider.js +29 -0
  77. package/lib/modularDrawer/utils/haveOneCommonProvider.js.map +1 -0
  78. package/lib/modularDrawer/utils/index.d.ts +2 -1
  79. package/lib/modularDrawer/utils/index.d.ts.map +1 -1
  80. package/lib/modularDrawer/utils/index.js +3 -1
  81. package/lib/modularDrawer/utils/index.js.map +1 -1
  82. package/lib/utils/__tests__/composeHooks.test.d.ts +2 -0
  83. package/lib/utils/__tests__/composeHooks.test.d.ts.map +1 -0
  84. package/lib/utils/__tests__/composeHooks.test.js +35 -0
  85. package/lib/utils/__tests__/composeHooks.test.js.map +1 -0
  86. package/lib/utils/__tests__/getAccountTuplesForCurrency.test.d.ts +2 -0
  87. package/lib/utils/__tests__/getAccountTuplesForCurrency.test.d.ts.map +1 -0
  88. package/lib/utils/__tests__/getAccountTuplesForCurrency.test.js +104 -0
  89. package/lib/utils/__tests__/getAccountTuplesForCurrency.test.js.map +1 -0
  90. package/lib/utils/composeHooks.d.ts +11 -0
  91. package/lib/utils/composeHooks.d.ts.map +1 -0
  92. package/lib/utils/composeHooks.js +25 -0
  93. package/lib/utils/composeHooks.js.map +1 -0
  94. package/lib/utils/getAccountTuplesForCurrency.d.ts +8 -0
  95. package/lib/utils/getAccountTuplesForCurrency.d.ts.map +1 -0
  96. package/lib/utils/getAccountTuplesForCurrency.js +19 -0
  97. package/lib/utils/getAccountTuplesForCurrency.js.map +1 -0
  98. package/lib/wallet-api/Exchange/server.d.ts.map +1 -1
  99. package/lib/wallet-api/Exchange/server.js +6 -6
  100. package/lib/wallet-api/Exchange/server.js.map +1 -1
  101. package/lib-es/__tests__/migration/account-migration.js +3 -0
  102. package/lib-es/__tests__/migration/account-migration.js.map +1 -1
  103. package/lib-es/__tests__/test-helpers/environment.js +3 -0
  104. package/lib-es/__tests__/test-helpers/environment.js.map +1 -1
  105. package/lib-es/bridge/crypto-assets/index.d.ts +4 -0
  106. package/lib-es/bridge/crypto-assets/index.d.ts.map +1 -0
  107. package/lib-es/bridge/crypto-assets/index.js +24 -0
  108. package/lib-es/bridge/crypto-assets/index.js.map +1 -0
  109. package/lib-es/bridge/crypto-assets/index.test.d.ts +2 -0
  110. package/lib-es/bridge/crypto-assets/index.test.d.ts.map +1 -0
  111. package/lib-es/bridge/crypto-assets/index.test.js +60 -0
  112. package/lib-es/bridge/crypto-assets/index.test.js.map +1 -0
  113. package/lib-es/bridge/generic-alpaca/alpaca/network/network-alpaca.d.ts +3 -1
  114. package/lib-es/bridge/generic-alpaca/alpaca/network/network-alpaca.d.ts.map +1 -1
  115. package/lib-es/bridge/generic-alpaca/alpaca/network/network-alpaca.js +6 -0
  116. package/lib-es/bridge/generic-alpaca/alpaca/network/network-alpaca.js.map +1 -1
  117. package/lib-es/bridge/impl.d.ts +2 -0
  118. package/lib-es/bridge/impl.d.ts.map +1 -1
  119. package/lib-es/bridge/impl.js +6 -0
  120. package/lib-es/bridge/impl.js.map +1 -1
  121. package/lib-es/bridge/useBridgeTransaction.test.js +1 -1
  122. package/lib-es/bridge/useBridgeTransaction.test.js.map +1 -1
  123. package/lib-es/e2e/families/osmosis.d.ts +3 -0
  124. package/lib-es/e2e/families/osmosis.d.ts.map +1 -0
  125. package/lib-es/e2e/families/osmosis.js +12 -0
  126. package/lib-es/e2e/families/osmosis.js.map +1 -0
  127. package/lib-es/e2e/index.d.ts +9 -0
  128. package/lib-es/e2e/index.d.ts.map +1 -1
  129. package/lib-es/e2e/speculos.d.ts.map +1 -1
  130. package/lib-es/e2e/speculos.js +50 -17
  131. package/lib-es/e2e/speculos.js.map +1 -1
  132. package/lib-es/e2e/speculosCI.d.ts.map +1 -1
  133. package/lib-es/e2e/speculosCI.js +22 -4
  134. package/lib-es/e2e/speculosCI.js.map +1 -1
  135. package/lib-es/env.react.d.ts +1 -1
  136. package/lib-es/env.react.d.ts.map +1 -1
  137. package/lib-es/exchange/error.d.ts +2 -1
  138. package/lib-es/exchange/error.d.ts.map +1 -1
  139. package/lib-es/exchange/error.js +5 -3
  140. package/lib-es/exchange/error.js.map +1 -1
  141. package/lib-es/exchange/swap/completeExchange.js +2 -2
  142. package/lib-es/exchange/swap/completeExchange.js.map +1 -1
  143. package/lib-es/families/evm/config.d.ts.map +1 -1
  144. package/lib-es/families/evm/config.js +51 -0
  145. package/lib-es/families/evm/config.js.map +1 -1
  146. package/lib-es/families/evm/walletApiAdapter.js +1 -1
  147. package/lib-es/families/solana/bridge/mock-data.d.ts.map +1 -1
  148. package/lib-es/families/solana/bridge/mock-data.js +46 -316
  149. package/lib-es/families/solana/bridge/mock-data.js.map +1 -1
  150. package/lib-es/families/solana/bridge/mock.js +3 -3
  151. package/lib-es/families/solana/bridge/mock.js.map +1 -1
  152. package/lib-es/featureFlags/defaultFeatures.d.ts +3 -0
  153. package/lib-es/featureFlags/defaultFeatures.d.ts.map +1 -1
  154. package/lib-es/featureFlags/defaultFeatures.js +4 -0
  155. package/lib-es/featureFlags/defaultFeatures.js.map +1 -1
  156. package/lib-es/featureFlags/useFeature.d.ts +1 -1
  157. package/lib-es/featureFlags/useFeature.d.ts.map +1 -1
  158. package/lib-es/modularDrawer/__mocks__/accounts.mock.d.ts +18 -0
  159. package/lib-es/modularDrawer/__mocks__/accounts.mock.d.ts.map +1 -0
  160. package/lib-es/modularDrawer/__mocks__/accounts.mock.js +42 -0
  161. package/lib-es/modularDrawer/__mocks__/accounts.mock.js.map +1 -0
  162. package/lib-es/modularDrawer/__mocks__/currencies.mock.d.ts +17 -0
  163. package/lib-es/modularDrawer/__mocks__/currencies.mock.d.ts.map +1 -0
  164. package/lib-es/modularDrawer/__mocks__/currencies.mock.js +55 -0
  165. package/lib-es/modularDrawer/__mocks__/currencies.mock.js.map +1 -0
  166. package/lib-es/modularDrawer/__mocks__/useGroupedCurrenciesByProvider.mock.d.ts +22 -0
  167. package/lib-es/modularDrawer/__mocks__/useGroupedCurrenciesByProvider.mock.d.ts.map +1 -0
  168. package/lib-es/modularDrawer/__mocks__/useGroupedCurrenciesByProvider.mock.js +38 -0
  169. package/lib-es/modularDrawer/__mocks__/useGroupedCurrenciesByProvider.mock.js.map +1 -0
  170. package/lib-es/modularDrawer/utils/__tests__/haveOneCommonProvider.test.d.ts +2 -0
  171. package/lib-es/modularDrawer/utils/__tests__/haveOneCommonProvider.test.d.ts.map +1 -0
  172. package/lib-es/modularDrawer/utils/__tests__/haveOneCommonProvider.test.js +26 -0
  173. package/lib-es/modularDrawer/utils/__tests__/haveOneCommonProvider.test.js.map +1 -0
  174. package/lib-es/modularDrawer/utils/haveOneCommonProvider.d.ts +11 -0
  175. package/lib-es/modularDrawer/utils/haveOneCommonProvider.d.ts.map +1 -0
  176. package/lib-es/modularDrawer/utils/haveOneCommonProvider.js +25 -0
  177. package/lib-es/modularDrawer/utils/haveOneCommonProvider.js.map +1 -0
  178. package/lib-es/modularDrawer/utils/index.d.ts +2 -1
  179. package/lib-es/modularDrawer/utils/index.d.ts.map +1 -1
  180. package/lib-es/modularDrawer/utils/index.js +2 -1
  181. package/lib-es/modularDrawer/utils/index.js.map +1 -1
  182. package/lib-es/utils/__tests__/composeHooks.test.d.ts +2 -0
  183. package/lib-es/utils/__tests__/composeHooks.test.d.ts.map +1 -0
  184. package/lib-es/utils/__tests__/composeHooks.test.js +33 -0
  185. package/lib-es/utils/__tests__/composeHooks.test.js.map +1 -0
  186. package/lib-es/utils/__tests__/getAccountTuplesForCurrency.test.d.ts +2 -0
  187. package/lib-es/utils/__tests__/getAccountTuplesForCurrency.test.d.ts.map +1 -0
  188. package/lib-es/utils/__tests__/getAccountTuplesForCurrency.test.js +102 -0
  189. package/lib-es/utils/__tests__/getAccountTuplesForCurrency.test.js.map +1 -0
  190. package/lib-es/utils/composeHooks.d.ts +11 -0
  191. package/lib-es/utils/composeHooks.d.ts.map +1 -0
  192. package/lib-es/utils/composeHooks.js +21 -0
  193. package/lib-es/utils/composeHooks.js.map +1 -0
  194. package/lib-es/utils/getAccountTuplesForCurrency.d.ts +8 -0
  195. package/lib-es/utils/getAccountTuplesForCurrency.d.ts.map +1 -0
  196. package/lib-es/utils/getAccountTuplesForCurrency.js +15 -0
  197. package/lib-es/utils/getAccountTuplesForCurrency.js.map +1 -0
  198. package/lib-es/wallet-api/Exchange/server.d.ts.map +1 -1
  199. package/lib-es/wallet-api/Exchange/server.js +6 -6
  200. package/lib-es/wallet-api/Exchange/server.js.map +1 -1
  201. package/package.json +50 -50
  202. package/src/__tests__/migration/account-migration.ts +3 -0
  203. package/src/__tests__/test-helpers/environment.ts +3 -0
  204. package/src/bridge/crypto-assets/index.test.ts +71 -0
  205. package/src/bridge/crypto-assets/index.ts +30 -0
  206. package/src/bridge/generic-alpaca/alpaca/network/network-alpaca.ts +8 -1
  207. package/src/bridge/impl.ts +8 -0
  208. package/src/bridge/useBridgeTransaction.test.ts +1 -1
  209. package/src/e2e/families/osmosis.ts +13 -0
  210. package/src/e2e/speculos.ts +82 -23
  211. package/src/e2e/speculosCI.ts +32 -10
  212. package/src/exchange/error.ts +5 -3
  213. package/src/exchange/swap/completeExchange.ts +2 -2
  214. package/src/families/evm/config.ts +51 -0
  215. package/src/families/evm/walletApiAdapter.ts +1 -1
  216. package/src/families/solana/bridge/mock-data.ts +52 -316
  217. package/src/families/solana/bridge/mock.ts +3 -3
  218. package/src/featureFlags/defaultFeatures.ts +4 -0
  219. package/src/modularDrawer/__mocks__/accounts.mock.ts +43 -0
  220. package/src/modularDrawer/__mocks__/currencies.mock.ts +62 -0
  221. package/src/modularDrawer/__mocks__/useGroupedCurrenciesByProvider.mock.ts +49 -0
  222. package/src/modularDrawer/utils/__tests__/haveOneCommonProvider.test.ts +34 -0
  223. package/src/modularDrawer/utils/haveOneCommonProvider.ts +31 -0
  224. package/src/modularDrawer/utils/index.ts +2 -1
  225. package/src/utils/__tests__/composeHooks.test.ts +46 -0
  226. package/src/utils/__tests__/getAccountTuplesForCurrency.test.ts +138 -0
  227. package/src/utils/composeHooks.ts +26 -0
  228. package/src/utils/getAccountTuplesForCurrency.ts +34 -0
  229. package/src/wallet-api/Exchange/server.ts +7 -6
@@ -20,6 +20,9 @@ import {
20
20
  import { getAlpacaAccountBridge } from "./generic-alpaca/accountBridge";
21
21
  import { getAlpacaCurrencyBridge } from "./generic-alpaca/currencyBridge";
22
22
  import { AddressesSanctionedError } from "@ledgerhq/coin-framework/sanction/errors";
23
+ import { CryptoAssetsStore } from "@ledgerhq/coin-framework/crypto-assets/type";
24
+ import { setCryptoAssetsStore as setCryptoAssetsStoreForCoinFramework } from "@ledgerhq/coin-framework/crypto-assets/index";
25
+ import { getCryptoAssetsStore, setCryptoAssetsStore } from "./crypto-assets";
23
26
 
24
27
  const alpacaized = {
25
28
  xrp: true,
@@ -100,6 +103,11 @@ export function getAccountBridgeByFamily(family: string, accountId?: string): Ac
100
103
  return wrapAccountBridge(jsBridge.accountBridge);
101
104
  }
102
105
 
106
+ export function setup(store: CryptoAssetsStore) {
107
+ setCryptoAssetsStore(store);
108
+ setCryptoAssetsStoreForCoinFramework(getCryptoAssetsStore());
109
+ }
110
+
103
111
  function wrapAccountBridge<T extends TransactionCommon>(
104
112
  bridge: AccountBridge<T>,
105
113
  ): AccountBridge<T> {
@@ -11,7 +11,7 @@ import useBridgeTransaction, {
11
11
  getGlobalOnBridgeError,
12
12
  } from "./useBridgeTransaction";
13
13
  import { setSupportedCurrencies } from "../currencies";
14
- import { LiveConfig } from "@ledgerhq/live-config/lib/LiveConfig";
14
+ import { LiveConfig } from "@ledgerhq/live-config/LiveConfig";
15
15
 
16
16
  const BTC = getCryptoCurrencyById("bitcoin");
17
17
 
@@ -0,0 +1,13 @@
1
+ import { Delegate } from "../models/Delegate";
2
+ import { containsSubstringInEvent, pressBoth, pressUntilTextFound, waitFor } from "../speculos";
3
+ import { DeviceLabels } from "../enum/DeviceLabels";
4
+ import expect from "expect";
5
+
6
+ export async function delegateOsmosis(delegatingAccount: Delegate) {
7
+ await waitFor(DeviceLabels.PLEASE_REVIEW);
8
+ const events = await pressUntilTextFound(DeviceLabels.CAPS_APPROVE);
9
+ const amountInUosmo = (Number(delegatingAccount.amount) * 1_000_000).toString();
10
+ const isAmountCorrect = containsSubstringInEvent(amountInUosmo, events);
11
+ expect(isAmountCorrect).toBeTruthy();
12
+ await pressBoth();
13
+ }
@@ -11,7 +11,7 @@ import { createSpeculosDeviceCI, releaseSpeculosDeviceCI } from "./speculosCI";
11
11
  import type { AppCandidate } from "@ledgerhq/coin-framework/bot/types";
12
12
  import { DeviceModelId } from "@ledgerhq/devices";
13
13
  import { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
14
- import axios from "axios";
14
+ import axios, { AxiosError, AxiosResponse } from "axios";
15
15
  import { getEnv } from "@ledgerhq/live-env";
16
16
  import { getCryptoCurrencyById } from "../currencies";
17
17
  import { DeviceLabels } from "../e2e/enum/DeviceLabels";
@@ -38,6 +38,7 @@ import { delegateMultiversX } from "./families/multiversX";
38
38
  import { NFTTransaction, Transaction } from "./models/Transaction";
39
39
  import { Delegate } from "./models/Delegate";
40
40
  import { Swap } from "./models/Swap";
41
+ import { delegateOsmosis } from "./families/osmosis";
41
42
 
42
43
  const isSpeculosRemote = process.env.REMOTE_SPECULOS === "true";
43
44
 
@@ -414,13 +415,59 @@ interface ResponseData {
414
415
  events: Event[];
415
416
  }
416
417
 
417
- export async function waitFor(text: string, maxAttempts = 10): Promise<string[]> {
418
+ function getSpeculosAddress(): string {
419
+ const speculosAddress = process.env.SPECULOS_ADDRESS;
420
+ return speculosAddress || "http://127.0.0.1";
421
+ }
422
+
423
+ async function retryAxiosRequest<T>(
424
+ requestFn: () => Promise<AxiosResponse<T>>,
425
+ maxRetries: number = 5,
426
+ baseDelay: number = 1000,
427
+ retryableStatusCodes: number[] = [500, 502, 503, 504],
428
+ ): Promise<AxiosResponse<T>> {
429
+ let lastError: AxiosError | Error;
430
+
431
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
432
+ try {
433
+ return await requestFn();
434
+ } catch (error) {
435
+ lastError = error as AxiosError | Error;
436
+
437
+ const isRetryable =
438
+ axios.isAxiosError(error) &&
439
+ error.response &&
440
+ retryableStatusCodes.includes(error.response.status);
441
+
442
+ const isNetworkError = axios.isAxiosError(error) && !error.response;
443
+
444
+ if ((isRetryable || isNetworkError) && attempt < maxRetries) {
445
+ const delay = baseDelay * (attempt + 1);
446
+ console.warn(
447
+ `Axios request failed (attempt ${attempt + 1}/${maxRetries + 1}), retrying in ${delay}ms...`,
448
+ {
449
+ status: axios.isAxiosError(error) ? error.response?.status : "network error",
450
+ message: error.message,
451
+ },
452
+ );
453
+ await new Promise(resolve => setTimeout(resolve, delay));
454
+ continue;
455
+ }
456
+
457
+ throw lastError;
458
+ }
459
+ }
460
+
461
+ throw lastError!;
462
+ }
463
+
464
+ export async function waitFor(text: string, maxAttempts = 15): Promise<string[]> {
418
465
  const port = getEnv("SPECULOS_API_PORT");
419
- const address = process.env.SPECULOS_ADDRESS || "http://127.0.0.1";
466
+ const address = getSpeculosAddress();
420
467
  const url = `${address}:${port}/events?stream=false&currentscreenonly=true`;
421
468
 
422
469
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
423
- const { data } = await axios.get<ResponseData>(url);
470
+ const { data } = await retryAxiosRequest(() => axios.get<ResponseData>(url));
424
471
  const texts = data.events.map(event => event.text);
425
472
 
426
473
  if (texts?.some(t => t?.toLowerCase().includes(text.toLowerCase()))) {
@@ -435,10 +482,12 @@ export async function waitFor(text: string, maxAttempts = 10): Promise<string[]>
435
482
 
436
483
  export async function pressBoth() {
437
484
  const speculosApiPort = getEnv("SPECULOS_API_PORT");
438
- const speculosAddress = process.env.SPECULOS_ADDRESS || "http://127.0.0.1";
439
- await axios.post(`${speculosAddress}:${speculosApiPort}/button/both`, {
440
- action: "press-and-release",
441
- });
485
+ const speculosAddress = getSpeculosAddress();
486
+ await retryAxiosRequest(() =>
487
+ axios.post(`${speculosAddress}:${speculosApiPort}/button/both`, {
488
+ action: "press-and-release",
489
+ }),
490
+ );
442
491
  }
443
492
 
444
493
  export async function pressUntilTextFound(
@@ -464,27 +513,33 @@ export async function pressUntilTextFound(
464
513
  }
465
514
 
466
515
  async function fetchCurrentScreenTexts(speculosApiPort: number): Promise<string> {
467
- const speculosAddress = process.env.SPECULOS_ADDRESS || "http://127.0.0.1";
468
- const response = await axios.get<ResponseData>(
469
- `${speculosAddress}:${speculosApiPort}/events?stream=false&currentscreenonly=true`,
516
+ const speculosAddress = getSpeculosAddress();
517
+ const response = await retryAxiosRequest(() =>
518
+ axios.get<ResponseData>(
519
+ `${speculosAddress}:${speculosApiPort}/events?stream=false&currentscreenonly=true`,
520
+ ),
470
521
  );
471
522
  return response.data.events.map(event => event.text).join("");
472
523
  }
473
524
 
474
525
  async function fetchAllEvents(speculosApiPort: number): Promise<string[]> {
475
- const speculosAddress = process.env.SPECULOS_ADDRESS || "http://127.0.0.1";
476
- const response = await axios.get<ResponseData>(
477
- `${speculosAddress}:${speculosApiPort}/events?stream=false&currentscreenonly=false`,
526
+ const speculosAddress = getSpeculosAddress();
527
+ const response = await retryAxiosRequest(() =>
528
+ axios.get<ResponseData>(
529
+ `${speculosAddress}:${speculosApiPort}/events?stream=false&currentscreenonly=false`,
530
+ ),
478
531
  );
479
532
  return response.data.events.map(event => event.text);
480
533
  }
481
534
 
482
535
  export async function pressRightButton(): Promise<void> {
483
536
  const speculosApiPort = getEnv("SPECULOS_API_PORT");
484
- const speculosAddress = process.env.SPECULOS_ADDRESS || "http://127.0.0.1";
485
- await axios.post(`${speculosAddress}:${speculosApiPort}/button/right`, {
486
- action: "press-and-release",
487
- });
537
+ const speculosAddress = getSpeculosAddress();
538
+ await retryAxiosRequest(() =>
539
+ axios.post(`${speculosAddress}:${speculosApiPort}/button/right`, {
540
+ action: "press-and-release",
541
+ }),
542
+ );
488
543
  }
489
544
 
490
545
  export function containsSubstringInEvent(targetString: string, events: string[]): boolean {
@@ -502,12 +557,14 @@ export function containsSubstringInEvent(targetString: string, events: string[])
502
557
  }
503
558
 
504
559
  export async function takeScreenshot(port?: number): Promise<Buffer | undefined> {
505
- const speculosAddress = process.env.SPECULOS_ADDRESS || "http://127.0.0.1";
560
+ const speculosAddress = getSpeculosAddress();
506
561
  const speculosApiPort = port ?? getEnv("SPECULOS_API_PORT");
507
562
  try {
508
- const response = await axios.get(`${speculosAddress}:${speculosApiPort}/screenshot`, {
509
- responseType: "arraybuffer",
510
- });
563
+ const response = await retryAxiosRequest(() =>
564
+ axios.get(`${speculosAddress}:${speculosApiPort}/screenshot`, {
565
+ responseType: "arraybuffer",
566
+ }),
567
+ );
511
568
  return response.data;
512
569
  } catch (error) {
513
570
  console.error("Error downloading speculos screenshot:", error);
@@ -656,9 +713,11 @@ export async function signDelegationTransaction(delegatingAccount: Delegate) {
656
713
  break;
657
714
  case Account.ATOM_1.currency.name:
658
715
  case Account.INJ_1.currency.name:
659
- case Account.OSMO_1.currency.name:
660
716
  await delegateCosmos(delegatingAccount);
661
717
  break;
718
+ case Account.OSMO_1.currency.name:
719
+ await delegateOsmosis(delegatingAccount);
720
+ break;
662
721
  case Account.MULTIVERS_X_1.currency.name:
663
722
  await delegateMultiversX();
664
723
  break;
@@ -61,22 +61,44 @@ async function githubApiRequest<T = unknown>({
61
61
  function waitForSpeculosReady(url: string, { interval = 2000, timeout = 300_000 } = {}) {
62
62
  return new Promise((resolve, reject) => {
63
63
  const startTime = Date.now();
64
+ let currentRequest: ReturnType<typeof https.get> | null = null;
65
+
66
+ function cleanup() {
67
+ if (currentRequest) {
68
+ currentRequest.destroy();
69
+ currentRequest = null;
70
+ }
71
+ }
64
72
 
65
73
  function check() {
66
- https
67
- .get(url, res => {
68
- if (res.statusCode && res.statusCode >= 200 && res.statusCode < 400) {
69
- process.env.SPECULOS_ADDRESS = url;
70
- resolve(true);
71
- } else {
72
- retry();
73
- }
74
- })
75
- .on("error", retry);
74
+ cleanup();
75
+
76
+ currentRequest = https.get(url, { timeout: 10000 }, res => {
77
+ if (res.statusCode && res.statusCode >= 200 && res.statusCode < 400) {
78
+ process.env.SPECULOS_ADDRESS = url;
79
+ cleanup();
80
+ console.warn(`Speculos is ready at ${url}`);
81
+ resolve(true);
82
+ } else {
83
+ console.warn(`Speculos not ready yet, status: ${res.statusCode}`);
84
+ retry();
85
+ }
86
+ });
87
+
88
+ currentRequest.on("error", error => {
89
+ console.error(`Request error: ${error.message}`);
90
+ retry();
91
+ });
92
+
93
+ currentRequest.on("timeout", () => {
94
+ console.error("Request timeout");
95
+ retry();
96
+ });
76
97
  }
77
98
 
78
99
  function retry() {
79
100
  if (Date.now() - startTime >= timeout) {
101
+ cleanup();
80
102
  reject(new Error(`Timeout: ${url} did not become available within ${timeout}ms`));
81
103
  } else {
82
104
  setTimeout(check, interval);
@@ -13,10 +13,12 @@ export type CompleteExchangeStep =
13
13
 
14
14
  export class CompleteExchangeError extends Error {
15
15
  step: CompleteExchangeStep;
16
+ title?: string;
16
17
 
17
- constructor(step: CompleteExchangeStep, message?: string) {
18
+ constructor(step: CompleteExchangeStep, title?: string, message?: string) {
18
19
  super(message);
19
20
  this.name = "CompleteExchangeError";
21
+ this.title = title;
20
22
  this.step = step;
21
23
  }
22
24
  }
@@ -26,8 +28,8 @@ export function convertTransportError(
26
28
  err: unknown,
27
29
  ): CompleteExchangeError | unknown {
28
30
  if (err instanceof TransportStatusError) {
29
- const errorMessage = getExchangeErrorMessage(err.statusCode, step);
30
- return new CompleteExchangeError(step, errorMessage);
31
+ const { errorName, errorMessage } = getExchangeErrorMessage(err.statusCode, step);
32
+ return new CompleteExchangeError(step, errorName, errorMessage);
31
33
  }
32
34
  return err;
33
35
  }
@@ -175,7 +175,7 @@ const completeExchange = (
175
175
  } catch (e) {
176
176
  if (e instanceof TransportStatusError && e.statusCode === 0x6a83) {
177
177
  throw new WrongDeviceForAccountPayout(
178
- getExchangeErrorMessage(e.statusCode, currentStep),
178
+ getExchangeErrorMessage(e.statusCode, currentStep).errorMessage,
179
179
  {
180
180
  accountName: getDefaultAccountName(payoutAccount),
181
181
  },
@@ -217,7 +217,7 @@ const completeExchange = (
217
217
  if (e instanceof TransportStatusError && e.statusCode === 0x6a83) {
218
218
  log(COMPLETE_EXCHANGE_LOG, "transport error");
219
219
  throw new WrongDeviceForAccountRefund(
220
- getExchangeErrorMessage(e.statusCode, currentStep),
220
+ getExchangeErrorMessage(e.statusCode, currentStep).errorMessage,
221
221
  {
222
222
  accountName: getDefaultAccountName(refundAccount),
223
223
  },
@@ -612,6 +612,57 @@ const evmConfig: CurrencyLiveConfigDefinition = {
612
612
  showNfts: false,
613
613
  },
614
614
  },
615
+ config_currency_sei_network_evm: {
616
+ type: "object",
617
+ default: {
618
+ status: {
619
+ type: "active",
620
+ },
621
+ node: {
622
+ type: "external",
623
+ uri: "https://sei-evm-rpc.publicnode.com",
624
+ },
625
+ explorer: {
626
+ type: "etherscan",
627
+ uri: "https://proxyetherscan.api.live.ledger.com/v2/api/1329",
628
+ },
629
+ showNfts: false,
630
+ },
631
+ },
632
+ config_currency_berachain: {
633
+ type: "object",
634
+ default: {
635
+ status: {
636
+ type: "active",
637
+ },
638
+ node: {
639
+ type: "external",
640
+ uri: "https://rpc.berachain.com",
641
+ },
642
+ explorer: {
643
+ type: "etherscan",
644
+ uri: "https://proxyetherscan.api.live.ledger.com/v2/api/80094",
645
+ },
646
+ showNfts: false,
647
+ },
648
+ },
649
+ config_currency_hyperevm: {
650
+ type: "object",
651
+ default: {
652
+ status: {
653
+ type: "active",
654
+ },
655
+ node: {
656
+ type: "external",
657
+ uri: "https://rpc.hypurrscan.io",
658
+ },
659
+ explorer: {
660
+ type: "etherscan",
661
+ uri: "https://proxyetherscan.api.live.ledger.com/v2/api/999",
662
+ },
663
+ showNfts: false,
664
+ },
665
+ },
615
666
  config_currency_polygon_zk_evm: {
616
667
  type: "object",
617
668
  default: {
@@ -48,7 +48,7 @@ const convertToLiveTransaction: ConvertToLiveTransaction<
48
48
 
49
49
  /**
50
50
  * We explicitly set unrelated type specific fields to undefined to avoid transaction
51
- * type assertion errors during the `prepareTransaction` logic (libs/coin-evm/src/prepareTransaction.ts)
51
+ * type assertion errors during the `prepareTransaction` logic (libs/coin-modules/coin-evm/src/bridge/prepareTransaction.ts)
52
52
  * when performing an `updateTransaction` with a newly created tx
53
53
  * Which is what happen in this case (in apps/ledger-live-desktop/src/renderer/modals/SignTransaction/Body.tsx):
54
54
  // `createTransaction` will create a type 2 tx by default with `maxFeePerGas` and `maxPriorityFeePerGas` set to 0