@totemsdk/core 1.0.9 → 1.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +5 -5
  3. package/dist/Streamable.js +54 -31
  4. package/dist/adapters/index.js +18 -8
  5. package/dist/adapters/types.js +19 -8
  6. package/dist/binio.js +5 -1
  7. package/dist/bip39.js +24 -14
  8. package/dist/derive.js +11 -7
  9. package/dist/index.js +130 -22
  10. package/dist/javaStreamables.js +49 -30
  11. package/dist/lease/LeaseMonitor.js +7 -3
  12. package/dist/lease/LeaseStore.js +7 -3
  13. package/dist/lease/WatermarkStore.js +7 -3
  14. package/dist/lease/index.js +13 -4
  15. package/dist/lease-client.js +8 -3
  16. package/dist/minima32.js +22 -13
  17. package/dist/minimaWireSerializer.js +20 -14
  18. package/dist/mmr.js +35 -23
  19. package/dist/mx.js +10 -1
  20. package/dist/params.js +9 -5
  21. package/dist/script.js +12 -7
  22. package/dist/scripts/contract-helpers.js +37 -26
  23. package/dist/scripts/dapp-types.js +11 -6
  24. package/dist/scripts/index.js +38 -4
  25. package/dist/scripts/types.js +26 -12
  26. package/dist/scripts/witness-serializer.js +48 -30
  27. package/dist/transaction.js +55 -46
  28. package/dist/treekey.js +74 -58
  29. package/dist/tx/TransactionLifecycle.js +11 -5
  30. package/dist/tx/TransactionReceiptStore.js +7 -3
  31. package/dist/tx/TransactionService.js +14 -10
  32. package/dist/tx/index.js +11 -3
  33. package/dist/tx/types.js +2 -1
  34. package/dist/util.js +5 -1
  35. package/dist/utils.js +12 -5
  36. package/dist/verify.js +36 -25
  37. package/dist/version.js +5 -2
  38. package/dist/wots.d.ts +2 -2
  39. package/dist/wots.js +94 -64
  40. package/package.json +50 -6
  41. package/src/Streamable.d.ts +0 -268
  42. package/src/Streamable.js +0 -416
  43. package/src/Streamable.ts +0 -567
  44. package/src/__tests__/Streamable.parity.test.ts +0 -422
  45. package/src/__tests__/perAddressDerivation.parity.test.ts +0 -152
  46. package/src/__tests__/roottree-prepare.test.ts +0 -101
  47. package/src/__tests__/wots-parity.test.ts +0 -289
  48. package/src/adapters/index.d.ts +0 -190
  49. package/src/adapters/index.js +0 -117
  50. package/src/adapters/index.ts +0 -301
  51. package/src/adapters/types.ts +0 -235
  52. package/src/addr.oracle.test.ts +0 -25
  53. package/src/address.test.ts +0 -55
  54. package/src/binio.ts +0 -21
  55. package/src/bip39.d.ts +0 -91
  56. package/src/bip39.js +0 -427
  57. package/src/bip39.ts +0 -432
  58. package/src/derive.d.ts +0 -2
  59. package/src/derive.js +0 -13
  60. package/src/derive.ts +0 -11
  61. package/src/index.d.ts +0 -26
  62. package/src/index.js +0 -128
  63. package/src/index.test.ts +0 -5
  64. package/src/index.ts +0 -221
  65. package/src/javaStreamables.d.ts +0 -233
  66. package/src/javaStreamables.js +0 -332
  67. package/src/javaStreamables.ts +0 -403
  68. package/src/lease/LeaseMonitor.d.ts +0 -44
  69. package/src/lease/LeaseMonitor.js +0 -111
  70. package/src/lease/LeaseMonitor.ts +0 -157
  71. package/src/lease/LeaseStore.d.ts +0 -57
  72. package/src/lease/LeaseStore.js +0 -148
  73. package/src/lease/LeaseStore.ts +0 -203
  74. package/src/lease/WatermarkStore.d.ts +0 -61
  75. package/src/lease/WatermarkStore.js +0 -206
  76. package/src/lease/WatermarkStore.ts +0 -270
  77. package/src/lease/index.d.ts +0 -14
  78. package/src/lease/index.js +0 -22
  79. package/src/lease/index.ts +0 -41
  80. package/src/lease-client.d.ts +0 -31
  81. package/src/lease-client.js +0 -44
  82. package/src/lease-client.ts +0 -69
  83. package/src/minima32.d.ts +0 -10
  84. package/src/minima32.js +0 -113
  85. package/src/minima32.test.ts +0 -11
  86. package/src/minima32.ts +0 -127
  87. package/src/minimaWireSerializer.d.ts +0 -189
  88. package/src/minimaWireSerializer.js +0 -311
  89. package/src/minimaWireSerializer.test.ts +0 -466
  90. package/src/minimaWireSerializer.ts +0 -117
  91. package/src/mmr.d.ts +0 -157
  92. package/src/mmr.js +0 -340
  93. package/src/mmr.oracle.test.ts +0 -28
  94. package/src/mmr.ts +0 -429
  95. package/src/mx.test.ts +0 -25
  96. package/src/mx.ts +0 -1
  97. package/src/params.d.ts +0 -29
  98. package/src/params.d.ts.map +0 -1
  99. package/src/params.js +0 -20
  100. package/src/params.js.map +0 -1
  101. package/src/params.ts +0 -44
  102. package/src/script.d.ts +0 -7
  103. package/src/script.js +0 -27
  104. package/src/script.ts +0 -24
  105. package/src/scripts/contract-helpers.ts +0 -609
  106. package/src/scripts/dapp-types.ts +0 -240
  107. package/src/scripts/index.ts +0 -22
  108. package/src/scripts/types.d.ts +0 -81
  109. package/src/scripts/types.js +0 -145
  110. package/src/scripts/types.ts +0 -247
  111. package/src/scripts/witness-serializer.ts +0 -384
  112. package/src/transaction.ts +0 -430
  113. package/src/treekey.d.ts +0 -383
  114. package/src/treekey.js +0 -774
  115. package/src/treekey.parity.test.ts +0 -459
  116. package/src/treekey.ts +0 -975
  117. package/src/tx/TransactionLifecycle.d.ts +0 -55
  118. package/src/tx/TransactionLifecycle.js +0 -188
  119. package/src/tx/TransactionLifecycle.ts +0 -280
  120. package/src/tx/TransactionReceiptStore.d.ts +0 -36
  121. package/src/tx/TransactionReceiptStore.js +0 -89
  122. package/src/tx/TransactionReceiptStore.ts +0 -112
  123. package/src/tx/TransactionService.d.ts +0 -31
  124. package/src/tx/TransactionService.js +0 -140
  125. package/src/tx/TransactionService.ts +0 -252
  126. package/src/tx/index.d.ts +0 -13
  127. package/src/tx/index.js +0 -20
  128. package/src/tx/index.ts +0 -44
  129. package/src/tx/types.d.ts +0 -80
  130. package/src/tx/types.js +0 -6
  131. package/src/tx/types.ts +0 -130
  132. package/src/util.d.ts +0 -1
  133. package/src/util.js +0 -5
  134. package/src/util.ts +0 -1
  135. package/src/utils.d.ts +0 -8
  136. package/src/utils.js +0 -42
  137. package/src/utils.ts +0 -38
  138. package/src/verify.ts +0 -210
  139. package/src/version.ts +0 -13
  140. package/src/wots.d.ts +0 -224
  141. package/src/wots.d.ts.map +0 -1
  142. package/src/wots.js +0 -565
  143. package/src/wots.js.map +0 -1
  144. package/src/wots.ts +0 -651
  145. package/test-vectors.json +0 -45
