@totemsdk/core 1.0.11 → 1.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/dist/index.d.ts CHANGED
@@ -10,8 +10,8 @@ export type { WotsIndices } from './tx/index.js';
10
10
  export * from './utils.js';
11
11
  export { F, hex, fromHex, u16be, u32be, assert32, h, prfChainSeed, toWinternitzDigits, baseWWithChecksum, derivePKdigest, wotsKeypairFromSeed, wotsSign, wotsSignLegacy, wotsPkFromSig, wotsVerify, wotsVerifyDigest, wotsPublicKeyFromSeed, type WotsKeypair, type WotsSignature, } from './wots.js';
12
12
  export * from './params.js';
13
- export { serializeMiniNumber, serializeMiniData, hashAllObjects, deriveChainSeedJava, deriveChildTreeSeedJava, hashObject, serializeMiniNumberZERO, serializeMiniNumberONE, writeHashToStream, javaHashAllObjects, indexToMiniDataBytes, derivePerAddressSeed, createMMREntryNumber, serializeMMREntryNumber, serializeMMRData, serializeMMREntry, precomputeTransactionCoinID, type MMREntryNumber as JavaMMREntryNumber, type MMRData as JavaMMRData, type MMREntry as JavaMMREntry, } from './javaStreamables.js';
14
- export { TreeKey, type KeyGenProgress, type ProgressCallback, TreeKeyNode, verifyTreeSignature, serializeTreeSignature, deserializeTreeSignature, getRootPublicKey, DEFAULT_KEYS_PER_LEVEL, DEFAULT_LEVELS, type SignatureProof, type TreeSignature, createPerAddressTreeKey, createPerAddressTreeKeyAsync, deriveAddressPublicKey, getPerAddressPublicKey, } from './treekey.js';
13
+ export { serializeMiniNumber, serializeMiniData, hashAllObjects, deriveChainSeedJava, deriveChildTreeSeedJava, hashObject, serializeMiniNumberZERO, serializeMiniNumberONE, writeHashToStream, javaHashAllObjects, indexToMiniDataBytes, derivePerAddressSeed, deriveRootPrivSeed, deriveUnifiedChildSeed, createMMREntryNumber, serializeMMREntryNumber, serializeMMRData, serializeMMREntry, precomputeTransactionCoinID, type MMREntryNumber as JavaMMREntryNumber, type MMRData as JavaMMRData, type MMREntry as JavaMMREntry, } from './javaStreamables.js';
14
+ export { TreeKey, type KeyGenProgress, type ProgressCallback, TreeKeyNode, verifyTreeSignature, serializeTreeSignature, deserializeTreeSignature, getRootPublicKey, DEFAULT_KEYS_PER_LEVEL, DEFAULT_LEVELS, type SignatureProof, type TreeSignature, createUnifiedChildTreeKey, createUnifiedChildTreeKeyAsync, createUnifiedRootTreeKey, deriveUnifiedAddressPublicKey, createPerAddressTreeKey, createPerAddressTreeKeyAsync, } from './treekey.js';
15
15
  export { scriptFromWotsPk, wotsAddressFromKeypair } from './script.js';
16
16
  export * from './minima32.js';
17
17
  export * from './mmr.js';
