@ledgerhq/live-common 34.54.0-nightly.20251129023709 → 34.54.0-nightly.20251202023925

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 (54) hide show
  1. package/lib/account/index.d.ts +1 -0
  2. package/lib/account/index.d.ts.map +1 -1
  3. package/lib/account/index.js +4 -1
  4. package/lib/account/index.js.map +1 -1
  5. package/lib/account/recentAddresses.d.ts +10 -0
  6. package/lib/account/recentAddresses.d.ts.map +1 -0
  7. package/lib/account/recentAddresses.js +60 -0
  8. package/lib/account/recentAddresses.js.map +1 -0
  9. package/lib/e2e/index.d.ts +3 -0
  10. package/lib/e2e/index.d.ts.map +1 -1
  11. package/lib/exchange/swap/postSwapState.d.ts.map +1 -1
  12. package/lib/exchange/swap/postSwapState.js +10 -6
  13. package/lib/exchange/swap/postSwapState.js.map +1 -1
  14. package/lib/exchange/swap/types.d.ts +3 -1
  15. package/lib/exchange/swap/types.d.ts.map +1 -1
  16. package/lib/featureFlags/defaultFeatures.d.ts.map +1 -1
  17. package/lib/featureFlags/defaultFeatures.js +1 -0
  18. package/lib/featureFlags/defaultFeatures.js.map +1 -1
  19. package/lib/featureFlags/useFeature.d.ts +1 -1
  20. package/lib/featureFlags/useFeature.d.ts.map +1 -1
  21. package/lib/wallet-api/Exchange/server.d.ts.map +1 -1
  22. package/lib/wallet-api/Exchange/server.js +4 -0
  23. package/lib/wallet-api/Exchange/server.js.map +1 -1
  24. package/lib-es/account/index.d.ts +1 -0
  25. package/lib-es/account/index.d.ts.map +1 -1
  26. package/lib-es/account/index.js +1 -0
  27. package/lib-es/account/index.js.map +1 -1
  28. package/lib-es/account/recentAddresses.d.ts +10 -0
  29. package/lib-es/account/recentAddresses.d.ts.map +1 -0
  30. package/lib-es/account/recentAddresses.js +55 -0
  31. package/lib-es/account/recentAddresses.js.map +1 -0
  32. package/lib-es/e2e/index.d.ts +3 -0
  33. package/lib-es/e2e/index.d.ts.map +1 -1
  34. package/lib-es/exchange/swap/postSwapState.d.ts.map +1 -1
  35. package/lib-es/exchange/swap/postSwapState.js +10 -6
  36. package/lib-es/exchange/swap/postSwapState.js.map +1 -1
  37. package/lib-es/exchange/swap/types.d.ts +3 -1
  38. package/lib-es/exchange/swap/types.d.ts.map +1 -1
  39. package/lib-es/featureFlags/defaultFeatures.d.ts.map +1 -1
  40. package/lib-es/featureFlags/defaultFeatures.js +1 -0
  41. package/lib-es/featureFlags/defaultFeatures.js.map +1 -1
  42. package/lib-es/featureFlags/useFeature.d.ts +1 -1
  43. package/lib-es/featureFlags/useFeature.d.ts.map +1 -1
  44. package/lib-es/wallet-api/Exchange/server.d.ts.map +1 -1
  45. package/lib-es/wallet-api/Exchange/server.js +4 -0
  46. package/lib-es/wallet-api/Exchange/server.js.map +1 -1
  47. package/package.json +54 -54
  48. package/src/account/index.ts +6 -0
  49. package/src/account/recentAddresses.test.ts +104 -0
  50. package/src/account/recentAddresses.ts +84 -0
  51. package/src/exchange/swap/postSwapState.ts +10 -5
  52. package/src/exchange/swap/types.ts +3 -1
  53. package/src/featureFlags/defaultFeatures.ts +1 -0
  54. package/src/wallet-api/Exchange/server.ts +5 -0
