@ledgerhq/live-common 34.42.2-nightly.0 → 34.43.0-nightly.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/e2e/index.d.ts +1 -0
- package/lib/e2e/index.d.ts.map +1 -1
- package/lib/e2e/speculos.d.ts.map +1 -1
- package/lib/e2e/speculos.js +45 -15
- package/lib/e2e/speculos.js.map +1 -1
- package/lib/e2e/speculosCI.d.ts.map +1 -1
- package/lib/e2e/speculosCI.js +22 -4
- package/lib/e2e/speculosCI.js.map +1 -1
- package/lib/env.react.d.ts +1 -1
- package/lib/env.react.d.ts.map +1 -1
- package/lib/families/solana/bridge/mock-data.d.ts.map +1 -1
- package/lib/families/solana/bridge/mock-data.js +46 -316
- package/lib/families/solana/bridge/mock-data.js.map +1 -1
- package/lib/families/solana/bridge/mock.js +2 -2
- package/lib/families/solana/bridge/mock.js.map +1 -1
- package/lib/modularDrawer/__mocks__/accounts.mock.d.ts +18 -0
- package/lib/modularDrawer/__mocks__/accounts.mock.d.ts.map +1 -0
- package/lib/modularDrawer/__mocks__/accounts.mock.js +48 -0
- package/lib/modularDrawer/__mocks__/accounts.mock.js.map +1 -0
- package/lib/utils/__tests__/composeHooks.test.d.ts +2 -0
- package/lib/utils/__tests__/composeHooks.test.d.ts.map +1 -0
- package/lib/utils/__tests__/composeHooks.test.js +35 -0
- package/lib/utils/__tests__/composeHooks.test.js.map +1 -0
- package/lib/utils/__tests__/getAccountTuplesForCurrency.test.d.ts +2 -0
- package/lib/utils/__tests__/getAccountTuplesForCurrency.test.d.ts.map +1 -0
- package/lib/utils/__tests__/getAccountTuplesForCurrency.test.js +104 -0
- package/lib/utils/__tests__/getAccountTuplesForCurrency.test.js.map +1 -0
- package/lib/utils/composeHooks.d.ts +11 -0
- package/lib/utils/composeHooks.d.ts.map +1 -0
- package/lib/utils/composeHooks.js +25 -0
- package/lib/utils/composeHooks.js.map +1 -0
- package/lib/utils/getAccountTuplesForCurrency.d.ts +8 -0
- package/lib/utils/getAccountTuplesForCurrency.d.ts.map +1 -0
- package/lib/utils/getAccountTuplesForCurrency.js +19 -0
- package/lib/utils/getAccountTuplesForCurrency.js.map +1 -0
- package/lib-es/e2e/index.d.ts +1 -0
- package/lib-es/e2e/index.d.ts.map +1 -1
- package/lib-es/e2e/speculos.d.ts.map +1 -1
- package/lib-es/e2e/speculos.js +45 -15
- package/lib-es/e2e/speculos.js.map +1 -1
- package/lib-es/e2e/speculosCI.d.ts.map +1 -1
- package/lib-es/e2e/speculosCI.js +22 -4
- package/lib-es/e2e/speculosCI.js.map +1 -1
- package/lib-es/env.react.d.ts +1 -1
- package/lib-es/env.react.d.ts.map +1 -1
- package/lib-es/families/solana/bridge/mock-data.d.ts.map +1 -1
- package/lib-es/families/solana/bridge/mock-data.js +46 -316
- package/lib-es/families/solana/bridge/mock-data.js.map +1 -1
- package/lib-es/families/solana/bridge/mock.js +3 -3
- package/lib-es/families/solana/bridge/mock.js.map +1 -1
- package/lib-es/modularDrawer/__mocks__/accounts.mock.d.ts +18 -0
- package/lib-es/modularDrawer/__mocks__/accounts.mock.d.ts.map +1 -0
- package/lib-es/modularDrawer/__mocks__/accounts.mock.js +42 -0
- package/lib-es/modularDrawer/__mocks__/accounts.mock.js.map +1 -0
- package/lib-es/utils/__tests__/composeHooks.test.d.ts +2 -0
- package/lib-es/utils/__tests__/composeHooks.test.d.ts.map +1 -0
- package/lib-es/utils/__tests__/composeHooks.test.js +33 -0
- package/lib-es/utils/__tests__/composeHooks.test.js.map +1 -0
- package/lib-es/utils/__tests__/getAccountTuplesForCurrency.test.d.ts +2 -0
- package/lib-es/utils/__tests__/getAccountTuplesForCurrency.test.d.ts.map +1 -0
- package/lib-es/utils/__tests__/getAccountTuplesForCurrency.test.js +102 -0
- package/lib-es/utils/__tests__/getAccountTuplesForCurrency.test.js.map +1 -0
- package/lib-es/utils/composeHooks.d.ts +11 -0
- package/lib-es/utils/composeHooks.d.ts.map +1 -0
- package/lib-es/utils/composeHooks.js +21 -0
- package/lib-es/utils/composeHooks.js.map +1 -0
- package/lib-es/utils/getAccountTuplesForCurrency.d.ts +8 -0
- package/lib-es/utils/getAccountTuplesForCurrency.d.ts.map +1 -0
- package/lib-es/utils/getAccountTuplesForCurrency.js +15 -0
- package/lib-es/utils/getAccountTuplesForCurrency.js.map +1 -0
- package/package.json +44 -44
- package/src/e2e/speculos.ts +77 -21
- package/src/e2e/speculosCI.ts +32 -10
- package/src/families/solana/bridge/mock-data.ts +52 -316
- package/src/families/solana/bridge/mock.ts +3 -3
- package/src/modularDrawer/__mocks__/accounts.mock.ts +43 -0
- package/src/utils/__tests__/composeHooks.test.ts +46 -0
- package/src/utils/__tests__/getAccountTuplesForCurrency.test.ts +138 -0
- package/src/utils/composeHooks.ts +26 -0
- package/src/utils/getAccountTuplesForCurrency.ts +34 -0
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"composeHooks.test.d.ts","sourceRoot":"","sources":["../../../src/utils/__tests__/composeHooks.test.ts"],"names":[],"mappings":""}
|
@@ -0,0 +1,33 @@
|
|
1
|
+
import { composeHooks } from "../composeHooks";
|
2
|
+
describe("composeHooks", () => {
|
3
|
+
it("should compose hooks and merge their results", () => {
|
4
|
+
const hook1 = (items) => items.map(item => ({ id: item.id, extra: item.id * 2 }));
|
5
|
+
const hook2 = (items) => items.map(item => ({ ...item, final: item.extra + 1 }));
|
6
|
+
const composed = composeHooks(hook1, hook2);
|
7
|
+
const input = [{ id: 1 }, { id: 2 }];
|
8
|
+
const processedInput = input.map(item => ({ id: item.id, extra: item.id * 2 }));
|
9
|
+
const result = composed(processedInput);
|
10
|
+
expect(result).toEqual([
|
11
|
+
{ id: 1, extra: 2, final: 3 },
|
12
|
+
{ id: 2, extra: 4, final: 5 },
|
13
|
+
]);
|
14
|
+
});
|
15
|
+
it("should handle hooks that return undefined", () => {
|
16
|
+
const hook1 = (items) => items.map(item => ({ id: item.id, extra: item.id * 2 }));
|
17
|
+
const hook2 = () => undefined;
|
18
|
+
const composed = composeHooks(hook1, hook2);
|
19
|
+
const input = [{ id: 1 }, { id: 2 }];
|
20
|
+
const result = composed(input);
|
21
|
+
expect(result).toEqual([
|
22
|
+
{ id: 1, extra: 2 },
|
23
|
+
{ id: 2, extra: 4 },
|
24
|
+
]);
|
25
|
+
});
|
26
|
+
it("should return the original items if no hooks are provided", () => {
|
27
|
+
const composed = composeHooks();
|
28
|
+
const input = [{ id: 1 }, { id: 2 }];
|
29
|
+
const result = composed(input);
|
30
|
+
expect(result).toEqual(input);
|
31
|
+
});
|
32
|
+
});
|
33
|
+
//# sourceMappingURL=composeHooks.test.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"composeHooks.test.js","sourceRoot":"","sources":["../../../src/utils/__tests__/composeHooks.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,KAAK,GAAG,CAAC,KAA4B,EAAE,EAAE,CAC7C,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3D,MAAM,KAAK,GAAG,CAAC,KAA2C,EAAE,EAAE,CAC5D,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAE1D,MAAM,QAAQ,GAAG,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAE5C,MAAM,KAAK,GAA0B,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;QAC5D,MAAM,cAAc,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAChF,MAAM,MAAM,GAAG,QAAQ,CAAC,cAAc,CAAC,CAAC;QAExC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACrB,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE;YAC7B,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE;SAC9B,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,KAAK,GAAG,CAAC,KAA4B,EAAE,EAAE,CAC7C,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3D,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,SAAS,CAAC;QAE9B,MAAM,QAAQ,GAAG,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAE5C,MAAM,KAAK,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;QACrC,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;QAE/B,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACrB,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE;YACnB,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE;SACpB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC;QAEhC,MAAM,KAAK,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;QACrC,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;QAE/B,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"getAccountTuplesForCurrency.test.d.ts","sourceRoot":"","sources":["../../../src/utils/__tests__/getAccountTuplesForCurrency.test.ts"],"names":[],"mappings":""}
|
@@ -0,0 +1,102 @@
|
|
1
|
+
import { getCryptoCurrencyById, getTokenById } from "@ledgerhq/cryptoassets";
|
2
|
+
import { genAccount } from "@ledgerhq/live-common/mock/account";
|
3
|
+
import { getAccountTuplesForCurrency } from "../getAccountTuplesForCurrency";
|
4
|
+
function* accountGenerator(currency) {
|
5
|
+
let id = 0;
|
6
|
+
while (true) {
|
7
|
+
id += 1;
|
8
|
+
yield genAccount(`mocked-account-${id}`, { currency, operationsSize: 0 });
|
9
|
+
}
|
10
|
+
}
|
11
|
+
const getAccountCreator = (currencyId) => {
|
12
|
+
const generator = accountGenerator(getCryptoCurrencyById(currencyId));
|
13
|
+
return () => generator.next().value;
|
14
|
+
};
|
15
|
+
describe("getAccountTuplesForCurrency", () => {
|
16
|
+
const getEthAccount = getAccountCreator("ethereum");
|
17
|
+
const getBtcAccount = getAccountCreator("bitcoin");
|
18
|
+
const getPolkadotAccount = getAccountCreator("polkadot");
|
19
|
+
const getCosmosAccount = getAccountCreator("cosmos");
|
20
|
+
describe("CryptoCurrency", () => {
|
21
|
+
test("returns all accounts associated to the CryptoCurrency", () => {
|
22
|
+
const ethCurrency = getCryptoCurrencyById("ethereum");
|
23
|
+
const ethAccounts = [getEthAccount(), getEthAccount()];
|
24
|
+
const allAccounts = [
|
25
|
+
getCosmosAccount(),
|
26
|
+
...ethAccounts,
|
27
|
+
getBtcAccount(),
|
28
|
+
getPolkadotAccount(),
|
29
|
+
];
|
30
|
+
const results = getAccountTuplesForCurrency(ethCurrency, allAccounts);
|
31
|
+
expect(results).toHaveLength(2);
|
32
|
+
results.forEach((result, index) => {
|
33
|
+
expect(result.account).toEqual(ethAccounts[index]);
|
34
|
+
expect(result.subAccount).toBeNull();
|
35
|
+
});
|
36
|
+
});
|
37
|
+
test("returns an empty array if the CryptoCurrency passed has no associated account", () => {
|
38
|
+
const ethCurrency = getCryptoCurrencyById("ethereum");
|
39
|
+
const allAccounts = [getCosmosAccount(), getBtcAccount(), getPolkadotAccount()];
|
40
|
+
const results = getAccountTuplesForCurrency(ethCurrency, allAccounts);
|
41
|
+
expect(results).toHaveLength(0);
|
42
|
+
});
|
43
|
+
test("filters based on the accountId map", () => {
|
44
|
+
const ethCurrency = getCryptoCurrencyById("ethereum");
|
45
|
+
const ethAccounts = [getEthAccount(), getEthAccount(), getEthAccount(), getEthAccount()];
|
46
|
+
const results = getAccountTuplesForCurrency(ethCurrency, ethAccounts, new Map([[ethAccounts[0].id, true]]));
|
47
|
+
expect(results).toHaveLength(1);
|
48
|
+
});
|
49
|
+
});
|
50
|
+
describe("TokenCurrency", () => {
|
51
|
+
const aaveToken = getTokenById("ethereum/erc20/aave");
|
52
|
+
test("returns correct parent accounts including a new subAccount when a TokenCurrency is provided", () => {
|
53
|
+
const ethAccounts = [
|
54
|
+
{ ...getEthAccount(), subAccounts: [] },
|
55
|
+
{ ...getEthAccount(), subAccounts: [] },
|
56
|
+
];
|
57
|
+
const allAccounts = [
|
58
|
+
getCosmosAccount(),
|
59
|
+
...ethAccounts,
|
60
|
+
getBtcAccount(),
|
61
|
+
getPolkadotAccount(),
|
62
|
+
];
|
63
|
+
const results = getAccountTuplesForCurrency(aaveToken, allAccounts);
|
64
|
+
expect(results).toHaveLength(ethAccounts.length);
|
65
|
+
results.forEach((result, index) => {
|
66
|
+
expect(result.account).toEqual(ethAccounts[index]);
|
67
|
+
expect(result.subAccount.token).toEqual(aaveToken);
|
68
|
+
});
|
69
|
+
});
|
70
|
+
test("returns correct parent accounts including already existing subAccounts when a TokenCurrency is provided", () => {
|
71
|
+
const ethAccounts = [{ ...getEthAccount(), subAccounts: [aaveToken] }];
|
72
|
+
const allAccounts = [
|
73
|
+
getCosmosAccount(),
|
74
|
+
...ethAccounts,
|
75
|
+
getBtcAccount(),
|
76
|
+
getPolkadotAccount(),
|
77
|
+
];
|
78
|
+
const results = getAccountTuplesForCurrency(aaveToken, allAccounts);
|
79
|
+
expect(results).toHaveLength(ethAccounts.length);
|
80
|
+
results.forEach((result, index) => {
|
81
|
+
expect(result.account).toEqual(ethAccounts[index]);
|
82
|
+
expect(result.subAccount.token).toEqual(aaveToken);
|
83
|
+
});
|
84
|
+
});
|
85
|
+
test("returns an empty array when a TokenCurrency is provided but the accounts list is empty", () => {
|
86
|
+
const allAccounts = [];
|
87
|
+
const results = getAccountTuplesForCurrency(aaveToken, allAccounts);
|
88
|
+
expect(results).toHaveLength(0);
|
89
|
+
});
|
90
|
+
test("does not filter based on the accountId map", () => {
|
91
|
+
const aaveAccounts = [
|
92
|
+
{ ...getEthAccount(), subAccounts: [aaveToken] },
|
93
|
+
{ ...getEthAccount(), subAccounts: [aaveToken] },
|
94
|
+
{ ...getEthAccount(), subAccounts: [aaveToken] },
|
95
|
+
{ ...getEthAccount(), subAccounts: [aaveToken] },
|
96
|
+
];
|
97
|
+
const results = getAccountTuplesForCurrency(aaveToken, aaveAccounts, new Map([[aaveAccounts[0].id, true]]));
|
98
|
+
expect(results).toHaveLength(4);
|
99
|
+
});
|
100
|
+
});
|
101
|
+
});
|
102
|
+
//# sourceMappingURL=getAccountTuplesForCurrency.test.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"getAccountTuplesForCurrency.test.js","sourceRoot":"","sources":["../../../src/utils/__tests__/getAccountTuplesForCurrency.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAC;AAGhE,OAAO,EAAE,2BAA2B,EAAE,MAAM,gCAAgC,CAAC;AAE7E,QAAQ,CAAC,CAAC,gBAAgB,CAAC,QAAwB;IACjD,IAAI,EAAE,GAAG,CAAC,CAAC;IACX,OAAO,IAAI,EAAE;QACX,EAAE,IAAI,CAAC,CAAC;QACR,MAAM,UAAU,CAAC,kBAAkB,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC,EAAE,CAAC,CAAC;KAC3E;AACH,CAAC;AACD,MAAM,iBAAiB,GAAG,CAAC,UAAkB,EAAE,EAAE;IAC/C,MAAM,SAAS,GAAG,gBAAgB,CAAC,qBAAqB,CAAC,UAAU,CAAC,CAAC,CAAC;IACtE,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;AACtC,CAAC,CAAC;AAEF,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;IAC3C,MAAM,aAAa,GAAG,iBAAiB,CAAC,UAAU,CAAC,CAAC;IACpD,MAAM,aAAa,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;IACnD,MAAM,kBAAkB,GAAG,iBAAiB,CAAC,UAAU,CAAC,CAAC;IACzD,MAAM,gBAAgB,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAErD,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;QAC9B,IAAI,CAAC,uDAAuD,EAAE,GAAG,EAAE;YACjE,MAAM,WAAW,GAAG,qBAAqB,CAAC,UAAU,CAAC,CAAC;YACtD,MAAM,WAAW,GAAG,CAAC,aAAa,EAAE,EAAE,aAAa,EAAE,CAAC,CAAC;YACvD,MAAM,WAAW,GAAc;gBAC7B,gBAAgB,EAAE;gBAClB,GAAG,WAAW;gBACd,aAAa,EAAE;gBACf,kBAAkB,EAAE;aACrB,CAAC;YAEF,MAAM,OAAO,GAAG,2BAA2B,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;YAEtE,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAChC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;gBAChC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;gBACnD,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,QAAQ,EAAE,CAAC;YACvC,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,+EAA+E,EAAE,GAAG,EAAE;YACzF,MAAM,WAAW,GAAG,qBAAqB,CAAC,UAAU,CAAC,CAAC;YACtD,MAAM,WAAW,GAAc,CAAC,gBAAgB,EAAE,EAAE,aAAa,EAAE,EAAE,kBAAkB,EAAE,CAAC,CAAC;YAE3F,MAAM,OAAO,GAAG,2BAA2B,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;YAEtE,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,oCAAoC,EAAE,GAAG,EAAE;YAC9C,MAAM,WAAW,GAAG,qBAAqB,CAAC,UAAU,CAAC,CAAC;YACtD,MAAM,WAAW,GAAG,CAAC,aAAa,EAAE,EAAE,aAAa,EAAE,EAAE,aAAa,EAAE,EAAE,aAAa,EAAE,CAAC,CAAC;YAEzF,MAAM,OAAO,GAAG,2BAA2B,CACzC,WAAW,EACX,WAAW,EACX,IAAI,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,CACrC,CAAC;YAEF,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;QAC7B,MAAM,SAAS,GAAG,YAAY,CAAC,qBAAqB,CAAC,CAAC;QAEtD,IAAI,CAAC,6FAA6F,EAAE,GAAG,EAAE;YACvG,MAAM,WAAW,GAAG;gBAClB,EAAE,GAAG,aAAa,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE;gBACvC,EAAE,GAAG,aAAa,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE;aACxC,CAAC;YACF,MAAM,WAAW,GAAc;gBAC7B,gBAAgB,EAAE;gBAClB,GAAG,WAAW;gBACd,aAAa,EAAE;gBACf,kBAAkB,EAAE;aACrB,CAAC;YAEF,MAAM,OAAO,GAAG,2BAA2B,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;YAEpE,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;YACjD,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;gBAChC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;gBACnD,MAAM,CAAE,MAAM,CAAC,UAAsD,CAAC,KAAK,CAAC,CAAC,OAAO,CAClF,SAAS,CACV,CAAC;YACJ,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,yGAAyG,EAAE,GAAG,EAAE;YACnH,MAAM,WAAW,GAAG,CAAC,EAAE,GAAG,aAAa,EAAE,EAAE,WAAW,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;YACvE,MAAM,WAAW,GAAc;gBAC7B,gBAAgB,EAAE;gBAClB,GAAG,WAAW;gBACd,aAAa,EAAE;gBACf,kBAAkB,EAAE;aACrB,CAAC;YAEF,MAAM,OAAO,GAAG,2BAA2B,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;YAEpE,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;YACjD,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;gBAChC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;gBACnD,MAAM,CAAE,MAAM,CAAC,UAAsD,CAAC,KAAK,CAAC,CAAC,OAAO,CAClF,SAAS,CACV,CAAC;YACJ,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,wFAAwF,EAAE,GAAG,EAAE;YAClG,MAAM,WAAW,GAAc,EAAE,CAAC;YAElC,MAAM,OAAO,GAAG,2BAA2B,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;YACpE,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,4CAA4C,EAAE,GAAG,EAAE;YACtD,MAAM,YAAY,GAAG;gBACnB,EAAE,GAAG,aAAa,EAAE,EAAE,WAAW,EAAE,CAAC,SAAS,CAAC,EAAE;gBAChD,EAAE,GAAG,aAAa,EAAE,EAAE,WAAW,EAAE,CAAC,SAAS,CAAC,EAAE;gBAChD,EAAE,GAAG,aAAa,EAAE,EAAE,WAAW,EAAE,CAAC,SAAS,CAAC,EAAE;gBAChD,EAAE,GAAG,aAAa,EAAE,EAAE,WAAW,EAAE,CAAC,SAAS,CAAC,EAAE;aACjD,CAAC;YAEF,MAAM,OAAO,GAAG,2BAA2B,CACzC,SAAS,EACT,YAAY,EACZ,IAAI,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,CACtC,CAAC;YAEF,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
/**
|
2
|
+
*
|
3
|
+
* @param hooks - An array of functions that take an array of items of type T and return an array of items of type U or undefined.
|
4
|
+
* @template T - The type of the items in the input array.
|
5
|
+
* @template U - The type of the items in the output array.
|
6
|
+
* @description This function composes multiple hooks into a single hook that processes an array of items of type T and returns an array of items of type T & U.
|
7
|
+
* @returns A function that takes an array of items of type T and returns an array of items of type T & U.
|
8
|
+
*
|
9
|
+
*/
|
10
|
+
export declare function composeHooks<T, U>(...hooks: Array<(items: T[]) => U[] | undefined>): (items: T[]) => (T & U)[];
|
11
|
+
//# sourceMappingURL=composeHooks.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"composeHooks.d.ts","sourceRoot":"","sources":["../../src/utils/composeHooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,wBAAgB,YAAY,CAAC,CAAC,EAAE,CAAC,EAC/B,GAAG,KAAK,EAAE,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,GAAG,SAAS,CAAC,GAC/C,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAa3B"}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
/**
|
2
|
+
*
|
3
|
+
* @param hooks - An array of functions that take an array of items of type T and return an array of items of type U or undefined.
|
4
|
+
* @template T - The type of the items in the input array.
|
5
|
+
* @template U - The type of the items in the output array.
|
6
|
+
* @description This function composes multiple hooks into a single hook that processes an array of items of type T and returns an array of items of type T & U.
|
7
|
+
* @returns A function that takes an array of items of type T and returns an array of items of type T & U.
|
8
|
+
*
|
9
|
+
*/
|
10
|
+
export function composeHooks(...hooks) {
|
11
|
+
return (items) => {
|
12
|
+
return hooks.reduce((acc, hook) => {
|
13
|
+
const result = hook?.(acc) ?? [];
|
14
|
+
return acc.map((item, i) => ({
|
15
|
+
...item,
|
16
|
+
...result[i],
|
17
|
+
}));
|
18
|
+
}, items);
|
19
|
+
};
|
20
|
+
}
|
21
|
+
//# sourceMappingURL=composeHooks.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"composeHooks.js","sourceRoot":"","sources":["../../src/utils/composeHooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,UAAU,YAAY,CAC1B,GAAG,KAA6C;IAEhD,OAAO,CAAC,KAAU,EAAa,EAAE;QAC/B,OAAO,KAAK,CAAC,MAAM,CACjB,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;YACZ,MAAM,MAAM,GAAG,IAAI,EAAE,CAAC,GAAU,CAAC,IAAI,EAAE,CAAC;YACxC,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC3B,GAAG,IAAI;gBACP,GAAG,MAAM,CAAC,CAAC,CAAC;aACb,CAAC,CAAC,CAAC;QACN,CAAC,EACD,KAAkB,CACnB,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
|
@@ -0,0 +1,8 @@
|
|
1
|
+
import type { Account, TokenAccount } from "@ledgerhq/types-live";
|
2
|
+
import { CryptoCurrency, TokenCurrency } from "@ledgerhq/types-cryptoassets";
|
3
|
+
export type AccountTuple = {
|
4
|
+
account: Account;
|
5
|
+
subAccount: TokenAccount | null;
|
6
|
+
};
|
7
|
+
export declare function getAccountTuplesForCurrency(currency: CryptoCurrency | TokenCurrency, allAccounts: Account[], accountIds?: Map<string, boolean>): AccountTuple[];
|
8
|
+
//# sourceMappingURL=getAccountTuplesForCurrency.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"getAccountTuplesForCurrency.d.ts","sourceRoot":"","sources":["../../src/utils/getAccountTuplesForCurrency.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAG7E,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,YAAY,GAAG,IAAI,CAAC;CACjC,CAAC;AAEF,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,cAAc,GAAG,aAAa,EACxC,WAAW,EAAE,OAAO,EAAE,EACtB,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,YAAY,EAAE,CAoBhB"}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import { makeEmptyTokenAccount } from "@ledgerhq/coin-framework/account/helpers";
|
2
|
+
export function getAccountTuplesForCurrency(currency, allAccounts, accountIds) {
|
3
|
+
const isToken = currency.type === "TokenCurrency";
|
4
|
+
const targetCurrencyId = isToken ? currency.parentCurrency.id : currency.id;
|
5
|
+
return allAccounts
|
6
|
+
.filter(account => account.currency.id === targetCurrencyId &&
|
7
|
+
(isToken ? true : accountIds ? accountIds.has(account.id) : true))
|
8
|
+
.map(account => {
|
9
|
+
const subAccount = isToken
|
10
|
+
? account.subAccounts?.find((subAcc) => subAcc.type === "TokenAccount" && subAcc.token.id === currency.id) || makeEmptyTokenAccount(account, currency)
|
11
|
+
: null;
|
12
|
+
return { account, subAccount };
|
13
|
+
});
|
14
|
+
}
|
15
|
+
//# sourceMappingURL=getAccountTuplesForCurrency.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"getAccountTuplesForCurrency.js","sourceRoot":"","sources":["../../src/utils/getAccountTuplesForCurrency.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,0CAA0C,CAAC;AAOjF,MAAM,UAAU,2BAA2B,CACzC,QAAwC,EACxC,WAAsB,EACtB,UAAiC;IAEjC,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,KAAK,eAAe,CAAC;IAClD,MAAM,gBAAgB,GAAG,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;IAE5E,OAAO,WAAW;SACf,MAAM,CACL,OAAO,CAAC,EAAE,CACR,OAAO,CAAC,QAAQ,CAAC,EAAE,KAAK,gBAAgB;QACxC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CACpE;SACA,GAAG,CAAC,OAAO,CAAC,EAAE;QACb,MAAM,UAAU,GAAG,OAAO;YACxB,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,CACvB,CAAC,MAAM,EAA0B,EAAE,CACjC,MAAM,CAAC,IAAI,KAAK,cAAc,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,QAAQ,CAAC,EAAE,CACpE,IAAI,qBAAqB,CAAC,OAAO,EAAE,QAAQ,CAAC;YAC/C,CAAC,CAAC,IAAI,CAAC;QAET,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;IACjC,CAAC,CAAC,CAAC;AACP,CAAC"}
|
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.
|
4
|
+
"version": "34.43.0-nightly.1",
|
5
5
|
"repository": {
|
6
6
|
"type": "git",
|
7
7
|
"url": "https://github.com/LedgerHQ/ledger-live.git"
|
@@ -162,43 +162,42 @@
|
|
162
162
|
"xstate": "^5.19.2",
|
163
163
|
"yargs": "^17.0.0",
|
164
164
|
"zod": "^3.22.4",
|
165
|
-
"@ledgerhq/coin-algorand": "^0.9.15-nightly.
|
166
|
-
"@ledgerhq/coin-aptos": "^2.6.1-nightly.
|
167
|
-
"@ledgerhq/coin-bitcoin": "^0.18.1-nightly.
|
168
|
-
"@ledgerhq/coin-cardano": "^0.10.1-nightly.
|
169
|
-
"@ledgerhq/coin-
|
170
|
-
"@ledgerhq/coin-
|
171
|
-
"@ledgerhq/coin-
|
172
|
-
"@ledgerhq/coin-
|
173
|
-
"@ledgerhq/coin-
|
174
|
-
"@ledgerhq/coin-
|
175
|
-
"@ledgerhq/coin-
|
176
|
-
"@ledgerhq/coin-
|
177
|
-
"@ledgerhq/coin-
|
178
|
-
"@ledgerhq/coin-
|
179
|
-
"@ledgerhq/coin-
|
180
|
-
"@ledgerhq/coin-
|
181
|
-
"@ledgerhq/coin-
|
182
|
-
"@ledgerhq/coin-
|
183
|
-
"@ledgerhq/coin-
|
184
|
-
"@ledgerhq/coin-
|
185
|
-
"@ledgerhq/coin-
|
186
|
-
"@ledgerhq/coin-
|
187
|
-
"@ledgerhq/coin-
|
188
|
-
"@ledgerhq/coin-
|
189
|
-
"@ledgerhq/coin-
|
190
|
-
"@ledgerhq/coin-xrp": "^6.4.2-nightly.0",
|
165
|
+
"@ledgerhq/coin-algorand": "^0.9.15-nightly.1",
|
166
|
+
"@ledgerhq/coin-aptos": "^2.6.1-nightly.1",
|
167
|
+
"@ledgerhq/coin-bitcoin": "^0.18.1-nightly.1",
|
168
|
+
"@ledgerhq/coin-cardano": "^0.10.1-nightly.1",
|
169
|
+
"@ledgerhq/coin-celo": "^1.1.13-nightly.1",
|
170
|
+
"@ledgerhq/coin-cosmos": "^0.16.4-nightly.1",
|
171
|
+
"@ledgerhq/coin-evm": "^2.24.1-nightly.1",
|
172
|
+
"@ledgerhq/coin-filecoin": "^1.9.15-nightly.1",
|
173
|
+
"@ledgerhq/coin-framework": "^5.7.1-nightly.1",
|
174
|
+
"@ledgerhq/coin-hedera": "^1.9.1-nightly.1",
|
175
|
+
"@ledgerhq/coin-icon": "^0.11.2-nightly.1",
|
176
|
+
"@ledgerhq/coin-internet_computer": "^1.7.15-nightly.1",
|
177
|
+
"@ledgerhq/coin-mina": "^1.1.14-nightly.1",
|
178
|
+
"@ledgerhq/coin-multiversx": "^0.4.15-nightly.1",
|
179
|
+
"@ledgerhq/coin-near": "^0.11.15-nightly.1",
|
180
|
+
"@ledgerhq/coin-polkadot": "^6.4.1-nightly.1",
|
181
|
+
"@ledgerhq/coin-solana": "^0.29.0-nightly.1",
|
182
|
+
"@ledgerhq/coin-stacks": "^0.8.15-nightly.1",
|
183
|
+
"@ledgerhq/coin-stellar": "^5.3.3-nightly.1",
|
184
|
+
"@ledgerhq/coin-sui": "^0.7.1-nightly.1",
|
185
|
+
"@ledgerhq/coin-tezos": "^5.6.2-nightly.1",
|
186
|
+
"@ledgerhq/coin-ton": "^0.13.4-nightly.1",
|
187
|
+
"@ledgerhq/coin-tron": "^4.4.3-nightly.1",
|
188
|
+
"@ledgerhq/coin-vechain": "^2.7.15-nightly.1",
|
189
|
+
"@ledgerhq/coin-xrp": "^6.4.2-nightly.1",
|
191
190
|
"@ledgerhq/crypto-icons-ui": "^1.16.0",
|
192
|
-
"@ledgerhq/cryptoassets": "^13.22.0",
|
193
|
-
"@ledgerhq/device-core": "^0.5.4-nightly.
|
191
|
+
"@ledgerhq/cryptoassets": "^13.22.1-nightly.0",
|
192
|
+
"@ledgerhq/device-core": "^0.5.4-nightly.1",
|
194
193
|
"@ledgerhq/devices": "8.4.8",
|
195
194
|
"@ledgerhq/errors": "^6.23.0",
|
196
195
|
"@ledgerhq/hw-app-algorand": "^6.31.4",
|
197
196
|
"@ledgerhq/hw-app-aptos": "^6.34.4",
|
198
197
|
"@ledgerhq/hw-app-btc": "^10.10.0",
|
199
|
-
"@ledgerhq/hw-app-celo": "^6.33.11-nightly.
|
198
|
+
"@ledgerhq/hw-app-celo": "^6.33.11-nightly.1",
|
200
199
|
"@ledgerhq/hw-app-cosmos": "^6.32.4",
|
201
|
-
"@ledgerhq/hw-app-eth": "^6.45.13-nightly.
|
200
|
+
"@ledgerhq/hw-app-eth": "^6.45.13-nightly.1",
|
202
201
|
"@ledgerhq/hw-app-exchange": "^0.10.4",
|
203
202
|
"@ledgerhq/hw-app-hedera": "^1.2.4",
|
204
203
|
"@ledgerhq/hw-app-icon": "^1.3.4",
|
@@ -209,27 +208,28 @@
|
|
209
208
|
"@ledgerhq/hw-app-sui": "^1.2.0",
|
210
209
|
"@ledgerhq/hw-app-tezos": "^6.31.4",
|
211
210
|
"@ledgerhq/hw-app-trx": "^6.31.4",
|
212
|
-
"@ledgerhq/hw-app-vet": "^0.5.
|
211
|
+
"@ledgerhq/hw-app-vet": "^0.5.11-nightly.0",
|
213
212
|
"@ledgerhq/hw-app-xrp": "^6.32.2",
|
214
213
|
"@ledgerhq/hw-transport": "^6.31.8",
|
215
214
|
"@ledgerhq/hw-transport-mocker": "^6.29.8",
|
216
|
-
"@ledgerhq/ledger-cal-service": "^1.2.
|
215
|
+
"@ledgerhq/ledger-cal-service": "^1.2.2-nightly.0",
|
217
216
|
"@ledgerhq/live-config": "^3.1.0",
|
218
|
-
"@ledgerhq/live-countervalues": "^0.5.15-nightly.
|
219
|
-
"@ledgerhq/live-countervalues-react": "^0.2.44-nightly.
|
217
|
+
"@ledgerhq/live-countervalues": "^0.5.15-nightly.1",
|
218
|
+
"@ledgerhq/live-countervalues-react": "^0.2.44-nightly.1",
|
220
219
|
"@ledgerhq/live-dmk-shared": "^0.11.1",
|
221
|
-
"@ledgerhq/live-env": "^2.
|
220
|
+
"@ledgerhq/live-env": "^2.13.0-nightly.0",
|
222
221
|
"@ledgerhq/live-hooks": "0.1.0",
|
223
|
-
"@ledgerhq/live-network": "^2.0.
|
224
|
-
"@ledgerhq/live-nft": "^0.8.15-nightly.
|
222
|
+
"@ledgerhq/live-network": "^2.0.14-nightly.0",
|
223
|
+
"@ledgerhq/live-nft": "^0.8.15-nightly.1",
|
225
224
|
"@ledgerhq/live-promise": "^0.1.1",
|
226
|
-
"@ledgerhq/live-signer-evm": "^0.6.2-nightly.
|
227
|
-
"@ledgerhq/live-signer-solana": "^0.5.0-nightly.
|
228
|
-
"@ledgerhq/live-wallet": "^0.11.6-nightly.
|
225
|
+
"@ledgerhq/live-signer-evm": "^0.6.2-nightly.1",
|
226
|
+
"@ledgerhq/live-signer-solana": "^0.5.0-nightly.1",
|
227
|
+
"@ledgerhq/live-wallet": "^0.11.6-nightly.1",
|
229
228
|
"@ledgerhq/logs": "^6.13.0",
|
230
|
-
"@ledgerhq/speculos-transport": "^0.2.
|
229
|
+
"@ledgerhq/speculos-transport": "^0.2.7-nightly.0",
|
231
230
|
"@ledgerhq/wallet-api-acre-module": "^0.5.0",
|
232
|
-
"@ledgerhq/wallet-api-exchange-module": "^0.14.0"
|
231
|
+
"@ledgerhq/wallet-api-exchange-module": "^0.14.0",
|
232
|
+
"@ledgerhq/coin-casper": "^2.0.6-nightly.1"
|
233
233
|
},
|
234
234
|
"devDependencies": {
|
235
235
|
"@solana/web3.js": "1.95.4",
|
@@ -277,7 +277,7 @@
|
|
277
277
|
"undici": "6.19.2",
|
278
278
|
"uuid": "^8.3.2",
|
279
279
|
"ws": "7",
|
280
|
-
"@ledgerhq/device-react": "^0.2.39-nightly.
|
280
|
+
"@ledgerhq/device-react": "^0.2.39-nightly.1",
|
281
281
|
"@ledgerhq/types-cryptoassets": "^7.24.0-nightly.0",
|
282
282
|
"@ledgerhq/types-devices": "^6.25.3",
|
283
283
|
"@ledgerhq/types-live": "^6.78.1-nightly.0"
|
package/src/e2e/speculos.ts
CHANGED
@@ -11,7 +11,7 @@ import { createSpeculosDeviceCI, releaseSpeculosDeviceCI } from "./speculosCI";
|
|
11
11
|
import type { AppCandidate } from "@ledgerhq/coin-framework/bot/types";
|
12
12
|
import { DeviceModelId } from "@ledgerhq/devices";
|
13
13
|
import { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
|
14
|
-
import axios from "axios";
|
14
|
+
import axios, { AxiosError, AxiosResponse } from "axios";
|
15
15
|
import { getEnv } from "@ledgerhq/live-env";
|
16
16
|
import { getCryptoCurrencyById } from "../currencies";
|
17
17
|
import { DeviceLabels } from "../e2e/enum/DeviceLabels";
|
@@ -415,13 +415,59 @@ interface ResponseData {
|
|
415
415
|
events: Event[];
|
416
416
|
}
|
417
417
|
|
418
|
+
function getSpeculosAddress(): string {
|
419
|
+
const speculosAddress = process.env.SPECULOS_ADDRESS;
|
420
|
+
return speculosAddress || "http://127.0.0.1";
|
421
|
+
}
|
422
|
+
|
423
|
+
async function retryAxiosRequest<T>(
|
424
|
+
requestFn: () => Promise<AxiosResponse<T>>,
|
425
|
+
maxRetries: number = 5,
|
426
|
+
baseDelay: number = 1000,
|
427
|
+
retryableStatusCodes: number[] = [500, 502, 503, 504],
|
428
|
+
): Promise<AxiosResponse<T>> {
|
429
|
+
let lastError: AxiosError | Error;
|
430
|
+
|
431
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
432
|
+
try {
|
433
|
+
return await requestFn();
|
434
|
+
} catch (error) {
|
435
|
+
lastError = error as AxiosError | Error;
|
436
|
+
|
437
|
+
const isRetryable =
|
438
|
+
axios.isAxiosError(error) &&
|
439
|
+
error.response &&
|
440
|
+
retryableStatusCodes.includes(error.response.status);
|
441
|
+
|
442
|
+
const isNetworkError = axios.isAxiosError(error) && !error.response;
|
443
|
+
|
444
|
+
if ((isRetryable || isNetworkError) && attempt < maxRetries) {
|
445
|
+
const delay = baseDelay * (attempt + 1);
|
446
|
+
console.warn(
|
447
|
+
`Axios request failed (attempt ${attempt + 1}/${maxRetries + 1}), retrying in ${delay}ms...`,
|
448
|
+
{
|
449
|
+
status: axios.isAxiosError(error) ? error.response?.status : "network error",
|
450
|
+
message: error.message,
|
451
|
+
},
|
452
|
+
);
|
453
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
454
|
+
continue;
|
455
|
+
}
|
456
|
+
|
457
|
+
throw lastError;
|
458
|
+
}
|
459
|
+
}
|
460
|
+
|
461
|
+
throw lastError!;
|
462
|
+
}
|
463
|
+
|
418
464
|
export async function waitFor(text: string, maxAttempts = 15): Promise<string[]> {
|
419
465
|
const port = getEnv("SPECULOS_API_PORT");
|
420
|
-
const address =
|
466
|
+
const address = getSpeculosAddress();
|
421
467
|
const url = `${address}:${port}/events?stream=false¤tscreenonly=true`;
|
422
468
|
|
423
469
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
424
|
-
const { data } = await axios.get<ResponseData>(url);
|
470
|
+
const { data } = await retryAxiosRequest(() => axios.get<ResponseData>(url));
|
425
471
|
const texts = data.events.map(event => event.text);
|
426
472
|
|
427
473
|
if (texts?.some(t => t?.toLowerCase().includes(text.toLowerCase()))) {
|
@@ -436,10 +482,12 @@ export async function waitFor(text: string, maxAttempts = 15): Promise<string[]>
|
|
436
482
|
|
437
483
|
export async function pressBoth() {
|
438
484
|
const speculosApiPort = getEnv("SPECULOS_API_PORT");
|
439
|
-
const speculosAddress =
|
440
|
-
await
|
441
|
-
|
442
|
-
|
485
|
+
const speculosAddress = getSpeculosAddress();
|
486
|
+
await retryAxiosRequest(() =>
|
487
|
+
axios.post(`${speculosAddress}:${speculosApiPort}/button/both`, {
|
488
|
+
action: "press-and-release",
|
489
|
+
}),
|
490
|
+
);
|
443
491
|
}
|
444
492
|
|
445
493
|
export async function pressUntilTextFound(
|
@@ -465,27 +513,33 @@ export async function pressUntilTextFound(
|
|
465
513
|
}
|
466
514
|
|
467
515
|
async function fetchCurrentScreenTexts(speculosApiPort: number): Promise<string> {
|
468
|
-
const speculosAddress =
|
469
|
-
const response = await
|
470
|
-
|
516
|
+
const speculosAddress = getSpeculosAddress();
|
517
|
+
const response = await retryAxiosRequest(() =>
|
518
|
+
axios.get<ResponseData>(
|
519
|
+
`${speculosAddress}:${speculosApiPort}/events?stream=false¤tscreenonly=true`,
|
520
|
+
),
|
471
521
|
);
|
472
522
|
return response.data.events.map(event => event.text).join("");
|
473
523
|
}
|
474
524
|
|
475
525
|
async function fetchAllEvents(speculosApiPort: number): Promise<string[]> {
|
476
|
-
const speculosAddress =
|
477
|
-
const response = await
|
478
|
-
|
526
|
+
const speculosAddress = getSpeculosAddress();
|
527
|
+
const response = await retryAxiosRequest(() =>
|
528
|
+
axios.get<ResponseData>(
|
529
|
+
`${speculosAddress}:${speculosApiPort}/events?stream=false¤tscreenonly=false`,
|
530
|
+
),
|
479
531
|
);
|
480
532
|
return response.data.events.map(event => event.text);
|
481
533
|
}
|
482
534
|
|
483
535
|
export async function pressRightButton(): Promise<void> {
|
484
536
|
const speculosApiPort = getEnv("SPECULOS_API_PORT");
|
485
|
-
const speculosAddress =
|
486
|
-
await
|
487
|
-
|
488
|
-
|
537
|
+
const speculosAddress = getSpeculosAddress();
|
538
|
+
await retryAxiosRequest(() =>
|
539
|
+
axios.post(`${speculosAddress}:${speculosApiPort}/button/right`, {
|
540
|
+
action: "press-and-release",
|
541
|
+
}),
|
542
|
+
);
|
489
543
|
}
|
490
544
|
|
491
545
|
export function containsSubstringInEvent(targetString: string, events: string[]): boolean {
|
@@ -503,12 +557,14 @@ export function containsSubstringInEvent(targetString: string, events: string[])
|
|
503
557
|
}
|
504
558
|
|
505
559
|
export async function takeScreenshot(port?: number): Promise<Buffer | undefined> {
|
506
|
-
const speculosAddress =
|
560
|
+
const speculosAddress = getSpeculosAddress();
|
507
561
|
const speculosApiPort = port ?? getEnv("SPECULOS_API_PORT");
|
508
562
|
try {
|
509
|
-
const response = await
|
510
|
-
|
511
|
-
|
563
|
+
const response = await retryAxiosRequest(() =>
|
564
|
+
axios.get(`${speculosAddress}:${speculosApiPort}/screenshot`, {
|
565
|
+
responseType: "arraybuffer",
|
566
|
+
}),
|
567
|
+
);
|
512
568
|
return response.data;
|
513
569
|
} catch (error) {
|
514
570
|
console.error("Error downloading speculos screenshot:", error);
|
package/src/e2e/speculosCI.ts
CHANGED
@@ -61,22 +61,44 @@ async function githubApiRequest<T = unknown>({
|
|
61
61
|
function waitForSpeculosReady(url: string, { interval = 2000, timeout = 300_000 } = {}) {
|
62
62
|
return new Promise((resolve, reject) => {
|
63
63
|
const startTime = Date.now();
|
64
|
+
let currentRequest: ReturnType<typeof https.get> | null = null;
|
65
|
+
|
66
|
+
function cleanup() {
|
67
|
+
if (currentRequest) {
|
68
|
+
currentRequest.destroy();
|
69
|
+
currentRequest = null;
|
70
|
+
}
|
71
|
+
}
|
64
72
|
|
65
73
|
function check() {
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
}
|
75
|
-
|
74
|
+
cleanup();
|
75
|
+
|
76
|
+
currentRequest = https.get(url, { timeout: 10000 }, res => {
|
77
|
+
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 400) {
|
78
|
+
process.env.SPECULOS_ADDRESS = url;
|
79
|
+
cleanup();
|
80
|
+
console.warn(`Speculos is ready at ${url}`);
|
81
|
+
resolve(true);
|
82
|
+
} else {
|
83
|
+
console.warn(`Speculos not ready yet, status: ${res.statusCode}`);
|
84
|
+
retry();
|
85
|
+
}
|
86
|
+
});
|
87
|
+
|
88
|
+
currentRequest.on("error", error => {
|
89
|
+
console.error(`Request error: ${error.message}`);
|
90
|
+
retry();
|
91
|
+
});
|
92
|
+
|
93
|
+
currentRequest.on("timeout", () => {
|
94
|
+
console.error("Request timeout");
|
95
|
+
retry();
|
96
|
+
});
|
76
97
|
}
|
77
98
|
|
78
99
|
function retry() {
|
79
100
|
if (Date.now() - startTime >= timeout) {
|
101
|
+
cleanup();
|
80
102
|
reject(new Error(`Timeout: ${url} did not become available within ${timeout}ms`));
|
81
103
|
} else {
|
82
104
|
setTimeout(check, interval);
|