package/dist/index.js CHANGED
@@ -18,8 +18,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
18
18
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
19
19
  };
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.serializeTreeSignature = exports.verifyTreeSignature = exports.TreeKeyNode = exports.TreeKey = exports.precomputeTransactionCoinID = exports.serializeMMREntry = exports.serializeMMRData = exports.serializeMMREntryNumber = exports.createMMREntryNumber = exports.derivePerAddressSeed = exports.indexToMiniDataBytes = exports.javaHashAllObjects = exports.writeHashToStream = exports.serializeMiniNumberONE = exports.serializeMiniNumberZERO = exports.hashObject = exports.deriveChildTreeSeedJava = exports.deriveChainSeedJava = exports.hashAllObjects = exports.serializeMiniData = exports.serializeMiniNumber = exports.wotsPublicKeyFromSeed = exports.wotsVerifyDigest = exports.wotsVerify = exports.wotsPkFromSig = exports.wotsSignLegacy = exports.wotsSign = exports.wotsKeypairFromSeed = exports.derivePKdigest = exports.baseWWithChecksum = exports.toWinternitzDigits = exports.prfChainSeed = exports.h = exports.assert32 = exports.u32be = exports.u16be = exports.fromHex = exports.hex = exports.F = exports.TransactionReceiptStore = exports.WatermarkExhaustedError = exports.TransactionLifecycleError = exports.TransactionLifecycle = exports.TransactionService = exports.flatIndexFromLanes = exports.finalizeLease = exports.prepareLease = exports.LeaseMonitor = exports.WatermarkStore = exports.LeaseStore = void 0;
22
- exports.writeMiniString = exports.bigIntToByteArray = exports.bytesToHex = exports.hexToBytes = exports.concat = exports.writeMMREntryNumber = exports.writeMiniByte = exports.writeMiniData = exports.writeMiniNumber = exports.MINIMA_CONSTANTS = exports.validateChallenge = exports.createChallenge = exports.normalizeHex = exports.deriveAddressFromPublicKey = exports.verifyTreeSignatureDetailed = exports.verifySignatureDetailed = exports.verifySignature = exports.buildMinimaCoin = exports.createDefaultTransaction = exports.precomputeTransactionCoinIDTx = exports.computeTransactionDigest = exports.serializeTransaction = exports.serializeCoin = exports.parseDecimalToMiniNumber = exports.generateSeedPhrase = exports.generateWordList = exports.phraseToSeed = exports.convertWordListToSeed = exports.convertStringToSeed = exports.validatePhrase = exports.cleanSeedPhrase = exports.WORD_LIST = exports.addressToRoot = exports.scriptToAddress = exports.wotsAddressFromKeypair = exports.scriptFromWotsPk = exports.getPerAddressPublicKey = exports.deriveAddressPublicKey = exports.createPerAddressTreeKeyAsync = exports.createPerAddressTreeKey = exports.DEFAULT_LEVELS = exports.DEFAULT_KEYS_PER_LEVEL = exports.getRootPublicKey = exports.deserializeTreeSignature = void 0;
21
+ exports.TreeKeyNode = exports.TreeKey = exports.precomputeTransactionCoinID = exports.serializeMMREntry = exports.serializeMMRData = exports.serializeMMREntryNumber = exports.createMMREntryNumber = exports.deriveUnifiedChildSeed = exports.deriveRootPrivSeed = exports.derivePerAddressSeed = exports.indexToMiniDataBytes = exports.javaHashAllObjects = exports.writeHashToStream = exports.serializeMiniNumberONE = exports.serializeMiniNumberZERO = exports.hashObject = exports.deriveChildTreeSeedJava = exports.deriveChainSeedJava = exports.hashAllObjects = exports.serializeMiniData = exports.serializeMiniNumber = exports.wotsPublicKeyFromSeed = exports.wotsVerifyDigest = exports.wotsVerify = exports.wotsPkFromSig = exports.wotsSignLegacy = exports.wotsSign = exports.wotsKeypairFromSeed = exports.derivePKdigest = exports.baseWWithChecksum = exports.toWinternitzDigits = exports.prfChainSeed = exports.h = exports.assert32 = exports.u32be = exports.u16be = exports.fromHex = exports.hex = exports.F = exports.TransactionReceiptStore = exports.WatermarkExhaustedError = exports.TransactionLifecycleError = exports.TransactionLifecycle = exports.TransactionService = exports.flatIndexFromLanes = exports.finalizeLease = exports.prepareLease = exports.LeaseMonitor = exports.WatermarkStore = exports.LeaseStore = void 0;
22
+ exports.writeMiniString = exports.bigIntToByteArray = exports.bytesToHex = exports.hexToBytes = exports.concat = exports.writeMMREntryNumber = exports.writeMiniByte = exports.writeMiniData = exports.writeMiniNumber = exports.MINIMA_CONSTANTS = exports.validateChallenge = exports.createChallenge = exports.normalizeHex = exports.deriveAddressFromPublicKey = exports.verifyTreeSignatureDetailed = exports.verifySignatureDetailed = exports.verifySignature = exports.buildMinimaCoin = exports.createDefaultTransaction = exports.precomputeTransactionCoinIDTx = exports.computeTransactionDigest = exports.serializeTransaction = exports.serializeCoin = exports.parseDecimalToMiniNumber = exports.generateSeedPhrase = exports.generateWordList = exports.phraseToSeed = exports.convertWordListToSeed = exports.convertStringToSeed = exports.validatePhrase = exports.cleanSeedPhrase = exports.WORD_LIST = exports.addressToRoot = exports.scriptToAddress = exports.wotsAddressFromKeypair = exports.scriptFromWotsPk = exports.createPerAddressTreeKeyAsync = exports.createPerAddressTreeKey = exports.deriveUnifiedAddressPublicKey = exports.createUnifiedRootTreeKey = exports.createUnifiedChildTreeKeyAsync = exports.createUnifiedChildTreeKey = exports.DEFAULT_LEVELS = exports.DEFAULT_KEYS_PER_LEVEL = exports.getRootPublicKey = exports.deserializeTreeSignature = exports.serializeTreeSignature = exports.verifyTreeSignature = void 0;
23
23
  // Version information for bundle duplication detection
24
24
  __exportStar(require("./version.js"), exports);
25
25
  // Platform-agnostic Adapters (SDK Upgrade)
