@ledgerhq/live-common 34.55.0-nightly.20251219024040 → 34.55.0-nightly.20251223024125
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/lib/account/recentAddresses.d.ts +2 -1
- package/lib/account/recentAddresses.d.ts.map +1 -1
- package/lib/account/recentAddresses.js +27 -9
- package/lib/account/recentAddresses.js.map +1 -1
- package/lib/e2e/enum/Provider.d.ts.map +1 -1
- package/lib/e2e/enum/Provider.js +3 -1
- package/lib/e2e/enum/Provider.js.map +1 -1
- package/lib/exchange/providers/swap.d.ts.map +1 -1
- package/lib/exchange/providers/swap.js +2 -0
- package/lib/exchange/providers/swap.js.map +1 -1
- package/lib/families/canton/react.d.ts.map +1 -1
- package/lib/families/canton/react.js +11 -9
- package/lib/families/canton/react.js.map +1 -1
- package/lib-es/account/recentAddresses.d.ts +2 -1
- package/lib-es/account/recentAddresses.d.ts.map +1 -1
- package/lib-es/account/recentAddresses.js +27 -9
- package/lib-es/account/recentAddresses.js.map +1 -1
- package/lib-es/e2e/enum/Provider.d.ts.map +1 -1
- package/lib-es/e2e/enum/Provider.js +3 -1
- package/lib-es/e2e/enum/Provider.js.map +1 -1
- package/lib-es/exchange/providers/swap.d.ts.map +1 -1
- package/lib-es/exchange/providers/swap.js +2 -0
- package/lib-es/exchange/providers/swap.js.map +1 -1
- package/lib-es/families/canton/react.d.ts.map +1 -1
- package/lib-es/families/canton/react.js +11 -9
- package/lib-es/families/canton/react.js.map +1 -1
- package/package.json +75 -75
- package/src/account/recentAddresses.test.ts +115 -15
- package/src/account/recentAddresses.ts +37 -13
- package/src/e2e/enum/Provider.ts +3 -1
- package/src/exchange/providers/swap.ts +2 -0
- package/src/families/canton/react.test.ts +24 -20
- package/src/families/canton/react.ts +12 -7
- package/src/families/hedera/__snapshots__/bridge.integration.test.ts.snap +758 -34
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ledgerhq/live-common",
|
|
3
3
|
"description": "Common ground for the Ledger Live apps",
|
|
4
|
-
"version": "34.55.0-nightly.
|
|
4
|
+
"version": "34.55.0-nightly.20251223024125",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "https://github.com/LedgerHQ/ledger-live.git"
|
|
@@ -145,7 +145,7 @@
|
|
|
145
145
|
"@zondax/ledger-mina-js": "0.0.2",
|
|
146
146
|
"@zondax/ledger-stacks": "^1.0.2",
|
|
147
147
|
"async": "^3.2.3",
|
|
148
|
-
"axios": "1.
|
|
148
|
+
"axios": "1.13.2",
|
|
149
149
|
"bech32": "^1.1.3",
|
|
150
150
|
"bignumber.js": "^9.1.2",
|
|
151
151
|
"bip32": "^2.0.6",
|
|
@@ -178,79 +178,79 @@
|
|
|
178
178
|
"xstate": "^5.19.2",
|
|
179
179
|
"yargs": "^17.0.0",
|
|
180
180
|
"zod": "^3.22.4",
|
|
181
|
-
"@ledgerhq/coin-algorand": "^0.15.0-nightly.
|
|
182
|
-
"@ledgerhq/coin-aptos": "^3.8.0-nightly.
|
|
183
|
-
"@ledgerhq/coin-bitcoin": "^0.27.0-nightly.
|
|
184
|
-
"@ledgerhq/coin-
|
|
185
|
-
"@ledgerhq/coin-
|
|
186
|
-
"@ledgerhq/coin-
|
|
187
|
-
"@ledgerhq/coin-
|
|
188
|
-
"@ledgerhq/coin-
|
|
189
|
-
"@ledgerhq/coin-evm": "^2.37.0-nightly.
|
|
190
|
-
"@ledgerhq/coin-filecoin": "^1.16.0-nightly.
|
|
191
|
-
"@ledgerhq/coin-framework": "^6.11.0-nightly.
|
|
192
|
-
"@ledgerhq/coin-hedera": "^1.16.0-nightly.
|
|
193
|
-
"@ledgerhq/coin-icon": "^0.16.0-nightly.
|
|
194
|
-
"@ledgerhq/coin-internet_computer": "^1.12.0-nightly.
|
|
195
|
-
"@ledgerhq/coin-
|
|
196
|
-
"@ledgerhq/coin-
|
|
197
|
-
"@ledgerhq/coin-multiversx": "^0.9.0-nightly.
|
|
198
|
-
"@ledgerhq/coin-
|
|
199
|
-
"@ledgerhq/coin-
|
|
200
|
-
"@ledgerhq/coin-
|
|
201
|
-
"@ledgerhq/coin-stacks": "^0.13.0-nightly.
|
|
202
|
-
"@ledgerhq/coin-stellar": "^6.9.0-nightly.
|
|
203
|
-
"@ledgerhq/coin-
|
|
204
|
-
"@ledgerhq/coin-
|
|
205
|
-
"@ledgerhq/coin-ton": "^0.18.0-nightly.
|
|
206
|
-
"@ledgerhq/coin-tron": "^5.8.0-nightly.
|
|
207
|
-
"@ledgerhq/coin-vechain": "^2.14.0-nightly.
|
|
208
|
-
"@ledgerhq/coin-xrp": "^7.10.0-nightly.
|
|
209
|
-
"@ledgerhq/cryptoassets": "^13.35.0-nightly.
|
|
210
|
-
"@ledgerhq/device-core": "^0.6.11-nightly.
|
|
211
|
-
"@ledgerhq/devices": "8.8.0-nightly.
|
|
212
|
-
"@ledgerhq/errors": "^6.28.0-nightly.
|
|
213
|
-
"@ledgerhq/hw-app-algorand": "^6.31.11-nightly.
|
|
214
|
-
"@ledgerhq/hw-app-aptos": "^6.34.11-nightly.
|
|
215
|
-
"@ledgerhq/hw-app-btc": "^10.14.0-nightly.
|
|
216
|
-
"@ledgerhq/hw-app-celo": "^6.35.6-nightly.
|
|
217
|
-
"@ledgerhq/hw-app-
|
|
218
|
-
"@ledgerhq/hw-app-
|
|
219
|
-
"@ledgerhq/hw-app-exchange": "^0.18.2-nightly.
|
|
220
|
-
"@ledgerhq/hw-app-hedera": "^1.2.11-nightly.
|
|
221
|
-
"@ledgerhq/hw-app-icon": "^1.3.11-nightly.
|
|
222
|
-
"@ledgerhq/hw-app-kaspa": "^1.3.4-nightly.
|
|
223
|
-
"@ledgerhq/hw-app-multiversx": "^6.26.2-nightly.
|
|
224
|
-
"@ledgerhq/hw-app-near": "^6.31.11-nightly.
|
|
225
|
-
"@ledgerhq/hw-app-polkadot": "^6.34.11-nightly.
|
|
226
|
-
"@ledgerhq/hw-app-str": "^7.3.0-nightly.
|
|
181
|
+
"@ledgerhq/coin-algorand": "^0.15.0-nightly.20251223024125",
|
|
182
|
+
"@ledgerhq/coin-aptos": "^3.8.0-nightly.20251223024125",
|
|
183
|
+
"@ledgerhq/coin-bitcoin": "^0.27.0-nightly.20251223024125",
|
|
184
|
+
"@ledgerhq/coin-canton": "^0.12.0-nightly.20251223024125",
|
|
185
|
+
"@ledgerhq/coin-cardano": "^0.16.0-nightly.20251223024125",
|
|
186
|
+
"@ledgerhq/coin-casper": "^2.5.0-nightly.20251223024125",
|
|
187
|
+
"@ledgerhq/coin-celo": "^1.8.0-nightly.20251223024125",
|
|
188
|
+
"@ledgerhq/coin-cosmos": "^0.21.0-nightly.20251223024125",
|
|
189
|
+
"@ledgerhq/coin-evm": "^2.37.0-nightly.20251223024125",
|
|
190
|
+
"@ledgerhq/coin-filecoin": "^1.16.0-nightly.20251223024125",
|
|
191
|
+
"@ledgerhq/coin-framework": "^6.11.0-nightly.20251223024125",
|
|
192
|
+
"@ledgerhq/coin-hedera": "^1.16.0-nightly.20251223024125",
|
|
193
|
+
"@ledgerhq/coin-icon": "^0.16.0-nightly.20251223024125",
|
|
194
|
+
"@ledgerhq/coin-internet_computer": "^1.12.0-nightly.20251223024125",
|
|
195
|
+
"@ledgerhq/coin-kaspa": "^1.6.0-nightly.20251223024125",
|
|
196
|
+
"@ledgerhq/coin-mina": "^1.5.0-nightly.20251223024125",
|
|
197
|
+
"@ledgerhq/coin-multiversx": "^0.9.0-nightly.20251223024125",
|
|
198
|
+
"@ledgerhq/coin-near": "^0.17.0-nightly.20251223024125",
|
|
199
|
+
"@ledgerhq/coin-polkadot": "^6.14.0-nightly.20251223024125",
|
|
200
|
+
"@ledgerhq/coin-solana": "^0.39.0-nightly.20251223024125",
|
|
201
|
+
"@ledgerhq/coin-stacks": "^0.13.0-nightly.20251223024125",
|
|
202
|
+
"@ledgerhq/coin-stellar": "^6.9.0-nightly.20251223024125",
|
|
203
|
+
"@ledgerhq/coin-sui": "^0.19.0-nightly.20251223024125",
|
|
204
|
+
"@ledgerhq/coin-tezos": "^6.11.0-nightly.20251223024125",
|
|
205
|
+
"@ledgerhq/coin-ton": "^0.18.0-nightly.20251223024125",
|
|
206
|
+
"@ledgerhq/coin-tron": "^5.8.0-nightly.20251223024125",
|
|
207
|
+
"@ledgerhq/coin-vechain": "^2.14.0-nightly.20251223024125",
|
|
208
|
+
"@ledgerhq/coin-xrp": "^7.10.0-nightly.20251223024125",
|
|
209
|
+
"@ledgerhq/cryptoassets": "^13.35.0-nightly.20251223024125",
|
|
210
|
+
"@ledgerhq/device-core": "^0.6.11-nightly.20251223024125",
|
|
211
|
+
"@ledgerhq/devices": "8.8.0-nightly.20251223024125",
|
|
212
|
+
"@ledgerhq/errors": "^6.28.0-nightly.20251223024125",
|
|
213
|
+
"@ledgerhq/hw-app-algorand": "^6.31.11-nightly.20251223024125",
|
|
214
|
+
"@ledgerhq/hw-app-aptos": "^6.34.11-nightly.20251223024125",
|
|
215
|
+
"@ledgerhq/hw-app-btc": "^10.14.0-nightly.20251223024125",
|
|
216
|
+
"@ledgerhq/hw-app-celo": "^6.35.6-nightly.20251223024125",
|
|
217
|
+
"@ledgerhq/hw-app-cosmos": "^6.32.11-nightly.20251223024125",
|
|
218
|
+
"@ledgerhq/hw-app-eth": "^7.1.0-nightly.20251223024125",
|
|
219
|
+
"@ledgerhq/hw-app-exchange": "^0.18.2-nightly.20251223024125",
|
|
220
|
+
"@ledgerhq/hw-app-hedera": "^1.2.11-nightly.20251223024125",
|
|
221
|
+
"@ledgerhq/hw-app-icon": "^1.3.11-nightly.20251223024125",
|
|
222
|
+
"@ledgerhq/hw-app-kaspa": "^1.3.4-nightly.20251223024125",
|
|
223
|
+
"@ledgerhq/hw-app-multiversx": "^6.26.2-nightly.20251223024125",
|
|
224
|
+
"@ledgerhq/hw-app-near": "^6.31.11-nightly.20251223024125",
|
|
225
|
+
"@ledgerhq/hw-app-polkadot": "^6.34.11-nightly.20251223024125",
|
|
226
|
+
"@ledgerhq/hw-app-str": "^7.3.0-nightly.20251223024125",
|
|
227
227
|
"@ledgerhq/hw-app-sui": "^1.4.0",
|
|
228
|
-
"@ledgerhq/hw-app-tezos": "^6.31.11-nightly.
|
|
229
|
-
"@ledgerhq/hw-app-trx": "^6.31.11-nightly.
|
|
230
|
-
"@ledgerhq/hw-app-vet": "^0.8.2-nightly.
|
|
231
|
-
"@ledgerhq/hw-
|
|
232
|
-
"@ledgerhq/hw-
|
|
233
|
-
"@ledgerhq/hw-transport": "6.31.15-nightly.
|
|
234
|
-
"@ledgerhq/hw-
|
|
235
|
-
"@ledgerhq/client-ids": "^0.2.0-nightly.
|
|
236
|
-
"@ledgerhq/ledger-cal-service": "^1.9.3-nightly.
|
|
237
|
-
"@ledgerhq/
|
|
238
|
-
"@ledgerhq/
|
|
239
|
-
"@ledgerhq/live-countervalues": "^0.10.3-nightly.
|
|
240
|
-
"@ledgerhq/live-countervalues-react": "^0.7.5-nightly.
|
|
241
|
-
"@ledgerhq/live-dmk-shared": "^0.16.0-nightly.
|
|
242
|
-
"@ledgerhq/live-env": "^2.23.0-nightly.
|
|
243
|
-
"@ledgerhq/live-hooks": "0.3.0-nightly.
|
|
244
|
-
"@ledgerhq/live-network": "^2.1.4-nightly.
|
|
228
|
+
"@ledgerhq/hw-app-tezos": "^6.31.11-nightly.20251223024125",
|
|
229
|
+
"@ledgerhq/hw-app-trx": "^6.31.11-nightly.20251223024125",
|
|
230
|
+
"@ledgerhq/hw-app-vet": "^0.8.2-nightly.20251223024125",
|
|
231
|
+
"@ledgerhq/hw-app-xrp": "^6.32.9-nightly.20251223024125",
|
|
232
|
+
"@ledgerhq/hw-bolos": "^6.32.11-nightly.20251223024125",
|
|
233
|
+
"@ledgerhq/hw-transport": "6.31.15-nightly.20251223024125",
|
|
234
|
+
"@ledgerhq/hw-transport-mocker": "^6.30.0-nightly.20251223024125",
|
|
235
|
+
"@ledgerhq/client-ids": "^0.2.0-nightly.20251223024125",
|
|
236
|
+
"@ledgerhq/ledger-cal-service": "^1.9.3-nightly.20251223024125",
|
|
237
|
+
"@ledgerhq/ledger-trust-service": "^0.4.5-nightly.20251223024125",
|
|
238
|
+
"@ledgerhq/live-config": "^3.3.0-nightly.20251223024125",
|
|
239
|
+
"@ledgerhq/live-countervalues": "^0.10.3-nightly.20251223024125",
|
|
240
|
+
"@ledgerhq/live-countervalues-react": "^0.7.5-nightly.20251223024125",
|
|
241
|
+
"@ledgerhq/live-dmk-shared": "^0.16.0-nightly.20251223024125",
|
|
242
|
+
"@ledgerhq/live-env": "^2.23.0-nightly.20251223024125",
|
|
243
|
+
"@ledgerhq/live-hooks": "0.3.0-nightly.20251223024125",
|
|
244
|
+
"@ledgerhq/live-network": "^2.1.4-nightly.20251223024125",
|
|
245
245
|
"@ledgerhq/live-promise": "^0.1.1",
|
|
246
|
-
"@ledgerhq/live-signer-
|
|
247
|
-
"@ledgerhq/live-signer-
|
|
248
|
-
"@ledgerhq/live-signer-solana": "^0.8.0-nightly.
|
|
249
|
-
"@ledgerhq/live-wallet": "^0.17.0-nightly.
|
|
246
|
+
"@ledgerhq/live-signer-canton": "^0.5.4-nightly.20251223024125",
|
|
247
|
+
"@ledgerhq/live-signer-evm": "^0.11.0-nightly.20251223024125",
|
|
248
|
+
"@ledgerhq/live-signer-solana": "^0.8.0-nightly.20251223024125",
|
|
249
|
+
"@ledgerhq/live-wallet": "^0.17.0-nightly.20251223024125",
|
|
250
250
|
"@ledgerhq/logs": "^6.13.0",
|
|
251
|
-
"@ledgerhq/speculos-transport": "^0.4.0-nightly.
|
|
252
|
-
"@ledgerhq/wallet-api-acre-module": "^0.11.0-nightly.
|
|
253
|
-
"@ledgerhq/wallet-api-exchange-module": "^0.20.0-nightly.
|
|
251
|
+
"@ledgerhq/speculos-transport": "^0.4.0-nightly.20251223024125",
|
|
252
|
+
"@ledgerhq/wallet-api-acre-module": "^0.11.0-nightly.20251223024125",
|
|
253
|
+
"@ledgerhq/wallet-api-exchange-module": "^0.20.0-nightly.20251223024125"
|
|
254
254
|
},
|
|
255
255
|
"devDependencies": {
|
|
256
256
|
"@solana/web3.js": "1.95.4",
|
|
@@ -297,10 +297,10 @@
|
|
|
297
297
|
"undici": "6.19.2",
|
|
298
298
|
"uuid": "^8.3.2",
|
|
299
299
|
"ws": "8.18.3",
|
|
300
|
-
"@ledgerhq/device-react": "^0.3.5-nightly.
|
|
301
|
-
"@ledgerhq/types-cryptoassets": "^7.31.0-nightly.
|
|
300
|
+
"@ledgerhq/device-react": "^0.3.5-nightly.20251223024125",
|
|
301
|
+
"@ledgerhq/types-cryptoassets": "^7.31.0-nightly.20251223024125",
|
|
302
302
|
"@ledgerhq/types-devices": "^6.27.0",
|
|
303
|
-
"@ledgerhq/types-live": "^6.91.0-nightly.
|
|
303
|
+
"@ledgerhq/types-live": "^6.91.0-nightly.20251223024125"
|
|
304
304
|
},
|
|
305
305
|
"scripts": {
|
|
306
306
|
"build": "zx ./scripts/build-ts.mjs",
|
|
@@ -17,7 +17,13 @@ describe("RecentAddressesStore", () => {
|
|
|
17
17
|
const addresses = store.getAddresses("ethereum");
|
|
18
18
|
expect(addresses).toEqual([newAddress]);
|
|
19
19
|
expect(onAddAddressCompleteMock).toHaveBeenCalledTimes(1);
|
|
20
|
-
expect(onAddAddressCompleteMock).toHaveBeenCalledWith({
|
|
20
|
+
expect(onAddAddressCompleteMock).toHaveBeenCalledWith({
|
|
21
|
+
ethereum: [
|
|
22
|
+
expect.objectContaining({
|
|
23
|
+
address: newAddress,
|
|
24
|
+
}),
|
|
25
|
+
],
|
|
26
|
+
});
|
|
21
27
|
});
|
|
22
28
|
|
|
23
29
|
it("should add a second address and return addresses sorted by insertion", async () => {
|
|
@@ -26,14 +32,21 @@ describe("RecentAddressesStore", () => {
|
|
|
26
32
|
let addresses = store.getAddresses("ethereum");
|
|
27
33
|
expect(addresses).toEqual([newAddress]);
|
|
28
34
|
expect(onAddAddressCompleteMock).toHaveBeenCalledTimes(1);
|
|
29
|
-
expect(onAddAddressCompleteMock).toHaveBeenCalledWith({
|
|
35
|
+
expect(onAddAddressCompleteMock).toHaveBeenCalledWith({
|
|
36
|
+
ethereum: [expect.objectContaining({ address: newAddress })],
|
|
37
|
+
});
|
|
30
38
|
|
|
31
39
|
const newAddress2 = "0xB69B37A4Fb4A18b3258f974ff6e9f529AD2647b1";
|
|
32
40
|
await store.addAddress("ethereum", newAddress2);
|
|
33
41
|
addresses = store.getAddresses("ethereum");
|
|
34
42
|
expect(addresses).toEqual([newAddress2, newAddress]);
|
|
35
43
|
expect(onAddAddressCompleteMock).toHaveBeenCalledTimes(2);
|
|
36
|
-
expect(onAddAddressCompleteMock).toHaveBeenCalledWith({
|
|
44
|
+
expect(onAddAddressCompleteMock).toHaveBeenCalledWith({
|
|
45
|
+
ethereum: [
|
|
46
|
+
expect.objectContaining({ address: newAddress2 }),
|
|
47
|
+
expect.objectContaining({ address: newAddress }),
|
|
48
|
+
],
|
|
49
|
+
});
|
|
37
50
|
});
|
|
38
51
|
|
|
39
52
|
it("should replace at first place when an address is already saved", async () => {
|
|
@@ -42,43 +55,61 @@ describe("RecentAddressesStore", () => {
|
|
|
42
55
|
let addresses = store.getAddresses("ethereum");
|
|
43
56
|
expect(addresses).toEqual([newAddress]);
|
|
44
57
|
expect(onAddAddressCompleteMock).toHaveBeenCalledTimes(1);
|
|
45
|
-
expect(onAddAddressCompleteMock).toHaveBeenCalledWith({
|
|
58
|
+
expect(onAddAddressCompleteMock).toHaveBeenCalledWith({
|
|
59
|
+
ethereum: [expect.objectContaining({ address: newAddress })],
|
|
60
|
+
});
|
|
46
61
|
|
|
47
62
|
const newAddress2 = "0xB69B37A4Fb4A18b3258f974ff6e9f529AD2647b1";
|
|
48
63
|
await store.addAddress("ethereum", newAddress2);
|
|
49
64
|
addresses = store.getAddresses("ethereum");
|
|
50
65
|
expect(addresses).toEqual([newAddress2, newAddress]);
|
|
51
66
|
expect(onAddAddressCompleteMock).toHaveBeenCalledTimes(2);
|
|
52
|
-
expect(onAddAddressCompleteMock).toHaveBeenCalledWith({
|
|
67
|
+
expect(onAddAddressCompleteMock).toHaveBeenCalledWith({
|
|
68
|
+
ethereum: [
|
|
69
|
+
expect.objectContaining({ address: newAddress2 }),
|
|
70
|
+
expect.objectContaining({ address: newAddress }),
|
|
71
|
+
],
|
|
72
|
+
});
|
|
53
73
|
|
|
54
74
|
await store.addAddress("ethereum", newAddress);
|
|
55
75
|
addresses = store.getAddresses("ethereum");
|
|
56
76
|
expect(addresses).toEqual([newAddress, newAddress2]);
|
|
57
77
|
expect(onAddAddressCompleteMock).toHaveBeenCalledTimes(3);
|
|
58
|
-
expect(onAddAddressCompleteMock).toHaveBeenCalledWith({
|
|
78
|
+
expect(onAddAddressCompleteMock).toHaveBeenCalledWith({
|
|
79
|
+
ethereum: [
|
|
80
|
+
expect.objectContaining({ address: newAddress }),
|
|
81
|
+
expect.objectContaining({ address: newAddress2 }),
|
|
82
|
+
],
|
|
83
|
+
});
|
|
59
84
|
});
|
|
60
85
|
|
|
61
86
|
it("should replace at first place and remove last element when addresses exceed count limit", async () => {
|
|
62
|
-
|
|
87
|
+
const expectedAddresses: string[] = [];
|
|
88
|
+
const expectedObjects: any[] = [];
|
|
63
89
|
for (let index = 0; index < RECENT_ADDRESSES_COUNT_LIMIT; index++) {
|
|
64
|
-
|
|
65
|
-
|
|
90
|
+
const addr = `0x66c4371aE8FFeD2ec1c2EBbbcCfb7E494181E1E3${index}`;
|
|
91
|
+
await store.addAddress("ethereum", addr);
|
|
92
|
+
expectedAddresses.unshift(addr);
|
|
93
|
+
expectedObjects.unshift(expect.objectContaining({ address: addr }));
|
|
66
94
|
}
|
|
67
95
|
|
|
68
96
|
let addresses = store.getAddresses("ethereum");
|
|
69
97
|
expect(addresses).toEqual(expectedAddresses);
|
|
70
98
|
expect(onAddAddressCompleteMock).toHaveBeenCalledTimes(RECENT_ADDRESSES_COUNT_LIMIT);
|
|
71
|
-
expect(onAddAddressCompleteMock).toHaveBeenCalledWith({ ethereum:
|
|
99
|
+
expect(onAddAddressCompleteMock).toHaveBeenCalledWith({ ethereum: expectedObjects });
|
|
72
100
|
|
|
73
101
|
const newAddress2 = "0xB69B37A4Fb4A18b3258f974ff6e9f529AD2647b1";
|
|
74
102
|
expectedAddresses.splice(expectedAddresses.length - 1, 1);
|
|
75
|
-
expectedAddresses
|
|
103
|
+
expectedAddresses.unshift(newAddress2);
|
|
104
|
+
|
|
105
|
+
expectedObjects.splice(expectedObjects.length - 1, 1);
|
|
106
|
+
expectedObjects.unshift(expect.objectContaining({ address: newAddress2 }));
|
|
76
107
|
|
|
77
108
|
await store.addAddress("ethereum", newAddress2);
|
|
78
109
|
addresses = store.getAddresses("ethereum");
|
|
79
110
|
expect(addresses).toEqual(expectedAddresses);
|
|
80
111
|
expect(onAddAddressCompleteMock).toHaveBeenCalledTimes(RECENT_ADDRESSES_COUNT_LIMIT + 1);
|
|
81
|
-
expect(onAddAddressCompleteMock).toHaveBeenCalledWith({ ethereum:
|
|
112
|
+
expect(onAddAddressCompleteMock).toHaveBeenCalledWith({ ethereum: expectedObjects });
|
|
82
113
|
});
|
|
83
114
|
|
|
84
115
|
it("should add an address of a different currency", async () => {
|
|
@@ -88,7 +119,9 @@ describe("RecentAddressesStore", () => {
|
|
|
88
119
|
let addresses = store.getAddresses("ethereum");
|
|
89
120
|
expect(addresses).toEqual([newAddress]);
|
|
90
121
|
expect(onAddAddressCompleteMock).toHaveBeenCalledTimes(1);
|
|
91
|
-
expect(onAddAddressCompleteMock).toHaveBeenCalledWith({
|
|
122
|
+
expect(onAddAddressCompleteMock).toHaveBeenCalledWith({
|
|
123
|
+
ethereum: [expect.objectContaining({ address: newAddress })],
|
|
124
|
+
});
|
|
92
125
|
|
|
93
126
|
const newAddress2 = "bc1pxlmrudqyq8qd8pfsc4mpmlaw56x6vtcr9m8nvp8kj3gckefc4kmqhkg4l7";
|
|
94
127
|
await store.addAddress("bitcoin", newAddress2);
|
|
@@ -97,8 +130,75 @@ describe("RecentAddressesStore", () => {
|
|
|
97
130
|
expect(addresses).toEqual([newAddress2]);
|
|
98
131
|
expect(onAddAddressCompleteMock).toHaveBeenCalledTimes(2);
|
|
99
132
|
expect(onAddAddressCompleteMock).toHaveBeenCalledWith({
|
|
100
|
-
ethereum: [newAddress],
|
|
101
|
-
bitcoin: [newAddress2],
|
|
133
|
+
ethereum: [expect.objectContaining({ address: newAddress })],
|
|
134
|
+
bitcoin: [expect.objectContaining({ address: newAddress2 })],
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it("should update timestamp and move to top when re-adding an existing address", async () => {
|
|
139
|
+
const address1 = "0x66c4371aE8FFeD2ec1c2EBbbcCfb7E494181E1E3";
|
|
140
|
+
const address2 = "0xB69B37A4Fb4A18b3258f974ff6e9f529AD2647b1";
|
|
141
|
+
const address3 = "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0";
|
|
142
|
+
|
|
143
|
+
const now = Date.now();
|
|
144
|
+
const oneYear = 365 * 24 * 60 * 60 * 1000;
|
|
145
|
+
const threeYearsAgo = now - 3 * oneYear;
|
|
146
|
+
const oneYearAgo = now - oneYear;
|
|
147
|
+
|
|
148
|
+
const dateNowSpy = jest.spyOn(Date, "now");
|
|
149
|
+
|
|
150
|
+
// Add address1 3 years ago
|
|
151
|
+
dateNowSpy.mockReturnValue(threeYearsAgo);
|
|
152
|
+
await store.addAddress("ethereum", address1);
|
|
153
|
+
|
|
154
|
+
// Add address2 1 year ago
|
|
155
|
+
dateNowSpy.mockReturnValue(oneYearAgo);
|
|
156
|
+
await store.addAddress("ethereum", address2);
|
|
157
|
+
|
|
158
|
+
// Add address3 now
|
|
159
|
+
dateNowSpy.mockReturnValue(now);
|
|
160
|
+
await store.addAddress("ethereum", address3);
|
|
161
|
+
|
|
162
|
+
let addresses = store.getAddresses("ethereum");
|
|
163
|
+
expect(addresses).toEqual([address3, address2, address1]);
|
|
164
|
+
|
|
165
|
+
// Re-add address1 (the oldest one) now
|
|
166
|
+
const reAddTime = now + 1000;
|
|
167
|
+
dateNowSpy.mockReturnValue(reAddTime);
|
|
168
|
+
await store.addAddress("ethereum", address1);
|
|
169
|
+
|
|
170
|
+
addresses = store.getAddresses("ethereum");
|
|
171
|
+
expect(addresses).toEqual([address1, address3, address2]);
|
|
172
|
+
|
|
173
|
+
expect(onAddAddressCompleteMock).toHaveBeenLastCalledWith({
|
|
174
|
+
ethereum: [
|
|
175
|
+
expect.objectContaining({ address: address1, lastUsed: reAddTime }),
|
|
176
|
+
expect.objectContaining({ address: address3, lastUsed: now }),
|
|
177
|
+
expect.objectContaining({ address: address2, lastUsed: oneYearAgo }),
|
|
178
|
+
],
|
|
102
179
|
});
|
|
103
180
|
});
|
|
181
|
+
|
|
182
|
+
it("should migrate legacy string addresses to RecentAddress objects on setup", async () => {
|
|
183
|
+
const legacyAddress1 = "0x66c4371aE8FFeD2ec1c2EBbbcCfb7E494181E1E3";
|
|
184
|
+
const legacyAddress2 = "0xB69B37A4Fb4A18b3258f974ff6e9f529AD2647b1";
|
|
185
|
+
const modernAddress = "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0";
|
|
186
|
+
const modernTimestamp = 1234567890;
|
|
187
|
+
|
|
188
|
+
const legacyCache: any = {
|
|
189
|
+
ethereum: [
|
|
190
|
+
legacyAddress1,
|
|
191
|
+
{ address: modernAddress, lastUsed: modernTimestamp },
|
|
192
|
+
legacyAddress2,
|
|
193
|
+
],
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
setupRecentAddressesStore(legacyCache, onAddAddressCompleteMock);
|
|
197
|
+
store = getRecentAddressesStore();
|
|
198
|
+
|
|
199
|
+
const addresses = store.getAddresses("ethereum");
|
|
200
|
+
|
|
201
|
+
// Order should be preserved: legacy1, modern, legacy2
|
|
202
|
+
expect(addresses).toEqual([legacyAddress1, modernAddress, legacyAddress2]);
|
|
203
|
+
});
|
|
104
204
|
});
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import type { RecentAddressesState, RecentAddress } from "@ledgerhq/types-live";
|
|
2
|
+
|
|
1
3
|
export const RECENT_ADDRESSES_COUNT_LIMIT = 12;
|
|
2
4
|
|
|
3
|
-
export type RecentAddressesCache =
|
|
5
|
+
export type RecentAddressesCache = RecentAddressesState;
|
|
4
6
|
|
|
5
7
|
export interface RecentAddressesStore {
|
|
6
8
|
addAddress(currency: string, address: string): void;
|
|
@@ -8,8 +10,6 @@ export interface RecentAddressesStore {
|
|
|
8
10
|
getAddresses(currency: string): string[];
|
|
9
11
|
}
|
|
10
12
|
|
|
11
|
-
type CallbackMode = "triggerCallback" | "skipCallback";
|
|
12
|
-
|
|
13
13
|
let recentAddressesStore: RecentAddressesStore | null = null;
|
|
14
14
|
|
|
15
15
|
export function getRecentAddressesStore(): RecentAddressesStore {
|
|
@@ -30,26 +30,43 @@ export function setupRecentAddressesStore(
|
|
|
30
30
|
|
|
31
31
|
class RecentAddressesStoreImpl implements RecentAddressesStore {
|
|
32
32
|
private addressesByCurrency: RecentAddressesCache = {};
|
|
33
|
-
private readonly onAddAddressComplete: (addressesByCurrency:
|
|
33
|
+
private readonly onAddAddressComplete: (addressesByCurrency: RecentAddressesCache) => void;
|
|
34
34
|
|
|
35
35
|
constructor(
|
|
36
36
|
addressesByCurrency: RecentAddressesCache,
|
|
37
37
|
onAddAddressComplete: (addressesByCurrency: RecentAddressesCache) => void,
|
|
38
38
|
) {
|
|
39
|
-
this.addressesByCurrency =
|
|
39
|
+
this.addressesByCurrency = this.sanitizeCache(addressesByCurrency);
|
|
40
40
|
this.onAddAddressComplete = onAddAddressComplete;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
private sanitizeCache(cache: RecentAddressesCache): RecentAddressesCache {
|
|
44
|
+
const sanitized: RecentAddressesCache = {};
|
|
45
|
+
for (const currency in cache) {
|
|
46
|
+
const entries = cache[currency] as (RecentAddress | string)[];
|
|
47
|
+
sanitized[currency] = entries.map(entry => {
|
|
48
|
+
if (typeof entry === "string") {
|
|
49
|
+
return { address: entry, lastUsed: Date.now() };
|
|
50
|
+
}
|
|
51
|
+
return entry;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
return sanitized;
|
|
55
|
+
}
|
|
56
|
+
|
|
43
57
|
addAddress(currency: string, address: string): void {
|
|
44
|
-
this.addAddressToCache(currency, address,
|
|
58
|
+
this.addAddressToCache(currency, address, Date.now(), true);
|
|
45
59
|
}
|
|
46
60
|
|
|
47
61
|
syncAddresses(cache: RecentAddressesCache): void {
|
|
48
62
|
const previousAddresses = { ...this.addressesByCurrency };
|
|
49
63
|
this.addressesByCurrency = { ...cache };
|
|
50
64
|
for (const currency in previousAddresses) {
|
|
51
|
-
|
|
52
|
-
|
|
65
|
+
const entries = previousAddresses[currency] as (RecentAddress | string)[];
|
|
66
|
+
for (const entry of entries) {
|
|
67
|
+
const address = typeof entry === "string" ? entry : entry.address;
|
|
68
|
+
const timestamp = typeof entry === "string" ? undefined : entry.lastUsed;
|
|
69
|
+
this.addAddressToCache(currency, address, timestamp ?? Date.now(), false);
|
|
53
70
|
}
|
|
54
71
|
}
|
|
55
72
|
|
|
@@ -58,26 +75,33 @@ class RecentAddressesStoreImpl implements RecentAddressesStore {
|
|
|
58
75
|
|
|
59
76
|
getAddresses(currency: string): string[] {
|
|
60
77
|
const addresses = this.addressesByCurrency[currency];
|
|
61
|
-
|
|
78
|
+
if (!addresses) return [];
|
|
79
|
+
return addresses.map(entry => entry.address);
|
|
62
80
|
}
|
|
63
81
|
|
|
64
|
-
private addAddressToCache(
|
|
82
|
+
private addAddressToCache(
|
|
83
|
+
currency: string,
|
|
84
|
+
address: string,
|
|
85
|
+
timestamp: number,
|
|
86
|
+
shouldTriggerCallback: boolean,
|
|
87
|
+
): void {
|
|
65
88
|
if (!this.addressesByCurrency[currency]) {
|
|
66
89
|
this.addressesByCurrency[currency] = [];
|
|
67
90
|
}
|
|
68
91
|
|
|
69
92
|
const addresses = this.addressesByCurrency[currency];
|
|
70
|
-
const addressIndex = addresses.
|
|
93
|
+
const addressIndex = addresses.findIndex(entry => entry.address === address);
|
|
94
|
+
|
|
71
95
|
if (addressIndex !== -1) {
|
|
72
96
|
addresses.splice(addressIndex, 1);
|
|
73
97
|
} else if (addresses.length >= RECENT_ADDRESSES_COUNT_LIMIT) {
|
|
74
98
|
addresses.pop();
|
|
75
99
|
}
|
|
76
100
|
|
|
77
|
-
addresses.unshift(address);
|
|
101
|
+
addresses.unshift({ address, lastUsed: timestamp });
|
|
78
102
|
this.addressesByCurrency[currency] = [...addresses];
|
|
79
103
|
|
|
80
|
-
if (
|
|
104
|
+
if (shouldTriggerCallback) {
|
|
81
105
|
this.onAddAddressComplete(this.addressesByCurrency);
|
|
82
106
|
}
|
|
83
107
|
}
|
package/src/e2e/enum/Provider.ts
CHANGED
|
@@ -11,7 +11,9 @@ export class Provider {
|
|
|
11
11
|
static readonly ONE_INCH = new Provider("oneinch", "1inch", false, false, true);
|
|
12
12
|
static readonly VELORA = new Provider("velora", "Velora", false, false, true);
|
|
13
13
|
static readonly MOONPAY = new Provider("moonpay", "MoonPay", true, false, true);
|
|
14
|
-
|
|
14
|
+
//TODO: THORCHAIN is actually kyc: false but due to the speculos crashing with native flow the bug needs to be fixed first before activating
|
|
15
|
+
//and adapting the flow accordingly
|
|
16
|
+
static readonly THORCHAIN = new Provider("thorswap", "THORChain", true, true, false);
|
|
15
17
|
static readonly UNISWAP = new Provider("uniswap", "Uniswap", false, false, false);
|
|
16
18
|
static readonly LIFI = new Provider("lifi", "LI.FI", false, true, false);
|
|
17
19
|
static readonly CIC = new Provider("cic", "CIC", false, true, true);
|
|
@@ -248,12 +248,14 @@ const DEFAULT_SWAP_PROVIDERS: Record<string, ProviderConfig & Partial<Additional
|
|
|
248
248
|
export const dexProvidersContractAddress: { [key: string]: string } = {
|
|
249
249
|
"0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad": "Uniswap",
|
|
250
250
|
"0x111111125421ca6dc452d289314280a0f8842a65": "1inch",
|
|
251
|
+
"0x6a000f20005980200259b80c5102003040001068": "velora",
|
|
251
252
|
};
|
|
252
253
|
|
|
253
254
|
export const termsOfUse: { [key: string]: string } = {
|
|
254
255
|
paraswap: "https://paraswap.io/tos",
|
|
255
256
|
"1inch": "https://1inch.com/assets/Widget_1inch.com_Terms_of_Use.pdf",
|
|
256
257
|
Uniswap: "https://uniswap.org/terms-of-service",
|
|
258
|
+
velora: "https://www.velora.xyz/terms/terms-of-use",
|
|
257
259
|
};
|
|
258
260
|
|
|
259
261
|
export const privacyPolicy: { [key: string]: string } = {
|
|
@@ -26,35 +26,39 @@ describe("getRemainingTime", () => {
|
|
|
26
26
|
test("should format seconds only", () => {
|
|
27
27
|
expect(getRemainingTime(30 * SECOND)).toBe("30s");
|
|
28
28
|
expect(getRemainingTime(59 * SECOND)).toBe("59s");
|
|
29
|
-
expect(getRemainingTime(1 * SECOND)).toBe("
|
|
29
|
+
expect(getRemainingTime(1 * SECOND)).toBe("01s");
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
test("should format minutes and seconds", () => {
|
|
33
|
-
expect(getRemainingTime(1 * MINUTE + 30 * SECOND)).toBe("
|
|
34
|
-
expect(getRemainingTime(5 * MINUTE + 15 * SECOND)).toBe("
|
|
33
|
+
expect(getRemainingTime(1 * MINUTE + 30 * SECOND)).toBe("01m 30s");
|
|
34
|
+
expect(getRemainingTime(5 * MINUTE + 15 * SECOND)).toBe("05m 15s");
|
|
35
35
|
expect(getRemainingTime(59 * MINUTE + 59 * SECOND)).toBe("59m 59s");
|
|
36
36
|
});
|
|
37
37
|
|
|
38
38
|
test("should format hours, minutes and seconds", () => {
|
|
39
|
-
expect(getRemainingTime(1 * HOUR + 30 * MINUTE + 15 * SECOND)).toBe("
|
|
40
|
-
expect(getRemainingTime(2 * HOUR + 5 * MINUTE + 10 * SECOND)).toBe("
|
|
39
|
+
expect(getRemainingTime(1 * HOUR + 30 * MINUTE + 15 * SECOND)).toBe("01h 30m 15s");
|
|
40
|
+
expect(getRemainingTime(2 * HOUR + 5 * MINUTE + 10 * SECOND)).toBe("02h 05m 10s");
|
|
41
41
|
expect(getRemainingTime(23 * HOUR + 59 * MINUTE + 59 * SECOND)).toBe("23h 59m 59s");
|
|
42
42
|
});
|
|
43
43
|
|
|
44
44
|
test("should format days, hours, minutes and seconds", () => {
|
|
45
|
-
expect(getRemainingTime(1 * DAY + 2 * HOUR + 30 * MINUTE + 15 * SECOND)).toBe(
|
|
46
|
-
|
|
45
|
+
expect(getRemainingTime(1 * DAY + 2 * HOUR + 30 * MINUTE + 15 * SECOND)).toBe(
|
|
46
|
+
"01d 02h 30m 15s",
|
|
47
|
+
);
|
|
48
|
+
expect(getRemainingTime(5 * DAY + 10 * HOUR + 5 * MINUTE + 10 * SECOND)).toBe(
|
|
49
|
+
"05d 10h 05m 10s",
|
|
50
|
+
);
|
|
47
51
|
expect(getRemainingTime(10 * DAY + 23 * HOUR + 59 * MINUTE + 59 * SECOND)).toBe(
|
|
48
52
|
"10d 23h 59m 59s",
|
|
49
53
|
);
|
|
50
54
|
});
|
|
51
55
|
|
|
52
56
|
test("should skip zero values", () => {
|
|
53
|
-
expect(getRemainingTime(1 * DAY)).toBe("
|
|
54
|
-
expect(getRemainingTime(1 * HOUR)).toBe("
|
|
55
|
-
expect(getRemainingTime(1 * MINUTE)).toBe("
|
|
56
|
-
expect(getRemainingTime(1 * DAY + 1 * MINUTE)).toBe("
|
|
57
|
-
expect(getRemainingTime(1 * DAY + 1 * HOUR)).toBe("
|
|
57
|
+
expect(getRemainingTime(1 * DAY)).toBe("01d 00h 00m 00s");
|
|
58
|
+
expect(getRemainingTime(1 * HOUR)).toBe("01h 00m 00s");
|
|
59
|
+
expect(getRemainingTime(1 * MINUTE)).toBe("01m 00s");
|
|
60
|
+
expect(getRemainingTime(1 * DAY + 1 * MINUTE)).toBe("01d 00h 01m 00s");
|
|
61
|
+
expect(getRemainingTime(1 * DAY + 1 * HOUR)).toBe("01d 01h 00m 00s");
|
|
58
62
|
});
|
|
59
63
|
});
|
|
60
64
|
|
|
@@ -89,41 +93,41 @@ describe("useTimeRemaining", () => {
|
|
|
89
93
|
test("should return formatted time remaining for valid proposal", () => {
|
|
90
94
|
const expiresAt = Date.now() + 2 * HOUR + 30 * MINUTE + 15 * SECOND;
|
|
91
95
|
const { result } = renderHook(() => useTimeRemaining(expiresAt * 1000));
|
|
92
|
-
expect(result.current).toBe("
|
|
96
|
+
expect(result.current).toBe("02h 30m 15s");
|
|
93
97
|
});
|
|
94
98
|
|
|
95
99
|
test("should update time remaining every second", () => {
|
|
96
100
|
const expiresAt = Date.now() + 2 * MINUTE + 30 * SECOND;
|
|
97
101
|
const { result } = renderHook(() => useTimeRemaining(expiresAt * 1000));
|
|
98
102
|
|
|
99
|
-
expect(result.current).toBe("
|
|
103
|
+
expect(result.current).toBe("02m 30s");
|
|
100
104
|
|
|
101
105
|
act(() => {
|
|
102
106
|
jest.advanceTimersByTime(1 * SECOND);
|
|
103
107
|
});
|
|
104
|
-
expect(result.current).toBe("
|
|
108
|
+
expect(result.current).toBe("02m 29s");
|
|
105
109
|
|
|
106
110
|
act(() => {
|
|
107
111
|
jest.advanceTimersByTime(1 * SECOND);
|
|
108
112
|
});
|
|
109
|
-
expect(result.current).toBe("
|
|
113
|
+
expect(result.current).toBe("02m 28s");
|
|
110
114
|
|
|
111
115
|
act(() => {
|
|
112
116
|
jest.advanceTimersByTime(30 * SECOND);
|
|
113
117
|
});
|
|
114
|
-
expect(result.current).toBe("
|
|
118
|
+
expect(result.current).toBe("01m 58s");
|
|
115
119
|
});
|
|
116
120
|
|
|
117
121
|
test("should return empty string when time expires", () => {
|
|
118
122
|
const expiresAt = Date.now() + 2 * SECOND;
|
|
119
123
|
const { result } = renderHook(() => useTimeRemaining(expiresAt * 1000));
|
|
120
124
|
|
|
121
|
-
expect(result.current).toBe("
|
|
125
|
+
expect(result.current).toBe("02s");
|
|
122
126
|
|
|
123
127
|
act(() => {
|
|
124
128
|
jest.advanceTimersByTime(1 * SECOND);
|
|
125
129
|
});
|
|
126
|
-
expect(result.current).toBe("
|
|
130
|
+
expect(result.current).toBe("01s");
|
|
127
131
|
|
|
128
132
|
act(() => {
|
|
129
133
|
jest.advanceTimersByTime(1 * SECOND);
|
|
@@ -135,7 +139,7 @@ describe("useTimeRemaining", () => {
|
|
|
135
139
|
const expiresAt = Date.now() + 1 * HOUR;
|
|
136
140
|
const { result, unmount } = renderHook(() => useTimeRemaining(expiresAt * 1000));
|
|
137
141
|
|
|
138
|
-
expect(result.current).toBe("
|
|
142
|
+
expect(result.current).toBe("01h 00m 00s");
|
|
139
143
|
|
|
140
144
|
unmount();
|
|
141
145
|
|