Documentation
3 - Address derivation

3 - Address derivation

From step 3 to step 6, you work will be implemented in the Ledger Live repository (opens in a new tab).

Derive Address from device

Before starting this step, make sure you have setup your environment to work with ledger-live.

First define the signer interface, which will reflect your embedded app js binding:

export type MyCoinAddress = {
  address: string,
  publicKey: string,
  returnCode: number,
};
export type MyCoinSignature = {
  signature: Buffer | null,
  returnCode: number
};
export interface MyCoinSigner {
  getAddress(path: string, display?: bool): Promise<MyCoinAddress>;
  sign(path: string, message: string): Promise<MyCoinSignature>;
}

Then get an address from the device for MyCoin, by creating the hw-getAddress.ts Resolver:

libs/coin-mycoin/src/hw-getAddress.js:

import type { GetAddressFn } from "@ledgerhq/coin-framework/bridge/getAddressWrapper";
import type { SignerContext } from "@ledgerhq/coin-framework/signer";
import type { GetAddressOptions } from "@ledgerhq/coin-framework/derivation";
import type { MyCoinAddress, MyCoinSignature, MyCoinSigner } from "./signer";
 
const resolver = (
  signerContext: SignerContext<MyCoinSigner, MyCoinAddress | MyCoinSignature>,
): GetAddressFn => {
  return async (deviceId: string, { path, verify }: GetAddressOptions) => {
    const address = (await signerContext(deviceId, signer =>
      signer.getAddress(path, verify),
    )) as PolkadotAddress;
    return {
      address: address.address,
      publicKey: address.pubKey,
      path,
    };
  };
};
 
export default resolver;

Test that you can derive an address:

ledger-live getAddress --currency mycoin --path "44'/8008'/0'/0/0" --derivationMode ""

Derivation

Ledger Live uses the BIP44 derivation mode by default (as derivationMode=""), which is standard and most common way for HD wallet. If MyCoin has a conventional derivation path (BIP44), Ledger Live should already be able to derive an address correctly.

If you need to use another derivation mode:

Make changes to libs/ledger-live-common/src/derivation.ts (opens in a new tab):

  1. Add a new derivation mode with overridesDerivation:
// const modes = Object.freeze({
// ...
  mycoinbip44h: { // Hardened BIP44 for MyCoin
    overridesDerivation: "44'/8008'/<account>'/0'/<address>'",
  },
// });
  1. Add the mode to family in legacyDerivations:
// const legacyDerivations: $Shape<CryptoCurrencyConfig<DerivationMode[]>> = {
// ...
  mycoin: ["mycoinbip44h"],
// };
  1. Disable the default use of BIP44 in disableBIP44:
// const disableBIP44 = {
// ...
  mycoin: true,
// };
  1. Add the coin to seedIdentifierPath:
// const seedIdentifierPath = {
// ...
  mycoin: `${purpose}'/${coinType}'/0'/0'/0'`,
// };

See Derivation documentation (opens in a new tab) for further details.

You can check that the derivationMode is correct by executing:

pnpm build:cli
pnpm run:cli  getAddress --currency=mycoin --path="44'/8008'/0'/0/0" --derivationMode=""
Ledger
Copyright © Ledger SAS. All rights reserved. Ledger, Ledger Nano S, Ledger Vault, Bolos are registered trademarks of Ledger SAS