diff --git a/.changeset/giant-wasps-exist.md b/.changeset/giant-wasps-exist.md new file mode 100644 index 000000000000..de7493093d8d --- /dev/null +++ b/.changeset/giant-wasps-exist.md @@ -0,0 +1,6 @@ +--- +"ledger-live-desktop": patch +"@ledgerhq/live-common": patch +--- + +Fix confirmation message for swap web app diff --git a/apps/ledger-live-desktop/src/renderer/components/DeviceAction/index.tsx b/apps/ledger-live-desktop/src/renderer/components/DeviceAction/index.tsx index 4ca1a1b5aebd..a3cbb907d373 100644 --- a/apps/ledger-live-desktop/src/renderer/components/DeviceAction/index.tsx +++ b/apps/ledger-live-desktop/src/renderer/components/DeviceAction/index.tsx @@ -1,4 +1,5 @@ import React, { useEffect, Component } from "react"; +import BigNumber from "bignumber.js"; import { Trans, useTranslation } from "react-i18next"; import { useDispatch, useSelector } from "react-redux"; import { Action } from "@ledgerhq/live-common/hw/actions/types"; @@ -324,15 +325,41 @@ export const DeviceActionDefaultRendering = ({ return renderListingApps(); } - if (completeExchangeStarted && !completeExchangeResult && !completeExchangeError) { + if (completeExchangeStarted && !completeExchangeResult && !completeExchangeError && !isLoading) { const { exchangeType } = request as { exchangeType: number }; // FIXME: could use a TS enum (when LLD will be in TS) or a JS object instead of raw numbers for switch values for clarity switch (exchangeType) { // swap case 0x00: { - // FIXME: should use `renderSwapDeviceConfirmationV2` but all params not available in hookState for this SDK exchange flow - return
{"Confirm swap on your device"}
; + const { + transaction, + exchange, + provider, + rate = 1, + amountExpectedTo = 0, + } = request as { + transaction: Transaction; + exchange: Exchange; + provider: string; + rate: number; + amountExpectedTo: number; + }; + const { estimatedFees } = hookState; + + return renderSwapDeviceConfirmation({ + modelId: device.modelId, + type, + transaction, + exchangeRate: { + provider, + rate: new BigNumber(rate), + } as ExchangeRate, + exchange, + swapDefaultTrack, + amountExpectedTo: amountExpectedTo.toString() ?? undefined, + estimatedFees: estimatedFees?.toString() ?? undefined, + }); } case 0x01: // sell diff --git a/apps/ledger-live-desktop/src/renderer/modals/Platform/Exchange/CompleteExchange/Body.tsx b/apps/ledger-live-desktop/src/renderer/modals/Platform/Exchange/CompleteExchange/Body.tsx index ef615ec85e13..633bd5eaf787 100644 --- a/apps/ledger-live-desktop/src/renderer/modals/Platform/Exchange/CompleteExchange/Body.tsx +++ b/apps/ledger-live-desktop/src/renderer/modals/Platform/Exchange/CompleteExchange/Body.tsx @@ -4,7 +4,6 @@ import { Exchange, ExchangeSwap } from "@ledgerhq/live-common/exchange/platform/ import { Exchange as SwapExchange } from "@ledgerhq/live-common/exchange/swap/types"; import { setBroadcastTransaction } from "@ledgerhq/live-common/exchange/swap/setBroadcastTransaction"; import { getUpdateAccountWithUpdaterParams } from "@ledgerhq/live-common/exchange/swap/getUpdateAccountWithUpdaterParams"; -import { convertParametersToValidFormat } from "@ledgerhq/live-common/exchange/swap/webApp/index"; import { Operation, SignedOperation } from "@ledgerhq/types-live"; import { Transaction } from "@ledgerhq/live-common/generated/types"; import { TokenCurrency } from "@ledgerhq/types-cryptoassets"; @@ -13,6 +12,7 @@ import { ModalBody } from "~/renderer/components/Modal"; import Box from "~/renderer/components/Box"; import { useBroadcast } from "~/renderer/hooks/useBroadcast"; import { BodyContent } from "./BodyContent"; +import { getMagnitudeAwareRate } from "@ledgerhq/live-common/exchange/swap/webApp/index"; export type Data = { provider: string; @@ -32,12 +32,21 @@ const Body = ({ data, onClose }: { data: Data; onClose?: () => void | undefined const dispatch = useDispatch(); const { onResult, onCancel, swapId, rate, ...exchangeParams } = data; const { exchange, provider, transaction: transactionParams } = exchangeParams; + const { amount } = transactionParams; const { fromAccount: account, fromParentAccount: parentAccount, toAccount, } = exchange as ExchangeSwap; - const request = { ...exchangeParams }; + + const magnitudeAwareRate = getMagnitudeAwareRate({ + fromAccount: account, + toAccount, + rate, + }); + const amountExpectedTo = +amount * +magnitudeAwareRate; + + const request = { ...exchangeParams, amountExpectedTo }; const tokenCurrency: TokenCurrency | undefined = account.type === "TokenAccount" ? account.token : undefined; @@ -72,13 +81,10 @@ const Body = ({ data, onClose }: { data: Data; onClose?: () => void | undefined broadcast(signedOperation).then(operation => { // Save swap history if (swapId && rate && toAccount) { - const { result, magnitudeAwareRate } = convertParametersToValidFormat({ + const result = { operation, swapId, - fromAccount: account, - toAccount, - rate, - }); + }; setBroadcastTransaction({ result, provider, @@ -112,6 +118,7 @@ const Body = ({ data, onClose }: { data: Data; onClose?: () => void | undefined onResult, signedOperation, transaction, + magnitudeAwareRate, ]); return ( diff --git a/libs/ledger-live-common/src/exchange/platform/transfer/completeExchange.ts b/libs/ledger-live-common/src/exchange/platform/transfer/completeExchange.ts index f68ab3d4cf7b..73c95d2cbaad 100644 --- a/libs/ledger-live-common/src/exchange/platform/transfer/completeExchange.ts +++ b/libs/ledger-live-common/src/exchange/platform/transfer/completeExchange.ts @@ -125,7 +125,7 @@ const completeExchange = ( o.next({ type: "complete-exchange-requested", - estimatedFees, + estimatedFees: estimatedFees.toString(), }); if (unsubscribed) return; diff --git a/libs/ledger-live-common/src/exchange/platform/types.ts b/libs/ledger-live-common/src/exchange/platform/types.ts index 96ec38fb0198..d2da58a546d1 100644 --- a/libs/ledger-live-common/src/exchange/platform/types.ts +++ b/libs/ledger-live-common/src/exchange/platform/types.ts @@ -1,5 +1,4 @@ import type { Account, AccountLike, AccountRaw, AccountRawLike } from "@ledgerhq/types-live"; -import { BigNumber } from "bignumber.js"; import type { Transaction } from "../../generated/types"; import { ExchangeTypes, RateTypes } from "@ledgerhq/hw-app-exchange"; @@ -7,7 +6,7 @@ export type CompleteExchangeRequestEvent = | { type: "complete-exchange" } | { type: "complete-exchange-requested"; - estimatedFees: BigNumber; + estimatedFees: string; } | { type: "complete-exchange-error"; diff --git a/libs/ledger-live-common/src/exchange/swap/completeExchange.ts b/libs/ledger-live-common/src/exchange/swap/completeExchange.ts index 8cc3ed9e7a3b..5aef45e93a8c 100644 --- a/libs/ledger-live-common/src/exchange/swap/completeExchange.ts +++ b/libs/ledger-live-common/src/exchange/swap/completeExchange.ts @@ -147,6 +147,11 @@ const completeExchange = ( throw convertTransportError(currentStep, e); } + o.next({ + type: "complete-exchange-requested", + estimatedFees: estimatedFees.toString(), + }); + // Swap specific checks to confirm the refund address is correct. if (unsubscribed) return; const refundAddressParameters = await perFamily[ @@ -182,11 +187,6 @@ const completeExchange = ( throw convertTransportError(currentStep, e); } - o.next({ - type: "complete-exchange-requested", - estimatedFees, - }); - if (unsubscribed) return; ignoreTransportError = true; currentStep = "SIGN_COIN_TRANSACTION"; diff --git a/libs/ledger-live-common/src/exchange/swap/webApp/utils.ts b/libs/ledger-live-common/src/exchange/swap/webApp/utils.ts index 3a5e8ba4eec1..fddff8b7f98b 100644 --- a/libs/ledger-live-common/src/exchange/swap/webApp/utils.ts +++ b/libs/ledger-live-common/src/exchange/swap/webApp/utils.ts @@ -32,21 +32,9 @@ export const convertToNonAtomicUnit = (amount, account) => { return amount.shiftedBy(-fromMagnitude); }; -export const convertParametersToValidFormat = ({ - operation, - swapId, - fromAccount, - toAccount, - rate, -}) => { - const result = { operation, swapId }; +export const getMagnitudeAwareRate = ({ fromAccount, toAccount, rate }): BigNumber => { const unitFrom = getAccountUnit(fromAccount); const unitTo = getAccountUnit(toAccount); - const magnitudeAwareRate = new BigNumber(rate).div( - new BigNumber(10).pow(unitFrom.magnitude - unitTo.magnitude), - ); - return { - result, - magnitudeAwareRate, - }; + const magnitudeAwareRate = new BigNumber(rate).shiftedBy(unitTo.magnitude - unitFrom.magnitude); + return magnitudeAwareRate; }; diff --git a/libs/ledger-live-common/src/hw/actions/completeExchange.ts b/libs/ledger-live-common/src/hw/actions/completeExchange.ts index d45cd50aa8a8..0f48135b79b3 100644 --- a/libs/ledger-live-common/src/hw/actions/completeExchange.ts +++ b/libs/ledger-live-common/src/hw/actions/completeExchange.ts @@ -13,6 +13,7 @@ type State = { freezeReduxDevice: boolean; completeExchangeRequested: boolean; isLoading: boolean; + estimatedFees: string | undefined; }; type CompleteExchangeState = AppState & State; @@ -39,7 +40,7 @@ type Result = type CompleteExchangeAction = Action; export type ExchangeRequestEvent = | { type: "complete-exchange" } - | { type: "complete-exchange-requested" } + | { type: "complete-exchange-requested"; estimatedFees: string } | { type: "complete-exchange-error"; error: Error } | { type: "complete-exchange-result"; completeExchangeResult: Transaction }; @@ -63,6 +64,7 @@ const initialState: State = { completeExchangeRequested: false, freezeReduxDevice: false, isLoading: true, + estimatedFees: undefined, }; const reducer = (state: State, e: ExchangeRequestEvent) => { @@ -84,7 +86,7 @@ const reducer = (state: State, e: ExchangeRequestEvent) => { case "complete-exchange-requested": return { ...state, - completeExchangeRequested: true, + estimatedFees: e.estimatedFees, isLoading: false, }; case "complete-exchange-result":