@ledgerhq/live-common 34.44.0-nightly.2 → 34.44.0-nightly.4

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 (120) hide show
  1. package/lib/bridge/generic-alpaca/alpaca/network/network-alpaca.d.ts +3 -1
  2. package/lib/bridge/generic-alpaca/alpaca/network/network-alpaca.d.ts.map +1 -1
  3. package/lib/bridge/generic-alpaca/alpaca/network/network-alpaca.js +6 -0
  4. package/lib/bridge/generic-alpaca/alpaca/network/network-alpaca.js.map +1 -1
  5. package/lib/device/use-cases/listAppsUseCase.test.js +2 -2
  6. package/lib/device/use-cases/listAppsUseCase.test.js.map +1 -1
  7. package/lib/e2e/enum/DeviceLabels.d.ts +5 -1
  8. package/lib/e2e/enum/DeviceLabels.d.ts.map +1 -1
  9. package/lib/e2e/enum/DeviceLabels.js +4 -0
  10. package/lib/e2e/enum/DeviceLabels.js.map +1 -1
  11. package/lib/e2e/families/evm.js +1 -1
  12. package/lib/e2e/families/evm.js.map +1 -1
  13. package/lib/e2e/index.d.ts +2 -0
  14. package/lib/e2e/index.d.ts.map +1 -1
  15. package/lib/e2e/speculos.d.ts.map +1 -1
  16. package/lib/e2e/speculos.js +16 -24
  17. package/lib/e2e/speculos.js.map +1 -1
  18. package/lib/exchange/swap/hooks/usePickDefaultAccount.test.js +22 -10
  19. package/lib/exchange/swap/hooks/usePickDefaultAccount.test.js.map +1 -1
  20. package/lib/exchange/swap/hooks/wrapper.d.ts +3 -0
  21. package/lib/exchange/swap/hooks/wrapper.d.ts.map +1 -0
  22. package/lib/exchange/swap/hooks/wrapper.js +40 -0
  23. package/lib/exchange/swap/hooks/wrapper.js.map +1 -0
  24. package/lib/exchange/swap/postSwapState.d.ts.map +1 -1
  25. package/lib/exchange/swap/postSwapState.js +63 -4
  26. package/lib/exchange/swap/postSwapState.js.map +1 -1
  27. package/lib/exchange/swap/setBroadcastTransaction.d.ts +4 -1
  28. package/lib/exchange/swap/setBroadcastTransaction.d.ts.map +1 -1
  29. package/lib/exchange/swap/setBroadcastTransaction.js +7 -1
  30. package/lib/exchange/swap/setBroadcastTransaction.js.map +1 -1
  31. package/lib/exchange/swap/types.d.ts +7 -0
  32. package/lib/exchange/swap/types.d.ts.map +1 -1
  33. package/lib/featureFlags/defaultFeatures.d.ts.map +1 -1
  34. package/lib/featureFlags/defaultFeatures.js +1 -0
  35. package/lib/featureFlags/defaultFeatures.js.map +1 -1
  36. package/lib/featureFlags/useFeature.d.ts +1 -1
  37. package/lib/featureFlags/useFeature.d.ts.map +1 -1
  38. package/lib/hw/customLockScreenLoad.d.ts +1 -9
  39. package/lib/hw/customLockScreenLoad.d.ts.map +1 -1
  40. package/lib/hw/customLockScreenLoad.js +5 -1
  41. package/lib/hw/customLockScreenLoad.js.map +1 -1
  42. package/lib/modularDrawer/utils/getBalanceAndFiatValue.d.ts +20 -0
  43. package/lib/modularDrawer/utils/getBalanceAndFiatValue.d.ts.map +1 -0
  44. package/lib/modularDrawer/utils/getBalanceAndFiatValue.js +39 -0
  45. package/lib/modularDrawer/utils/getBalanceAndFiatValue.js.map +1 -0
  46. package/lib/modularDrawer/utils/index.d.ts +2 -1
  47. package/lib/modularDrawer/utils/index.d.ts.map +1 -1
  48. package/lib/modularDrawer/utils/index.js +3 -1
  49. package/lib/modularDrawer/utils/index.js.map +1 -1
  50. package/lib/wallet-api/Exchange/server.d.ts.map +1 -1
  51. package/lib/wallet-api/Exchange/server.js +10 -0
  52. package/lib/wallet-api/Exchange/server.js.map +1 -1
  53. package/lib-es/bridge/generic-alpaca/alpaca/network/network-alpaca.d.ts +3 -1
  54. package/lib-es/bridge/generic-alpaca/alpaca/network/network-alpaca.d.ts.map +1 -1
  55. package/lib-es/bridge/generic-alpaca/alpaca/network/network-alpaca.js +6 -0
  56. package/lib-es/bridge/generic-alpaca/alpaca/network/network-alpaca.js.map +1 -1
  57. package/lib-es/device/use-cases/listAppsUseCase.test.js +1 -1
  58. package/lib-es/device/use-cases/listAppsUseCase.test.js.map +1 -1
  59. package/lib-es/e2e/enum/DeviceLabels.d.ts +5 -1
  60. package/lib-es/e2e/enum/DeviceLabels.d.ts.map +1 -1
  61. package/lib-es/e2e/enum/DeviceLabels.js +4 -0
  62. package/lib-es/e2e/enum/DeviceLabels.js.map +1 -1
  63. package/lib-es/e2e/families/evm.js +1 -1
  64. package/lib-es/e2e/families/evm.js.map +1 -1
  65. package/lib-es/e2e/index.d.ts +2 -0
  66. package/lib-es/e2e/index.d.ts.map +1 -1
  67. package/lib-es/e2e/speculos.d.ts.map +1 -1
  68. package/lib-es/e2e/speculos.js +18 -26
  69. package/lib-es/e2e/speculos.js.map +1 -1
  70. package/lib-es/exchange/swap/hooks/usePickDefaultAccount.test.js +21 -9
  71. package/lib-es/exchange/swap/hooks/usePickDefaultAccount.test.js.map +1 -1
  72. package/lib-es/exchange/swap/hooks/wrapper.d.ts +3 -0
  73. package/lib-es/exchange/swap/hooks/wrapper.d.ts.map +1 -0
  74. package/lib-es/exchange/swap/hooks/wrapper.js +13 -0
  75. package/lib-es/exchange/swap/hooks/wrapper.js.map +1 -0
  76. package/lib-es/exchange/swap/postSwapState.d.ts.map +1 -1
  77. package/lib-es/exchange/swap/postSwapState.js +63 -4
  78. package/lib-es/exchange/swap/postSwapState.js.map +1 -1
  79. package/lib-es/exchange/swap/setBroadcastTransaction.d.ts +4 -1
  80. package/lib-es/exchange/swap/setBroadcastTransaction.d.ts.map +1 -1
  81. package/lib-es/exchange/swap/setBroadcastTransaction.js +7 -1
  82. package/lib-es/exchange/swap/setBroadcastTransaction.js.map +1 -1
  83. package/lib-es/exchange/swap/types.d.ts +7 -0
  84. package/lib-es/exchange/swap/types.d.ts.map +1 -1
  85. package/lib-es/featureFlags/defaultFeatures.d.ts.map +1 -1
  86. package/lib-es/featureFlags/defaultFeatures.js +1 -0
  87. package/lib-es/featureFlags/defaultFeatures.js.map +1 -1
  88. package/lib-es/featureFlags/useFeature.d.ts +1 -1
  89. package/lib-es/featureFlags/useFeature.d.ts.map +1 -1
  90. package/lib-es/hw/customLockScreenLoad.d.ts +1 -9
  91. package/lib-es/hw/customLockScreenLoad.d.ts.map +1 -1
  92. package/lib-es/hw/customLockScreenLoad.js +5 -1
  93. package/lib-es/hw/customLockScreenLoad.js.map +1 -1
  94. package/lib-es/modularDrawer/utils/getBalanceAndFiatValue.d.ts +20 -0
  95. package/lib-es/modularDrawer/utils/getBalanceAndFiatValue.d.ts.map +1 -0
  96. package/lib-es/modularDrawer/utils/getBalanceAndFiatValue.js +32 -0
  97. package/lib-es/modularDrawer/utils/getBalanceAndFiatValue.js.map +1 -0
  98. package/lib-es/modularDrawer/utils/index.d.ts +2 -1
  99. package/lib-es/modularDrawer/utils/index.d.ts.map +1 -1
  100. package/lib-es/modularDrawer/utils/index.js +2 -1
  101. package/lib-es/modularDrawer/utils/index.js.map +1 -1
  102. package/lib-es/wallet-api/Exchange/server.d.ts.map +1 -1
  103. package/lib-es/wallet-api/Exchange/server.js +10 -0
  104. package/lib-es/wallet-api/Exchange/server.js.map +1 -1
  105. package/package.json +72 -72
  106. package/src/bridge/generic-alpaca/alpaca/network/network-alpaca.ts +10 -0
  107. package/src/device/use-cases/listAppsUseCase.test.ts +1 -1
  108. package/src/e2e/enum/DeviceLabels.ts +4 -0
  109. package/src/e2e/families/evm.ts +1 -1
  110. package/src/e2e/speculos.ts +21 -28
  111. package/src/exchange/swap/hooks/usePickDefaultAccount.test.ts +25 -12
  112. package/src/exchange/swap/hooks/wrapper.tsx +18 -0
  113. package/src/exchange/swap/postSwapState.ts +97 -2
  114. package/src/exchange/swap/setBroadcastTransaction.ts +12 -0
  115. package/src/exchange/swap/types.ts +7 -0
  116. package/src/featureFlags/defaultFeatures.ts +1 -0
  117. package/src/hw/customLockScreenLoad.ts +7 -11
  118. package/src/modularDrawer/utils/getBalanceAndFiatValue.ts +53 -0
  119. package/src/modularDrawer/utils/index.ts +7 -1
  120. package/src/wallet-api/Exchange/server.ts +10 -0
