Skip to content

Commit

Permalink
🩹 (signer-eth) [DSDK-641]: Add list of eth plugins to compatible apps (…
Browse files Browse the repository at this point in the history
  • Loading branch information
aussedatlo authored Jan 21, 2025
2 parents c0558e2 + 8799e83 commit 7642ada
Show file tree
Hide file tree
Showing 14 changed files with 171 additions and 13 deletions.
5 changes: 5 additions & 0 deletions .changeset/smart-shrimps-cheer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@ledgerhq/device-signer-kit-ethereum": patch
---

Don't open Ethereum app if a plugin is already active
5 changes: 5 additions & 0 deletions .changeset/two-peaches-kiss.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@ledgerhq/device-management-kit": patch
---

Add a list of compatible apps for OpenAppDA and SendCommandInAppDA
24 changes: 20 additions & 4 deletions apps/sample/src/components/DeviceActionsView/AllDeviceActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,21 +49,37 @@ export const AllDeviceActions: React.FC<{ sessionId: string }> = ({
title: "Open app",
description:
"Perform all the actions necessary to open an app on the device",
executeDeviceAction: ({ appName, unlockTimeout }, inspect) => {
executeDeviceAction: (
{ appName, unlockTimeout, compatibleAppNames },
inspect,
) => {
const compatibleAppNamesArray: string[] = compatibleAppNames
.split(",")
.map((name) => name.trim());
const deviceAction = new OpenAppDeviceAction({
input: { appName, unlockTimeout },
input: {
appName,
unlockTimeout,
compatibleAppNames: compatibleAppNamesArray,
},
inspect,
});
return dmk.executeDeviceAction({
sessionId,
deviceAction,
});
},
initialValues: { appName: "", unlockTimeout: UNLOCK_TIMEOUT },
initialValues: {
appName: "",
unlockTimeout: UNLOCK_TIMEOUT,
compatibleAppNames: "",
},
deviceModelId,
} satisfies DeviceActionProps<
OpenAppDAOutput,
OpenAppDAInput,
Omit<OpenAppDAInput, "compatibleAppNames"> & {
compatibleAppNames: string;
},
OpenAppDAError,
OpenAppDAIntermediateValue
>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,60 @@ describe("OpenAppDeviceAction", () => {
);
});

it("should end in a success if a compatible app is already opened", (done) => {
getDeviceSessionStateMock.mockReturnValue({
sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,
deviceStatus: DeviceStatus.CONNECTED,
currentApp: {
name: "Bitcoin Testnet",
version: "1.0.0",
},
});

setupGetDeviceStatusMock([
{
currentApp: "Bitcoin Testnet",
currentAppVersion: "1.0.0",
},
]);
const openAppDeviceAction = new OpenAppDeviceAction({
input: {
appName: "Bitcoin",
unlockTimeout: undefined,
compatibleAppNames: ["Bitcoin Testnet"],
},
});
jest
.spyOn(openAppDeviceAction, "extractDependencies")
.mockReturnValue(extractDependenciesMock());

const expectedStates: Array<OpenAppDAState> = [
{
status: DeviceActionStatus.Pending, // get onboarding status
intermediateValue: {
requiredUserInteraction: UserInteractionRequired.None,
},
},
{
status: DeviceActionStatus.Pending, // get app and version
intermediateValue: {
requiredUserInteraction: UserInteractionRequired.None,
},
},
{
status: DeviceActionStatus.Completed,
output: undefined,
},
];

testDeviceActionStates(
openAppDeviceAction,
expectedStates,
makeDeviceActionInternalApiMock(),
done,
);
});

it("should end in a success if the dashboard is open and open app succeeds", (done) => {
getDeviceSessionStateMock.mockReturnValue({
sessionStateType: DeviceSessionStateType.ReadyWithoutSecureChannel,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,12 @@ export class OpenAppDeviceAction extends XStateDeviceAction<
if (context._internalState.currentlyRunningApp === null)
throw new Error("context.currentlyRunningApp === null");
return (
context._internalState.currentlyRunningApp === context.input.appName
context._internalState.currentlyRunningApp ===
context.input.appName ||
(context.input.compatibleAppNames !== undefined &&
context.input.compatibleAppNames.includes(
context._internalState.currentlyRunningApp,
))
);
},
isDashboardOpen: ({ context }: { context: types["context"] }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export type OpenAppDAOutput = void;

export type OpenAppDAInput = GetDeviceStatusDAInput & {
readonly appName: string;
readonly compatibleAppNames?: string[];
};

export type OpenAppDAError =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,10 @@ export class SendCommandInAppDeviceAction<
actors: {
sendCommand: fromPromise(sendCommand),
openAppStateMachine: new OpenAppDeviceAction({
input: { appName: this.input.appName },
input: {
appName: this.input.appName,
compatibleAppNames: this.input.compatibleAppNames,
},
}).makeStateMachine(internalAPI),
},
guards: {
Expand Down Expand Up @@ -139,7 +142,10 @@ export class SendCommandInAppDeviceAction<
OpenAppDeviceAction: {
invoke: {
id: "openAppStateMachine",
input: { appName: this.input.appName },
input: {
appName: this.input.appName,
compatibleAppNames: this.input.compatibleAppNames,
},
src: "openAppStateMachine",
onSnapshot: {
actions: assign({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export type SendCommandInAppDAInput<
readonly command: Command<CommandResponse, CommandArgs, CommandErrorCodes>;
readonly appName: string;
readonly requiredUserInteraction: UserInteraction;
readonly compatibleAppNames?: string[];
};

export type SendCommandInAppDAError<CommandErrorCodes = void> =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { type TransactionParserService } from "@internal/transaction/service/par
import { type TypedDataParserService } from "@internal/typed-data/service/TypedDataParserService";

import { GetAddressCommand } from "./command/GetAddressCommand";
import { ETHEREUM_PLUGINS } from "./constant/plugins";
import { EthAppBinder } from "./EthAppBinder";

describe("EthAppBinder", () => {
Expand Down Expand Up @@ -154,6 +155,7 @@ describe("EthAppBinder", () => {
command: new GetAddressCommand(params),
appName: "Ethereum",
requiredUserInteraction: UserInteractionRequired.VerifyAddress,
compatibleAppNames: ETHEREUM_PLUGINS,
},
}),
});
Expand Down Expand Up @@ -185,6 +187,7 @@ describe("EthAppBinder", () => {
command: new GetAddressCommand(params),
appName: "Ethereum",
requiredUserInteraction: UserInteractionRequired.None,
compatibleAppNames: ETHEREUM_PLUGINS,
},
}),
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { TransactionParserService } from "@internal/transaction/service/parser/T
import { type TypedDataParserService } from "@internal/typed-data/service/TypedDataParserService";

import { GetAddressCommand } from "./command/GetAddressCommand";
import { ETHEREUM_PLUGINS } from "./constant/plugins";
import { SignPersonalMessageDeviceAction } from "./device-action/SignPersonalMessage/SignPersonalMessageDeviceAction";
import { SignTransactionDeviceAction } from "./device-action/SignTransaction/SignTransactionDeviceAction";

Expand All @@ -47,6 +48,7 @@ export class EthAppBinder {
input: {
command: new GetAddressCommand(args),
appName: "Ethereum",
compatibleAppNames: ETHEREUM_PLUGINS,
requiredUserInteraction: args.checkOnDevice
? UserInteractionRequired.VerifyAddress
: UserInteractionRequired.None,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
export const ETHEREUM_PLUGINS: string[] = [
"1inch",
"Aave",
"Alkemi",
"Angle",
"APWine",
"ArtBlocks",
"Brick Towers",
"capsa",
"cBridge",
"ChorusOne",
"CIAN",
"Coinbase",
"Cometh",
"Compound",
"DODO",
"EigenLayer",
"ENS",
"Figment",
"Harvest",
"Kelp",
"Kiln",
"Lens",
"libertify",
"Lido",
"[ L ] Market",
"Midas",
"Morpho",
"Nested",
"OKX Web3",
"OpenSea",
"P2P.org",
"Paraswap",
"POAP",
"QuickSwap",
"Rarible",
"Ribbon",
"Ricochet",
"Rocket Pool",
"Spool",
"Squid",
"Staderlabs",
"StakeDAO",
"StakeKit",
"Swell",
"Thales",
"Yearn",
];
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
type SignPersonalMessageDAOutput,
} from "@api/app-binder/SignPersonalMessageDeviceActionTypes";
import { type Signature } from "@api/model/Signature";
import { ETHEREUM_PLUGINS } from "@internal/app-binder/constant/plugins";
import { SendSignPersonalMessageTask } from "@internal/app-binder/task/SendSignPersonalMessageTask";

export type MachineDependencies = {
Expand Down Expand Up @@ -69,7 +70,7 @@ export class SignPersonalMessageDeviceAction extends XStateDeviceAction<
},
actors: {
openAppStateMachine: new OpenAppDeviceAction({
input: { appName: "Ethereum" },
input: { appName: "Ethereum", compatibleAppNames: ETHEREUM_PLUGINS },
}).makeStateMachine(internalApi),
signPersonalMessage: fromPromise(signPersonalMessage),
},
Expand Down Expand Up @@ -109,7 +110,10 @@ export class SignPersonalMessageDeviceAction extends XStateDeviceAction<
}),
invoke: {
id: "openAppStateMachine",
input: { appName: "Ethereum" },
input: {
appName: "Ethereum",
compatibleAppNames: ETHEREUM_PLUGINS,
},
src: "openAppStateMachine",
onSnapshot: {
actions: assign({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
GetChallengeCommand,
type GetChallengeCommandResponse,
} from "@internal/app-binder/command/GetChallengeCommand";
import { ETHEREUM_PLUGINS } from "@internal/app-binder/constant/plugins";
import {
BuildTransactionContextTask,
type BuildTransactionContextTaskArgs,
Expand Down Expand Up @@ -129,7 +130,7 @@ export class SignTransactionDeviceAction extends XStateDeviceAction<
},
actors: {
openAppStateMachine: new OpenAppDeviceAction({
input: { appName: "Ethereum" },
input: { appName: "Ethereum", compatibleAppNames: ETHEREUM_PLUGINS },
}).makeStateMachine(internalApi),
getChallenge: fromPromise(getChallenge),
buildContext: fromPromise(buildContext),
Expand Down Expand Up @@ -183,7 +184,10 @@ export class SignTransactionDeviceAction extends XStateDeviceAction<
}),
invoke: {
id: "openAppStateMachine",
input: { appName: "Ethereum" },
input: {
appName: "Ethereum",
compatibleAppNames: ETHEREUM_PLUGINS,
},
src: "openAppStateMachine",
onSnapshot: {
actions: assign({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
import { type Signature } from "@api/model/Signature";
import { type TypedData } from "@api/model/TypedData";
import { SignEIP712Command } from "@internal/app-binder/command/SignEIP712Command";
import { ETHEREUM_PLUGINS } from "@internal/app-binder/constant/plugins";
import { BuildEIP712ContextTask } from "@internal/app-binder/task/BuildEIP712ContextTask";
import {
ProvideEIP712ContextTask,
Expand Down Expand Up @@ -92,7 +93,7 @@ export class SignTypedDataDeviceAction extends XStateDeviceAction<
},
actors: {
openAppStateMachine: new OpenAppDeviceAction({
input: { appName: "Ethereum" },
input: { appName: "Ethereum", compatibleAppNames: ETHEREUM_PLUGINS },
}).makeStateMachine(internalApi),
buildContext: fromPromise(buildContext),
provideContext: fromPromise(provideContext),
Expand Down Expand Up @@ -135,7 +136,10 @@ export class SignTypedDataDeviceAction extends XStateDeviceAction<
}),
invoke: {
id: "openAppStateMachine",
input: { appName: "Ethereum" },
input: {
appName: "Ethereum",
compatibleAppNames: ETHEREUM_PLUGINS,
},
src: "openAppStateMachine",
onSnapshot: {
actions: assign({
Expand Down

0 comments on commit 7642ada

Please sign in to comment.