Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/LIVE-12193 track swap cancel accept #6799

Merged
merged 15 commits into from
May 13, 2024
8 changes: 8 additions & 0 deletions .changeset/swift-pigs-kneel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"ledger-live-desktop": minor
"live-mobile": minor
"@ledgerhq/live-common": minor
"@ledgerhq/wallet-api-exchange-module": minor
---

Track swap cancel and accept with by returning device property from custom.exchange.start handler
4 changes: 2 additions & 2 deletions apps/ledger-live-desktop/src/renderer/actions/UI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ export const openExchangeDrawer = createAction(
fromAccountId?: string;
toAccountId?: string;
tokenCurrency?: string;
onResult: (nonce: string) => void;
onCancel: (error: Error) => void;
onResult: (result: { nonce: string; device: Device }) => void;
onCancel: (cancelResult: { error: Error; device: Device }) => void;
}
| ({
type: "EXCHANGE_COMPLETE";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ import { AppManifest } from "@ledgerhq/live-common/wallet-api/types";
import DeviceAction from "~/renderer/components/DeviceAction";
import {
createAction,
Result as StartExchangeResult,
StartExchangeErrorResult,
StartExchangeSuccessResult,
Result,
andreicovaciu marked this conversation as resolved.
Show resolved Hide resolved
} from "@ledgerhq/live-common/hw/actions/startExchange";
import startExchange from "@ledgerhq/live-common/exchange/platform/startExchange";
import connectApp from "@ledgerhq/live-common/hw/connectApp";
Expand All @@ -35,11 +37,11 @@ const Divider = styled(Box)`
`;

export type StartExchangeData = {
onCancel?: (error: Error) => void;
onCancel?: (startExchangeError: StartExchangeErrorResult) => void;
exchangeType: ExchangeType;
provider?: string;
exchange?: Exchange;
onResult: (startExchangeResult: string) => void;
onResult: (startExchangeResult: StartExchangeSuccessResult) => void;
};

export function isStartExchangeData(data: unknown): data is StartExchangeData {
Expand Down Expand Up @@ -150,12 +152,12 @@ export const LiveAppDrawer = () => {
<DeviceAction
action={action}
request={data}
onResult={(result: StartExchangeResult) => {
onResult={(result: Result) => {
andreicovaciu marked this conversation as resolved.
Show resolved Hide resolved
if ("startExchangeResult" in result) {
data.onResult(result.startExchangeResult as unknown as string);
data.onResult(result.startExchangeResult);
}
if ("startExchangeError" in result) {
data.onCancel?.(result.startExchangeError as unknown as Error);
data.onCancel?.(result.startExchangeError);
dispatch(closePlatformAppDrawer());
}
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,13 +190,13 @@ export const PlatformAPIWebview = forwardRef<WebviewAPI, WebviewProps>(
dispatch(
openModal("MODAL_PLATFORM_EXCHANGE_START", {
exchangeType,
onResult: (nonce: string) => {
onResult: result => {
tracking.platformStartExchangeSuccess(manifest);
resolve(nonce);
resolve(result.nonce);
},
onCancel: (error: Error) => {
onCancel: cancelResult => {
tracking.platformStartExchangeFail(manifest);
reject(error);
reject(cancelResult.error);
},
}),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,11 +178,11 @@ function useUiHook(manifest: AppManifest, tracking: Record<string, TrackFunction
openExchangeDrawer({
type: "EXCHANGE_START",
exchangeType: ExchangeType[exchangeType],
onResult: (nonce: string) => {
onSuccess(nonce);
onResult: result => {
onSuccess(result.nonce);
},
onCancel: (error: Error) => {
onCancel(error);
onCancel: cancelResult => {
onCancel(cancelResult.error);
},
}),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,11 @@ export function usePTXCustomHandlers(manifest: WebviewProps["manifest"]) {
type: "EXCHANGE_START",
...exchangeParams,
exchangeType: ExchangeType[exchangeParams.exchangeType],
onResult: (nonce: string) => {
onSuccess(nonce);
onResult: result => {
onSuccess(result.nonce, result.device);
},
onCancel: (error: Error) => {
onCancel(error);
onCancel: cancelResult => {
onCancel(cancelResult.error, cancelResult.device);
},
}),
);
Expand Down Expand Up @@ -88,5 +88,5 @@ export function usePTXCustomHandlers(manifest: WebviewProps["manifest"]) {
},
}),
};
}, [accounts, dispatch, manifest, tracking, setDrawer]);
}, [accounts, tracking, manifest, dispatch, setDrawer]);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@ import { createAction } from "@ledgerhq/live-common/hw/actions/startExchange";
import startExchange from "@ledgerhq/live-common/exchange/platform/startExchange";
import { ExchangeType } from "@ledgerhq/live-common/wallet-api/react";
import connectApp from "@ledgerhq/live-common/hw/connectApp";
import {
StartExchangeErrorResult,
StartExchangeSuccessResult,
} from "@ledgerhq/live-common/hw/actions/startExchange";

export type Data = {
onCancel?: (error: Error) => void;
onCancel?: (error: StartExchangeErrorResult) => void;
exchangeType: ExchangeType;
onResult: (startExchangeResult: string) => void;
onResult: (startExchangeResult: StartExchangeSuccessResult) => void;
};
export function isStartExchangeData(data: unknown): data is Data {
if (data === null || typeof data !== "object") {
Expand All @@ -31,7 +35,9 @@ const StartExchange = () => {
<ModalBody
onClose={() => {
if (data.onCancel) {
data.onCancel(new Error("Interrupted by user"));
data.onCancel({
error: new Error("Interrupted by user"),
});
}
onClose?.();
}}
Expand All @@ -44,10 +50,10 @@ const StartExchange = () => {
}}
onResult={result => {
if ("startExchangeResult" in result) {
data.onResult(result.startExchangeResult as string);
data.onResult(result.startExchangeResult);
}
if ("startExchangeError" in result) {
data.onCancel?.(result.startExchangeError as Error);
data.onCancel?.(result.startExchangeError);
}
onClose?.();
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import type { Operation } from "@ledgerhq/types-live";
import { ScreenName } from "~/const";

export type ResultStart = {
startExchangeResult?: string;
startExchangeError?: Error;
startExchangeResult?: { nonce: string; device: Device };
startExchangeError?: { error: Error; device?: Device };
device?: Device;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -336,19 +336,19 @@ export const PlatformAPIWebview = forwardRef<WebviewAPI, WebviewProps>(
provider,
},
onResult: (result: {
startExchangeResult?: string;
startExchangeError?: Error;
startExchangeResult?: { nonce: string; device: Device };
startExchangeError?: { error: Error; device?: Device };
device?: Device;
}) => {
andreicovaciu marked this conversation as resolved.
Show resolved Hide resolved
if (result.startExchangeError) {
tracking.platformStartExchangeFail(manifest);
reject(result.startExchangeError);
reject(result.startExchangeError.error);
}

if (result.startExchangeResult) {
tracking.platformStartExchangeSuccess(manifest);
setDevice(result.device);
resolve(result.startExchangeResult);
resolve(result.startExchangeResult.nonce);
}

const n =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -434,17 +434,17 @@ function useUiHook(): UiHook {
exchangeType: ExchangeType[exchangeType],
},
onResult: (result: {
startExchangeResult?: string;
startExchangeError?: Error;
startExchangeResult?: { nonce: string; device: Device };
startExchangeError?: { error: Error; device?: Device };
device?: Device;
}) => {
andreicovaciu marked this conversation as resolved.
Show resolved Hide resolved
if (result.startExchangeError) {
onCancel(result.startExchangeError);
onCancel(result.startExchangeError.error);
}

if (result.startExchangeResult) {
setDevice(result.device);
onSuccess(result.startExchangeResult);
onSuccess(result.startExchangeResult.nonce);
}

const n =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,18 @@ export function usePTXCustomHandlers(manifest: WebviewProps["manifest"]) {
},
onResult: result => {
if (result.startExchangeError) {
onCancel(result.startExchangeError);
onCancel(
result.startExchangeError.error,
result.startExchangeError.device || device,
);
}

if (result.startExchangeResult) {
setDevice(result.device);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll have to look at this result.device later on to see how we can remove this and instead use result.startExchangeResult.device

onSuccess(result.startExchangeResult);
onSuccess(
result.startExchangeResult.nonce,
result.startExchangeResult.device || device,
);
}

navigation.pop();
Expand Down
5 changes: 4 additions & 1 deletion libs/exchange-module/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ export class ExchangeModule extends CustomModule {
},
);

return result.transactionId;
return {
transactionId: result.transactionId,
device: result.device,
};
}

/**
Expand Down
1 change: 1 addition & 0 deletions libs/exchange-module/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export type ExchangeStartSwapParams = {

export type ExchangeStartResult = {
transactionId: string;
device?: { deviceId?: string; modelId?: string };
};

export type ExchangeCompleteBaseParams = {
Expand Down
10 changes: 5 additions & 5 deletions libs/ledger-live-common/src/exchange/platform/startExchange.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ const withDevicePromise = (deviceId, fn) =>
const startExchange = (input: StartExchangeInput): Observable<ExchangeRequestEvent> => {
return new Observable(o => {
let unsubscribed = false;
const { deviceId, exchangeType, appVersion, provider } = input;
const { device, exchangeType, appVersion, provider } = input;
const startExchangeAsync = async () => {
await withDevicePromise(deviceId, async transport => {
log("exchange", `attempt to connect to ${deviceId}`);
await withDevicePromise(device.deviceId, async transport => {
log("exchange", `attempt to connect to ${device.deviceId}`);
let version;
if (unsubscribed) return;
if (provider) {
Expand Down Expand Up @@ -48,7 +48,7 @@ const startExchange = (input: StartExchangeInput): Observable<ExchangeRequestEve
const nonce: string = await exchange.startNewTransaction();
o.next({
type: "start-exchange-result",
nonce,
startExchangeResult: { nonce, device },
});
});
};
Expand All @@ -61,7 +61,7 @@ const startExchange = (input: StartExchangeInput): Observable<ExchangeRequestEve
error => {
o.next({
type: "start-exchange-error",
error,
startExchangeError: { error, device },
});
o.complete();
unsubscribed = true;
Expand Down
3 changes: 2 additions & 1 deletion libs/ledger-live-common/src/exchange/platform/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { Account, AccountLike, AccountRaw, AccountRawLike } from "@ledgerhq
import { ExchangeTypes, RateTypes } from "@ledgerhq/hw-app-exchange";
import type { Transaction } from "../../generated/types";
import { ExchangeSwap } from "../swap/types";
import { Device } from "../../hw/actions/types";

export type CompleteExchangeRequestEvent =
| { type: "complete-exchange" }
Expand Down Expand Up @@ -29,7 +30,7 @@ export type ExchangeSellRaw = {
};

export type StartExchangeInput = {
deviceId: string;
device: Device;
exchangeType: number;
appVersion?: string;
provider?: string;
Expand Down
33 changes: 23 additions & 10 deletions libs/ledger-live-common/src/hw/actions/startExchange.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,19 @@ import { ExchangeType } from "@ledgerhq/live-app-sdk";
import { getMainAccount } from "../../account";
import { isExchangeSwap, type Exchange } from "../../exchange/types";

export type StartExchangeSuccessResult = {
nonce: string;
device: Device;
};

export type StartExchangeErrorResult = {
error: Error;
device?: Device;
};

type State = {
startExchangeResult: string | null | undefined;
startExchangeError: Error | null | undefined;
startExchangeResult: StartExchangeSuccessResult | null | undefined;
startExchangeError: StartExchangeErrorResult | null | undefined;
freezeReduxDevice: boolean;
isLoading: boolean;
error?: Error; //NB connectApp errors
Expand All @@ -22,17 +32,17 @@ type StartExchangeState = AppState & State;
type StartExchangeRequest = { exchangeType: ExchangeType; provider?: string; exchange?: Exchange };
export type Result =
| {
startExchangeResult: string;
startExchangeResult: StartExchangeSuccessResult;
}
| {
startExchangeError: Error;
startExchangeError: StartExchangeErrorResult;
};

type StartExchangeAction = Action<any, StartExchangeState, Result>;
export type ExchangeRequestEvent =
| { type: "start-exchange" }
| { type: "start-exchange-error"; error: Error }
| { type: "start-exchange-result"; nonce: string };
| { type: "start-exchange-error"; startExchangeError: StartExchangeErrorResult }
| { type: "start-exchange-result"; startExchangeResult: StartExchangeSuccessResult };

const mapResult = ({
startExchangeResult,
Expand Down Expand Up @@ -61,12 +71,15 @@ const reducer = (state: State, e: ExchangeRequestEvent) => {
return { ...state, freezeReduxDevice: true };

case "start-exchange-error":
return { ...state, startExchangeError: e.error, isLoading: false };
return { ...state, startExchangeError: e.startExchangeError, isLoading: false };

case "start-exchange-result":
return {
...state,
startExchangeResult: e.nonce,
startExchangeResult: {
nonce: e.startExchangeResult.nonce,
device: e.startExchangeResult.device,
},
isLoading: false,
};
}
Expand All @@ -85,7 +98,7 @@ function useFrozenValue<T>(value: T, frozen: boolean): T {
export const createAction = (
connectAppExec: (arg0: ConnectAppInput) => Observable<ConnectAppEvent>,
startExchangeExec: (arg0: {
deviceId: string;
device: Device;
exchangeType: ExchangeType;
appVersion?: string;
provider?: string;
Expand Down Expand Up @@ -148,7 +161,7 @@ export const createAction = (
type: "start-exchange",
}),
startExchangeExec({
deviceId: device.deviceId,
device,
exchangeType,
provider,
appVersion: appAndVersion?.version,
Expand Down
4 changes: 2 additions & 2 deletions libs/ledger-live-common/src/wallet-api/Exchange/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ type ExchangeStartParamsUiRequest =
type ExchangeUiHooks = {
"custom.exchange.start": (params: {
exchangeParams: ExchangeStartParamsUiRequest;
onSuccess: (nonce: string) => void;
onCancel: (error: Error) => void;
onSuccess: (nonce: string, device?: ExchangeStartResult["device"]) => void;
onCancel: (error: Error, device?: ExchangeStartResult["device"]) => void;
}) => void;
"custom.exchange.complete": (params: {
exchangeParams: CompleteExchangeUiRequest;
Expand Down