@totemsdk/root-identity 1.0.6 → 1.0.8

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.
@@ -0,0 +1,158 @@
1
+ /**
2
+ * UnifiedIdentityWallet — single root identity with true hierarchical key derivation.
3
+ *
4
+ * Architecture
5
+ * ────────────
6
+ * baseSeed (32 bytes)
7
+ * │
8
+ * ├── root_priv_seed = deriveRootPrivSeed(baseSeed)
9
+ * │ └── rootTreeKey = createUnifiedRootTreeKey(baseSeed) ← identity anchor (NEVER a spend address)
10
+ * │
11
+ * ├── child_seed_0 = deriveUnifiedChildSeed(baseSeed, 0)
12
+ * │ └── childTreeKey_0 ← spend address 0
13
+ * ├── child_seed_1 = deriveUnifiedChildSeed(baseSeed, 1)
14
+ * │ └── childTreeKey_1 ← spend address 1
15
+ * │ …
16
+ * └── child_seed_N = deriveUnifiedChildSeed(baseSeed, N)
17
+ * └── childTreeKey_N ← spend address N
18
+ *
19
+ * Child seeds are cryptographically descended from root_priv_seed, not siblings.
20
+ * This enables genuine ancestral proofs: the root can prove control of any child
21
+ * without revealing relationships between children.
22
+ *
23
+ * Addresses are Minima-compatible: RETURN SIGNEDBY(treeKey.rootPubKey) scripts,
24
+ * WOTS proof-chain signatures. Nodes never see the derivation hierarchy.
25
+ *
26
+ * Watermarks are tracked in memory. Callers that need persistence should read
27
+ * `getRootUses()` / `getChildUses(index)` after each signing operation and
28
+ * restore them via `setRootUses()` / `setChildUses()` on the next session.
29
+ */
30
+ import { type TreeKey } from '@totemsdk/core';
31
+ import type { WotsProof, OwnershipProof } from './types.js';
32
+ export declare const MAX_CHILD_COUNT = 64;
33
+ export declare class UnifiedIdentityWallet {
34
+ private readonly baseSeed;
35
+ private readonly childCount;
36
+ /** Cached root TreeKey (identity anchor). Created lazily. */
37
+ private cachedRootTreeKey?;
38
+ /** Cached child TreeKey instances. Created lazily. */
39
+ private readonly childTreeKeyCache;
40
+ /** Cached addresses and public keys (populated on first access per key). */
41
+ private cachedRootAddress?;
42
+ private cachedRootPublicKey?;
43
+ private readonly childAddressCache;
44
+ private readonly childPubKeyCache;
45
+ /** Per-slot watermarks (in-memory; persist via getWatermarkState / restoreWatermarkState). */
46
+ private rootUses;
47
+ private readonly childUsesMap;
48
+ /**
49
+ * @param baseSeed - 32-byte raw seed (use `UnifiedIdentityWallet.fromPhrase` for mnemonic input)
50
+ * @param childCount - Number of child addresses (1–64, default 64)
51
+ */
52
+ constructor(baseSeed: Uint8Array, childCount?: number);
53
+ /** Create a wallet from a Minima-compatible BIP39 seed phrase. */
54
+ static fromPhrase(phrase: string, childCount?: number): UnifiedIdentityWallet;
55
+ /** Generate a new random Minima-compatible 24-word seed phrase. */
56
+ static generatePhrase(): string;
57
+ /** Validate a Minima-compatible seed phrase. */
58
+ static validatePhrase(phrase: string): boolean;
59
+ /** Minima address for the root key. NEVER use this address for spending. */
60
+ getRootAddress(): string;
61
+ /** 64-char hex public key for the root key. */
62
+ getRootPublicKey(): string;
63
+ /** Minima spend address for child `index` (0-based). */
64
+ getChildAddress(index: number): string;
65
+ /** 64-char hex public key for child `index`. */
66
+ getChildPublicKey(index: number): string;
67
+ /** All addresses: root first, then all children in order. */
68
+ getAllAddresses(): string[];
69
+ /** Root address and children as a structured object. */
70
+ getAddressMap(): {
71
+ root: string;
72
+ children: string[];
73
+ };
74
+ /**
75
+ * Sign `message` with the root identity key (for off-chain attestations).
76
+ * Hashes the message with SHA3-256 before signing.
77
+ * @throws if root TreeKey is exhausted (262 144 uses)
78
+ */
79
+ signFromRoot(message: string): WotsProof;
80
+ /**
81
+ * Sign `message` with child key `index` (0-based) for on-chain transactions.
82
+ * Each child maintains its own independent use counter.
83
+ * @throws if child TreeKey is exhausted or index out of range
84
+ */
85
+ signFromChild(index: number, message: string): WotsProof;
86
+ /**
87
+ * Produce an ownership proof demonstrating that this root identity controls
88
+ * all given child addresses.
89
+ *
90
+ * The root key signs a canonical JSON message containing all child public keys
91
+ * (sorted) and a timestamp, enabling third-party verification without any
92
+ * network access.
93
+ *
94
+ * @param childIndices - Which children to include (0-based)
95
+ */
96
+ proveOwnership(childIndices: number[]): OwnershipProof;
97
+ /**
98
+ * Verify an ownership proof produced by `proveOwnership`.
99
+ *
100
+ * Returns `true` only when:
101
+ * - The canonical message is reconstructed correctly (child keys are sorted).
102
+ * - The root WOTS signature validates against the root public key and address.
103
+ * - Every child public key correctly derives the corresponding child address.
104
+ *
105
+ * Pure crypto — no network access required.
106
+ * Always returns `false` (never throws) on malformed or incomplete proof data.
107
+ */
108
+ static verifyOwnershipProof(proof: OwnershipProof): boolean;
109
+ /**
110
+ * Get (or create and cache) the TreeKey for child `index` (0-based).
111
+ *
112
+ * Use this for transaction signing — the child TreeKey is the spend key.
113
+ * Call `getChildUses` / `setChildUses` to manage the watermark manually.
114
+ */
115
+ getChildTreeKey(index: number): TreeKey;
116
+ /**
117
+ * Get (or create and cache) the root identity TreeKey.
118
+ *
119
+ * Use this only for off-chain attestation signing, not for spending.
120
+ */
121
+ getRootTreeKey(): TreeKey;
122
+ /** Number of times the root identity key has signed (for persistence). */
123
+ getRootUses(): number;
124
+ /** Restore root watermark from a previously persisted value. */
125
+ setRootUses(uses: number): void;
126
+ /** Number of times child `index` has signed (for persistence). */
127
+ getChildUses(index: number): number;
128
+ /** Restore child watermark from a previously persisted value. */
129
+ setChildUses(index: number, uses: number): void;
130
+ /** Number of child addresses configured for this wallet. */
131
+ getChildCount(): number;
132
+ /** Maximum one-time signatures available per slot (3 levels × 64 keys = 262 144). */
133
+ getMaxUsesPerSlot(): number;
134
+ /**
135
+ * Return a serialisable snapshot of all current watermark counters.
136
+ *
137
+ * Persist the returned object (e.g. to encrypted storage) and pass it back
138
+ * to `restoreWatermarkState()` at the start of the next session so that no
139
+ * one-time-use signing slot is ever reused.
140
+ */
141
+ getWatermarkState(): {
142
+ rootUses: number;
143
+ childUses: Record<number, number>;
144
+ };
145
+ /**
146
+ * Restore watermark counters from a previously persisted snapshot.
147
+ *
148
+ * Call this immediately after constructing the wallet to prevent slot reuse
149
+ * across sessions. Out-of-range or invalid entries are silently skipped.
150
+ */
151
+ restoreWatermarkState(state: {
152
+ rootUses?: number;
153
+ childUses?: Record<number, number>;
154
+ }): void;
155
+ private assertChildIndex;
156
+ private populateRootCache;
157
+ private getOrCreateChildTreeKey;
158
+ }
@@ -0,0 +1,361 @@
1
+ "use strict";
2
+ /**
3
+ * UnifiedIdentityWallet — single root identity with true hierarchical key derivation.
4
+ *
5
+ * Architecture
6
+ * ────────────
7
+ * baseSeed (32 bytes)
8
+ * │
9
+ * ├── root_priv_seed = deriveRootPrivSeed(baseSeed)
10
+ * │ └── rootTreeKey = createUnifiedRootTreeKey(baseSeed) ← identity anchor (NEVER a spend address)
11
+ * │
12
+ * ├── child_seed_0 = deriveUnifiedChildSeed(baseSeed, 0)
13
+ * │ └── childTreeKey_0 ← spend address 0
14
+ * ├── child_seed_1 = deriveUnifiedChildSeed(baseSeed, 1)
15
+ * │ └── childTreeKey_1 ← spend address 1
16
+ * │ …
17
+ * └── child_seed_N = deriveUnifiedChildSeed(baseSeed, N)
18
+ * └── childTreeKey_N ← spend address N
19
+ *
20
+ * Child seeds are cryptographically descended from root_priv_seed, not siblings.
21
+ * This enables genuine ancestral proofs: the root can prove control of any child
22
+ * without revealing relationships between children.
23
+ *
24
+ * Addresses are Minima-compatible: RETURN SIGNEDBY(treeKey.rootPubKey) scripts,
25
+ * WOTS proof-chain signatures. Nodes never see the derivation hierarchy.
26
+ *
27
+ * Watermarks are tracked in memory. Callers that need persistence should read
28
+ * `getRootUses()` / `getChildUses(index)` after each signing operation and
29
+ * restore them via `setRootUses()` / `setChildUses()` on the next session.
30
+ */
31
+ Object.defineProperty(exports, "__esModule", { value: true });
32
+ exports.UnifiedIdentityWallet = exports.MAX_CHILD_COUNT = void 0;
33
+ const core_1 = require("@totemsdk/core");
34
+ const core_2 = require("@totemsdk/core");
35
+ exports.MAX_CHILD_COUNT = 64;
36
+ const OWNERSHIP_OP = 'TOTEM_OWNERSHIP_PROOF_V1';
37
+ // ─────────────────────────────────────────────────────────────────────────────
38
+ // Helpers
39
+ // ─────────────────────────────────────────────────────────────────────────────
40
+ function hashMessage(message) {
41
+ return (0, core_1.sha3_256)(new TextEncoder().encode(message));
42
+ }
43
+ function addressFromPublicKeyBytes(pkBytes) {
44
+ const script = (0, core_2.scriptFromWotsPk)(pkBytes);
45
+ return (0, core_2.scriptToAddress)(script);
46
+ }
47
+ /**
48
+ * Build the deterministic ownership-proof message that the root key signs.
49
+ *
50
+ * Child public keys are sorted lexicographically before serialization so that
51
+ * the same child set always produces the same canonical message regardless of
52
+ * the order in which indices were passed to `proveOwnership`.
53
+ */
54
+ function buildOwnershipMessage(rootAddress, childPublicKeys, timestamp) {
55
+ return JSON.stringify({
56
+ op: OWNERSHIP_OP,
57
+ rootAddress,
58
+ childPublicKeys: [...childPublicKeys].sort(),
59
+ timestamp,
60
+ });
61
+ }
62
+ // ─────────────────────────────────────────────────────────────────────────────
63
+ // UnifiedIdentityWallet
64
+ // ─────────────────────────────────────────────────────────────────────────────
65
+ class UnifiedIdentityWallet {
66
+ // ── Construction ────────────────────────────────────────────────────────────
67
+ /**
68
+ * @param baseSeed - 32-byte raw seed (use `UnifiedIdentityWallet.fromPhrase` for mnemonic input)
69
+ * @param childCount - Number of child addresses (1–64, default 64)
70
+ */
71
+ constructor(baseSeed, childCount = exports.MAX_CHILD_COUNT) {
72
+ /** Cached child TreeKey instances. Created lazily. */
73
+ this.childTreeKeyCache = new Map();
74
+ this.childAddressCache = new Map();
75
+ this.childPubKeyCache = new Map();
76
+ /** Per-slot watermarks (in-memory; persist via getWatermarkState / restoreWatermarkState). */
77
+ this.rootUses = 0;
78
+ this.childUsesMap = new Map();
79
+ if (baseSeed.length !== 32) {
80
+ throw new Error(`baseSeed must be exactly 32 bytes, got ${baseSeed.length}`);
81
+ }
82
+ if (childCount < 1 || childCount > exports.MAX_CHILD_COUNT) {
83
+ throw new Error(`childCount must be 1–${exports.MAX_CHILD_COUNT}, got ${childCount}`);
84
+ }
85
+ this.baseSeed = baseSeed;
86
+ this.childCount = childCount;
87
+ }
88
+ /** Create a wallet from a Minima-compatible BIP39 seed phrase. */
89
+ static fromPhrase(phrase, childCount = exports.MAX_CHILD_COUNT) {
90
+ return new UnifiedIdentityWallet((0, core_2.phraseToSeed)(phrase), childCount);
91
+ }
92
+ /** Generate a new random Minima-compatible 24-word seed phrase. */
93
+ static generatePhrase() {
94
+ return (0, core_2.generateSeedPhrase)();
95
+ }
96
+ /** Validate a Minima-compatible seed phrase. */
97
+ static validatePhrase(phrase) {
98
+ return (0, core_2.validatePhrase)(phrase);
99
+ }
100
+ // ── Address accessors ────────────────────────────────────────────────────────
101
+ /** Minima address for the root key. NEVER use this address for spending. */
102
+ getRootAddress() {
103
+ if (!this.cachedRootAddress) {
104
+ this.populateRootCache();
105
+ }
106
+ return this.cachedRootAddress;
107
+ }
108
+ /** 64-char hex public key for the root key. */
109
+ getRootPublicKey() {
110
+ if (!this.cachedRootPublicKey) {
111
+ this.populateRootCache();
112
+ }
113
+ return this.cachedRootPublicKey;
114
+ }
115
+ /** Minima spend address for child `index` (0-based). */
116
+ getChildAddress(index) {
117
+ this.assertChildIndex(index);
118
+ if (!this.childAddressCache.has(index)) {
119
+ this.getOrCreateChildTreeKey(index);
120
+ }
121
+ return this.childAddressCache.get(index);
122
+ }
123
+ /** 64-char hex public key for child `index`. */
124
+ getChildPublicKey(index) {
125
+ this.assertChildIndex(index);
126
+ if (!this.childPubKeyCache.has(index)) {
127
+ this.getOrCreateChildTreeKey(index);
128
+ }
129
+ return this.childPubKeyCache.get(index);
130
+ }
131
+ /** All addresses: root first, then all children in order. */
132
+ getAllAddresses() {
133
+ const out = [this.getRootAddress()];
134
+ for (let i = 0; i < this.childCount; i++) {
135
+ out.push(this.getChildAddress(i));
136
+ }
137
+ return out;
138
+ }
139
+ /** Root address and children as a structured object. */
140
+ getAddressMap() {
141
+ const children = [];
142
+ for (let i = 0; i < this.childCount; i++) {
143
+ children.push(this.getChildAddress(i));
144
+ }
145
+ return { root: this.getRootAddress(), children };
146
+ }
147
+ // ── Signing ─────────────────────────────────────────────────────────────────
148
+ /**
149
+ * Sign `message` with the root identity key (for off-chain attestations).
150
+ * Hashes the message with SHA3-256 before signing.
151
+ * @throws if root TreeKey is exhausted (262 144 uses)
152
+ */
153
+ signFromRoot(message) {
154
+ const treeKey = this.getRootTreeKey();
155
+ treeKey.setUses(this.rootUses);
156
+ const sig = treeKey.sign(hashMessage(message));
157
+ this.rootUses++;
158
+ return {
159
+ address: this.getRootAddress(),
160
+ publicKey: this.getRootPublicKey(),
161
+ signature: (0, core_2.bytesToHex)((0, core_2.serializeTreeSignature)(sig)),
162
+ message,
163
+ };
164
+ }
165
+ /**
166
+ * Sign `message` with child key `index` (0-based) for on-chain transactions.
167
+ * Each child maintains its own independent use counter.
168
+ * @throws if child TreeKey is exhausted or index out of range
169
+ */
170
+ signFromChild(index, message) {
171
+ this.assertChildIndex(index);
172
+ const treeKey = this.getOrCreateChildTreeKey(index);
173
+ const uses = this.childUsesMap.get(index) ?? 0;
174
+ treeKey.setUses(uses);
175
+ const sig = treeKey.sign(hashMessage(message));
176
+ this.childUsesMap.set(index, uses + 1);
177
+ return {
178
+ address: this.getChildAddress(index),
179
+ publicKey: this.getChildPublicKey(index),
180
+ signature: (0, core_2.bytesToHex)((0, core_2.serializeTreeSignature)(sig)),
181
+ message,
182
+ };
183
+ }
184
+ // ── Ownership proofs ─────────────────────────────────────────────────────────
185
+ /**
186
+ * Produce an ownership proof demonstrating that this root identity controls
187
+ * all given child addresses.
188
+ *
189
+ * The root key signs a canonical JSON message containing all child public keys
190
+ * (sorted) and a timestamp, enabling third-party verification without any
191
+ * network access.
192
+ *
193
+ * @param childIndices - Which children to include (0-based)
194
+ */
195
+ proveOwnership(childIndices) {
196
+ if (childIndices.length === 0) {
197
+ throw new Error('childIndices must contain at least one index');
198
+ }
199
+ const seen = new Set();
200
+ for (const idx of childIndices) {
201
+ this.assertChildIndex(idx);
202
+ if (seen.has(idx))
203
+ throw new Error(`Duplicate child index: ${idx}`);
204
+ seen.add(idx);
205
+ }
206
+ const timestamp = new Date().toISOString();
207
+ const childAddresses = childIndices.map(i => this.getChildAddress(i));
208
+ const childPublicKeys = childIndices.map(i => this.getChildPublicKey(i));
209
+ const rootAddress = this.getRootAddress();
210
+ const rootPublicKey = this.getRootPublicKey();
211
+ const message = buildOwnershipMessage(rootAddress, childPublicKeys, timestamp);
212
+ const rootProof = this.signFromRoot(message);
213
+ return { rootAddress, rootPublicKey, childAddresses, childPublicKeys, rootProof, timestamp };
214
+ }
215
+ /**
216
+ * Verify an ownership proof produced by `proveOwnership`.
217
+ *
218
+ * Returns `true` only when:
219
+ * - The canonical message is reconstructed correctly (child keys are sorted).
220
+ * - The root WOTS signature validates against the root public key and address.
221
+ * - Every child public key correctly derives the corresponding child address.
222
+ *
223
+ * Pure crypto — no network access required.
224
+ * Always returns `false` (never throws) on malformed or incomplete proof data.
225
+ */
226
+ static verifyOwnershipProof(proof) {
227
+ try {
228
+ if (!proof || typeof proof !== 'object')
229
+ return false;
230
+ const { rootAddress, rootPublicKey, childAddresses, childPublicKeys, rootProof, timestamp } = proof;
231
+ if (!rootAddress || !rootPublicKey || !timestamp ||
232
+ !Array.isArray(childAddresses) || !Array.isArray(childPublicKeys) ||
233
+ !rootProof || typeof rootProof.signature !== 'string') {
234
+ return false;
235
+ }
236
+ if (childAddresses.length === 0)
237
+ return false;
238
+ if (childAddresses.length !== childPublicKeys.length)
239
+ return false;
240
+ const canonicalMessage = buildOwnershipMessage(rootAddress, childPublicKeys, timestamp);
241
+ if (rootProof.message !== canonicalMessage)
242
+ return false;
243
+ const sigResult = (0, core_2.verifySignatureDetailed)(rootAddress, canonicalMessage, rootProof.signature, rootPublicKey);
244
+ if (!sigResult.valid)
245
+ return false;
246
+ for (let i = 0; i < childPublicKeys.length; i++) {
247
+ const pkBytes = (0, core_2.hexToBytes)(childPublicKeys[i]);
248
+ const derivedAddress = addressFromPublicKeyBytes(pkBytes);
249
+ if (derivedAddress.toLowerCase() !== childAddresses[i].toLowerCase())
250
+ return false;
251
+ }
252
+ return true;
253
+ }
254
+ catch {
255
+ return false;
256
+ }
257
+ }
258
+ // ── TreeKey access (for low-level transaction signing) ───────────────────────
259
+ /**
260
+ * Get (or create and cache) the TreeKey for child `index` (0-based).
261
+ *
262
+ * Use this for transaction signing — the child TreeKey is the spend key.
263
+ * Call `getChildUses` / `setChildUses` to manage the watermark manually.
264
+ */
265
+ getChildTreeKey(index) {
266
+ this.assertChildIndex(index);
267
+ return this.getOrCreateChildTreeKey(index);
268
+ }
269
+ /**
270
+ * Get (or create and cache) the root identity TreeKey.
271
+ *
272
+ * Use this only for off-chain attestation signing, not for spending.
273
+ */
274
+ getRootTreeKey() {
275
+ if (!this.cachedRootTreeKey) {
276
+ this.cachedRootTreeKey = (0, core_2.createUnifiedRootTreeKey)(this.baseSeed);
277
+ }
278
+ return this.cachedRootTreeKey;
279
+ }
280
+ // ── Watermark access ─────────────────────────────────────────────────────────
281
+ /** Number of times the root identity key has signed (for persistence). */
282
+ getRootUses() { return this.rootUses; }
283
+ /** Restore root watermark from a previously persisted value. */
284
+ setRootUses(uses) {
285
+ if (uses < 0)
286
+ throw new Error('uses must be non-negative');
287
+ this.rootUses = uses;
288
+ }
289
+ /** Number of times child `index` has signed (for persistence). */
290
+ getChildUses(index) {
291
+ this.assertChildIndex(index);
292
+ return this.childUsesMap.get(index) ?? 0;
293
+ }
294
+ /** Restore child watermark from a previously persisted value. */
295
+ setChildUses(index, uses) {
296
+ this.assertChildIndex(index);
297
+ if (uses < 0)
298
+ throw new Error('uses must be non-negative');
299
+ this.childUsesMap.set(index, uses);
300
+ }
301
+ /** Number of child addresses configured for this wallet. */
302
+ getChildCount() { return this.childCount; }
303
+ /** Maximum one-time signatures available per slot (3 levels × 64 keys = 262 144). */
304
+ getMaxUsesPerSlot() { return 64 * 64 * 64; }
305
+ /**
306
+ * Return a serialisable snapshot of all current watermark counters.
307
+ *
308
+ * Persist the returned object (e.g. to encrypted storage) and pass it back
309
+ * to `restoreWatermarkState()` at the start of the next session so that no
310
+ * one-time-use signing slot is ever reused.
311
+ */
312
+ getWatermarkState() {
313
+ const childUses = {};
314
+ for (const [index, uses] of this.childUsesMap) {
315
+ childUses[index] = uses;
316
+ }
317
+ return { rootUses: this.rootUses, childUses };
318
+ }
319
+ /**
320
+ * Restore watermark counters from a previously persisted snapshot.
321
+ *
322
+ * Call this immediately after constructing the wallet to prevent slot reuse
323
+ * across sessions. Out-of-range or invalid entries are silently skipped.
324
+ */
325
+ restoreWatermarkState(state) {
326
+ if (typeof state?.rootUses === 'number' && state.rootUses >= 0) {
327
+ this.rootUses = Math.floor(state.rootUses);
328
+ }
329
+ if (state?.childUses && typeof state.childUses === 'object') {
330
+ for (const [key, uses] of Object.entries(state.childUses)) {
331
+ const index = Number(key);
332
+ if (Number.isInteger(index) && index >= 0 && index < this.childCount && typeof uses === 'number' && uses >= 0) {
333
+ this.childUsesMap.set(index, Math.floor(uses));
334
+ }
335
+ }
336
+ }
337
+ }
338
+ // ── Private helpers ──────────────────────────────────────────────────────────
339
+ assertChildIndex(index) {
340
+ if (!Number.isInteger(index) || index < 0 || index >= this.childCount) {
341
+ throw new Error(`Child index ${index} is out of range [0, ${this.childCount - 1}]`);
342
+ }
343
+ }
344
+ populateRootCache() {
345
+ const pkBytes = this.getRootTreeKey().getPublicKey();
346
+ this.cachedRootPublicKey = (0, core_2.bytesToHex)(pkBytes);
347
+ this.cachedRootAddress = addressFromPublicKeyBytes(pkBytes);
348
+ }
349
+ getOrCreateChildTreeKey(index) {
350
+ const cached = this.childTreeKeyCache.get(index);
351
+ if (cached)
352
+ return cached;
353
+ const treeKey = (0, core_2.createUnifiedChildTreeKey)(this.baseSeed, index);
354
+ this.childTreeKeyCache.set(index, treeKey);
355
+ const pkBytes = treeKey.getPublicKey();
356
+ this.childPubKeyCache.set(index, (0, core_2.bytesToHex)(pkBytes));
357
+ this.childAddressCache.set(index, addressFromPublicKeyBytes(pkBytes));
358
+ return treeKey;
359
+ }
360
+ }
361
+ exports.UnifiedIdentityWallet = UnifiedIdentityWallet;
package/dist/index.d.ts CHANGED
@@ -2,7 +2,13 @@
2
2
  * @module @totemsdk/root-identity
