Skip to content

Commit

Permalink
Merge pull request #6799 from LedgerHQ/feat/LIVE-12193-track-swap-can…
Browse files Browse the repository at this point in the history
…cel-accept

Feat/LIVE-12193 track swap cancel accept
  • Loading branch information
Justkant committed May 13, 2024
2 parents a18c28e + 11c839e commit 5b18e6a
Show file tree
Hide file tree
Showing 17 changed files with 94 additions and 63 deletions.
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,8 @@ import { AppManifest } from "@ledgerhq/live-common/wallet-api/types";
import DeviceAction from "~/renderer/components/DeviceAction";
import {
createAction,
Result as StartExchangeResult,
StartExchangeErrorResult,
StartExchangeSuccessResult,
} 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 +36,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 +151,12 @@ export const LiveAppDrawer = () => {
<DeviceAction
action={action}
request={data}
onResult={(result: StartExchangeResult) => {
onResult={result => {
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 @@ -193,13 +193,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 @@ -179,11 +179,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 @@ -338,20 +338,16 @@ export const PlatformAPIWebview = forwardRef<WebviewAPI, WebviewProps>(
exchangeType,
provider,
},
onResult: (result: {
startExchangeResult?: string;
startExchangeError?: Error;
device?: Device;
}) => {
onResult: result => {
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
10 changes: 3 additions & 7 deletions apps/ledger-live-mobile/src/components/Web3AppWebview/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -432,18 +432,14 @@ function useUiHook(): UiHook {
request: {
exchangeType: ExchangeType[exchangeType],
},
onResult: (result: {
startExchangeResult?: string;
startExchangeError?: Error;
device?: Device;
}) => {
onResult: result => {
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);
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

0 comments on commit 5b18e6a

Please sign in to comment.