Add full Chain 138 integration: 8 steps, chain spec, app-ethereum config, docs
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
92
GAPS_AND_MISSING_INTEGRATIONS.md
Normal file
92
GAPS_AND_MISSING_INTEGRATIONS.md
Normal file
@@ -0,0 +1,92 @@
|
||||
# Ledger Chain 138 Integration — Gaps and Missing Integrations
|
||||
|
||||
**Last Updated:** 2026-02-12
|
||||
**Purpose:** Test results and checklist of gaps, fixes, and possible missing integrations for the 8-step Ledger codebase.
|
||||
|
||||
---
|
||||
|
||||
## Tests performed
|
||||
|
||||
| Check | Result |
|
||||
|-------|--------|
|
||||
| Step 8 `run-checklist.sh` | ✅ Runs and prints full manual test plan |
|
||||
| Step 1 currency vs eip155-138.json | ✅ chainId 138, slip44 60, explorer URLs match |
|
||||
| Step 5 RPC list vs ADD_CHAIN138 doc | ✅ Same public RPCs and explorer |
|
||||
| Step 3 explorer API | ✅ **Fixed** — was Etherscan-style; now uses Blockscout v2 `GET /api/v2/addresses/{address}/transactions` |
|
||||
| Step 4 signer types vs hw-app-eth | ✅ publicKey used; Ledger may use `pubKey` in some APIs — confirm in ledger-live |
|
||||
| Step 6 config default shape | ⚠️ Ledger live-config may expect different shape (e.g. `status: "active"` string); confirm in ledger-live |
|
||||
| Step 7 Wallet API | ⚠️ Ethereum family may already support multiple chainIds; our snippets are for extension only |
|
||||
|
||||
---
|
||||
|
||||
## Gaps addressed in repo
|
||||
|
||||
1. **Step 3 — Blockscout API**
|
||||
`network-explorer.ts` previously used Etherscan-style `module=account&action=txlist`. Blockscout uses REST v2: `GET /api/v2/addresses/{address_hash}/transactions` with pagination via `next_page_params` (block_number, index, items_count). The implementation was updated to use this API and export `EXPLORER_API_V2`.
|
||||
|
||||
---
|
||||
|
||||
## Possible missing integrations (to add when Ledger confirms)
|
||||
|
||||
### 1. Tokens (CAL / token list)
|
||||
|
||||
- **Gap:** No Step 1-style token entries or Crypto Assets List (CAL) for Chain 138 tokens (e.g. LINK, WETH, cUSDT, cUSDC).
|
||||
- **Action:** After Ledger adds the chain, follow [Tokens integration](https://developers.ledger.com/docs/ledger-live/accounts/integration/tokens/before-you-start): device app (if needed), API, CAL. Provide token contract addresses from [CHAIN138_TOKEN_ADDRESSES](docs/CHAIN138_TOKEN_ADDRESSES.md).
|
||||
|
||||
### 2. Swap
|
||||
|
||||
- **Gap:** No swap provider or Exchange SDK integration for Chain 138.
|
||||
- **Action:** Optional; only if Ledger or a partner will support swap on Chain 138. See [Swap integration](https://developers.ledger.com/docs/ledger-live/accounts/integration/swap/before-you-start).
|
||||
|
||||
### 3. Staking
|
||||
|
||||
- **Gap:** No staking API or UI for Chain 138 (e.g. validator staking if applicable).
|
||||
- **Action:** Only if Chain 138 has staking and Ledger supports it; follow [Staking strategy](https://developers.ledger.com/docs/ledger-live/accounts/integration/staking/strategy).
|
||||
|
||||
### 4. Clear Signing plugin (dApps)
|
||||
|
||||
- **Gap:** No Clear Signing plugin for Chain 138–specific contract calls (e.g. CCIP, bridge) so the device shows human-readable descriptions.
|
||||
- **Action:** Optional; see [Clear Signing for dApps](https://developers.ledger.com/docs/clear-signing/for-dapps/get-started) and [Write a plugin](https://developers.ledger.com/docs/ledger-live/discover/integration/dapp-browser/plugin).
|
||||
|
||||
### 5. i18n (LLD / LLM error keys)
|
||||
|
||||
- **Gap:** Step 6 README says “add error translation keys” but does not list the exact keys or strings.
|
||||
- **Action:** When adding the currency to LLD/LLM, copy the same error keys used for Ethereum (or the family) and add any Chain 138–specific messages. Ledger’s contribution guide will specify the key format (e.g. `errors.defi_oracle_meta_mainnet.*`).
|
||||
|
||||
### 6. live-common supported currencies (exact files)
|
||||
|
||||
- **Gap:** Step 6 references `live-common-set-supported-currencies.js` and `live-common-setup.js`; exact paths can differ by ledger-live version (e.g. under `apps/ledger-live-desktop/` or generated).
|
||||
- **Action:** After cloning ledger-live, search for where supported currencies are set and add `defi_oracle_meta_mainnet` there; confirm file names in the current branch.
|
||||
|
||||
### 7. wallet-api FAMILIES and union types
|
||||
|
||||
- **Gap:** Step 7 snippets show validation/types/serializer for Ethereum with chainId 138; the actual wallet-api repo may extend Ethereum family instead of adding a new family. The `FAMILIES` array and `Transaction` union may not need a new entry if Ethereum already supports multiple chainIds.
|
||||
- **Action:** Check wallet-api `packages/core/src/families/ethereum` and `common.ts`; if chainId is already a field in the schema, add 138 to allowed values and ensure Ledger Wallet adapter maps it.
|
||||
|
||||
### 8. Currency optional fields
|
||||
|
||||
- **Gap:** Step 1 currency did not set `blockAvgTime` or `disableCountervalue`.
|
||||
- **Status:** ✅ **Addressed** — `step-01-currency/currencies.chain138.ts` now includes `blockAvgTime: 2`. Uncomment `disableCountervalue: true` in the file if fiat should not be shown for Chain 138.
|
||||
|
||||
### 9. App-ethereum icon for Chain 138
|
||||
|
||||
- **Gap:** Step 2 README mentions “Ledger may require a network icon.” Our app-ethereum fork has the network entry but may need an icon asset for the device UI.
|
||||
- **Action:** If Ledger requests an icon, follow [Device App Kit deliverables (Icons)](https://developers.ledger.com/docs/device-app/submission-process/deliverables/icons) or provide a standard Ethereum-style icon for Chain 138.
|
||||
|
||||
### 10. E2E and integration tests
|
||||
|
||||
- **Gap:** Step 8 is manual only; no automated E2E or integration test scripts in this repo.
|
||||
- **Action:** Ledger’s flow includes [E2E](https://developers.ledger.com/docs/ledger-live/accounts/integration/blockchain/qa-requirements/e2e) and [Integration](https://developers.ledger.com/docs/ledger-live/accounts/integration/blockchain/qa-requirements/integ) tests. After integration, add or run these in the ledger-live monorepo for Chain 138.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| Category | Status |
|
||||
|----------|--------|
|
||||
| **Fixed in repo** | Step 3 Blockscout API (v2) |
|
||||
| **Confirm with Ledger** | Step 6 config shape, Step 7 extend vs new family, Step 4 pubKey vs publicKey |
|
||||
| **Add when needed** | Tokens/CAL, optional Swap/Staking, Clear Signing plugin, i18n keys, blockAvgTime/disableCountervalue, app-ethereum icon |
|
||||
| **Discover at integration time** | Exact LLD/LLM currency list file paths, E2E/integration test setup |
|
||||
|
||||
Use this document alongside [LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE.md](docs/LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE.md) and the step READMEs when implementing or handing off to Ledger.
|
||||
42
README.md
42
README.md
@@ -1 +1,41 @@
|
||||
# LedgerLive
|
||||
# Ledger Chain 138 Integration — Generated Code for All 8 Steps
|
||||
|
||||
**Purpose:** Drop-in or reference code for integrating Defi Oracle Meta Mainnet (Chain ID 138) with Ledger Wallet. Use after Ledger has accepted the integration request.
|
||||
|
||||
**Reference:** [LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE.md](docs/LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE.md) | [ADD_CHAIN138_TO_LEDGER_LIVE.md](docs/ADD_CHAIN138_TO_LEDGER_LIVE.md) | [DEFI_ORACLE_META_MAINNET_PROJECT_DESCRIPTION.md](docs/DEFI_ORACLE_META_MAINNET_PROJECT_DESCRIPTION.md)
|
||||
|
||||
---
|
||||
|
||||
## Layout
|
||||
|
||||
| Step | Path | Description |
|
||||
|------|------|-------------|
|
||||
| 1 | `step-01-currency/` | Cryptoassets currency entry for ledger-live |
|
||||
| 2 | `step-02-device-app-lib/` | App-ethereum network entry (patch/snippet) |
|
||||
| 3 | `step-03-coin-module/` | Coin-module skeleton (Ethereum family extension) |
|
||||
| 4 | `step-04-signer/` | Signer types and getAddress resolver |
|
||||
| 5 | `step-05-api/` | RPC/explorer config and network module |
|
||||
| 6 | `step-06-lld-llm/` | live-common setup and config |
|
||||
| 7 | `step-07-wallet-api/` | Wallet API family (validation, types, serializer) |
|
||||
| 8 | `step-08-manual-tests/` | Manual test plan and checklist script |
|
||||
|
||||
**Additional files:**
|
||||
|
||||
| Path | Description |
|
||||
|------|-------------|
|
||||
| `chains/eip155-138.json` | Chain spec for [ChainList](https://chainlist.org) / Ledger chains registry |
|
||||
| `app-ethereum/makefile_conf/chain/defi_oracle.mk` | Device app (nanos) build config for Chain 138 |
|
||||
| `docs/` | Full integration guide, project description, and Ledger form instructions |
|
||||
|
||||
---
|
||||
|
||||
## Gaps and missing integrations
|
||||
|
||||
See **[GAPS_AND_MISSING_INTEGRATIONS.md](GAPS_AND_MISSING_INTEGRATIONS.md)** for test results, fixes applied (e.g. Step 3 Blockscout v2 API), and a checklist of possible missing pieces (tokens/CAL, swap, staking, Clear Signing, i18n, E2E tests, etc.).
|
||||
|
||||
## Usage
|
||||
|
||||
1. Submit the [Ledger form](https://tally.so/r/mORpv8) and wait for approval.
|
||||
2. Fork/clone [LedgerHQ/ledger-live](https://github.com/LedgerHQ/ledger-live) and optionally [LedgerHQ/wallet-api](https://github.com/LedgerHQ/wallet-api).
|
||||
3. Copy or adapt the files from each step into the Ledger repos as instructed in the step README or comments.
|
||||
4. Run Step 8 manual tests before submitting to Ledger.
|
||||
|
||||
4
app-ethereum/makefile_conf/chain/defi_oracle.mk
Normal file
4
app-ethereum/makefile_conf/chain/defi_oracle.mk
Normal file
@@ -0,0 +1,4 @@
|
||||
PATH_APP_LOAD_PARAMS += "44'/60'"
|
||||
TICKER = "ETH"
|
||||
CHAIN_ID = 138
|
||||
APPNAME = "Defi Oracle Meta"
|
||||
49
chains/eip155-138.json
Normal file
49
chains/eip155-138.json
Normal file
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"name": "Defi Oracle Meta Mainnet",
|
||||
"chain": "dfiometa",
|
||||
"icon": "defioraclemeta",
|
||||
"rpc": [
|
||||
"https://rpc-http-pub.d-bis.org",
|
||||
"wss://rpc-ws-pub.d-bis.org",
|
||||
"https://rpc.d-bis.org",
|
||||
"wss://rpc.d-bis.org",
|
||||
"https://rpc2.d-bis.org",
|
||||
"wss://ws.rpc.d-bis.org",
|
||||
"wss://ws.rpc2.d-bis.org",
|
||||
"https://rpc.public-0138.defi-oracle.io",
|
||||
"wss://rpc.public-0138.defi-oracle.io",
|
||||
"https://rpc.defi-oracle.io",
|
||||
"wss://wss.defi-oracle.io",
|
||||
"https://defi-oracle-meta.rpc.thirdweb.com/${THIRDWEB_API_KEY}",
|
||||
"https://138.rpc.thirdweb.com/${THIRDWEB_API_KEY}"
|
||||
],
|
||||
"features": [
|
||||
{
|
||||
"name": "EIP155"
|
||||
},
|
||||
{
|
||||
"name": "EIP1559"
|
||||
}
|
||||
],
|
||||
"faucets": [],
|
||||
"nativeCurrency": {
|
||||
"name": "Ether",
|
||||
"symbol": "ETH",
|
||||
"decimals": 18
|
||||
},
|
||||
"infoURL": "https://d-bis.org",
|
||||
"shortName": "dfio-meta-main",
|
||||
"chainId": 138,
|
||||
"networkId": 1,
|
||||
"slip44": 60,
|
||||
"ens": {
|
||||
"registry": "0x57f1887a8BF19b14fC0dF6Fd9B2acc9Af147eA85"
|
||||
},
|
||||
"explorers": [
|
||||
{
|
||||
"name": "Blockscout",
|
||||
"url": "https://explorer.d-bis.org",
|
||||
"standard": "EIP3091"
|
||||
}
|
||||
]
|
||||
}
|
||||
211
docs/ADD_CHAIN138_TO_LEDGER_LIVE.md
Normal file
211
docs/ADD_CHAIN138_TO_LEDGER_LIVE.md
Normal file
@@ -0,0 +1,211 @@
|
||||
# Add Chain 138 (Defi Oracle Meta Mainnet) to Ledger Live
|
||||
|
||||
**Last Updated:** 2026-02-13
|
||||
**Status:** Action plan and submission guide
|
||||
|
||||
---
|
||||
|
||||
## Complete this now (your only required action) — ✅ Submitted 2026-02-13
|
||||
|
||||
The form has been submitted. Next: await Ledger’s response and follow their process (agreement + integration steps). For reference, the steps were:
|
||||
|
||||
1. **Open:** [Ledger blockchain integration form](https://tally.so/r/mORpv8).
|
||||
2. **Paste** the text below into the form field *"What are you looking from Ledger?"*, then replace `[your email/Telegram]` with your contact.
|
||||
3. **Submit** the form. Ledger will reply with next steps (and any agreement).
|
||||
|
||||
**Copy-paste block:**
|
||||
|
||||
```
|
||||
We would like to add Defi Oracle Meta Mainnet (Chain ID 138) to Ledger Live so users can manage ETH and tokens on this EVM chain natively in Ledger Wallet.
|
||||
|
||||
- Chain name: Defi Oracle Meta Mainnet
|
||||
- Chain ID: 138 (0x8a)
|
||||
- EVM-compatible (EIP-155, EIP-1559), standard derivation 44'/60'
|
||||
- Public RPCs and block explorer are live; chain is listed on Chainlist (chainlist.org/chain/138).
|
||||
- We already have Chain ID 138 configured in a Ledger App-Ethereum fork (network name "Defi Oracle Meta", ticker ETH) and can provide specs or PRs as needed.
|
||||
|
||||
Preferred contact: [your email/Telegram]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Ledger Live does not support user-added custom EVM networks. To have **Defi Oracle Meta Mainnet (Chain ID 138)** appear and work in Ledger Live (desktop/mobile), the chain must be added to Ledger’s supported list via their **official blockchain integration process**.
|
||||
|
||||
This doc gives the steps and materials to request and support that integration.
|
||||
|
||||
---
|
||||
|
||||
## Step 1: Submit the official request (required first)
|
||||
|
||||
**Do not start code changes** before Ledger has accepted your request. Their developer portal states:
|
||||
|
||||
> ⚠️ Don't start the development without signing an agreement with our teams.
|
||||
|
||||
1. **Open the Ledger blockchain integration request form:**
|
||||
**https://tally.so/r/mORpv8**
|
||||
|
||||
2. **Fill in the form** (e.g. “What are you looking from Ledger?”) with a short request to add **Defi Oracle Meta Mainnet (Chain ID 138)** to Ledger Live. Suggested text:
|
||||
|
||||
```
|
||||
We would like to add Defi Oracle Meta Mainnet (Chain ID 138) to Ledger Live so users can manage ETH and tokens on this EVM chain natively in Ledger Wallet.
|
||||
|
||||
- Chain name: Defi Oracle Meta Mainnet
|
||||
- Chain ID: 138 (0x8a)
|
||||
- EVM-compatible (EIP-155, EIP-1559), standard derivation 44'/60'
|
||||
- Public RPCs and block explorer are live; chain is listed on Chainlist (chainlist.org/chain/138).
|
||||
- We already have Chain ID 138 configured in a Ledger App-Ethereum fork (network name "Defi Oracle Meta", ticker ETH) and can provide specs or PRs as needed.
|
||||
|
||||
Preferred contact: [your email/Telegram]
|
||||
```
|
||||
|
||||
3. **Submit** and wait for Ledger to respond. They will guide you through the next steps (and any agreement).
|
||||
|
||||
---
|
||||
|
||||
## Step 2: What Ledger’s integration involves (after they respond)
|
||||
|
||||
Ledger’s [Adding your blockchain to Ledger Wallet](https://developers.ledger.com/docs/ledger-live/accounts/getting-started) guide outlines an **8-step process**. For an **EVM chain** like 138, the main touchpoints are:
|
||||
|
||||
| Step | What it means for Chain 138 |
|
||||
|------|-----------------------------|
|
||||
| **1 – Currency** | Register the chain in Ledger’s crypto-assets (e.g. `@ledgerhq/cryptoassets` in ledger-live), with `ethereumLikeInfo.chainId: 138` and explorerViews. |
|
||||
| **2 – Device app lib** | Ethereum app already supports multiple chain IDs; use `hw-app-eth` with chainId 138 in tx building/signing. Chain 138 may need to be in **official** Ledger app-ethereum (see below). |
|
||||
| **3 – Create module** | EVM chains often use the same “Ethereum” family module with different chain config (RPC, explorer). |
|
||||
| **4 – Derivation / Signer** | Standard EVM: `44'/60'` (already used in our app-ethereum config). |
|
||||
| **5 – API** | Ledger may use their own indexer/RPC or point to your public RPCs and Blockscout. |
|
||||
| **6 – LLD & LLM** | Desktop and mobile Ledger Wallet apps: live-common setup, currency list, i18n; run dev and QA. |
|
||||
| **7 – Wallet API** | wallet-api: Ethereum family extended for chainId 138 (or new family); Ledger Wallet adapter. |
|
||||
| **8 – Manual tests** | Execute send/receive test plan (sync, receive, balance, broadcast, operations, account). |
|
||||
|
||||
**Full step-by-step (all steps, no gaps):** [LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE.md](LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE.md). **Generated code for all 8 steps:** [step-01-currency/](../step-01-currency/) through [step-08-manual-tests/](../step-08-manual-tests/) — drop-in snippets and config for each step.
|
||||
|
||||
Ledger will tell you exactly which repos (e.g. `ledger-live`, `app-ethereum`, `wallet-api`) and which files to change or which data to provide.
|
||||
|
||||
---
|
||||
|
||||
## Step 3: Materials to have ready for Ledger
|
||||
|
||||
When Ledger asks for chain details or integration data, you can point them to or paste the following.
|
||||
|
||||
**Project description (short/medium/long):** [DEFI_ORACLE_META_MAINNET_PROJECT_DESCRIPTION.md](DEFI_ORACLE_META_MAINNET_PROJECT_DESCRIPTION.md) — use the **medium** paragraph for Ledger or listing forms.
|
||||
|
||||
### 3.1 Chain specification (Chainlist-compatible)
|
||||
|
||||
Our canonical chain spec is in this repo at `pr-workspace/chains/_data/chains/eip155-138.json`. Summary:
|
||||
|
||||
| Field | Value |
|
||||
|-------|--------|
|
||||
| **name** | Defi Oracle Meta Mainnet |
|
||||
| **chainId** | 138 |
|
||||
| **networkId** | 1 |
|
||||
| **shortName** | dfio-meta-main |
|
||||
| **nativeCurrency** | Ether (ETH), 18 decimals |
|
||||
| **slip44** | 60 (standard EVM) |
|
||||
| **infoURL** | https://d-bis.org |
|
||||
|
||||
**RPC URLs (public):**
|
||||
|
||||
- `https://rpc-http-pub.d-bis.org`
|
||||
- `wss://rpc-ws-pub.d-bis.org`
|
||||
- `https://rpc.d-bis.org`
|
||||
- `wss://rpc.d-bis.org`
|
||||
- `https://rpc2.d-bis.org`
|
||||
- `wss://ws.rpc.d-bis.org`
|
||||
- `wss://ws.rpc2.d-bis.org`
|
||||
- `https://rpc.public-0138.defi-oracle.io`
|
||||
- `wss://rpc.public-0138.defi-oracle.io`
|
||||
- `https://rpc.defi-oracle.io`
|
||||
- `wss://wss.defi-oracle.io`
|
||||
|
||||
**Block explorer:**
|
||||
|
||||
- Blockscout: `https://explorer.d-bis.org` (EIP3091)
|
||||
|
||||
**Features:** EIP-155, EIP-1559.
|
||||
|
||||
### 3.2 Ledger App-Ethereum (device) configuration
|
||||
|
||||
We already have Chain 138 in our app-ethereum fork:
|
||||
|
||||
- **`pr-workspace/app-ethereum/src/network.c`** (line 42):
|
||||
`{.chain_id = 138, .name = "Defi Oracle Meta", .ticker = "ETH"}`
|
||||
- **`pr-workspace/app-ethereum/makefile_conf/chain/defi_oracle.mk`**:
|
||||
`CHAIN_ID = 138`, `APPNAME = "Defi Oracle Meta"`, `TICKER = "ETH"`, derivation `44'/60'`
|
||||
|
||||
If Ledger asks for device-app changes, we can either:
|
||||
|
||||
- Propose a PR to **LedgerHQ/app-ethereum** adding the same entry to `network.c` (and any makefile/chain list they use), or
|
||||
- Provide the exact patch/snippet for them to integrate.
|
||||
|
||||
### 3.3 References in this repo
|
||||
|
||||
- [PUBLIC_RPC_CHAIN138_LEDGER.md](./PUBLIC_RPC_CHAIN138_LEDGER.md) – RPC list, NPMplus mapping, Ledger usage.
|
||||
- [CHAIN138_WALLET_CONFIG_VALIDATION.md](./CHAIN138_WALLET_CONFIG_VALIDATION.md) – Validated wallet config (MetaMask, ethers, Ledger).
|
||||
- [LEDGER_CHAIN138_ISSUES_AND_WORKAROUNDS.md](./LEDGER_CHAIN138_ISSUES_AND_WORKAROUNDS.md) – Current limitations and workarounds (e.g. Ledger + MetaMask).
|
||||
|
||||
---
|
||||
|
||||
## Public code review repo for the Ledger Live team
|
||||
|
||||
**All public code, specs, and patches for Ledger team review:** [**https://github.com/bis-innovations/LedgerLive**](https://github.com/bis-innovations/LedgerLive)
|
||||
|
||||
Use this repo to publish Chain 138 integration materials (cryptoassets entries, config snippets, app-ethereum changes, or full patches) so the Ledger Live team can review before or alongside any PR to LedgerHQ repos. Clone, add your changes, push, and share the repo or specific branches/PRs with Ledger when they ask for code.
|
||||
|
||||
### Initialize and push (from GitHub instructions)
|
||||
|
||||
**New repo (first commit):**
|
||||
```bash
|
||||
echo "# LedgerLive" >> README.md
|
||||
git init
|
||||
git add README.md
|
||||
git commit -m "first commit"
|
||||
git branch -M main
|
||||
git remote add origin https://github.com/bis-innovations/LedgerLive.git
|
||||
git push -u origin main
|
||||
```
|
||||
|
||||
**Existing local repo:**
|
||||
```bash
|
||||
git remote add origin https://github.com/bis-innovations/LedgerLive.git
|
||||
git branch -M main
|
||||
git push -u origin main
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 4: Optional – prepare for a future PR to Ledger Live
|
||||
|
||||
If Ledger confirms that adding Chain 138 is done by editing their **ledger-live** monorepo (e.g. `libs/ledgerjs/packages/cryptoassets` or `libs/ledger-live-common`), you can:
|
||||
|
||||
1. **Publish for review:** Push your work to [bis-innovations/LedgerLive](https://github.com/bis-innovations/LedgerLive) for Ledger team code review.
|
||||
2. Clone upstream: `git clone https://github.com/LedgerHQ/ledger-live.git`
|
||||
3. Follow their [installation and contribution guide](https://github.com/LedgerHQ/ledger-live/blob/develop/CONTRIBUTING.md).
|
||||
4. Locate where EVM chains are defined (often a data file or config listing chainId, name, RPC, explorer).
|
||||
5. Add an entry for Chain ID 138 using the spec in **Step 3.1** and any format Ledger requires.
|
||||
|
||||
Do this **only after** Ledger has accepted the request and indicated where to add the chain; their structure may differ from public guesses.
|
||||
|
||||
---
|
||||
|
||||
## Summary checklist
|
||||
|
||||
- [x] Submit the request at **https://tally.so/r/mORpv8** (describe Chain 138 and add preferred contact) — **Done 2026-02-13.**
|
||||
- [ ] Wait for Ledger’s response and follow their process (agreement + integration steps).
|
||||
- [x] **Materials ready:** chain spec ([chains/eip155-138.json](../chains/eip155-138.json)), public RPCs, explorer, app-ethereum config ([app-ethereum/makefile_conf/chain/defi_oracle.mk](../app-ethereum/makefile_conf/chain/defi_oracle.mk)), project description ([DEFI_ORACLE_META_MAINNET_PROJECT_DESCRIPTION.md](DEFI_ORACLE_META_MAINNET_PROJECT_DESCRIPTION.md)) — all present in repo.
|
||||
- [x] **Deployment reference ready:** [LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE.md](../11-references/LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE.md) — full 8-step integration with gaps filled, Chain 138 quick reference, and deployment checklist.
|
||||
- [ ] If Ledger asks for a PR or code review: publish code to **[bis-innovations/LedgerLive](https://github.com/bis-innovations/LedgerLive)** for their review; use the materials above and [LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE.md](../11-references/LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE.md) with their contribution guidelines.
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- **Public code review for Ledger team:** [**bis-innovations/LedgerLive**](https://github.com/bis-innovations/LedgerLive) — use for all Chain 138 integration code/specs/patches for Ledger Live team review.
|
||||
- **Full 8-step integration (this repo):** [LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE.md](../11-references/LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE.md) — all steps, deployment checklist, Chain 138 quick reference.
|
||||
- **Ledger – Adding your blockchain:** https://developers.ledger.com/docs/ledger-live/accounts/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
|
||||
- **Ledger Wallet API:** https://github.com/LedgerHQ/wallet-api
|
||||
- **Chainlist (Chain 138):** https://chainlist.org/chain/138
|
||||
96
docs/CHAIN138_TOKEN_ADDRESSES.md
Normal file
96
docs/CHAIN138_TOKEN_ADDRESSES.md
Normal file
@@ -0,0 +1,96 @@
|
||||
# Token Contract Addresses - ChainID 138
|
||||
|
||||
**Last Updated:** 2026-01-31
|
||||
**Document Version:** 1.0
|
||||
**Status:** Active Documentation
|
||||
|
||||
---
|
||||
|
||||
**Network**: ChainID 138 (SMOM-DBIS-138)
|
||||
**RPC Endpoint** (admin/deployment): `http://192.168.11.211:8545` (RPC_CORE_1) or `https://rpc-core.d-bis.org`
|
||||
**Explorer**: https://explorer.d-bis.org
|
||||
**Last Updated**: 2025-12-24
|
||||
|
||||
---
|
||||
|
||||
## 📋 ERC20 Token Contracts
|
||||
|
||||
### Standard Tokens
|
||||
|
||||
| Token | Symbol | Address | Decimals | Status | Notes |
|
||||
|-------|--------|---------|----------|--------|-------|
|
||||
| **Wrapped Ether** | WETH | `0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2` | 18 | ✅ Pre-deployed | Pre-deployed in Genesis |
|
||||
| **Wrapped Ether v10** | WETH10 | `0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f` | 18 | ✅ Pre-deployed | Pre-deployed in Genesis |
|
||||
| **Chainlink Token** | LINK | `0xb7721dD53A8c629d9f1Ba31a5819AFe250002b03` | 18 | ✅ Deployed | Used for CCIP fees |
|
||||
|
||||
### Compliant Stablecoins
|
||||
|
||||
| Token | Symbol | Address | Decimals | Status | Notes |
|
||||
|-------|--------|---------|----------|--------|-------|
|
||||
| **Tether USD (Compliant)** | cUSDT | `0x93E66202A11B1772E55407B32B44e5Cd8eda7f22` | 6 | ✅ Deployed | Compliant USDT token |
|
||||
| **USD Coin (Compliant)** | cUSDC | `0xf22258f57794CC8E06237084b353Ab30fFfa640b` | 6 | ✅ Deployed | Compliant USDC token |
|
||||
|
||||
---
|
||||
|
||||
## 🔗 Token Registry
|
||||
|
||||
The tokens can be tracked through the TokenRegistry contract:
|
||||
|
||||
| Contract | Address | Purpose |
|
||||
|----------|---------|---------|
|
||||
| **TokenRegistry** | `0x91Efe92229dbf7C5B38D422621300956B55870Fa` | Centralized registry for all tokens on ChainID 138 |
|
||||
|
||||
---
|
||||
|
||||
## 📊 Summary
|
||||
|
||||
### Total Token Contracts: 5
|
||||
|
||||
1. **WETH** - `0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2`
|
||||
2. **WETH10** - `0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f`
|
||||
3. **LINK** - `0xb7721dD53A8c629d9f1Ba31a5819AFe250002b03`
|
||||
4. **CompliantUSDT (cUSDT)** - `0x93E66202A11B1772E55407B32B44e5Cd8eda7f22`
|
||||
5. **CompliantUSDC (cUSDC)** - `0xf22258f57794CC8E06237084b353Ab30fFfa640b`
|
||||
|
||||
---
|
||||
|
||||
## 📝 Notes
|
||||
|
||||
1. **WETH9 and WETH10** were pre-deployed in the genesis block
|
||||
2. **LINK token** is used for CCIP (Cross-Chain Interoperability Protocol) fees
|
||||
3. **Compliant stablecoins** (cUSDT, cUSDC) include regulatory compliance features
|
||||
4. All addresses are checksummed and verified on-chain
|
||||
5. Token list maintained at: `token-lists/lists/dbis-138.tokenlist.json`
|
||||
|
||||
---
|
||||
|
||||
## 🔍 Verification
|
||||
|
||||
To verify a token contract on-chain:
|
||||
|
||||
```bash
|
||||
# Check contract code
|
||||
cast code <TOKEN_ADDRESS> --rpc-url http://192.168.11.211:8545
|
||||
|
||||
# Check token details (name, symbol, decimals)
|
||||
cast call <TOKEN_ADDRESS> "name()" --rpc-url http://192.168.11.211:8545
|
||||
cast call <TOKEN_ADDRESS> "symbol()" --rpc-url http://192.168.11.211:8545
|
||||
cast call <TOKEN_ADDRESS> "decimals()" --rpc-url http://192.168.11.211:8545
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Token alignment
|
||||
|
||||
| Source | File |
|
||||
|--------|------|
|
||||
| Token list | `token-lists/lists/dbis-138.tokenlist.json` |
|
||||
| Canonical | `smom-dbis-138/services/token-aggregation/src/config/canonical-tokens.ts` (FALLBACK_ADDRESSES) |
|
||||
| Allowlist | `dbis_core/src/core/defi/tezos-usdtz/allowlist.config.ts` (ALLOWED_CHAIN138_TOKENS) |
|
||||
|
||||
---
|
||||
|
||||
**References:**
|
||||
- Token List: `token-lists/lists/dbis-138.tokenlist.json`
|
||||
- Deployment Docs: `explorer-monorepo/docs/DEPLOYMENT_COMPLETE_CHAINID_138.md`
|
||||
- Contract Reference: [CONTRACT_ADDRESSES_REFERENCE.md](CONTRACT_ADDRESSES_REFERENCE.md), [CONTRACT_INVENTORY_AND_VERIFICATION.md](CONTRACT_INVENTORY_AND_VERIFICATION.md)
|
||||
89
docs/DEFI_ORACLE_META_MAINNET_PROJECT_DESCRIPTION.md
Normal file
89
docs/DEFI_ORACLE_META_MAINNET_PROJECT_DESCRIPTION.md
Normal file
@@ -0,0 +1,89 @@
|
||||
# Defi Oracle Meta Mainnet (Chain ID 138) — Project Description
|
||||
|
||||
**Last Updated:** 2026-02-12
|
||||
**Purpose:** Reusable project descriptions for listings, Ledger, Chainlist, CoinGecko, outreach, and documentation.
|
||||
|
||||
---
|
||||
|
||||
## Short (1–2 sentences)
|
||||
|
||||
**For:** Forms, badges, meta tags, character-limited fields.
|
||||
|
||||
**Option A (technical):**
|
||||
Defi Oracle Meta Mainnet (Chain ID 138) is an EVM-compatible blockchain built on Hyperledger Besu with QBFT consensus, offering ~2s block time, native oracle integration, and CCIP cross-chain bridges.
|
||||
|
||||
**Option B (use-case):**
|
||||
Defi Oracle Meta Mainnet is an enterprise-grade EVM chain (Chain ID 138) with compliant stablecoins, cross-chain bridges (CCIP), and native oracle support for institutional DeFi.
|
||||
|
||||
**Option C (minimal):**
|
||||
Production EVM chain (Chain ID 138) on Hyperledger Besu with QBFT, CCIP bridges, and Blockscout explorer.
|
||||
|
||||
---
|
||||
|
||||
## Medium (one paragraph)
|
||||
|
||||
**For:** Ledger submission, Chainlist, CoinGecko chain description, listing blurbs.
|
||||
|
||||
DeFi Oracle Meta Mainnet (Chain ID 138) is an enterprise-grade, EVM-compatible blockchain built on Hyperledger Besu with QBFT consensus. It features ~2-second block time, native oracle integration, Chainlink CCIP cross-chain bridges to Ethereum Mainnet and other EVM chains, and compliant stablecoins (cUSDT, cUSDC, cEURC) for institutional DeFi applications. The network is production-ready with public RPC endpoints, a Blockscout block explorer, and full MetaMask and Chainlist support.
|
||||
|
||||
---
|
||||
|
||||
## Long (full description)
|
||||
|
||||
**For:** README, submission packages, detailed outreach, documentation.
|
||||
|
||||
**DeFi Oracle Meta Mainnet (Chain ID 138)** is a production-ready, EVM-compatible blockchain built on **Hyperledger Besu** with **QBFT consensus**. It provides immediate finality with approximately **2-second block time** and is designed for institutional DeFi with native oracle integration, cross-chain bridges, and compliant assets.
|
||||
|
||||
**Network:** Chain ID 138 (0x8a), native currency ETH (18 decimals), standard EVM derivation (SLIP-44: 60). EIP-155 and EIP-1559 supported.
|
||||
|
||||
**Infrastructure:** Tiered architecture (validators, sentries, RPC nodes), public RPC endpoints (HTTPS and WebSocket), and **Blockscout** block explorer at https://explorer.d-bis.org. Information and docs: https://d-bis.org.
|
||||
|
||||
**Cross-chain:** Full **Chainlink CCIP** implementation (CCIP Router, CCIPWETH9Bridge, CCIPWETH10Bridge) for cross-chain transfers with Ethereum Mainnet and other supported chains. LINK-based fees; relay and monitoring tooling deployed.
|
||||
|
||||
**Assets:** Compliant stablecoins (cUSDT, cUSDC, cEURC), WETH9/WETH10, LINK, and a token registry with compliance controls. Oracle price feeds and keeper infrastructure for institutional use.
|
||||
|
||||
**Ecosystem:** MetaMask integration (custom network and Chainlist), thirdweb bridge support, token aggregation and market-data APIs, and deployment automation. Listed on Chainlist (chainlist.org/chain/138).
|
||||
|
||||
---
|
||||
|
||||
## Key facts (bullet form)
|
||||
|
||||
Use for forms, tables, or “About” sections:
|
||||
|
||||
| Item | Value |
|
||||
|------|--------|
|
||||
| **Name** | Defi Oracle Meta Mainnet |
|
||||
| **Chain ID** | 138 (0x8a) |
|
||||
| **Network ID** | 1 |
|
||||
| **Consensus** | QBFT (Hyperledger Besu) |
|
||||
| **Block time** | ~2 seconds |
|
||||
| **Native currency** | ETH (18 decimals) |
|
||||
| **Explorer** | https://explorer.d-bis.org (Blockscout) |
|
||||
| **Info / docs** | https://d-bis.org |
|
||||
| **EVM** | Yes (EIP-155, EIP-1559) |
|
||||
| **Derivation** | 44'/60' (standard EVM) |
|
||||
|
||||
**Features:** Public RPC (HTTPS/WSS), CCIP bridges, compliant stablecoins, oracle feeds, Blockscout, Chainlist, MetaMask, thirdweb.
|
||||
|
||||
---
|
||||
|
||||
## RPC and explorer (copy-paste)
|
||||
|
||||
**RPC (HTTP):**
|
||||
https://rpc-http-pub.d-bis.org, https://rpc.d-bis.org, https://rpc2.d-bis.org, https://rpc.defi-oracle.io, https://rpc.public-0138.defi-oracle.io
|
||||
|
||||
**RPC (WebSocket):**
|
||||
wss://rpc-ws-pub.d-bis.org, wss://rpc.d-bis.org, wss://ws.rpc.d-bis.org, wss://ws.rpc2.d-bis.org, wss://wss.defi-oracle.io, wss://rpc.public-0138.defi-oracle.io
|
||||
|
||||
**Block explorer:**
|
||||
https://explorer.d-bis.org
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- [CONTRACT_ADDRESSES_REFERENCE](CONTRACT_ADDRESSES_REFERENCE.md) — Canonical contract addresses (Chain 138)
|
||||
- [CHAINS_AND_PROTOCOLS_BRIDGE_INTEGRATION](CHAINS_AND_PROTOCOLS_BRIDGE_INTEGRATION.md) — Bridge chains and protocol acceptance
|
||||
- [ADD_CHAIN138_TO_LEDGER_LIVE](../04-configuration/ADD_CHAIN138_TO_LEDGER_LIVE.md) — Ledger Live submission (uses medium description)
|
||||
- [COINGECKO_SUBMISSION_PACKAGE](../04-configuration/coingecko/COINGECKO_SUBMISSION_PACKAGE.md) — CoinGecko chain/token submission
|
||||
- Main project repo — Full project README (see bis-innovations/proxmox or d-bis smom-dbis-138)
|
||||
237
docs/LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE.md
Normal file
237
docs/LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE.md
Normal file
@@ -0,0 +1,237 @@
|
||||
# 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 138–specific 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 Ledger’s 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
|
||||
9
step-01-currency/README.md
Normal file
9
step-01-currency/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Step 1 — Currency
|
||||
|
||||
Add the Chain 138 currency to `@ledgerhq/cryptoassets`.
|
||||
|
||||
**In ledger-live repo:**
|
||||
|
||||
1. Open `libs/ledgerjs/packages/cryptoassets/src/currencies.ts` (or `currencies.js`).
|
||||
2. Add the `defi_oracle_meta_mainnet` entry from `currencies.chain138.ts` to the cryptoassets map.
|
||||
3. If the repo uses a single flat object keyed by id, add: `defi_oracle_meta_mainnet: { ...defiOracleMetaMainnetCurrencyRaw }`.
|
||||
62
step-01-currency/currencies.chain138.ts
Normal file
62
step-01-currency/currencies.chain138.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Step 1 — Currency (Cryptoassets library)
|
||||
* Target: ledger-live libs/ledgerjs/packages/cryptoassets/src/currencies.ts
|
||||
* Add this entry to the cryptoassets map (merge with existing ethereum or add as new key).
|
||||
*
|
||||
* Chain 138: Defi Oracle Meta Mainnet
|
||||
* @see https://developers.ledger.com/docs/ledger-live/accounts/integration/blockchain/cryptoassets-library
|
||||
*/
|
||||
|
||||
export const defiOracleMetaMainnetCurrency = {
|
||||
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 },
|
||||
blockAvgTime: 2, // Chain 138 ~2s block time (Besu QBFT)
|
||||
// disableCountervalue: true, // uncomment if fiat should not be shown
|
||||
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",
|
||||
},
|
||||
],
|
||||
} as const;
|
||||
|
||||
// Plain object form for JSON/currencies.js style (if repo uses .js)
|
||||
export const defiOracleMetaMainnetCurrencyRaw = {
|
||||
type: "CryptoCurrency",
|
||||
id: "defi_oracle_meta_mainnet",
|
||||
coinType: 60,
|
||||
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 },
|
||||
blockAvgTime: 2,
|
||||
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",
|
||||
},
|
||||
],
|
||||
} as const;
|
||||
5
step-02-device-app-lib/README.md
Normal file
5
step-02-device-app-lib/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Step 2 — Device app lib
|
||||
|
||||
- **EVM/Chain 138:** Use existing `@ledgerhq/hw-app-eth`; no new device app lib. Ensure `chainId: 138` in transaction building/signing.
|
||||
- **app-ethereum (C):** If upstream Ledger app-ethereum does not list Chain 138, add the line from `network-entry-chain138.c` to `src/network.c`. Our fork already has it at `pr-workspace/app-ethereum/src/network.c` line 42.
|
||||
- **Icons:** If Ledger requires a network icon, use their icon process (see Device App Kit docs). Chain 138 can share the generic Ethereum-style icon until a custom one is added.
|
||||
30
step-02-device-app-lib/hw-app-eth-usage.ts
Normal file
30
step-02-device-app-lib/hw-app-eth-usage.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Step 2 — Device app lib (JS bindings)
|
||||
* For EVM/Chain 138 we use existing @ledgerhq/hw-app-eth. No new package needed.
|
||||
* Ensure chainId 138 is passed when building/signing transactions.
|
||||
*
|
||||
* Example usage in coin-module or live-common (signer/bridge):
|
||||
*/
|
||||
|
||||
import Eth from "@ledgerhq/hw-app-eth";
|
||||
|
||||
const CHAIN_ID_138 = 138;
|
||||
|
||||
// When getting address (path is BIP44 EVM: 44'/60'/0'/0/0)
|
||||
async function getAddress(
|
||||
transport: { send: (cla: number, ins: number, p1: number, p2: number, data?: Buffer) => Promise<Buffer> },
|
||||
path: string,
|
||||
display?: boolean
|
||||
) {
|
||||
const eth = new Eth(transport);
|
||||
const result = await eth.getAddress(path, display ?? false);
|
||||
return { address: result.address, publicKey: result.publicKey, path };
|
||||
}
|
||||
|
||||
// When signing a transaction, the serialized tx must include chainId 138 (EIP-155)
|
||||
// so the device shows "Defi Oracle Meta" and signs correctly.
|
||||
function buildTxWithChainId(tx: { chainId?: number; [k: string]: unknown }) {
|
||||
return { ...tx, chainId: tx.chainId ?? CHAIN_ID_138 };
|
||||
}
|
||||
|
||||
export { getAddress, buildTxWithChainId, CHAIN_ID_138 };
|
||||
12
step-02-device-app-lib/network-entry-chain138.c
Normal file
12
step-02-device-app-lib/network-entry-chain138.c
Normal file
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Step 2 — Device app lib (app-ethereum network entry)
|
||||
* Target: LedgerHQ/app-ethereum src/network.c
|
||||
*
|
||||
* Our fork already has Chain 138 at line 42. This snippet is for upstream Ledger
|
||||
* app-ethereum if they don't yet list Chain 138. Add one line to NETWORK_MAPPING[].
|
||||
*
|
||||
* Format: {.chain_id = 138, .name = "Defi Oracle Meta", .ticker = "ETH"},
|
||||
*/
|
||||
|
||||
/* Insert in src/network.c inside NETWORK_MAPPING[], e.g. after Polygon (137): */
|
||||
{.chain_id = 138, .name = "Defi Oracle Meta", .ticker = "ETH"},
|
||||
19
step-03-coin-module/README.md
Normal file
19
step-03-coin-module/README.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# Step 3 — Create coin module
|
||||
|
||||
For Chain 138 we **extend the Ethereum family** in ledger-live (no new coin-module). Use:
|
||||
|
||||
**Note:** `network-explorer.ts` uses Blockscout REST v2 API (`GET /api/v2/addresses/{address}/transactions`) with `next_page_params` pagination. Do not use Etherscan-style `module=account&action=txlist` — Blockscout uses a different API.
|
||||
|
||||
- **config.chain138.ts** — Chain 138 RPC and explorer config; plug into Ethereum family config or currency config.
|
||||
- **network-explorer.ts** — Example network layer (getLastBlock, getBalance, getTransactionCount, getAddressTransactions). Adapt to the Ethereum coin-module’s network/bridge API (e.g. wrap in the same interface as other EVM chains).
|
||||
|
||||
If Ledger requests a **dedicated** coin-module, create `libs/coin-modules/coin-defi_oracle_meta/` with:
|
||||
|
||||
- `bridge/` — sync, buildTransaction, signOperation, broadcast, getFeesForTransaction, getTransactionStatus
|
||||
- `logic/` — core logic (no bridge imports)
|
||||
- `network/` — this explorer + RPC wrapper
|
||||
- `signer/` — Step 4 getAddress + sign
|
||||
- `types/` — bridge, signer, errors
|
||||
- `config.ts`, `index.ts`
|
||||
|
||||
Dependency rule: `logic` → `network` only; `bridge` → `logic`, `network`, `signer`.
|
||||
28
step-03-coin-module/config.chain138.ts
Normal file
28
step-03-coin-module/config.chain138.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Step 3 — Create coin module (config for Ethereum family + Chain 138)
|
||||
* Target: ledger-live libs/coin-modules (or extend libs/ledger-live-common/src/families/ethereum)
|
||||
*
|
||||
* For Chain 138 we extend the Ethereum family. This config is used by the bridge/network.
|
||||
*/
|
||||
|
||||
export const CHAIN_ID = 138 as const;
|
||||
|
||||
export const RPC_URLS = [
|
||||
"https://rpc-http-pub.d-bis.org",
|
||||
"https://rpc.d-bis.org",
|
||||
"https://rpc2.d-bis.org",
|
||||
"https://rpc.public-0138.defi-oracle.io",
|
||||
"https://rpc.defi-oracle.io",
|
||||
] as const;
|
||||
|
||||
export const EXPLORER_BASE = "https://explorer.d-bis.org" as const;
|
||||
|
||||
export const chain138Config = {
|
||||
chainId: CHAIN_ID,
|
||||
rpcUrls: RPC_URLS,
|
||||
explorer: {
|
||||
address: `${EXPLORER_BASE}/address/$address`,
|
||||
tx: `${EXPLORER_BASE}/tx/$hash`,
|
||||
token: `${EXPLORER_BASE}/token/$contractAddress?a=$address`,
|
||||
},
|
||||
} as const;
|
||||
75
step-03-coin-module/network-explorer.ts
Normal file
75
step-03-coin-module/network-explorer.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Step 3 — Coin module: network layer (explorer/RPC wrapper)
|
||||
* Target: ledger-live libs/coin-modules/coin-ethereum (or coin-defi_oracle_meta) src/network/
|
||||
*
|
||||
* Wraps Chain 138 RPC and Blockscout for sync, history, fees. Use in bridge.
|
||||
*/
|
||||
|
||||
const RPC_URL = "https://rpc-http-pub.d-bis.org";
|
||||
const EXPLORER_API = "https://explorer.d-bis.org/api";
|
||||
|
||||
export async function getLastBlock(): Promise<number> {
|
||||
const res = await fetch(RPC_URL, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "eth_blockNumber", params: [] }),
|
||||
});
|
||||
const data = await res.json();
|
||||
return parseInt(data.result, 16);
|
||||
}
|
||||
|
||||
export async function getBalance(address: string): Promise<string> {
|
||||
const res = await fetch(RPC_URL, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
jsonrpc: "2.0",
|
||||
id: 1,
|
||||
method: "eth_getBalance",
|
||||
params: [address, "latest"],
|
||||
}),
|
||||
});
|
||||
const data = await res.json();
|
||||
return data.result ?? "0x0";
|
||||
}
|
||||
|
||||
export async function getTransactionCount(address: string): Promise<number> {
|
||||
const res = await fetch(RPC_URL, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
jsonrpc: "2.0",
|
||||
id: 1,
|
||||
method: "eth_getTransactionCount",
|
||||
params: [address, "latest"],
|
||||
}),
|
||||
});
|
||||
const data = await res.json();
|
||||
return parseInt(data.result ?? "0x0", 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* Explorer: get transactions for address.
|
||||
* Blockscout REST v2: GET /api/v2/addresses/{address_hash}/transactions
|
||||
* Response: { items: Tx[], next_page_params?: { block_number, index, items_count } }
|
||||
*/
|
||||
const EXPLORER_API_V2 = "https://explorer.d-bis.org/api/v2";
|
||||
|
||||
export async function getAddressTransactions(
|
||||
address: string,
|
||||
params?: { block_number?: number; index?: number; items_count?: number }
|
||||
): Promise<{ items: unknown[]; next_page_params?: { block_number: number; index: number; items_count: number } }> {
|
||||
let url = `${EXPLORER_API_V2}/addresses/${encodeURIComponent(address)}/transactions`;
|
||||
if (params?.block_number != null && params?.index != null && params?.items_count != null) {
|
||||
url += `?block_number=${params.block_number}&index=${params.index}&items_count=${params.items_count}`;
|
||||
}
|
||||
const res = await fetch(url);
|
||||
if (!res.ok) return { items: [] };
|
||||
const data = await res.json();
|
||||
return {
|
||||
items: data.items ?? [],
|
||||
next_page_params: data.next_page_params,
|
||||
};
|
||||
}
|
||||
|
||||
export { RPC_URL, EXPLORER_API, EXPLORER_API_V2 };
|
||||
15
step-04-signer/README.md
Normal file
15
step-04-signer/README.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Step 4 — Derivation / Signer
|
||||
|
||||
- **types-signer.ts** — Signer interface (Ethereum-style: getAddress, signTransaction, signPersonalMessage). Use as-is for EVM/Chain 138.
|
||||
- **getAddress.ts** — getAddress resolver using `@ledgerhq/coin-framework` (GetAddressFn, SignerContext, GetAddressOptions). Register in live-common family setup.
|
||||
|
||||
**CLI check (after currency is added):**
|
||||
```bash
|
||||
ledger-live getAddress --currency defi_oracle_meta_mainnet --path "44'/60'/0'/0/0" --derivationMode ""
|
||||
```
|
||||
Or with ethereum currency and chainId in config:
|
||||
```bash
|
||||
ledger-live getAddress --currency ethereum --path "44'/60'/0'/0/0" --derivationMode ""
|
||||
```
|
||||
|
||||
Derivation for Chain 138: **44'/60'/0'/0/0** (standard EVM BIP44).
|
||||
32
step-04-signer/getAddress.ts
Normal file
32
step-04-signer/getAddress.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Step 4 — Derivation / Signer: getAddress resolver
|
||||
* Target: ledger-live libs/coin-modules/coin-*/src/signer/getAddress.ts
|
||||
*
|
||||
* Uses @ledgerhq/coin-framework getAddressWrapper. For Ethereum family the
|
||||
* existing Ethereum getAddress resolver applies; ensure currency/chainId 138
|
||||
* is used when resolving for Defi Oracle Meta Mainnet.
|
||||
*
|
||||
* Example resolver shape (adapt to your coin-framework version):
|
||||
*/
|
||||
|
||||
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 { EthereumAddress, EthereumSigner } from "./types-signer";
|
||||
|
||||
const resolver = (
|
||||
signerContext: SignerContext<EthereumSigner, EthereumAddress>
|
||||
): GetAddressFn => {
|
||||
return async (deviceId: string, { path, verify }: GetAddressOptions) => {
|
||||
const address = (await signerContext(deviceId, (signer) =>
|
||||
signer.getAddress(path, verify)
|
||||
)) as EthereumAddress;
|
||||
return {
|
||||
address: address.address,
|
||||
publicKey: address.publicKey,
|
||||
path,
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
export default resolver;
|
||||
22
step-04-signer/types-signer.ts
Normal file
22
step-04-signer/types-signer.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Step 4 — Derivation / Signer: types
|
||||
* Target: ledger-live libs/coin-modules/coin-*/src/types/signer.ts
|
||||
* For EVM we use the same as Ethereum; Chain 138 uses path 44'/60'/0'/0/0.
|
||||
*/
|
||||
|
||||
export type EthereumAddress = {
|
||||
address: string;
|
||||
publicKey: string;
|
||||
returnCode: number;
|
||||
};
|
||||
|
||||
export type EthereumSignature = {
|
||||
signature: Buffer | null;
|
||||
returnCode: number;
|
||||
};
|
||||
|
||||
export interface EthereumSigner {
|
||||
getAddress(path: string, display?: boolean): Promise<EthereumAddress>;
|
||||
signTransaction(path: string, rawTxHex: string): Promise<EthereumSignature>;
|
||||
signPersonalMessage(path: string, messageHex: string): Promise<EthereumSignature>;
|
||||
}
|
||||
9
step-05-api/README.md
Normal file
9
step-05-api/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Step 5 — API
|
||||
|
||||
Provide **RPC and explorer** details to Ledger. Use **rpc-explorer-config.ts**:
|
||||
|
||||
- **RPC_ENDPOINTS** — Public HTTPS and WSS URLs for Chain 138.
|
||||
- **EXPLORER** — Blockscout at https://explorer.d-bis.org (EIP3091); optional apiUrl for indexer.
|
||||
- **BLOCK_AVG_TIME_SEC** — ~2s for Chain 138 (Besu QBFT).
|
||||
|
||||
Ledger may run their own indexer or proxy; they will specify. Have these values ready for their config or env (e.g. `API_DEFI_ORACLE_META_NODE`).
|
||||
31
step-05-api/rpc-explorer-config.ts
Normal file
31
step-05-api/rpc-explorer-config.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Step 5 — API: RPC and Explorer config for Ledger Wallet / coin-module
|
||||
* Target: ledger-live config or env; Ledger may use this for their indexer/RPC.
|
||||
*
|
||||
* Chain 138 public endpoints. Provide these to Ledger when they ask for API/RPC.
|
||||
*/
|
||||
|
||||
export const CHAIN_ID = 138;
|
||||
|
||||
export const RPC_ENDPOINTS = [
|
||||
"https://rpc-http-pub.d-bis.org",
|
||||
"wss://rpc-ws-pub.d-bis.org",
|
||||
"https://rpc.d-bis.org",
|
||||
"wss://rpc.d-bis.org",
|
||||
"https://rpc2.d-bis.org",
|
||||
"wss://ws.rpc.d-bis.org",
|
||||
"wss://ws.rpc2.d-bis.org",
|
||||
"https://rpc.public-0138.defi-oracle.io",
|
||||
"wss://rpc.public-0138.defi-oracle.io",
|
||||
"https://rpc.defi-oracle.io",
|
||||
"wss://wss.defi-oracle.io",
|
||||
] as const;
|
||||
|
||||
export const EXPLORER = {
|
||||
name: "Blockscout",
|
||||
url: "https://explorer.d-bis.org",
|
||||
standard: "EIP3091",
|
||||
apiUrl: "https://explorer.d-bis.org/api",
|
||||
} as const;
|
||||
|
||||
export const BLOCK_AVG_TIME_SEC = 2;
|
||||
7
step-06-lld-llm/README.md
Normal file
7
step-06-lld-llm/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Step 6 — LLD & LLM
|
||||
|
||||
1. **live-common setup** — Use **setup.chain138.ts** as reference; in `libs/ledger-live-common/src/families/ethereum/setup.ts` (or new family) ensure Defi Oracle Meta Mainnet currency gets the same bridge/resolver as Ethereum with chainId 138.
|
||||
2. **Config** — Add **config.chain138.ts** entry to `libs/ledger-live-common/src/bridge/config.ts` so `config_currency_defi_oracle_meta_mainnet` is loaded (status, node.url). Env: `API_DEFI_ORACLE_META_NODE`.
|
||||
3. **LLD** — In `live-common-set-supported-currencies.js` add `defi_oracle_meta_mainnet`. Add error keys in `static/i18n/en`.
|
||||
4. **LLM** — In `live-common-setup.js` add `defi_oracle_meta_mainnet`. Add error keys in `src/locales/en/common.json`.
|
||||
5. **Run:** `pnpm dev:lld` (desktop), `pnpm dev:llm` (mobile).
|
||||
21
step-06-lld-llm/config.chain138.ts
Normal file
21
step-06-lld-llm/config.chain138.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Step 6 — LLD & LLM: live-common config for Chain 138
|
||||
* Target: ledger-live libs/ledger-live-common/src/bridge/config.ts (or families/ethereum/config)
|
||||
*
|
||||
* Add to the config map so dynamic config (e.g. node URL) can be loaded for defi_oracle_meta_mainnet.
|
||||
*/
|
||||
|
||||
import type { ConfigInfo } from "@ledgerhq/live-config/LiveConfig";
|
||||
import { getEnv } from "@ledgerhq/live-env";
|
||||
|
||||
export const defiOracleMetaConfig: Record<string, ConfigInfo> = {
|
||||
config_currency_defi_oracle_meta_mainnet: {
|
||||
type: "object",
|
||||
default: {
|
||||
status: { type: "active" },
|
||||
node: {
|
||||
url: getEnv("API_DEFI_ORACLE_META_NODE") ?? "https://rpc-http-pub.d-bis.org",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
6
step-06-lld-llm/lld-llm-currency-list.txt
Normal file
6
step-06-lld-llm/lld-llm-currency-list.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
# Step 6 — Add currency to LLD and LLM supported lists
|
||||
# LLD: add "defi_oracle_meta_mainnet" to live-common-set-supported-currencies.js
|
||||
# LLM: add "defi_oracle_meta_mainnet" to live-common-setup.js
|
||||
# i18n: add error translation keys in static/i18n/en (LLD) and src/locales/en/common.json (LLM)
|
||||
|
||||
defi_oracle_meta_mainnet
|
||||
35
step-06-lld-llm/setup.chain138.ts
Normal file
35
step-06-lld-llm/setup.chain138.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Step 6 — LLD & LLM: live-common family setup (snippet for Chain 138)
|
||||
* Target: ledger-live libs/ledger-live-common/src/families/ethereum/setup.ts
|
||||
* (or new family libs/ledger-live-common/src/families/defi_oracle_meta/setup.ts)
|
||||
*
|
||||
* Merge Chain 138 into Ethereum family setup: ensure getCryptoCurrencyById("defi_oracle_meta_mainnet")
|
||||
* (or ethereum with chainId 138 in config) is supported and bridge/resolver use the same signer.
|
||||
*
|
||||
* Example shape (simplified; actual ledger-live uses createBridges, executeWithSigner, etc.):
|
||||
*/
|
||||
|
||||
/*
|
||||
import { getCryptoCurrencyById } from "@ledgerhq/cryptoassets/currencies";
|
||||
import Transport from "@ledgerhq/hw-transport";
|
||||
import Eth from "@ledgerhq/hw-app-eth";
|
||||
import type { Bridge } from "@ledgerhq/types-live";
|
||||
import { createResolver, executeWithSigner } from "../../bridge/setup";
|
||||
import myCoinResolver from "@ledgerhq/coin-ethereum/signer/index"; // or your coin-module
|
||||
|
||||
const createSigner = (transport: Transport) => new Eth(transport);
|
||||
|
||||
const currency = getCryptoCurrencyById("defi_oracle_meta_mainnet");
|
||||
const getCurrencyConfig = () => getCurrencyConfiguration(currency);
|
||||
|
||||
const bridge: Bridge<...> = createBridges(
|
||||
executeWithSigner(createSigner),
|
||||
getCurrencyConfig
|
||||
);
|
||||
const resolver = createResolver(createSigner, myCoinResolver);
|
||||
|
||||
export { bridge, resolver, cliTools };
|
||||
*/
|
||||
|
||||
export const SETUP_CURRENCY_ID = "defi_oracle_meta_mainnet";
|
||||
export const SETUP_SIGNER_CREATOR = "createSigner: (transport) => new Eth(transport)";
|
||||
9
step-07-wallet-api/README.md
Normal file
9
step-07-wallet-api/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Step 7 — Wallet API
|
||||
|
||||
1. **wallet-api repo** — If Ethereum family already supports multiple chainIds, add **138** to validation and routing. Otherwise use:
|
||||
- **validation.ethereum-chain138.ts** — Zod schema allowing chainId 138.
|
||||
- **types.ethereum-chain138.ts** — Transaction types.
|
||||
- **serializer.ethereum-chain138.ts** — Serialize/deserialize for JSON-RPC.
|
||||
- In `packages/core/src/families/common.ts` ensure `FAMILIES` includes the family; in `validation.ts` and `serializer.ts` add the new type to the union.
|
||||
2. **ledger-live repo** — Bump `@ledgerhq/wallet-api-core`, `-server`, `-client`. Add or extend **walletApiAdapter.chain138.ts** in `libs/ledger-live-common/src/families/ethereum/walletApiAdapter.ts` so WalletAPI transactions with chainId 138 map to LL transactions. Do not edit the generated `generated/walletApiAdapter.ts` by hand; add the source adapter and run the sync-families-dispatch script.
|
||||
3. **Changelog** — `pnpm changelog`, create changeset for `@ledgerhq/wallet-api-core` (minor), open PR.
|
||||
45
step-07-wallet-api/serializer.ethereum-chain138.ts
Normal file
45
step-07-wallet-api/serializer.ethereum-chain138.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Step 7 — Wallet API: serialize/deserialize for JSON-RPC
|
||||
* Target: wallet-api packages/core/src/families/ethereum/serializer.ts
|
||||
*
|
||||
* Ethereum family already has serialization; ensure chainId is preserved.
|
||||
* When adding a new family, implement serializeTransaction/deserializeTransaction
|
||||
* for the new type and add to the union in packages/core/src/families/serializer.ts.
|
||||
*/
|
||||
|
||||
import type { RawEthereumTransaction } from "./types.ethereum-chain138";
|
||||
import type { EthereumTransaction } from "./types.ethereum-chain138";
|
||||
|
||||
export function serializeEthereumTransaction(
|
||||
tx: EthereumTransaction
|
||||
): RawEthereumTransaction {
|
||||
return {
|
||||
family: "ethereum",
|
||||
amount: tx.amount,
|
||||
recipient: tx.recipient,
|
||||
gasPrice: tx.gasPrice,
|
||||
maxFeePerGas: tx.maxFeePerGas,
|
||||
maxPriorityFeePerGas: tx.maxPriorityFeePerGas,
|
||||
gasLimit: tx.gasLimit,
|
||||
data: tx.data,
|
||||
nonce: tx.nonce,
|
||||
chainId: tx.chainId,
|
||||
};
|
||||
}
|
||||
|
||||
export function deserializeEthereumTransaction(
|
||||
raw: RawEthereumTransaction
|
||||
): EthereumTransaction {
|
||||
return {
|
||||
family: "ethereum",
|
||||
amount: raw.amount,
|
||||
recipient: raw.recipient,
|
||||
gasPrice: raw.gasPrice,
|
||||
maxFeePerGas: raw.maxFeePerGas,
|
||||
maxPriorityFeePerGas: raw.maxPriorityFeePerGas,
|
||||
gasLimit: raw.gasLimit,
|
||||
data: raw.data,
|
||||
nonce: raw.nonce,
|
||||
chainId: raw.chainId,
|
||||
};
|
||||
}
|
||||
33
step-07-wallet-api/types.ethereum-chain138.ts
Normal file
33
step-07-wallet-api/types.ethereum-chain138.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Step 7 — Wallet API: types for Ethereum family (Chain 138)
|
||||
* Target: wallet-api packages/core/src/families/ethereum/types.ts
|
||||
*
|
||||
* Transaction and Raw transaction types. Chain 138 uses same shape as Ethereum;
|
||||
* chainId 138 identifies the network.
|
||||
*/
|
||||
|
||||
export interface EthereumTransaction {
|
||||
family: "ethereum";
|
||||
amount: string;
|
||||
recipient: string;
|
||||
gasPrice?: string;
|
||||
maxFeePerGas?: string;
|
||||
maxPriorityFeePerGas?: string;
|
||||
gasLimit?: string;
|
||||
data?: string;
|
||||
nonce?: number;
|
||||
chainId: number; // 138 for Defi Oracle Meta Mainnet
|
||||
}
|
||||
|
||||
export interface RawEthereumTransaction {
|
||||
family: "ethereum";
|
||||
amount: string;
|
||||
recipient: string;
|
||||
gasPrice?: string;
|
||||
maxFeePerGas?: string;
|
||||
maxPriorityFeePerGas?: string;
|
||||
gasLimit?: string;
|
||||
data?: string;
|
||||
nonce?: number;
|
||||
chainId: number;
|
||||
}
|
||||
28
step-07-wallet-api/validation.ethereum-chain138.ts
Normal file
28
step-07-wallet-api/validation.ethereum-chain138.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Step 7 — Wallet API: validation (Zod) for Ethereum family with chainId 138
|
||||
* Target: ledger-live wallet-api packages/core/src/families/ethereum/validation.ts
|
||||
* (If Ledger adds Chain 138 to Ethereum family, ensure chainId 138 is allowed in schema.)
|
||||
*
|
||||
* Example: extend schemaRawEthereumTransaction to allow chainId 138.
|
||||
*/
|
||||
|
||||
import { z } from "zod";
|
||||
|
||||
const CHAIN_ID_138 = 138;
|
||||
|
||||
export const schemaRawEthereumTransaction = z.object({
|
||||
family: z.literal("ethereum"),
|
||||
amount: z.string(),
|
||||
recipient: z.string(),
|
||||
gasPrice: z.string().optional(),
|
||||
maxFeePerGas: z.string().optional(),
|
||||
maxPriorityFeePerGas: z.string().optional(),
|
||||
gasLimit: z.string().optional(),
|
||||
data: z.string().optional(),
|
||||
nonce: z.number().optional(),
|
||||
chainId: z.number().refine((id) => id === 1 || id === CHAIN_ID_138, {
|
||||
message: "chainId must be 1 (Ethereum) or 138 (Defi Oracle Meta Mainnet)",
|
||||
}),
|
||||
});
|
||||
|
||||
export type RawEthereumTransaction = z.infer<typeof schemaRawEthereumTransaction>;
|
||||
32
step-07-wallet-api/walletApiAdapter.chain138.ts
Normal file
32
step-07-wallet-api/walletApiAdapter.chain138.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Step 7 — Wallet API: Ledger Wallet adapter (WalletAPI tx <-> LL tx)
|
||||
* Target: ledger-live libs/ledger-live-common/src/families/ethereum/walletApiAdapter.ts
|
||||
*
|
||||
* If Chain 138 is exposed via Wallet API, ensure the adapter maps WalletAPI
|
||||
* Ethereum transaction (with chainId 138) to Ledger Wallet Ethereum transaction.
|
||||
* Add to the generated walletApiAdapter dispatch (via sync-families-dispatch script).
|
||||
*/
|
||||
|
||||
/*
|
||||
// Example: in libs/ledger-live-common/src/families/ethereum/walletApiAdapter.ts
|
||||
export function fromWalletAPITransaction(
|
||||
walletApiTx: WalletAPIEthereumTransaction
|
||||
): EthereumTransaction {
|
||||
return {
|
||||
...walletApiTx,
|
||||
chainId: walletApiTx.chainId ?? 138,
|
||||
};
|
||||
}
|
||||
|
||||
export function toWalletAPITransaction(
|
||||
llTx: EthereumTransaction
|
||||
): WalletAPIEthereumTransaction {
|
||||
return {
|
||||
...llTx,
|
||||
chainId: llTx.chainId,
|
||||
};
|
||||
}
|
||||
*/
|
||||
|
||||
export const ADAPTER_NOTE =
|
||||
"Extend ethereum walletApiAdapter to handle chainId 138; register in sync-families-dispatch so generated walletApiAdapter.ts includes it.";
|
||||
6
step-08-manual-tests/README.md
Normal file
6
step-08-manual-tests/README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Step 8 — Manual tests
|
||||
|
||||
- **test-plan.md** — Full send/receive test plan (sync, receive, balance, broadcast, operations, account). Check off each item after testing in Ledger Wallet.
|
||||
- **run-checklist.sh** — Prints the checklist to the terminal. Run: `chmod +x run-checklist.sh && ./run-checklist.sh`.
|
||||
|
||||
Complete these tests before considering the integration done or before submitting to Ledger.
|
||||
12
step-08-manual-tests/run-checklist.sh
Executable file
12
step-08-manual-tests/run-checklist.sh
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
# Step 8 — Manual test checklist runner (prints steps; no automation)
|
||||
# Usage: ./run-checklist.sh
|
||||
|
||||
set -e
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
echo "=== Ledger Chain 138 Manual Test Checklist ==="
|
||||
echo "Run each item in Ledger Wallet (desktop or mobile) with Defi Oracle Meta Mainnet."
|
||||
echo ""
|
||||
cat "${SCRIPT_DIR}/test-plan.md"
|
||||
echo ""
|
||||
echo "=== End of checklist ==="
|
||||
42
step-08-manual-tests/test-plan.md
Normal file
42
step-08-manual-tests/test-plan.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# Step 8 — Send/Receive Manual Test Plan
|
||||
|
||||
**Source:** [Ledger Manual tests](https://developers.ledger.com/docs/ledger-live/accounts/integration/blockchain/test-plan)
|
||||
|
||||
Execute after Chain 138 is added to Ledger Wallet (LLD/LLM). Use a Ledger device with Ethereum app and Chain 138 configured.
|
||||
|
||||
---
|
||||
|
||||
## Synchronization
|
||||
|
||||
- [ ] Add an account (Defi Oracle Meta Mainnet)
|
||||
- [ ] Migrate an account: Add an account in prod, don’t crash using tested version
|
||||
- [ ] Synchronizing manually does not throw an error (green check)
|
||||
- [ ] Synchronizing of a big account (multiple pages when fetching history)
|
||||
|
||||
## Receive / Address verification
|
||||
|
||||
- [ ] Users can verify their address with the nano
|
||||
- [ ] Users can verify their address without the nano
|
||||
|
||||
## Balance
|
||||
|
||||
- [ ] Available balance is right
|
||||
|
||||
## Broadcast
|
||||
|
||||
- [ ] Send max operation empties the account
|
||||
- [ ] Send operation sends the right amount
|
||||
- [ ] Users cannot send more than their balance
|
||||
|
||||
## Operations
|
||||
|
||||
- [ ] Optimistic operation is filled correctly
|
||||
- [ ] Operation history has every transaction of the account
|
||||
- [ ] Operation has the right transaction ID
|
||||
- [ ] User can reach the tx details by clicking on “View on explorer”
|
||||
- [ ] Operation account is right
|
||||
|
||||
## Account details
|
||||
|
||||
- [ ] Fiat value fetched from countervalues is right (if enabled)
|
||||
- [ ] Users can favorite their account and it is shown
|
||||
Reference in New Issue
Block a user