xno-skills 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +63 -24
  2. package/dist/cjs/version.d.ts +2 -2
  3. package/dist/cjs/version.js +1 -1
  4. package/dist/esm/version.d.ts +2 -2
  5. package/dist/esm/version.js +1 -1
  6. package/package.json +8 -3
  7. package/dist/package.json +0 -65
  8. package/dist/src/address-bip44.d.ts +0 -59
  9. package/dist/src/address-bip44.d.ts.map +0 -1
  10. package/dist/src/address-bip44.js +0 -194
  11. package/dist/src/address-bip44.js.map +0 -1
  12. package/dist/src/address-legacy.d.ts +0 -10
  13. package/dist/src/address-legacy.d.ts.map +0 -1
  14. package/dist/src/address-legacy.js +0 -121
  15. package/dist/src/address-legacy.js.map +0 -1
  16. package/dist/src/base32.d.ts +0 -46
  17. package/dist/src/base32.d.ts.map +0 -1
  18. package/dist/src/base32.js +0 -112
  19. package/dist/src/base32.js.map +0 -1
  20. package/dist/src/blake2b.d.ts +0 -19
  21. package/dist/src/blake2b.d.ts.map +0 -1
  22. package/dist/src/blake2b.js +0 -28
  23. package/dist/src/blake2b.js.map +0 -1
  24. package/dist/src/cli.d.ts +0 -3
  25. package/dist/src/cli.d.ts.map +0 -1
  26. package/dist/src/cli.js +0 -262
  27. package/dist/src/cli.js.map +0 -1
  28. package/dist/src/convert.d.ts +0 -41
  29. package/dist/src/convert.d.ts.map +0 -1
  30. package/dist/src/convert.js +0 -132
  31. package/dist/src/convert.js.map +0 -1
  32. package/dist/src/index.d.ts +0 -9
  33. package/dist/src/index.d.ts.map +0 -1
  34. package/dist/src/index.js +0 -10
  35. package/dist/src/index.js.map +0 -1
  36. package/dist/src/mcp.d.ts +0 -2
  37. package/dist/src/mcp.d.ts.map +0 -1
  38. package/dist/src/mcp.js +0 -137
  39. package/dist/src/mcp.js.map +0 -1
  40. package/dist/src/qr.d.ts +0 -9
  41. package/dist/src/qr.d.ts.map +0 -1
  42. package/dist/src/qr.js +0 -23
  43. package/dist/src/qr.js.map +0 -1
  44. package/dist/src/seed.d.ts +0 -26
  45. package/dist/src/seed.d.ts.map +0 -1
  46. package/dist/src/seed.js +0 -67
  47. package/dist/src/seed.js.map +0 -1
  48. package/dist/src/validate.d.ts +0 -7
  49. package/dist/src/validate.d.ts.map +0 -1
  50. package/dist/src/validate.js +0 -66
  51. package/dist/src/validate.js.map +0 -1
package/README.md CHANGED
@@ -15,9 +15,12 @@ npx skills add CasualSecurityInc/xno-skills
15
15
  ```
16
16
 
17
17
  Available skills:
18
- - `create-wallet`: Workflow for generating and securing new wallets.
18
+ - `create-wallet`: Wallet creation/import guidance (BIP39 default; legacy supported; safe `--stdin` workflows).
19
19
  - `convert-units`: High-precision unit conversion reference.
20
+ - `generate-qr`: Terminal-friendly Nano payment QR codes (address + optional amount).
20
21
  - `validate-address`: Address format and checksum verification guide.
22
+ - `check-balance`: Check balance/pending via Nano node RPC.
23
+ - `mcp-purse`: Use `xno-mcp` as a private “purse” custody blackbox (addresses only; no seed leakage).
21
24
 
22
25
  ## MCP Server
23
26
 
@@ -30,15 +33,19 @@ To use it, add the following to your MCP client configuration:
30
33
  "mcpServers": {
31
34
  "xno": {
32
35
  "command": "npx",
33
- "args": ["-y", "xno-mcp"]
36
+ "args": ["-y", "-p", "xno-skills@^0.3.0", "xno-mcp"]
34
37
  }
35
38
  }
36
39
  }
37
40
  ```
38
41
 
39
42
  Exposed tools:
