@totemsdk/core 1.0.7 → 1.0.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@totemsdk/core",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "Core cryptographic primitives for Totem SDK",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -26,6 +26,10 @@
26
26
  "types": "./dist/tx/index.d.ts",
27
27
  "import": "./dist/tx/index.js"
28
28
  },
29
+ "./scripts": {
30
+ "types": "./dist/scripts/index.d.ts",
31
+ "import": "./dist/scripts/index.js"
32
+ },
29
33
  "./test-vectors.json": "./test-vectors.json"
30
34
  },
31
35
  "files": [
@@ -263,3 +263,6 @@ export declare function writeHierarchicalWitness(bundle: HierarchicalWitnessBund
263
263
  * Write hierarchical witness and return as hex string
264
264
  */
265
265
  export declare function writeHierarchicalWitnessToHex(bundle: HierarchicalWitnessBundle): string;
266
+ export declare const encodeMiniNumber: typeof writeMiniNumber;
267
+ export declare const encodeMiniData: typeof writeMiniData;
268
+ export declare const encodeMiniString: typeof writeMiniString;
package/src/Streamable.js CHANGED
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  /**
3
2
  * Streamable.ts - Canonical Java-Compatible Serialization Primitives
4
3
  *
@@ -21,29 +20,7 @@
21
20
  * Created: 2026-01-20
22
21
  * Purpose: Single source of truth for all Minima type serialization
23
22
  */
24
- Object.defineProperty(exports, "__esModule", { value: true });
25
- exports.STATETYPE_BOOL = exports.STATETYPE_STRING = exports.STATETYPE_NUMBER = exports.STATETYPE_HEX = void 0;
26
- exports.hexToBytes = hexToBytes;
27
- exports.bytesToHex = bytesToHex;
28
- exports.concat = concat;
29
- exports.writeMiniByte = writeMiniByte;
30
- exports.writeMiniData = writeMiniData;
31
- exports.writeMiniString = writeMiniString;
32
- exports.bigIntToByteArray = bigIntToByteArray;
33
- exports.writeMiniNumber = writeMiniNumber;
34
- exports.writeHashToStream = writeHashToStream;
35
- exports.writeMMREntryNumber = writeMMREntryNumber;
36
- exports.normalizeHexString = normalizeHexString;
37
- exports.writeStateVariable = writeStateVariable;
38
- exports.writeMMRData = writeMMRData;
39
- exports.writeMMRProofChunk = writeMMRProofChunk;
40
- exports.writeMMRProof = writeMMRProof;
41
- exports.writeSignatureProof = writeSignatureProof;
42
- exports.writeSignature = writeSignature;
43
- exports.writeWitness = writeWitness;
44
- exports.writeHierarchicalWitness = writeHierarchicalWitness;
45
- exports.writeHierarchicalWitnessToHex = writeHierarchicalWitnessToHex;
46
- function hexToBytes(hex) {
23
+ export function hexToBytes(hex) {
47
24
  const cleanHex = hex.startsWith('0x') ? hex.slice(2) : hex;
48
25
  if (cleanHex.length === 0) {
49
26
  return new Uint8Array(0);
@@ -57,10 +34,10 @@ function hexToBytes(hex) {
57
34
  }
58
35
  return bytes;
59
36
  }
60
- function bytesToHex(bytes) {
37
+ export function bytesToHex(bytes) {
61
38
  return '0x' + Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('');
62
39
  }
63
- function concat(...arrays) {
40
+ export function concat(...arrays) {
64
41
  const totalLength = arrays.reduce((sum, arr) => sum + arr.length, 0);
65
42
  const result = new Uint8Array(totalLength);
66
43
  let offset = 0;
@@ -75,7 +52,7 @@ function concat(...arrays) {
75
52
  *
76
53
  * Format: single byte (0-255)
77
54
  */
78
- function writeMiniByte(value) {
55
+ export function writeMiniByte(value) {
79
56
  if (typeof value === 'boolean') {
80
57
  return new Uint8Array([value ? 1 : 0]);
81
58
  }
@@ -89,7 +66,7 @@ function writeMiniByte(value) {
89
66
  *
90
67
  * Format: 4-byte big-endian int length + raw bytes
91
68
  */
92
- function writeMiniData(data) {
69
+ export function writeMiniData(data) {
93
70
  const length = data.length;
94
71
  const lengthBytes = new Uint8Array([
95
72
  (length >> 24) & 0xff,
@@ -105,7 +82,7 @@ function writeMiniData(data) {
105
82
  * Format: MiniData encoding of UTF-8 bytes
106
83
  * = 4-byte int length + UTF-8 bytes
107
84
  */
108
- function writeMiniString(str) {
85
+ export function writeMiniString(str) {
109
86
  const utf8Bytes = new TextEncoder().encode(str);
110
87
  return writeMiniData(utf8Bytes);
111
88
  }
@@ -119,7 +96,7 @@ function writeMiniString(str) {
119
96
  * @param value - The BigInt value (must be non-negative)
120
97
  * @returns Uint8Array in two's complement format
121
98
  */
122
- function bigIntToByteArray(value) {
99
+ export function bigIntToByteArray(value) {
123
100
  if (value < 0n) {
124
101
  throw new Error(`bigIntToByteArray does not support negative values: ${value}`);
125
102
  }
@@ -152,7 +129,7 @@ function bigIntToByteArray(value) {
152
129
  * @param value - The unscaled BigInt value
153
130
  * @param scale - The scale (decimal places), default 0
154
131
  */
155
- function writeMiniNumber(value, scale = 0) {
132
+ export function writeMiniNumber(value, scale = 0) {
156
133
  if (typeof value !== 'bigint') {
157
134
  throw new Error(`writeMiniNumber requires bigint, got ${typeof value}`);
158
135
  }
@@ -176,7 +153,7 @@ function writeMiniNumber(value, scale = 0) {
176
153
  * Format: 4-byte big-endian int length + hash bytes
177
154
  * (Same as MiniData)
178
155
  */
179
- function writeHashToStream(hash) {
156
+ export function writeHashToStream(hash) {
180
157
  return writeMiniData(hash);
181
158
  }
182
159
  /**
@@ -194,7 +171,7 @@ function writeHashToStream(hash) {
194
171
  * [00 01 00] - MiniNumber: scale=0, len=1, data=0x00
195
172
  * [00 00 00 LL ...] - MiniData: 4-byte len + BigInteger bytes
196
173
  */
197
- function writeMMREntryNumber(value, scale = 0) {
174
+ export function writeMMREntryNumber(value, scale = 0) {
198
175
  if (value < 0n) {
199
176
  throw new Error(`writeMMREntryNumber does not support negative values: ${value}`);
200
177
  }
@@ -208,10 +185,10 @@ function writeMMREntryNumber(value, scale = 0) {
208
185
  /**
209
186
  * StateVariable type constants from Java StateVariable.java
210
187
  */
211
- exports.STATETYPE_HEX = 1;
212
- exports.STATETYPE_NUMBER = 2;
213
- exports.STATETYPE_STRING = 4;
214
- exports.STATETYPE_BOOL = 8;
188
+ export const STATETYPE_HEX = 1;
189
+ export const STATETYPE_NUMBER = 2;
190
+ export const STATETYPE_STRING = 4;
191
+ export const STATETYPE_BOOL = 8;
215
192
  /**
216
193
  * Normalize hex/address string to 0x format.
217
194
  * Handles both Mx (Minima Base32) and 0x formats.
@@ -220,7 +197,7 @@ exports.STATETYPE_BOOL = 8;
220
197
  * Note: For Mx conversion, caller should use mxToHex from minima-base32
221
198
  * This function handles 0x prefix normalization only.
222
199
  */
223
- function normalizeHexString(value) {
200
+ export function normalizeHexString(value) {
224
201
  if (!value) {
225
202
  return '0x00';
226
203
  }
@@ -242,7 +219,7 @@ function normalizeHexString(value) {
242
219
  * @param sv - StateVariable with high-level value
243
220
  * @param mxToHex - Optional function to convert Mx addresses to 0x hex
244
221
  */
245
- function writeStateVariable(sv, mxToHex) {
222
+ export function writeStateVariable(sv, mxToHex) {
246
223
  if (sv.port < 0 || sv.port > 255) {
247
224
  throw new Error(`StateVariable port must be 0-255, got ${sv.port}`);
248
225
  }
@@ -251,7 +228,7 @@ function writeStateVariable(sv, mxToHex) {
251
228
  let dataBytes;
252
229
  switch (sv.type) {
253
230
  case 'bool':
254
- typeByte = writeMiniByte(exports.STATETYPE_BOOL);
231
+ typeByte = writeMiniByte(STATETYPE_BOOL);
255
232
  if (typeof sv.value === 'boolean') {
256
233
  dataBytes = writeMiniByte(sv.value);
257
234
  }
@@ -263,7 +240,7 @@ function writeStateVariable(sv, mxToHex) {
263
240
  }
264
241
  break;
265
242
  case 'number':
266
- typeByte = writeMiniByte(exports.STATETYPE_NUMBER);
243
+ typeByte = writeMiniByte(STATETYPE_NUMBER);
267
244
  if (typeof sv.value === 'bigint') {
268
245
  dataBytes = writeMiniNumber(sv.value);
269
246
  }
@@ -275,7 +252,7 @@ function writeStateVariable(sv, mxToHex) {
275
252
  }
276
253
  break;
277
254
  case 'hex':
278
- typeByte = writeMiniByte(exports.STATETYPE_HEX);
255
+ typeByte = writeMiniByte(STATETYPE_HEX);
279
256
  if (typeof sv.value === 'string') {
280
257
  let normalizedHex = sv.value;
281
258
  if (sv.value.toLowerCase().startsWith('mx') && mxToHex) {
@@ -294,7 +271,7 @@ function writeStateVariable(sv, mxToHex) {
294
271
  }
295
272
  break;
296
273
  case 'string':
297
- typeByte = writeMiniByte(exports.STATETYPE_STRING);
274
+ typeByte = writeMiniByte(STATETYPE_STRING);
298
275
  if (typeof sv.value === 'string') {
299
276
  let bracketedValue = sv.value;
300
277
  if (!sv.value.startsWith('[') || !sv.value.endsWith(']')) {
@@ -318,7 +295,7 @@ function writeStateVariable(sv, mxToHex) {
318
295
  * mData.writeHashToStream(zOut); // 4-byte len + hash
319
296
  * mValue.writeDataStream(zOut); // MiniNumber
320
297
  */
321
- function writeMMRData(mmrData) {
298
+ export function writeMMRData(mmrData) {
322
299
  const hashBytes = writeHashToStream(mmrData.data);
323
300
  const valueBytes = writeMiniNumber(mmrData.value, 0);
324
301
  return concat(hashBytes, valueBytes);
@@ -330,7 +307,7 @@ function writeMMRData(mmrData) {
330
307
  * mLeft.writeDataStream(zOut); // MiniByte (1 byte)
331
308
  * mMMRData.writeDataStream(zOut); // MMRData
332
309
  */
333
- function writeMMRProofChunk(chunk) {
310
+ export function writeMMRProofChunk(chunk) {
334
311
  const leftByte = writeMiniByte(chunk.isLeft);
335
312
  const dataBytes = writeMMRData(chunk.mmrData);
336
313
  return concat(leftByte, dataBytes);
@@ -343,7 +320,7 @@ function writeMMRProofChunk(chunk) {
343
320
  * MiniNumber.WriteToStream(zOut, len); // Array length as MiniNumber
344
321
  * for each chunk: chunk.writeDataStream(zOut);
345
322
  */
346
- function writeMMRProof(proof) {
323
+ export function writeMMRProof(proof) {
347
324
  const blockTimeBytes = writeMiniNumber(proof.blockTime, 0);
348
325
  const lengthBytes = writeMiniNumber(BigInt(proof.chunks.length), 0);
349
326
  const parts = [blockTimeBytes, lengthBytes];
@@ -360,7 +337,7 @@ function writeMMRProof(proof) {
360
337
  * mSignature.writeDataStream(zOut); // MiniData
361
338
  * mProof.writeDataStream(zOut); // MMRProof
362
339
  */
363
- function writeSignatureProof(sigProof) {
340
+ export function writeSignatureProof(sigProof) {
364
341
  const pubKeyBytes = writeMiniData(sigProof.leafPubkey);
365
342
  const sigBytes = writeMiniData(sigProof.signature);
366
343
  const proofBytes = writeMMRProof(sigProof.mmrProof);
@@ -373,7 +350,7 @@ function writeSignatureProof(sigProof) {
373
350
  * MiniNumber.WriteToStream(zOut, mSignatures.size());
374
351
  * for each sig: sig.writeDataStream(zOut);
375
352
  */
376
- function writeSignature(sig) {
353
+ export function writeSignature(sig) {
377
354
  const lengthBytes = writeMiniNumber(BigInt(sig.proofs.length), 0);
378
355
  const parts = [lengthBytes];
379
356
  for (const proof of sig.proofs) {
@@ -392,7 +369,7 @@ function writeSignature(sig) {
392
369
  * MiniNumber.WriteToStream(zOut, mScriptProofs.size());
393
370
  * for each sp: sp.writeDataStream(zOut);
394
371
  */
395
- function writeWitness(witness) {
372
+ export function writeWitness(witness) {
396
373
  const parts = [];
397
374
  // Signatures
398
375
  parts.push(writeMiniNumber(BigInt(witness.signatures.length), 0));
@@ -415,7 +392,7 @@ function writeWitness(witness) {
415
392
  * Write a simplified hierarchical witness (signatures only)
416
393
  * Used for WOTS transaction signing flow
417
394
  */
418
- function writeHierarchicalWitness(bundle) {
395
+ export function writeHierarchicalWitness(bundle) {
419
396
  const lengthBytes = writeMiniNumber(BigInt(bundle.signatures.length), 0);
420
397
  const parts = [lengthBytes];
421
398
  for (const sig of bundle.signatures) {
@@ -426,6 +403,14 @@ function writeHierarchicalWitness(bundle) {
426
403
  /**
427
404
  * Write hierarchical witness and return as hex string
428
405
  */
429
- function writeHierarchicalWitnessToHex(bundle) {
406
+ export function writeHierarchicalWitnessToHex(bundle) {
430
407
  return bytesToHex(writeHierarchicalWitness(bundle));
431
408
  }
409
+ // ============================================================
410
+ // EXTENSION-MATCHING ALIASES
411
+ // ============================================================
412
+ // The extension's WitnessSerializer uses encode* naming, while SDK uses write* naming.
413
+ // These aliases provide compatibility with extension code.
414
+ export const encodeMiniNumber = writeMiniNumber;
415
+ export const encodeMiniData = writeMiniData;
416
+ export const encodeMiniString = writeMiniString;
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  /**
3
2
  * Java-Compatible Serialization Helpers
4
3
  *
@@ -13,26 +12,8 @@
13
12
  * NOTE: This module provides number-based wrappers for backward compatibility.
14
13
  * The canonical implementations are in Streamable.ts which uses bigint for precision.
15
14
  */
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.serializeMiniNumber = serializeMiniNumber;
18
- exports.serializeMiniData = serializeMiniData;
19
- exports.hashAllObjects = hashAllObjects;
20
- exports.deriveChainSeedJava = deriveChainSeedJava;
21
- exports.deriveChildTreeSeedJava = deriveChildTreeSeedJava;
22
- exports.hashObject = hashObject;
23
- exports.indexToMiniDataBytes = indexToMiniDataBytes;
24
- exports.derivePerAddressSeed = derivePerAddressSeed;
25
- exports.serializeMiniNumberZERO = serializeMiniNumberZERO;
26
- exports.serializeMiniNumberONE = serializeMiniNumberONE;
27
- exports.writeHashToStream = writeHashToStream;
28
- exports.javaHashAllObjects = javaHashAllObjects;
29
- exports.createMMREntryNumber = createMMREntryNumber;
30
- exports.serializeMMREntryNumber = serializeMMREntryNumber;
31
- exports.serializeMMRData = serializeMMRData;
32
- exports.serializeMMREntry = serializeMMREntry;
33
- exports.precomputeTransactionCoinID = precomputeTransactionCoinID;
34
- const sha3_1 = require("@noble/hashes/sha3");
35
- const Streamable_1 = require("./Streamable");
15
+ import { sha3_256 } from '@noble/hashes/sha3.js';
16
+ import { writeMiniNumber as streamableWriteMiniNumber, writeMiniData as streamableWriteMiniData, writeHashToStream as streamableWriteHashToStream, bigIntToByteArray } from './Streamable.js';
36
17
  /**
37
18
  * Serialize a number in MiniNumber format (Java compatible)
38
19
  *
@@ -41,10 +22,10 @@ const Streamable_1 = require("./Streamable");
41
22
  * @param n - Non-negative integer to serialize
42
23
  * @returns Serialized bytes matching Java MiniNumber format
43
24
  */
44
- function serializeMiniNumber(n) {
25
+ export function serializeMiniNumber(n) {
45
26
  if (n < 0)
46
27
  throw new Error('MiniNumber must be non-negative');
47
- return (0, Streamable_1.writeMiniNumber)(BigInt(n));
28
+ return streamableWriteMiniNumber(BigInt(n));
48
29
  }
49
30
  /**
50
31
  * Serialize bytes in MiniData format (Java compatible)
@@ -54,8 +35,8 @@ function serializeMiniNumber(n) {
54
35
  * @param data - Bytes to serialize
55
36
  * @returns Serialized bytes matching Java MiniData format
56
37
  */
57
- function serializeMiniData(data) {
58
- return (0, Streamable_1.writeMiniData)(data);
38
+ export function serializeMiniData(data) {
39
+ return streamableWriteMiniData(data);
59
40
  }
60
41
  /**
61
42
  * Hash multiple Streamable objects (Java compatible)
@@ -70,7 +51,7 @@ function serializeMiniData(data) {
70
51
  * @param items - Array of serialized objects (use serializeMiniNumber/serializeMiniData)
71
52
  * @returns 32-byte SHA3-256 hash
72
53
  */
73
- function hashAllObjects(...items) {
54
+ export function hashAllObjects(...items) {
74
55
  // Concatenate all serialized items
75
56
  const totalLength = items.reduce((sum, item) => sum + item.length, 0);
76
57
  const combined = new Uint8Array(totalLength);
@@ -80,7 +61,7 @@ function hashAllObjects(...items) {
80
61
  offset += item.length;
81
62
  }
82
63
  // SHA3-256 hash
83
- return (0, sha3_1.sha3_256)(combined);
64
+ return sha3_256(combined);
84
65
  }
85
66
  /**
86
67
  * Derive per-chain seed matching Java TreeKeyNode.java exactly
@@ -92,7 +73,7 @@ function hashAllObjects(...items) {
92
73
  * @param index - Chain index (0-63)
93
74
  * @returns 32-byte derived seed for this chain
94
75
  */
95
- function deriveChainSeedJava(privateSeed, index) {
76
+ export function deriveChainSeedJava(privateSeed, index) {
96
77
  const indexSerialized = serializeMiniNumber(index);
97
78
  const seedSerialized = serializeMiniData(privateSeed);
98
79
  return hashAllObjects(indexSerialized, seedSerialized);
@@ -110,7 +91,7 @@ function deriveChainSeedJava(privateSeed, index) {
110
91
  * @param childIndex - Child index (0-63)
111
92
  * @returns 32-byte derived seed for child tree
112
93
  */
113
- function deriveChildTreeSeedJava(childSeed, childIndex) {
94
+ export function deriveChildTreeSeedJava(childSeed, childIndex) {
114
95
  const indexSerialized = serializeMiniNumber(childIndex);
115
96
  const seedSerialized = serializeMiniData(childSeed);
116
97
  return hashAllObjects(indexSerialized, seedSerialized);
@@ -126,9 +107,9 @@ function deriveChildTreeSeedJava(childSeed, childIndex) {
126
107
  * @param data - Raw bytes (will be serialized as MiniData)
127
108
  * @returns 32-byte SHA3-256 hash
128
109
  */
129
- function hashObject(data) {
110
+ export function hashObject(data) {
130
111
  const serialized = serializeMiniData(data);
131
- return (0, sha3_1.sha3_256)(serialized);
112
+ return sha3_256(serialized);
132
113
  }
133
114
  /**
134
115
  * Convert index to MiniData bytes matching Java's:
@@ -140,7 +121,7 @@ function hashObject(data) {
140
121
  * @param index - Non-negative integer (0, 1, 2, ...)
141
122
  * @returns Minimal byte representation of the index
142
123
  */
143
- function indexToMiniDataBytes(index) {
124
+ export function indexToMiniDataBytes(index) {
144
125
  if (index === 0) {
145
126
  return new Uint8Array([0x00]);
146
127
  }
@@ -168,7 +149,7 @@ function indexToMiniDataBytes(index) {
168
149
  * @param addressIndex - Address index (0, 1, 2, ... 63)
169
150
  * @returns 32-byte private seed for this address's TreeKey
170
151
  */
171
- function derivePerAddressSeed(baseSeed, addressIndex) {
152
+ export function derivePerAddressSeed(baseSeed, addressIndex) {
172
153
  // Step 1: Create modifier bytes from BigInteger representation of index
173
154
  const modifierBytes = indexToMiniDataBytes(addressIndex);
174
155
  // Step 2: Serialize both as MiniData (4-byte length prefix each)
@@ -178,20 +159,27 @@ function derivePerAddressSeed(baseSeed, addressIndex) {
178
159
  const combined = new Uint8Array(baseSeedSerialized.length + modifierSerialized.length);
179
160
  combined.set(baseSeedSerialized, 0);
180
161
  combined.set(modifierSerialized, baseSeedSerialized.length);
181
- return (0, sha3_1.sha3_256)(combined);
162
+ const result = sha3_256(combined);
163
+ // DIAGNOSTIC: Log first 8 bytes to detect bundle duplication or implementation differences
164
+ // Enable via: globalThis.TOTEM_SEED_DEBUG = true
165
+ if (typeof console !== 'undefined' && globalThis.TOTEM_SEED_DEBUG) {
166
+ const toHex = (b) => Array.from(b.slice(0, 8)).map(x => x.toString(16).padStart(2, '0')).join('');
167
+ console.log(`[derivePerAddressSeed] idx=${addressIndex} baseSeed[0:8]=${toHex(baseSeed)} -> result[0:8]=${toHex(result)}`);
168
+ }
169
+ return result;
182
170
  }
183
171
  /**
184
172
  * Serialize MiniNumber.ZERO - cached for performance
185
173
  * Returns: [0x00, 0x01, 0x00] = scale(0) + length(1) + value(0)
186
174
  */
187
- function serializeMiniNumberZERO() {
175
+ export function serializeMiniNumberZERO() {
188
176
  return new Uint8Array([0x00, 0x01, 0x00]);
189
177
  }
190
178
  /**
191
179
  * Serialize MiniNumber.ONE
192
180
  * Returns: [0x00, 0x01, 0x01] = scale(0) + length(1) + value(1)
193
181
  */
194
- function serializeMiniNumberONE() {
182
+ export function serializeMiniNumberONE() {
195
183
  return new Uint8Array([0x00, 0x01, 0x01]);
196
184
  }
197
185
  /**
@@ -202,8 +190,8 @@ function serializeMiniNumberONE() {
202
190
  * @param data - Hash bytes (max 64 bytes per MINIMA_MAX_HASH_LENGTH)
203
191
  * @returns Serialized bytes with 4-byte length prefix
204
192
  */
205
- function writeHashToStream(data) {
206
- return (0, Streamable_1.writeHashToStream)(data);
193
+ export function writeHashToStream(data) {
194
+ return streamableWriteHashToStream(data);
207
195
  }
208
196
  /**
209
197
  * Java hashAllObjects for MMRData hashing
@@ -223,7 +211,7 @@ function writeHashToStream(data) {
223
211
  * @param items - Pre-serialized items to concatenate and hash
224
212
  * @returns 32-byte SHA3-256 hash
225
213
  */
226
- function javaHashAllObjects(...items) {
214
+ export function javaHashAllObjects(...items) {
227
215
  const totalLength = items.reduce((sum, item) => sum + item.length, 0);
228
216
  const combined = new Uint8Array(totalLength);
229
217
  let offset = 0;
@@ -231,12 +219,12 @@ function javaHashAllObjects(...items) {
231
219
  combined.set(item, offset);
232
220
  offset += item.length;
233
221
  }
234
- return (0, sha3_1.sha3_256)(combined);
222
+ return sha3_256(combined);
235
223
  }
236
224
  /**
237
225
  * Create MMREntryNumber from bigint (common case for integer positions)
238
226
  */
239
- function createMMREntryNumber(value) {
227
+ export function createMMREntryNumber(value) {
240
228
  return { scale: 0, unscaled: value };
241
229
  }
242
230
  /**
@@ -249,7 +237,7 @@ function createMMREntryNumber(value) {
249
237
  * @param entry - MMREntryNumber to serialize
250
238
  * @returns Serialized bytes: MiniNumber(scale) + MiniData(unscaled bytes)
251
239
  */
252
- function serializeMMREntryNumber(entry) {
240
+ export function serializeMMREntryNumber(entry) {
253
241
  const scaleSerialized = serializeMiniNumber(entry.scale);
254
242
  const unscaledBytes = bigintToSignedBytes(entry.unscaled);
255
243
  const unscaledSerialized = serializeMiniData(unscaledBytes);
@@ -263,7 +251,7 @@ function serializeMMREntryNumber(entry) {
263
251
  * Uses the canonical implementation from Streamable.ts
264
252
  */
265
253
  function bigintToSignedBytes(n) {
266
- return (0, Streamable_1.bigIntToByteArray)(n);
254
+ return bigIntToByteArray(n);
267
255
  }
268
256
  /**
269
257
  * Serialize MMRData matching Java MMRData.writeDataStream()
@@ -275,7 +263,7 @@ function bigintToSignedBytes(n) {
275
263
  * @param mmrData - MMRData to serialize
276
264
  * @returns Serialized bytes: writeHashToStream(hash) + MiniNumber(value)
277
265
  */
278
- function serializeMMRData(mmrData) {
266
+ export function serializeMMRData(mmrData) {
279
267
  const hashSerialized = writeHashToStream(mmrData.data);
280
268
  const valueSerialized = serializeMiniNumber(Number(mmrData.value));
281
269
  const result = new Uint8Array(hashSerialized.length + valueSerialized.length);
@@ -295,7 +283,7 @@ function serializeMMRData(mmrData) {
295
283
  * @param entry - MMREntry to serialize
296
284
  * @returns Serialized bytes: MiniNumber(row) + MMREntryNumber + MMRData
297
285
  */
298
- function serializeMMREntry(entry) {
286
+ export function serializeMMREntry(entry) {
299
287
  const rowSerialized = serializeMiniNumber(entry.row);
300
288
  const entryNumberSerialized = serializeMMREntryNumber(entry.entryNumber);
301
289
  const mmrDataSerialized = serializeMMRData(entry.mmrData);
@@ -309,7 +297,23 @@ function serializeMMREntry(entry) {
309
297
  result.set(mmrDataSerialized, offset);
310
298
  return result;
311
299
  }
312
- function precomputeTransactionCoinID(inputs, outputs) {
300
+ /**
301
+ * Precompute output coin IDs before computing the transaction digest.
302
+ *
303
+ * CRITICAL: Java's txnsign command calls TxPoWGenerator.precomputeTransactionCoinID(txn)
304
+ * BEFORE calculateTransactionID(). This means the transaction digest that gets signed
305
+ * includes the PRECOMPUTED output coin IDs, not the placeholder 0x00.
306
+ *
307
+ * Formula: outputCoinID = SHA3-256( writeMiniData(input[0].coinID) || writeMiniNumber(outputIndex) )
308
+ * This matches Java's Crypto.hashObjects(baseCoinID, new MiniNumber(outputNum))
309
+ *
310
+ * Without this, the wallet signs a different digest than what the node verifies against,
311
+ * causing allsignaturesvalid=false on every transaction.
312
+ *
313
+ * @param inputs - Transaction inputs array, each must have a coinId (Uint8Array)
314
+ * @param outputs - Transaction outputs array, each will have its coinId mutated in-place
315
+ */
316
+ export function precomputeTransactionCoinID(inputs, outputs) {
313
317
  if (inputs.length === 0)
314
318
  return;
315
319
  const baseCoinId = inputs[0].coinId;
@@ -318,11 +322,11 @@ function precomputeTransactionCoinID(inputs, outputs) {
318
322
  `(placeholder?). Real coinId from CoinProof required for signing.`);
319
323
  }
320
324
  for (let i = 0; i < outputs.length; i++) {
321
- const baseCoinIdStream = (0, Streamable_1.writeMiniData)(baseCoinId);
322
- const outputIndexStream = (0, Streamable_1.writeMiniNumber)(BigInt(i));
325
+ const baseCoinIdStream = streamableWriteMiniData(baseCoinId);
326
+ const outputIndexStream = streamableWriteMiniNumber(BigInt(i));
323
327
  const combined = new Uint8Array(baseCoinIdStream.length + outputIndexStream.length);
324
328
  combined.set(baseCoinIdStream, 0);
325
329
  combined.set(outputIndexStream, baseCoinIdStream.length);
326
- outputs[i].coinId = (0, sha3_1.sha3_256)(combined);
330
+ outputs[i].coinId = sha3_256(combined);
327
331
  }
328
332
  }
package/src/mmr.d.ts CHANGED
@@ -7,6 +7,7 @@ export declare function serializeMMRProof(proof: {
7
7
  };
8
8
  }>;
9
9
  }, blockTime?: bigint): Bytes;
10
+ export declare const serializeRealMMRProof: typeof serializeMMRProof;
10
11
  export type Bytes = Uint8Array;
11
12
  /**
12
13
  * Byte-exact one-leaf MMR leaf used by Minima Address.java path:
@@ -147,13 +148,10 @@ export declare function verifyMMRProof(leafPubkey: Bytes, proof: MMRProof, expec
147
148
  *
148
149
  * @returns { proof: MMRProof, blockTime: bigint }
149
150
  */
150
- export declare function deserializeMMRProof(data: Bytes): {
151
- proof: MMRProof;
152
- blockTime: bigint;
153
- bytesRead: number;
154
- };
155
151
  export declare function parseMMRProofFromHex(data: Bytes): {
156
152
  proof: MMRProof;
157
153
  blockTime: bigint;
158
154
  bytesRead: number;
159
155
  };
156
+ /** @deprecated Use parseMMRProofFromHex */
157
+ export declare const deserializeMMRProof: typeof parseMMRProofFromHex;
package/src/mmr.js CHANGED
@@ -1,24 +1,12 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MMRTree = void 0;
4
- exports.serializeMMRProof = serializeMMRProof;
5
- exports.mmrLeafExact = mmrLeafExact;
6
- exports.mmrRootFromSingleLeaf = mmrRootFromSingleLeaf;
7
- exports.createMMRDataLeafNode = createMMRDataLeafNode;
8
- exports.createMMRDataParentNode = createMMRDataParentNode;
9
- exports.calculateProofRoot = calculateProofRoot;
10
- exports.verifyMMRProof = verifyMMRProof;
11
- exports.deserializeMMRProof = deserializeMMRProof;
12
- exports.parseMMRProofFromHex = deserializeMMRProof;
13
1
  // packages/totem-sdk/packages/core/src/mmr.ts
14
2
  // Full MMR implementation matching Minima's MMR.java, MMRData.java, and TreeKeyNode.java
15
- const sha3_1 = require("@noble/hashes/sha3");
16
- const javaStreamables_1 = require("./javaStreamables");
3
+ import { sha3_256 as nobleSha3 } from '@noble/hashes/sha3.js';
4
+ import { serializeMiniNumber, serializeMiniData, javaHashAllObjects } from "./javaStreamables.js";
17
5
  // Import canonical wire serialization from Streamable.ts (single source of truth)
18
- const Streamable_1 = require("./Streamable");
6
+ import { writeMMRProof } from "./Streamable.js";
19
7
  // Re-export for API compatibility (existing code imports from mmr.ts)
20
8
  // Using a wrapper function for better compatibility with dynamic imports
21
- function serializeMMRProof(proof, blockTime = 0n) {
9
+ export function serializeMMRProof(proof, blockTime = 0n) {
22
10
  // Convert to Streamable format and serialize
23
11
  const streamableProof = {
24
12
  blockTime: blockTime,
@@ -27,11 +15,12 @@ function serializeMMRProof(proof, blockTime = 0n) {
27
15
  mmrData: { data: c.mmrData.data, value: c.mmrData.value }
28
16
  }))
29
17
  };
30
- return (0, Streamable_1.writeMMRProof)(streamableProof);
18
+ return writeMMRProof(streamableProof);
31
19
  }
20
+ export const serializeRealMMRProof = serializeMMRProof;
32
21
  /** SHA3-256 helper returning 32 bytes */
33
22
  function sha3(data) {
34
- return sha3_1.sha3_256(data);
23
+ return nobleSha3(data);
35
24
  }
36
25
  /** concat utility */
37
26
  function concat(...parts) {
@@ -70,14 +59,14 @@ function encodeMiniStringUTF8(text) {
70
59
  * Byte-exact one-leaf MMR leaf used by Minima Address.java path:
71
60
  * sha3( MiniNumber.ZERO || MiniString(script) || MiniNumber.ZERO )
72
61
  */
73
- function mmrLeafExact(script) {
62
+ export function mmrLeafExact(script) {
74
63
  const zero = encodeMiniNumberZERO();
75
64
  const mstr = encodeMiniStringUTF8(script);
76
65
  const all = concat(zero, mstr, zero);
77
66
  return sha3(all); // 32-byte leaf hash
78
67
  }
79
68
  /** In a single-leaf MMR the root equals the leaf commitment. */
80
- function mmrRootFromSingleLeaf(script) {
69
+ export function mmrRootFromSingleLeaf(script) {
81
70
  return mmrLeafExact(script);
82
71
  }
83
72
  /**
@@ -97,20 +86,20 @@ function mmrRootFromSingleLeaf(script) {
97
86
  * 2. MiniData (pubkey): [4-byte length] + [bytes] (writeDataStream, NOT writeHashToStream)
98
87
  * 3. MiniNumber.ZERO: [0x00, 0x01, 0x00]
99
88
  */
100
- function createMMRDataLeafNode(pubkey, sumValue = 0n) {
89
+ export function createMMRDataLeafNode(pubkey, sumValue = 0n) {
101
90
  // Use cached ZERO serialization for efficiency
102
91
  const zero = new Uint8Array([0x00, 0x01, 0x00]); // MiniNumber.ZERO
103
92
  // IMPORTANT: hashAllObjects uses writeDataStream which is 4-byte length prefixed
104
- const pubkeySerialized = (0, javaStreamables_1.serializeMiniData)(pubkey);
93
+ const pubkeySerialized = serializeMiniData(pubkey);
105
94
  // For sumValue, serialize as MiniNumber
106
95
  let sumSerialized;
107
96
  if (sumValue === 0n) {
108
97
  sumSerialized = new Uint8Array([0x00, 0x01, 0x00]); // MiniNumber.ZERO
109
98
  }
110
99
  else {
111
- sumSerialized = (0, javaStreamables_1.serializeMiniNumber)(Number(sumValue));
100
+ sumSerialized = serializeMiniNumber(Number(sumValue));
112
101
  }
113
- const hash = (0, javaStreamables_1.javaHashAllObjects)(zero, pubkeySerialized, sumSerialized);
102
+ const hash = javaHashAllObjects(zero, pubkeySerialized, sumSerialized);
114
103
  return { data: hash, value: sumValue };
115
104
  }
116
105
  /**
@@ -130,22 +119,22 @@ function createMMRDataLeafNode(pubkey, sumValue = 0n) {
130
119
  * 3. MiniData (right.data): [4-byte length] + [bytes]
131
120
  * 4. MiniNumber (sumvalue): serialized MiniNumber
132
121
  */
133
- function createMMRDataParentNode(left, right) {
122
+ export function createMMRDataParentNode(left, right) {
134
123
  const sumValue = left.value + right.value;
135
124
  // MiniNumber.ONE: [0x00, 0x01, 0x01]
136
125
  const one = new Uint8Array([0x00, 0x01, 0x01]);
137
126
  // Serialize left and right data as MiniData (4-byte length-prefixed)
138
- const leftDataSerialized = (0, javaStreamables_1.serializeMiniData)(left.data);
139
- const rightDataSerialized = (0, javaStreamables_1.serializeMiniData)(right.data);
127
+ const leftDataSerialized = serializeMiniData(left.data);
128
+ const rightDataSerialized = serializeMiniData(right.data);
140
129
  // Serialize sum value
141
130
  let sumSerialized;
142
131
  if (sumValue === 0n) {
143
132
  sumSerialized = new Uint8Array([0x00, 0x01, 0x00]); // MiniNumber.ZERO
144
133
  }
145
134
  else {
146
- sumSerialized = (0, javaStreamables_1.serializeMiniNumber)(Number(sumValue));
135
+ sumSerialized = serializeMiniNumber(Number(sumValue));
147
136
  }
148
- const hash = (0, javaStreamables_1.javaHashAllObjects)(one, leftDataSerialized, rightDataSerialized, sumSerialized);
137
+ const hash = javaHashAllObjects(one, leftDataSerialized, rightDataSerialized, sumSerialized);
149
138
  return { data: hash, value: sumValue };
150
139
  }
151
140
  /**
@@ -154,12 +143,10 @@ function createMMRDataParentNode(left, right) {
154
143
  *
155
144
  * This matches TreeKeyNode.java which always uses 64 leaves (2^6)
156
145
  */
157
- class MMRTree {
158
- constructor() {
159
- this.entries = new Map();
160
- this.leafCount = 0;
161
- this.maxRow = 0;
162
- }
146
+ export class MMRTree {
147
+ entries = new Map();
148
+ leafCount = 0;
149
+ maxRow = 0;
163
150
  getKey(row, entryNumber) {
164
151
  return `${row}:${entryNumber}`;
165
152
  }
@@ -252,7 +239,6 @@ class MMRTree {
252
239
  return entry?.mmrData || null;
253
240
  }
254
241
  }
255
- exports.MMRTree = MMRTree;
256
242
  /**
257
243
  * Calculate root from leaf data and proof
258
244
  * Matches SignatureProof.getRootPublicKey() in Java
@@ -261,7 +247,7 @@ exports.MMRTree = MMRTree;
261
247
  * MMRData pubentry = MMRData.CreateMMRDataLeafNode(mPublicKey, MiniNumber.ZERO);
262
248
  * return mProof.calculateProof(pubentry).getData();
263
249
  */
264
- function calculateProofRoot(leafData, proof) {
250
+ export function calculateProofRoot(leafData, proof) {
265
251
  let current = leafData;
266
252
  for (const chunk of proof.chunks) {
267
253
  if (chunk.isLeft) {
@@ -278,7 +264,7 @@ function calculateProofRoot(leafData, proof) {
278
264
  /**
279
265
  * Verify a proof: check that leaf + proof computes to expected root
280
266
  */
281
- function verifyMMRProof(leafPubkey, proof, expectedRoot) {
267
+ export function verifyMMRProof(leafPubkey, proof, expectedRoot) {
282
268
  const leafData = createMMRDataLeafNode(leafPubkey, 0n);
283
269
  const computedRoot = calculateProofRoot(leafData, proof);
284
270
  if (computedRoot.length !== expectedRoot.length)
@@ -304,7 +290,7 @@ function verifyMMRProof(leafPubkey, proof, expectedRoot) {
304
290
  *
305
291
  * @returns { proof: MMRProof, blockTime: bigint }
306
292
  */
307
- function deserializeMMRProof(data) {
293
+ export function parseMMRProofFromHex(data) {
308
294
  let offset = 0;
309
295
  // Read blockTime as MiniNumber
310
296
  const { value: blockTime, bytesRead: btRead } = readMiniNumber(data, offset);
@@ -350,3 +336,5 @@ function readMiniNumber(data, offset) {
350
336
  // For TreeKey MMR, scale is always 0
351
337
  return { value, bytesRead: 2 + length };
352
338
  }
339
+ /** @deprecated Use parseMMRProofFromHex */
340
+ export const deserializeMMRProof = parseMMRProofFromHex;
@@ -0,0 +1,81 @@
1
+ import type { MMRProofChunk, MMRProof } from '../mmr.js';
2
+ export type { MMRProof };
3
+ export type StateVariableType = 'STATE' | 'PREVSTATE' | 'SAMESTATE';
4
+ export interface StateValue {
5
+ port: number;
6
+ value: string | bigint | Uint8Array | boolean;
7
+ type: 'bool' | 'number' | 'hex' | 'string';
8
+ }
9
+ export interface VerifyOutExpectation {
10
+ inputIndex: number | '@INPUT';
11
+ outputAddress: string;
12
+ amount: string | bigint;
13
+ tokenId: string;
14
+ keepState: boolean;
15
+ }
16
+ export type ScriptType = 'signedby' | 'multisig' | 'multisig_mofn' | 'timelock' | 'htlc' | 'mast' | 'exchange' | 'vault' | 'flashcash' | 'slowcash' | 'stateful' | 'custom';
17
+ export interface ScriptDescriptor {
18
+ address: string;
19
+ scriptType: ScriptType;
20
+ script: string;
21
+ wotsRootPublicKey?: string;
22
+ mastProof?: MMRProof;
23
+ extraScripts?: Map<string, string>;
24
+ stateVariables?: StateValue[];
25
+ storeState?: boolean;
26
+ verifyOutExpectations?: VerifyOutExpectation[];
27
+ timelockBlock?: bigint;
28
+ htlcHash?: string;
29
+ htlcPreimage?: string;
30
+ multisigKeys?: string[];
31
+ multisigThreshold?: number;
32
+ externalSignatures?: ExternalSignature[];
33
+ }
34
+ export interface ExternalSignature {
35
+ publicKey: string;
36
+ signature: string;
37
+ proof?: MMRProof;
38
+ signatureType: 'wots' | 'standard';
39
+ validated?: boolean;
40
+ }
41
+ export interface ScriptCatalogEntry {
42
+ address: string;
43
+ script: string;
44
+ scriptType: ScriptType;
45
+ createdAt: number;
46
+ lastUsed: number;
47
+ }
48
+ export interface ScriptProofResult {
49
+ script: string;
50
+ proof: MMRProof;
51
+ serialized: Uint8Array;
52
+ }
53
+ export interface TransactionRoundState {
54
+ round: number;
55
+ previousRound: number;
56
+ preservedPorts: number[];
57
+ newStates: StateValue[];
58
+ }
59
+ export interface FlatMMRProofChunk {
60
+ isLeft: boolean;
61
+ data: Uint8Array;
62
+ }
63
+ export interface LegacyMMRProof {
64
+ blockTime: bigint;
65
+ proofChain: FlatMMRProofChunk[];
66
+ }
67
+ export declare function convertFlatChunkToSDK(chunk: FlatMMRProofChunk): MMRProofChunk;
68
+ export declare function convertLegacyProofToSDK(legacy: LegacyMMRProof): {
69
+ proof: MMRProof;
70
+ blockTime: bigint;
71
+ };
72
+ export declare function createEmptyMMRProof(): MMRProof;
73
+ export declare function createSignedByDescriptor(address: string, wotsRootPublicKey: string): ScriptDescriptor;
74
+ export declare function createMultisigDescriptor(address: string, publicKey1: string, publicKey2: string, ownPublicKey: string): ScriptDescriptor;
75
+ export declare function createMofNMultisigDescriptor(address: string, threshold: number, publicKeys: string[], ownPublicKey: string): ScriptDescriptor;
76
+ export declare function createTimelockDescriptor(address: string, publicKey: string, unlockBlock: bigint): ScriptDescriptor;
77
+ export declare function createHTLCDescriptor(address: string, ownerPublicKey: string, recipientPublicKey: string, hashLock: string, timeoutBlock: bigint, isOwner: boolean, preimage?: string): ScriptDescriptor;
78
+ export declare function createMASTDescriptor(address: string, rootHash: string, branchScript: string, branchProof: string, wotsPublicKey?: string): ScriptDescriptor;
79
+ export declare function createExchangeDescriptor(address: string, ownerPublicKey: string, desiredAddress: string, desiredAmount: string, desiredTokenId: string): ScriptDescriptor;
80
+ export declare function createFlashCashDescriptor(address: string, ownerPublicKey: string, interestMultiplier?: string): ScriptDescriptor;
81
+ export declare function createSlowCashDescriptor(address: string, ownerPublicKey: string, withdrawalPercent?: string, cooldownBlocks?: bigint): ScriptDescriptor;
@@ -0,0 +1,145 @@
1
+ function kissHex(hex) {
2
+ const raw = hex.startsWith('0x') || hex.startsWith('0X') ? hex.slice(2) : hex;
3
+ return '0x' + raw.toUpperCase();
4
+ }
5
+ export function convertFlatChunkToSDK(chunk) {
6
+ return {
7
+ isLeft: chunk.isLeft,
8
+ mmrData: { data: chunk.data, value: 0n }
9
+ };
10
+ }
11
+ export function convertLegacyProofToSDK(legacy) {
12
+ return {
13
+ proof: {
14
+ chunks: legacy.proofChain.map(convertFlatChunkToSDK)
15
+ },
16
+ blockTime: legacy.blockTime
17
+ };
18
+ }
19
+ export function createEmptyMMRProof() {
20
+ return { chunks: [] };
21
+ }
22
+ export function createSignedByDescriptor(address, wotsRootPublicKey) {
23
+ return {
24
+ address,
25
+ scriptType: 'signedby',
26
+ script: `RETURN SIGNEDBY(${kissHex(wotsRootPublicKey)})`,
27
+ wotsRootPublicKey,
28
+ mastProof: createEmptyMMRProof(),
29
+ storeState: false
30
+ };
31
+ }
32
+ export function createMultisigDescriptor(address, publicKey1, publicKey2, ownPublicKey) {
33
+ return {
34
+ address,
35
+ scriptType: 'multisig',
36
+ script: `RETURN SIGNEDBY(${kissHex(publicKey1)}) AND SIGNEDBY(${kissHex(publicKey2)})`,
37
+ wotsRootPublicKey: ownPublicKey,
38
+ multisigKeys: [publicKey1, publicKey2],
39
+ multisigThreshold: 2,
40
+ mastProof: createEmptyMMRProof(),
41
+ storeState: false
42
+ };
43
+ }
44
+ export function createMofNMultisigDescriptor(address, threshold, publicKeys, ownPublicKey) {
45
+ const formattedKeys = publicKeys.map(pk => kissHex(pk)).join(' ');
46
+ return {
47
+ address,
48
+ scriptType: 'multisig_mofn',
49
+ script: `RETURN MULTISIG(${threshold} ${formattedKeys})`,
50
+ wotsRootPublicKey: ownPublicKey,
51
+ multisigKeys: publicKeys,
52
+ multisigThreshold: threshold,
53
+ mastProof: createEmptyMMRProof(),
54
+ storeState: false
55
+ };
56
+ }
57
+ export function createTimelockDescriptor(address, publicKey, unlockBlock) {
58
+ return {
59
+ address,
60
+ scriptType: 'timelock',
61
+ script: `RETURN SIGNEDBY(${kissHex(publicKey)}) AND @BLOCK GT ${unlockBlock}`,
62
+ wotsRootPublicKey: publicKey,
63
+ timelockBlock: unlockBlock,
64
+ mastProof: createEmptyMMRProof(),
65
+ storeState: false
66
+ };
67
+ }
68
+ export function createHTLCDescriptor(address, ownerPublicKey, recipientPublicKey, hashLock, timeoutBlock, isOwner, preimage) {
69
+ const script = `IF @BLOCK GT ${timeoutBlock} AND SIGNEDBY(${kissHex(ownerPublicKey)}) THEN RETURN TRUE ENDIF RETURN (SIGNEDBY(${kissHex(recipientPublicKey)}) AND SHA3(STATE(1)) EQ ${kissHex(hashLock)})`;
70
+ const descriptor = {
71
+ address,
72
+ scriptType: 'htlc',
73
+ script,
74
+ wotsRootPublicKey: isOwner ? ownerPublicKey : recipientPublicKey,
75
+ htlcHash: hashLock,
76
+ timelockBlock: timeoutBlock,
77
+ mastProof: createEmptyMMRProof(),
78
+ storeState: false
79
+ };
80
+ if (preimage) {
81
+ descriptor.htlcPreimage = preimage;
82
+ descriptor.stateVariables = [{ port: 1, value: preimage, type: 'string' }];
83
+ }
84
+ return descriptor;
85
+ }
86
+ export function createMASTDescriptor(address, rootHash, branchScript, branchProof, wotsPublicKey) {
87
+ return {
88
+ address,
89
+ scriptType: 'mast',
90
+ script: `MAST ${kissHex(rootHash)}`,
91
+ wotsRootPublicKey: wotsPublicKey,
92
+ extraScripts: new Map([[branchScript, branchProof]]),
93
+ mastProof: createEmptyMMRProof(),
94
+ storeState: false
95
+ };
96
+ }
97
+ export function createExchangeDescriptor(address, ownerPublicKey, desiredAddress, desiredAmount, desiredTokenId) {
98
+ const ownerPk = kissHex(ownerPublicKey);
99
+ const script = `IF SIGNEDBY(PREVSTATE(0)) THEN RETURN TRUE ENDIF ASSERT VERIFYOUT(@INPUT PREVSTATE(1) PREVSTATE(2) PREVSTATE(3) TRUE) RETURN TRUE`;
100
+ return {
101
+ address,
102
+ scriptType: 'exchange',
103
+ script,
104
+ wotsRootPublicKey: ownerPublicKey,
105
+ stateVariables: [
106
+ { port: 0, value: ownerPk, type: 'hex' },
107
+ { port: 1, value: desiredAddress, type: 'hex' },
108
+ { port: 2, value: desiredAmount, type: 'number' },
109
+ { port: 3, value: desiredTokenId, type: 'hex' }
110
+ ],
111
+ verifyOutExpectations: [{
112
+ inputIndex: '@INPUT',
113
+ outputAddress: desiredAddress,
114
+ amount: desiredAmount,
115
+ tokenId: desiredTokenId,
116
+ keepState: true
117
+ }],
118
+ mastProof: createEmptyMMRProof(),
119
+ storeState: true
120
+ };
121
+ }
122
+ export function createFlashCashDescriptor(address, ownerPublicKey, interestMultiplier = '1.01') {
123
+ const script = `IF SIGNEDBY(PREVSTATE(1)) THEN RETURN TRUE ENDIF ASSERT SAMESTATE(1 1) RETURN VERIFYOUT(@INPUT @ADDRESS @AMOUNT*${interestMultiplier} @TOKENID TRUE)`;
124
+ return {
125
+ address,
126
+ scriptType: 'flashcash',
127
+ script,
128
+ wotsRootPublicKey: ownerPublicKey,
129
+ stateVariables: [{ port: 1, value: ownerPublicKey, type: 'hex' }],
130
+ mastProof: createEmptyMMRProof(),
131
+ storeState: true
132
+ };
133
+ }
134
+ export function createSlowCashDescriptor(address, ownerPublicKey, withdrawalPercent = '0.9', cooldownBlocks = 10000n) {
135
+ const script = `IF @COINAGE LT ${cooldownBlocks} THEN RETURN FALSE ENDIF ASSERT SIGNEDBY(${kissHex(ownerPublicKey)}) AND VERIFYOUT(@INPUT @ADDRESS @AMOUNT*${withdrawalPercent} @TOKENID TRUE)`;
136
+ return {
137
+ address,
138
+ scriptType: 'slowcash',
139
+ script,
140
+ wotsRootPublicKey: ownerPublicKey,
141
+ timelockBlock: cooldownBlocks,
142
+ mastProof: createEmptyMMRProof(),
143
+ storeState: false
144
+ };
145
+ }