Skip to content

Commit

Permalink
Ledger improvements (#434)
Browse files Browse the repository at this point in the history
  • Loading branch information
sh-wallet authored Jan 27, 2025
1 parent 3d6c041 commit 0d79c4b
Show file tree
Hide file tree
Showing 32 changed files with 1,426 additions and 930 deletions.
78 changes: 30 additions & 48 deletions packages/background/src/ledger/ledger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,15 @@ import {
ErrFailedGetVersion,
ErrFailedInit,
ErrFailedSign,
ErrModuleLedgerSign,
} from "./types";
import { WalletError } from "@keplr-wallet/router";

export enum LedgerApp {
Cosmos = "cosmos",
Ethereum = "ethereum",
}

export enum LedgerInitErrorOn {
Transport,
App,
Unknown,
}

export const LedgerWebUSBIniter: TransportIniter = async () => {
return await TransportWebUSB.create();
};
Expand All @@ -38,19 +34,6 @@ export const LedgerWebHIDIniter: TransportIniter = async () => {
return await TransportWebHID.create();
};

export class LedgerInitError extends Error {
public readonly errorOn: LedgerInitErrorOn;
public readonly code: number;

constructor(errorOn: LedgerInitErrorOn, code: number, message?: string) {
super(message);
this.errorOn = errorOn;
this.code = code;

Object.setPrototypeOf(this, LedgerInitError.prototype);
}
}

export class Ledger {
constructor(
public readonly cosmosApp: CosmosApp | undefined = undefined,
Expand All @@ -67,8 +50,8 @@ export class Ledger {
try {
transport = await transportIniter(...initArgs);
} catch (e) {
throw new LedgerInitError(
LedgerInitErrorOn.Transport,
throw new WalletError(
ErrModuleLedgerSign,
ErrFailedInit,
"Connect and unlock your Ledger device."
);
Expand All @@ -95,8 +78,8 @@ export class Ledger {
// However, it is almost same as that the device is not unlocked to user-side.
// So, handle this case as initializing failed in `Transport`.
if (versionResponse.deviceLocked) {
throw new LedgerInitError(
LedgerInitErrorOn.Transport,
throw new WalletError(
ErrModuleLedgerSign,
ErrCodeDeviceLocked,
"Unlock your Ledger device."
);
Expand All @@ -110,8 +93,8 @@ export class Ledger {
console.log(e);
}
if (appName && appName !== cosmosLikeApp) {
throw new LedgerInitError(
LedgerInitErrorOn.App,
throw new WalletError(
ErrModuleLedgerSign,
ErrCodeUnsupportedApp,
"Invalid cosmos app selected"
);
Expand All @@ -122,22 +105,21 @@ export class Ledger {
if (transport) {
await transport.close();
}
console.log("Testing1::", e.message);

if (
e.message === "Device is on screen saver" ||
e.message?.includes("Unknown Status Code: 21781")
) {
throw new LedgerInitError(
LedgerInitErrorOn.Transport,
throw new WalletError(
ErrModuleLedgerSign,
ErrCodeDeviceLocked,
"Unlock your Ledger device."
);
}

throw new LedgerInitError(
LedgerInitErrorOn.App,
ErrFailedInit,
throw new WalletError(
ErrModuleLedgerSign,
ErrCodeAppNotInitialised,
`Open the ${cosmosLikeApp} app on Ledger and try again.`
);
}
Expand All @@ -152,8 +134,8 @@ export class Ledger {
testMode: boolean;
}> {
if (!this.cosmosApp) {
throw new LedgerInitError(
LedgerInitErrorOn.App,
throw new WalletError(
ErrModuleLedgerSign,
ErrCodeAppNotInitialised,
"Please initialize Cosmos app first"
);
Expand All @@ -162,8 +144,8 @@ export class Ledger {
const result = await this.cosmosApp.getVersion();

if (result.error_message !== "No errors") {
throw new LedgerInitError(
LedgerInitErrorOn.App,
throw new WalletError(
ErrModuleLedgerSign,
ErrFailedGetVersion,
result.error_message
);
Expand All @@ -182,8 +164,8 @@ export class Ledger {
async getPublicKey(app: LedgerApp, fields: BIP44HDPath): Promise<Uint8Array> {
if (app === LedgerApp.Ethereum) {
if (!this.ethereumApp) {
throw new LedgerInitError(
LedgerInitErrorOn.App,
throw new WalletError(
ErrModuleLedgerSign,
ErrCodeAppNotInitialised,
"Please initialize Ethereum app first"
);
Expand All @@ -198,12 +180,12 @@ export class Ledger {
// Compress the public key
return publicKeyConvert(pubKey, true);
} catch (e: any) {
throw new LedgerInitError(LedgerInitErrorOn.App, e);
throw new WalletError(ErrModuleLedgerSign, e);
}
} else {
if (!this.cosmosApp) {
throw new LedgerInitError(
LedgerInitErrorOn.App,
throw new WalletError(
ErrModuleLedgerSign,
ErrCodeAppNotInitialised,
"Please initialize Cosmos app first"
);
Expand All @@ -215,8 +197,8 @@ export class Ledger {
fields.addressIndex
);
if (result.error_message !== "No errors") {
throw new LedgerInitError(
LedgerInitErrorOn.App,
throw new WalletError(
ErrModuleLedgerSign,
ErrFailedGetPublicKey,
result.error_message
);
Expand All @@ -228,8 +210,8 @@ export class Ledger {

async sign(fields: BIP44HDPath, message: Uint8Array): Promise<Uint8Array> {
if (!this.cosmosApp) {
throw new LedgerInitError(
LedgerInitErrorOn.App,
throw new WalletError(
ErrModuleLedgerSign,
ErrCodeAppNotInitialised,
"Please initialize Cosmos app first"
);
Expand All @@ -242,8 +224,8 @@ export class Ledger {
message
);
if (result.error_message !== "No errors") {
throw new LedgerInitError(
LedgerInitErrorOn.App,
throw new WalletError(
ErrModuleLedgerSign,
ErrFailedSign,
result.error_message
);
Expand All @@ -259,8 +241,8 @@ export class Ledger {
message: Uint8Array
) {
if (!this.ethereumApp) {
throw new LedgerInitError(
LedgerInitErrorOn.App,
throw new WalletError(
ErrModuleLedgerSign,
ErrCodeAppNotInitialised,
"Please initialize Ethereum app first"
);
Expand Down
1 change: 1 addition & 0 deletions packages/background/src/ledger/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export type TransportIniter = (...args: any[]) => Promise<Transport>;

export interface LedgerOptions {
defaultMode: string;
platform: string;
transportIniters: {
[mode: string]: TransportIniter;
};
Expand Down
Loading

0 comments on commit 0d79c4b

Please sign in to comment.