@neuraiproject/neurai-key 3.0.2 → 3.1.0
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.
- package/README.md +102 -8
- package/dist/NeuraiKey.global.js +86 -5
- package/dist/NeuraiKey.global.js.map +1 -1
- package/dist/browser.js +87 -6
- package/dist/browser.js.map +1 -1
- package/dist/index.cjs +89 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +30 -4
- package/dist/index.js +87 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ Generate Neurai addresses from a mnemonic phrase following the standards BIP32,
|
|
|
5
5
|
That is, use your 12 words to get addresses for Neurai mainnet and testnet.
|
|
6
6
|
|
|
7
7
|
**NPM**: https://www.npmjs.com/package/@neuraiproject/neurai-key
|
|
8
|
-
**CDN**: https://cdn.jsdelivr.net/npm/@neuraiproject/neurai-key@3.
|
|
8
|
+
**CDN**: https://cdn.jsdelivr.net/npm/@neuraiproject/neurai-key@3.1.0/dist/NeuraiKey.global.js
|
|
9
9
|
|
|
10
10
|
## Features
|
|
11
11
|
|
|
@@ -16,7 +16,16 @@ That is, use your 12 words to get addresses for Neurai mainnet and testnet.
|
|
|
16
16
|
- ✅ Mainnet and Testnet support for Neurai (XNA)
|
|
17
17
|
- ✅ Support for both XNA (BIP44: 1900) and XNA Legacy (BIP44: 0) networks
|
|
18
18
|
- ✅ Convert raw public keys into Neurai mainnet or testnet addresses
|
|
19
|
-
- ✅
|
|
19
|
+
- ✅ AuthScript witness v1 addresses with Bech32m encoding
|
|
20
|
+
- ✅ `authType = 0x00` NoAuth addresses from `witnessScript` only
|
|
21
|
+
- ✅ `authType = 0x01` PostQuantum ML-DSA-44 AuthScript addresses
|
|
22
|
+
- ✅ `authType = 0x02` Legacy secp256k1 AuthScript addresses
|
|
23
|
+
|
|
24
|
+
## Compatibility Note
|
|
25
|
+
|
|
26
|
+
Starting in `3.1.0`, PQ AuthScript descriptors are computed as `0x01 || HASH160(0x05 || rawPublicKey)` to match `neurai-sign-transaction` and the node implementation.
|
|
27
|
+
|
|
28
|
+
This changes PQ AuthScript addresses and commitments compared to older releases of this library. If you previously generated PQ addresses with an older version of `neurai-key`, treat them as legacy outputs and verify fund exposure before migrating.
|
|
20
29
|
|
|
21
30
|
## Network Types
|
|
22
31
|
|
|
@@ -24,7 +33,7 @@ This library supports three Neurai network configurations:
|
|
|
24
33
|
|
|
25
34
|
- **`xna` / `xna-test`**: Current Neurai standard (BIP44 coin type: 1900)
|
|
26
35
|
- **`xna-legacy` / `xna-legacy-test`**: Legacy Neurai addresses (BIP44 coin type: 0)
|
|
27
|
-
- **`xna-pq` / `xna-pq-test`**:
|
|
36
|
+
- **`xna-pq` / `xna-pq-test`**: AuthScript witness v1 addresses (Bech32m, `nq1` / `tnq1`)
|
|
28
37
|
|
|
29
38
|
The main difference is the derivation path and address encoding:
|
|
30
39
|
- **XNA**: mainnet `m/44'/1900'/0'/0/0`, testnet `m/44'/1'/0'/0/0` — Base58Check (recommended for new wallets)
|
|
@@ -185,6 +194,14 @@ console.log(testAddress); // tPXGaMRNwZuV1UKSrD9gABPscrJWUmedQ9
|
|
|
185
194
|
|
|
186
195
|
Generate quantum-resistant AuthScript addresses using the ML-DSA-44 signature scheme (FIPS 204). The library now follows the migrated `witness v1 = AuthScript` layout, so the Bech32m program is a 32-byte commitment instead of the old 20-byte PQ keyhash.
|
|
187
196
|
|
|
197
|
+
Supported AuthScript variants:
|
|
198
|
+
|
|
199
|
+
| `authType` | Name | Description |
|
|
200
|
+
|------------|------|-------------|
|
|
201
|
+
| `0x00` | NoAuth | No signature. Spend path depends only on `witnessScript` |
|
|
202
|
+
| `0x01` | PQ | ML-DSA-44 post-quantum signature |
|
|
203
|
+
| `0x02` | Legacy | secp256k1 signature inside the AuthScript framework |
|
|
204
|
+
|
|
188
205
|
### Generate a PQ address
|
|
189
206
|
|
|
190
207
|
```javascript
|
|
@@ -207,7 +224,7 @@ Outputs
|
|
|
207
224
|
{
|
|
208
225
|
address: 'nq1...', // Bech32m AuthScript address
|
|
209
226
|
authType: 1, // 0x01 = PQ single-key auth
|
|
210
|
-
authDescriptor: '01...', // 0x01 || HASH160(pq_pubkey)
|
|
227
|
+
authDescriptor: '01...', // 0x01 || HASH160(0x05 || pq_pubkey)
|
|
211
228
|
commitment: '...', // tagged_hash("NeuraiAuthScript", ...)
|
|
212
229
|
path: "m/100'/1900'/0'/0/0", // PQ derivation path
|
|
213
230
|
publicKey: '...', // ML-DSA-44 public key (2624 hex chars = 1312 bytes)
|
|
@@ -244,7 +261,84 @@ console.log(pqAddress.witnessScript); // 5151
|
|
|
244
261
|
console.log(pqAddress.commitment); // new 32-byte commitment
|
|
245
262
|
```
|
|
246
263
|
|
|
247
|
-
`
|
|
264
|
+
`getPQAddress()` always generates `authType = 0x01` PQ addresses. Use `getNoAuthAddress()` for `0x00` and `getLegacyAuthScriptAddress()` / `getLegacyAuthScriptAddressByWIF()` for `0x02`.
|
|
265
|
+
|
|
266
|
+
### Generate a NoAuth address
|
|
267
|
+
|
|
268
|
+
```javascript
|
|
269
|
+
import NeuraiKey from "@neuraiproject/neurai-key";
|
|
270
|
+
|
|
271
|
+
const noAuth = NeuraiKey.getNoAuthAddress("xna-pq-test");
|
|
272
|
+
|
|
273
|
+
console.log(noAuth);
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
Outputs
|
|
277
|
+
|
|
278
|
+
```javascript
|
|
279
|
+
{
|
|
280
|
+
address: "tnq1...",
|
|
281
|
+
authType: 0,
|
|
282
|
+
commitment: "...",
|
|
283
|
+
witnessScript: "51"
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
You can provide a custom `witnessScript`:
|
|
288
|
+
|
|
289
|
+
```javascript
|
|
290
|
+
const noAuth = NeuraiKey.getNoAuthAddress("xna-pq-test", {
|
|
291
|
+
witnessScript: "527551"
|
|
292
|
+
});
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### Generate a Legacy AuthScript address from mnemonic
|
|
296
|
+
|
|
297
|
+
This derives a normal secp256k1 key using the selected legacy/current HD network, then wraps it as an AuthScript address using the PQ Bech32m network.
|
|
298
|
+
|
|
299
|
+
```javascript
|
|
300
|
+
import NeuraiKey from "@neuraiproject/neurai-key";
|
|
301
|
+
|
|
302
|
+
const mnemonic = "result pact model attract result puzzle final boss private educate luggage era";
|
|
303
|
+
|
|
304
|
+
const legacyAuth = NeuraiKey.getLegacyAuthScriptAddress(
|
|
305
|
+
"xna-pq-test",
|
|
306
|
+
"xna-test",
|
|
307
|
+
mnemonic,
|
|
308
|
+
0,
|
|
309
|
+
0
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
console.log(legacyAuth);
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
Outputs
|
|
316
|
+
|
|
317
|
+
```javascript
|
|
318
|
+
{
|
|
319
|
+
address: "tnq1...",
|
|
320
|
+
path: "m/44'/1'/0'/0/0",
|
|
321
|
+
publicKey: "...", // compressed secp256k1 pubkey
|
|
322
|
+
privateKey: "...",
|
|
323
|
+
WIF: "...",
|
|
324
|
+
authType: 2,
|
|
325
|
+
authDescriptor: "02...",
|
|
326
|
+
commitment: "...",
|
|
327
|
+
witnessScript: "51"
|
|
328
|
+
}
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
### Generate a Legacy AuthScript address from WIF
|
|
332
|
+
|
|
333
|
+
```javascript
|
|
334
|
+
import NeuraiKey from "@neuraiproject/neurai-key";
|
|
335
|
+
|
|
336
|
+
const wif = "cVP9mzcDqMzWDhekiKMWKqEy739Cp6rKDT4tbG4wXXVfopMfTiBW";
|
|
337
|
+
const legacyAuth = NeuraiKey.getLegacyAuthScriptAddressByWIF("xna-pq-test", wif);
|
|
338
|
+
|
|
339
|
+
console.log(legacyAuth.address);
|
|
340
|
+
console.log(legacyAuth.publicKey);
|
|
341
|
+
```
|
|
248
342
|
|
|
249
343
|
### Advanced: derive by path with HD key reuse
|
|
250
344
|
|
|
@@ -265,7 +359,7 @@ const addr1 = NeuraiKey.getPQAddressByPath("xna-pq", hdKey, "m/100'/1900'/0'/0/1
|
|
|
265
359
|
| Public key size | 1312 bytes |
|
|
266
360
|
| Derivation path (mainnet) | `m/100'/1900'/0'/0/index` |
|
|
267
361
|
| Derivation path (testnet default/external) | `m/100'/1'/account'/0/index` |
|
|
268
|
-
| Auth descriptor | `0x01 \|\| HASH160(pq_pubkey)` |
|
|
362
|
+
| Auth descriptor | `0x01 \|\| HASH160(0x05 \|\| pq_pubkey)` |
|
|
269
363
|
| Commitment | `tagged_hash("NeuraiAuthScript", 0x01 \|\| auth_descriptor \|\| SHA256(witnessScript))` |
|
|
270
364
|
| Default witnessScript | `OP_TRUE` (`51` in hex) |
|
|
271
365
|
|
|
@@ -318,7 +412,7 @@ const NeuraiKey = require("@neuraiproject/neurai-key");
|
|
|
318
412
|
</html>
|
|
319
413
|
```
|
|
320
414
|
|
|
321
|
-
## Package layout in `3.
|
|
415
|
+
## Package layout in `3.1.0`
|
|
322
416
|
|
|
323
417
|
- `dist/index.js`: ESM main entry
|
|
324
418
|
- `dist/index.cjs`: CommonJS entry
|
|
@@ -338,7 +432,7 @@ const NeuraiKey = require("@neuraiproject/neurai-key");
|
|
|
338
432
|
|
|
339
433
|
`npm test`
|
|
340
434
|
|
|
341
|
-
The test script already builds the package before running
|
|
435
|
+
The test script already builds the package before running Vitest.
|
|
342
436
|
|
|
343
437
|
## BIP32
|
|
344
438
|
|
package/dist/NeuraiKey.global.js
CHANGED
|
@@ -23716,7 +23716,10 @@ zurdo`.split('\n');
|
|
|
23716
23716
|
|
|
23717
23717
|
const AUTHSCRIPT_TAG = "NeuraiAuthScript";
|
|
23718
23718
|
const AUTHSCRIPT_VERSION = 0x01;
|
|
23719
|
+
const NOAUTH_TYPE = 0x00;
|
|
23719
23720
|
const PQ_AUTH_TYPE = 0x01;
|
|
23721
|
+
const LEGACY_AUTH_TYPE = 0x02;
|
|
23722
|
+
const PQ_PUBLIC_KEY_HEADER = Uint8Array.from([0x05]);
|
|
23720
23723
|
const DEFAULT_WITNESS_SCRIPT = Uint8Array.from([0x51]);
|
|
23721
23724
|
function encodeWIF(privateKey, version, compressed = true) {
|
|
23722
23725
|
const payload = compressed
|
|
@@ -23777,27 +23780,51 @@ zurdo`.split('\n');
|
|
|
23777
23780
|
function normalizeWitnessScript(input) {
|
|
23778
23781
|
return input ? ensureBytes(input) : Uint8Array.from(DEFAULT_WITNESS_SCRIPT);
|
|
23779
23782
|
}
|
|
23783
|
+
function buildAuthDescriptor(authType, publicKey) {
|
|
23784
|
+
if (authType === NOAUTH_TYPE) {
|
|
23785
|
+
return Uint8Array.from([NOAUTH_TYPE]);
|
|
23786
|
+
}
|
|
23787
|
+
if (!publicKey) {
|
|
23788
|
+
throw new Error(`Auth type 0x${authType.toString(16).padStart(2, "0")} requires a public key`);
|
|
23789
|
+
}
|
|
23790
|
+
if (authType === PQ_AUTH_TYPE) {
|
|
23791
|
+
return concatBytes(Uint8Array.from([PQ_AUTH_TYPE]), hash160(concatBytes(PQ_PUBLIC_KEY_HEADER, publicKey)));
|
|
23792
|
+
}
|
|
23793
|
+
if (authType === LEGACY_AUTH_TYPE) {
|
|
23794
|
+
return concatBytes(Uint8Array.from([LEGACY_AUTH_TYPE]), hash160(publicKey));
|
|
23795
|
+
}
|
|
23796
|
+
throw new Error(`Unsupported authType: 0x${String(authType).padStart(2, "0")}`);
|
|
23797
|
+
}
|
|
23780
23798
|
function pqPublicKeyToAuthDescriptor(publicKey) {
|
|
23781
|
-
return
|
|
23799
|
+
return buildAuthDescriptor(PQ_AUTH_TYPE, publicKey);
|
|
23782
23800
|
}
|
|
23783
23801
|
function pqPublicKeyToCommitment(publicKey, options = {}) {
|
|
23784
23802
|
return pqPublicKeyToCommitmentParts(publicKey, options).commitment;
|
|
23785
23803
|
}
|
|
23786
|
-
function
|
|
23804
|
+
function authScriptCommitmentParts(authType, publicKey, options = {}) {
|
|
23787
23805
|
const witnessScript = normalizeWitnessScript(options.witnessScript);
|
|
23788
|
-
const authDescriptor =
|
|
23806
|
+
const authDescriptor = buildAuthDescriptor(authType, publicKey);
|
|
23789
23807
|
const witnessScriptHash = sha256Hash(witnessScript);
|
|
23790
23808
|
const commitment = taggedHash(AUTHSCRIPT_TAG, concatBytes(Uint8Array.from([AUTHSCRIPT_VERSION]), authDescriptor, witnessScriptHash));
|
|
23791
23809
|
return {
|
|
23792
23810
|
authDescriptor,
|
|
23793
|
-
authType
|
|
23811
|
+
authType,
|
|
23794
23812
|
commitment,
|
|
23795
23813
|
witnessScript,
|
|
23796
23814
|
};
|
|
23797
23815
|
}
|
|
23816
|
+
function pqPublicKeyToCommitmentParts(publicKey, options = {}) {
|
|
23817
|
+
return authScriptCommitmentParts(PQ_AUTH_TYPE, publicKey, options);
|
|
23818
|
+
}
|
|
23798
23819
|
function pqPublicKeyToAddressBytes(publicKey, network, options = {}) {
|
|
23799
23820
|
return bech32mEncode(network.hrp, network.witnessVersion, pqPublicKeyToCommitment(publicKey, options));
|
|
23800
23821
|
}
|
|
23822
|
+
function noAuthToAddressBytes(network, options = {}) {
|
|
23823
|
+
return bech32mEncode(network.hrp, network.witnessVersion, authScriptCommitmentParts(NOAUTH_TYPE, null, options).commitment);
|
|
23824
|
+
}
|
|
23825
|
+
function legacyAuthScriptToAddressBytes(publicKey, network, options = {}) {
|
|
23826
|
+
return bech32mEncode(network.hrp, network.witnessVersion, authScriptCommitmentParts(LEGACY_AUTH_TYPE, publicKey, options).commitment);
|
|
23827
|
+
}
|
|
23801
23828
|
function normalizePublicKey(input) {
|
|
23802
23829
|
return ensureBytes(input);
|
|
23803
23830
|
}
|
|
@@ -24067,7 +24094,7 @@ zurdo`.split('\n');
|
|
|
24067
24094
|
const authScript = pqPublicKeyToCommitmentParts(publicKey, options);
|
|
24068
24095
|
return {
|
|
24069
24096
|
address: pqPublicKeyToAddressBytes(publicKey, chain, options),
|
|
24070
|
-
authType:
|
|
24097
|
+
authType: 0x01,
|
|
24071
24098
|
authDescriptor: bytesToHex(authScript.authDescriptor),
|
|
24072
24099
|
commitment: bytesToHex(authScript.commitment),
|
|
24073
24100
|
path,
|
|
@@ -24077,6 +24104,57 @@ zurdo`.split('\n');
|
|
|
24077
24104
|
witnessScript: bytesToHex(authScript.witnessScript),
|
|
24078
24105
|
};
|
|
24079
24106
|
}
|
|
24107
|
+
function getNoAuthAddress(network, options = {}) {
|
|
24108
|
+
const chain = getPQNetwork(network);
|
|
24109
|
+
const parts = authScriptCommitmentParts(0x00, null, options);
|
|
24110
|
+
return {
|
|
24111
|
+
address: noAuthToAddressBytes(chain, options),
|
|
24112
|
+
authType: 0x00,
|
|
24113
|
+
commitment: bytesToHex(parts.commitment),
|
|
24114
|
+
witnessScript: bytesToHex(parts.witnessScript),
|
|
24115
|
+
};
|
|
24116
|
+
}
|
|
24117
|
+
function getLegacyAuthScriptAddress(network, legacyNetwork, mnemonic, account, index, passphrase = "", options = {}) {
|
|
24118
|
+
const pqChain = getPQNetwork(network);
|
|
24119
|
+
const legacyChain = getNetwork(legacyNetwork);
|
|
24120
|
+
const coinType = legacyChain.bip44;
|
|
24121
|
+
const hdKey = getHDKey(legacyNetwork, mnemonic, passphrase);
|
|
24122
|
+
const path = `m/44'/${coinType}'/${account}'/0/${index}`;
|
|
24123
|
+
const derived = hdKey.derive(path);
|
|
24124
|
+
if (!derived.privateKey) {
|
|
24125
|
+
throw new Error("Could not derive private key for path");
|
|
24126
|
+
}
|
|
24127
|
+
const legacyObject = privateKeyToAddressObject(derived.privateKey, legacyChain, path);
|
|
24128
|
+
const publicKeyBytes = ensureBytes(legacyObject.publicKey);
|
|
24129
|
+
const parts = authScriptCommitmentParts(0x02, publicKeyBytes, options);
|
|
24130
|
+
return {
|
|
24131
|
+
address: legacyAuthScriptToAddressBytes(publicKeyBytes, pqChain, options),
|
|
24132
|
+
path,
|
|
24133
|
+
publicKey: legacyObject.publicKey,
|
|
24134
|
+
privateKey: legacyObject.privateKey,
|
|
24135
|
+
WIF: legacyObject.WIF,
|
|
24136
|
+
authType: 0x02,
|
|
24137
|
+
authDescriptor: bytesToHex(parts.authDescriptor),
|
|
24138
|
+
commitment: bytesToHex(parts.commitment),
|
|
24139
|
+
witnessScript: bytesToHex(parts.witnessScript),
|
|
24140
|
+
};
|
|
24141
|
+
}
|
|
24142
|
+
function getLegacyAuthScriptAddressByWIF(network, wif, options = {}) {
|
|
24143
|
+
const pqChain = getPQNetwork(network);
|
|
24144
|
+
const publicKeyHex = publicKeyHexFromWIF(wif);
|
|
24145
|
+
const publicKeyBytes = ensureBytes(publicKeyHex);
|
|
24146
|
+
const parts = authScriptCommitmentParts(0x02, publicKeyBytes, options);
|
|
24147
|
+
return {
|
|
24148
|
+
address: legacyAuthScriptToAddressBytes(publicKeyBytes, pqChain, options),
|
|
24149
|
+
publicKey: publicKeyHex,
|
|
24150
|
+
privateKey: "",
|
|
24151
|
+
WIF: wif,
|
|
24152
|
+
authType: 0x02,
|
|
24153
|
+
authDescriptor: bytesToHex(parts.authDescriptor),
|
|
24154
|
+
commitment: bytesToHex(parts.commitment),
|
|
24155
|
+
witnessScript: bytesToHex(parts.witnessScript),
|
|
24156
|
+
};
|
|
24157
|
+
}
|
|
24080
24158
|
function getPQAddress(network, mnemonic, account, index, passphrase = "", options = {}) {
|
|
24081
24159
|
const chain = getPQNetwork(network);
|
|
24082
24160
|
const hdKey = getPQHDKey(network, mnemonic, passphrase);
|
|
@@ -24129,6 +24207,9 @@ zurdo`.split('\n');
|
|
|
24129
24207
|
getPQAddress,
|
|
24130
24208
|
getPQAddressByPath,
|
|
24131
24209
|
getPQHDKey,
|
|
24210
|
+
getNoAuthAddress,
|
|
24211
|
+
getLegacyAuthScriptAddress,
|
|
24212
|
+
getLegacyAuthScriptAddressByWIF,
|
|
24132
24213
|
pqPublicKeyToAddress,
|
|
24133
24214
|
pqPublicKeyToAuthDescriptorHex,
|
|
24134
24215
|
pqPublicKeyToCommitmentHex,
|