@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,112 +0,0 @@
1
- /**
2
- * @module TransactionReceiptStore
3
- * Persistent storage for transaction receipts
4
- *
5
- * Uses in-memory cache backed by persistent storage.
6
- * Pattern:
7
- * - initialize() loads from storage into memory cache
8
- * - Sync getters read from memory cache (fast, no I/O)
9
- * - Mutators update memory cache AND persist to storage
10
- */
11
-
12
- import type { StorageAdapter, LoggerAdapter } from '../adapters/index.js';
13
- import { NoopLogger } from '../adapters/index.js';
14
- import type { TransactionReceipt } from './types.js';
15
-
16
- export interface TransactionReceiptStoreConfig {
17
- storageKey?: string;
18
- maxReceipts?: number;
19
- }
20
-
21
- const DEFAULT_STORAGE_KEY = 'totem_transaction_receipts';
22
- const DEFAULT_MAX_RECEIPTS = 1000;
23
-
24
- export class TransactionReceiptStore {
25
- private receipts: TransactionReceipt[] = [];
26
- private _initialized = false;
27
- private readonly storageKey: string;
28
- private readonly maxReceipts: number;
29
- private readonly storage: StorageAdapter;
30
- private readonly logger: LoggerAdapter;
31
-
32
- constructor(
33
- storage: StorageAdapter,
34
- logger: LoggerAdapter = new NoopLogger(),
35
- config: TransactionReceiptStoreConfig = {}
36
- ) {
37
- this.storage = storage;
38
- this.logger = logger;
39
- this.storageKey = config.storageKey ?? DEFAULT_STORAGE_KEY;
40
- this.maxReceipts = config.maxReceipts ?? DEFAULT_MAX_RECEIPTS;
41
- }
42
-
43
- async initialize(): Promise<void> {
44
- if (this._initialized) return;
45
- await this.load();
46
- this._initialized = true;
47
- }
48
-
49
- isInitialized(): boolean {
50
- return this._initialized;
51
- }
52
-
53
- private async load(): Promise<void> {
54
- try {
55
- const receipts = await this.storage.get<TransactionReceipt[]>(this.storageKey);
56
- if (receipts) {
57
- this.receipts = receipts;
58
- this.logger.debug(`Loaded ${this.receipts.length} transaction receipts`);
59
- }
60
- } catch (error) {
61
- this.logger.error('Failed to load receipts:', error);
62
- }
63
- }
64
-
65
- private async persist(): Promise<void> {
66
- try {
67
- const trimmedReceipts = this.receipts.slice(-this.maxReceipts);
68
- await this.storage.set(this.storageKey, trimmedReceipts);
69
- this.receipts = trimmedReceipts;
70
- } catch (error) {
71
- this.logger.error('Failed to persist receipts:', error);
72
- throw error;
73
- }
74
- }
75
-
76
- async add(receipt: TransactionReceipt): Promise<void> {
77
- this.receipts.push(receipt);
78
- this.logger.debug(`Added receipt: ${receipt.txpowid}`);
79
- await this.persist();
80
- }
81
-
82
- getAll(): TransactionReceipt[] {
83
- return [...this.receipts].reverse();
84
- }
85
-
86
- getByTxpowid(txpowid: string): TransactionReceipt | undefined {
87
- return this.receipts.find(r => r.txpowid === txpowid);
88
- }
89
-
90
- getRecent(count: number = 50): TransactionReceipt[] {
91
- return this.getAll().slice(0, count);
92
- }
93
-
94
- async updateStatus(txpowid: string, status: TransactionReceipt['status']): Promise<void> {
95
- const receipt = this.receipts.find(r => r.txpowid === txpowid);
96
- if (receipt) {
97
- receipt.status = status;
98
- this.logger.debug(`Updated receipt status: ${txpowid} → ${status}`);
99
- await this.persist();
100
- }
101
- }
102
-
103
- async clear(): Promise<void> {
104
- this.receipts = [];
105
- await this.storage.remove(this.storageKey);
106
- this.logger.debug('Cleared all receipts');
107
- }
108
-
109
- count(): number {
110
- return this.receipts.length;
111
- }
112
- }
@@ -1,31 +0,0 @@
1
- /**
2
- * @module TransactionService
3
- * Handles WOTS signing flow: prepare → sign → finalize
4
- *
5
- * Platform-agnostic implementation using HttpClient adapter.
6
- */
7
- import type { HttpClient, LoggerAdapter, MetricsAdapter } from '../adapters';
8
- import type { PrepareRequest, PrepareResponse, SignRequest, SignResult, FinalizeRequest, FinalizeResponse } from './types';
9
- export interface TransactionServiceConfig {
10
- baseUrl: string;
11
- apiKey: string;
12
- paramSet?: string;
13
- }
14
- export interface WotsSigningDependencies {
15
- wotsSign: (seed: Uint8Array, index: number, message: Uint8Array, paramSet: any) => Uint8Array;
16
- fromHex: (hex: string) => Uint8Array;
17
- getParamSet: (name: string) => any;
18
- defaultParamSet: any;
19
- }
20
- export declare class TransactionService {
21
- private readonly http;
22
- private readonly logger;
23
- private readonly metrics;
24
- private readonly config;
25
- constructor(http: HttpClient, config: TransactionServiceConfig, logger?: LoggerAdapter, metrics?: MetricsAdapter);
26
- prepare(params: PrepareRequest, rootPublicKey: string): Promise<PrepareResponse>;
27
- sign(request: SignRequest, seed: Uint8Array, deps: WotsSigningDependencies, paramSetName?: string): Promise<SignResult>;
28
- finalize(params: FinalizeRequest): Promise<FinalizeResponse>;
29
- private serializeWitnessToHex;
30
- private bytesToHex;
31
- }
@@ -1,140 +0,0 @@
1
- "use strict";
2
- /**
3
- * @module TransactionService
4
- * Handles WOTS signing flow: prepare → sign → finalize
5
- *
6
- * Platform-agnostic implementation using HttpClient adapter.
7
- */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.TransactionService = void 0;
10
- const adapters_1 = require("../adapters");
11
- class TransactionService {
12
- constructor(http, config, logger = new adapters_1.NoopLogger(), metrics = new adapters_1.NoopMetrics()) {
13
- this.http = http;
14
- this.config = config;
15
- this.logger = logger;
16
- this.metrics = metrics;
17
- }
18
- async prepare(params, rootPublicKey) {
19
- const startTime = Date.now();
20
- const url = `${this.config.baseUrl.replace(/\/$/, '')}/wots/hardened/prepare`;
21
- const txId = params.txId || `tx-${Date.now()}-${Math.random().toString(36).slice(2)}`;
22
- this.logger.debug('Requesting lease for transaction...');
23
- this.logger.debug(` txId: ${txId}, to: ${params.to}, amount: ${params.amount}`);
24
- try {
25
- const response = await this.http.post(url, {
26
- txId,
27
- rootPublicKey,
28
- to: params.to,
29
- amount: params.amount,
30
- tokenId: params.tokenId || '0x00',
31
- burn: params.burn || null,
32
- paramSet: this.config.paramSet || 'minima',
33
- }, {
34
- headers: {
35
- 'Content-Type': 'application/json',
36
- 'x-api-key': this.config.apiKey,
37
- },
38
- });
39
- const result = response.data;
40
- const elapsed = Date.now() - startTime;
41
- this.metrics.timing('tx_prepare_duration_ms', elapsed);
42
- this.metrics.increment('tx_prepare_success');
43
- this.logger.debug(`Lease acquired (${elapsed}ms)`);
44
- this.logger.debug(` leaseId: ${result.leaseId}`);
45
- this.logger.debug(` indices: (addressIndex=${result.addressIndex}, l1=${result.l1}, l2=${result.l2})`);
46
- this.logger.debug(` TTL: ${result.leaseTTL}ms`);
47
- return result;
48
- }
49
- catch (error) {
50
- this.metrics.increment('tx_prepare_error');
51
- this.logger.error('Lease acquisition failed:', error);
52
- throw error;
53
- }
54
- }
55
- async sign(request, seed, deps, paramSetName = 'minima') {
56
- const startTime = Date.now();
57
- const { addressIndex, l1, l2, digestTx } = request;
58
- this.logger.debug('Starting on-demand key derivation...');
59
- this.logger.debug(` indices: (addressIndex=${addressIndex}, l1=${l1}, l2=${l2}), paramSet: ${paramSetName}`);
60
- // All param set names now resolve to the same Java-compatible w=8 param set
61
- const paramSet = deps.defaultParamSet;
62
- const digestBytes = deps.fromHex(digestTx);
63
- if (digestBytes.length !== 32) {
64
- throw new Error(`Invalid digest length: ${digestBytes.length}, expected 32 bytes`);
65
- }
66
- this.logger.debug('Deriving WOTS keys from root seed...');
67
- const addrStart = Date.now();
68
- const addrSignature = deps.wotsSign(seed, addressIndex, digestBytes, paramSet);
69
- this.logger.debug(` Address signed (${Date.now() - addrStart}ms)`);
70
- const l1Start = Date.now();
71
- const l1Signature = deps.wotsSign(seed, l1, digestBytes, paramSet);
72
- this.logger.debug(` L1 signed (${Date.now() - l1Start}ms)`);
73
- const l2Start = Date.now();
74
- const l2Signature = deps.wotsSign(seed, l2, digestBytes, paramSet);
75
- this.logger.debug(` L2 signed (${Date.now() - l2Start}ms)`);
76
- const L = paramSet.L;
77
- const toHexArray = (sig) => {
78
- const result = [];
79
- for (let i = 0; i < L; i++) {
80
- const chunk = sig.subarray(i * 32, (i + 1) * 32);
81
- result.push('0x' + this.bytesToHex(chunk));
82
- }
83
- return result;
84
- };
85
- const witnessBundle = {
86
- addressIndex,
87
- l1,
88
- l2,
89
- signatures: {
90
- l1Proof: toHexArray(addrSignature),
91
- l2Proof: toHexArray(l1Signature),
92
- l3Proof: toHexArray(l2Signature),
93
- },
94
- };
95
- const signedHex = this.serializeWitnessToHex(witnessBundle, digestTx);
96
- const elapsed = Date.now() - startTime;
97
- this.metrics.timing('tx_sign_duration_ms', elapsed);
98
- this.logger.debug(`Signature created (${elapsed}ms), size: ${signedHex.length} chars`);
99
- return { witnessBundle, signedHex };
100
- }
101
- async finalize(params) {
102
- const startTime = Date.now();
103
- const url = `${this.config.baseUrl.replace(/\/$/, '')}/wots/hardened/finalize`;
104
- this.logger.debug('Submitting signed transaction to network...');
105
- this.logger.debug(` leaseToken: ${params.leaseToken.slice(0, 16)}...`);
106
- try {
107
- const response = await this.http.post(url, params, {
108
- headers: {
109
- 'Content-Type': 'application/json',
110
- 'x-api-key': this.config.apiKey,
111
- },
112
- });
113
- const result = response.data;
114
- const elapsed = Date.now() - startTime;
115
- this.metrics.timing('tx_finalize_duration_ms', elapsed);
116
- this.metrics.increment('tx_finalize_success');
117
- this.logger.debug(`Transaction finalized (${elapsed}ms)`);
118
- this.logger.debug(` txpowid: ${result.txpowid}, leaseId: ${result.leaseId}`);
119
- return result;
120
- }
121
- catch (error) {
122
- this.metrics.increment('tx_finalize_error');
123
- this.logger.error('Finalization failed:', error);
124
- throw error;
125
- }
126
- }
127
- serializeWitnessToHex(bundle, digestHex) {
128
- const l1ProofHex = bundle.signatures.l1Proof.map(p => p.replace(/^0x/, '')).join('');
129
- const l2ProofHex = bundle.signatures.l2Proof.map(p => p.replace(/^0x/, '')).join('');
130
- const l3ProofHex = bundle.signatures.l3Proof.map(p => p.replace(/^0x/, '')).join('');
131
- const digest = digestHex.replace(/^0x/, '');
132
- return `0x${digest}${l1ProofHex}${l2ProofHex}${l3ProofHex}`;
133
- }
134
- bytesToHex(bytes) {
135
- return Array.from(bytes)
136
- .map(b => b.toString(16).padStart(2, '0'))
137
- .join('');
138
- }
139
- }
140
- exports.TransactionService = TransactionService;
@@ -1,252 +0,0 @@
1
- /**
2
- * @module TransactionService
3
- * Handles WOTS signing flow: prepare → sign → finalize
4
- *
5
- * Platform-agnostic implementation using HttpClient adapter.
6
- *
7
- * Sign architecture (2026-02): uses per-address TreeKey (depth=3, keysPerLevel=64)
8
- * matching Minima Wallet.java exactly. Each address has its own TreeKey derived
9
- * from the wallet seed. Signing produces 3 proofs (Root→L1→L2→DATA).
10
- */
11
-
12
- import type { HttpClient, LoggerAdapter, MetricsAdapter } from '../adapters/index.js';
13
- import { NoopLogger, NoopMetrics } from '../adapters/index.js';
14
- import { createPerAddressTreeKey, serializeTreeSignature } from '../treekey.js';
15
- import { serializeMMRProof } from '../mmr.js';
16
- import { fromHex } from '../wots.js';
17
- import type {
18
- PrepareRequest,
19
- PrepareResponse,
20
- SignRequest,
21
- SignResult,
22
- HierarchicalWitnessBundle,
23
- FinalizeRequest,
24
- FinalizeResponse,
25
- } from './types.js';
26
-
27
- export interface TransactionServiceConfig {
28
- baseUrl: string;
29
- apiKey: string;
30
- paramSet?: string;
31
- }
32
-
33
- /**
34
- * @deprecated WotsSigningDependencies is no longer used by TransactionService.sign().
35
- * The service now derives everything from the seed and indices directly using
36
- * the built-in TreeKey implementation. This interface is kept for backward compatibility
37
- * only and will be removed in a future version.
38
- */
39
- export interface WotsSigningDependencies {
40
- wotsSign?: (seed: Uint8Array, index: number, message: Uint8Array, paramSet: any) => Uint8Array;
41
- fromHex?: (hex: string) => Uint8Array;
42
- getParamSet?: (name: string) => any;
43
- defaultParamSet?: any;
44
- }
45
-
46
- export class TransactionService {
47
- private readonly http: HttpClient;
48
- private readonly logger: LoggerAdapter;
49
- private readonly metrics: MetricsAdapter;
50
- private readonly config: TransactionServiceConfig;
51
-
52
- constructor(
53
- http: HttpClient,
54
- config: TransactionServiceConfig,
55
- logger: LoggerAdapter = new NoopLogger(),
56
- metrics: MetricsAdapter = new NoopMetrics()
57
- ) {
58
- this.http = http;
59
- this.config = config;
60
- this.logger = logger;
61
- this.metrics = metrics;
62
- }
63
-
64
- async prepare(params: PrepareRequest, rootPublicKey: string): Promise<PrepareResponse> {
65
- const startTime = Date.now();
66
- const url = `${this.config.baseUrl.replace(/\/$/, '')}/v1/wots-hardened/prepare`;
67
- const txId = params.txId || `tx-${Date.now()}-${Math.random().toString(36).slice(2)}`;
68
-
69
- this.logger.debug('Requesting lease for transaction...');
70
- this.logger.debug(` txId: ${txId}, to: ${params.to}, amount: ${params.amount}`);
71
-
72
- if (typeof params.addressIndex !== 'number' || params.addressIndex < 0 || params.addressIndex >= 64) {
73
- throw new Error('params.addressIndex is required and must be 0-63');
74
- }
75
-
76
- try {
77
- const response = await this.http.post<PrepareResponse>(url, {
78
- txId,
79
- rootPublicKey,
80
- to: params.to,
81
- amount: params.amount,
82
- tokenId: params.tokenId || '0x00',
83
- burn: params.burn || null,
84
- paramSet: this.config.paramSet || 'v2-spec',
85
- addressIndex: params.addressIndex,
86
- walletMode: params.walletMode || 'AnonTree',
87
- perAddressPublicKey: params.perAddressPublicKey ?? null,
88
- }, {
89
- headers: {
90
- 'Content-Type': 'application/json',
91
- 'x-api-key': this.config.apiKey,
92
- },
93
- });
94
-
95
- if (response.status === 429) {
96
- const body = response.data as any;
97
- const err: any = new Error(body?.error || 'Daily signing limit reached');
98
- err.code = 429;
99
- err.limit = body?.limit;
100
- err.used = body?.used;
101
- err.retryAfter = body?.retryAfter;
102
- throw err;
103
- }
104
-
105
- if (!response.ok) {
106
- const body = response.data as any;
107
- const msg = body?.error || body?.message || `HTTP ${response.status}`;
108
- const err: any = new Error(msg);
109
- err.code = response.status;
110
- throw err;
111
- }
112
-
113
- const result = response.data;
114
- const elapsed = Date.now() - startTime;
115
- this.metrics.timing('tx_prepare_duration_ms', elapsed);
116
- this.metrics.increment('tx_prepare_success');
117
-
118
- this.logger.debug(`Lease acquired (${elapsed}ms)`);
119
- this.logger.debug(` leaseId: ${result.leaseId}`);
120
- this.logger.debug(` indices: (addressIndex=${result.addressIndex}, l1=${result.l1}, l2=${result.l2})`);
121
- this.logger.debug(` TTL: ${result.leaseTTL}ms`);
122
-
123
- return result;
124
- } catch (error: any) {
125
- if (error.code === 429 || error.code === 400 || error.code === 403 || error.code === 409) {
126
- throw error;
127
- }
128
- this.metrics.increment('tx_prepare_error');
129
- this.logger.error('Lease acquisition failed:', error);
130
- throw error;
131
- }
132
- }
133
-
134
- /**
135
- * Sign a transaction using per-address TreeKey architecture.
136
- *
137
- * Produces 3 proofs (Root→L1→L2→DATA) matching Minima's TreeKey.sign() exactly.
138
- *
139
- * @param request - Indices and digestTx from the /prepare response
140
- * @param seed - 32-byte wallet base seed (from mnemonic)
141
- * @param _deps - Deprecated, unused. Pass null or omit.
142
- * @param _paramSet - Deprecated, unused. TreeKey uses its own param set.
143
- */
144
- async sign(
145
- request: SignRequest,
146
- seed: Uint8Array,
147
- _deps?: WotsSigningDependencies | null,
148
- _paramSet?: string
149
- ): Promise<SignResult> {
150
- const startTime = Date.now();
151
- const { addressIndex, l1, l2, digestTx } = request;
152
-
153
- this.logger.debug('Starting per-address TreeKey signing...');
154
- this.logger.debug(` indices: (addressIndex=${addressIndex}, l1=${l1}, l2=${l2})`);
155
-
156
- if (addressIndex < 0 || addressIndex >= 64) {
157
- throw new Error(`Invalid addressIndex: ${addressIndex}. Must be 0-63.`);
158
- }
159
-
160
- const digestBytes = fromHex(digestTx);
161
- if (digestBytes.length !== 32) {
162
- throw new Error(`Invalid digest length: ${digestBytes.length}, expected 32 bytes`);
163
- }
164
-
165
- // Derive per-address TreeKey matching Minima Wallet.java
166
- this.logger.debug(` Deriving per-address TreeKey for index ${addressIndex}...`);
167
- const treeKey = createPerAddressTreeKey(seed, addressIndex);
168
-
169
- // Convert (l1, l2) to Java-compatible 'uses' counter
170
- // Java's TreeKey.sign() uses baseConversion(uses) to compute path
171
- const KEYS_PER_LEVEL = 64;
172
- const uses = l1 * KEYS_PER_LEVEL + l2;
173
- this.logger.debug(` Converting indices to uses: (l1=${l1}, l2=${l2}) → uses=${uses}`);
174
-
175
- // setUses() + sign() matches Java pattern: tk.setUses(uses) → tk.sign(zData)
176
- treeKey.setUses(uses);
177
- const treeSignature = treeKey.sign(digestBytes);
178
- const newUses = treeKey.getUses();
179
-
180
- this.logger.debug(` TreeKey signing complete, proofs: ${treeSignature.proofs.length}, newUses: ${newUses}`);
181
-
182
- // Build HierarchicalWitnessBundle with unified naming
183
- const treeKeyPubkey = treeKey.getPublicKey();
184
- const witnessBundle: HierarchicalWitnessBundle = {
185
- addressIndex,
186
- l1,
187
- l2,
188
- rootPublicKey: `0x${this.bytesToHex(treeKeyPubkey)}`,
189
- proofs: treeSignature.proofs.map((proof: any) => ({
190
- leafPubkey: `0x${this.bytesToHex(proof.leafPubkey)}`,
191
- signature: `0x${this.bytesToHex(proof.signature)}`,
192
- mmrProof: `0x${this.bytesToHex(serializeMMRProof(proof.mmrProof))}`,
193
- })),
194
- };
195
-
196
- // Serialize to byte-exact Java-compatible wire format
197
- const serializedBytes = serializeTreeSignature(treeSignature);
198
- const signedHex = `0x${this.bytesToHex(serializedBytes)}`;
199
-
200
- const elapsed = Date.now() - startTime;
201
- this.metrics.timing('tx_sign_duration_ms', elapsed);
202
- this.logger.debug(`Signature created (${elapsed}ms), serialized: ${serializedBytes.length} bytes`);
203
-
204
- return { witnessBundle, signedHex };
205
- }
206
-
207
- async finalize(params: FinalizeRequest): Promise<FinalizeResponse> {
208
- const startTime = Date.now();
209
- const url = `${this.config.baseUrl.replace(/\/$/, '')}/v1/wots-hardened/finalize`;
210
-
211
- this.logger.debug('Submitting signed transaction to network...');
212
- this.logger.debug(` leaseToken: ${params.leaseToken.slice(0, 16)}...`);
213
-
214
- try {
215
- const response = await this.http.post<FinalizeResponse>(url, params, {
216
- headers: {
217
- 'Content-Type': 'application/json',
218
- 'x-api-key': this.config.apiKey,
219
- },
220
- });
221
-
222
- if (!response.ok) {
223
- const body = response.data as any;
224
- const msg = body?.error || body?.message || `HTTP ${response.status}`;
225
- const err: any = new Error(msg);
226
- err.code = response.status;
227
- throw err;
228
- }
229
-
230
- const result = response.data;
231
- const elapsed = Date.now() - startTime;
232
- this.metrics.timing('tx_finalize_duration_ms', elapsed);
233
- this.metrics.increment('tx_finalize_success');
234
-
235
- this.logger.debug(`Transaction finalized (${elapsed}ms)`);
236
- this.logger.debug(` txpowid: ${result.txpowid}, leaseId: ${result.leaseId}`);
237
-
238
- return result;
239
- } catch (error: any) {
240
- if (error.code !== undefined) throw error;
241
- this.metrics.increment('tx_finalize_error');
242
- this.logger.error('Finalization failed:', error);
243
- throw error;
244
- }
245
- }
246
-
247
- private bytesToHex(bytes: Uint8Array): string {
248
- return Array.from(bytes)
249
- .map(b => b.toString(16).padStart(2, '0'))
250
- .join('');
251
- }
252
- }
package/src/tx/index.d.ts DELETED
@@ -1,13 +0,0 @@
1
- /**
2
- * @module @totemsdk/core/tx
3
- * Transaction service and lifecycle management
4
- *
5
- * This module provides:
6
- * - TransactionService: WOTS signing flow (prepare → sign → finalize)
7
- * - TransactionLifecycle: Orchestrates flow with lease/watermark stores
8
- * - TransactionReceiptStore: Persistent transaction history
9
- */
10
- export { TransactionService, type TransactionServiceConfig, type WotsSigningDependencies, } from './TransactionService';
11
- export { TransactionLifecycle, TransactionLifecycleError, WatermarkExhaustedError, type TransactionLifecycleConfig, type WatermarkSyncFunction, type PrepareResult, } from './TransactionLifecycle';
12
- export { TransactionReceiptStore, type TransactionReceiptStoreConfig, } from './TransactionReceiptStore';
13
- export type { WotsIndices, PrepareRequest, PrepareResponse, SignRequest, SignResult, WitnessBundle, FinalizeRequest, FinalizeResponse, TransactionMetadata, TransactionReceipt, TransactionError, } from './types';
package/src/tx/index.js DELETED
@@ -1,20 +0,0 @@
1
- "use strict";
2
- /**
3
- * @module @totemsdk/core/tx
4
- * Transaction service and lifecycle management
5
- *
6
- * This module provides:
7
- * - TransactionService: WOTS signing flow (prepare → sign → finalize)
8
- * - TransactionLifecycle: Orchestrates flow with lease/watermark stores
9
- * - TransactionReceiptStore: Persistent transaction history
10
- */
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.TransactionReceiptStore = exports.WatermarkExhaustedError = exports.TransactionLifecycleError = exports.TransactionLifecycle = exports.TransactionService = void 0;
13
- var TransactionService_1 = require("./TransactionService");
14
- Object.defineProperty(exports, "TransactionService", { enumerable: true, get: function () { return TransactionService_1.TransactionService; } });
15
- var TransactionLifecycle_1 = require("./TransactionLifecycle");
16
- Object.defineProperty(exports, "TransactionLifecycle", { enumerable: true, get: function () { return TransactionLifecycle_1.TransactionLifecycle; } });
17
- Object.defineProperty(exports, "TransactionLifecycleError", { enumerable: true, get: function () { return TransactionLifecycle_1.TransactionLifecycleError; } });
18
- Object.defineProperty(exports, "WatermarkExhaustedError", { enumerable: true, get: function () { return TransactionLifecycle_1.WatermarkExhaustedError; } });
19
- var TransactionReceiptStore_1 = require("./TransactionReceiptStore");
20
- Object.defineProperty(exports, "TransactionReceiptStore", { enumerable: true, get: function () { return TransactionReceiptStore_1.TransactionReceiptStore; } });
package/src/tx/index.ts DELETED
@@ -1,44 +0,0 @@
1
- /**
2
- * @module @totemsdk/core/tx
3
- * Transaction service and lifecycle management
4
- *
5
- * This module provides:
6
- * - TransactionService: WOTS signing flow (prepare → sign → finalize)
7
- * - TransactionLifecycle: Orchestrates flow with lease/watermark stores
8
- * - TransactionReceiptStore: Persistent transaction history
9
- */
10
-
11
- export {
12
- TransactionService,
13
- type TransactionServiceConfig,
14
- type WotsSigningDependencies,
15
- } from './TransactionService.js';
16
-
17
- export {
18
- TransactionLifecycle,
19
- TransactionLifecycleError,
20
- WatermarkExhaustedError,
21
- type TransactionLifecycleConfig,
22
- type WatermarkSyncFunction,
23
- type PrepareResult,
24
- } from './TransactionLifecycle.js';
25
-
26
- export {
27
- TransactionReceiptStore,
28
- type TransactionReceiptStoreConfig,
29
- } from './TransactionReceiptStore.js';
30
-
31
- export type {
32
- WotsIndices,
33
- PrepareRequest,
34
- PrepareResponse,
35
- SignRequest,
36
- SignResult,
37
- HierarchicalWitnessBundle,
38
- WitnessBundle,
39
- FinalizeRequest,
40
- FinalizeResponse,
41
- TransactionMetadata,
42
- TransactionReceipt,
43
- TransactionError,
44
- } from './types.js';