@@ -0,0 +1,104 @@
1
+ import { RecentAddressesStore, setupRecentAddressesStore, getRecentAddressesStore } from ".";
2
+ import { RECENT_ADDRESSES_COUNT_LIMIT } from "./recentAddresses";
3
+
4
+ describe("RecentAddressesStore", () => {
5
+ const onAddAddressCompleteMock = jest.fn();
6
+ let store: RecentAddressesStore;
7
+
8
+ beforeEach(() => {
9
+ onAddAddressCompleteMock.mockClear();
10
+ setupRecentAddressesStore({}, onAddAddressCompleteMock);
11
+ store = getRecentAddressesStore();
12
+ });
13
+
14
+ it("should add one address and return this only address", async () => {
15
+ const newAddress = "0x66c4371aE8FFeD2ec1c2EBbbcCfb7E494181E1E3";
16
+ await store.addAddress("ethereum", newAddress);
17
+ const addresses = store.getAddresses("ethereum");
18
+ expect(addresses).toEqual([newAddress]);
19
+ expect(onAddAddressCompleteMock).toHaveBeenCalledTimes(1);
20
+ expect(onAddAddressCompleteMock).toHaveBeenCalledWith({ ethereum: [newAddress] });
21
+ });
22
+
23
+ it("should add a second address and return addresses sorted by insertion", async () => {
24
+ const newAddress = "0x66c4371aE8FFeD2ec1c2EBbbcCfb7E494181E1E3";
25
+ await store.addAddress("ethereum", newAddress);
26
+ let addresses = store.getAddresses("ethereum");
27
+ expect(addresses).toEqual([newAddress]);
28
+ expect(onAddAddressCompleteMock).toHaveBeenCalledTimes(1);
29
+ expect(onAddAddressCompleteMock).toHaveBeenCalledWith({ ethereum: [newAddress] });
30
+
31
+ const newAddress2 = "0xB69B37A4Fb4A18b3258f974ff6e9f529AD2647b1";
32
+ await store.addAddress("ethereum", newAddress2);
33
+ addresses = store.getAddresses("ethereum");
34
+ expect(addresses).toEqual([newAddress2, newAddress]);
35
+ expect(onAddAddressCompleteMock).toHaveBeenCalledTimes(2);
36
+ expect(onAddAddressCompleteMock).toHaveBeenCalledWith({ ethereum: [newAddress2, newAddress] });
37
+ });
38
+
39
+ it("should replace at first place when an address is already saved", async () => {
40
+ const newAddress = "0x66c4371aE8FFeD2ec1c2EBbbcCfb7E494181E1E3";
41
+ await store.addAddress("ethereum", newAddress);
42
+ let addresses = store.getAddresses("ethereum");
43
+ expect(addresses).toEqual([newAddress]);
44
+ expect(onAddAddressCompleteMock).toHaveBeenCalledTimes(1);
45
+ expect(onAddAddressCompleteMock).toHaveBeenCalledWith({ ethereum: [newAddress] });
46
+
47
+ const newAddress2 = "0xB69B37A4Fb4A18b3258f974ff6e9f529AD2647b1";
48
+ await store.addAddress("ethereum", newAddress2);
49
+ addresses = store.getAddresses("ethereum");
50
+ expect(addresses).toEqual([newAddress2, newAddress]);
51
+ expect(onAddAddressCompleteMock).toHaveBeenCalledTimes(2);
52
+ expect(onAddAddressCompleteMock).toHaveBeenCalledWith({ ethereum: [newAddress2, newAddress] });
53
+
54
+ await store.addAddress("ethereum", newAddress);
55
+ addresses = store.getAddresses("ethereum");
56
+ expect(addresses).toEqual([newAddress, newAddress2]);
57
+ expect(onAddAddressCompleteMock).toHaveBeenCalledTimes(3);
58
+ expect(onAddAddressCompleteMock).toHaveBeenCalledWith({ ethereum: [newAddress, newAddress2] });
59
+ });
60
+
61
+ it("should replace at first place and remove last element when addresses exceed count limit", async () => {
62
+ let expectedAddresses: string[] = [];
63
+ for (let index = 0; index < RECENT_ADDRESSES_COUNT_LIMIT; index++) {
64
+ await store.addAddress("ethereum", `0x66c4371aE8FFeD2ec1c2EBbbcCfb7E494181E1E3${index}`);
65
+ expectedAddresses.unshift(`0x66c4371aE8FFeD2ec1c2EBbbcCfb7E494181E1E3${index}`);
66
+ }
67
+
68
+ let addresses = store.getAddresses("ethereum");
69
+ expect(addresses).toEqual(expectedAddresses);
70
+ expect(onAddAddressCompleteMock).toHaveBeenCalledTimes(RECENT_ADDRESSES_COUNT_LIMIT);
71
+ expect(onAddAddressCompleteMock).toHaveBeenCalledWith({ ethereum: expectedAddresses });
72
+
73
+ const newAddress2 = "0xB69B37A4Fb4A18b3258f974ff6e9f529AD2647b1";
74
+ expectedAddresses.splice(expectedAddresses.length - 1, 1);
75
+ expectedAddresses = [newAddress2, ...expectedAddresses];
76
+
77
+ await store.addAddress("ethereum", newAddress2);
78
+ addresses = store.getAddresses("ethereum");
79
+ expect(addresses).toEqual(expectedAddresses);
80
+ expect(onAddAddressCompleteMock).toHaveBeenCalledTimes(RECENT_ADDRESSES_COUNT_LIMIT + 1);
81
+ expect(onAddAddressCompleteMock).toHaveBeenCalledWith({ ethereum: expectedAddresses });
82
+ });
83
+
84
+ it("should add an address of a different currency", async () => {
85
+ const newAddress = "0x66c4371aE8FFeD2ec1c2EBbbcCfb7E494181E1E3";
86
+ await store.addAddress("ethereum", newAddress);
87
+
88
+ let addresses = store.getAddresses("ethereum");
89
+ expect(addresses).toEqual([newAddress]);
90
+ expect(onAddAddressCompleteMock).toHaveBeenCalledTimes(1);
91
+ expect(onAddAddressCompleteMock).toHaveBeenCalledWith({ ethereum: [newAddress] });
92
+
93
+ const newAddress2 = "bc1pxlmrudqyq8qd8pfsc4mpmlaw56x6vtcr9m8nvp8kj3gckefc4kmqhkg4l7";
94
+ await store.addAddress("bitcoin", newAddress2);
95
+
96
+ addresses = store.getAddresses("bitcoin");
97
+ expect(addresses).toEqual([newAddress2]);
98
+ expect(onAddAddressCompleteMock).toHaveBeenCalledTimes(2);
99
+ expect(onAddAddressCompleteMock).toHaveBeenCalledWith({
100
+ ethereum: [newAddress],
101
+ bitcoin: [newAddress2],
102
+ });
103
+ });
104
+ });
@@ -0,0 +1,84 @@
1
+ export const RECENT_ADDRESSES_COUNT_LIMIT = 12;
2
+
3
+ export type RecentAddressesCache = Record<string, string[]>;
4
+
5
+ export interface RecentAddressesStore {
6
+ addAddress(currency: string, address: string): void;
7
+ syncAddresses(cache: RecentAddressesCache): void;
8
+ getAddresses(currency: string): string[];
9
+ }
10
+
11
+ type CallbackMode = "triggerCallback" | "skipCallback";
12
+
13
+ let recentAddressesStore: RecentAddressesStore | null = null;
14
+
15
+ export function getRecentAddressesStore(): RecentAddressesStore {
16
+ if (recentAddressesStore === null) {
17
+ throw new Error(
18
+ "Recent addresses store instance is null, please call function setupRecentAddressesStore in application initialization",
19
+ );
20
+ }
21
+ return recentAddressesStore;
22
+ }
23
+
24
+ export function setupRecentAddressesStore(
25
+ addressesByCurrency: RecentAddressesCache,
26
+ onAddAddressComplete: (addressesByCurrency: RecentAddressesCache) => void,
27
+ ): void {
28
+ recentAddressesStore = new RecentAddressesStoreImpl(addressesByCurrency, onAddAddressComplete);
29
+ }
30
+
31
+ class RecentAddressesStoreImpl implements RecentAddressesStore {
32
+ private addressesByCurrency: RecentAddressesCache = {};
33
+ private readonly onAddAddressComplete: (addressesByCurrency: Record<string, string[]>) => void;
34
+
35
+ constructor(
36
+ addressesByCurrency: RecentAddressesCache,
37
+ onAddAddressComplete: (addressesByCurrency: RecentAddressesCache) => void,
38
+ ) {
39
+ this.addressesByCurrency = { ...addressesByCurrency };
40
+ this.onAddAddressComplete = onAddAddressComplete;
41
+ }
42
+
43
+ addAddress(currency: string, address: string): void {
44
+ this.addAddressToCache(currency, address, "triggerCallback");
45
+ }
46
+
47
+ syncAddresses(cache: RecentAddressesCache): void {
48
+ const previousAddresses = { ...this.addressesByCurrency };
49
+ this.addressesByCurrency = { ...cache };
50
+ for (const currency in previousAddresses) {
51
+ for (const address of previousAddresses[currency]) {
52
+ this.addAddressToCache(currency, address, "skipCallback");
53
+ }
54
+ }
55
+
56
+ this.onAddAddressComplete(this.addressesByCurrency);
57
+ }
58
+
59
+ getAddresses(currency: string): string[] {
60
+ const addresses = this.addressesByCurrency[currency];
61
+ return addresses ?? [];
62
+ }
63
+
64
+ private addAddressToCache(currency: string, address: string, callbackMode: CallbackMode): void {
65
+ if (!this.addressesByCurrency[currency]) {
66
+ this.addressesByCurrency[currency] = [];
67
+ }
68
+
69
+ const addresses = this.addressesByCurrency[currency];
70
+ const addressIndex = addresses.indexOf(address);
71
+ if (addressIndex !== -1) {
72
+ addresses.splice(addressIndex, 1);
73
+ } else if (addresses.length >= RECENT_ADDRESSES_COUNT_LIMIT) {
74
+ addresses.pop();
75
+ }
76
+
77
+ addresses.unshift(address);
78
+ this.addressesByCurrency[currency] = [...addresses];
79
+
80
+ if (callbackMode === "triggerCallback") {
81
+ this.onAddAddressComplete(this.addressesByCurrency);
82
+ }
83
+ }
84
+ }
@@ -106,6 +106,7 @@ export const postSwapCancelled: PostSwapCancelled = async ({
106
106
  seedIdTo,
107
107
  refundAddress,
108
108
  payoutAddress,
109
+ data,
109
110
  ...rest
110
111
  }) => {
111
112
  if (isIntegrationTestEnv()) return mockPostSwapCancelled({ provider, swapId, ...rest });
@@ -138,7 +139,8 @@ export const postSwapCancelled: PostSwapCancelled = async ({
138
139
 
139
140
  const shouldIncludeAddresses =
140
141
  rest.statusCode === "WrongDeviceForAccountPayout" ||
141
- rest.statusCode === "WrongDeviceForAccountRefund";
142
+ rest.statusCode === "WrongDeviceForAccountRefund" ||
143
+ rest.statusCode === "FeeNotLoaded";
142
144
 
143
145
  const requestData = {
144
146
  provider,
@@ -147,11 +149,14 @@ export const postSwapCancelled: PostSwapCancelled = async ({
147
149
  swapIntentWithoutProvider,
148
150
  payloadAddressMatchAccountAddress,
149
151
  fromAmount,
150
- fromAccountAddress: shouldIncludeAddresses ? fromAccountAddress : undefined,
151
- toAccountAddress: shouldIncludeAddresses ? toAccountAddress : undefined,
152
- payloadRefundAddress: shouldIncludeAddresses ? refundAddress : undefined,
153
- payloadPayoutAddress: shouldIncludeAddresses ? payoutAddress : undefined,
152
+ ...(shouldIncludeAddresses && {
153
+ fromAccountAddress,
154
+ toAccountAddress,
155
+ payloadRefundAddress: refundAddress,
156
+ payloadPayoutAddress: payoutAddress,
157
+ }),
154
158
  maybeSeedMatch: seedIdFrom === seedIdTo, // Only true if both accounts are from the same seed and from the same chain type
159
+ data,
155
160
  ...rest,
156
161
  };
157
162
 
@@ -214,7 +214,9 @@ export type SwapStateAcceptedRequest = SwapStateRequest & {
214
214
  transactionId: string;
215
215
  };
216
216
 
217
- export type SwapStateCancelledRequest = SwapStateRequest;
217
+ export type SwapStateCancelledRequest = SwapStateRequest & {
218
+ data?: string;
219
+ };
218
220
 
219
221
  export type PostSwapAccepted = (arg0: SwapStateAcceptedRequest) => Promise<null>;
220
222
 
@@ -731,6 +731,7 @@ export const DEFAULT_FEATURES: Features = {
731
731
  },
732
732
  },
733
733
  zcashShielded: DEFAULT_FEATURE,
734
+ llmNanoOnboardingFundWallet: DEFAULT_FEATURE,
734
735
  };
735
736
 
736
737
  // Firebase SDK treat JSON values as strings
@@ -53,6 +53,8 @@ import { getSwapStepFromError } from "../../exchange/error";
53
53
  import { postSwapCancelled } from "../../exchange/swap";
54
54
  import { DeviceModelId } from "@ledgerhq/types-devices";
55
55
  import { setBroadcastTransaction } from "../../exchange/swap/setBroadcastTransaction";
56
+ import { Transaction as EvmTransaction } from "@ledgerhq/coin-evm/types/index";
57
+ import { padHexString } from "@ledgerhq/hw-app-eth";
56
58
 
57
59
  export { ExchangeType };
58
60
 
@@ -599,6 +601,9 @@ export const handlers = ({
599
601
  fromAmount,
600
602
  seedIdFrom: mainFromAccount.seedIdentifier,
601
603
  seedIdTo: toParentAccount?.seedIdentifier || (toAccount as Account)?.seedIdentifier,
604
+ data: (transaction as EvmTransaction).data
605
+ ? `0x${padHexString((transaction as EvmTransaction).data?.toString("hex") || "")}`
606
+ : "0x",
602
607
  });
603
608
 
604
609
  reject(error);