@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.
- package/LICENSE +21 -0
- package/README.md +5 -5
- package/dist/Streamable.js +54 -31
- package/dist/adapters/index.js +18 -8
- package/dist/adapters/types.js +19 -8
- package/dist/binio.js +5 -1
- package/dist/bip39.js +24 -14
- package/dist/derive.js +11 -7
- package/dist/index.js +130 -22
- package/dist/javaStreamables.js +49 -30
- package/dist/lease/LeaseMonitor.js +7 -3
- package/dist/lease/LeaseStore.js +7 -3
- package/dist/lease/WatermarkStore.js +7 -3
- package/dist/lease/index.js +13 -4
- package/dist/lease-client.js +8 -3
- package/dist/minima32.js +22 -13
- package/dist/minimaWireSerializer.js +20 -14
- package/dist/mmr.js +35 -23
- package/dist/mx.js +10 -1
- package/dist/params.js +9 -5
- package/dist/script.js +12 -7
- package/dist/scripts/contract-helpers.js +37 -26
- package/dist/scripts/dapp-types.js +11 -6
- package/dist/scripts/index.js +38 -4
- package/dist/scripts/types.js +26 -12
- package/dist/scripts/witness-serializer.js +48 -30
- package/dist/transaction.js +55 -46
- package/dist/treekey.js +74 -58
- package/dist/tx/TransactionLifecycle.js +11 -5
- package/dist/tx/TransactionReceiptStore.js +7 -3
- package/dist/tx/TransactionService.js +14 -10
- package/dist/tx/index.js +11 -3
- package/dist/tx/types.js +2 -1
- package/dist/util.js +5 -1
- package/dist/utils.js +12 -5
- package/dist/verify.js +36 -25
- package/dist/version.js +5 -2
- package/dist/wots.js +94 -64
- package/package.json +31 -6
- package/src/Streamable.d.ts +0 -268
- package/src/Streamable.js +0 -416
- package/src/Streamable.ts +0 -567
- package/src/__tests__/Streamable.parity.test.ts +0 -422
- package/src/__tests__/perAddressDerivation.parity.test.ts +0 -152
- package/src/__tests__/roottree-prepare.test.ts +0 -101
- package/src/__tests__/wots-parity.test.ts +0 -289
- package/src/adapters/index.d.ts +0 -190
- package/src/adapters/index.js +0 -117
- package/src/adapters/index.ts +0 -301
- package/src/adapters/types.ts +0 -235
- package/src/addr.oracle.test.ts +0 -25
- package/src/address.test.ts +0 -55
- package/src/binio.ts +0 -21
- package/src/bip39.d.ts +0 -91
- package/src/bip39.js +0 -427
- package/src/bip39.ts +0 -432
- package/src/derive.d.ts +0 -2
- package/src/derive.js +0 -13
- package/src/derive.ts +0 -11
- package/src/index.d.ts +0 -26
- package/src/index.js +0 -128
- package/src/index.test.ts +0 -5
- package/src/index.ts +0 -221
- package/src/javaStreamables.d.ts +0 -233
- package/src/javaStreamables.js +0 -332
- package/src/javaStreamables.ts +0 -403
- package/src/lease/LeaseMonitor.d.ts +0 -44
- package/src/lease/LeaseMonitor.js +0 -111
- package/src/lease/LeaseMonitor.ts +0 -157
- package/src/lease/LeaseStore.d.ts +0 -57
- package/src/lease/LeaseStore.js +0 -148
- package/src/lease/LeaseStore.ts +0 -203
- package/src/lease/WatermarkStore.d.ts +0 -61
- package/src/lease/WatermarkStore.js +0 -206
- package/src/lease/WatermarkStore.ts +0 -270
- package/src/lease/index.d.ts +0 -14
- package/src/lease/index.js +0 -22
- package/src/lease/index.ts +0 -41
- package/src/lease-client.d.ts +0 -31
- package/src/lease-client.js +0 -44
- package/src/lease-client.ts +0 -69
- package/src/minima32.d.ts +0 -10
- package/src/minima32.js +0 -113
- package/src/minima32.test.ts +0 -11
- package/src/minima32.ts +0 -127
- package/src/minimaWireSerializer.d.ts +0 -189
- package/src/minimaWireSerializer.js +0 -311
- package/src/minimaWireSerializer.test.ts +0 -466
- package/src/minimaWireSerializer.ts +0 -117
- package/src/mmr.d.ts +0 -157
- package/src/mmr.js +0 -340
- package/src/mmr.oracle.test.ts +0 -28
- package/src/mmr.ts +0 -429
- package/src/mx.test.ts +0 -25
- package/src/mx.ts +0 -1
- package/src/params.d.ts +0 -29
- package/src/params.d.ts.map +0 -1
- package/src/params.js +0 -20
- package/src/params.js.map +0 -1
- package/src/params.ts +0 -44
- package/src/script.d.ts +0 -7
- package/src/script.js +0 -27
- package/src/script.ts +0 -24
- package/src/scripts/contract-helpers.ts +0 -609
- package/src/scripts/dapp-types.ts +0 -240
- package/src/scripts/index.ts +0 -22
- package/src/scripts/types.d.ts +0 -81
- package/src/scripts/types.js +0 -145
- package/src/scripts/types.ts +0 -247
- package/src/scripts/witness-serializer.ts +0 -384
- package/src/transaction.ts +0 -430
- package/src/treekey.d.ts +0 -383
- package/src/treekey.js +0 -774
- package/src/treekey.parity.test.ts +0 -459
- package/src/treekey.ts +0 -975
- package/src/tx/TransactionLifecycle.d.ts +0 -55
- package/src/tx/TransactionLifecycle.js +0 -188
- package/src/tx/TransactionLifecycle.ts +0 -280
- package/src/tx/TransactionReceiptStore.d.ts +0 -36
- package/src/tx/TransactionReceiptStore.js +0 -89
- package/src/tx/TransactionReceiptStore.ts +0 -112
- package/src/tx/TransactionService.d.ts +0 -31
- package/src/tx/TransactionService.js +0 -140
- package/src/tx/TransactionService.ts +0 -252
- package/src/tx/index.d.ts +0 -13
- package/src/tx/index.js +0 -20
- package/src/tx/index.ts +0 -44
- package/src/tx/types.d.ts +0 -80
- package/src/tx/types.js +0 -6
- package/src/tx/types.ts +0 -130
- package/src/util.d.ts +0 -1
- package/src/util.js +0 -5
- package/src/util.ts +0 -1
- package/src/utils.d.ts +0 -8
- package/src/utils.js +0 -42
- package/src/utils.ts +0 -38
- package/src/verify.ts +0 -210
- package/src/version.ts +0 -13
- package/src/wots.d.ts +0 -224
- package/src/wots.d.ts.map +0 -1
- package/src/wots.js +0 -565
- package/src/wots.js.map +0 -1
- package/src/wots.ts +0 -651
- package/test-vectors.json +0 -45
package/src/lease-client.ts
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Totem <-> Axia hardened WOTS helpers (no deps on server internals).
|
|
3
|
-
*/
|
|
4
|
-
export type PrepareArgs = {
|
|
5
|
-
txId: string;
|
|
6
|
-
rootPublicKey: string; // 0x… (32-byte pk digest hex)
|
|
7
|
-
to: string; // Mx…
|
|
8
|
-
amount: string; // decimal string
|
|
9
|
-
tokenId?: string; // default "0x00"
|
|
10
|
-
burn?: string | null; // optional
|
|
11
|
-
digestL2?: string | null; // optional — if you precompute trees
|
|
12
|
-
digestL3?: string | null; // optional — if you precompute trees
|
|
13
|
-
ttlMs?: number; // default 20000
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export type PrepareResp = {
|
|
17
|
-
leaseToken: string; // JWT
|
|
18
|
-
lease: { addressIndex: number; l1: number; l2: number };
|
|
19
|
-
txId: string;
|
|
20
|
-
digestTx?: string | null; // optional
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export async function prepareLease(apiUrl: string, apiKey: string, args: PrepareArgs): Promise<PrepareResp> {
|
|
24
|
-
const res = await fetch(`${apiUrl}/v1/wots-hardened/prepare`, {
|
|
25
|
-
method: 'POST',
|
|
26
|
-
headers: { 'content-type': 'application/json', 'x-api-key': apiKey },
|
|
27
|
-
body: JSON.stringify({
|
|
28
|
-
tokenId: "0x00",
|
|
29
|
-
burn: null,
|
|
30
|
-
digestL2: null,
|
|
31
|
-
digestL3: null,
|
|
32
|
-
ttlMs: 20000,
|
|
33
|
-
...args
|
|
34
|
-
})
|
|
35
|
-
});
|
|
36
|
-
if (!res.ok) throw new Error(`prepareLease ${res.status}`);
|
|
37
|
-
const raw = await res.json() as {
|
|
38
|
-
leaseToken: string;
|
|
39
|
-
lease?: { addressIndex: number; l1: number; l2: number };
|
|
40
|
-
addressIndex?: number;
|
|
41
|
-
l1?: number;
|
|
42
|
-
l2?: number;
|
|
43
|
-
txId: string;
|
|
44
|
-
digestTx?: string | null;
|
|
45
|
-
};
|
|
46
|
-
const lease = raw.lease ?? { addressIndex: raw.addressIndex ?? 0, l1: raw.l1 ?? 0, l2: raw.l2 ?? 0 };
|
|
47
|
-
return {
|
|
48
|
-
leaseToken: raw.leaseToken,
|
|
49
|
-
lease,
|
|
50
|
-
txId: raw.txId,
|
|
51
|
-
digestTx: raw.digestTx ?? null
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export async function finalizeLease(apiUrl: string, apiKey: string, leaseToken: string, signedHex: string) {
|
|
56
|
-
const res = await fetch(`${apiUrl}/v1/wots-hardened/finalize`, {
|
|
57
|
-
method: 'POST',
|
|
58
|
-
headers: { 'content-type': 'application/json', 'x-api-key': apiKey },
|
|
59
|
-
body: JSON.stringify({ leaseToken, signedHex })
|
|
60
|
-
});
|
|
61
|
-
const text = await res.text();
|
|
62
|
-
return { status: res.status, body: text };
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/** lane tuple -> flat WOTS index (64^3 space) */
|
|
66
|
-
export function flatIndexFromLanes(addressIndex: number, l1: number, l2: number): number {
|
|
67
|
-
if (addressIndex|l1|l2 & ~63) throw new Error('lane out of range');
|
|
68
|
-
return (addressIndex * 64 * 64) + (l1 * 64) + l2;
|
|
69
|
-
}
|
package/src/minima32.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export declare function encodeMxRadix32Frame(frame: Uint8Array): string;
|
|
2
|
-
export declare function decodeMxRadix32Frame(mx: string): Uint8Array;
|
|
3
|
-
/** Encode raw 32 bytes to Mx address with frame and checksum */
|
|
4
|
-
export declare function encodeMx(root32: Uint8Array): string;
|
|
5
|
-
/** Decode Mx address to raw 32 bytes, validating frame and checksum */
|
|
6
|
-
export declare function decodeMx(mx: string): Uint8Array;
|
|
7
|
-
/** Make an Mx address from a hex string (legacy API compatibility) */
|
|
8
|
-
export declare function makeMinimaAddress(hex: string): string;
|
|
9
|
-
/** Convert an Mx address back to uppercase hex (legacy API compatibility) */
|
|
10
|
-
export declare function convertMinimaAddress(mx: string): string;
|
package/src/minima32.js
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// Minima "Mx" Base32 — matches org.minima.utils.BaseConverter.encode32/decode32
|
|
3
|
-
// Source behavior: BigInteger radix-32, then i→w, l→y, o→z, uppercased, prefixed with "Mx".
|
|
4
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
-
exports.encodeMxRadix32Frame = encodeMxRadix32Frame;
|
|
6
|
-
exports.decodeMxRadix32Frame = decodeMxRadix32Frame;
|
|
7
|
-
exports.encodeMx = encodeMx;
|
|
8
|
-
exports.decodeMx = decodeMx;
|
|
9
|
-
exports.makeMinimaAddress = makeMinimaAddress;
|
|
10
|
-
exports.convertMinimaAddress = convertMinimaAddress;
|
|
11
|
-
function bytesToBigInt(bytes) {
|
|
12
|
-
let x = 0n;
|
|
13
|
-
for (const b of bytes)
|
|
14
|
-
x = (x << 8n) | BigInt(b);
|
|
15
|
-
return x;
|
|
16
|
-
}
|
|
17
|
-
function bigIntToBytes(x) {
|
|
18
|
-
if (x === 0n)
|
|
19
|
-
return new Uint8Array([0]); // not normally hit for framed addresses
|
|
20
|
-
let hex = x.toString(16);
|
|
21
|
-
if (hex.length % 2)
|
|
22
|
-
hex = '0' + hex;
|
|
23
|
-
const out = new Uint8Array(hex.length / 2);
|
|
24
|
-
for (let i = 0; i < out.length; i++) {
|
|
25
|
-
out[i] = parseInt(hex.slice(2 * i, 2 * i + 2), 16);
|
|
26
|
-
}
|
|
27
|
-
return out;
|
|
28
|
-
}
|
|
29
|
-
function encodeMxRadix32Frame(frame) {
|
|
30
|
-
let s = bytesToBigInt(frame).toString(32).toLowerCase();
|
|
31
|
-
// JAR swaps (avoid ambiguous letters) then uppercase and add prefix
|
|
32
|
-
s = s.replace(/i/g, 'w').replace(/l/g, 'y').replace(/o/g, 'z');
|
|
33
|
-
return 'Mx' + s.toUpperCase();
|
|
34
|
-
}
|
|
35
|
-
function decodeMxRadix32Frame(mx) {
|
|
36
|
-
let s = mx.trim().toLowerCase();
|
|
37
|
-
if (s.startsWith('mx'))
|
|
38
|
-
s = s.slice(2);
|
|
39
|
-
s = s.replace(/w/g, 'i').replace(/y/g, 'l').replace(/z/g, 'o'); // reverse swaps
|
|
40
|
-
// parse base-32 by hand (radix 32)
|
|
41
|
-
let x = 0n;
|
|
42
|
-
for (const ch of s) {
|
|
43
|
-
const v = parseInt(ch, 32);
|
|
44
|
-
if (Number.isNaN(v))
|
|
45
|
-
throw new Error(`Invalid base32 character: ${ch}`);
|
|
46
|
-
x = x * 32n + BigInt(v);
|
|
47
|
-
}
|
|
48
|
-
return bigIntToBytes(x);
|
|
49
|
-
}
|
|
50
|
-
// Import SHA3 for checksum calculation
|
|
51
|
-
const sha3_1 = require("@noble/hashes/sha3");
|
|
52
|
-
/** Encode raw 32 bytes to Mx address with frame and checksum */
|
|
53
|
-
function encodeMx(root32) {
|
|
54
|
-
if (root32.length !== 32) {
|
|
55
|
-
throw new Error(`Expected 32 bytes, got ${root32.length}`);
|
|
56
|
-
}
|
|
57
|
-
// Build frame: [sentinel(1), length(2), data(32), checksum(4)]
|
|
58
|
-
const frame = new Uint8Array(1 + 2 + 32 + 4);
|
|
59
|
-
frame[0] = 0x01; // Sentinel byte
|
|
60
|
-
frame[1] = 0; // Length high byte
|
|
61
|
-
frame[2] = 32; // Length low byte
|
|
62
|
-
frame.set(root32, 3);
|
|
63
|
-
// Calculate checksum of the raw 32 bytes
|
|
64
|
-
const chk = sha3_1.sha3_256(root32);
|
|
65
|
-
frame.set(chk.slice(0, 4), 35);
|
|
66
|
-
return encodeMxRadix32Frame(frame);
|
|
67
|
-
}
|
|
68
|
-
/** Decode Mx address to raw 32 bytes, validating frame and checksum */
|
|
69
|
-
function decodeMx(mx) {
|
|
70
|
-
const frame = decodeMxRadix32Frame(mx);
|
|
71
|
-
// Validate frame structure
|
|
72
|
-
if (frame[0] !== 0x01) {
|
|
73
|
-
throw new Error(`Invalid sentinel byte: ${frame[0]}`);
|
|
74
|
-
}
|
|
75
|
-
const len = (frame[1] << 8) | frame[2];
|
|
76
|
-
if (len !== 32) {
|
|
77
|
-
throw new Error(`Invalid length: ${len}, expected 32`);
|
|
78
|
-
}
|
|
79
|
-
const root32 = frame.slice(3, 35);
|
|
80
|
-
const checksum = frame.slice(35, 39);
|
|
81
|
-
// Validate checksum
|
|
82
|
-
const expectedChk = sha3_1.sha3_256(root32);
|
|
83
|
-
const expected = expectedChk.slice(0, 4);
|
|
84
|
-
for (let i = 0; i < 4; i++) {
|
|
85
|
-
if (checksum[i] !== expected[i]) {
|
|
86
|
-
throw new Error('Invalid checksum');
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
return root32;
|
|
90
|
-
}
|
|
91
|
-
// Aliases for backward compatibility
|
|
92
|
-
function hexToBytes(hex) {
|
|
93
|
-
let h = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
94
|
-
if (h.length % 2)
|
|
95
|
-
h = "0" + h;
|
|
96
|
-
const out = new Uint8Array(h.length / 2);
|
|
97
|
-
for (let i = 0; i < out.length; i++)
|
|
98
|
-
out[i] = parseInt(h.slice(i * 2, i * 2 + 2), 16);
|
|
99
|
-
return out;
|
|
100
|
-
}
|
|
101
|
-
function bytesToHex(bytes) {
|
|
102
|
-
return Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('').toUpperCase();
|
|
103
|
-
}
|
|
104
|
-
/** Make an Mx address from a hex string (legacy API compatibility) */
|
|
105
|
-
function makeMinimaAddress(hex) {
|
|
106
|
-
const bytes = hexToBytes(hex);
|
|
107
|
-
return encodeMx(bytes);
|
|
108
|
-
}
|
|
109
|
-
/** Convert an Mx address back to uppercase hex (legacy API compatibility) */
|
|
110
|
-
function convertMinimaAddress(mx) {
|
|
111
|
-
const bytes = decodeMx(mx);
|
|
112
|
-
return bytesToHex(bytes);
|
|
113
|
-
}
|
package/src/minima32.test.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { encodeMxRadix32Frame, decodeMxRadix32Frame } from './minima32';
|
|
3
|
-
|
|
4
|
-
describe('Minima radix-32 with swaps', () => {
|
|
5
|
-
it('roundtrips arbitrary frames', () => {
|
|
6
|
-
const frame = Uint8Array.from([0x01, 0x00, 0x02, 0xaa, 0xff, 0xde, 0xad, 0xbe, 0xef].slice(0, 6));
|
|
7
|
-
const mx = encodeMxRadix32Frame(frame);
|
|
8
|
-
const back = decodeMxRadix32Frame(mx);
|
|
9
|
-
expect([...back]).toEqual([...frame]);
|
|
10
|
-
});
|
|
11
|
-
});
|
package/src/minima32.ts
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
// Minima "Mx" Base32 — matches org.minima.utils.BaseConverter.encode32/decode32
|
|
2
|
-
// Source behavior: BigInteger radix-32, then i→w, l→y, o→z, uppercased, prefixed with "Mx".
|
|
3
|
-
|
|
4
|
-
function bytesToBigInt(bytes: Uint8Array): bigint {
|
|
5
|
-
let x = 0n;
|
|
6
|
-
for (const b of bytes) x = (x << 8n) | BigInt(b);
|
|
7
|
-
return x;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
function bigIntToBytes(x: bigint): Uint8Array {
|
|
11
|
-
if (x === 0n) return new Uint8Array([0]); // not normally hit for framed addresses
|
|
12
|
-
let hex = x.toString(16);
|
|
13
|
-
if (hex.length % 2) hex = '0' + hex;
|
|
14
|
-
const out = new Uint8Array(hex.length / 2);
|
|
15
|
-
for (let i = 0; i < out.length; i++) {
|
|
16
|
-
out[i] = parseInt(hex.slice(2 * i, 2 * i + 2), 16);
|
|
17
|
-
}
|
|
18
|
-
return out;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function encodeMxRadix32Frame(frame: Uint8Array): string {
|
|
22
|
-
let s = bytesToBigInt(frame).toString(32).toLowerCase();
|
|
23
|
-
// JAR swaps (avoid ambiguous letters) then uppercase and add prefix
|
|
24
|
-
s = s.replace(/i/g, 'w').replace(/l/g, 'y').replace(/o/g, 'z');
|
|
25
|
-
return 'Mx' + s.toUpperCase();
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export function decodeMxRadix32Frame(mx: string): Uint8Array {
|
|
29
|
-
let s = mx.trim().toLowerCase();
|
|
30
|
-
if (s.startsWith('mx')) s = s.slice(2);
|
|
31
|
-
s = s.replace(/w/g, 'i').replace(/y/g, 'l').replace(/z/g, 'o'); // reverse swaps
|
|
32
|
-
|
|
33
|
-
// parse base-32 by hand (radix 32)
|
|
34
|
-
let x = 0n;
|
|
35
|
-
for (const ch of s) {
|
|
36
|
-
const v = parseInt(ch, 32);
|
|
37
|
-
if (Number.isNaN(v)) throw new Error(`Invalid base32 character: ${ch}`);
|
|
38
|
-
x = x * 32n + BigInt(v);
|
|
39
|
-
}
|
|
40
|
-
return bigIntToBytes(x);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
import { sha3_256 as nobleSha3 } from '@noble/hashes/sha3.js';
|
|
44
|
-
|
|
45
|
-
/** Encode raw 32 bytes to Mx address with frame and checksum */
|
|
46
|
-
export function makeMxAddress(root32: Uint8Array): string {
|
|
47
|
-
if (root32.length !== 32) {
|
|
48
|
-
throw new Error(`Expected 32 bytes, got ${root32.length}`);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Build frame: [sentinel(1), length(2), data(32), checksum(4)]
|
|
52
|
-
const frame = new Uint8Array(1 + 2 + 32 + 4);
|
|
53
|
-
frame[0] = 0x01; // Sentinel byte
|
|
54
|
-
frame[1] = 0; // Length high byte
|
|
55
|
-
frame[2] = 32; // Length low byte
|
|
56
|
-
frame.set(root32, 3);
|
|
57
|
-
|
|
58
|
-
// Calculate checksum of the raw 32 bytes
|
|
59
|
-
const chk = nobleSha3(root32);
|
|
60
|
-
frame.set(chk.slice(0, 4), 35);
|
|
61
|
-
|
|
62
|
-
return encodeMxRadix32Frame(frame);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/** Decode Mx address to raw 32 bytes, validating frame and checksum */
|
|
66
|
-
export function parseMxAddress(mx: string): Uint8Array {
|
|
67
|
-
const frame = decodeMxRadix32Frame(mx);
|
|
68
|
-
|
|
69
|
-
// Validate frame structure
|
|
70
|
-
if (frame[0] !== 0x01) {
|
|
71
|
-
throw new Error(`Invalid sentinel byte: ${frame[0]}`);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const len = (frame[1] << 8) | frame[2];
|
|
75
|
-
if (len !== 32) {
|
|
76
|
-
throw new Error(`Invalid length: ${len}, expected 32`);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const root32 = frame.slice(3, 35);
|
|
80
|
-
const checksum = frame.slice(35, 39);
|
|
81
|
-
|
|
82
|
-
// Validate checksum
|
|
83
|
-
const expectedChk = nobleSha3(root32);
|
|
84
|
-
const expected = expectedChk.slice(0, 4);
|
|
85
|
-
|
|
86
|
-
for (let i = 0; i < 4; i++) {
|
|
87
|
-
if (checksum[i] !== expected[i]) {
|
|
88
|
-
throw new Error('Invalid checksum');
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return root32;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Aliases for backward compatibility
|
|
96
|
-
function hexToBytes(hex: string): Uint8Array {
|
|
97
|
-
let h = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
98
|
-
if (h.length % 2) h = "0" + h;
|
|
99
|
-
const out = new Uint8Array(h.length / 2);
|
|
100
|
-
for (let i = 0; i < out.length; i++) out[i] = parseInt(h.slice(i * 2, i * 2 + 2), 16);
|
|
101
|
-
return out;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function bytesToHex(bytes: Uint8Array): string {
|
|
105
|
-
return Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('').toUpperCase();
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/** Make an Mx address from a hex string (legacy API compatibility) */
|
|
109
|
-
export function hexToMx(hex: string): string {
|
|
110
|
-
const bytes = hexToBytes(hex);
|
|
111
|
-
return makeMxAddress(bytes);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/** Convert an Mx address back to uppercase hex (legacy API compatibility) */
|
|
115
|
-
export function mxToHex(mx: string): string {
|
|
116
|
-
const bytes = parseMxAddress(mx);
|
|
117
|
-
return bytesToHex(bytes);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/** @deprecated Use makeMxAddress */
|
|
121
|
-
export const encodeMx = makeMxAddress;
|
|
122
|
-
/** @deprecated Use parseMxAddress */
|
|
123
|
-
export const decodeMx = parseMxAddress;
|
|
124
|
-
/** @deprecated Use hexToMx */
|
|
125
|
-
export const makeMinimaAddress = hexToMx;
|
|
126
|
-
/** @deprecated Use mxToHex */
|
|
127
|
-
export const convertMinimaAddress = mxToHex;
|
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Minima Wire Format Serializer
|
|
3
|
-
*
|
|
4
|
-
* Byte-exact serialization matching Minima's Java Signature.java and SignatureProof.java
|
|
5
|
-
*
|
|
6
|
-
* Wire Format Reference:
|
|
7
|
-
*
|
|
8
|
-
* Signature.writeDataStream():
|
|
9
|
-
* 1. MiniNumber - count of SignatureProofs
|
|
10
|
-
* 2. For each SignatureProof.writeDataStream()
|
|
11
|
-
*
|
|
12
|
-
* SignatureProof.writeDataStream():
|
|
13
|
-
* 1. MiniData (publicKey) - 4-byte big-endian length + bytes
|
|
14
|
-
* 2. MiniData (signature) - 4-byte big-endian length + bytes
|
|
15
|
-
* 3. MMRProof.writeDataStream()
|
|
16
|
-
*
|
|
17
|
-
* MMRProof.writeDataStream():
|
|
18
|
-
* 1. MiniNumber (blockTime)
|
|
19
|
-
* 2. MiniNumber (chain length)
|
|
20
|
-
* 3. For each chunk:
|
|
21
|
-
* - MiniByte (isLeft) - 1 byte (0 or 1)
|
|
22
|
-
* - MMRData.writeDataStream():
|
|
23
|
-
* - hash (4-byte length prefix + 32 bytes via writeHashToStream)
|
|
24
|
-
* - value (MiniNumber)
|
|
25
|
-
*
|
|
26
|
-
* CRITICAL (2026-01): Java's writeHashToStream uses writeInt (4-byte prefix),
|
|
27
|
-
* identical to writeDataStream. See MiniData.java lines 282-289.
|
|
28
|
-
*/
|
|
29
|
-
export type Bytes = Uint8Array;
|
|
30
|
-
/**
|
|
31
|
-
* Serialize MiniNumber matching Java MiniNumber.writeDataStream()
|
|
32
|
-
* Format: [scale: 1 byte] [length: 1 byte] [data: N bytes]
|
|
33
|
-
*
|
|
34
|
-
* Scale is always 0 for integers (no decimal places)
|
|
35
|
-
* Length is 1 byte (NOT 4 bytes like MiniData)
|
|
36
|
-
*/
|
|
37
|
-
export declare function serializeMiniNumber(value: bigint): Bytes;
|
|
38
|
-
/**
|
|
39
|
-
* Serialize MiniData matching Java MiniData.writeDataStream()
|
|
40
|
-
* Format: [4-byte big-endian length] [data bytes]
|
|
41
|
-
*/
|
|
42
|
-
export declare function serializeMiniData(data: Bytes): Bytes;
|
|
43
|
-
/**
|
|
44
|
-
* Write hash with 4-byte length prefix matching Java MiniData.writeHashToStream()
|
|
45
|
-
*
|
|
46
|
-
* From MiniData.java writeHashToStream (lines 282-289):
|
|
47
|
-
* zOut.writeInt(mData.length); // 4-byte big-endian int
|
|
48
|
-
* zOut.write(mData); // raw bytes
|
|
49
|
-
*
|
|
50
|
-
* CRITICAL: Java uses writeInt (4 bytes), same as writeDataStream!
|
|
51
|
-
* The only difference is a max length check of 64 bytes (MINIMA_MAX_HASH_LENGTH).
|
|
52
|
-
*
|
|
53
|
-
* Used by MMRData.writeDataStream() for the hash field.
|
|
54
|
-
*/
|
|
55
|
-
export declare function writeHashToStream(hash: Bytes): Bytes;
|
|
56
|
-
/**
|
|
57
|
-
* MMRData structure matching Minima's MMRData.java
|
|
58
|
-
*/
|
|
59
|
-
export interface MMRData {
|
|
60
|
-
data: Bytes;
|
|
61
|
-
value: bigint;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* MMRProofChunk structure matching Minima's MMRProof.MMRProofChunk
|
|
65
|
-
*/
|
|
66
|
-
export interface MMRProofChunk {
|
|
67
|
-
isLeft: boolean;
|
|
68
|
-
mmrData: MMRData;
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* MMRProof structure matching Minima's MMRProof.java
|
|
72
|
-
*/
|
|
73
|
-
export interface MMRProof {
|
|
74
|
-
chunks: MMRProofChunk[];
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Serialize MMRData matching Java MMRData.writeDataStream()
|
|
78
|
-
*
|
|
79
|
-
* CRITICAL FIX (2026-01): Analysis of coinexport output shows MMRData uses
|
|
80
|
-
* MiniData format (4-byte length prefix + 32 bytes) for the hash field,
|
|
81
|
-
* NOT raw 32 bytes. This matches what Minima's node produces.
|
|
82
|
-
*
|
|
83
|
-
* Format:
|
|
84
|
-
* - hash (MiniData: 4-byte length + 32 bytes)
|
|
85
|
-
* - value (MiniNumber)
|
|
86
|
-
*/
|
|
87
|
-
export declare function serializeMMRData(mmrData: MMRData): Bytes;
|
|
88
|
-
/**
|
|
89
|
-
* Serialize MMRProof matching Java MMRProof.writeDataStream()
|
|
90
|
-
*
|
|
91
|
-
* Format:
|
|
92
|
-
* 1. MiniNumber (blockTime) - always 0 for TreeKey proofs
|
|
93
|
-
* 2. MiniNumber (chain length)
|
|
94
|
-
* 3. For each chunk:
|
|
95
|
-
* - MiniByte (isLeft) - 1 byte
|
|
96
|
-
* - MMRData (hash + value)
|
|
97
|
-
*/
|
|
98
|
-
export declare function serializeMMRProof(proof: MMRProof, blockTime?: bigint): Bytes;
|
|
99
|
-
/**
|
|
100
|
-
* SignatureProof structure matching Minima's SignatureProof.java
|
|
101
|
-
*/
|
|
102
|
-
export interface SignatureProof {
|
|
103
|
-
publicKey: Bytes;
|
|
104
|
-
signature: Bytes;
|
|
105
|
-
proof: MMRProof;
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Serialize SignatureProof matching Java SignatureProof.writeDataStream()
|
|
109
|
-
*
|
|
110
|
-
* Format:
|
|
111
|
-
* 1. MiniData (publicKey) - 4-byte length + bytes
|
|
112
|
-
* 2. MiniData (signature) - 4-byte length + bytes
|
|
113
|
-
* 3. MMRProof.writeDataStream()
|
|
114
|
-
*/
|
|
115
|
-
export declare function serializeSignatureProof(sigProof: SignatureProof): Bytes;
|
|
116
|
-
/**
|
|
117
|
-
* Signature structure matching Minima's Signature.java
|
|
118
|
-
*/
|
|
119
|
-
export interface Signature {
|
|
120
|
-
proofs: SignatureProof[];
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Serialize Signature matching Java Signature.writeDataStream()
|
|
124
|
-
*
|
|
125
|
-
* Format:
|
|
126
|
-
* 1. MiniNumber - count of SignatureProofs
|
|
127
|
-
* 2. For each SignatureProof.writeDataStream()
|
|
128
|
-
*
|
|
129
|
-
* From Signature.java:
|
|
130
|
-
* MiniNumber.WriteToStream(zOut, mSignatures.size());
|
|
131
|
-
* for(SignatureProof sig : mSignatures) {
|
|
132
|
-
* sig.writeDataStream(zOut);
|
|
133
|
-
* }
|
|
134
|
-
*/
|
|
135
|
-
export declare function serializeSignature(signature: Signature): Bytes;
|
|
136
|
-
/**
|
|
137
|
-
* Convert hex string to bytes
|
|
138
|
-
*/
|
|
139
|
-
export declare function fromHex(hex: string): Bytes;
|
|
140
|
-
/**
|
|
141
|
-
* Convert bytes to hex string with 0x prefix
|
|
142
|
-
*/
|
|
143
|
-
export declare function toHex(bytes: Bytes): string;
|
|
144
|
-
/**
|
|
145
|
-
* Convert SignatureProofHex format (from TransactionService) to wire format bytes
|
|
146
|
-
*
|
|
147
|
-
* This is the main entry point for serializing hierarchical TreeKey signatures
|
|
148
|
-
* for txnimport.
|
|
149
|
-
*/
|
|
150
|
-
export interface SignatureProofHex {
|
|
151
|
-
leafPubkey: string;
|
|
152
|
-
signature: string;
|
|
153
|
-
mmrProof: string;
|
|
154
|
-
}
|
|
155
|
-
export interface HierarchicalWitnessBundle {
|
|
156
|
-
addressIndex: number;
|
|
157
|
-
l1: number;
|
|
158
|
-
l2: number;
|
|
159
|
-
rootPublicKey: string;
|
|
160
|
-
proofs: SignatureProofHex[];
|
|
161
|
-
}
|
|
162
|
-
/**
|
|
163
|
-
* Serialize hierarchical witness bundle to Minima wire format
|
|
164
|
-
*
|
|
165
|
-
* This converts the HierarchicalWitnessBundle (with hex strings) to
|
|
166
|
-
* the proper Witness signature format matching Witness.java → Signature.java hierarchy.
|
|
167
|
-
*
|
|
168
|
-
* CRITICAL FIX (2026-01): Must use double-nesting to match Java format:
|
|
169
|
-
* - Witness.writeDataStream writes: [signatureCount][Signature[0].writeDataStream()]...
|
|
170
|
-
* - Signature.writeDataStream writes: [proofCount][SignatureProof[0]]...
|
|
171
|
-
*
|
|
172
|
-
* So the final format is:
|
|
173
|
-
* [1] = signatureCount (we have 1 Signature object in Witness)
|
|
174
|
-
* [N] = proofCount inside that Signature (2 for address-based TreeKey)
|
|
175
|
-
* [SignatureProof[0]]
|
|
176
|
-
* [SignatureProof[1]]
|
|
177
|
-
*
|
|
178
|
-
* IMPORTANT: Uses pre-serialized MMR proof bytes directly to avoid
|
|
179
|
-
* double-serialization (deserialize then re-serialize).
|
|
180
|
-
*/
|
|
181
|
-
export declare function serializeHierarchicalWitness(bundle: HierarchicalWitnessBundle): Bytes;
|
|
182
|
-
/**
|
|
183
|
-
* @deprecated (2026-01) This function's output is NOT used in the main Totem transaction flow.
|
|
184
|
-
* MinimaTransactionBuilder.serializeWitness in the extension handles actual witness serialization.
|
|
185
|
-
* Kept for API compatibility and potential future direct SDK usage.
|
|
186
|
-
*
|
|
187
|
-
* Serialize hierarchical witness bundle to hex string for transport
|
|
188
|
-
*/
|
|
189
|
-
export declare function serializeHierarchicalWitnessToHex(bundle: HierarchicalWitnessBundle): string;
|