@totemsdk/core 1.0.9 → 1.0.10

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 (144) 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.js +94 -64
  39. package/package.json +31 -6
  40. package/src/Streamable.d.ts +0 -268
  41. package/src/Streamable.js +0 -416
  42. package/src/Streamable.ts +0 -567
  43. package/src/__tests__/Streamable.parity.test.ts +0 -422
  44. package/src/__tests__/perAddressDerivation.parity.test.ts +0 -152
  45. package/src/__tests__/roottree-prepare.test.ts +0 -101
  46. package/src/__tests__/wots-parity.test.ts +0 -289
  47. package/src/adapters/index.d.ts +0 -190
  48. package/src/adapters/index.js +0 -117
  49. package/src/adapters/index.ts +0 -301
  50. package/src/adapters/types.ts +0 -235
  51. package/src/addr.oracle.test.ts +0 -25
  52. package/src/address.test.ts +0 -55
  53. package/src/binio.ts +0 -21
  54. package/src/bip39.d.ts +0 -91
  55. package/src/bip39.js +0 -427
  56. package/src/bip39.ts +0 -432
  57. package/src/derive.d.ts +0 -2
  58. package/src/derive.js +0 -13
  59. package/src/derive.ts +0 -11
  60. package/src/index.d.ts +0 -26
  61. package/src/index.js +0 -128
  62. package/src/index.test.ts +0 -5
  63. package/src/index.ts +0 -221
  64. package/src/javaStreamables.d.ts +0 -233
  65. package/src/javaStreamables.js +0 -332
  66. package/src/javaStreamables.ts +0 -403
  67. package/src/lease/LeaseMonitor.d.ts +0 -44
  68. package/src/lease/LeaseMonitor.js +0 -111
  69. package/src/lease/LeaseMonitor.ts +0 -157
  70. package/src/lease/LeaseStore.d.ts +0 -57
  71. package/src/lease/LeaseStore.js +0 -148
  72. package/src/lease/LeaseStore.ts +0 -203
  73. package/src/lease/WatermarkStore.d.ts +0 -61
  74. package/src/lease/WatermarkStore.js +0 -206
  75. package/src/lease/WatermarkStore.ts +0 -270
  76. package/src/lease/index.d.ts +0 -14
  77. package/src/lease/index.js +0 -22
  78. package/src/lease/index.ts +0 -41
  79. package/src/lease-client.d.ts +0 -31
  80. package/src/lease-client.js +0 -44
  81. package/src/lease-client.ts +0 -69
  82. package/src/minima32.d.ts +0 -10
  83. package/src/minima32.js +0 -113
  84. package/src/minima32.test.ts +0 -11
  85. package/src/minima32.ts +0 -127
  86. package/src/minimaWireSerializer.d.ts +0 -189
  87. package/src/minimaWireSerializer.js +0 -311
  88. package/src/minimaWireSerializer.test.ts +0 -466
  89. package/src/minimaWireSerializer.ts +0 -117
  90. package/src/mmr.d.ts +0 -157
  91. package/src/mmr.js +0 -340
  92. package/src/mmr.oracle.test.ts +0 -28
  93. package/src/mmr.ts +0 -429
  94. package/src/mx.test.ts +0 -25
  95. package/src/mx.ts +0 -1
  96. package/src/params.d.ts +0 -29
  97. package/src/params.d.ts.map +0 -1
  98. package/src/params.js +0 -20
  99. package/src/params.js.map +0 -1
  100. package/src/params.ts +0 -44
  101. package/src/script.d.ts +0 -7
  102. package/src/script.js +0 -27
  103. package/src/script.ts +0 -24
  104. package/src/scripts/contract-helpers.ts +0 -609
  105. package/src/scripts/dapp-types.ts +0 -240
  106. package/src/scripts/index.ts +0 -22
  107. package/src/scripts/types.d.ts +0 -81
  108. package/src/scripts/types.js +0 -145
  109. package/src/scripts/types.ts +0 -247
  110. package/src/scripts/witness-serializer.ts +0 -384
  111. package/src/transaction.ts +0 -430
  112. package/src/treekey.d.ts +0 -383
  113. package/src/treekey.js +0 -774
  114. package/src/treekey.parity.test.ts +0 -459
  115. package/src/treekey.ts +0 -975
  116. package/src/tx/TransactionLifecycle.d.ts +0 -55
  117. package/src/tx/TransactionLifecycle.js +0 -188
  118. package/src/tx/TransactionLifecycle.ts +0 -280
  119. package/src/tx/TransactionReceiptStore.d.ts +0 -36
  120. package/src/tx/TransactionReceiptStore.js +0 -89
  121. package/src/tx/TransactionReceiptStore.ts +0 -112
  122. package/src/tx/TransactionService.d.ts +0 -31
  123. package/src/tx/TransactionService.js +0 -140
  124. package/src/tx/TransactionService.ts +0 -252
  125. package/src/tx/index.d.ts +0 -13
  126. package/src/tx/index.js +0 -20
  127. package/src/tx/index.ts +0 -44
  128. package/src/tx/types.d.ts +0 -80
  129. package/src/tx/types.js +0 -6
  130. package/src/tx/types.ts +0 -130
  131. package/src/util.d.ts +0 -1
  132. package/src/util.js +0 -5
  133. package/src/util.ts +0 -1
  134. package/src/utils.d.ts +0 -8
  135. package/src/utils.js +0 -42
  136. package/src/utils.ts +0 -38
  137. package/src/verify.ts +0 -210
  138. package/src/version.ts +0 -13
  139. package/src/wots.d.ts +0 -224
  140. package/src/wots.d.ts.map +0 -1
  141. package/src/wots.js +0 -565
  142. package/src/wots.js.map +0 -1
  143. package/src/wots.ts +0 -651
  144. 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
- }