@@ -1,14 +1,60 @@
1
+ import crypto from "crypto";
1
2
  import network from "@ledgerhq/live-network";
2
3
  import { mockPostSwapAccepted, mockPostSwapCancelled } from "./mock";
3
4
  import type { PostSwapAccepted, PostSwapCancelled } from "./types";
4
5
  import { isIntegrationTestEnv } from "./utils/isIntegrationTestEnv";
5
6
  import { getSwapAPIBaseURL, getSwapUserIP } from ".";
6
7
 
8
+ function createSwapIntentHashes({
9
+ provider,
10
+ fromAccountId,
11
+ toAccountId,
12
+ amount,
13
+ }: {
14
+ provider: string;
15
+ fromAccountId?: string;
16
+ toAccountId?: string;
17
+ amount?: string;
18
+ }) {
19
+ // for example '2025-08-01' used to add a one day unique nonce to the swap intent hash
20
+ const currentday = new Date().toISOString().split("T")[0];
21
+
22
+ const swapIntentWithProvider = crypto
23
+ .createHash("sha256")
24
+ .update(
25
+ JSON.stringify({
26
+ provider,
27
+ fromAccountId,
28
+ toAccountId,
29
+ amount,
30
+ currentday,
31
+ }),
32
+ )
33
+ .digest("hex");
34
+
35
+ const swapIntentWithoutProvider = crypto
36
+ .createHash("sha256")
37
+ .update(
38
+ JSON.stringify({
39
+ fromAccountId,
40
+ toAccountId,
41
+ amount,
42
+ currentday,
43
+ }),
44
+ )
45
+ .digest("hex");
46
+
47
+ return { swapIntentWithProvider, swapIntentWithoutProvider };
48
+ }
49
+
7
50
  export const postSwapAccepted: PostSwapAccepted = async ({
8
51
  provider,
9
52
  swapId = "",
10
53
  transactionId,
11
54
  swapAppVersion,
55
+ fromAccountId,
56
+ toAccountId,
57
+ amount,
12
58
  ...rest
13
59
  }) => {
14
60
  if (isIntegrationTestEnv())
@@ -21,6 +67,14 @@ export const postSwapAccepted: PostSwapAccepted = async ({
21
67
  if (!swapId) {
22
68
  return null;
23
69
  }
70
+
71
+ const { swapIntentWithProvider, swapIntentWithoutProvider } = createSwapIntentHashes({
72
+ provider,
73
+ fromAccountId,
74
+ toAccountId,
75
+ amount,
76
+ });
77
+
24
78
  try {
25
79
  const ipHeader = getSwapUserIP();
26
80
  const headers = {
@@ -31,7 +85,7 @@ export const postSwapAccepted: PostSwapAccepted = async ({
31
85
  await network({
32
86
  method: "POST",
33
87
  url: `${getSwapAPIBaseURL()}/swap/accepted`,
34
- data: { provider, swapId, transactionId, ...rest },
88
+ data: { provider, swapId, swapIntentWithProvider, swapIntentWithoutProvider, ...rest },
35
89
  ...(Object.keys(headers).length > 0 ? { headers } : {}),
36
90
  });
37
91
  } catch (error) {
@@ -45,6 +99,13 @@ export const postSwapCancelled: PostSwapCancelled = async ({
45
99
  provider,
46
100
  swapId = "",
47
101
  swapAppVersion,
102
+ fromAccountId,
103
+ toAccountId,
104
+ amount,
105
+ seedIdFrom,
106
+ seedIdTo,
107
+ refundAddress,
108
+ payoutAddress,
48
109
  ...rest
49
110
  }) => {
50
111
  if (isIntegrationTestEnv()) return mockPostSwapCancelled({ provider, swapId, ...rest });
@@ -57,6 +118,22 @@ export const postSwapCancelled: PostSwapCancelled = async ({
57
118
  return null;
58
119
  }
59
120
 
121
+ const { swapIntentWithProvider, swapIntentWithoutProvider } = createSwapIntentHashes({
122
+ provider,
123
+ fromAccountId,
124
+ toAccountId,
125
+ amount,
126
+ });
127
+
128
+ // Check if the refundAddress and payoutAddress match the account addresses, just to eliminate this supposition
129
+ const payloadAddressMatchAccountAddress =
130
+ fromAccountId &&
131
+ toAccountId &&
132
+ refundAddress &&
133
+ payoutAddress &&
134
+ fromAccountId.includes(refundAddress) &&
135
+ toAccountId.includes(payoutAddress);
136
+
60
137
  try {
61
138
  const ipHeader = getSwapUserIP();
62
139
  const headers = {
@@ -64,10 +141,28 @@ export const postSwapCancelled: PostSwapCancelled = async ({
64
141
  ...(swapAppVersion ? { "x-swap-app-version": swapAppVersion } : {}),
65
142
  };
66
143
 
144
+ const shouldIncludeAddresses =
145
+ rest.statusCode === "WrongDeviceForAccountPayout" ||
146
+ rest.statusCode === "WrongDeviceForAccountRefund";
147
+
148
+ const requestData = {
149
+ provider,
150
+ swapId,
151
+ swapIntentWithProvider,
152
+ swapIntentWithoutProvider,
153
+ payloadAddressMatchAccountAddress,
154
+ fromAccountId: shouldIncludeAddresses ? fromAccountId : undefined,
155
+ toAccountId: shouldIncludeAddresses ? toAccountId : undefined,
156
+ payloadRefundAddress: shouldIncludeAddresses ? refundAddress : undefined,
157
+ payloadPayoutAddress: shouldIncludeAddresses ? payoutAddress : undefined,
158
+ maybeSeedMatch: seedIdFrom === seedIdTo, // Only true if both accounts are from the same seed and from the same chain type
159
+ ...rest,
160
+ };
161
+
67
162
  await network({
68
163
  method: "POST",
69
164
  url: `${getSwapAPIBaseURL()}/swap/cancelled`,
70
- data: { provider, swapId, ...rest },
165
+ data: requestData,
71
166
  ...(Object.keys(headers).length > 0 ? { headers } : {}),
72
167
  });
73
168
  } catch (error) {
@@ -12,6 +12,9 @@ export const setBroadcastTransaction = ({
12
12
  hardwareWalletType,
13
13
  swapType,
14
14
  swapAppVersion,
15
+ fromAccountId,
16
+ toAccountId,
17
+ amount,
15
18
  }: {
16
19
  result: { operation: Operation | string; swapId: string };
17
20
  provider: string;
@@ -20,6 +23,9 @@ export const setBroadcastTransaction = ({
20
23
  hardwareWalletType?: DeviceModelId;
21
24
  swapType?: TradeMethod;
22
25
  swapAppVersion?: string;
26
+ fromAccountId?: string;
27
+ toAccountId?: string;
28
+ amount?: string;
23
29
  }) => {
24
30
  const { operation, swapId } = result;
25
31
 
@@ -39,6 +45,9 @@ export const setBroadcastTransaction = ({
39
45
  hardwareWalletType,
40
46
  swapType: swapType,
41
47
  swapAppVersion,
48
+ fromAccountId,
49
+ toAccountId,
50
+ amount,
42
51
  });
43
52
  } else {
44
53
  postSwapAccepted({
@@ -50,6 +59,9 @@ export const setBroadcastTransaction = ({
50
59
  hardwareWalletType,
51
60
  swapType,
52
61
  swapAppVersion,
62
+ fromAccountId,
63
+ toAccountId,
64
+ amount,
53
65
  });
54
66
  }
55
67
  };
@@ -200,6 +200,13 @@ type SwapStateRequest = {
200
200
  hardwareWalletType: DeviceModelId;
201
201
  swapType: TradeMethod;
202
202
  swapAppVersion?: string;
203
+ fromAccountId?: string;
204
+ toAccountId?: string;
205
+ amount?: string;
206
+ seedIdFrom?: string;
207
+ seedIdTo?: string;
208
+ refundAddress?: string;
209
+ payoutAddress?: string;
203
210
  }>;
204
211
 
205
212
  export type SwapStateAcceptedRequest = SwapStateRequest & {
@@ -677,6 +677,7 @@ export const DEFAULT_FEATURES: Features = {
677
677
  ...DEFAULT_FEATURE,
678
678
  params: {},
679
679
  },
680
+ supportDeviceApex: DEFAULT_FEATURE,
680
681
  };
681
682
 
682
683
  // Firebase SDK treat JSON values as strings
@@ -19,7 +19,7 @@ import customLockScreenFetchSize from "./customLockScreenFetchSize";
19
19
  import customLockScreenFetchHash from "./customLockScreenFetchHash";
20
20
  import { gzip } from "pako";
21
21
  import { CLSSupportedDeviceModelId } from "../device/use-cases/isCustomLockScreenSupported";
22
- import { getScreenSpecs } from "../device/use-cases/screenSpecs";
22
+ import { getScreenSpecs, type ScreenSpecs } from "../device/use-cases/screenSpecs";
23
23
  import { DeviceDisconnectedWhileSendingError } from "@ledgerhq/device-management-kit";
24
24
  import { withTransport } from "../deviceSDK/transports/core";
25
25
 
@@ -60,15 +60,6 @@ export type LoadimageResult = {
60
60
  imageSize: number;
61
61
  };
62
62
 
63
- type ScreenSpecs = {
64
- width: number;
65
- height: number;
66
- paddingTop: number;
67
- paddingBottom: number;
68
- paddingLeft: number;
69
- paddingRight: number;
70
- };
71
-
72
63
  export type LoadImageRequest = {
73
64
  hexImage: string; // When provided, will skip the backup if it matches the hash.
74
65
  padImage?: boolean;
@@ -268,6 +259,11 @@ function padHexImage(hexImage: string, screenSpecs: ScreenSpecs): string {
268
259
  return result;
269
260
  }
270
261
 
262
+ const bitsPerPixelToBppIndicator: Record<ScreenSpecs["bitsPerPixel"], number> = {
263
+ 1: 0,
264
+ 4: 2,
265
+ };
266
+
271
267
  export async function generateCustomLockScreenImageFormat(
272
268
  hexImage: string,
273
269
  compressImage: boolean,
@@ -276,7 +272,7 @@ export async function generateCustomLockScreenImageFormat(
276
272
  ) {
277
273
  const width = screenSpecs.width;
278
274
  const height = screenSpecs.height;
279
- const bpp = 2; // value for 4 bits per pixel
275
+ const bpp = bitsPerPixelToBppIndicator[screenSpecs.bitsPerPixel];
280
276
  const compression = compressImage ? 1 : 0;
281
277
 
282
278
  const header = Buffer.alloc(8);
@@ -0,0 +1,53 @@
1
+ import { formatCurrencyUnit } from "@ledgerhq/coin-framework/currencies/formatCurrencyUnit";
2
+ import { isAccount } from "@ledgerhq/coin-framework/account/helpers";
3
+ import {
4
+ getPortfolioCount,
5
+ getBalanceHistoryWithCountervalue,
6
+ } from "@ledgerhq/live-countervalues/portfolio";
7
+ import type { CounterValuesState } from "@ledgerhq/live-countervalues/types";
8
+ import { Currency } from "@ledgerhq/types-cryptoassets";
9
+ import { Account, TokenAccount } from "@ledgerhq/types-live";
10
+ import BigNumber from "bignumber.js";
11
+
12
+ /**
13
+ *
14
+ * @param account - The account to get the balance and fiat value for
15
+ * @param state - The current state of countervalues
16
+ * @param toCurrency - The currency to convert to
17
+ * @param discreet - Whether to show the balance in discreet mode
18
+ * @param showCode - Whether to show the currency code in the formatted balance
19
+ * @returns An object containing the balance and fiat value
20
+ */
21
+ export const getBalanceAndFiatValue = (
22
+ account: Account | TokenAccount,
23
+ state: CounterValuesState,
24
+ toCurrency: Currency,
25
+ discreet: boolean = false,
26
+ showCode: boolean = true,
27
+ ) => {
28
+ const isAnAccount = isAccount(account);
29
+ const details = isAnAccount ? account.currency : account.token;
30
+ const balance = formatCurrencyUnit(details.units[0], account.balance, {
31
+ showCode,
32
+ discreet,
33
+ });
34
+
35
+ const count = getPortfolioCount([account], "day");
36
+ const { history, countervalueAvailable } = getBalanceHistoryWithCountervalue(
37
+ account,
38
+ "day",
39
+ count,
40
+ state,
41
+ toCurrency,
42
+ );
43
+
44
+ if (!countervalueAvailable) return { balance, fiatValue: undefined };
45
+
46
+ const { countervalue } = history[history.length - 1] ?? {};
47
+ const fiatValue = formatCurrencyUnit(toCurrency.units[0], BigNumber(countervalue ?? 0), {
48
+ showCode,
49
+ discreet,
50
+ });
51
+
52
+ return { balance, fiatValue };
53
+ };
@@ -1,6 +1,7 @@
1
1
  import { CryptoOrTokenCurrency } from "@ledgerhq/types-cryptoassets";
2
2
  import { CurrenciesByProviderId } from "../../deposit/type";
3
3
  import { haveOneCommonProvider } from "./haveOneCommonProvider";
4
+ import { getBalanceAndFiatValue } from "./getBalanceAndFiatValue";
4
5
 
5
6
  function isCorrespondingCurrency(
6
7
  elem: CryptoOrTokenCurrency,
@@ -27,4 +28,9 @@ const getEffectiveCurrency = (
27
28
  return provider.currenciesByNetwork.find(elem => currencyIds.includes(elem.id)) ?? currency;
28
29
  };
29
30
 
30
- export { isCorrespondingCurrency, getEffectiveCurrency, haveOneCommonProvider };
31
+ export {
32
+ isCorrespondingCurrency,
33
+ getEffectiveCurrency,
34
+ haveOneCommonProvider,
35
+ getBalanceAndFiatValue,
36
+ };
@@ -571,6 +571,9 @@ export const handlers = ({
571
571
  targetCurrencyId: toCurrency?.id,
572
572
  hardwareWalletType: deviceInfo?.modelId as DeviceModelId,
573
573
  swapAppVersion,
574
+ fromAccountId: fromAccount.id,
575
+ toAccountId: toAccount?.id,
576
+ amount: amountExpectedTo.toString(),
574
577
  });
575
578
 
576
579
  resolve({ operationHash, swapId });
@@ -587,6 +590,13 @@ export const handlers = ({
587
590
  hardwareWalletType: deviceInfo?.modelId as DeviceModelId,
588
591
  swapType: quoteId ? "fixed" : "float",
589
592
  swapAppVersion,
593
+ fromAccountId: fromAccount.id,
594
+ toAccountId: toAccount?.id,
595
+ refundAddress,
596
+ payoutAddress,
597
+ amount: amountExpectedTo.toString(),
598
+ seedIdFrom: mainFromAccount.seedIdentifier,
599
+ seedIdTo: toParentAccount?.seedIdentifier || (toAccount as Account)?.seedIdentifier,
590
600
  });
591
601
 
592
602
  reject(error);