@totemsdk/core 1.0.0
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/dist/Streamable.d.ts +268 -0
- package/dist/Streamable.js +416 -0
- package/dist/adapters/index.d.ts +190 -0
- package/dist/adapters/index.js +107 -0
- package/dist/adapters/types.d.ts +149 -0
- package/dist/adapters/types.js +67 -0
- package/dist/binio.d.ts +9 -0
- package/dist/binio.js +30 -0
- package/dist/bip39.d.ts +91 -0
- package/dist/bip39.js +417 -0
- package/dist/derive.d.ts +2 -0
- package/dist/derive.js +9 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.js +53 -0
- package/dist/javaStreamables.d.ts +233 -0
- package/dist/javaStreamables.js +332 -0
- package/dist/lease/LeaseMonitor.d.ts +44 -0
- package/dist/lease/LeaseMonitor.js +107 -0
- package/dist/lease/LeaseStore.d.ts +57 -0
- package/dist/lease/LeaseStore.js +144 -0
- package/dist/lease/WatermarkStore.d.ts +61 -0
- package/dist/lease/WatermarkStore.js +202 -0
- package/dist/lease/index.d.ts +14 -0
- package/dist/lease/index.js +13 -0
- package/dist/lease-client.d.ts +31 -0
- package/dist/lease-client.js +39 -0
- package/dist/minima32.d.ts +18 -0
- package/dist/minima32.js +112 -0
- package/dist/minimaWireSerializer.d.ts +60 -0
- package/dist/minimaWireSerializer.js +71 -0
- package/dist/mmr.d.ts +156 -0
- package/dist/mmr.js +342 -0
- package/dist/mx.d.ts +1 -0
- package/dist/mx.js +1 -0
- package/dist/params.d.ts +29 -0
- package/dist/params.js +16 -0
- package/dist/script.d.ts +7 -0
- package/dist/script.js +22 -0
- package/dist/scripts/contract-helpers.d.ts +252 -0
- package/dist/scripts/contract-helpers.js +394 -0
- package/dist/scripts/dapp-types.d.ts +119 -0
- package/dist/scripts/dapp-types.js +72 -0
- package/dist/scripts/index.d.ts +4 -0
- package/dist/scripts/index.js +4 -0
- package/dist/scripts/types.d.ts +81 -0
- package/dist/scripts/types.js +145 -0
- package/dist/scripts/witness-serializer.d.ts +29 -0
- package/dist/scripts/witness-serializer.js +288 -0
- package/dist/transaction.d.ts +106 -0
- package/dist/transaction.js +284 -0
- package/dist/treekey.d.ts +383 -0
- package/dist/treekey.js +762 -0
- package/dist/tx/TransactionLifecycle.d.ts +55 -0
- package/dist/tx/TransactionLifecycle.js +189 -0
- package/dist/tx/TransactionReceiptStore.d.ts +36 -0
- package/dist/tx/TransactionReceiptStore.js +85 -0
- package/dist/tx/TransactionService.d.ts +50 -0
- package/dist/tx/TransactionService.js +178 -0
- package/dist/tx/index.d.ts +13 -0
- package/dist/tx/index.js +12 -0
- package/dist/tx/types.d.ts +114 -0
- package/dist/tx/types.js +5 -0
- package/dist/util.d.ts +1 -0
- package/dist/util.js +1 -0
- package/dist/utils.d.ts +8 -0
- package/dist/utils.js +35 -0
- package/dist/verify.d.ts +18 -0
- package/dist/verify.js +162 -0
- package/dist/version.d.ts +12 -0
- package/dist/version.js +12 -0
- package/dist/wots.d.ts +232 -0
- package/dist/wots.js +538 -0
- package/package.json +65 -0
- package/src/Streamable.d.ts +265 -0
- package/src/Streamable.js +431 -0
- package/src/Streamable.ts +567 -0
- package/src/__tests__/Streamable.parity.test.ts +422 -0
- package/src/__tests__/perAddressDerivation.parity.test.ts +152 -0
- package/src/__tests__/wots-parity.test.ts +289 -0
- package/src/adapters/index.d.ts +190 -0
- package/src/adapters/index.js +117 -0
- package/src/adapters/index.ts +301 -0
- package/src/adapters/types.ts +235 -0
- package/src/addr.oracle.test.ts +25 -0
- package/src/address.test.ts +55 -0
- package/src/binio.ts +21 -0
- package/src/bip39.d.ts +91 -0
- package/src/bip39.js +427 -0
- package/src/bip39.ts +432 -0
- package/src/derive.d.ts +2 -0
- package/src/derive.js +13 -0
- package/src/derive.ts +11 -0
- package/src/index.d.ts +26 -0
- package/src/index.js +128 -0
- package/src/index.test.ts +5 -0
- package/src/index.ts +206 -0
- package/src/javaStreamables.d.ts +233 -0
- package/src/javaStreamables.js +328 -0
- package/src/javaStreamables.ts +403 -0
- package/src/lease/LeaseMonitor.d.ts +44 -0
- package/src/lease/LeaseMonitor.js +111 -0
- package/src/lease/LeaseMonitor.ts +157 -0
- package/src/lease/LeaseStore.d.ts +57 -0
- package/src/lease/LeaseStore.js +148 -0
- package/src/lease/LeaseStore.ts +203 -0
- package/src/lease/WatermarkStore.d.ts +61 -0
- package/src/lease/WatermarkStore.js +206 -0
- package/src/lease/WatermarkStore.ts +270 -0
- package/src/lease/index.d.ts +14 -0
- package/src/lease/index.js +22 -0
- package/src/lease/index.ts +41 -0
- package/src/lease-client.d.ts +31 -0
- package/src/lease-client.js +44 -0
- package/src/lease-client.ts +69 -0
- package/src/minima32.d.ts +10 -0
- package/src/minima32.js +113 -0
- package/src/minima32.test.ts +11 -0
- package/src/minima32.ts +127 -0
- package/src/minimaWireSerializer.d.ts +189 -0
- package/src/minimaWireSerializer.js +311 -0
- package/src/minimaWireSerializer.test.ts +466 -0
- package/src/minimaWireSerializer.ts +117 -0
- package/src/mmr.d.ts +153 -0
- package/src/mmr.js +351 -0
- package/src/mmr.oracle.test.ts +28 -0
- package/src/mmr.ts +429 -0
- package/src/mx.test.ts +25 -0
- package/src/mx.ts +1 -0
- package/src/params.d.ts +29 -0
- package/src/params.d.ts.map +1 -0
- package/src/params.js +20 -0
- package/src/params.js.map +1 -0
- package/src/params.ts +44 -0
- package/src/script.d.ts +7 -0
- package/src/script.js +27 -0
- package/src/script.ts +24 -0
- package/src/scripts/contract-helpers.ts +609 -0
- package/src/scripts/dapp-types.ts +240 -0
- package/src/scripts/index.ts +22 -0
- package/src/scripts/types.ts +247 -0
- package/src/scripts/witness-serializer.ts +384 -0
- package/src/transaction.ts +430 -0
- package/src/treekey.d.ts +383 -0
- package/src/treekey.js +778 -0
- package/src/treekey.parity.test.ts +459 -0
- package/src/treekey.ts +979 -0
- package/src/tx/TransactionLifecycle.d.ts +55 -0
- package/src/tx/TransactionLifecycle.js +188 -0
- package/src/tx/TransactionLifecycle.ts +280 -0
- package/src/tx/TransactionReceiptStore.d.ts +36 -0
- package/src/tx/TransactionReceiptStore.js +89 -0
- package/src/tx/TransactionReceiptStore.ts +112 -0
- package/src/tx/TransactionService.d.ts +31 -0
- package/src/tx/TransactionService.js +140 -0
- package/src/tx/TransactionService.ts +250 -0
- package/src/tx/index.d.ts +13 -0
- package/src/tx/index.js +20 -0
- package/src/tx/index.ts +44 -0
- package/src/tx/types.d.ts +80 -0
- package/src/tx/types.js +6 -0
- package/src/tx/types.ts +127 -0
- package/src/util.d.ts +1 -0
- package/src/util.js +5 -0
- package/src/util.ts +1 -0
- package/src/utils.d.ts +8 -0
- package/src/utils.js +42 -0
- package/src/utils.ts +38 -0
- package/src/verify.ts +209 -0
- package/src/version.ts +13 -0
- package/src/wots.d.ts +224 -0
- package/src/wots.d.ts.map +1 -0
- package/src/wots.js +559 -0
- package/src/wots.js.map +1 -0
- package/src/wots.ts +636 -0
- package/test-vectors.json +45 -0
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @totemsdk/core/adapters
|
|
3
|
+
* Platform-agnostic adapter interfaces for SDK portability
|
|
4
|
+
*
|
|
5
|
+
* These interfaces enable the SDK to work across multiple platforms:
|
|
6
|
+
* - Browser (Chrome Extensions, web apps)
|
|
7
|
+
* - Node.js (server-side, CLI tools)
|
|
8
|
+
* - React Native (mobile apps) - follow-up
|
|
9
|
+
*
|
|
10
|
+
* Each platform provides its own implementation of these adapters.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export interface StorageAdapter {
|
|
14
|
+
get<T>(key: string): Promise<T | null>;
|
|
15
|
+
set<T>(key: string, value: T): Promise<void>;
|
|
16
|
+
remove(key: string): Promise<boolean>;
|
|
17
|
+
clear(): Promise<void>;
|
|
18
|
+
keys(): Promise<string[]>;
|
|
19
|
+
has(key: string): Promise<boolean>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface AuthTokenProvider {
|
|
23
|
+
getToken(): Promise<string | null>;
|
|
24
|
+
setToken(token: string): Promise<void>;
|
|
25
|
+
clearToken(): Promise<void>;
|
|
26
|
+
onTokenChange(callback: (token: string | null) => void): () => void;
|
|
27
|
+
isAuthenticated(): Promise<boolean>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type BinaryData = Uint8Array | ArrayBuffer;
|
|
31
|
+
|
|
32
|
+
export interface WebSocketFactoryOptions {
|
|
33
|
+
pingIntervalMs?: number;
|
|
34
|
+
pongTimeoutMs?: number;
|
|
35
|
+
maxPayloadBytes?: number;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface WebSocketOpenEvent {
|
|
39
|
+
type: 'open';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface WebSocketCloseEvent {
|
|
43
|
+
type: 'close';
|
|
44
|
+
code: number;
|
|
45
|
+
reason: string;
|
|
46
|
+
wasClean: boolean;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface WebSocketMessageEvent {
|
|
50
|
+
type: 'message';
|
|
51
|
+
data: string | BinaryData;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface WebSocketErrorEvent {
|
|
55
|
+
type: 'error';
|
|
56
|
+
message?: string;
|
|
57
|
+
error?: Error;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export type WebSocketEventMap = {
|
|
61
|
+
open: WebSocketOpenEvent;
|
|
62
|
+
close: WebSocketCloseEvent;
|
|
63
|
+
message: WebSocketMessageEvent;
|
|
64
|
+
error: WebSocketErrorEvent;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export interface WebSocketFactory {
|
|
68
|
+
create(url: string, protocols?: string[], options?: WebSocketFactoryOptions): WebSocketClient;
|
|
69
|
+
dispose(): void;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface WebSocketClient {
|
|
73
|
+
readonly readyState: number;
|
|
74
|
+
readonly url: string;
|
|
75
|
+
|
|
76
|
+
send(data: string | BinaryData): void;
|
|
77
|
+
close(code?: number, reason?: string): void;
|
|
78
|
+
terminate(): void;
|
|
79
|
+
|
|
80
|
+
addEventListener<K extends keyof WebSocketEventMap>(
|
|
81
|
+
event: K,
|
|
82
|
+
listener: (ev: WebSocketEventMap[K]) => void
|
|
83
|
+
): void;
|
|
84
|
+
|
|
85
|
+
removeEventListener<K extends keyof WebSocketEventMap>(
|
|
86
|
+
event: K,
|
|
87
|
+
listener: (ev: WebSocketEventMap[K]) => void
|
|
88
|
+
): void;
|
|
89
|
+
|
|
90
|
+
removeAllListeners(): void;
|
|
91
|
+
|
|
92
|
+
onopen: ((ev: WebSocketOpenEvent) => void) | null;
|
|
93
|
+
onclose: ((ev: WebSocketCloseEvent) => void) | null;
|
|
94
|
+
onmessage: ((ev: WebSocketMessageEvent) => void) | null;
|
|
95
|
+
onerror: ((ev: WebSocketErrorEvent) => void) | null;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export const WebSocketReadyState = {
|
|
99
|
+
CONNECTING: 0,
|
|
100
|
+
OPEN: 1,
|
|
101
|
+
CLOSING: 2,
|
|
102
|
+
CLOSED: 3,
|
|
103
|
+
} as const;
|
|
104
|
+
|
|
105
|
+
export interface CancellationToken {
|
|
106
|
+
readonly cancelled: boolean;
|
|
107
|
+
onCancel(callback: () => void): () => void;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export interface CancellationTokenSource {
|
|
111
|
+
readonly token: CancellationToken;
|
|
112
|
+
cancel(): void;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function createCancellationToken(): CancellationTokenSource {
|
|
116
|
+
let cancelled = false;
|
|
117
|
+
const callbacks = new Set<() => void>();
|
|
118
|
+
|
|
119
|
+
const token: CancellationToken = {
|
|
120
|
+
get cancelled() { return cancelled; },
|
|
121
|
+
onCancel(callback: () => void): () => void {
|
|
122
|
+
if (cancelled) {
|
|
123
|
+
callback();
|
|
124
|
+
return () => {};
|
|
125
|
+
}
|
|
126
|
+
callbacks.add(callback);
|
|
127
|
+
return () => callbacks.delete(callback);
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
token,
|
|
133
|
+
cancel() {
|
|
134
|
+
if (!cancelled) {
|
|
135
|
+
cancelled = true;
|
|
136
|
+
callbacks.forEach(cb => cb());
|
|
137
|
+
callbacks.clear();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export interface HttpClient {
|
|
144
|
+
get<T>(url: string, options?: HttpRequestOptions): Promise<HttpResponse<T>>;
|
|
145
|
+
post<T>(url: string, body?: unknown, options?: HttpRequestOptions): Promise<HttpResponse<T>>;
|
|
146
|
+
put<T>(url: string, body?: unknown, options?: HttpRequestOptions): Promise<HttpResponse<T>>;
|
|
147
|
+
delete<T>(url: string, options?: HttpRequestOptions): Promise<HttpResponse<T>>;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export interface HttpRequestOptions {
|
|
151
|
+
headers?: Record<string, string>;
|
|
152
|
+
timeout?: number;
|
|
153
|
+
cancellationToken?: CancellationToken;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export interface HttpResponse<T> {
|
|
157
|
+
ok: boolean;
|
|
158
|
+
status: number;
|
|
159
|
+
statusText: string;
|
|
160
|
+
headers: Record<string, string>;
|
|
161
|
+
data: T;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export interface ConfigProvider {
|
|
165
|
+
get<T>(key: string): T | undefined;
|
|
166
|
+
get<T>(key: string, defaultValue: T): T;
|
|
167
|
+
set<T>(key: string, value: T): void;
|
|
168
|
+
has(key: string): boolean;
|
|
169
|
+
getAll(): Record<string, unknown>;
|
|
170
|
+
|
|
171
|
+
readonly apiUrl: string;
|
|
172
|
+
readonly wsUrl: string;
|
|
173
|
+
readonly network: 'mainnet' | 'testnet' | 'devnet';
|
|
174
|
+
readonly apiKey?: string;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export interface LoggerAdapter {
|
|
178
|
+
debug(message: string, ...args: unknown[]): void;
|
|
179
|
+
info(message: string, ...args: unknown[]): void;
|
|
180
|
+
warn(message: string, ...args: unknown[]): void;
|
|
181
|
+
error(message: string, ...args: unknown[]): void;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export interface MetricsAdapter {
|
|
185
|
+
increment(name: string, value?: number, tags?: Record<string, string>): void;
|
|
186
|
+
gauge(name: string, value: number, tags?: Record<string, string>): void;
|
|
187
|
+
timing(name: string, durationMs: number, tags?: Record<string, string>): void;
|
|
188
|
+
histogram(name: string, value: number, tags?: Record<string, string>): void;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export interface TimerAdapter {
|
|
192
|
+
setTimeout(callback: () => void, ms: number): TimerHandle;
|
|
193
|
+
setInterval(callback: () => void, ms: number): TimerHandle;
|
|
194
|
+
clearTimeout(handle: TimerHandle): void;
|
|
195
|
+
clearInterval(handle: TimerHandle): void;
|
|
196
|
+
now(): number;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export type TimerHandle = ReturnType<typeof setTimeout>;
|
|
200
|
+
|
|
201
|
+
export interface CryptoAdapter {
|
|
202
|
+
randomBytes(length: number): Uint8Array;
|
|
203
|
+
sha256(data: Uint8Array): Uint8Array;
|
|
204
|
+
sha256Async(data: Uint8Array): Promise<Uint8Array>;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export interface AdapterRegistry {
|
|
208
|
+
storage: StorageAdapter;
|
|
209
|
+
auth: AuthTokenProvider;
|
|
210
|
+
websocket: WebSocketFactory;
|
|
211
|
+
http: HttpClient;
|
|
212
|
+
config: ConfigProvider;
|
|
213
|
+
logger: LoggerAdapter;
|
|
214
|
+
metrics?: MetricsAdapter;
|
|
215
|
+
timer: TimerAdapter;
|
|
216
|
+
crypto: CryptoAdapter;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export function createAdapterRegistry(adapters: Partial<AdapterRegistry>): AdapterRegistry {
|
|
220
|
+
const required: (keyof AdapterRegistry)[] = [
|
|
221
|
+
'storage', 'auth', 'websocket', 'http', 'config', 'logger', 'timer', 'crypto'
|
|
222
|
+
];
|
|
223
|
+
|
|
224
|
+
for (const key of required) {
|
|
225
|
+
if (!adapters[key]) {
|
|
226
|
+
throw new Error(`Missing required adapter: ${key}`);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return adapters as AdapterRegistry;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export class NoopLogger implements LoggerAdapter {
|
|
234
|
+
debug(_message: string, ..._args: unknown[]): void {}
|
|
235
|
+
info(_message: string, ..._args: unknown[]): void {}
|
|
236
|
+
warn(_message: string, ..._args: unknown[]): void {}
|
|
237
|
+
error(_message: string, ..._args: unknown[]): void {}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
export class ConsoleLogger implements LoggerAdapter {
|
|
241
|
+
constructor(private prefix: string = '[SDK]') {}
|
|
242
|
+
|
|
243
|
+
debug(message: string, ...args: unknown[]): void {
|
|
244
|
+
console.debug(`${this.prefix} ${message}`, ...args);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
info(message: string, ...args: unknown[]): void {
|
|
248
|
+
console.info(`${this.prefix} ${message}`, ...args);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
warn(message: string, ...args: unknown[]): void {
|
|
252
|
+
console.warn(`${this.prefix} ${message}`, ...args);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
error(message: string, ...args: unknown[]): void {
|
|
256
|
+
console.error(`${this.prefix} ${message}`, ...args);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
export class NoopMetrics implements MetricsAdapter {
|
|
261
|
+
increment(_name: string, _value?: number, _tags?: Record<string, string>): void {}
|
|
262
|
+
gauge(_name: string, _value: number, _tags?: Record<string, string>): void {}
|
|
263
|
+
timing(_name: string, _durationMs: number, _tags?: Record<string, string>): void {}
|
|
264
|
+
histogram(_name: string, _value: number, _tags?: Record<string, string>): void {}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export class DefaultTimerAdapter implements TimerAdapter {
|
|
268
|
+
setTimeout(callback: () => void, ms: number): TimerHandle {
|
|
269
|
+
return setTimeout(callback, ms);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
setInterval(callback: () => void, ms: number): TimerHandle {
|
|
273
|
+
return setInterval(callback, ms);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
clearTimeout(handle: TimerHandle): void {
|
|
277
|
+
clearTimeout(handle);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
clearInterval(handle: TimerHandle): void {
|
|
281
|
+
clearInterval(handle);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
now(): number {
|
|
285
|
+
return Date.now();
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
export interface LifecycleAdapter {
|
|
290
|
+
onSuspend(callback: () => void): () => void;
|
|
291
|
+
onResume?(callback: () => void): () => void;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export class NoopLifecycleAdapter implements LifecycleAdapter {
|
|
295
|
+
onSuspend(_callback: () => void): () => void {
|
|
296
|
+
return () => {};
|
|
297
|
+
}
|
|
298
|
+
onResume(_callback: () => void): () => void {
|
|
299
|
+
return () => {};
|
|
300
|
+
}
|
|
301
|
+
}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @totemsdk/core/adapters/types
|
|
3
|
+
* Shared type definitions for SDK modules
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface WotsIndices {
|
|
7
|
+
addressIndex: number;
|
|
8
|
+
l1: number;
|
|
9
|
+
l2: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type LeaseStatus = 'pending' | 'active' | 'expired' | 'finalized' | 'cancelled';
|
|
13
|
+
|
|
14
|
+
export interface StoredLease {
|
|
15
|
+
leaseId: string;
|
|
16
|
+
leaseToken: string;
|
|
17
|
+
indices: WotsIndices;
|
|
18
|
+
expiresAt: number;
|
|
19
|
+
status: LeaseStatus;
|
|
20
|
+
createdAt: number;
|
|
21
|
+
txId?: string;
|
|
22
|
+
leaseTTL: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface WatermarkState {
|
|
26
|
+
next_addressIndex: number;
|
|
27
|
+
next_l1: number;
|
|
28
|
+
next_l2: number;
|
|
29
|
+
usedIndices: Array<[number, number, number]>;
|
|
30
|
+
lastSyncTimestamp?: number;
|
|
31
|
+
serverWatermark?: WotsIndices;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface SyncResult {
|
|
35
|
+
updated: boolean;
|
|
36
|
+
drift: number;
|
|
37
|
+
hasConflict: boolean;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface LeaseExpiryEvent {
|
|
41
|
+
leaseId: string;
|
|
42
|
+
expiresAt: number;
|
|
43
|
+
remainingMs: number;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type LeaseExpiryCallback = (event: LeaseExpiryEvent) => void;
|
|
47
|
+
|
|
48
|
+
export interface TransactionPrepareParams {
|
|
49
|
+
txId: string;
|
|
50
|
+
rootPublicKey: string;
|
|
51
|
+
to: string;
|
|
52
|
+
amount: string;
|
|
53
|
+
tokenId?: string;
|
|
54
|
+
burn?: string | null;
|
|
55
|
+
digestL2?: string | null;
|
|
56
|
+
digestL3?: string | null;
|
|
57
|
+
ttlMs?: number;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface PreparedTransaction {
|
|
61
|
+
leaseToken: string;
|
|
62
|
+
lease: WotsIndices;
|
|
63
|
+
txId: string;
|
|
64
|
+
digestTx?: string | null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface SignedTransaction {
|
|
68
|
+
txId: string;
|
|
69
|
+
signedHex: string;
|
|
70
|
+
leaseToken: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface FinalizedTransaction {
|
|
74
|
+
txId: string;
|
|
75
|
+
status: 'success' | 'failed';
|
|
76
|
+
blockHeight?: number;
|
|
77
|
+
confirmations?: number;
|
|
78
|
+
error?: string;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export type TransactionStatus =
|
|
82
|
+
| 'preparing'
|
|
83
|
+
| 'signing'
|
|
84
|
+
| 'submitting'
|
|
85
|
+
| 'pending'
|
|
86
|
+
| 'confirmed'
|
|
87
|
+
| 'failed';
|
|
88
|
+
|
|
89
|
+
export interface TransactionState {
|
|
90
|
+
txId: string;
|
|
91
|
+
status: TransactionStatus;
|
|
92
|
+
lease?: StoredLease;
|
|
93
|
+
signedHex?: string;
|
|
94
|
+
blockHeight?: number;
|
|
95
|
+
confirmations?: number;
|
|
96
|
+
error?: string;
|
|
97
|
+
createdAt: number;
|
|
98
|
+
updatedAt: number;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export interface BalanceSnapshot {
|
|
102
|
+
address: string;
|
|
103
|
+
confirmed: string;
|
|
104
|
+
unconfirmed: string;
|
|
105
|
+
total: string;
|
|
106
|
+
tokenId: string;
|
|
107
|
+
timestamp: number;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export interface BalanceUpdate {
|
|
111
|
+
type: 'snapshot' | 'delta';
|
|
112
|
+
address: string;
|
|
113
|
+
tokenId: string;
|
|
114
|
+
confirmed?: string;
|
|
115
|
+
unconfirmed?: string;
|
|
116
|
+
total?: string;
|
|
117
|
+
delta?: string;
|
|
118
|
+
timestamp: number;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export type ConnectionStatus =
|
|
122
|
+
| 'disconnected'
|
|
123
|
+
| 'connecting'
|
|
124
|
+
| 'connected'
|
|
125
|
+
| 'reconnecting'
|
|
126
|
+
| 'error';
|
|
127
|
+
|
|
128
|
+
export interface ConnectionState {
|
|
129
|
+
status: ConnectionStatus;
|
|
130
|
+
lastConnectedAt?: number;
|
|
131
|
+
lastDisconnectedAt?: number;
|
|
132
|
+
reconnectAttempts: number;
|
|
133
|
+
error?: string;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export interface QuotaInfo {
|
|
137
|
+
used: number;
|
|
138
|
+
limit: number;
|
|
139
|
+
remaining: number;
|
|
140
|
+
resetsAt: number;
|
|
141
|
+
windowMs: number;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export interface RpcError {
|
|
145
|
+
code: number;
|
|
146
|
+
message: string;
|
|
147
|
+
data?: unknown;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export class SdkError extends Error {
|
|
151
|
+
constructor(
|
|
152
|
+
message: string,
|
|
153
|
+
public readonly code: string,
|
|
154
|
+
public readonly cause?: Error
|
|
155
|
+
) {
|
|
156
|
+
super(message);
|
|
157
|
+
this.name = 'SdkError';
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export class StorageError extends SdkError {
|
|
162
|
+
constructor(message: string, cause?: Error) {
|
|
163
|
+
super(message, 'STORAGE_ERROR', cause);
|
|
164
|
+
this.name = 'StorageError';
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export class NetworkError extends SdkError {
|
|
169
|
+
constructor(message: string, cause?: Error) {
|
|
170
|
+
super(message, 'NETWORK_ERROR', cause);
|
|
171
|
+
this.name = 'NetworkError';
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export class AuthenticationError extends SdkError {
|
|
176
|
+
constructor(message: string, cause?: Error) {
|
|
177
|
+
super(message, 'AUTH_ERROR', cause);
|
|
178
|
+
this.name = 'AuthenticationError';
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export class LeaseError extends SdkError {
|
|
183
|
+
constructor(message: string, cause?: Error) {
|
|
184
|
+
super(message, 'LEASE_ERROR', cause);
|
|
185
|
+
this.name = 'LeaseError';
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export class TransactionError extends SdkError {
|
|
190
|
+
constructor(message: string, cause?: Error) {
|
|
191
|
+
super(message, 'TRANSACTION_ERROR', cause);
|
|
192
|
+
this.name = 'TransactionError';
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export class QuotaExceededError extends SdkError {
|
|
197
|
+
constructor(
|
|
198
|
+
message: string,
|
|
199
|
+
public readonly quotaInfo: QuotaInfo,
|
|
200
|
+
cause?: Error
|
|
201
|
+
) {
|
|
202
|
+
super(message, 'QUOTA_EXCEEDED', cause);
|
|
203
|
+
this.name = 'QuotaExceededError';
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export type EventUnsubscribe = () => void;
|
|
208
|
+
|
|
209
|
+
export interface EventEmitter<Events extends Record<string, unknown>> {
|
|
210
|
+
on<K extends keyof Events>(event: K, listener: (data: Events[K]) => void): EventUnsubscribe;
|
|
211
|
+
off<K extends keyof Events>(event: K, listener: (data: Events[K]) => void): void;
|
|
212
|
+
emit<K extends keyof Events>(event: K, data: Events[K]): void;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export function createEventEmitter<Events extends Record<string, unknown>>(): EventEmitter<Events> {
|
|
216
|
+
const listeners = new Map<keyof Events, Set<(data: unknown) => void>>();
|
|
217
|
+
|
|
218
|
+
return {
|
|
219
|
+
on<K extends keyof Events>(event: K, listener: (data: Events[K]) => void): EventUnsubscribe {
|
|
220
|
+
if (!listeners.has(event)) {
|
|
221
|
+
listeners.set(event, new Set());
|
|
222
|
+
}
|
|
223
|
+
listeners.get(event)!.add(listener as (data: unknown) => void);
|
|
224
|
+
return () => listeners.get(event)?.delete(listener as (data: unknown) => void);
|
|
225
|
+
},
|
|
226
|
+
|
|
227
|
+
off<K extends keyof Events>(event: K, listener: (data: Events[K]) => void): void {
|
|
228
|
+
listeners.get(event)?.delete(listener as (data: unknown) => void);
|
|
229
|
+
},
|
|
230
|
+
|
|
231
|
+
emit<K extends keyof Events>(event: K, data: Events[K]): void {
|
|
232
|
+
listeners.get(event)?.forEach(listener => listener(data));
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { scriptToAddress } from "./derive";
|
|
3
|
+
import { decodeMx } from "../../base32/src/minima32";
|
|
4
|
+
import { bytesToHex } from "@noble/hashes/utils";
|
|
5
|
+
|
|
6
|
+
describe("Script → Mx (Minima oracles)", () => {
|
|
7
|
+
it("RETURN TRUE", () => {
|
|
8
|
+
const mx = scriptToAddress("RETURN TRUE");
|
|
9
|
+
expect(mx).toBe("MxG082Z5AW0TACM86D3R2WT4Z1PKJKYGWRKDGM2DU30RB43EAVA8HBQURHCQE9V");
|
|
10
|
+
// payload should equal oracle root
|
|
11
|
+
expect(bytesToHex(decodeMx(mx)).toUpperCase()).toBe(
|
|
12
|
+
"582AA40EA996419A3D8A5D26039A4E9584B746C2C26F860DAC8372BEA4457AF6"
|
|
13
|
+
);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("LET x 1 RETURN x == 1", () => {
|
|
17
|
+
const mx = scriptToAddress("LET x 1 RETURN x == 1");
|
|
18
|
+
expect(mx).toBe("MxG085JV8JAT8VVQGR7Z8UVVQQYZ5TUEMN4Y4HU98T9SU8CVRU5Y5NRWFVU5MEF");
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("RETURN SIGNEDBY(0xFFFF)", () => {
|
|
22
|
+
const mx = scriptToAddress("RETURN SIGNEDBY(0xFFFF)");
|
|
23
|
+
expect(mx).toBe("MxG0835THZEDNNJHWU8S5AM61FGCZRRV3BB1RQN371SR4S6J0EWA2SUWYS7MZVQ");
|
|
24
|
+
});
|
|
25
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { makeMinimaAddress, convertMinimaAddress } from "./index";
|
|
3
|
+
|
|
4
|
+
describe("Address Tests (matching Java AddressTests)", () => {
|
|
5
|
+
it("testMakeMinimaAddress - should roundtrip various lengths", () => {
|
|
6
|
+
// Test cases from Java AddressTests.testMakeMinimaAddress()
|
|
7
|
+
const testCases = [
|
|
8
|
+
"0xFFFF",
|
|
9
|
+
"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", // 19 bytes (38 hex chars)
|
|
10
|
+
"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", // 66 bytes (132 hex chars)
|
|
11
|
+
"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", // 34 bytes
|
|
12
|
+
"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", // 20 bytes
|
|
13
|
+
"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" // 38 bytes
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
for (const hexInput of testCases) {
|
|
17
|
+
console.log(`Testing hex length ${(hexInput.length - 2) / 2} bytes`);
|
|
18
|
+
|
|
19
|
+
// Make Minima address
|
|
20
|
+
const mxAddress = makeMinimaAddress(hexInput);
|
|
21
|
+
console.log(` Input: ${hexInput.slice(0, 20)}...`);
|
|
22
|
+
console.log(` Output: ${mxAddress}`);
|
|
23
|
+
|
|
24
|
+
// Convert back
|
|
25
|
+
const converted = convertMinimaAddress(mxAddress);
|
|
26
|
+
|
|
27
|
+
// Should be equal (case-insensitive comparison since we uppercase on output)
|
|
28
|
+
expect(converted.toUpperCase()).toBe(hexInput.toUpperCase());
|
|
29
|
+
console.log(` ✓ Roundtrip successful\n`);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("should handle MiniData constructor test cases", () => {
|
|
34
|
+
// Test cases from the Java constructor tests
|
|
35
|
+
const testCases = [
|
|
36
|
+
"0xF0F0",
|
|
37
|
+
"0xFFFF",
|
|
38
|
+
"0xFFF0F0"
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
for (const hexInput of testCases) {
|
|
42
|
+
const mxAddress = makeMinimaAddress(hexInput);
|
|
43
|
+
const converted = convertMinimaAddress(mxAddress);
|
|
44
|
+
expect(converted.toUpperCase()).toBe(hexInput.toUpperCase());
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("should handle empty MiniData", () => {
|
|
49
|
+
// Java test includes new MiniData() which is empty
|
|
50
|
+
const empty = "0x";
|
|
51
|
+
const mxAddress = makeMinimaAddress(empty);
|
|
52
|
+
const converted = convertMinimaAddress(mxAddress);
|
|
53
|
+
expect(converted).toBe("0X");
|
|
54
|
+
});
|
|
55
|
+
});
|
package/src/binio.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export class BinWriter {
|
|
2
|
+
#buf: number[] = [];
|
|
3
|
+
get bytes(): Uint8Array { return new Uint8Array(this.#buf); }
|
|
4
|
+
|
|
5
|
+
writeU8(n: number) { this.#buf.push(n & 0xff); }
|
|
6
|
+
writeU16(n: number) { this.#buf.push((n >>> 8) & 0xff, n & 0xff); } // big-endian
|
|
7
|
+
writeU32(n: number) {
|
|
8
|
+
this.#buf.push((n>>>24)&0xff, (n>>>16)&0xff, (n>>>8)&0xff, n&0xff);
|
|
9
|
+
}
|
|
10
|
+
writeU64(bi: bigint) {
|
|
11
|
+
// big-endian 8 bytes
|
|
12
|
+
const out = new Uint8Array(8);
|
|
13
|
+
let x = bi;
|
|
14
|
+
for (let i = 7; i >= 0; i--) {
|
|
15
|
+
out[i] = Number(x & 0xffn);
|
|
16
|
+
x >>= 8n;
|
|
17
|
+
}
|
|
18
|
+
this.writeBytes(out);
|
|
19
|
+
}
|
|
20
|
+
writeBytes(b: Uint8Array) { for (const x of b) this.#buf.push(x); }
|
|
21
|
+
}
|