@lerna-labs/hydra-sdk 1.0.0-beta.22 → 1.0.0-beta.25

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.
@@ -11,4 +11,4 @@
11
11
  * }
12
12
  * ```
13
13
  */
14
- export type { ClientInput, ClientMessage, ConnectionState, HeadStatus, HydraHeadInfo, HydraMessage, HydraMonitorOptions, HydraStatus, HydraTransaction, HydraWsMessage, hydraStatus, hydraTransaction, ServerOutput, TimestampedEvent, } from './types.js';
14
+ export type { ClientInput, ClientMessage, ConfirmedSnapshot, ConnectionState, HeadStatus, HydraHeadInfo, HydraMessage, HydraMonitorOptions, HydraSnapshot, HydraStatus, HydraTransaction, HydraWsMessage, hydraStatus, hydraTransaction, ServerOutput, TimestampedEvent, } from './types.js';
@@ -50,6 +50,28 @@ export type HydraStatus = 'IDLE' | 'INITIALIZING' | 'OPEN' | 'CLOSED' | 'FANOUT_
50
50
  export type hydraStatus = HydraStatus;
51
51
  /** Connection state of the WebSocket. */
52
52
  export type ConnectionState = 'IDLE' | 'CONNECTING' | 'CONNECTED' | 'FAILED' | 'DISCONNECTED';
53
+ /** A confirmed Hydra L2 snapshot. */
54
+ export interface HydraSnapshot {
55
+ headId: string;
56
+ version: number;
57
+ number: number;
58
+ confirmed: HydraTransaction[];
59
+ utxo: HydraUTxOs;
60
+ utxoToCommit: HydraUTxOs | null;
61
+ utxoToDecommit: HydraUTxOs | null;
62
+ }
63
+ /** Multi-party aggregate signature map. */
64
+ export type MultiSignature = Record<string, string>;
65
+ /** Discriminated union for confirmed snapshot variants. */
66
+ export type ConfirmedSnapshot = {
67
+ tag: 'InitialSnapshot';
68
+ headId: string;
69
+ initialUTxO?: HydraUTxOs;
70
+ } | {
71
+ tag: 'ConfirmedSnapshot';
72
+ snapshot: HydraSnapshot;
73
+ signatures: MultiSignature;
74
+ };
53
75
  /** Messages that can be sent to the Hydra node over WebSocket. */
54
76
  export type ClientInput = {
55
77
  tag: 'Init';
@@ -60,43 +82,41 @@ export type ClientInput = {
60
82
  transaction: HydraTransaction;
61
83
  } | {
62
84
  tag: 'Close';
85
+ } | {
86
+ tag: 'SafeClose';
63
87
  } | {
64
88
  tag: 'Contest';
65
89
  } | {
66
90
  tag: 'Fanout';
67
91
  } | {
68
92
  tag: 'Decommit';
69
- transaction: HydraTransaction;
93
+ decommitTx: HydraTransaction;
70
94
  } | {
71
95
  tag: 'Recover';
72
96
  recoverTxId: string;
97
+ } | {
98
+ tag: 'SideLoadSnapshot';
99
+ snapshot: ConfirmedSnapshot;
73
100
  };
74
- /** Greetings message received on initial WebSocket connection. */
75
101
  /** Hydra node environment info reported in Greetings. */
76
102
  export interface HydraEnv {
77
- /** Configured peer addresses (comma-separated or empty). */
78
- configuredPeers: string;
79
- /** Contestation period in seconds. */
80
- contestationPeriod: number;
81
- /** Deposit period in seconds. */
82
- depositPeriod: number;
83
- /** Other parties' verification keys. */
103
+ party: {
104
+ vkey: string;
105
+ };
106
+ signingKey?: string;
84
107
  otherParties: {
85
108
  vkey: string;
86
109
  }[];
87
- /** All participant key hashes. */
88
110
  participants: string[];
89
- /** This node's party identity. */
90
- party: {
91
- vkey: string;
92
- };
111
+ contestationPeriod: number;
112
+ depositPeriod: number;
113
+ unsyncedPeriod?: number;
114
+ configuredPeers: string;
93
115
  [key: string]: unknown;
94
116
  }
95
117
  /** Network connectivity info reported in Greetings. */
96
118
  export interface HydraNetworkInfo {
97
- /** Whether the node is connected to the Cardano network. */
98
119
  networkConnected: boolean;
99
- /** Per-peer connection info. */
100
120
  peersInfo: Record<string, unknown>;
101
121
  [key: string]: unknown;
102
122
  }
@@ -109,40 +129,28 @@ export interface GreetingsMessage {
109
129
  headStatus: HeadStatus;
110
130
  hydraHeadId?: string;
111
131
  snapshotUtxo?: HydraUTxOs;
112
- hydraNodeVersion?: string;
113
- env?: HydraEnv;
114
- networkInfo?: HydraNetworkInfo;
115
- /** L1 chain sync status (e.g. `"InSync"`). Available in Hydra >= 1.3.0. */
116
- chainSyncedStatus?: string;
117
- /** Current L1 slot number. Available in Hydra >= 1.3.0. */
118
- currentSlot?: number;
132
+ timestamp?: string;
133
+ hydraNodeVersion: string;
134
+ env: HydraEnv;
135
+ networkInfo: HydraNetworkInfo;
136
+ chainSyncedStatus: string;
137
+ currentSlot: number;
119
138
  }
120
139
  /**
121
140
  * Summary of Hydra head info extracted from the Greetings message.
122
141
  * Excludes the full UTxO snapshot to keep payloads small.
123
142
  */
124
143
  export interface HydraHeadInfo {
125
- /** Current head status. */
126
144
  headStatus: HeadStatus;
127
- /** On-chain head identifier / policy ID (null when head is Idle / not yet initialized). */
128
145
  headId: string | null;
129
- /** Hydra node version string. */
130
146
  nodeVersion: string | null;
131
- /** This node's verification key. */
132
147
  me: string;
133
- /** Contestation period in seconds. */
134
148
  contestationPeriod: number | null;
135
- /** Deposit period in seconds. */
136
149
  depositPeriod: number | null;
137
- /** All participant key hashes. */
138
150
  participants: string[];
139
- /** Whether the node is connected to the Cardano network. */
140
151
  networkConnected: boolean;
141
- /** Number of configured peers. */
142
152
  peerCount: number;
143
- /** L1 chain sync status (e.g. `"InSync"`). Null if not reported (Hydra < 1.3.0). */
144
153
  chainSyncedStatus: string | null;
145
- /** Current L1 slot number. Null if not reported (Hydra < 1.3.0). */
146
154
  currentSlot: number | null;
147
155
  }
148
156
  export interface HeadIsInitializingMessage {
@@ -151,6 +159,8 @@ export interface HeadIsInitializingMessage {
151
159
  parties: {
152
160
  vkey: string;
153
161
  }[];
162
+ seq: number;
163
+ timestamp: string;
154
164
  [key: string]: unknown;
155
165
  }
156
166
  export interface CommittedMessage {
@@ -159,78 +169,309 @@ export interface CommittedMessage {
159
169
  vkey: string;
160
170
  };
161
171
  utxo: HydraUTxOs;
172
+ seq: number;
173
+ timestamp: string;
162
174
  [key: string]: unknown;
163
175
  }
164
176
  export interface HeadIsOpenMessage {
165
177
  tag: 'HeadIsOpen';
178
+ headId: string;
166
179
  utxo: HydraUTxOs;
180
+ seq: number;
181
+ timestamp: string;
167
182
  [key: string]: unknown;
168
183
  }
169
184
  export interface HeadIsClosedMessage {
170
185
  tag: 'HeadIsClosed';
186
+ headId: string;
187
+ snapshotNumber: number;
188
+ contestationDeadline: string;
189
+ seq: number;
190
+ timestamp: string;
171
191
  [key: string]: unknown;
172
192
  }
173
193
  export interface HeadIsContestedMessage {
174
194
  tag: 'HeadIsContested';
195
+ headId: string;
196
+ snapshotNumber: number;
197
+ contestationDeadline: string;
198
+ seq: number;
199
+ timestamp: string;
175
200
  [key: string]: unknown;
176
201
  }
177
202
  export interface ReadyToFanoutMessage {
178
203
  tag: 'ReadyToFanout';
204
+ headId: string;
205
+ seq: number;
206
+ timestamp: string;
179
207
  [key: string]: unknown;
180
208
  }
181
209
  export interface HeadIsAbortedMessage {
182
210
  tag: 'HeadIsAborted';
211
+ headId: string;
212
+ utxo: HydraUTxOs;
213
+ seq: number;
214
+ timestamp: string;
183
215
  [key: string]: unknown;
184
216
  }
185
217
  export interface HeadIsFinalizedMessage {
186
218
  tag: 'HeadIsFinalized';
219
+ headId: string;
220
+ utxo: HydraUTxOs;
221
+ seq: number;
222
+ timestamp: string;
187
223
  [key: string]: unknown;
188
224
  }
189
225
  export interface TxValidMessage {
190
226
  tag: 'TxValid';
191
- transaction: HydraTransaction;
227
+ headId: string;
228
+ transactionId: string;
229
+ seq: number;
230
+ timestamp: string;
192
231
  [key: string]: unknown;
193
232
  }
194
233
  export interface TxInvalidMessage {
195
234
  tag: 'TxInvalid';
235
+ headId: string;
236
+ utxo: HydraUTxOs;
196
237
  transaction: HydraTransaction;
197
238
  validationError: {
198
239
  reason: string;
199
240
  };
241
+ seq: number;
242
+ timestamp: string;
200
243
  [key: string]: unknown;
201
244
  }
202
245
  export interface SnapshotConfirmedMessage {
203
246
  tag: 'SnapshotConfirmed';
247
+ headId: string;
248
+ snapshot: HydraSnapshot;
249
+ seq: number;
250
+ timestamp: string;
204
251
  [key: string]: unknown;
205
252
  }
206
- export interface DecommitApprovedMessage {
207
- tag: 'DecommitApproved';
253
+ export interface SnapshotSideLoadedMessage {
254
+ tag: 'SnapshotSideLoaded';
255
+ headId: string;
256
+ snapshotNumber: number;
257
+ seq: number;
258
+ timestamp: string;
208
259
  [key: string]: unknown;
209
260
  }
210
- export interface DecommitInvalidMessage {
211
- tag: 'DecommitInvalid';
212
- decommitInvalidReason: unknown;
261
+ export interface CommitRecordedMessage {
262
+ tag: 'CommitRecorded';
263
+ headId: string;
264
+ utxoToCommit: HydraUTxOs;
265
+ pendingDeposit: string;
266
+ deadline: string;
267
+ seq: number;
268
+ timestamp: string;
213
269
  [key: string]: unknown;
214
270
  }
215
- export interface DecommitFinalizedMessage {
216
- tag: 'DecommitFinalized';
271
+ export interface CommitApprovedMessage {
272
+ tag: 'CommitApproved';
273
+ headId: string;
274
+ utxoToCommit: HydraUTxOs;
275
+ seq: number;
276
+ timestamp: string;
217
277
  [key: string]: unknown;
218
278
  }
219
279
  export interface CommitFinalizedMessage {
220
280
  tag: 'CommitFinalized';
281
+ headId: string;
282
+ depositTxId: string;
283
+ seq: number;
284
+ timestamp: string;
221
285
  [key: string]: unknown;
222
286
  }
223
- export interface CommitApprovedMessage {
224
- tag: 'CommitApproved';
287
+ export interface CommitRecoveredMessage {
288
+ tag: 'CommitRecovered';
289
+ headId: string;
290
+ recoveredUTxO: HydraUTxOs;
291
+ recoveredTxId: string;
292
+ seq: number;
293
+ timestamp: string;
294
+ [key: string]: unknown;
295
+ }
296
+ export interface DepositActivatedMessage {
297
+ tag: 'DepositActivated';
298
+ headId: string;
299
+ depositTxId: string;
300
+ deadline: string;
301
+ chainTime: string;
302
+ seq: number;
303
+ timestamp: string;
304
+ [key: string]: unknown;
305
+ }
306
+ export interface DepositExpiredMessage {
307
+ tag: 'DepositExpired';
308
+ headId: string;
309
+ depositTxId: string;
310
+ deadline: string;
311
+ chainTime: string;
312
+ seq: number;
313
+ timestamp: string;
314
+ [key: string]: unknown;
315
+ }
316
+ export interface DecommitRequestedMessage {
317
+ tag: 'DecommitRequested';
318
+ headId: string;
319
+ decommitTx: HydraTransaction;
320
+ utxoToDecommit: HydraUTxOs;
321
+ seq: number;
322
+ timestamp: string;
323
+ [key: string]: unknown;
324
+ }
325
+ export interface DecommitApprovedMessage {
326
+ tag: 'DecommitApproved';
327
+ headId: string;
328
+ decommitTxId: string;
329
+ utxoToDecommit: HydraUTxOs;
330
+ seq: number;
331
+ timestamp: string;
332
+ [key: string]: unknown;
333
+ }
334
+ export interface DecommitFinalizedMessage {
335
+ tag: 'DecommitFinalized';
336
+ headId: string;
337
+ distributedUTxO: HydraUTxOs;
338
+ seq: number;
339
+ timestamp: string;
340
+ [key: string]: unknown;
341
+ }
342
+ export interface DecommitInvalidMessage {
343
+ tag: 'DecommitInvalid';
344
+ headId: string;
345
+ decommitTx: HydraTransaction;
346
+ decommitInvalidReason: {
347
+ tag: 'DecommitTxInvalid';
348
+ localUTxO: HydraUTxOs;
349
+ validationError: {
350
+ reason: string;
351
+ };
352
+ } | {
353
+ tag: 'DecommitAlreadyInFlight';
354
+ otherDecommitTxId: string;
355
+ };
356
+ seq: number;
357
+ timestamp: string;
225
358
  [key: string]: unknown;
226
359
  }
227
360
  export interface CommandFailedMessage {
228
361
  tag: 'CommandFailed';
229
362
  clientInput: ClientInput;
363
+ state: unknown;
230
364
  [key: string]: unknown;
231
365
  }
232
366
  export interface PostTxOnChainFailedMessage {
233
367
  tag: 'PostTxOnChainFailed';
368
+ postChainTx: unknown;
369
+ postTxError: unknown;
370
+ [key: string]: unknown;
371
+ }
372
+ export interface InvalidInputMessage {
373
+ tag: 'InvalidInput';
374
+ reason: string;
375
+ input: string;
376
+ [key: string]: unknown;
377
+ }
378
+ export interface RejectedInputBecauseUnsyncedMessage {
379
+ tag: 'RejectedInputBecauseUnsynced';
380
+ clientInput: ClientInput;
381
+ drift: number;
382
+ [key: string]: unknown;
383
+ }
384
+ export interface SideLoadSnapshotRejectedMessage {
385
+ tag: 'SideLoadSnapshotRejected';
386
+ clientInput: ClientInput;
387
+ requirementFailure: unknown;
388
+ [key: string]: unknown;
389
+ }
390
+ export interface PeerConnectedMessage {
391
+ tag: 'PeerConnected';
392
+ peer: string;
393
+ seq: number;
394
+ timestamp: string;
395
+ [key: string]: unknown;
396
+ }
397
+ export interface PeerDisconnectedMessage {
398
+ tag: 'PeerDisconnected';
399
+ peer: string;
400
+ seq: number;
401
+ timestamp: string;
402
+ [key: string]: unknown;
403
+ }
404
+ export interface NetworkConnectedMessage {
405
+ tag: 'NetworkConnected';
406
+ seq: number;
407
+ timestamp: string;
408
+ [key: string]: unknown;
409
+ }
410
+ export interface NetworkDisconnectedMessage {
411
+ tag: 'NetworkDisconnected';
412
+ seq: number;
413
+ timestamp: string;
414
+ [key: string]: unknown;
415
+ }
416
+ export interface NetworkVersionMismatchMessage {
417
+ tag: 'NetworkVersionMismatch';
418
+ ourVersion: unknown;
419
+ theirVersion: unknown;
420
+ seq: number;
421
+ timestamp: string;
422
+ [key: string]: unknown;
423
+ }
424
+ export interface NetworkClusterIDMismatchMessage {
425
+ tag: 'NetworkClusterIDMismatch';
426
+ clusterPeers?: unknown;
427
+ misconfiguredPeers?: unknown;
428
+ seq: number;
429
+ timestamp: string;
430
+ [key: string]: unknown;
431
+ }
432
+ export interface SyncedStatusReportMessage {
433
+ tag: 'SyncedStatusReport';
434
+ chainSlot: number;
435
+ chainTime: string;
436
+ drift: number;
437
+ synced: string;
438
+ [key: string]: unknown;
439
+ }
440
+ export interface NodeSyncedMessage {
441
+ tag: 'NodeSynced';
442
+ chainSlot: number;
443
+ chainTime: string;
444
+ drift: number;
445
+ seq: number;
446
+ timestamp: string;
447
+ [key: string]: unknown;
448
+ }
449
+ export interface NodeUnsyncedMessage {
450
+ tag: 'NodeUnsynced';
451
+ chainSlot: number;
452
+ chainTime: string;
453
+ drift: number;
454
+ seq: number;
455
+ timestamp: string;
456
+ [key: string]: unknown;
457
+ }
458
+ export interface IgnoredHeadInitializingMessage {
459
+ tag: 'IgnoredHeadInitializing';
460
+ headId: string;
461
+ contestationPeriod: number;
462
+ parties: {
463
+ vkey: string;
464
+ }[];
465
+ participants: string[];
466
+ seq: number;
467
+ timestamp: string;
468
+ [key: string]: unknown;
469
+ }
470
+ export interface EventLogRotatedMessage {
471
+ tag: 'EventLogRotated';
472
+ seq: number;
473
+ checkpoint: unknown;
474
+ timestamp: string;
234
475
  [key: string]: unknown;
235
476
  }
236
477
  /** Catch-all for message types not explicitly defined above. */
@@ -239,7 +480,7 @@ export interface UnknownMessage {
239
480
  [key: string]: unknown;
240
481
  }
241
482
  /** All possible messages the Hydra node can send over its WebSocket API. */
242
- export type ServerOutput = GreetingsMessage | HeadIsInitializingMessage | CommittedMessage | HeadIsOpenMessage | HeadIsClosedMessage | HeadIsContestedMessage | ReadyToFanoutMessage | HeadIsAbortedMessage | HeadIsFinalizedMessage | TxValidMessage | TxInvalidMessage | SnapshotConfirmedMessage | DecommitApprovedMessage | DecommitInvalidMessage | DecommitFinalizedMessage | CommitFinalizedMessage | CommitApprovedMessage | CommandFailedMessage | PostTxOnChainFailedMessage | UnknownMessage;
483
+ export type ServerOutput = GreetingsMessage | HeadIsInitializingMessage | CommittedMessage | HeadIsOpenMessage | HeadIsClosedMessage | HeadIsContestedMessage | ReadyToFanoutMessage | HeadIsAbortedMessage | HeadIsFinalizedMessage | TxValidMessage | TxInvalidMessage | SnapshotConfirmedMessage | SnapshotSideLoadedMessage | CommitRecordedMessage | CommitApprovedMessage | CommitFinalizedMessage | CommitRecoveredMessage | DepositActivatedMessage | DepositExpiredMessage | DecommitRequestedMessage | DecommitApprovedMessage | DecommitFinalizedMessage | DecommitInvalidMessage | CommandFailedMessage | PostTxOnChainFailedMessage | InvalidInputMessage | RejectedInputBecauseUnsyncedMessage | SideLoadSnapshotRejectedMessage | PeerConnectedMessage | PeerDisconnectedMessage | NetworkConnectedMessage | NetworkDisconnectedMessage | NetworkVersionMismatchMessage | NetworkClusterIDMismatchMessage | SyncedStatusReportMessage | NodeSyncedMessage | NodeUnsyncedMessage | IgnoredHeadInitializingMessage | EventLogRotatedMessage | UnknownMessage;
243
484
  /** Client echo messages (errors, command failures). */
244
485
  export type ClientMessage = CommandFailedMessage | PostTxOnChainFailedMessage;
245
486
  /** Any message received via the Hydra WebSocket. */
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ export type { DiskCache, DiskCacheConfig } from './cache/disk-cache.js';
2
2
  export { createDiskCache } from './cache/disk-cache.js';
3
3
  export { optionalEnv, requireEnv } from './config.js';
4
4
  export { HydraMonitor } from './hydra/hydra-monitor.js';
5
- export type { HeadStatus, HydraHeadInfo, HydraMessage, HydraMonitorOptions, HydraStatus, HydraTransaction, HydraWsMessage, hydraStatus, hydraTransaction, ServerOutput, TimestampedEvent, } from './hydra/messages.js';
5
+ export type { ConfirmedSnapshot, HeadStatus, HydraHeadInfo, HydraMessage, HydraMonitorOptions, HydraSnapshot, HydraStatus, HydraTransaction, HydraWsMessage, hydraStatus, hydraTransaction, ServerOutput, TimestampedEvent, } from './hydra/messages.js';
6
6
  export type { ParsedUtxo, UtxoQueryOptions } from './hydra/utxo.js';
7
7
  export { getUtxoSet, queryUtxoByAddress } from './hydra/utxo.js';
8
8
  export type { IpfsClient, IpfsConfig, PinResult } from './ipfs/ipfs.js';
@@ -23,13 +23,16 @@ export function verifySignature(signature, message, signingAddress, signatureKey
23
23
  const signatureBytes = coseSign1.signature();
24
24
  const [, , , payload1] = cbor.decode(bufferToHex(coseSign1.signed_data().to_bytes()));
25
25
  const signaturePayloadAscii = bufferToAscii(payload1);
26
- const { words } = bech32.decode(signingAddress);
26
+ const { words, prefix } = bech32.decode(signingAddress);
27
27
  const addressBytes = Buffer.from(bech32.fromWords(words));
28
28
  const coseSigKey = cbor.decode(signatureKey);
29
29
  const cosePublicKey = coseSigKey.get(-2);
30
30
  const sigKey = CSL.PublicKey.from_bytes(cosePublicKey);
31
31
  const publicKeyHash = sigKey.hash();
32
- const address_matches = addressBytes.toString('hex').slice(2) === publicKeyHash.to_hex();
32
+ // pool1... bech32 encodes the raw 28-byte key hash with no header byte.
33
+ // All other address types (addr, drep, stake) have a 1-byte header prefix.
34
+ const addressHex = addressBytes.toString('hex');
35
+ const address_matches = prefix === 'pool' ? addressHex === publicKeyHash.to_hex() : addressHex.slice(2) === publicKeyHash.to_hex();
33
36
  const sig = CSL.Ed25519Signature.from_bytes(signatureBytes);
34
37
  const validates = sigKey.verify(coseSign1.signed_data().to_bytes(), sig);
35
38
  const message_matches = signaturePayloadAscii === message;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lerna-labs/hydra-sdk",
3
- "version": "1.0.0-beta.22",
3
+ "version": "1.0.0-beta.25",
4
4
  "description": "TypeScript SDK for managing Cardano Hydra Heads — lifecycle, UTxO queries, wallet management, transaction submission, and signature verification",
5
5
  "keywords": [
6
6
  "cardano",
@@ -48,13 +48,13 @@
48
48
  "devDependencies": {
49
49
  "@types/ws": "^8.18.1"
50
50
  },
51
- "homepage": "https://github.com/Lerna-Labs/hydra-sdk#readme",
51
+ "homepage": "https://github.com/lerna-labs/hydra-sdk#readme",
52
52
  "bugs": {
53
- "url": "https://github.com/Lerna-Labs/hydra-sdk/issues"
53
+ "url": "https://github.com/lerna-labs/hydra-sdk/issues"
54
54
  },
55
55
  "repository": {
56
56
  "type": "git",
57
- "url": "https://github.com/Lerna-Labs/hydra-sdk",
57
+ "url": "https://github.com/lerna-labs/hydra-sdk",
58
58
  "directory": "packages/core"
59
59
  }
60
60
  }