@ledgerhq/live-wallet 0.16.1-nightly.20251205111238 → 0.16.2
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.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +40 -8
- package/lib/store.d.ts +2 -15
- package/lib/store.d.ts.map +1 -1
- package/lib/store.js +2 -14
- package/lib/store.js.map +1 -1
- package/lib/walletsync/__mocks__/index.d.ts +1 -1
- package/lib/walletsync/__mocks__/index.d.ts.map +1 -1
- package/lib/walletsync/root.d.ts +0 -24
- package/lib/walletsync/root.d.ts.map +1 -1
- package/lib/walletsync/root.js +0 -2
- package/lib/walletsync/root.js.map +1 -1
- package/lib-es/store.d.ts +2 -15
- package/lib-es/store.d.ts.map +1 -1
- package/lib-es/store.js +1 -12
- package/lib-es/store.js.map +1 -1
- package/lib-es/walletsync/__mocks__/index.d.ts +1 -1
- package/lib-es/walletsync/__mocks__/index.d.ts.map +1 -1
- package/lib-es/walletsync/root.d.ts +0 -24
- package/lib-es/walletsync/root.d.ts.map +1 -1
- package/lib-es/walletsync/root.js +0 -2
- package/lib-es/walletsync/root.js.map +1 -1
- package/package.json +9 -9
- package/src/ordering.test.ts +0 -1
- package/src/store.test.ts +0 -2
- package/src/store.ts +2 -23
- package/src/walletsync/root.ts +0 -2
- package/lib/walletsync/__mocks__/modules/recentAddresses.d.ts +0 -8
- package/lib/walletsync/__mocks__/modules/recentAddresses.d.ts.map +0 -1
- package/lib/walletsync/__mocks__/modules/recentAddresses.js +0 -32
- package/lib/walletsync/__mocks__/modules/recentAddresses.js.map +0 -1
- package/lib/walletsync/modules/recentAddresses.d.ts +0 -47
- package/lib/walletsync/modules/recentAddresses.d.ts.map +0 -1
- package/lib/walletsync/modules/recentAddresses.js +0 -92
- package/lib/walletsync/modules/recentAddresses.js.map +0 -1
- package/lib-es/walletsync/__mocks__/modules/recentAddresses.d.ts +0 -8
- package/lib-es/walletsync/__mocks__/modules/recentAddresses.d.ts.map +0 -1
- package/lib-es/walletsync/__mocks__/modules/recentAddresses.js +0 -25
- package/lib-es/walletsync/__mocks__/modules/recentAddresses.js.map +0 -1
- package/lib-es/walletsync/modules/recentAddresses.d.ts +0 -47
- package/lib-es/walletsync/modules/recentAddresses.d.ts.map +0 -1
- package/lib-es/walletsync/modules/recentAddresses.js +0 -87
- package/lib-es/walletsync/modules/recentAddresses.js.map +0 -1
- package/src/walletsync/__mocks__/modules/recentAddresses.ts +0 -45
- package/src/walletsync/__tests__/modules/recentAddresses.test.ts +0 -487
- package/src/walletsync/modules/recentAddresses.ts +0 -125
|
@@ -1,487 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/consistent-type-assertions */
|
|
2
|
-
|
|
3
|
-
import { RecentAddressesState } from "@ledgerhq/types-live";
|
|
4
|
-
import { WalletSyncDataManagerResolutionContext } from "../../types";
|
|
5
|
-
import manager, { DistantRecentAddressesState } from "../../modules/recentAddresses";
|
|
6
|
-
|
|
7
|
-
describe("recentAddress", () => {
|
|
8
|
-
describe("diffLocalToDistant", () => {
|
|
9
|
-
it.each([
|
|
10
|
-
{
|
|
11
|
-
localData: {} as RecentAddressesState,
|
|
12
|
-
latestState: {
|
|
13
|
-
ethereum: [{ address: "some random address", index: 0 }],
|
|
14
|
-
} as DistantRecentAddressesState,
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
localData: {} as RecentAddressesState,
|
|
18
|
-
latestState: {
|
|
19
|
-
ethereum: [{ address: "some random address", index: 0 }],
|
|
20
|
-
solana: [{ address: "some random address on Solana", index: 0 }],
|
|
21
|
-
} as DistantRecentAddressesState,
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
localData: {
|
|
25
|
-
ethereum: ["some random address"],
|
|
26
|
-
},
|
|
27
|
-
latestState: {} as DistantRecentAddressesState,
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
localData: {
|
|
31
|
-
ethereum: ["some random address", "some random address 2"],
|
|
32
|
-
},
|
|
33
|
-
latestState: {
|
|
34
|
-
ethereum: [{ address: "some random address", index: 0 }],
|
|
35
|
-
} as DistantRecentAddressesState,
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
localData: {
|
|
39
|
-
solana: ["some random address"],
|
|
40
|
-
},
|
|
41
|
-
latestState: {
|
|
42
|
-
ethereum: [{ address: "some random address", index: 0 }],
|
|
43
|
-
} as DistantRecentAddressesState,
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
localData: {
|
|
47
|
-
ethereum: ["some random address"],
|
|
48
|
-
solana: ["some random address on Solana"],
|
|
49
|
-
},
|
|
50
|
-
latestState: {
|
|
51
|
-
ethereum: [{ address: "some random address", index: 0 }],
|
|
52
|
-
} as DistantRecentAddressesState,
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
localData: {
|
|
56
|
-
ethereum: ["some random address"],
|
|
57
|
-
solana: ["some random address on Solana", "some random address on Solana 2"],
|
|
58
|
-
},
|
|
59
|
-
latestState: {
|
|
60
|
-
ethereum: [{ address: "some random address", index: 0 }],
|
|
61
|
-
solana: [{ address: "some random address on Solana", index: 0 }],
|
|
62
|
-
} as DistantRecentAddressesState,
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
localData: {
|
|
66
|
-
ethereum: ["some random address"],
|
|
67
|
-
solana: ["some random address on Solana 2", "some random address on Solana 3"],
|
|
68
|
-
},
|
|
69
|
-
latestState: {
|
|
70
|
-
ethereum: [{ address: "some random address", index: 0 }],
|
|
71
|
-
solana: [
|
|
72
|
-
{ address: "some random address on Solana", index: 0 },
|
|
73
|
-
{ address: "some random address on Solana 2", index: 1 },
|
|
74
|
-
],
|
|
75
|
-
} as DistantRecentAddressesState,
|
|
76
|
-
},
|
|
77
|
-
])(
|
|
78
|
-
"should return true when local data is different from latest state #%#",
|
|
79
|
-
({ localData, latestState }) => {
|
|
80
|
-
const result = manager.diffLocalToDistant(localData, latestState);
|
|
81
|
-
|
|
82
|
-
expect(result).toEqual({
|
|
83
|
-
hasChanges: true,
|
|
84
|
-
nextState: expect.any(Object),
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
Object.entries(localData).forEach(([key, value]) => {
|
|
88
|
-
const nextState = result.nextState;
|
|
89
|
-
expect(nextState[key]).toEqual(
|
|
90
|
-
expect.arrayContaining(value.map((address, index) => ({ address, index }))),
|
|
91
|
-
);
|
|
92
|
-
});
|
|
93
|
-
},
|
|
94
|
-
);
|
|
95
|
-
|
|
96
|
-
it.each([
|
|
97
|
-
{
|
|
98
|
-
localData: {} as RecentAddressesState,
|
|
99
|
-
latestState: {} as DistantRecentAddressesState,
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
localData: { ethereum: ["some random address"] } as RecentAddressesState,
|
|
103
|
-
latestState: {
|
|
104
|
-
ethereum: [{ address: "some random address", index: 0 }],
|
|
105
|
-
} as DistantRecentAddressesState,
|
|
106
|
-
},
|
|
107
|
-
{
|
|
108
|
-
localData: {
|
|
109
|
-
ethereum: ["some random address", "some random address 2"],
|
|
110
|
-
} as RecentAddressesState,
|
|
111
|
-
latestState: {
|
|
112
|
-
ethereum: [
|
|
113
|
-
{ address: "some random address", index: 0 },
|
|
114
|
-
{ address: "some random address 2", index: 1 },
|
|
115
|
-
],
|
|
116
|
-
} as DistantRecentAddressesState,
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
localData: {
|
|
120
|
-
ethereum: ["some random address", "some random address 2"],
|
|
121
|
-
} as RecentAddressesState,
|
|
122
|
-
latestState: {
|
|
123
|
-
ethereum: [
|
|
124
|
-
{ address: "some random address 2", index: 1 },
|
|
125
|
-
{ address: "some random address", index: 0 },
|
|
126
|
-
],
|
|
127
|
-
} as DistantRecentAddressesState,
|
|
128
|
-
},
|
|
129
|
-
{
|
|
130
|
-
localData: {
|
|
131
|
-
ethereum: ["some random address"],
|
|
132
|
-
solana: ["some random address on Solana"],
|
|
133
|
-
} as RecentAddressesState,
|
|
134
|
-
latestState: {
|
|
135
|
-
ethereum: [{ address: "some random address", index: 0 }],
|
|
136
|
-
solana: [{ address: "some random address on Solana", index: 0 }],
|
|
137
|
-
} as DistantRecentAddressesState,
|
|
138
|
-
},
|
|
139
|
-
{
|
|
140
|
-
localData: {
|
|
141
|
-
ethereum: ["some random address", "some random address 2"],
|
|
142
|
-
solana: ["some random address on Solana"],
|
|
143
|
-
} as RecentAddressesState,
|
|
144
|
-
latestState: {
|
|
145
|
-
ethereum: [
|
|
146
|
-
{ address: "some random address", index: 0 },
|
|
147
|
-
{ address: "some random address 2", index: 1 },
|
|
148
|
-
],
|
|
149
|
-
solana: [{ address: "some random address on Solana", index: 0 }],
|
|
150
|
-
} as DistantRecentAddressesState,
|
|
151
|
-
},
|
|
152
|
-
{
|
|
153
|
-
localData: {
|
|
154
|
-
ethereum: ["some random address", "some random address 2"],
|
|
155
|
-
solana: ["some random address on Solana"],
|
|
156
|
-
} as RecentAddressesState,
|
|
157
|
-
latestState: {
|
|
158
|
-
ethereum: [
|
|
159
|
-
{ address: "some random address 2", index: 1 },
|
|
160
|
-
{ address: "some random address", index: 0 },
|
|
161
|
-
],
|
|
162
|
-
solana: [{ address: "some random address on Solana", index: 0 }],
|
|
163
|
-
} as DistantRecentAddressesState,
|
|
164
|
-
},
|
|
165
|
-
{
|
|
166
|
-
localData: {
|
|
167
|
-
ethereum: ["some random address", "some random address 2"],
|
|
168
|
-
solana: ["some random address on Solana", "some random address 2 on Solana"],
|
|
169
|
-
} as RecentAddressesState,
|
|
170
|
-
latestState: {
|
|
171
|
-
ethereum: [
|
|
172
|
-
{ address: "some random address", index: 0 },
|
|
173
|
-
{ address: "some random address 2", index: 1 },
|
|
174
|
-
],
|
|
175
|
-
solana: [
|
|
176
|
-
{ address: "some random address on Solana", index: 0 },
|
|
177
|
-
{ address: "some random address 2 on Solana", index: 1 },
|
|
178
|
-
],
|
|
179
|
-
} as DistantRecentAddressesState,
|
|
180
|
-
},
|
|
181
|
-
{
|
|
182
|
-
localData: {
|
|
183
|
-
ethereum: ["some random address", "some random address 2"],
|
|
184
|
-
solana: ["some random address on Solana", "some random address 2 on Solana"],
|
|
185
|
-
} as RecentAddressesState,
|
|
186
|
-
latestState: {
|
|
187
|
-
ethereum: [
|
|
188
|
-
{ address: "some random address", index: 0 },
|
|
189
|
-
{ address: "some random address 2", index: 1 },
|
|
190
|
-
],
|
|
191
|
-
solana: [
|
|
192
|
-
{ address: "some random address 2 on Solana", index: 1 },
|
|
193
|
-
{ address: "some random address on Solana", index: 0 },
|
|
194
|
-
],
|
|
195
|
-
} as DistantRecentAddressesState,
|
|
196
|
-
},
|
|
197
|
-
{
|
|
198
|
-
localData: {
|
|
199
|
-
ethereum: ["some random address", "some random address 2"],
|
|
200
|
-
solana: ["some random address on Solana", "some random address 2 on Solana"],
|
|
201
|
-
} as RecentAddressesState,
|
|
202
|
-
latestState: {
|
|
203
|
-
ethereum: [
|
|
204
|
-
{ address: "some random address 2", index: 1 },
|
|
205
|
-
{ address: "some random address", index: 0 },
|
|
206
|
-
],
|
|
207
|
-
solana: [
|
|
208
|
-
{ address: "some random address 2 on Solana", index: 1 },
|
|
209
|
-
{ address: "some random address on Solana", index: 0 },
|
|
210
|
-
],
|
|
211
|
-
} as DistantRecentAddressesState,
|
|
212
|
-
},
|
|
213
|
-
])(
|
|
214
|
-
"should return false when latest data and latest state have the same data #%#",
|
|
215
|
-
({ localData, latestState }) => {
|
|
216
|
-
const result = manager.diffLocalToDistant(localData, latestState);
|
|
217
|
-
expect(result).toEqual({
|
|
218
|
-
hasChanges: false,
|
|
219
|
-
nextState: latestState,
|
|
220
|
-
});
|
|
221
|
-
},
|
|
222
|
-
);
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
describe("resolveIncrementalUpdate", () => {
|
|
226
|
-
it("should return no changes when there is no incoming state #%#", async () => {
|
|
227
|
-
const result = await manager.resolveIncrementalUpdate(
|
|
228
|
-
{} as unknown as WalletSyncDataManagerResolutionContext,
|
|
229
|
-
{},
|
|
230
|
-
{},
|
|
231
|
-
undefined as unknown as DistantRecentAddressesState,
|
|
232
|
-
);
|
|
233
|
-
expect(result).toEqual({
|
|
234
|
-
hasChanges: false,
|
|
235
|
-
});
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
it.each([
|
|
239
|
-
[{} as DistantRecentAddressesState],
|
|
240
|
-
[{ ethereum: [{ address: "some random address", index: 0 }] } as DistantRecentAddressesState],
|
|
241
|
-
[
|
|
242
|
-
{
|
|
243
|
-
ethereum: [
|
|
244
|
-
{ address: "some random address", index: 0 },
|
|
245
|
-
{ address: "some random address 2", index: 1 },
|
|
246
|
-
],
|
|
247
|
-
} as DistantRecentAddressesState,
|
|
248
|
-
],
|
|
249
|
-
])(
|
|
250
|
-
"should return no changes when latest state and incoming state are the same",
|
|
251
|
-
async (state: DistantRecentAddressesState) => {
|
|
252
|
-
const result = await manager.resolveIncrementalUpdate(
|
|
253
|
-
{} as unknown as WalletSyncDataManagerResolutionContext,
|
|
254
|
-
{},
|
|
255
|
-
state,
|
|
256
|
-
state,
|
|
257
|
-
);
|
|
258
|
-
expect(result).toEqual({
|
|
259
|
-
hasChanges: false,
|
|
260
|
-
});
|
|
261
|
-
},
|
|
262
|
-
);
|
|
263
|
-
|
|
264
|
-
it.each([
|
|
265
|
-
{
|
|
266
|
-
localData: {} as RecentAddressesState,
|
|
267
|
-
incomingState: {} as DistantRecentAddressesState,
|
|
268
|
-
},
|
|
269
|
-
{
|
|
270
|
-
localData: { ethereum: ["some random address"] } as RecentAddressesState,
|
|
271
|
-
incomingState: {
|
|
272
|
-
ethereum: [{ address: "some random address", index: 0 }],
|
|
273
|
-
} as DistantRecentAddressesState,
|
|
274
|
-
},
|
|
275
|
-
{
|
|
276
|
-
localData: {
|
|
277
|
-
ethereum: ["some random address", "some random address 2"],
|
|
278
|
-
} as RecentAddressesState,
|
|
279
|
-
incomingState: {
|
|
280
|
-
ethereum: [
|
|
281
|
-
{ address: "some random address", index: 0 },
|
|
282
|
-
{ address: "some random address 2", index: 1 },
|
|
283
|
-
],
|
|
284
|
-
} as DistantRecentAddressesState,
|
|
285
|
-
},
|
|
286
|
-
{
|
|
287
|
-
localData: {
|
|
288
|
-
ethereum: ["some random address", "some random address 2"],
|
|
289
|
-
} as RecentAddressesState,
|
|
290
|
-
incomingState: {
|
|
291
|
-
ethereum: [
|
|
292
|
-
{ address: "some random address 2", index: 1 },
|
|
293
|
-
{ address: "some random address", index: 0 },
|
|
294
|
-
],
|
|
295
|
-
} as DistantRecentAddressesState,
|
|
296
|
-
},
|
|
297
|
-
{
|
|
298
|
-
localData: {
|
|
299
|
-
ethereum: ["some random address"],
|
|
300
|
-
solana: ["some random address on Solana"],
|
|
301
|
-
} as RecentAddressesState,
|
|
302
|
-
incomingState: {
|
|
303
|
-
ethereum: [{ address: "some random address", index: 0 }],
|
|
304
|
-
solana: [{ address: "some random address on Solana", index: 0 }],
|
|
305
|
-
} as DistantRecentAddressesState,
|
|
306
|
-
},
|
|
307
|
-
{
|
|
308
|
-
localData: {
|
|
309
|
-
ethereum: ["some random address", "some random address 2"],
|
|
310
|
-
solana: ["some random address on Solana"],
|
|
311
|
-
} as RecentAddressesState,
|
|
312
|
-
incomingState: {
|
|
313
|
-
ethereum: [
|
|
314
|
-
{ address: "some random address", index: 0 },
|
|
315
|
-
{ address: "some random address 2", index: 1 },
|
|
316
|
-
],
|
|
317
|
-
solana: [{ address: "some random address on Solana", index: 0 }],
|
|
318
|
-
} as DistantRecentAddressesState,
|
|
319
|
-
},
|
|
320
|
-
{
|
|
321
|
-
localData: {
|
|
322
|
-
ethereum: ["some random address", "some random address 2"],
|
|
323
|
-
solana: ["some random address on Solana"],
|
|
324
|
-
} as RecentAddressesState,
|
|
325
|
-
incomingState: {
|
|
326
|
-
ethereum: [
|
|
327
|
-
{ address: "some random address 2", index: 1 },
|
|
328
|
-
{ address: "some random address", index: 0 },
|
|
329
|
-
],
|
|
330
|
-
solana: [{ address: "some random address on Solana", index: 0 }],
|
|
331
|
-
} as DistantRecentAddressesState,
|
|
332
|
-
},
|
|
333
|
-
{
|
|
334
|
-
localData: {
|
|
335
|
-
ethereum: ["some random address", "some random address 2"],
|
|
336
|
-
solana: ["some random address on Solana", "some random address 2 on Solana"],
|
|
337
|
-
} as RecentAddressesState,
|
|
338
|
-
incomingState: {
|
|
339
|
-
ethereum: [
|
|
340
|
-
{ address: "some random address", index: 0 },
|
|
341
|
-
{ address: "some random address 2", index: 1 },
|
|
342
|
-
],
|
|
343
|
-
solana: [
|
|
344
|
-
{ address: "some random address on Solana", index: 0 },
|
|
345
|
-
{ address: "some random address 2 on Solana", index: 1 },
|
|
346
|
-
],
|
|
347
|
-
} as DistantRecentAddressesState,
|
|
348
|
-
},
|
|
349
|
-
{
|
|
350
|
-
localData: {
|
|
351
|
-
ethereum: ["some random address", "some random address 2"],
|
|
352
|
-
solana: ["some random address on Solana", "some random address 2 on Solana"],
|
|
353
|
-
} as RecentAddressesState,
|
|
354
|
-
incomingState: {
|
|
355
|
-
ethereum: [
|
|
356
|
-
{ address: "some random address", index: 0 },
|
|
357
|
-
{ address: "some random address 2", index: 1 },
|
|
358
|
-
],
|
|
359
|
-
solana: [
|
|
360
|
-
{ address: "some random address 2 on Solana", index: 1 },
|
|
361
|
-
{ address: "some random address on Solana", index: 0 },
|
|
362
|
-
],
|
|
363
|
-
} as DistantRecentAddressesState,
|
|
364
|
-
},
|
|
365
|
-
{
|
|
366
|
-
localData: {
|
|
367
|
-
ethereum: ["some random address", "some random address 2"],
|
|
368
|
-
solana: ["some random address on Solana", "some random address 2 on Solana"],
|
|
369
|
-
} as RecentAddressesState,
|
|
370
|
-
incomingState: {
|
|
371
|
-
ethereum: [
|
|
372
|
-
{ address: "some random address 2", index: 1 },
|
|
373
|
-
{ address: "some random address", index: 0 },
|
|
374
|
-
],
|
|
375
|
-
solana: [
|
|
376
|
-
{ address: "some random address 2 on Solana", index: 1 },
|
|
377
|
-
{ address: "some random address on Solana", index: 0 },
|
|
378
|
-
],
|
|
379
|
-
} as DistantRecentAddressesState,
|
|
380
|
-
},
|
|
381
|
-
])(
|
|
382
|
-
"should return no changes when local data and incoming state have the same data #%#",
|
|
383
|
-
async ({ localData, incomingState }) => {
|
|
384
|
-
const result = await manager.resolveIncrementalUpdate(
|
|
385
|
-
{} as unknown as WalletSyncDataManagerResolutionContext,
|
|
386
|
-
localData,
|
|
387
|
-
{},
|
|
388
|
-
incomingState,
|
|
389
|
-
);
|
|
390
|
-
expect(result).toEqual({
|
|
391
|
-
hasChanges: false,
|
|
392
|
-
});
|
|
393
|
-
},
|
|
394
|
-
);
|
|
395
|
-
|
|
396
|
-
it.each([
|
|
397
|
-
{
|
|
398
|
-
localData: {} as RecentAddressesState,
|
|
399
|
-
incomingState: {
|
|
400
|
-
ethereum: [{ address: "some random address", index: 0 }],
|
|
401
|
-
} as DistantRecentAddressesState,
|
|
402
|
-
},
|
|
403
|
-
{
|
|
404
|
-
localData: { ethereum: ["some random address"] } as RecentAddressesState,
|
|
405
|
-
incomingState: {
|
|
406
|
-
ethereum: [
|
|
407
|
-
{ address: "some random address", index: 0 },
|
|
408
|
-
{ address: "some random address 2", index: 1 },
|
|
409
|
-
],
|
|
410
|
-
} as DistantRecentAddressesState,
|
|
411
|
-
},
|
|
412
|
-
{
|
|
413
|
-
localData: {
|
|
414
|
-
ethereum: ["some random address"],
|
|
415
|
-
},
|
|
416
|
-
incomingState: {
|
|
417
|
-
ethereum: [{ address: "some random address", index: 0 }],
|
|
418
|
-
solana: [{ address: "some random address on Solana", index: 0 }],
|
|
419
|
-
} as DistantRecentAddressesState,
|
|
420
|
-
},
|
|
421
|
-
{
|
|
422
|
-
localData: {
|
|
423
|
-
ethereum: ["some random address"],
|
|
424
|
-
solana: ["some random address on Solana"],
|
|
425
|
-
},
|
|
426
|
-
incomingState: {
|
|
427
|
-
ethereum: [{ address: "some random address", index: 0 }],
|
|
428
|
-
solana: [
|
|
429
|
-
{ address: "some random address on Solana", index: 0 },
|
|
430
|
-
{ address: "some random address on Solana 2", index: 1 },
|
|
431
|
-
],
|
|
432
|
-
} as DistantRecentAddressesState,
|
|
433
|
-
},
|
|
434
|
-
{
|
|
435
|
-
localData: {
|
|
436
|
-
ethereum: ["some random address"],
|
|
437
|
-
solana: ["some random address on Solana"],
|
|
438
|
-
},
|
|
439
|
-
incomingState: {
|
|
440
|
-
ethereum: [
|
|
441
|
-
{ address: "some random address", index: 0 },
|
|
442
|
-
{ address: "some random address 2", index: 1 },
|
|
443
|
-
],
|
|
444
|
-
solana: [
|
|
445
|
-
{ address: "some random address on Solana", index: 0 },
|
|
446
|
-
{ address: "some random address on Solana 2", index: 1 },
|
|
447
|
-
],
|
|
448
|
-
} as DistantRecentAddressesState,
|
|
449
|
-
},
|
|
450
|
-
])(
|
|
451
|
-
"should return changes present local data is different from incoming state #%#",
|
|
452
|
-
async ({ localData, incomingState }) => {
|
|
453
|
-
const result = await manager.resolveIncrementalUpdate(
|
|
454
|
-
{} as unknown as WalletSyncDataManagerResolutionContext,
|
|
455
|
-
localData,
|
|
456
|
-
{},
|
|
457
|
-
incomingState,
|
|
458
|
-
);
|
|
459
|
-
|
|
460
|
-
const update: RecentAddressesState = {};
|
|
461
|
-
Object.keys(incomingState).forEach(key => {
|
|
462
|
-
update[key] = incomingState[key]
|
|
463
|
-
.sort((current, other) => current.index - other.index)
|
|
464
|
-
.map(data => data.address);
|
|
465
|
-
});
|
|
466
|
-
|
|
467
|
-
expect(result).toEqual({
|
|
468
|
-
hasChanges: true,
|
|
469
|
-
update,
|
|
470
|
-
});
|
|
471
|
-
},
|
|
472
|
-
);
|
|
473
|
-
});
|
|
474
|
-
|
|
475
|
-
describe("applyUpdate", () => {
|
|
476
|
-
it.each([
|
|
477
|
-
[{}],
|
|
478
|
-
[{ ethereum: ["some random address"] }],
|
|
479
|
-
[{ ethereum: ["some random address", "some random address 2"] }],
|
|
480
|
-
])("should return updated data #%#", (update: RecentAddressesState) => {
|
|
481
|
-
const result = manager.applyUpdate({}, update);
|
|
482
|
-
expect(result).toEqual(update);
|
|
483
|
-
});
|
|
484
|
-
});
|
|
485
|
-
});
|
|
486
|
-
|
|
487
|
-
//sameDistantState x 558,365 ops/sec ±1.50% (96 runs sampled)
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module recentAddresses
|
|
3
|
-
*
|
|
4
|
-
* This module is responsible for synchronizing recent addresses across Wallet instances
|
|
5
|
-
* in the WalletSync system. It manages an ordered list of recently used addresses,
|
|
6
|
-
* ensuring that when a user accesses an address on one Live instance, that address
|
|
7
|
-
* (and its position in the recent list) is propagated to all other synchronized Live instances.
|
|
8
|
-
*
|
|
9
|
-
* Recent addresses are off-chain data (not stored on the blockchain), and therefore need to
|
|
10
|
-
* be synchronized through the WalletSync system to ensure consistency across all Live instances.
|
|
11
|
-
*
|
|
12
|
-
* Key responsibilities:
|
|
13
|
-
* - Tracks local recent address changes and prepares them for synchronization
|
|
14
|
-
* - Resolves incoming recent address updates from other Live instances
|
|
15
|
-
* - Maintains the order/index of addresses in the recent list
|
|
16
|
-
* - Handles conflict resolution by accepting incoming state changes (last-write-wins strategy)
|
|
17
|
-
* - Maintains consistency between local state (string[]) and distant state (RecentAddressesState[])
|
|
18
|
-
*
|
|
19
|
-
* The module preserves the index/position of each address, allowing the UI to maintain
|
|
20
|
-
* a consistent ordering of recently used addresses across all synchronized Live instances.
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
import { z } from "zod";
|
|
24
|
-
import { WalletSyncDataManager } from "../types";
|
|
25
|
-
import { RecentAddressesState } from "@ledgerhq/types-live";
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* We dont use the same data structure for remote state
|
|
29
|
-
* An index attribute has been added to keep the order (recomputed locally)
|
|
30
|
-
*/
|
|
31
|
-
export type DistantRecentAddressesState = Record<
|
|
32
|
-
string,
|
|
33
|
-
{
|
|
34
|
-
address: string;
|
|
35
|
-
index: number;
|
|
36
|
-
}[]
|
|
37
|
-
>;
|
|
38
|
-
|
|
39
|
-
export function toDistantState(
|
|
40
|
-
addressesByCurrency: RecentAddressesState,
|
|
41
|
-
): DistantRecentAddressesState {
|
|
42
|
-
const state: DistantRecentAddressesState = {};
|
|
43
|
-
Object.keys(addressesByCurrency).forEach(key => {
|
|
44
|
-
state[key] = addressesByCurrency[key].map((address, index) => ({ address, index }));
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
return state;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export function toState(addressesByCurrency: DistantRecentAddressesState): RecentAddressesState {
|
|
51
|
-
const state: RecentAddressesState = {};
|
|
52
|
-
Object.keys(addressesByCurrency).forEach(key => {
|
|
53
|
-
state[key] = addressesByCurrency[key]
|
|
54
|
-
.sort((current, other) => current.index - other.index)
|
|
55
|
-
.map(data => data.address);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
return state;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function sameDistantState(
|
|
62
|
-
localData: RecentAddressesState,
|
|
63
|
-
distantState: DistantRecentAddressesState,
|
|
64
|
-
) {
|
|
65
|
-
const localDataKeys = Object.keys(localData);
|
|
66
|
-
const distantStateKeys = Object.keys(distantState);
|
|
67
|
-
return (
|
|
68
|
-
localDataKeys.length === distantStateKeys.length &&
|
|
69
|
-
distantStateKeys.every(key => {
|
|
70
|
-
return (
|
|
71
|
-
localData[key] &&
|
|
72
|
-
localData[key].length === distantState[key].length &&
|
|
73
|
-
!distantState[key].some(
|
|
74
|
-
data =>
|
|
75
|
-
data.index < 0 ||
|
|
76
|
-
data.index >= localData[key].length ||
|
|
77
|
-
localData[key][data.index] !== data.address,
|
|
78
|
-
)
|
|
79
|
-
);
|
|
80
|
-
})
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const recentAddressesSchema = z.object({
|
|
85
|
-
address: z.string(),
|
|
86
|
-
index: z.number(),
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
const schema = z.record(z.string(), z.array(recentAddressesSchema));
|
|
90
|
-
|
|
91
|
-
const manager: WalletSyncDataManager<RecentAddressesState, RecentAddressesState, typeof schema> = {
|
|
92
|
-
schema,
|
|
93
|
-
diffLocalToDistant(localData, latestState) {
|
|
94
|
-
if (!sameDistantState(localData, latestState ?? {})) {
|
|
95
|
-
return {
|
|
96
|
-
hasChanges: true,
|
|
97
|
-
nextState: toDistantState(localData),
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
return {
|
|
102
|
-
hasChanges: false,
|
|
103
|
-
nextState: latestState ?? {},
|
|
104
|
-
};
|
|
105
|
-
},
|
|
106
|
-
async resolveIncrementalUpdate(_ctx, localData, latestState, incomingState) {
|
|
107
|
-
if (!incomingState) {
|
|
108
|
-
return { hasChanges: false };
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
if (latestState === incomingState || sameDistantState(localData, incomingState)) {
|
|
112
|
-
return { hasChanges: false };
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
return {
|
|
116
|
-
hasChanges: true,
|
|
117
|
-
update: toState(incomingState),
|
|
118
|
-
};
|
|
119
|
-
},
|
|
120
|
-
applyUpdate(_localData, update) {
|
|
121
|
-
return update;
|
|
122
|
-
},
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
export default manager;
|