40
- - `generate_wallet`: Returns a new mnemonic, seed, and address.
41
- - `derive_address`: Derives an address from a mnemonic or seed and index.
43
+ - `purse_create` / `purse_list` / `purse_addresses`: Named “purses” (custody inside MCP; return addresses only).
44
+ - `purse_balance` / `purse_probe_balances`: Balance/pending checks for purse accounts via RPC.
45
+ - `config_get` / `config_set`: Store defaults (RPC URL, timeouts; optional purse persistence).
46
+ - `generate_wallet`: Generate a wallet (default: BIP39 derivation).
47
+ - `derive_address`: Derive an address (supports `bip39` + `legacy`, with `auto` preference).
48
+ - `probe_mnemonic`: Probe both derivations via RPC (helps resolve 24-word ambiguity).
42
49
  - `convert_units`: Converts between XNO and raw units.
43
50
  - `validate_address`: Validates address format and checksum.
44
51
 
@@ -48,22 +55,24 @@ Exposed tools:
48
55
  npm install xno-skills
49
56
  ```
50
57
 
58
+ ## Releasing
59
+
60
+ See `RELEASING.md`.
61
+
51
62
  ## Quick Start
52
63
 
53
64
  ```typescript
54
65
  import {
55
- generateSeed,
56
- seedToMnemonic,
57
- deriveAddressLegacy,
66
+ generateMnemonic,
67
+ deriveAddressBIP44,
58
68
  validateAddress,
59
69
  nanoToRaw,
60
70
  rawToNano
61
71
  } from 'xno-skills';
62
72
 
63
- // Generate a new wallet
64
- const seed = generateSeed();
65
- const mnemonic = seedToMnemonic(seed);
66
- const { address, privateKey, publicKey } = deriveAddressLegacy(seed, 0);
73
+ // Generate a new BIP39 wallet + first account (index 0)
74
+ const mnemonic = generateMnemonic(24);
75
+ const { address, privateKey, publicKey } = deriveAddressBIP44(mnemonic, 0);
67
76
 
68
77
  console.log('Address:', address);
69
78
  // nano_1abc123...
@@ -91,17 +100,21 @@ npx xno-skills --help
91
100
 
92
101
  ### Wallet Commands
93
102
 
103
+ Security note: avoid pasting mnemonics/seeds into chat logs. Prefer `--stdin` (or `--mnemonic-env`) for import/probing commands.
104
+
94
105
  #### Create a new wallet
95
106
 
96
107
  ```bash
97
- # Default output (seed + mnemonic + address)
108
+ # Default: BIP39 derivation
98
109
  xno-skills wallet create
99
110
 
100
- # Output only the seed
101
- xno-skills wallet create --seed
111
+ # Choose legacy derivation (24-word “seed phrase” style)
112
+ xno-skills wallet create --format legacy
102
113
 
103
- # Output only the mnemonic
104
- xno-skills wallet create --mnemonic
114
+ # Control BIP39 word count / passphrase / index
115
+ xno-skills wallet create --words 12
116
+ xno-skills wallet create --passphrase "optional passphrase"
117
+ xno-skills wallet create --index 0
105
118
 
106
119
  # JSON output
107
120
  xno-skills wallet create --json
@@ -110,17 +123,20 @@ xno-skills wallet create --json
110
123
  #### Restore from mnemonic
111
124
 
112
125
  ```bash
113
- xno-skills wallet from-mnemonic "word1 word2 ... word24"
126
+ # Safer import via stdin (recommended)
127
+ echo "word1 word2 ... word24" | xno-skills wallet from-mnemonic --stdin --json
114
128
 
115
129
  # JSON output
116
- xno-skills wallet from-mnemonic "word1 word2 ... word24" --json
130
+ xno-skills wallet from-mnemonic --stdin --json
117
131
  ```
118
132
 
119
- Output example:
120
- ```
121
- Seed: 0123456789abcdef...
122
- Mnemonic: word1 word2 word3 ... word24
123
- Address: nano_1abc123...
133
+ #### Probe mnemonic ambiguity (24-word)
134
+
135
+ If you have a Nano RPC endpoint, you can probe the first few indexes for both derivations and see which accounts are opened / have balances:
136
+
137
+ ```bash
138
+ export NANO_RPC_URL="http://127.0.0.1:7076"
139
+ echo "word1 word2 ... word24" | xno-skills wallet probe-mnemonic --stdin --json
124
140
  ```
