From 7f96077139f50eb2fb4ed2bfe4533fb1b083b8f1 Mon Sep 17 00:00:00 2001 From: Kieran Allen Date: Tue, 10 Oct 2023 10:57:42 +0100 Subject: [PATCH 1/4] feat: add 10s timeout on estimate gas calls for --- apps/ledger-live-desktop/static/i18n/en/app.json | 3 +++ .../ledger-live-mobile/src/locales/en/common.json | 3 +++ libs/coin-evm/src/api/node/ledger.ts | 6 ++++-- .../src/exchange/swap/hooks/useSwapTransaction.ts | 15 +++++++++++++-- libs/ledgerjs/packages/errors/src/index.ts | 1 + 5 files changed, 24 insertions(+), 4 deletions(-) diff --git a/apps/ledger-live-desktop/static/i18n/en/app.json b/apps/ledger-live-desktop/static/i18n/en/app.json index c5b778d3c2ba..b15e5f55082c 100644 --- a/apps/ledger-live-desktop/static/i18n/en/app.json +++ b/apps/ledger-live-desktop/static/i18n/en/app.json @@ -5423,6 +5423,9 @@ "FeeNotLoaded": { "title": "Couldn't load fee rates. Please set manual fees" }, + "FeeNotLoadedSwap": { + "title": "Network fee estimation failed because of technical issues. Try again or change the assets." + }, "FeeRequired": { "title": "Fees are required" }, diff --git a/apps/ledger-live-mobile/src/locales/en/common.json b/apps/ledger-live-mobile/src/locales/en/common.json index af26007c8411..59d667a58e5b 100644 --- a/apps/ledger-live-mobile/src/locales/en/common.json +++ b/apps/ledger-live-mobile/src/locales/en/common.json @@ -304,6 +304,9 @@ "FeeNotLoaded": { "title": "Could not load fee rates" }, + "FeeNotLoadedSwap": { + "title": "Network fee estimation failed because of technical issues. Try again or change the assets." + }, "FeeRequired": { "title": "Fees are required" }, diff --git a/libs/coin-evm/src/api/node/ledger.ts b/libs/coin-evm/src/api/node/ledger.ts index 36a550b33a10..f05dc03cc95c 100644 --- a/libs/coin-evm/src/api/node/ledger.ts +++ b/libs/coin-evm/src/api/node/ledger.ts @@ -15,7 +15,8 @@ import { NodeApi, isLedgerNodeConfig } from "./types"; import { getGasOptions } from "../gasTracker/ledger"; import { padHexString } from "../../logic"; -export const LEDGER_TIMEOUT = 200; // 200ms between 2 calls +export const LEDGER_TIMEOUT = 10000; +export const LEDGER_TIME_BETWEEN_TRIES = 200; // 200ms between 2 calls export const DEFAULT_RETRIES_API = 2; export async function fetchWithRetries( @@ -35,7 +36,7 @@ export async function fetchWithRetries( } catch (e) { if (retries) { // wait the API timeout before trying again - await delay(LEDGER_TIMEOUT); + await delay(LEDGER_TIME_BETWEEN_TRIES); // decrement with prefix here or it won't work return fetchWithRetries(params, --retries); } @@ -185,6 +186,7 @@ export const getGasEstimation: NodeApi["getGasEstimation"] = async ( estimated_gas_limit: string; }>({ method: "POST", + timeout: LEDGER_TIMEOUT, url: `${getEnv("EXPLORER")}/blockchain/v4/${node.explorerId}/tx/estimate-gas-limit`, data: { from: account.freshAddress, // should be necessary for some estimations diff --git a/libs/ledger-live-common/src/exchange/swap/hooks/useSwapTransaction.ts b/libs/ledger-live-common/src/exchange/swap/hooks/useSwapTransaction.ts index 6c8c4fe25d08..1eae6d66b748 100644 --- a/libs/ledger-live-common/src/exchange/swap/hooks/useSwapTransaction.ts +++ b/libs/ledger-live-common/src/exchange/swap/hooks/useSwapTransaction.ts @@ -1,4 +1,10 @@ -import { AmountRequired, NotEnoughGas, NotEnoughGasSwap } from "@ledgerhq/errors"; +import { + AmountRequired, + FeeNotLoaded, + FeeNotLoadedSwap, + NotEnoughGas, + NotEnoughGasSwap, +} from "@ledgerhq/errors"; import { useMemo } from "react"; import { SwapSelectorStateType, @@ -73,6 +79,11 @@ export const useFromAmountStatusMessage = ( }); } + // convert to swap variation of error to display correct message to frontend. + if (relevantStatus instanceof FeeNotLoaded) { + return new FeeNotLoadedSwap(); + } + return relevantStatus; }, [statusEntries, currency, estimatedFees, transaction?.amount, account?.id, parentAccount?.id]); }; @@ -123,7 +134,7 @@ export const useSwapTransaction = ({ const { account: toAccount } = toState; const transaction = bridgeTransaction?.transaction; - const fromAmountError = useFromAmountStatusMessage(bridgeTransaction, ["amount"]); + const fromAmountError = useFromAmountStatusMessage(bridgeTransaction, ["amount", "gasLimit"]); // treat the gasPrice error as a warning for swap. const fromAmountWarning = useFromAmountStatusMessage(bridgeTransaction, ["gasPrice"]); diff --git a/libs/ledgerjs/packages/errors/src/index.ts b/libs/ledgerjs/packages/errors/src/index.ts index bd7aea298cea..db9455b766e2 100644 --- a/libs/ledgerjs/packages/errors/src/index.ts +++ b/libs/ledgerjs/packages/errors/src/index.ts @@ -140,6 +140,7 @@ export const WrongAppForCurrency = createCustomErrorClass("WrongAppForCurrency") export const ETHAddressNonEIP = createCustomErrorClass("ETHAddressNonEIP"); export const CantScanQRCode = createCustomErrorClass("CantScanQRCode"); export const FeeNotLoaded = createCustomErrorClass("FeeNotLoaded"); +export const FeeNotLoadedSwap = createCustomErrorClass("FeeNotLoadedSwap"); export const FeeRequired = createCustomErrorClass("FeeRequired"); export const FeeTooHigh = createCustomErrorClass("FeeTooHigh"); export const PendingOperation = createCustomErrorClass("PendingOperation"); From 687782f7312a16761837e0603c516ab8c35b17c5 Mon Sep 17 00:00:00 2001 From: Kieran Allen Date: Tue, 10 Oct 2023 11:02:14 +0100 Subject: [PATCH 2/4] chore: add changeset --- .changeset/silver-lamps-warn.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .changeset/silver-lamps-warn.md diff --git a/.changeset/silver-lamps-warn.md b/.changeset/silver-lamps-warn.md new file mode 100644 index 000000000000..5322fba1a3cd --- /dev/null +++ b/.changeset/silver-lamps-warn.md @@ -0,0 +1,9 @@ +--- +"@ledgerhq/errors": patch +"ledger-live-desktop": patch +"live-mobile": patch +"@ledgerhq/live-common": patch +"@ledgerhq/coin-evm": patch +--- + +add 10s timeout to estimate gas From 4261b20bfbd74fb8f7eeacea50e479fad7a670a6 Mon Sep 17 00:00:00 2001 From: Kieran Allen Date: Wed, 25 Oct 2023 13:44:17 +0100 Subject: [PATCH 3/4] feat: add comment and num formatting --- libs/coin-evm/src/api/node/ledger.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/coin-evm/src/api/node/ledger.ts b/libs/coin-evm/src/api/node/ledger.ts index f05dc03cc95c..83f895a853ec 100644 --- a/libs/coin-evm/src/api/node/ledger.ts +++ b/libs/coin-evm/src/api/node/ledger.ts @@ -15,7 +15,7 @@ import { NodeApi, isLedgerNodeConfig } from "./types"; import { getGasOptions } from "../gasTracker/ledger"; import { padHexString } from "../../logic"; -export const LEDGER_TIMEOUT = 10000; +export const LEDGER_TIMEOUT = 10_000; // 10_000ms (10s) for network call timeout export const LEDGER_TIME_BETWEEN_TRIES = 200; // 200ms between 2 calls export const DEFAULT_RETRIES_API = 2; From 4838edcfde85fcd1bcaa9d0b6e27c4ae796f007d Mon Sep 17 00:00:00 2001 From: Kieran Allen Date: Wed, 25 Oct 2023 16:10:27 +0100 Subject: [PATCH 4/4] feat: add unit test --- .../__tests__/unit/api/node/ledger.unit.test.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/libs/coin-evm/src/__tests__/unit/api/node/ledger.unit.test.ts b/libs/coin-evm/src/__tests__/unit/api/node/ledger.unit.test.ts index 52b392078286..3cd0cea1bb1d 100644 --- a/libs/coin-evm/src/__tests__/unit/api/node/ledger.unit.test.ts +++ b/libs/coin-evm/src/__tests__/unit/api/node/ledger.unit.test.ts @@ -275,6 +275,22 @@ describe("EVM Family", () => { } }); + it("should throw GasEstimationError if request throws ECONNABORTED", async () => { + jest + .spyOn(axios, "request") + .mockImplementation(() => Promise.reject({ code: "ECONNABORTED" })); + + try { + await LEDGER_API.getGasEstimation(account, {} as any); + fail("Promise should have been rejected"); + } catch (e) { + if (e instanceof AssertionError) { + throw e; + } + expect(e).toBeInstanceOf(GasEstimationError); + } + }); + it("should return the expected payload", async () => { jest.spyOn(axios, "request").mockImplementation(async ({ data: transaction }) => { return (transaction as any)?.data?.length > 2