Skip to content
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
cbb0069
feat: add Ledger hardware wallet support for Tron (TRX)
gomesalexandre Dec 1, 2025
48e0e89
style: fix lint issues in Tron Ledger implementation
gomesalexandre Dec 1, 2025
96b4817
chore: version packages to 1.62.18-tron-ledger.0
gomesalexandre Dec 1, 2025
a2919f4
fix: add Tron support to Ledger WebUSB and WebHID transports
gomesalexandre Dec 1, 2025
fb99aeb
chore: version packages to 1.62.18-tron-ledger.1
gomesalexandre Dec 1, 2025
7075488
feat: reverts
gomesalexandre Dec 1, 2025
774fbc2
chore: remove version carets for exact dependency matching
gomesalexandre Dec 1, 2025
de9f747
feat: bump yarn.lock
gomesalexandre Dec 1, 2025
ff166fc
Merge remote-tracking branch 'origin/master' into feat_tron_ledger
gomesalexandre Dec 1, 2025
a56a33b
feat: add Sui Ledger hardware wallet support
gomesalexandre Dec 1, 2025
5617b1f
chore(release): publish 1.62.19-sui.0
gomesalexandre Dec 1, 2025
dc901d4
chore: version packages to 1.62.19-sui.0 and fix TypeScript errors
gomesalexandre Dec 1, 2025
cab9ef4
fix: strip m/ prefix from Sui derivation paths for Ledger
gomesalexandre Dec 1, 2025
d999dc0
chore(release): publish 1.62.19-sui.1
gomesalexandre Dec 1, 2025
0d475ff
debug: add comprehensive logging to Sui Ledger module
gomesalexandre Dec 1, 2025
33faadf
chore(release): publish 1.62.19-sui.2
gomesalexandre Dec 1, 2025
113552a
fix: harden Sui paths internally in Ledger adapter
gomesalexandre Dec 1, 2025
d4e4447
chore(release): publish 1.62.19-sui.3
gomesalexandre Dec 1, 2025
4083f9d
cleanup: remove debug logs from Sui Ledger module
gomesalexandre Dec 1, 2025
1ba1125
Revert "chore(release): publish 1.62.19-sui.3"
gomesalexandre Dec 1, 2025
8cd8793
fix: revert package.json version changes, keep only Sui dependency
gomesalexandre Dec 1, 2025
e59e988
fix: revert lerna.json version to match feat_tron_ledger branch
gomesalexandre Dec 1, 2025
7246a97
fix: resolve linting issues in Sui Ledger module
gomesalexandre Dec 1, 2025
c3cabb5
Merge remote-tracking branch 'origin/master' into feat_sui_ledger
gomesalexandre Dec 2, 2025
16f4977
feat: bump yarn.lock
gomesalexandre Dec 2, 2025
dbdf91c
chore(release): publish 1.62.20
gomesalexandre Dec 2, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/hdwallet-ledger-webhid/src/transport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Solana from "@ledgerhq/hw-app-solana";
import Trx from "@ledgerhq/hw-app-trx";
import Transport from "@ledgerhq/hw-transport";
import TransportWebHID from "@ledgerhq/hw-transport-webhid";
import Sui from "@mysten/ledgerjs-hw-app-sui";
import * as core from "@shapeshiftoss/hdwallet-core";
import * as ledger from "@shapeshiftoss/hdwallet-ledger";
import type {
Expand Down Expand Up @@ -85,6 +86,11 @@ export function translateCoinAndMethod<T extends LedgerTransportCoinType, U exte
const methodInstance = solana[method as LedgerTransportMethodName<"Solana">].bind(solana);
return methodInstance as LedgerTransportMethod<T, U>;
}
case "Sui": {
const sui = new Sui(transport as Transport);
const methodInstance = sui[method as LedgerTransportMethodName<"Sui">].bind(sui);
return methodInstance as LedgerTransportMethod<T, U>;
}
case "Tron": {
const trx = new Trx(transport as Transport);
const methodInstance = trx[method as LedgerTransportMethodName<"Tron">].bind(trx);
Expand Down
6 changes: 6 additions & 0 deletions packages/hdwallet-ledger-webusb/src/transport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Solana from "@ledgerhq/hw-app-solana";
import Trx from "@ledgerhq/hw-app-trx";
import Transport from "@ledgerhq/hw-transport";
import TransportWebUSB from "@ledgerhq/hw-transport-webusb";
import Sui from "@mysten/ledgerjs-hw-app-sui";
import * as core from "@shapeshiftoss/hdwallet-core";
import { getAppAndVersion, getDeviceInfo, LedgerTransport, openApp, Thorchain } from "@shapeshiftoss/hdwallet-ledger";
import type {
Expand Down Expand Up @@ -105,6 +106,11 @@ export async function translateCoinAndMethod<T extends LedgerTransportCoinType,
const methodInstance = solana[method as LedgerTransportMethodName<"Solana">].bind(solana);
return methodInstance as LedgerTransportMethod<T, U>;
}
case "Sui": {
const sui = new Sui(transport as Transport);
const methodInstance = sui[method as LedgerTransportMethodName<"Sui">].bind(sui);
return methodInstance as LedgerTransportMethod<T, U>;
}
case "Tron": {
const trx = new Trx(transport as Transport);
const methodInstance = trx[method as LedgerTransportMethodName<"Tron">].bind(trx);
Expand Down
1 change: 1 addition & 0 deletions packages/hdwallet-ledger/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"@ledgerhq/hw-app-trx": "^6.31.9",
"@ledgerhq/hw-transport": "6.31.8",
"@ledgerhq/logs": "6.13.0",
"@mysten/ledgerjs-hw-app-sui": "^0.7.0",
Comment thread
coderabbitai[bot] marked this conversation as resolved.
"@shapeshiftoss/bitcoinjs-lib": "7.0.0-shapeshift.0",
"@shapeshiftoss/hdwallet-core": "^1.62.19",
"@solana/web3.js": "1.95.8",
Expand Down
25 changes: 25 additions & 0 deletions packages/hdwallet-ledger/src/ledger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as cosmos from "./cosmos";
import * as eth from "./ethereum";
import * as mayachain from "./mayachain";
import * as solana from "./solana";
import * as sui from "./sui";
import * as thorchain from "./thorchain";
import { LedgerTransport } from "./transport";
import * as tron from "./tron";
Expand Down Expand Up @@ -148,6 +149,7 @@ export class LedgerHDWalletInfo
core.MayachainWalletInfo,
core.CosmosWalletInfo,
core.SolanaWalletInfo,
core.SuiWalletInfo,
core.TronWalletInfo
{
readonly _supportsBTCInfo = true;
Expand All @@ -156,6 +158,7 @@ export class LedgerHDWalletInfo
readonly _supportsMayachainInfo = true;
readonly _supportsCosmosInfo = true;
readonly _supportsSolanaInfo = true;
readonly _supportsSuiInfo = true;
readonly _supportsTronInfo = true;

public getVendor(): string {
Expand Down Expand Up @@ -241,6 +244,14 @@ export class LedgerHDWalletInfo
throw new Error("Method not implemented");
}

public suiGetAccountPaths(msg: core.SuiGetAccountPaths): Array<core.SuiAccountPath> {
return sui.suiGetAccountPaths(msg);
}

public suiNextAccountPath(msg: core.SuiAccountPath): core.SuiAccountPath | undefined {
return sui.suiNextAccountPath(msg);
}

public tronGetAccountPaths(msg: core.TronGetAccountPaths): Array<core.TronAccountPath> {
return tron.tronGetAccountPaths(msg);
}
Expand Down Expand Up @@ -294,6 +305,8 @@ export class LedgerHDWalletInfo
return core.mayachainDescribePath(msg.path);
case "Solana":
return core.solanaDescribePath(msg.path);
case "Sui":
return core.suiDescribePath(msg.path);
case "Tron":
return core.tronDescribePath(msg.path);
default:
Expand Down Expand Up @@ -373,6 +386,7 @@ export class LedgerHDWallet
core.MayachainWallet,
core.CosmosWallet,
core.SolanaWallet,
core.SuiWallet,
core.TronWallet
{
readonly _supportsBTC = true;
Expand All @@ -391,6 +405,7 @@ export class LedgerHDWallet
readonly _supportsMayachain = true;
readonly _supportsCosmos = true;
readonly _supportsSolana = true;
readonly _supportsSui = true;
readonly _supportsTron = true;

_isLedger = true;
Expand Down Expand Up @@ -634,6 +649,16 @@ export class LedgerHDWallet
return solana.solanaSignTx(this.transport, msg);
}

public async suiGetAddress(msg: core.SuiGetAddress): Promise<string> {
await this.validateCurrentApp("Sui");
return sui.suiGetAddress(this.transport, msg);
}

public async suiSignTx(msg: core.SuiSignTx): Promise<core.SuiSignedTx | null> {
await this.validateCurrentApp("Sui");
return sui.suiSignTx(this.transport, msg);
}

public async tronGetAddress(msg: core.TronGetAddress): Promise<string> {
await this.validateCurrentApp("Tron");
return tron.tronGetAddress(this.transport, msg);
Expand Down
97 changes: 97 additions & 0 deletions packages/hdwallet-ledger/src/sui.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import * as core from "@shapeshiftoss/hdwallet-core";

import { LedgerTransport } from "./transport";
import { handleError } from "./utils";

// Ledger expects m/ prefix to be stripped AND all segments to be hardened for Ed25519
function addressNListToBIP32Path(addressNList: core.BIP32Path): string {
// Use addressNListToHardenedBIP32 to ensure all segments are hardened, then strip m/
return core.addressNListToHardenedBIP32(addressNList).slice(2);
}

export async function suiGetAddress(transport: LedgerTransport, msg: core.SuiGetAddress): Promise<string> {
const bip32path = addressNListToBIP32Path(msg.addressNList);

try {
const res = await transport.call("Sui", "getPublicKey", bip32path, !!msg.showDisplay);
handleError(res, transport, "Unable to obtain Sui address from device.");

// Convert Uint8Array to hex string with 0x prefix
const addressBytes =
res.payload.address instanceof Uint8Array ? res.payload.address : new Uint8Array(res.payload.address);

const address = "0x" + Buffer.from(addressBytes).toString("hex");
return address;
} catch (error) {
console.error("[Sui Ledger] suiGetAddress error:", error);
throw error;
}
}

async function suiGetPublicKey(transport: LedgerTransport, addressNList: core.BIP32Path): Promise<string> {
const bip32path = addressNListToBIP32Path(addressNList);

try {
const res = await transport.call("Sui", "getPublicKey", bip32path, false);
handleError(res, transport, "Unable to obtain Sui public key from device.");

// Convert Uint8Array public key to hex string
const publicKeyBytes =
res.payload.publicKey instanceof Uint8Array ? res.payload.publicKey : new Uint8Array(res.payload.publicKey);

const publicKey = Buffer.from(publicKeyBytes).toString("hex");
return publicKey;
} catch (error) {
console.error("[Sui Ledger] suiGetPublicKey error:", error);
throw error;
}
}

export async function suiSignTx(transport: LedgerTransport, msg: core.SuiSignTx): Promise<core.SuiSignedTx> {
const bip32path = addressNListToBIP32Path(msg.addressNList);

try {
const res = await transport.call("Sui", "signTransaction", bip32path, Buffer.from(msg.intentMessageBytes));
handleError(res, transport, "Unable to sign Sui transaction.");

// Convert Uint8Array signature to hex string
const signatureBytes =
res.payload.signature instanceof Uint8Array ? res.payload.signature : new Uint8Array(res.payload.signature);
const signature = Buffer.from(signatureBytes).toString("hex");

const publicKey = await suiGetPublicKey(transport, msg.addressNList);

return {
signature,
publicKey,
};
} catch (error) {
console.error("[Sui Ledger] suiSignTx error:", error);
throw error;
}
}

export function suiGetAccountPaths(msg: core.SuiGetAccountPaths): Array<core.SuiAccountPath> {
return core.suiGetAccountPaths(msg);
}

export function suiNextAccountPath(msg: core.SuiAccountPath): core.SuiAccountPath | undefined {
const addressNList = msg.addressNList;
if (
addressNList[0] === 0x80000000 + 44 &&
addressNList[1] === 0x80000000 + core.slip44ByCoin("Sui") &&
addressNList[3] === 0x80000000 + 0 &&
addressNList[4] === 0x80000000 + 0
) {
return {
addressNList: [
0x80000000 + 44,
0x80000000 + core.slip44ByCoin("Sui"),
addressNList[2] + 1,
0x80000000 + 0,
0x80000000 + 0,
],
};
}
return undefined;
}
5 changes: 4 additions & 1 deletion packages/hdwallet-ledger/src/transport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type Eth from "@ledgerhq/hw-app-eth";
import Solana from "@ledgerhq/hw-app-solana";
import type Trx from "@ledgerhq/hw-app-trx";
import type Transport from "@ledgerhq/hw-transport";
import type Sui from "@mysten/ledgerjs-hw-app-sui";
import * as core from "@shapeshiftoss/hdwallet-core";

import type { getAppAndVersion } from "./hw/getAppAndVersion";
Expand All @@ -17,7 +18,7 @@ type MethodsOnly<T> = {
type UnwrapPromise<T> = T extends Promise<infer R> ? R : T;
type DefinitelyCallable<T> = T extends (...args: any) => any ? T : never;

export type LedgerTransportCoinType = null | "Btc" | "Eth" | "Thorchain" | "Cosmos" | "Solana" | "Tron";
export type LedgerTransportCoinType = null | "Btc" | "Eth" | "Thorchain" | "Cosmos" | "Solana" | "Sui" | "Tron";
type CurriedWithTransport<T extends (transport: Transport, ...args: any) => any> = T extends (
transport: Transport,
...args: infer R
Expand All @@ -44,6 +45,8 @@ type LedgerTransportMethodMap<T extends LedgerTransportCoinType> = T extends nul
? MethodsOnly<Cosmos>
: T extends "Solana"
? MethodsOnly<Solana>
: T extends "Sui"
? MethodsOnly<Sui>
: T extends "Tron"
? MethodsOnly<Trx>
: never;
Expand Down
1 change: 1 addition & 0 deletions packages/hdwallet-ledger/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,7 @@ const appNameBySlip44: Record<number, string> = {
145: "Bitcoin Cash",
195: "Tron",
501: "Solana",
784: "Sui",
931: "THORChain",
};

Expand Down