3
3
  *
4
4
  * Single root identity controlling up to 64 on-chain Minima addresses,
5
- * all cryptographically linked via full independent 3-level WOTS TreeKeys.
5
+ * all cryptographically linked via genuine hierarchical key derivation.
6
+ *
7
+ * Architecture:
8
+ * root_priv_seed = deriveRootPrivSeed(baseSeed)
9
+ * child_seed_i = deriveUnifiedChildSeed(baseSeed, i)
10
+ * rootTreeKey = TreeKey(root_priv_seed) ← identity anchor, never spent
11
+ * childTreeKey_i = TreeKey(child_seed_i) ← Minima spend address i
6
12
  *
7
13
  * Use cases:
8
14
  * - Chain-of-custody proofs
@@ -10,5 +16,6 @@
10
16
  * - Privacy-preserving KYC (selective disclosure)
11
17
  * - NFT / token ownership linking
12
18
  */
13
- export { RootIdentityWallet, MAX_CHILD_COUNT } from './RootIdentityWallet.js';
19
+ export { UnifiedIdentityWallet, MAX_CHILD_COUNT } from './UnifiedIdentityWallet.js';
20
+ export { UnifiedIdentityWallet as RootIdentityWallet } from './UnifiedIdentityWallet.js';
14
21
  export type { WotsProof, OwnershipProof } from './types.js';