125
141
 
126
142
  ### Convert Units
@@ -164,10 +180,27 @@ xno-skills qr nano_1abc123... --json
164
180
  xno-skills validate nano_1abc123...
165
181
  ```
166
182
 
183
+ ### RPC (balance/pending)
184
+
185
+ ```bash
186
+ export NANO_RPC_URL="http://127.0.0.1:7076"
187
+ xno-skills rpc account-balance nano_1abc123... --json --xno
188
+ ```
189
+
167
190
  ## API Reference
168
191
 
169
192
  ### Seed Generation
170
193
 
194
+ #### `generateMnemonic(wordCount = 24): string`
195
+
196
+ Generate a BIP39 mnemonic (12/15/18/21/24 words).
197
+
198
+ ```typescript
199
+ import { generateMnemonic } from 'xno-skills';
200
+
201
+ const mnemonic = generateMnemonic(24);
202
+ ```
203
+
171
204
  #### `generateSeed(): string`
172
205
 
173
206
  Generate a cryptographically secure 32-byte seed (256 bits).
@@ -192,7 +225,9 @@ const mnemonic = seedToMnemonic(seed);
192
225
 
193
226
  #### `mnemonicToSeed(mnemonic: string): string`
194
227
 
195
- Convert a BIP39 mnemonic phrase back to a hex-encoded seed.
228
+ Convert a BIP39 mnemonic phrase back to its underlying entropy (hex).
229
+
230
+ Note: this is **not** the BIP39 PBKDF2 “seed”; it’s the raw entropy the mnemonic encodes.
196
231
 
197
232
  ```typescript
198
233
  import { mnemonicToSeed } from 'xno-skills';
@@ -201,6 +236,10 @@ const seed = mnemonicToSeed(mnemonic);
201
236
  // Returns: "0123456789abcdef..." (64 hex characters)
