Skip to content

Commit 5e65f19

Browse files
thephezclaude
andauthored
feat: add view-wallet script and wallet import documentation (#67)
* feat: add view-wallet script to inspect existing wallet Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs: add importing existing wallet section and derivation path reference Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs: add claude.md * docs: apply review feedback * fix: rethrow non-identity errors in view-wallet identity lookup Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 037c02a commit 5e65f19

3 files changed

Lines changed: 170 additions & 0 deletions

File tree

CLAUDE.md

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
Tutorial code for [Dash Platform](https://docs.dash.org/platform) demonstrating how to interact with the Dash network using `@dashevo/evo-sdk`. Covers identities, DPNS names, data contracts, and documents.
8+
9+
## Commands
10+
11+
```bash
12+
npm test # Read-only tests (~2min, safe to run anytime)
13+
npm run test:read-write # Write tests (destructive, consumes testnet credits, ~5min)
14+
npm run test:all # Both suites sequentially
15+
npm run test:setup # Mocha tests for setupDashClient configuration
16+
17+
npm run lint # TypeScript type-check all JS files (tsc)
18+
npm run fmt # Format with Prettier
19+
```
20+
21+
**Running a single tutorial directly:**
22+
23+
```bash
24+
node connect.mjs
25+
node 1-Identities-and-Names/identity-retrieve.mjs
26+
```
27+
28+
**Running a single test file:**
29+
30+
```bash
31+
node --test --test-timeout=120000 test/read-only.test.mjs
32+
```
33+
34+
## Architecture
35+
36+
### Tutorial Structure
37+
38+
Each tutorial is a standalone `.mjs` ESM file with top-level `await`. The pattern is consistent:
39+
40+
```javascript
41+
import { setupDashClient } from '../setupDashClient.mjs';
42+
43+
const { sdk, keyManager } = await setupDashClient();
44+
45+
try {
46+
// Tutorial logic — use sdk and keyManager
47+
console.log(result.toJSON());
48+
} catch (e) {
49+
console.error('Something went wrong:\n', e.message);
50+
}
51+
```
52+
53+
### `setupDashClient.mjs`
54+
55+
The central helper (~500 lines) that all tutorials import. It handles:
56+
57+
- Loading `.env` via `dotenv`
58+
- BIP39 wallet derivation from `PLATFORM_MNEMONIC`
59+
- DIP-13 key path derivation
60+
- SDK instantiation (`createClient(network)`)
61+
- Key manager setup — returns `{ sdk, keyManager, addressKeyManager }`
62+
63+
`keyManager.identityId` resolves automatically from the mnemonic. `keyManager.getAuth()` returns the identity, key, and signer needed for signing transactions.
64+
65+
> **Note:** The in-memory key pattern in `setupDashClient` is for tutorials only — not suitable for production.
66+
67+
### Test Framework
68+
69+
Tests use Node.js built-in test runner. Each test runs a tutorial as a **subprocess** via `test/run-tutorial.mjs` and validates:
70+
71+
- Exit code is 0
72+
- `stdout`/`stderr` match expected regex patterns
73+
- Process was not killed (no timeout)
74+
75+
`test/assertions.mjs` provides helpers like `extractId()` and `extractKeyId()` to capture values from output for use in subsequent dependent tests.
76+
77+
**Read-write tests** maintain a shared state object to pass IDs (contract IDs, document IDs, etc.) between sequential dependent tests.
78+
79+
### Derivation Paths
80+
81+
All key derivation uses standard Dash paths. External wallets/tools must use the same paths for compatibility.
82+
83+
| Key type | Testnet path | Mainnet path |
84+
| - | - | - |
85+
| Platform address (BIP44) | `m/44'/1'/0'/0/i` | `m/44'/5'/0'/0/i` |
86+
| Identity master key (DIP-13) | `m/9'/1'/5'/0'/0'/0'/0'` | `m/9'/5'/5'/0'/0'/0'/0'` |
87+
| Identity keys 0–4 (DIP-13) | `m/9'/1'/5'/0'/0'/0'/k'` | `m/9'/5'/5'/0'/0'/0'/k'` |
88+
89+
Where `i` = address index and `k` = key index (0=MASTER, 1=HIGH auth, 2=CRITICAL auth, 3=TRANSFER, 4=ENCRYPTION).
90+
91+
No BIP39 passphrase is used.
92+
93+
### Environment Variables
94+
95+
Copy `.env.example` to `.env`. Key variables:
96+
97+
| Variable | Purpose |
98+
| - | - |
99+
| `PLATFORM_MNEMONIC` | BIP39 mnemonic; required for all write operations |
100+
| `NETWORK` | `testnet` (default) or `mainnet` |
101+
| `DATA_CONTRACT_ID` | Output of `contract-register-minimal.mjs` |
102+
| `DOCUMENT_ID` | Output of `document-submit.mjs` |
103+
| `RECIPIENT_ID` | Identity ID for credit transfers |
104+
| `RECIPIENT_PLATFORM_ADDRESS` | `tdash1...` address for send-funds |
105+
106+
Read-only tests skip gracefully when `PLATFORM_MNEMONIC` is unset.
107+
108+
### Directory Layout
109+
110+
- **Root** — shared utilities (`setupDashClient.mjs`, `connect.mjs`, `create-wallet.mjs`, `view-wallet.mjs`, `send-funds.mjs`)
111+
- **`1-Identities-and-Names/`** — identity registration, top-up, key management, DPNS name registration/lookup
112+
- **`2-Contracts-and-Documents/`** — data contract variants (minimal, indexed, binary, timestamps, history, NFT), document CRUD, NFT operations
113+
- **`test/`** — test runner, assertions, read-only and read-write test suites
114+
- **`docs/`** — HTML/JS interactive tutorial runner (separate from Node tutorials)
115+
116+
### Linting / Types
117+
118+
TypeScript (`tsconfig.json`) checks JS files with `strict: true`, `noUnusedLocals: true`, targeting Node16 modules. ESLint uses `airbnb-base`. Prettier uses single quotes, 2-space tabs, trailing commas.

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ npm ci
4848
1. Fund the platform address using the bridge URL printed in the previous step
4949
1. Create a `.env` file (see [`.env.example`](./.env.example)) and set `PLATFORM_MNEMONIC` to the
5050
mnemonic from step 2. Set `NETWORK` if needed (defaults to `testnet`).
51+
1. To inspect an existing wallet after configuring `PLATFORM_MNEMONIC`, run `node view-wallet.mjs`
5152

5253
Proceed with the [Identities and Names tutorials](./1-Identities-and-Names/) first and the
5354
[Contracts and Documents tutorials](./2-Contracts-and-Documents/) next. They align with the
@@ -80,6 +81,21 @@ npm run test:read-write
8081
npm run test:all
8182
```
8283

84+
### Importing an existing wallet
85+
86+
If you already have a Dash identity created with another tool (e.g. [Dash
87+
Bridge](https://bridge.thepasta.org/)), you can use it directly by setting `PLATFORM_MNEMONIC` to
88+
your existing mnemonic. Run `node view-wallet.mjs` to confirm the derived address and identity ID.
89+
90+
For compatibility, the external tool must use the same derivation paths (no BIP39 passphrase):
91+
92+
| Key type | Testnet | Mainnet |
93+
| - | - | - |
94+
| Platform address (BIP44) | `m/44'/1'/0'/0/i` | `m/44'/5'/0'/0/i` |
95+
| Identity keys (DIP-13) | `m/9'/1'/5'/0'/0'/0'/k'` | `m/9'/5'/5'/0'/0'/0'/k'` |
96+
97+
The first platform address (`i=0`) must be funded for top-up and send-funds operations.
98+
8399
## Contributing
84100

85101
PRs accepted.

view-wallet.mjs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import {
2+
createClient,
3+
clientConfig,
4+
AddressKeyManager,
5+
IdentityKeyManager,
6+
} from './setupDashClient.mjs';
7+
8+
const { mnemonic, network } = clientConfig;
9+
10+
if (!mnemonic) {
11+
console.error('No mnemonic found. Set PLATFORM_MNEMONIC in your .env file.');
12+
process.exit(1);
13+
}
14+
15+
try {
16+
const sdk = await createClient(network);
17+
const addressKeyManager = await AddressKeyManager.create({ sdk, mnemonic, network });
18+
const { bech32m, path } = addressKeyManager.primaryAddress;
19+
20+
let identityId = 'No identity found for this mnemonic';
21+
try {
22+
const keyManager = await IdentityKeyManager.create({ sdk, mnemonic, network });
23+
identityId = keyManager.identityId;
24+
} catch (e) {
25+
if (!e.message?.includes('No identity found for the given mnemonic')) throw e;
26+
}
27+
28+
// ⚠️ Never log mnemonics in real applications
29+
console.log('Network: ', network);
30+
console.log('Mnemonic: ', mnemonic);
31+
console.log(`First address: ${bech32m} (${path})`);
32+
console.log('Fund address: ', `https://bridge.thepasta.org/?address=${bech32m}`);
33+
console.log('Identity ID: ', identityId);
34+
} catch (e) {
35+
console.error('Something went wrong:\n', e.message);
36+
}

0 commit comments

Comments
 (0)