package/dist/index.js CHANGED
@@ -3,7 +3,13 @@
3
3
  * @module @totemsdk/root-identity
4
4
  *
5
5
  * Single root identity controlling up to 64 on-chain Minima addresses,
6
- * all cryptographically linked via full independent 3-level WOTS TreeKeys.
6
+ * all cryptographically linked via genuine hierarchical key derivation.
7
+ *
8
+ * Architecture:
9
+ * root_priv_seed = deriveRootPrivSeed(baseSeed)
10
+ * child_seed_i = deriveUnifiedChildSeed(baseSeed, i)
11
+ * rootTreeKey = TreeKey(root_priv_seed) ← identity anchor, never spent
12
+ * childTreeKey_i = TreeKey(child_seed_i) ← Minima spend address i
7
13
  *
8
14
  * Use cases:
9
15
  * - Chain-of-custody proofs
@@ -12,7 +18,9 @@
12
18
  * - NFT / token ownership linking
13
19
  */
14
20
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.MAX_CHILD_COUNT = exports.RootIdentityWallet = void 0;
16
- var RootIdentityWallet_js_1 = require("./RootIdentityWallet.js");
17
- Object.defineProperty(exports, "RootIdentityWallet", { enumerable: true, get: function () { return RootIdentityWallet_js_1.RootIdentityWallet; } });
18
- Object.defineProperty(exports, "MAX_CHILD_COUNT", { enumerable: true, get: function () { return RootIdentityWallet_js_1.MAX_CHILD_COUNT; } });
21
+ exports.RootIdentityWallet = exports.MAX_CHILD_COUNT = exports.UnifiedIdentityWallet = void 0;
22
+ var UnifiedIdentityWallet_js_1 = require("./UnifiedIdentityWallet.js");
23
+ Object.defineProperty(exports, "UnifiedIdentityWallet", { enumerable: true, get: function () { return UnifiedIdentityWallet_js_1.UnifiedIdentityWallet; } });
24
+ Object.defineProperty(exports, "MAX_CHILD_COUNT", { enumerable: true, get: function () { return UnifiedIdentityWallet_js_1.MAX_CHILD_COUNT; } });
25
+ var UnifiedIdentityWallet_js_2 = require("./UnifiedIdentityWallet.js");
26
+ Object.defineProperty(exports, "RootIdentityWallet", { enumerable: true, get: function () { return UnifiedIdentityWallet_js_2.UnifiedIdentityWallet; } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@totemsdk/root-identity",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "Single root identity controlling up to 64 on-chain addresses — all cryptographically linked via full independent 3-level TreeKeys",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -10,22 +10,20 @@
10
10
  "bare": "./dist/index.js",
11
11
  "browser": "./dist/index.js",
12
12
  "import": "./dist/index.js",
13
- "require": "./dist/index.cjs"
13
+ "require": "./dist/index.js"
14
14
  }
15
15
  },
