@ledgerhq/live-common 34.42.2-nightly.0 → 34.43.0-nightly.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/lib/appSupportsQuitApp.d.ts +1 -0
- package/lib/appSupportsQuitApp.d.ts.map +1 -1
- package/lib/appSupportsQuitApp.js +1 -0
- package/lib/appSupportsQuitApp.js.map +1 -1
- package/lib/appSupportsQuitApp.test.js +28 -3
- package/lib/appSupportsQuitApp.test.js.map +1 -1
- package/lib/bridge/generic-alpaca/alpaca/index.d.ts +1 -1
- package/lib/bridge/generic-alpaca/alpaca/index.d.ts.map +1 -1
- package/lib/bridge/generic-alpaca/alpaca/index.js.map +1 -1
- package/lib/bridge/generic-alpaca/alpaca/network/network-alpaca.d.ts +2 -6
- package/lib/bridge/generic-alpaca/alpaca/network/network-alpaca.d.ts.map +1 -1
- package/lib/bridge/generic-alpaca/alpaca/network/network-alpaca.js.map +1 -1
- package/lib/bridge/generic-alpaca/signOperation.js.map +1 -1
- package/lib/bridge/generic-alpaca/utils.d.ts +2 -2
- package/lib/bridge/generic-alpaca/utils.d.ts.map +1 -1
- package/lib/bridge/generic-alpaca/utils.js +1 -1
- package/lib/bridge/generic-alpaca/utils.js.map +1 -1
- 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/appSupportsQuitApp.d.ts +1 -0
- package/lib-es/appSupportsQuitApp.d.ts.map +1 -1
- package/lib-es/appSupportsQuitApp.js +1 -0
- package/lib-es/appSupportsQuitApp.js.map +1 -1
- package/lib-es/appSupportsQuitApp.test.js +6 -1
- package/lib-es/appSupportsQuitApp.test.js.map +1 -1
- package/lib-es/bridge/generic-alpaca/alpaca/index.d.ts +1 -1
- package/lib-es/bridge/generic-alpaca/alpaca/index.d.ts.map +1 -1
- package/lib-es/bridge/generic-alpaca/alpaca/index.js.map +1 -1
- package/lib-es/bridge/generic-alpaca/alpaca/network/network-alpaca.d.ts +2 -6
- package/lib-es/bridge/generic-alpaca/alpaca/network/network-alpaca.d.ts.map +1 -1
- package/lib-es/bridge/generic-alpaca/alpaca/network/network-alpaca.js.map +1 -1
- package/lib-es/bridge/generic-alpaca/signOperation.js.map +1 -1
- package/lib-es/bridge/generic-alpaca/utils.d.ts +2 -2
- package/lib-es/bridge/generic-alpaca/utils.d.ts.map +1 -1
- package/lib-es/bridge/generic-alpaca/utils.js +1 -1
- package/lib-es/bridge/generic-alpaca/utils.js.map +1 -1
- 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 +46 -46
- package/src/appSupportsQuitApp.test.ts +7 -1
- package/src/appSupportsQuitApp.ts +1 -0
- package/src/bridge/generic-alpaca/alpaca/index.ts +3 -3
- package/src/bridge/generic-alpaca/alpaca/network/network-alpaca.ts +3 -8
- package/src/bridge/generic-alpaca/signOperation.ts +1 -1
- package/src/bridge/generic-alpaca/utils.ts +3 -10
- 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
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.2",
|
5
5
|
"repository": {
|
6
6
|
"type": "git",
|
7
7
|
"url": "https://github.com/LedgerHQ/ledger-live.git"
|
@@ -162,73 +162,73 @@
|
|
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.
|
167
|
-
"@ledgerhq/coin-bitcoin": "^0.18.1-nightly.
|
168
|
-
"@ledgerhq/coin-cardano": "^0.10.1-nightly.
|
169
|
-
"@ledgerhq/coin-casper": "^2.0.6-nightly.
|
170
|
-
"@ledgerhq/coin-celo": "^1.1.13-nightly.
|
171
|
-
"@ledgerhq/coin-cosmos": "^0.16.4-nightly.
|
172
|
-
"@ledgerhq/coin-
|
173
|
-
"@ledgerhq/coin-
|
174
|
-
"@ledgerhq/coin-framework": "^5.
|
175
|
-
"@ledgerhq/coin-
|
176
|
-
"@ledgerhq/coin-
|
177
|
-
"@ledgerhq/coin-internet_computer": "^1.7.15-nightly.
|
178
|
-
"@ledgerhq/coin-mina": "^1.1.14-nightly.
|
179
|
-
"@ledgerhq/coin-multiversx": "^0.4.15-nightly.
|
180
|
-
"@ledgerhq/coin-near": "^0.11.15-nightly.
|
181
|
-
"@ledgerhq/coin-polkadot": "^6.
|
182
|
-
"@ledgerhq/coin-solana": "^0.
|
183
|
-
"@ledgerhq/coin-stacks": "^0.8.15-nightly.
|
184
|
-
"@ledgerhq/coin-stellar": "^5.
|
185
|
-
"@ledgerhq/coin-
|
186
|
-
"@ledgerhq/coin-
|
187
|
-
"@ledgerhq/coin-ton": "^0.13.4-nightly.
|
188
|
-
"@ledgerhq/coin-tron": "^4.
|
189
|
-
"@ledgerhq/coin-vechain": "^2.7.15-nightly.0",
|
190
|
-
"@ledgerhq/coin-xrp": "^6.4.2-nightly.0",
|
165
|
+
"@ledgerhq/coin-algorand": "^0.9.15-nightly.2",
|
166
|
+
"@ledgerhq/coin-aptos": "^2.7.0-nightly.2",
|
167
|
+
"@ledgerhq/coin-bitcoin": "^0.18.1-nightly.2",
|
168
|
+
"@ledgerhq/coin-cardano": "^0.10.1-nightly.2",
|
169
|
+
"@ledgerhq/coin-casper": "^2.0.6-nightly.2",
|
170
|
+
"@ledgerhq/coin-celo": "^1.1.13-nightly.2",
|
171
|
+
"@ledgerhq/coin-cosmos": "^0.16.4-nightly.2",
|
172
|
+
"@ledgerhq/coin-filecoin": "^1.9.15-nightly.2",
|
173
|
+
"@ledgerhq/coin-evm": "^2.25.0-nightly.2",
|
174
|
+
"@ledgerhq/coin-framework": "^5.8.0-nightly.2",
|
175
|
+
"@ledgerhq/coin-icon": "^0.11.2-nightly.2",
|
176
|
+
"@ledgerhq/coin-hedera": "^1.9.1-nightly.2",
|
177
|
+
"@ledgerhq/coin-internet_computer": "^1.7.15-nightly.2",
|
178
|
+
"@ledgerhq/coin-mina": "^1.1.14-nightly.2",
|
179
|
+
"@ledgerhq/coin-multiversx": "^0.4.15-nightly.2",
|
180
|
+
"@ledgerhq/coin-near": "^0.11.15-nightly.2",
|
181
|
+
"@ledgerhq/coin-polkadot": "^6.5.0-nightly.2",
|
182
|
+
"@ledgerhq/coin-solana": "^0.29.0-nightly.2",
|
183
|
+
"@ledgerhq/coin-stacks": "^0.8.15-nightly.2",
|
184
|
+
"@ledgerhq/coin-stellar": "^5.4.0-nightly.2",
|
185
|
+
"@ledgerhq/coin-tezos": "^5.7.0-nightly.2",
|
186
|
+
"@ledgerhq/coin-sui": "^0.8.0-nightly.2",
|
187
|
+
"@ledgerhq/coin-ton": "^0.13.4-nightly.2",
|
188
|
+
"@ledgerhq/coin-tron": "^4.5.0-nightly.2",
|
191
189
|
"@ledgerhq/crypto-icons-ui": "^1.16.0",
|
192
|
-
"@ledgerhq/cryptoassets": "^13.
|
193
|
-
"@ledgerhq/
|
190
|
+
"@ledgerhq/cryptoassets": "^13.23.0-nightly.1",
|
191
|
+
"@ledgerhq/coin-xrp": "^6.5.0-nightly.2",
|
192
|
+
"@ledgerhq/device-core": "^0.5.4-nightly.1",
|
194
193
|
"@ledgerhq/devices": "8.4.8",
|
195
194
|
"@ledgerhq/errors": "^6.23.0",
|
195
|
+
"@ledgerhq/coin-vechain": "^2.8.0-nightly.2",
|
196
196
|
"@ledgerhq/hw-app-algorand": "^6.31.4",
|
197
197
|
"@ledgerhq/hw-app-aptos": "^6.34.4",
|
198
|
+
"@ledgerhq/hw-app-celo": "^6.33.11-nightly.1",
|
198
199
|
"@ledgerhq/hw-app-btc": "^10.10.0",
|
199
|
-
"@ledgerhq/hw-app-celo": "^6.33.11-nightly.0",
|
200
|
-
"@ledgerhq/hw-app-cosmos": "^6.32.4",
|
201
|
-
"@ledgerhq/hw-app-eth": "^6.45.13-nightly.0",
|
202
200
|
"@ledgerhq/hw-app-exchange": "^0.10.4",
|
201
|
+
"@ledgerhq/hw-app-cosmos": "^6.32.4",
|
203
202
|
"@ledgerhq/hw-app-hedera": "^1.2.4",
|
204
203
|
"@ledgerhq/hw-app-icon": "^1.3.4",
|
205
204
|
"@ledgerhq/hw-app-multiversx": "^6.24.4",
|
206
205
|
"@ledgerhq/hw-app-near": "^6.31.4",
|
207
206
|
"@ledgerhq/hw-app-polkadot": "^6.34.4",
|
208
207
|
"@ledgerhq/hw-app-str": "^7.2.4",
|
209
|
-
"@ledgerhq/hw-app-sui": "^1.2.0",
|
210
|
-
"@ledgerhq/hw-app-tezos": "^6.31.4",
|
211
208
|
"@ledgerhq/hw-app-trx": "^6.31.4",
|
212
|
-
"@ledgerhq/hw-app-
|
209
|
+
"@ledgerhq/hw-app-tezos": "^6.31.4",
|
210
|
+
"@ledgerhq/hw-app-vet": "^0.5.11-nightly.1",
|
211
|
+
"@ledgerhq/hw-app-sui": "^1.2.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/
|
219
|
-
"@ledgerhq/live-countervalues
|
217
|
+
"@ledgerhq/hw-app-eth": "^6.45.13-nightly.1",
|
218
|
+
"@ledgerhq/live-countervalues": "^0.5.15-nightly.2",
|
219
|
+
"@ledgerhq/live-countervalues-react": "^0.2.44-nightly.2",
|
220
220
|
"@ledgerhq/live-dmk-shared": "^0.11.1",
|
221
|
-
"@ledgerhq/live-
|
221
|
+
"@ledgerhq/live-network": "^2.0.14-nightly.0",
|
222
222
|
"@ledgerhq/live-hooks": "0.1.0",
|
223
|
-
"@ledgerhq/live-
|
224
|
-
"@ledgerhq/live-nft": "^0.8.15-nightly.0",
|
223
|
+
"@ledgerhq/live-nft": "^0.8.15-nightly.2",
|
225
224
|
"@ledgerhq/live-promise": "^0.1.1",
|
226
|
-
"@ledgerhq/live-
|
227
|
-
"@ledgerhq/live-signer-
|
228
|
-
"@ledgerhq/live-
|
225
|
+
"@ledgerhq/live-env": "^2.13.0-nightly.0",
|
226
|
+
"@ledgerhq/live-signer-evm": "^0.6.2-nightly.2",
|
227
|
+
"@ledgerhq/live-signer-solana": "^0.5.0-nightly.2",
|
229
228
|
"@ledgerhq/logs": "^6.13.0",
|
230
|
-
"@ledgerhq/
|
229
|
+
"@ledgerhq/live-wallet": "^0.11.6-nightly.2",
|
231
230
|
"@ledgerhq/wallet-api-acre-module": "^0.5.0",
|
231
|
+
"@ledgerhq/speculos-transport": "^0.2.7-nightly.0",
|
232
232
|
"@ledgerhq/wallet-api-exchange-module": "^0.14.0"
|
233
233
|
},
|
234
234
|
"devDependencies": {
|
@@ -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"
|
@@ -1,4 +1,5 @@
|
|
1
|
-
import appSupportsQuitApp from "./appSupportsQuitApp";
|
1
|
+
import appSupportsQuitApp, { minAppVersion } from "./appSupportsQuitApp";
|
2
|
+
|
2
3
|
test("appSupportsQuitApp - Apps that are listed fail if version is lt", () => {
|
3
4
|
expect(
|
4
5
|
appSupportsQuitApp({
|
@@ -26,3 +27,8 @@ test("appSupportsQuitApp - Apps that are not listed pass the test", () => {
|
|
26
27
|
}),
|
27
28
|
).toBeTruthy();
|
28
29
|
});
|
30
|
+
test("minAppVersion - Sonic and Ethereum have the same min app version", () => {
|
31
|
+
expect(minAppVersion["Sonic"]).toBeDefined();
|
32
|
+
expect(minAppVersion["Ethereum"]).toBeDefined();
|
33
|
+
expect(minAppVersion["Sonic"]).toBe(minAppVersion["Ethereum"]);
|
34
|
+
});
|
@@ -5,16 +5,16 @@ import { getNetworkAlpacaApi } from "./network/network-alpaca";
|
|
5
5
|
import { Api } from "@ledgerhq/coin-framework/api/types";
|
6
6
|
import { XrpCoinConfig } from "@ledgerhq/coin-xrp/config";
|
7
7
|
|
8
|
-
export function getAlpacaApi(network: string, kind: "local" | "remote"): Api<any
|
8
|
+
export function getAlpacaApi(network: string, kind: "local" | "remote"): Api<any> {
|
9
9
|
if (kind === "local") {
|
10
10
|
switch (network) {
|
11
11
|
case "ripple":
|
12
12
|
case "xrp":
|
13
13
|
return createXrpApi(
|
14
14
|
getCurrencyConfiguration<XrpCoinConfig>(getCryptoCurrencyById("ripple")),
|
15
|
-
) as Api<any
|
15
|
+
) as Api<any>;
|
16
16
|
// as unknown as Api<any>; // FIXME: createXrpApi returns a strongly typed Api<XrpSender>, fix Api<any> to allow it
|
17
17
|
}
|
18
18
|
}
|
19
|
-
return getNetworkAlpacaApi(network) satisfies Partial<Api<any
|
19
|
+
return getNetworkAlpacaApi(network) satisfies Partial<Api<any>> as Api<any>;
|
20
20
|
}
|
@@ -107,14 +107,9 @@ const buildValidateIntent = (networkFamily: string) =>
|
|
107
107
|
return data;
|
108
108
|
};
|
109
109
|
|
110
|
-
// FIXME: shouldn't hardcode
|
111
|
-
type AssetInfo = {
|
112
|
-
type: "native"; // or "token" if applicable
|
113
|
-
};
|
114
|
-
|
115
110
|
const buildGetBalance = (networkFamily: string) =>
|
116
|
-
async function getBalance(address: string): Promise<Balance
|
117
|
-
const { data } = await network<Balance
|
111
|
+
async function getBalance(address: string): Promise<Balance[]> {
|
112
|
+
const { data } = await network<Balance, unknown>({
|
118
113
|
method: "GET",
|
119
114
|
url: `${ALPACA_URL}/${networkFamily}/account/${address}/balance`,
|
120
115
|
});
|
@@ -191,7 +186,7 @@ export const getNetworkAlpacaApi = (networkFamily: string) =>
|
|
191
186
|
listOperations: buildListOperations(networkFamily),
|
192
187
|
lastBlock: buildLastBlock(networkFamily),
|
193
188
|
craftTransaction: buildCraftTransaction(networkFamily),
|
194
|
-
getBlock(_height): Promise<Block
|
189
|
+
getBlock(_height): Promise<Block> {
|
195
190
|
throw new Error("getBlock is not supported");
|
196
191
|
},
|
197
192
|
getBlockInfo(_height: number): Promise<BlockInfo> {
|
@@ -40,7 +40,7 @@ export const genericSignOperation =
|
|
40
40
|
const transactionIntent = transactionToIntent(account, transaction);
|
41
41
|
transactionIntent.senderPublicKey = publicKey;
|
42
42
|
// NOTE: is setting the memo here instead of transactionToIntent sensible?
|
43
|
-
const txWithMemo = transactionIntent as TransactionIntent<
|
43
|
+
const txWithMemo = transactionIntent as TransactionIntent<MapMemo<string, string>>;
|
44
44
|
if (transaction["tag"]) {
|
45
45
|
const txMemo = String(transaction["tag"]);
|
46
46
|
txWithMemo.memo = {
|
@@ -1,17 +1,10 @@
|
|
1
1
|
import { encodeOperationId } from "@ledgerhq/coin-framework/operation";
|
2
2
|
import { Account, Operation, OperationType, TransactionCommon } from "@ledgerhq/types-live";
|
3
|
-
import {
|
4
|
-
Operation as CoreOperation,
|
5
|
-
Asset,
|
6
|
-
TransactionIntent,
|
7
|
-
} from "@ledgerhq/coin-framework/api/types";
|
3
|
+
import { Operation as CoreOperation, TransactionIntent } from "@ledgerhq/coin-framework/api/types";
|
8
4
|
import BigNumber from "bignumber.js";
|
9
5
|
import { fromBigNumberToBigInt } from "@ledgerhq/coin-framework/utils";
|
10
6
|
|
11
|
-
export function adaptCoreOperationToLiveOperation(
|
12
|
-
accountId: string,
|
13
|
-
op: CoreOperation<Asset>,
|
14
|
-
): Operation {
|
7
|
+
export function adaptCoreOperationToLiveOperation(accountId: string, op: CoreOperation): Operation {
|
15
8
|
return {
|
16
9
|
id: encodeOperationId(accountId, op.tx.hash, op.type),
|
17
10
|
hash: op.tx.hash,
|
@@ -38,7 +31,7 @@ export function transactionToIntent(
|
|
38
31
|
sender: account.freshAddress,
|
39
32
|
recipient: transaction.recipient,
|
40
33
|
amount: fromBigNumberToBigInt(transaction.amount, BigInt(0)),
|
41
|
-
asset:
|
34
|
+
asset: { type: "native" },
|
42
35
|
};
|
43
36
|
}
|
44
37
|
|
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);
|