@@ -1,430 +0,0 @@
1
- /**
2
- * Transaction Serialization & Digest Computation
3
- *
4
- * Port of the extension's MinimaTransactionBuilder serialization logic
5
- * to the SDK core for full parity with the Totem wallet extension.
6
- *
7
- * Matches Minima Java's Transaction.writeDataStream() and Coin.writeDataStream() exactly.
8
- *
9
- * CRITICAL: Before computing the transaction digest for signing, you MUST call
10
- * precomputeTransactionCoinID() to set output coin IDs. Without this, the signed
11
- * digest won't match what the Minima node verifies, causing allsignaturesvalid=false.
12
- */
13
-
14
- import { sha3_256 } from '@noble/hashes/sha3.js';
15
- import {
16
- writeMiniNumber,
17
- writeMiniData,
18
- writeHashToStream,
19
- writeMiniByte,
20
- writeMMREntryNumber,
21
- concat,
22
- hexToBytes,
23
- bytesToHex,
24
- } from './Streamable.js';
25
-
26
- const ZERO_TXPOWID = new Uint8Array([0x00]);
27
-
28
- const STATETYPE_HEX = 1;
29
- const STATETYPE_NUMBER = 2;
30
- const STATETYPE_STRING = 4;
31
- const STATETYPE_BOOL = 8;
32
-
33
- export interface MinimaTransaction {
34
- linkHash: Uint8Array;
35
- inputs: MinimaCoin[];
36
- outputs: MinimaCoin[];
37
- state: StateVariable[];
38
- }
39
-
40
- export interface MinimaCoin {
41
- coinId: Uint8Array;
42
- address: Uint8Array;
43
- amount: string;
44
- tokenId: Uint8Array;
45
- token: MinimaToken | null;
46
- storeState: boolean;
47
- state: StateVariable[] | RawStateVariable[];
48
- mmrEntryNumber: bigint;
49
- spent: boolean;
50
- created: bigint;
51
- rawAmountBytes?: Uint8Array;
52
- rawMmrEntryBytes?: Uint8Array;
53
- rawBlockCreatedBytes?: Uint8Array;
54
- rawTokenData?: Uint8Array;
55
- }
56
-
57
- export interface ParsedMiniNumber {
58
- scale: number;
59
- unscaledValue: bigint;
60
- }
61
-
62
- export interface MinimaToken {
63
- coinId: Uint8Array;
64
- scale: number;
65
- totalAmount: bigint;
66
- name: Uint8Array;
67
- script: Uint8Array;
68
- created?: bigint;
69
- }
70
-
71
- export interface StateVariable {
72
- port: number;
73
- value: string | bigint | boolean | Uint8Array;
74
- type: 'bool' | 'number' | 'hex' | 'string';
75
- }
76
-
77
- export interface RawStateVariable {
78
- port: number;
79
- type: number;
80
- rawData: Uint8Array;
81
- }
82
-
83
- export interface CoinProofData {
84
- coinId: Uint8Array;
85
- address: Uint8Array;
86
- rawAmountBytes: Uint8Array;
87
- tokenId: Uint8Array;
88
- storeState: boolean;
89
- mmrEntryNumber: bigint;
90
- rawMmrEntryBytes: Uint8Array;
91
- spent: boolean;
92
- blockCreated: bigint;
93
- rawBlockCreatedBytes: Uint8Array;
94
- state: RawStateVariable[];
95
- rawTokenData?: Uint8Array;
96
- }
97
-
98
- export interface SpendableCoinInput {
99
- coinId: string;
100
- address: string;
101
- amount: string;
102
- tokenId: string;
103
- rawAmountBytes?: Uint8Array;
104
- coinProofData?: CoinProofData;
105
- }
106
-
107
- export interface TransactionBuildResult {
108
- transaction: MinimaTransaction;
109
- digestTx: Uint8Array;
110
- digestTxHex: string;
111
- serialized: Uint8Array;
112
- serializedHex: string;
113
- }
114
-
115
- export function parseDecimalToMiniNumber(decimal: string): ParsedMiniNumber {
116
- if (!decimal || decimal === '') {
117
- return { scale: 0, unscaledValue: 0n };
118
- }
119
-
120
- if (decimal.includes('e') || decimal.includes('E')) {
121
- throw new Error(`Scientific notation not supported: "${decimal}". Convert to plain decimal first.`);
122
- }
123
-
124
- let isNegative = false;
125
- let cleaned = decimal.trim();
126
- if (cleaned.startsWith('-')) {
127
- isNegative = true;
128
- cleaned = cleaned.slice(1);
129
- }
130
-
131
- const dotIndex = cleaned.indexOf('.');
132
-
133
- let scale: number;
134
- let unscaledStr: string;
135
-
136
- if (dotIndex === -1) {
137
- scale = 0;
138
- unscaledStr = cleaned;
139
- } else {
140
- const wholePart = cleaned.slice(0, dotIndex);
141
- const fracPart = cleaned.slice(dotIndex + 1);
142
- scale = fracPart.length;
143
- unscaledStr = wholePart + fracPart;
144
- }
145
-
146
- unscaledStr = unscaledStr.replace(/^0+/, '') || '0';
147
-
148
- let unscaledValue = BigInt(unscaledStr);
149
- if (isNegative && unscaledValue !== 0n) {
150
- unscaledValue = -unscaledValue;
151
- }
152
-
153
- return { scale, unscaledValue };
154
- }
155
-
156
- function encodeParsedMiniNumber(parsed: ParsedMiniNumber): Uint8Array {
157
- return writeMiniNumber(parsed.unscaledValue, parsed.scale);
158
- }
159
-
160
- function normalizeAddressToHex(addr: string): string {
161
- if (!addr) {
162
- return '0x00';
163
- }
164
- const trimmed = addr.trim();
165
-
166
- const hexAddr = trimmed.startsWith('0x') ? trimmed : '0x' + trimmed;
167
- const cleanHex = hexAddr.slice(2);
168
- if (!/^[0-9a-fA-F]*$/.test(cleanHex)) {
169
- throw new Error(`Invalid hex address: contains non-hex characters`);
170
- }
171
- if (cleanHex.length % 2 !== 0) {
172
- throw new Error(`Invalid hex address: odd length (${cleanHex.length} chars)`);
173
- }
174
-
175
- return hexAddr;
176
- }
177
-
178
- function serializeStateVariable(sv: StateVariable): Uint8Array {
179
- if (sv.port < 0 || sv.port > 255) {
180
- throw new Error(`StateVariable port must be 0-255, got ${sv.port}`);
181
- }
182
-
183
- const portByte = new Uint8Array([sv.port]);
184
-
185
- let typeByte: Uint8Array;
186
- let dataBytes: Uint8Array;
187
-
188
- switch (sv.type) {
189
- case 'bool':
190
- typeByte = new Uint8Array([STATETYPE_BOOL]);
191
- if (typeof sv.value === 'boolean') {
192
- dataBytes = new Uint8Array([sv.value ? 1 : 0]);
193
- } else if (typeof sv.value === 'string') {
194
- dataBytes = new Uint8Array([sv.value.toUpperCase() === 'TRUE' ? 1 : 0]);
195
- } else {
196
- throw new Error(`Invalid bool StateVariable value: ${sv.value}`);
197
- }
198
- break;
199
-
200
- case 'number':
201
- typeByte = new Uint8Array([STATETYPE_NUMBER]);
202
- if (typeof sv.value === 'bigint') {
203
- dataBytes = writeMiniNumber(sv.value);
204
- } else if (typeof sv.value === 'string') {
205
- dataBytes = writeMiniNumber(BigInt(sv.value));
206
- } else {
207
- throw new Error(`Invalid number StateVariable value: ${sv.value}`);
208
- }
209
- break;
210
-
211
- case 'hex':
212
- typeByte = new Uint8Array([STATETYPE_HEX]);
213
- if (typeof sv.value === 'string') {
214
- const normalizedHex = normalizeAddressToHex(sv.value);
215
- dataBytes = writeMiniData(hexToBytes(normalizedHex));
216
- } else if (sv.value instanceof Uint8Array) {
217
- dataBytes = writeMiniData(sv.value);
218
- } else {
219
- throw new Error(`Invalid hex StateVariable value: ${sv.value}`);
220
- }
221
- break;
222
-
223
- case 'string':
224
- typeByte = new Uint8Array([STATETYPE_STRING]);
225
- if (typeof sv.value === 'string') {
226
- let bracketedValue = sv.value;
227
- if (!sv.value.startsWith('[') || !sv.value.endsWith(']')) {
228
- bracketedValue = `[${sv.value}]`;
229
- }
230
- const utf8Bytes = new TextEncoder().encode(bracketedValue);
231
- dataBytes = writeMiniData(utf8Bytes);
232
- } else {
233
- throw new Error(`Invalid string StateVariable value: ${sv.value}`);
234
- }
235
- break;
236
-
237
- default:
238
- throw new Error(`Unknown StateVariable type: ${(sv as any).type}`);
239
- }
240
-
241
- return concat(portByte, typeByte, dataBytes);
242
- }
243
-
244
- function serializeToken(token: MinimaToken): Uint8Array {
245
- // Java Token.writeDataStream() order: coinId, script, scale, totalAmount, name, created
246
- const parts: Uint8Array[] = [];
247
- parts.push(writeHashToStream(token.coinId));
248
- parts.push(writeMiniData(token.script));
249
- parts.push(writeMiniNumber(BigInt(token.scale)));
250
- parts.push(writeMiniNumber(token.totalAmount, 0));
251
- parts.push(writeMiniData(token.name));
252
- parts.push(writeMiniNumber(token.created ?? 0n));
253
- return concat(...parts);
254
- }
255
-
256
- export function serializeCoin(coin: MinimaCoin): Uint8Array {
257
- const parts: Uint8Array[] = [];
258
-
259
- parts.push(writeHashToStream(coin.coinId));
260
- parts.push(writeHashToStream(coin.address));
261
-
262
- let amountBytes: Uint8Array;
263
- if (coin.rawAmountBytes && coin.rawAmountBytes.length > 0) {
264
- amountBytes = coin.rawAmountBytes;
265
- } else {
266
- const parsedAmount = parseDecimalToMiniNumber(coin.amount);
267
- amountBytes = encodeParsedMiniNumber(parsedAmount);
268
- }
269
- parts.push(amountBytes);
270
-
271
- parts.push(writeMiniData(coin.tokenId));
272
- parts.push(writeMiniByte(coin.storeState));
273
-
274
- let mmrBytes: Uint8Array;
275
- if (coin.rawMmrEntryBytes && coin.rawMmrEntryBytes.length > 0) {
276
- mmrBytes = coin.rawMmrEntryBytes;
277
- } else {
278
- mmrBytes = writeMMREntryNumber(coin.mmrEntryNumber);
279
- }
280
- parts.push(mmrBytes);
281
-
282
- parts.push(writeMiniByte(coin.spent));
283
-
284
- let createdBytes: Uint8Array;
285
- if (coin.rawBlockCreatedBytes && coin.rawBlockCreatedBytes.length > 0) {
286
- createdBytes = coin.rawBlockCreatedBytes;
287
- } else {
288
- createdBytes = writeMiniNumber(coin.created);
289
- }
290
- parts.push(createdBytes);
291
-
292
- const stateCountBytes = writeMiniNumber(BigInt(coin.state.length));
293
- parts.push(stateCountBytes);
294
-
295
- for (const sv of coin.state) {
296
- let svBytes: Uint8Array;
297
- if ('rawData' in sv) {
298
- const raw = sv as RawStateVariable;
299
- const portByte = new Uint8Array([raw.port]);
300
- const typeByte = new Uint8Array([raw.type]);
301
- svBytes = concat(portByte, typeByte, raw.rawData);
302
- } else {
303
- svBytes = serializeStateVariable(sv as StateVariable);
304
- }
305
- parts.push(svBytes);
306
- }
307
-
308
- if (coin.rawTokenData && coin.rawTokenData.length > 0) {
309
- parts.push(writeMiniByte(true));
310
- parts.push(coin.rawTokenData);
311
- } else if (coin.token) {
312
- parts.push(writeMiniByte(true));
313
- parts.push(serializeToken(coin.token));
314
- } else {
315
- parts.push(writeMiniByte(false));
316
- }
317
-
318
- return concat(...parts);
319
- }
320
-
321
- export function serializeTransaction(tx: MinimaTransaction): Uint8Array {
322
- const parts: Uint8Array[] = [];
323
-
324
- parts.push(writeMiniNumber(BigInt(tx.inputs.length)));
325
-
326
- for (const input of tx.inputs) {
327
- parts.push(serializeCoin(input));
328
- }
329
-
330
- parts.push(writeMiniNumber(BigInt(tx.outputs.length)));
331
-
332
- for (const output of tx.outputs) {
333
- parts.push(serializeCoin(output));
334
- }
335
-
336
- parts.push(writeMiniNumber(BigInt(tx.state.length)));
337
-
338
- for (const sv of tx.state) {
339
- parts.push(serializeStateVariable(sv));
340
- }
341
-
342
- parts.push(writeHashToStream(tx.linkHash));
343
-
344
- return concat(...parts);
345
- }
346
-
347
- export function computeTransactionDigest(tx: MinimaTransaction): Uint8Array {
348
- const serialized = serializeTransaction(tx);
349
- return sha3_256(serialized);
350
- }
351
-
352
- export function precomputeTransactionCoinID(tx: MinimaTransaction): void {
353
- if (tx.inputs.length === 0) return;
354
-
355
- const baseCoinId = tx.inputs[0].coinId;
356
-
357
- if (baseCoinId.length < 2) {
358
- throw new Error(
359
- `Cannot precompute output coinIDs: input[0].coinId is ${baseCoinId.length} byte(s) ` +
360
- `(placeholder?). Real coinId from CoinProof required for signing.`
361
- );
362
- }
363
-
364
- for (let i = 0; i < tx.outputs.length; i++) {
365
- const baseCoinIdStream = writeMiniData(baseCoinId);
366
- const outputIndexStream = writeMiniNumber(BigInt(i));
367
- const combined = concat(baseCoinIdStream, outputIndexStream);
368
- tx.outputs[i].coinId = sha3_256(combined);
369
- }
370
- }
371
-
372
- export function createDefaultTransaction(): MinimaTransaction {
373
- return {
374
- linkHash: ZERO_TXPOWID,
375
- inputs: [],
376
- outputs: [],
377
- state: [],
378
- };
379
- }
380
-
381
- export function buildMinimaCoin(opts: {
382
- coinId?: Uint8Array;
383
- address: Uint8Array;
384
- amount: string;
385
- tokenId?: Uint8Array;
386
- storeState?: boolean;
387
- state?: StateVariable[];
388
- mmrEntryNumber?: bigint;
389
- spent?: boolean;
390
- created?: bigint;
391
- rawAmountBytes?: Uint8Array;
392
- rawMmrEntryBytes?: Uint8Array;
393
- rawBlockCreatedBytes?: Uint8Array;
394
- coinProofData?: CoinProofData;
395
- }): MinimaCoin {
396
- if (opts.coinProofData) {
397
- const cpd = opts.coinProofData;
398
- return {
399
- coinId: cpd.coinId,
400
- address: cpd.address,
401
- amount: opts.amount,
402
- tokenId: cpd.tokenId,
403
- token: null,
404
- storeState: cpd.storeState,
405
- state: cpd.state,
406
- mmrEntryNumber: cpd.mmrEntryNumber,
407
- spent: cpd.spent,
408
- created: cpd.blockCreated,
409
- rawAmountBytes: cpd.rawAmountBytes,
410
- rawMmrEntryBytes: cpd.rawMmrEntryBytes,
411
- rawBlockCreatedBytes: cpd.rawBlockCreatedBytes,
412
- };
413
- }
414
-
415
- return {
416
- coinId: opts.coinId || new Uint8Array([0x00]),
417
- address: opts.address,
418
- amount: opts.amount,
419
- tokenId: opts.tokenId || new Uint8Array([0x00]),
420
- token: null,
421
- storeState: opts.storeState ?? false,
422
- state: opts.state || [],
423
- mmrEntryNumber: opts.mmrEntryNumber ?? 0n,
424
- spent: opts.spent ?? false,
425
- created: opts.created ?? 0n,
426
- rawAmountBytes: opts.rawAmountBytes,
427
- rawMmrEntryBytes: opts.rawMmrEntryBytes,
428
- rawBlockCreatedBytes: opts.rawBlockCreatedBytes,
429
- };
430
- }