Files
LedgerLive/docs/LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE.md

238 lines
14 KiB
Markdown
Raw Permalink Normal View History

# Ledger Blockchain Integration — Complete Reference (All Steps)
**Last Updated:** 2026-02-13
**Purpose:** Full 8-step Ledger Wallet blockchain integration with gaps filled. Use for Defi Oracle Meta Mainnet (Chain ID 138) or any EVM chain.
**Public code review for Ledger team:** [**bis-innovations/LedgerLive**](https://github.com/bis-innovations/LedgerLive) — use this repo for all Chain 138 integration code, specs, and patches intended for Ledger Live team review.
**See also:** [ADD_CHAIN138_TO_LEDGER_LIVE](ADD_CHAIN138_TO_LEDGER_LIVE.md) for the Chain 138specific action plan and submission text. **Generated code for all 8 steps:** [step-01-currency/](../step-01-currency/) through [step-08-manual-tests/](../step-08-manual-tests/). **Gaps and missing integrations (tests, fixes, checklist):** [GAPS_AND_MISSING_INTEGRATIONS.md](../GAPS_AND_MISSING_INTEGRATIONS.md).
---
## Prerequisites (do first)
1. **Agreement with Ledger** — [Submit the form](https://tally.so/r/mORpv8). Do **not** start development before they respond.
2. **Device app** — Either Ledger builds it (option A) or you/partner build + security audit (option B). See [Device App Kit](https://developers.ledger.com/docs/device-app/getting-started).
3. **Repos** — Fork/clone [LedgerHQ/ledger-live](https://github.com/LedgerHQ/ledger-live). For **public code review by the Ledger team**, publish your work to [**bis-innovations/LedgerLive**](https://github.com/bis-innovations/LedgerLive). Requirements for ledger-live: Node 18, pnpm 8, Python 2.7 or 3.5+, C/C++ toolchain. Run `pnpm i` in `ledger-live`.
For **EVM chains (e.g. Chain 138):** The Ethereum device app already supports multiple chain IDs; Ledger may only need to add Chain 138 to the official app-ethereum `network.c` (we have this in our fork). No separate device app is required unless Ledger specifies otherwise.
---
## Step 1 — Currency (Cryptoassets library)
**Doc:** [1 - Currency](https://developers.ledger.com/docs/ledger-live/accounts/integration/blockchain/cryptoassets-library)
Add the coin to **`@ledgerhq/cryptoassets`** in `libs/ledgerjs/packages/cryptoassets/src/currencies.ts` (or `.js`).
**CryptoCurrency fields:** `id`, `name`, `ticker`, `managerAppName`, `coinType` (SLIP-44), `scheme`, `color`, `family`, `units` (first = main unit, last must have `magnitude: 0`), `explorerViews` (tx, address, token URLs with `$hash`, `$address`, `$contractAddress`). For EVM: set `ethereumLikeInfo: { chainId: number }`.
**Chain 138 example:**
```javascript
// In libs/ledgerjs/packages/cryptoassets/src/currencies.ts
defi_oracle_meta_mainnet: {
type: "CryptoCurrency",
id: "defi_oracle_meta_mainnet",
coinType: 60, // SLIP-44 Ethereum
name: "Defi Oracle Meta Mainnet",
managerAppName: "Ethereum",
ticker: "ETH",
countervalueTicker: "ETH",
scheme: "defi-oracle-meta",
color: "#627EEA",
family: "ethereum",
units: [
{ name: "ETH", code: "ETH", magnitude: 18 },
{ name: "wei", code: "wei", magnitude: 0 },
],
ethereumLikeInfo: { chainId: 138 },
explorerViews: [
{
address: "https://explorer.d-bis.org/address/$address",
tx: "https://explorer.d-bis.org/tx/$hash",
token: "https://explorer.d-bis.org/token/$contractAddress?a=$address",
},
],
},
```
Explorer order: list from most to least preferred; Ledger Wallet uses the first as default.
---
## Step 2 — Device app lib (JS bindings)
**Doc:** [2 - Device app lib](https://developers.ledger.com/docs/ledger-live/accounts/integration/blockchain/js-bindings) *(full content behind GitHub login)*
**Purpose:** JavaScript/TypeScript library that talks to the device app (e.g. `hw-app-eth` for Ethereum). Naming convention: `hw-app-*` (see `hw-app-btc`, `hw-app-eth` in the monorepo or on npm).
**For EVM / Chain 138:** The existing **Ethereum app** and **`@ledgerhq/hw-app-eth`** already support any chain ID; signing uses EIP-155 and the chain ID is passed in the transaction. No new device app lib is required unless Ledger asks for a dedicated package. If they do:
- Implement a class that extends or mirrors the Transport-based API (e.g. `getAddress(path, options)`, `signTransaction(path, rawTxHex)`, `signPersonalMessage(path, messageHex)`).
- Publish or add to the monorepo under `libs/ledgerjs/packages/hw-app-*`.
- The coin-module **signer** (Step 4) will call this lib.
**If using Ethereum family:** Ensure `chainId: 138` is passed in transaction building and signing so the device displays the correct network.
---
## Step 3 — Create coin module
**Doc:** [3 - Create module](https://developers.ledger.com/docs/ledger-live/accounts/integration/blockchain/create-module)
Add a **CoinModule** under `libs/coin-modules/` (e.g. for a dedicated family) or reuse the **Ethereum** family.
**For Chain 138 as Ethereum family:** Ledger typically adds new EVM chains by extending the existing **Ethereum** coin-module configuration (currency list, RPC, explorer) rather than creating a new `coin-defi_oracle_meta`. If Ledger requests a separate module:
- **Layout:** `api/` (optional), `bridge/`, `logic/`, `network/`, `signer/`, `types/`, `config.ts`, `index.ts`.
- **Rules:** One-way dependencies (e.g. `logic` must not import `bridge`). Use `index.ts` per folder to control exports.
- **live-common:** Add or extend `libs/ledger-live-common/src/families/ethereum/` (or `families/defi_oracle_meta/` if separate) with setup, config, and walletApiAdapter.
**Bridge** implements: sync, buildTransaction, signOperation, broadcast, getFeesForTransaction, getTransactionStatus, etc. **Network** wraps RPC/explorer (e.g. public RPCs and Blockscout for Chain 138).
---
## Step 4 — Derivation / signer
**Doc:** [4 - Derivation / Signer](https://developers.ledger.com/docs/ledger-live/accounts/integration/blockchain/address-derivation)
- Define **signer types** in the coin-module `types/signer.ts` (e.g. `getAddress(path, display?)`, `sign(path, message)` or transaction signing).
- Implement **getAddress** in `signer/getAddress.ts` using `@ledgerhq/coin-framework` (`GetAddressFn`, `SignerContext`, `GetAddressOptions`); return `{ address, publicKey, path }`.
- **EVM standard:** Derivation path `44'/60'/0'/0/0`; no custom overrides needed unless Ledger specifies.
**CLI check:**
```bash
ledger-live getAddress --currency ethereum --path "44'/60'/0'/0/0" --derivationMode ""
```
For Chain 138, currency may be `ethereum` with chainId 138 in config, or a dedicated id once added.
If you need **custom derivation:** extend `libs/coin-framework/src/derivation.ts` with `overridesDerivation`, `legacyDerivations`, `disableBIP44`, `seedIdentifierPath` for your family. See [LLC derivation](https://github.com/LedgerHQ/ledger-live/wiki/LLC:derivation).
---
## Step 5 — API
**Doc:** [5 - API](https://developers.ledger.com/docs/ledger-live/accounts/integration/blockchain/api) *(full content behind GitHub login)*
**Purpose:** Backend/API used by the coin-module and optionally by Ledger Wallet services: RPC, indexer, or explorer integration for sync, fees, broadcast, and history.
**For Chain 138:**
- **RPC:** Use public endpoints (e.g. `https://rpc-http-pub.d-bis.org`, `https://rpc.d-bis.org`) for `eth_*` calls. See [ADD_CHAIN138_TO_LEDGER_LIVE § 3.1](../04-configuration/ADD_CHAIN138_TO_LEDGER_LIVE.md#31-chain-specification-chainlist-compatible) and `pr-workspace/chains/_data/chains/eip155-138.json`.
- **Explorer:** Blockscout at `https://explorer.d-bis.org` (EIP3091). Use for tx/address/token links and, if needed, for history or verification.
- Ledger may run their own indexer or proxy; they will specify. Have public RPC and explorer URLs ready for their config.
---
## Step 6 — LLD & LLM (desktop and mobile)
**Doc:** [6 - LLD & LLM](https://developers.ledger.com/docs/ledger-live/accounts/integration/blockchain/desktop-mobile)
**Ledger Wallet Common (live-common):**
- In `libs/ledger-live-common/src/families/ethereum/` (or your family): **`setup.ts`** — create Bridge with `createBridges(executeWithSigner(createSigner), getCurrencyConfig)`, export `bridge`, `resolver`, `cliTools`.
- **Config:** Register coin config (e.g. `config_currency_defi_oracle_meta_mainnet`) with at least `status` and `node.url` (e.g. from env `API_DEFI_ORACLE_META_NODE` or Ledgers env naming).
**Ledger Wallet Desktop (LLD):**
- In `live-common-set-supported-currencies.js` add the currency id (e.g. `defi_oracle_meta_mainnet`).
- Add error translation keys in `static/i18n/en`.
- Run: `pnpm dev:lld`.
**Ledger Wallet Mobile (LLM):**
- In `live-common-setup.js` add the currency.
- Add error keys in `src/locales/en/common.json`.
- Run: `pnpm dev:llm` (iOS, Mac); Android: `pnpm mobile android`; iOS: `pnpm mobile ios` or open `ios/ledgerlivemobile.xcworkspace`.
---
## Step 7 — Wallet API (Ledger Wallet API)
**Doc:** [7 - Wallet API](https://developers.ledger.com/docs/ledger-live/accounts/integration/blockchain/ledger-services-kit)
**In [LedgerHQ/wallet-api](https://github.com/LedgerHQ/wallet-api):**
1. Fork/clone; `pnpm i` and `pnpm dev`.
2. If adding a **new family:** create `packages/core/src/families/{COIN_FAMILY}/` with `validation.ts` (Zod, at least `schemaRaw{COIN_FAMILY}Transaction`), `types.ts` (`{COIN_FAMILY}Transaction`, `Raw{COIN_FAMILY}Transaction`), `serializer.ts` (serialize/deserialize for JSON-RPC).
3. In `packages/core/src/families/common.ts` add family name to `FAMILIES`.
4. Export in `packages/core/src/families/index.ts`; update `types.ts` and `validation.ts` and `serializer.ts` for the union `Transaction` and `schemaRawTransaction`.
5. Run `pnpm changelog`, create changeset for `@ledgerhq/wallet-api-core` (minor bump), open PR.
**For EVM:** Chain 138 may be supported by extending the existing **Ethereum** family in wallet-api (e.g. allow chainId 138 in validation and routing). Ledger will confirm.
**In Ledger Wallet (ledger-live):**
- Bump `@ledgerhq/wallet-api-core`, `@ledgerhq/wallet-api-server`, `@ledgerhq/wallet-api-client`.
- Add or extend **Wallet API adapter** in `libs/ledger-live-common/src/families/ethereum/walletApiAdapter.ts` (or your family) so WalletAPI transaction type maps to Ledger Wallet transaction type. Ensure the adapter is included by the sync-families-dispatch script (do not edit generated file by hand; add the source adapter file).
Example PRs: [Ethereum adapter](https://github.com/LedgerHQ/ledger-live/pull/3182), [Filecoin](https://github.com/LedgerHQ/wallet-api/pull/127), [Solana](https://github.com/LedgerHQ/wallet-api/pull/132).
---
## Step 8 — Manual tests
**Doc:** [Manual tests](https://developers.ledger.com/docs/ledger-live/accounts/integration/blockchain/test-plan)
- **Sync:** Add account; migrate account (add in prod, no crash); sync completes without error; big account (multi-page history).
- **Receive / address:** Verify address with device; verify address without device.
- **Balance:** Available balance correct.
- **Broadcast:** Send max empties account; send amount correct; cannot send more than balance.
- **Operations:** Optimistic operation correct; history complete; tx id correct; “View on explorer” works; operation account correct.
- **Account:** Countervalue (fiat) correct if enabled; favorite works.
---
## Deployment checklist (all steps)
| # | Step | Owner | Action | Done |
|---|------|--------|--------|------|
| 0 | Agreement | Project | Submit [form](https://tally.so/r/mORpv8); wait for Ledger response. | |
| 0 | Device app | Ledger or us | For Chain 138: confirm Ethereum app + chainId 138 (our fork has it); or follow Device App Kit if Ledger requests. | |
| 1 | Currency | Ledger / us | Add Chain 138 to `@ledgerhq/cryptoassets` (id, ethereumLikeInfo.chainId 138, explorerViews). | |
| 2 | Device app lib | Ledger / us | For EVM: use `hw-app-eth`; ensure chainId 138 in tx building/signing. | |
| 3 | Create module | Ledger / us | Use or extend Ethereum coin-module; config RPC + explorer for Chain 138. | |
| 4 | Derivation/Signer | Ledger / us | Standard 44'/60'; getAddress + sign integrated. | |
| 5 | API | Ledger / us | RPC + Blockscout URLs provided; Ledger may add indexer/config. | |
| 6 | LLD & LLM | Ledger / us | live-common setup + config; LLD/LLM currency list + i18n; run dev and QA. | |
| 7 | Wallet API | Ledger / us | wallet-api: Ethereum family supports chainId 138 or new family; LL adapter updated. | |
| 8 | Manual tests | Ledger / us | Execute send/receive test plan (sync, receive, balance, broadcast, operations, account). | |
---
## Optional: tokens, swap, staking
- **Tokens:** [Before you start](https://developers.ledger.com/docs/ledger-live/accounts/integration/tokens/before-you-start) → Device app → API → CAL; add integration/bot and manual tests.
- **Swap:** Device app → Wallet API → Exchange SDK → Swap Live App → Ledger Wallet; manual + E2E.
- **Staking:** [Strategy](https://developers.ledger.com/docs/ledger-live/accounts/integration/staking/strategy) → API → manual + E2E/integration/React/bot.
---
## Chain 138 quick reference
| Item | Value |
|------|--------|
| Chain name | Defi Oracle Meta Mainnet |
| Chain ID | 138 (0x8a) |
| SLIP-44 | 60 (Ethereum) |
| Derivation | 44'/60'/0'/0/0 |
| Native | ETH, 18 decimals |
| Public RPC | https://rpc-http-pub.d-bis.org, https://rpc.d-bis.org, etc. |
| Explorer | https://explorer.d-bis.org (Blockscout, EIP3091) |
| Chainlist | https://chainlist.org/chain/138 |
| App-ethereum fork | `pr-workspace/app-ethereum` (network.c, defi_oracle.mk) |
---
## References
- [Ledger Adding your blockchain](https://developers.ledger.com/docs/ledger-live/accounts/getting-started)
- [Ledger Device App Kit](https://developers.ledger.com/docs/device-app/getting-started)
- [Ledger Blockchain integration form](https://tally.so/r/mORpv8)
- [Ledger Live monorepo](https://github.com/LedgerHQ/ledger-live)
- [Ledger App-Ethereum](https://github.com/LedgerHQ/app-ethereum)
- [ADD_CHAIN138_TO_LEDGER_LIVE](../04-configuration/ADD_CHAIN138_TO_LEDGER_LIVE.md) — Chain 138 submission and materials