16
16
  "files": [
17
17
  "dist",
18
+ "rust/pkg/",
19
+ "rust/pkg-node/",
18
20
  "README.md",
19
21
  "LICENSE"
20
22
  ],
21
23
  "peerDependencies": {
22
- "@noble/hashes": "^2.0.0",
23
- "@totemsdk/core": ">=1.0.1"
24
+ "@totemsdk/core": "^1.2.8"
24
25
  },
25
26
  "peerDependenciesMeta": {
26
- "@noble/hashes": {
27
- "optional": false
28
- },
29
27
  "@totemsdk/core": {
30
28
  "optional": false
31
29
  }
@@ -38,13 +36,12 @@
38
36
  "access": "public"
39
37
  },
40
38
  "devDependencies": {
41
- "@noble/hashes": "^2.2.0",
42
- "@types/jest": "^29.0.0",
39
+ "@types/jest": "^30.0.0",
43
40
  "@types/node": "^20.0.0",
44
- "jest": "^29.0.0",
41
+ "jest": "^30.4.2",
45
42
  "ts-jest": "^29.0.0",
46
- "typescript": "^5.0.0",
47
- "@totemsdk/core": "1.0.10"
43
+ "typescript": "^7.0.2",
44
+ "@totemsdk/core": "^1.2.8"
48
45
  },