202
237
  ```
203
238
 
239
+ #### `mnemonicToBIP39Seed(mnemonic: string, passphrase?: string): string`
240
+
241
+ Convert a BIP39 mnemonic (+ optional passphrase) to the PBKDF2 “seed” hex used for HD derivation.
242
+
204
243
  #### `validateMnemonic(mnemonic: string): boolean`
205
244
 
206
245
  Validate a BIP39 mnemonic phrase.
@@ -1,6 +1,6 @@
1
1
  export declare const pkg: {
2
2
  readonly name: "xno-skills";
3
- readonly version: "0.3.0";
3
+ readonly version: "0.3.2";
4
4
  };
5
- export declare const version: "0.3.0";
5
+ export declare const version: "0.3.2";
6
6
  //# sourceMappingURL=version.d.ts.map
@@ -5,7 +5,7 @@ exports.version = exports.pkg = void 0;
5
5
  // Keep this in sync by running "npm run build" (prebuild hook).
6
6
  exports.pkg = {
7
7
  name: "xno-skills",
8
- version: "0.3.0"
8
+ version: "0.3.2"
9
9
  };
10
10
  exports.version = exports.pkg.version;
11
11
  //# sourceMappingURL=version.js.map
@@ -1,6 +1,6 @@
1
1
  export declare const pkg: {
2
2
  readonly name: "xno-skills";
3
- readonly version: "0.3.0";
3
+ readonly version: "0.3.2";
4
4
  };
5
- export declare const version: "0.3.0";
5
+ export declare const version: "0.3.2";
6
6
  //# sourceMappingURL=version.d.ts.map
@@ -2,7 +2,7 @@
2
2
  // Keep this in sync by running "npm run build" (prebuild hook).
3
3
  export const pkg = {
4
4
  name: "xno-skills",
5
- version: "0.3.0"
5
+ version: "0.3.2"
6
6
  };
7
7
  export const version = pkg.version;
8
8
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xno-skills",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "XNO CLI - Interact with the Nano cryptocurrency",
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/index.js",
@@ -21,13 +21,18 @@
21
21
  "dist"
22
22
  ],
23
23
  "scripts": {
24
+ "preversion": "npm test",
25
+ "version": "node scripts/update-version.js && git add src/version.ts",
26
+ "postversion": "node -e \"const v=require('./package.json').version; console.log('Created tag v'+v+'. Next: git push && git push --tags, then publish a GitHub Release for v'+v);\"",
24
27
  "prebuild": "node scripts/update-version.js",
25
28
  "prebuild:esm": "node scripts/update-version.js",
26
29
  "prebuild:cjs": "node scripts/update-version.js",
27
- "test": "npm run build:esm && vitest",
30
+ "test": "npm run build:esm && vitest run",
31
+ "test:watch": "npm run build:esm && vitest",
28
32
  "build": "tsc",
29
33
  "build:esm": "tsc -p tsconfig.esm.json",
30
- "build:cjs": "tsc -p tsconfig.cjs.json"
34
+ "build:cjs": "tsc -p tsconfig.cjs.json",
35
+ "prepack": "npm run build && npm run build:cjs"
31
36
  },
32
37
  "keywords": [
33
38
  "nano",
package/dist/package.json DELETED
@@ -1,65 +0,0 @@
1
- {
2
- "name": "xno-skills",
3
- "version": "0.1.2",
4
- "description": "XNO CLI - Interact with the Nano cryptocurrency",
5
- "type": "module",
6
- "main": "./dist/cjs/index.js",
7
- "module": "./dist/esm/index.js",
8
- "types": "./dist/esm/index.d.ts",
9
- "bin": {
10
- "xno-skills": "bin/xno-skills",
11
- "xno-mcp": "bin/xno-mcp"
12
- },
13
- "exports": {
14
- ".": {
15
- "import": "./dist/esm/index.js",
16
- "require": "./dist/cjs/index.js",
17
- "types": "./dist/esm/index.d.ts"
18
- }
19
- },
20
- "files": [
21
- "dist"
22
- ],
23
- "scripts": {
24
- "test": "vitest",
25
- "build": "tsc",
26
- "build:esm": "tsc -p tsconfig.esm.json",
27
- "build:cjs": "tsc -p tsconfig.cjs.json"
28
- },
29
- "keywords": [
30
- "nano",
31
- "xno",
32
- "cryptocurrency",
33
- "wallet",
34
- "bip39",
35
- "bip44",
36
- "ed25519",
37
- "blake2b",
38
- "blockchain"
39
- ],
40
- "author": "Casual Security Inc",
41
- "repository": {
42
- "type": "git",
43
- "url": "git+https://github.com/casualsecurity/xno-skills.git"
44
- },
45
- "bugs": {
46
- "url": "https://github.com/casualsecurity/xno-skills/issues"
47
- },
48
- "homepage": "https://github.com/casualsecurity/xno-skills#readme",
49
- "license": "MIT",
50
- "devDependencies": {
51
- "@types/node": "^25.5.0",
52
- "@types/qrcode-terminal": "^0.12.2",
53
- "typescript": "^5.9.3",
54
- "vitest": "^4.1.0"
55
- },
56
- "dependencies": {
57
- "@modelcontextprotocol/sdk": "^1.27.1",
58
- "@noble/curves": "^2.0.1",
59
- "@noble/hashes": "^1.7.0",
60
- "@scure/bip39": "^2.0.1",
61
- "commander": "^14.0.3",
62
- "micro-key-producer": "^0.8.5",
63
- "qrcode-terminal": "^0.12.0"
64
- }
65
- }
@@ -1,59 +0,0 @@
1
- /**
2
- * Derive a private key from a mnemonic using BIP44 path for Nano
3
- * Path: m/44'/165'/[address_index]' (all hardened derivation)
4
- *
5
- * @param mnemonic - BIP39 mnemonic phrase (12 or 24 words)
6
- * @param index - Address index (0, 1, 2, ...)
7
- * @param passphrase - Optional BIP39 passphrase (default: empty string)
8
- * @returns 64-character hex string representing the 32-byte private key
9
- */
10
- export declare function derivePrivateKeyBIP44(mnemonic: string, index: number, passphrase?: string): string;
11
- /**
12
- * Derive public key from private key using Nano's Blake2b-512 Ed25519 variant
13
- * Note: Nano uses Blake2b-512 for Ed25519 key derivation, not standard SHA-512
14
- *
15
- * @param privateKey - 64-character hex string (32 bytes)
16
- * @returns 64-character hex string representing the 32-byte public key
17
- */
18
- export declare function derivePublicKeyBIP44(privateKey: string): string;
19
- /**
20
- * Convert public key to Nano address
21
- *
22
- * @param publicKey - 64-character hex string (32 bytes)
23
- * @returns Nano address starting with 'nano_'
24
- */
25
- export declare function publicKeyToAddressBIP44(publicKey: string): string;
26
- /**
27
- * Result of BIP44 address derivation
28
- */
29
- export interface BIP44AddressResult {
30
- privateKey: string;
31
- publicKey: string;
32
- address: string;
33
- }
34
- /**
35
- * Derive a Nano address from a mnemonic using BIP44 path
36
- * Path: m/44'/165'/[address_index]' (all hardened derivation)
37
- *
38
- * @param mnemonic - BIP39 mnemonic phrase (12 or 24 words)
39
- * @param index - Address index (0, 1, 2, ...)
40
- * @param passphrase - Optional BIP39 passphrase (default: empty string)
41
- * @returns Object containing privateKey, publicKey, and address
42
- */
43
- export declare function deriveAddressBIP44(mnemonic: string, index: number, passphrase?: string): BIP44AddressResult;
44
- /**
45
- * Validate a BIP39 mnemonic phrase
46
- *
47
- * @param mnemonic - Mnemonic phrase to validate
48
- * @returns true if valid, false otherwise
49
- */
50
- export declare function validateMnemonicBIP44(mnemonic: string): boolean;
51
- /**
52
- * Convert mnemonic to BIP39 seed (for debugging/verification)
53
- *
54
- * @param mnemonic - BIP39 mnemonic phrase
55
- * @param passphrase - Optional BIP39 passphrase
56
- * @returns 128-character hex string (64 bytes)
57
- */
58
- export declare function mnemonicToBIP39Seed(mnemonic: string, passphrase?: string): string;
59
- //# sourceMappingURL=address-bip44.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"address-bip44.d.ts","sourceRoot":"","sources":["../../src/address-bip44.ts"],"names":[],"mappings":"AA8EA;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,UAAU,GAAE,MAAW,GACtB,MAAM,CA0BR;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAuC/D;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAUjE;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,UAAU,GAAE,MAAW,GACtB,kBAAkB,CAUpB;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE/D;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,GAAE,MAAW,GAAG,MAAM,CAMrF"}
@@ -1,194 +0,0 @@
1
- // BIP44 derivation for Nano using SLIP-0010 for Ed25519
2
- // Path: m/44'/165'/[address_index]' (coin_type 165 for Nano)
3
- // Uses standard Ed25519 for public key derivation (not Blake2b like legacy)
4
- import * as bip39 from '@scure/bip39';
5
- import { wordlist } from '@scure/bip39/wordlists/english.js';
6
- import { HDKey } from 'micro-key-producer/slip10.js';
7
- import { ed25519 } from '@noble/curves/ed25519.js';
8
- import { blake2b } from '@noble/hashes/blake2b.js';
9
- /**
10
- * Convert Uint8Array to hex string
11
- */
12
- function bytesToHex(bytes) {
13
- return Array.from(bytes)
14
- .map(b => b.toString(16).padStart(2, '0'))
15
- .join('');
16
- }
17
- /**
18
- * Convert hex string to Uint8Array
19
- */
20
- function hexToBytes(hex) {
21
- if (hex.length % 2 !== 0) {
22
- throw new Error('Invalid hex string: length must be even');
23
- }
24
- const bytes = new Uint8Array(hex.length / 2);
25
- for (let i = 0; i < bytes.length; i++) {
26
- bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
27
- }
28
- return bytes;
29
- }
30
- /**
31
- * Encode public key bytes to Nano address format
32
- * Uses Blake2b-5 checksum (reversed) and base32 encoding
33
- */
34
- function encodeNanoAddress(publicKey) {
35
- const CHARSET = '13456789abcdefghijkmnopqrstuwxyz';
36
- // Calculate 5-byte Blake2b checksum and reverse it
37
- const checksum = blake2b(publicKey, { dkLen: 5 });
38
- const checksumReversed = new Uint8Array(checksum.length);
39
- for (let i = 0; i < checksum.length; i++) {
40
- checksumReversed[i] = checksum[checksum.length - 1 - i];
41
- }
42
- // Combine public key (32 bytes) + checksum (5 bytes, reversed) = 37 bytes
43
- const combined = new Uint8Array(publicKey.length + checksumReversed.length);
44
- combined.set(publicKey, 0);
45
- combined.set(checksumReversed, publicKey.length);
46
- // Encode using Nano's base32 with offset calculation
47
- const length = combined.length;
48
- const leftover = (length * 8) % 5;
49
- const offset = leftover === 0 ? 0 : 5 - leftover;
50
- let value = 0;
51
- let result = '';
52
- let bits = 0;
53
- for (let i = 0; i < length; i++) {
54
- value = (value << 8) | combined[i];
55
- bits += 8;
56
- while (bits >= 5) {
57
- result += CHARSET[(value >>> (bits + offset - 5)) & 31];
58
- bits -= 5;
59
- }
60
- }
61
- if (bits > 0) {
62
- result += CHARSET[(value << (5 - (bits + offset))) & 31];
63
- }
64
- return `nano_${result}`;
65
- }
66
- /**
67
- * Derive a private key from a mnemonic using BIP44 path for Nano
68
- * Path: m/44'/165'/[address_index]' (all hardened derivation)
69
- *
70
- * @param mnemonic - BIP39 mnemonic phrase (12 or 24 words)
71
- * @param index - Address index (0, 1, 2, ...)
72
- * @param passphrase - Optional BIP39 passphrase (default: empty string)
73
- * @returns 64-character hex string representing the 32-byte private key
74
- */
75
- export function derivePrivateKeyBIP44(mnemonic, index, passphrase = '') {
76
- // Validate mnemonic
77
- if (!bip39.validateMnemonic(mnemonic, wordlist)) {
78
- throw new Error('Invalid mnemonic phrase');
79
- }
80
- // Validate index
81
- if (!Number.isInteger(index) || index < 0 || index > 0x7FFFFFFF) {
82
- throw new Error('Index must be a valid 31-bit unsigned integer (0 to 2147483647)');
83
- }
84
- // Convert mnemonic to BIP39 seed (512-bit)
85
- const seed = bip39.mnemonicToSeedSync(mnemonic, passphrase);
86
- // Create HD key from seed using SLIP-0010 (Ed25519)
87
- const masterKey = HDKey.fromMasterSeed(seed);
88
- // Derive path: m/44'/165'/[index]'
89
- // 44' = BIP44 purpose
90
- // 165' = Nano coin type (SLIP-0044)
91
- // index' = address index (hardened)
92
- const path = `m/44'/165'/${index}'`;
93
- const derivedKey = masterKey.derive(path);
94
- // Return private key as hex string
95
- return bytesToHex(derivedKey.privateKey);
96
- }
97
- /**
98
- * Derive public key from private key using Nano's Blake2b-512 Ed25519 variant
99
- * Note: Nano uses Blake2b-512 for Ed25519 key derivation, not standard SHA-512
100
- *
101
- * @param privateKey - 64-character hex string (32 bytes)
102
- * @returns 64-character hex string representing the 32-byte public key
103
- */
104
- export function derivePublicKeyBIP44(privateKey) {
105
- if (privateKey.length !== 64) {
106
- throw new Error('Private key must be 64 hex characters (32 bytes)');
107
- }
108
- if (!/^[0-9a-fA-F]+$/.test(privateKey)) {
109
- throw new Error('Private key must be a valid hex string');
110
- }
111
- const privateKeyBytes = hexToBytes(privateKey);
112
- // Nano uses Blake2b-512 for Ed25519 key derivation instead of SHA-512
113
- const hash = blake2b(privateKeyBytes, { dkLen: 64 });
114
- // Clamp the first 32 bytes (scalar) per RFC 8032
115
- const scalarBytes = new Uint8Array(hash.slice(0, 32));
116
- scalarBytes[0] &= 248;
117
- scalarBytes[31] &= 127;
118
- scalarBytes[31] |= 64;
119
- // Convert to bigint (little-endian)
120
- let scalarBigint = 0n;
121
- for (let i = 0; i < 32; i++) {
122
- scalarBigint += BigInt(scalarBytes[i]) << BigInt(8 * i);
123
- }
124
- // Ed25519 curve order
125
- const CURVE_ORDER = BigInt('0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed');
126
- // Ensure scalar is in valid range
127
- if (scalarBigint === 0n || scalarBigint >= CURVE_ORDER) {
128
- scalarBigint = scalarBigint % CURVE_ORDER;
129
- if (scalarBigint === 0n) {
130
- scalarBigint = 1n;
131
- }
132
- }
133
- const publicKeyPoint = ed25519.Point.BASE.multiply(scalarBigint);
134
- return bytesToHex(publicKeyPoint.toBytes());
135
- }
136
- /**
137
- * Convert public key to Nano address
138
- *
139
- * @param publicKey - 64-character hex string (32 bytes)
140
- * @returns Nano address starting with 'nano_'
141
- */
142
- export function publicKeyToAddressBIP44(publicKey) {
143
- if (publicKey.length !== 64) {
144
- throw new Error('Public key must be 64 hex characters (32 bytes)');
145
- }
146
- if (!/^[0-9a-fA-F]+$/.test(publicKey)) {
147
- throw new Error('Public key must be a valid hex string');
148
- }
149
- const publicKeyBytes = hexToBytes(publicKey);
150
- return encodeNanoAddress(publicKeyBytes);
151
- }
152
- /**
153
- * Derive a Nano address from a mnemonic using BIP44 path
154
- * Path: m/44'/165'/[address_index]' (all hardened derivation)
155
- *
156
- * @param mnemonic - BIP39 mnemonic phrase (12 or 24 words)
157
- * @param index - Address index (0, 1, 2, ...)
158
- * @param passphrase - Optional BIP39 passphrase (default: empty string)
159
- * @returns Object containing privateKey, publicKey, and address
160
- */
161
- export function deriveAddressBIP44(mnemonic, index, passphrase = '') {
162
- const privateKey = derivePrivateKeyBIP44(mnemonic, index, passphrase);
163
- const publicKey = derivePublicKeyBIP44(privateKey);
164
- const address = publicKeyToAddressBIP44(publicKey);
165
- return {
166
- privateKey,
167
- publicKey,
168
- address,
169
- };
170
- }
171
- /**
172
- * Validate a BIP39 mnemonic phrase
173
- *
174
- * @param mnemonic - Mnemonic phrase to validate
175
- * @returns true if valid, false otherwise
176
- */
177
- export function validateMnemonicBIP44(mnemonic) {
178
- return bip39.validateMnemonic(mnemonic, wordlist);
179
- }
180
- /**
181
- * Convert mnemonic to BIP39 seed (for debugging/verification)
182
- *
183
- * @param mnemonic - BIP39 mnemonic phrase
184
- * @param passphrase - Optional BIP39 passphrase
185
- * @returns 128-character hex string (64 bytes)
186
- */
187
- export function mnemonicToBIP39Seed(mnemonic, passphrase = '') {
188
- if (!bip39.validateMnemonic(mnemonic, wordlist)) {
189
- throw new Error('Invalid mnemonic phrase');
190
- }
191
- const seed = bip39.mnemonicToSeedSync(mnemonic, passphrase);
192
- return bytesToHex(seed);
193
- }
194
- //# sourceMappingURL=address-bip44.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"address-bip44.js","sourceRoot":"","sources":["../../src/address-bip44.ts"],"names":[],"mappings":"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"}
@@ -1,10 +0,0 @@
1
- export declare function derivePrivateKeyLegacy(seed: string, index: number): string;
2
- export declare function derivePublicKeyLegacy(privateKey: string): string;
3
- export declare function publicKeyToAddress(publicKey: string): string;
4
- export interface LegacyAddressResult {
5
- privateKey: string;
6
- publicKey: string;
7
- address: string;
8
- }
9
- export declare function deriveAddressLegacy(seed: string, index: number): LegacyAddressResult;
10
- //# sourceMappingURL=address-legacy.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"address-legacy.d.ts","sourceRoot":"","sources":["../../src/address-legacy.ts"],"names":[],"mappings":"AAyBA,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CA0B1E;AAED,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAuChE;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAmB5D;AA4BD,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,mBAAmB,CAUpF"}