@@ -75,9 +75,12 @@ Object.defineProperty(exports, "serializeMiniNumberZERO", { enumerable: true, ge
75
75
  Object.defineProperty(exports, "serializeMiniNumberONE", { enumerable: true, get: function () { return javaStreamables_js_1.serializeMiniNumberONE; } });
76
76
  Object.defineProperty(exports, "writeHashToStream", { enumerable: true, get: function () { return javaStreamables_js_1.writeHashToStream; } });
77
77
  Object.defineProperty(exports, "javaHashAllObjects", { enumerable: true, get: function () { return javaStreamables_js_1.javaHashAllObjects; } });
78
- // Per-address key derivation (Minima Wallet.java compatible) - 2026-02
78
+ // Per-address key derivation (Minima Wallet.java compatible) - kept for migration detection
79
79
  Object.defineProperty(exports, "indexToMiniDataBytes", { enumerable: true, get: function () { return javaStreamables_js_1.indexToMiniDataBytes; } });
80
80
  Object.defineProperty(exports, "derivePerAddressSeed", { enumerable: true, get: function () { return javaStreamables_js_1.derivePerAddressSeed; } });
81
+ // Unified hierarchical key derivation (2026-06)
82
+ Object.defineProperty(exports, "deriveRootPrivSeed", { enumerable: true, get: function () { return javaStreamables_js_1.deriveRootPrivSeed; } });
83
+ Object.defineProperty(exports, "deriveUnifiedChildSeed", { enumerable: true, get: function () { return javaStreamables_js_1.deriveUnifiedChildSeed; } });
81
84
  // MMREntryNumber and MMREntry serialization (2026-01-18)
82
85
  Object.defineProperty(exports, "createMMREntryNumber", { enumerable: true, get: function () { return javaStreamables_js_1.createMMREntryNumber; } });
83
86
  Object.defineProperty(exports, "serializeMMREntryNumber", { enumerable: true, get: function () { return javaStreamables_js_1.serializeMMREntryNumber; } });
@@ -94,11 +97,14 @@ Object.defineProperty(exports, "deserializeTreeSignature", { enumerable: true, g
94
97
  Object.defineProperty(exports, "getRootPublicKey", { enumerable: true, get: function () { return treekey_js_1.getRootPublicKey; } });
95
98
  Object.defineProperty(exports, "DEFAULT_KEYS_PER_LEVEL", { enumerable: true, get: function () { return treekey_js_1.DEFAULT_KEYS_PER_LEVEL; } });
96
99
  Object.defineProperty(exports, "DEFAULT_LEVELS", { enumerable: true, get: function () { return treekey_js_1.DEFAULT_LEVELS; } });
97
- // Per-address TreeKey helpers (Minima Wallet.java compatible) - 2026-02
100
+ // Unified hierarchical TreeKey factories (2026-06)
101
+ Object.defineProperty(exports, "createUnifiedChildTreeKey", { enumerable: true, get: function () { return treekey_js_1.createUnifiedChildTreeKey; } });
102
+ Object.defineProperty(exports, "createUnifiedChildTreeKeyAsync", { enumerable: true, get: function () { return treekey_js_1.createUnifiedChildTreeKeyAsync; } });
103
+ Object.defineProperty(exports, "createUnifiedRootTreeKey", { enumerable: true, get: function () { return treekey_js_1.createUnifiedRootTreeKey; } });
104
+ Object.defineProperty(exports, "deriveUnifiedAddressPublicKey", { enumerable: true, get: function () { return treekey_js_1.deriveUnifiedAddressPublicKey; } });
105
+ // @deprecated — migrate to createUnifiedChildTreeKey
98
106
  Object.defineProperty(exports, "createPerAddressTreeKey", { enumerable: true, get: function () { return treekey_js_1.createPerAddressTreeKey; } });
99
107
  Object.defineProperty(exports, "createPerAddressTreeKeyAsync", { enumerable: true, get: function () { return treekey_js_1.createPerAddressTreeKeyAsync; } });
100
- Object.defineProperty(exports, "deriveAddressPublicKey", { enumerable: true, get: function () { return treekey_js_1.deriveAddressPublicKey; } });
101
- Object.defineProperty(exports, "getPerAddressPublicKey", { enumerable: true, get: function () { return treekey_js_1.getPerAddressPublicKey; } });
102
108
  // Script helpers (for address derivation)
103
109
  var script_js_1 = require("./script.js");
104
110
  Object.defineProperty(exports, "scriptFromWotsPk", { enumerable: true, get: function () { return script_js_1.scriptFromWotsPk; } });
@@ -210,6 +210,27 @@ export interface MMREntry {
210
210
  * @returns Serialized bytes: MiniNumber(row) + MMREntryNumber + MMRData
211
211
  */
212
212
  export declare function serializeMMREntry(entry: MMREntry): Uint8Array;
213
+ /**
214
+ * Derive the unified root private seed from a base wallet seed.
215
+ *
216
+ * Architecture:
217
+ * root_priv_seed = SHA3-256( serializeMiniData(baseSeed) ‖ serializeMiniData("ROOT_IDENTITY" bytes) )
218
+ *
219
+ * @param baseSeed - 32-byte wallet base seed (from mnemonic)
220
+ * @returns 32-byte root private seed
221
+ */
222
+ export declare function deriveRootPrivSeed(baseSeed: Uint8Array): Uint8Array;
223
+ /**
224
+ * Derive a unified child seed for the address at `index`.
225
+ *
226
+ * Architecture:
227
+ * child_seed_i = SHA3-256( serializeMiniData(root_priv_seed) ‖ serializeMiniData(indexBytes(i)) )
228
+ *
229
+ * @param baseSeed - 32-byte wallet base seed (from mnemonic)
230
+ * @param index - Address index (0-63)
231
+ * @returns 32-byte child seed for the TreeKey at this address
232
+ */
233
+ export declare function deriveUnifiedChildSeed(baseSeed: Uint8Array, index: number): Uint8Array;
213
234
  /**
214
235
  * Precompute output coin IDs before computing the transaction digest.
215
236
  *
@@ -30,6 +30,8 @@ exports.createMMREntryNumber = createMMREntryNumber;
30
30
  exports.serializeMMREntryNumber = serializeMMREntryNumber;
31
31
  exports.serializeMMRData = serializeMMRData;
32
32
  exports.serializeMMREntry = serializeMMREntry;
33
+ exports.deriveRootPrivSeed = deriveRootPrivSeed;
34
+ exports.deriveUnifiedChildSeed = deriveUnifiedChildSeed;
33
35
  exports.precomputeTransactionCoinID = precomputeTransactionCoinID;
34
36
  const sha3_js_1 = require("@noble/hashes/sha3.js");
35
37
  const Streamable_js_1 = require("./Streamable.js");
@@ -316,6 +318,44 @@ function serializeMMREntry(entry) {
316
318
  result.set(mmrDataSerialized, offset);
317
319
  return result;
318
320
  }
321
+ /**
322
+ * Derive the unified root private seed from a base wallet seed.
323
+ *
324
+ * Architecture:
325
+ * root_priv_seed = SHA3-256( serializeMiniData(baseSeed) ‖ serializeMiniData("ROOT_IDENTITY" bytes) )
326
+ *
327
+ * @param baseSeed - 32-byte wallet base seed (from mnemonic)
328
+ * @returns 32-byte root private seed
329
+ */
330
+ function deriveRootPrivSeed(baseSeed) {
331
+ const baseSeedSerialized = serializeMiniData(baseSeed);
332
+ const rootIdentityBytes = new TextEncoder().encode('ROOT_IDENTITY');
333
+ const rootIdentitySerialized = serializeMiniData(rootIdentityBytes);
334
+ const combined = new Uint8Array(baseSeedSerialized.length + rootIdentitySerialized.length);
335
+ combined.set(baseSeedSerialized, 0);
336
+ combined.set(rootIdentitySerialized, baseSeedSerialized.length);
337
+ return (0, sha3_js_1.sha3_256)(combined);
338
+ }
339
+ /**
340
+ * Derive a unified child seed for the address at `index`.
341
+ *
342
+ * Architecture:
343
+ * child_seed_i = SHA3-256( serializeMiniData(root_priv_seed) ‖ serializeMiniData(indexBytes(i)) )
344
+ *
345
+ * @param baseSeed - 32-byte wallet base seed (from mnemonic)
346
+ * @param index - Address index (0-63)
347
+ * @returns 32-byte child seed for the TreeKey at this address
348
+ */
349
+ function deriveUnifiedChildSeed(baseSeed, index) {
350
+ const rootPrivSeed = deriveRootPrivSeed(baseSeed);
351
+ const modifierBytes = indexToMiniDataBytes(index);
352
+ const rootSeedSerialized = serializeMiniData(rootPrivSeed);
353
+ const modifierSerialized = serializeMiniData(modifierBytes);
354
+ const combined = new Uint8Array(rootSeedSerialized.length + modifierSerialized.length);
355
+ combined.set(rootSeedSerialized, 0);
356
+ combined.set(modifierSerialized, rootSeedSerialized.length);
357
+ return (0, sha3_js_1.sha3_256)(combined);
358
+ }
319
359
  /**
320
360
  * Precompute output coin IDs before computing the transaction digest.
321
361
  *
package/dist/treekey.d.ts CHANGED
@@ -326,58 +326,74 @@ export declare function serializeTreeSignature(sig: TreeSignature): Bytes;
326
326
  export declare function deserializeTreeSignature(data: Bytes): TreeSignature;
327
327
  /**
328
328
  * ============================================================================
329
- * PER-ADDRESS TREEKEY FACTORY
329
+ * UNIFIED TREEKEY FACTORY
330
330
  * ============================================================================
331
331
  *
332
- * Minima Wallet.createNewKey() creates independent TreeKeys per address:
333
- * MiniData modifier = new MiniData(new BigInteger(Integer.toString(numkeys)));
334
- * MiniData privseed = Crypto.getInstance().hashObjects(baseSeed, modifier);
335
- * TreeKey treekey = TreeKey.createDefault(privseed);
332
+ * Single hierarchical derivation scheme:
336
333
  *
337
- * Each address gets its own TreeKey with:
338
- * - Unique seed derived from baseSeed + addressIndex
339
- * - Size=64, depth=3 (matching TreeKey.createDefault)
340
- * - 4096 one-time signatures per address (64×64)
334
+ * root_priv_seed = deriveRootPrivSeed(baseSeed)
335
+ * child_seed_i = deriveUnifiedChildSeed(baseSeed, i)
336
+ * child_treekey_i = new TreeKey(child_seed_i, 64, 3) ← spend address i
337
+ * root_treekey = new TreeKey(root_priv_seed, 64, 3) ← identity anchor
341
338
  *
342
- * Total wallet capacity: 64 addresses × 4096 signatures = 262,144 signatures
339
+ * Child seeds are cryptographically descended from root_priv_seed, not siblings.
340
+ * Addresses are Minima-compatible (RETURN SIGNEDBY(pubkey) scripts, WOTS sigs).
341
+ * The root TreeKey is NEVER used as a spend address.
342
+ *
343
+ * Signature capacity: 64 addresses × 4 096 signatures each = 262 144 total.
344
+ * Root identity capacity: 4 096 attestation signatures.
343
345
  * ============================================================================
344
346
  */
345
347
  /**
346
- * Create a per-address TreeKey matching Minima Wallet.createNewKey()
348
+ * Create the unified child TreeKey for spend address at `index`.
349
+ *
350
+ * Derivation: child_seed_i = deriveUnifiedChildSeed(baseSeed, i)
351
+ * treeKey = new TreeKey(child_seed_i, 64, 3)
347
352
  *
348
353
  * @param baseSeed - 32-byte wallet base seed (from mnemonic)
349
- * @param addressIndex - Address index (0-63)
350
- * @returns TreeKey for this address with size=64, depth=3
354
+ * @param index - Address index (0-63)
355
+ * @returns TreeKey for this spend address with size=64, depth=3
351
356
  */
352
- export declare function createPerAddressTreeKey(baseSeed: Bytes, addressIndex: number): TreeKey;
357
+ export declare function createUnifiedChildTreeKey(baseSeed: Bytes, index: number): TreeKey;
353
358
  /**
354
- * Async version with progress reporting for UI
359
+ * Async version with progress reporting for UI.
355
360
  *
356
361
  * @param baseSeed - 32-byte wallet base seed
357
- * @param addressIndex - Address index (0-63)
362
+ * @param index - Address index (0-63)
358
363
  * @param onProgress - Optional progress callback
359
- * @returns Promise resolving to TreeKey for this address
364
+ * @returns Promise resolving to the child TreeKey
360
365
  */
361
- export declare function createPerAddressTreeKeyAsync(baseSeed: Bytes, addressIndex: number, onProgress?: ProgressCallback): Promise<TreeKey>;
366
+ export declare function createUnifiedChildTreeKeyAsync(baseSeed: Bytes, index: number, onProgress?: ProgressCallback): Promise<TreeKey>;
362
367
  /**
363
- * Derive address public key from base seed and address index
368
+ * Create the unified root identity TreeKey (identity anchor, never a spend address).
364
369
  *
365
- * This is the fast path for getting an address public key without
366
- * needing to construct the full TreeKey. Useful for address derivation
367
- * during wallet initialization.
370
+ * Derivation: root_priv_seed = deriveRootPrivSeed(baseSeed)
371
+ * treeKey = new TreeKey(root_priv_seed, 64, 3)
368
372
  *
369
- * @param baseSeed - 32-byte wallet base seed
370
- * @param addressIndex - Address index (0-63)
371
- * @returns 32-byte address public key (MMR root of per-address TreeKey)
373
+ * @param baseSeed - 32-byte wallet base seed (from mnemonic)
374
+ * @returns Root identity TreeKey with size=64, depth=3
372
375
  */
373
- export declare function deriveAddressPublicKey(baseSeed: Bytes, addressIndex: number): Bytes;
376
+ export declare function createUnifiedRootTreeKey(baseSeed: Bytes): TreeKey;
374
377
  /**
375
- * Get the address public key from a per-address TreeKey
376
- *
377
- * In the per-address architecture, each address has its own TreeKey,
378
- * and the address public key is simply the TreeKey's root public key.
378
+ * Fast path for deriving a child address public key without constructing
379
+ * the full TreeKey. Useful during wallet initialisation.
379
380
  *
380
- * @param treeKey - Per-address TreeKey
381
- * @returns 32-byte address public key (TreeKey root)
381
+ * @param baseSeed - 32-byte wallet base seed
382
+ * @param index - Address index (0-63)
383
+ * @returns 32-byte address public key (MMR root of child TreeKey)
384
+ */
385
+ export declare function deriveUnifiedAddressPublicKey(baseSeed: Bytes, index: number): Bytes;
386
+ /**
387
+ * @deprecated Use {@link createUnifiedChildTreeKey} instead.
388
+ * This wrapper preserves the LEGACY per-address seed derivation
389
+ * (`SHA3-256(baseSeed ‖ indexBytes(i))`) so that existing callers
390
+ * that import this symbol by name continue to derive the same keys.
391
+ * New code must use createUnifiedChildTreeKey which applies the unified
392
+ * two-step derivation (root_priv_seed → child_seed_i).
382
393
  */
383
- export declare function getPerAddressPublicKey(treeKey: TreeKey): Bytes;
394
+ export declare function createPerAddressTreeKey(baseSeed: Bytes, addressIndex: number): TreeKey;
395
+ /**
396
+ * @deprecated Use {@link createUnifiedChildTreeKeyAsync} instead.
397
+ * Preserves legacy per-address seed derivation for backward compatibility.
398
+ */
399
+ export declare function createPerAddressTreeKeyAsync(baseSeed: Bytes, addressIndex: number, onProgress?: ProgressCallback): Promise<TreeKey>;
package/dist/treekey.js CHANGED
@@ -18,10 +18,12 @@ exports.getRootPublicKey = getRootPublicKey;
18
18
  exports.verifyTreeSignature = verifyTreeSignature;
19
19
  exports.serializeTreeSignature = serializeTreeSignature;
20
20
  exports.deserializeTreeSignature = deserializeTreeSignature;
21
+ exports.createUnifiedChildTreeKey = createUnifiedChildTreeKey;
22
+ exports.createUnifiedChildTreeKeyAsync = createUnifiedChildTreeKeyAsync;
23
+ exports.createUnifiedRootTreeKey = createUnifiedRootTreeKey;
24
+ exports.deriveUnifiedAddressPublicKey = deriveUnifiedAddressPublicKey;
21
25
  exports.createPerAddressTreeKey = createPerAddressTreeKey;
22
26
  exports.createPerAddressTreeKeyAsync = createPerAddressTreeKeyAsync;
23
- exports.deriveAddressPublicKey = deriveAddressPublicKey;
24
- exports.getPerAddressPublicKey = getPerAddressPublicKey;
25
27
  const javaStreamables_js_1 = require("./javaStreamables.js");
26
28
  const wots_js_1 = require("./wots.js");
27
29
  const params_js_1 = require("./params.js");
@@ -706,69 +708,95 @@ function deserializeTreeSignature(data) {
706
708
  }
707
709
  /**
708
710
  * ============================================================================
709
- * PER-ADDRESS TREEKEY FACTORY
711
+ * UNIFIED TREEKEY FACTORY
710
712
  * ============================================================================
711
713
  *
712
- * Minima Wallet.createNewKey() creates independent TreeKeys per address:
713
- * MiniData modifier = new MiniData(new BigInteger(Integer.toString(numkeys)));
714
- * MiniData privseed = Crypto.getInstance().hashObjects(baseSeed, modifier);
715
- * TreeKey treekey = TreeKey.createDefault(privseed);
714
+ * Single hierarchical derivation scheme:
716
715
  *
717
- * Each address gets its own TreeKey with:
718
- * - Unique seed derived from baseSeed + addressIndex
719
- * - Size=64, depth=3 (matching TreeKey.createDefault)
720
- * - 4096 one-time signatures per address (64×64)
716
+ * root_priv_seed = deriveRootPrivSeed(baseSeed)
717
+ * child_seed_i = deriveUnifiedChildSeed(baseSeed, i)
718
+ * child_treekey_i = new TreeKey(child_seed_i, 64, 3) ← spend address i
719
+ * root_treekey = new TreeKey(root_priv_seed, 64, 3) ← identity anchor
721
720
  *
722
- * Total wallet capacity: 64 addresses × 4096 signatures = 262,144 signatures
721
+ * Child seeds are cryptographically descended from root_priv_seed, not siblings.
722
+ * Addresses are Minima-compatible (RETURN SIGNEDBY(pubkey) scripts, WOTS sigs).
723
+ * The root TreeKey is NEVER used as a spend address.
724
+ *
725
+ * Signature capacity: 64 addresses × 4 096 signatures each = 262 144 total.
726
+ * Root identity capacity: 4 096 attestation signatures.
723
727
  * ============================================================================
724
728
  */
725
729
  /**
726
- * Create a per-address TreeKey matching Minima Wallet.createNewKey()
730
+ * Create the unified child TreeKey for spend address at `index`.
731
+ *
732
+ * Derivation: child_seed_i = deriveUnifiedChildSeed(baseSeed, i)
733
+ * treeKey = new TreeKey(child_seed_i, 64, 3)
727
734
  *
728
735
  * @param baseSeed - 32-byte wallet base seed (from mnemonic)
729
- * @param addressIndex - Address index (0-63)
730
- * @returns TreeKey for this address with size=64, depth=3
736
+ * @param index - Address index (0-63)
737
+ * @returns TreeKey for this spend address with size=64, depth=3
731
738
  */
732
- function createPerAddressTreeKey(baseSeed, addressIndex) {
733
- const addressSeed = (0, javaStreamables_js_1.derivePerAddressSeed)(baseSeed, addressIndex);
734
- return new TreeKey(addressSeed, 64, 3);
739
+ function createUnifiedChildTreeKey(baseSeed, index) {
740
+ const childSeed = (0, javaStreamables_js_1.deriveUnifiedChildSeed)(baseSeed, index);
741
+ return new TreeKey(childSeed, 64, 3);
735
742
  }
736
743
  /**
737
- * Async version with progress reporting for UI
744
+ * Async version with progress reporting for UI.
738
745
  *
739
746
  * @param baseSeed - 32-byte wallet base seed
740
- * @param addressIndex - Address index (0-63)
747
+ * @param index - Address index (0-63)
741
748
  * @param onProgress - Optional progress callback
742
- * @returns Promise resolving to TreeKey for this address
749
+ * @returns Promise resolving to the child TreeKey
743
750
  */
744
- async function createPerAddressTreeKeyAsync(baseSeed, addressIndex, onProgress) {
745
- const addressSeed = (0, javaStreamables_js_1.derivePerAddressSeed)(baseSeed, addressIndex);
746
- return TreeKey.createWithProgress(addressSeed, 64, 3, onProgress);
751
+ async function createUnifiedChildTreeKeyAsync(baseSeed, index, onProgress) {
752
+ const childSeed = (0, javaStreamables_js_1.deriveUnifiedChildSeed)(baseSeed, index);
753
+ return TreeKey.createWithProgress(childSeed, 64, 3, onProgress);
747
754
  }
748
755
  /**
749
- * Derive address public key from base seed and address index
756
+ * Create the unified root identity TreeKey (identity anchor, never a spend address).
750
757
  *
751
- * This is the fast path for getting an address public key without
752
- * needing to construct the full TreeKey. Useful for address derivation
753
- * during wallet initialization.
758
+ * Derivation: root_priv_seed = deriveRootPrivSeed(baseSeed)
759
+ * treeKey = new TreeKey(root_priv_seed, 64, 3)
754
760
  *
755
- * @param baseSeed - 32-byte wallet base seed
756
- * @param addressIndex - Address index (0-63)
757
- * @returns 32-byte address public key (MMR root of per-address TreeKey)
761
+ * @param baseSeed - 32-byte wallet base seed (from mnemonic)
762
+ * @returns Root identity TreeKey with size=64, depth=3
758
763
  */
759
- function deriveAddressPublicKey(baseSeed, addressIndex) {
760
- const treeKey = createPerAddressTreeKey(baseSeed, addressIndex);
761
- return treeKey.getPublicKey();
764
+ function createUnifiedRootTreeKey(baseSeed) {
765
+ const rootPrivSeed = (0, javaStreamables_js_1.deriveRootPrivSeed)(baseSeed);
766
+ return new TreeKey(rootPrivSeed, 64, 3);
762
767
  }
763
768
  /**
764
- * Get the address public key from a per-address TreeKey
769
+ * Fast path for deriving a child address public key without constructing
770
+ * the full TreeKey. Useful during wallet initialisation.
765
771
  *
766
- * In the per-address architecture, each address has its own TreeKey,
767
- * and the address public key is simply the TreeKey's root public key.
768
- *
769
- * @param treeKey - Per-address TreeKey
770
- * @returns 32-byte address public key (TreeKey root)
772
+ * @param baseSeed - 32-byte wallet base seed
773
+ * @param index - Address index (0-63)
774
+ * @returns 32-byte address public key (MMR root of child TreeKey)
771
775
  */
772
- function getPerAddressPublicKey(treeKey) {
773
- return treeKey.getPublicKey();
776
+ function deriveUnifiedAddressPublicKey(baseSeed, index) {
777
+ return createUnifiedChildTreeKey(baseSeed, index).getPublicKey();
778
+ }
779
+ // ---------------------------------------------------------------------------
780
+ // Deprecated aliases — kept for migration compatibility only.
781
+ // Downstream consumers should migrate to createUnifiedChildTreeKey.
782
+ // ---------------------------------------------------------------------------
783
+ /**
784
+ * @deprecated Use {@link createUnifiedChildTreeKey} instead.
785
+ * This wrapper preserves the LEGACY per-address seed derivation
786
+ * (`SHA3-256(baseSeed ‖ indexBytes(i))`) so that existing callers
787
+ * that import this symbol by name continue to derive the same keys.
788
+ * New code must use createUnifiedChildTreeKey which applies the unified
789
+ * two-step derivation (root_priv_seed → child_seed_i).
790
+ */
791
+ function createPerAddressTreeKey(baseSeed, addressIndex) {
792
+ const perAddressSeed = (0, javaStreamables_js_1.derivePerAddressSeed)(baseSeed instanceof Uint8Array ? baseSeed : new Uint8Array(baseSeed), addressIndex);
793
+ return new TreeKey(perAddressSeed, 64, 3);
794
+ }
795
+ /**
796
+ * @deprecated Use {@link createUnifiedChildTreeKeyAsync} instead.
797
+ * Preserves legacy per-address seed derivation for backward compatibility.
798
+ */
799
+ async function createPerAddressTreeKeyAsync(baseSeed, addressIndex, onProgress) {
800
+ const perAddressSeed = (0, javaStreamables_js_1.derivePerAddressSeed)(baseSeed instanceof Uint8Array ? baseSeed : new Uint8Array(baseSeed), addressIndex);
801
+ return TreeKey.createWithProgress(perAddressSeed, 64, 3, onProgress);
774
802
  }
@@ -41,8 +41,6 @@ class TransactionService {
41
41
  burn: params.burn || null,
42
42
  paramSet: this.config.paramSet || 'v2-spec',
43
43
  addressIndex: params.addressIndex,
44
- walletMode: params.walletMode || 'AnonTree',
45
- perAddressPublicKey: params.perAddressPublicKey ?? null,
46
44
  }, {
47
45
  headers: {
48
46
  'Content-Type': 'application/json',
@@ -106,9 +104,9 @@ class TransactionService {
106
104
  if (digestBytes.length !== 32) {
107
105
  throw new Error(`Invalid digest length: ${digestBytes.length}, expected 32 bytes`);
108
106
  }
109
- // Derive per-address TreeKey matching Minima Wallet.java
110
- this.logger.debug(` Deriving per-address TreeKey for index ${addressIndex}...`);
111
- const treeKey = (0, treekey_js_1.createPerAddressTreeKey)(seed, addressIndex);
107
+ // Derive unified child TreeKey for this address index
108
+ this.logger.debug(` Deriving unified child TreeKey for index ${addressIndex}...`);
109
+ const treeKey = (0, treekey_js_1.createUnifiedChildTreeKey)(seed, addressIndex);
112
110
  // Convert (l1, l2) to Java-compatible 'uses' counter
113
111
  // Java's TreeKey.sign() uses baseConversion(uses) to compute path
114
112
  const KEYS_PER_LEVEL = 64;
@@ -14,8 +14,6 @@ export interface PrepareRequest {
14
14
  burn?: string;
15
15
  txId?: string;
16
16
  addressIndex?: number;
17
- walletMode?: 'AnonTree' | 'RootTree';
18
- perAddressPublicKey?: string;
19
17
  }
20
18
  export interface PrepareResponse {
21
19
  addressIndex: number;
package/dist/wots.d.ts CHANGED
@@ -31,14 +31,14 @@ export declare function disableWotsLogger(): void;
31
31
  * Check if WOTS debug logging is enabled
32
32
  */
33
33
  export declare function isWotsDebugEnabled(): boolean;
34
- export declare const F: (x: Uint8Array) => Uint8Array<ArrayBufferLike> & Uint8Array<ArrayBuffer>;
34
+ export declare const F: (x: Uint8Array) => Uint8Array<ArrayBufferLike>;
35
35
  export declare const hex: (u: Uint8Array) => string;
36
36
  export declare const fromHex: (h: string) => Uint8Array;
37
37
  export declare const concatBytes: (...arrs: Uint8Array[]) => Uint8Array<ArrayBuffer>;
38
38
  export declare const u16be: (n: number) => Uint8Array<ArrayBuffer>;
39
39
  export declare const u32be: (n: number) => Uint8Array<ArrayBuffer>;
40
40
  export declare function assert32(u: Uint8Array, label?: string): void;
41
- export declare const h: (x: Uint8Array) => Uint8Array<ArrayBufferLike> & Uint8Array<ArrayBuffer>;
41
+ export declare const h: (x: Uint8Array) => Uint8Array<ArrayBufferLike>;
42
42
  /**
43
43
  * GMSSRandom - BouncyCastle's stateful PRNG for WOTS chain seed derivation
44
44
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@totemsdk/core",
3
- "version": "1.0.11",
3
+ "version": "1.1.0",
4
4
  "description": "Core cryptographic primitives for Totem SDK",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",