49
46
  "keywords": [
50
47
  "totem",
@@ -53,7 +50,6 @@
53
50
  "blockchain",
54
51
  "quantum-resistant",
55
52
  "wots",
56
- "kissvm",
57
53
  "utxo",
58
54
  "identity",
59
55
  "did",
@@ -63,19 +59,20 @@
63
59
  ],
64
60
  "author": "Totem SDK",
65
61
  "license": "MIT",
66
- "homepage": "https://totemsdk.com",
62
+ "homepage": "https://totem.ing",
67
63
  "bugs": {
68
- "url": "https://github.com/MrGheek/axia-totem/issues"
64
+ "url": "https://github.com/totem-sdk/totem-sdk/issues"
69
65
  },
70
66
  "repository": {
71
67
  "type": "git",
72
- "url": "git+https://github.com/MrGheek/axia-totem.git",
73
- "directory": "packages/totem-sdk/packages/root-identity"
68
+ "url": "git+https://github.com/totem-sdk/totem-sdk.git",
69
+ "directory": "packages/root-identity"
74
70
  },
75
71
  "scripts": {
76
- "build": "tsc",
77
- "clean": "rm -rf dist",
72
+ "build": "npm run build:wasm && tsc && node ../../scripts/clean-wasm-output-ignores.mjs",
73
+ "clean": "rm -rf dist rust/pkg rust/pkg-node rust/target",
78
74
  "pretest": "cd ../core && npm run build",
79
- "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --passWithNoTests"
75
+ "test": "jest",
76
+ "build:wasm": "cd rust && wasm-pack build --target bundler --out-dir pkg && wasm-pack build --target nodejs --out-dir pkg-node"
80
77
  }
81
78
  }