@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,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';