@originals/sdk 1.5.0 → 1.6.1
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/adapters/FeeOracleMock.js +2 -2
- package/dist/bitcoin/OrdinalsClient.d.ts +1 -1
- package/dist/bitcoin/OrdinalsClient.js +10 -8
- package/dist/bitcoin/PSBTBuilder.js +1 -1
- package/dist/bitcoin/utxo-selection.js +2 -2
- package/dist/cel/ExternalReferenceManager.d.ts +57 -0
- package/dist/cel/ExternalReferenceManager.js +73 -0
- package/dist/cel/OriginalsCel.d.ts +245 -0
- package/dist/cel/OriginalsCel.js +349 -0
- package/dist/cel/algorithms/createEventLog.d.ts +32 -0
- package/dist/cel/algorithms/createEventLog.js +56 -0
- package/dist/cel/algorithms/deactivateEventLog.d.ts +35 -0
- package/dist/cel/algorithms/deactivateEventLog.js +91 -0
- package/dist/cel/algorithms/index.d.ts +10 -0
- package/dist/cel/algorithms/index.js +10 -0
- package/dist/cel/algorithms/updateEventLog.d.ts +34 -0
- package/dist/cel/algorithms/updateEventLog.js +82 -0
- package/dist/cel/algorithms/verifyEventLog.d.ts +45 -0
- package/dist/cel/algorithms/verifyEventLog.js +255 -0
- package/dist/cel/algorithms/witnessEvent.d.ts +29 -0
- package/dist/cel/algorithms/witnessEvent.js +75 -0
- package/dist/cel/cli/create.d.ts +36 -0
- package/dist/cel/cli/create.js +282 -0
- package/dist/cel/cli/index.d.ts +11 -0
- package/dist/cel/cli/index.js +351 -0
- package/dist/cel/cli/inspect.d.ts +30 -0
- package/dist/cel/cli/inspect.js +475 -0
- package/dist/cel/cli/migrate.d.ts +41 -0
- package/dist/cel/cli/migrate.js +405 -0
- package/dist/cel/cli/verify.d.ts +31 -0
- package/dist/cel/cli/verify.js +205 -0
- package/dist/cel/hash.d.ts +46 -0
- package/dist/cel/hash.js +66 -0
- package/dist/cel/index.d.ts +15 -0
- package/dist/cel/index.js +15 -0
- package/dist/cel/layers/BtcoCelManager.d.ts +121 -0
- package/dist/cel/layers/BtcoCelManager.js +329 -0
- package/dist/cel/layers/PeerCelManager.d.ts +151 -0
- package/dist/cel/layers/PeerCelManager.js +299 -0
- package/dist/cel/layers/WebVHCelManager.d.ts +122 -0
- package/dist/cel/layers/WebVHCelManager.js +291 -0
- package/dist/cel/layers/index.d.ts +13 -0
- package/dist/cel/layers/index.js +16 -0
- package/dist/cel/serialization/cbor.d.ts +42 -0
- package/dist/cel/serialization/cbor.js +163 -0
- package/dist/cel/serialization/index.d.ts +9 -0
- package/dist/cel/serialization/index.js +9 -0
- package/dist/cel/serialization/json.d.ts +41 -0
- package/dist/cel/serialization/json.js +180 -0
- package/dist/cel/types.d.ts +149 -0
- package/dist/cel/types.js +7 -0
- package/dist/cel/witnesses/BitcoinWitness.d.ts +83 -0
- package/dist/cel/witnesses/BitcoinWitness.js +116 -0
- package/dist/cel/witnesses/HttpWitness.d.ts +79 -0
- package/dist/cel/witnesses/HttpWitness.js +163 -0
- package/dist/cel/witnesses/WitnessService.d.ts +49 -0
- package/dist/cel/witnesses/WitnessService.js +10 -0
- package/dist/cel/witnesses/index.d.ts +10 -0
- package/dist/cel/witnesses/index.js +7 -0
- package/dist/core/OriginalsSDK.js +5 -1
- package/dist/crypto/Signer.js +14 -6
- package/dist/crypto/noble-init.js +20 -1
- package/dist/did/BtcoDidResolver.d.ts +2 -2
- package/dist/did/BtcoDidResolver.js +12 -8
- package/dist/did/DIDManager.js +6 -4
- package/dist/did/KeyManager.d.ts +1 -1
- package/dist/did/KeyManager.js +7 -4
- package/dist/did/WebVHManager.js +1 -1
- package/dist/did/createBtcoDidDocument.js +2 -1
- package/dist/events/types.d.ts +4 -1
- package/dist/examples/create-module-original.js +1 -1
- package/dist/examples/full-lifecycle-flow.js +2 -2
- package/dist/index.d.ts +13 -0
- package/dist/index.js +12 -0
- package/dist/kinds/KindRegistry.js +59 -29
- package/dist/lifecycle/BatchOperations.d.ts +5 -3
- package/dist/lifecycle/BatchOperations.js +11 -5
- package/dist/lifecycle/LifecycleManager.d.ts +1 -1
- package/dist/lifecycle/LifecycleManager.js +42 -33
- package/dist/lifecycle/OriginalsAsset.js +2 -2
- package/dist/migration/MigrationManager.js +67 -3
- package/dist/storage/LocalStorageAdapter.js +4 -1
- package/dist/storage/MemoryStorageAdapter.js +7 -7
- package/dist/types/network.js +6 -3
- package/dist/utils/Logger.d.ts +6 -6
- package/dist/utils/Logger.js +5 -3
- package/dist/utils/MetricsCollector.js +1 -1
- package/dist/utils/bitcoin-address.js +4 -2
- package/dist/utils/cbor.js +16 -3
- package/dist/utils/encoding.d.ts +4 -4
- package/dist/utils/encoding.js +7 -6
- package/dist/utils/hash.js +6 -1
- package/dist/utils/serialization.d.ts +2 -2
- package/dist/utils/serialization.js +7 -5
- package/dist/utils/telemetry.js +6 -2
- package/dist/utils/validation.js +8 -4
- package/dist/vc/CredentialManager.d.ts +8 -8
- package/dist/vc/CredentialManager.js +46 -33
- package/dist/vc/Issuer.d.ts +2 -2
- package/dist/vc/Issuer.js +5 -1
- package/dist/vc/Verifier.d.ts +2 -2
- package/dist/vc/Verifier.js +12 -6
- package/dist/vc/documentLoader.d.ts +5 -3
- package/dist/vc/documentLoader.js +5 -4
- package/package.json +4 -1
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebVHCelManager - CEL Manager for did:webvh Layer
|
|
3
|
+
*
|
|
4
|
+
* Manages migration of Originals assets to the did:webvh layer (Layer 1).
|
|
5
|
+
* This layer provides HTTP-based witnessing for verifiable history.
|
|
6
|
+
*
|
|
7
|
+
* The did:webvh (Web Verifiable History) method combines domain-based
|
|
8
|
+
* resolution with cryptographic event logging for discoverable assets.
|
|
9
|
+
*
|
|
10
|
+
* @see https://identity.foundation/didwebvh/
|
|
11
|
+
*/
|
|
12
|
+
import { updateEventLog } from '../algorithms/updateEventLog';
|
|
13
|
+
import { witnessEvent } from '../algorithms/witnessEvent';
|
|
14
|
+
/**
|
|
15
|
+
* WebVHCelManager - Manages CEL-based asset migration to did:webvh layer
|
|
16
|
+
*
|
|
17
|
+
* The webvh layer is the first publication layer for Originals assets.
|
|
18
|
+
* Assets at this layer:
|
|
19
|
+
* - Have a did:webvh identifier based on a domain
|
|
20
|
+
* - Can have HTTP-based witness attestations
|
|
21
|
+
* - Are discoverable via web-based DID resolution
|
|
22
|
+
* - Can be further migrated to did:btco layer
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const httpWitness = new HttpWitness('https://witness.example.com/api/attest');
|
|
27
|
+
* const manager = new WebVHCelManager(
|
|
28
|
+
* async (data) => createEdDsaProof(data, privateKey),
|
|
29
|
+
* 'example.com',
|
|
30
|
+
* [httpWitness]
|
|
31
|
+
* );
|
|
32
|
+
*
|
|
33
|
+
* const webvhLog = await manager.migrate(peerLog);
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export class WebVHCelManager {
|
|
37
|
+
/**
|
|
38
|
+
* Creates a new WebVHCelManager instance
|
|
39
|
+
*
|
|
40
|
+
* @param signer - Function that signs data and returns a DataIntegrityProof
|
|
41
|
+
* @param domain - The domain for the did:webvh DID (e.g., 'example.com')
|
|
42
|
+
* @param witnesses - Optional array of witness services for attestations
|
|
43
|
+
* @param config - Optional configuration options
|
|
44
|
+
*/
|
|
45
|
+
constructor(signer, domain, witnesses = [], config = {}) {
|
|
46
|
+
if (typeof signer !== 'function') {
|
|
47
|
+
throw new Error('WebVHCelManager requires a signer function');
|
|
48
|
+
}
|
|
49
|
+
if (!domain || typeof domain !== 'string') {
|
|
50
|
+
throw new Error('WebVHCelManager requires a valid domain string');
|
|
51
|
+
}
|
|
52
|
+
// Basic domain validation
|
|
53
|
+
if (!/^[a-zA-Z0-9][a-zA-Z0-9.-]*[a-zA-Z0-9]$/.test(domain) && !/^[a-zA-Z0-9]$/.test(domain)) {
|
|
54
|
+
throw new Error(`Invalid domain format: ${domain}`);
|
|
55
|
+
}
|
|
56
|
+
if (!Array.isArray(witnesses)) {
|
|
57
|
+
throw new Error('witnesses must be an array');
|
|
58
|
+
}
|
|
59
|
+
this.signer = signer;
|
|
60
|
+
this.domain = domain;
|
|
61
|
+
this.witnesses = witnesses;
|
|
62
|
+
this.config = {
|
|
63
|
+
proofPurpose: 'assertionMethod',
|
|
64
|
+
...config,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Migrates a peer layer event log to the did:webvh layer
|
|
69
|
+
*
|
|
70
|
+
* This method:
|
|
71
|
+
* 1. Validates the input log (must have a create event with peer layer data)
|
|
72
|
+
* 2. Generates a new did:webvh DID based on the domain
|
|
73
|
+
* 3. Creates an update event with migration data
|
|
74
|
+
* 4. Optionally adds witness proofs from configured witnesses
|
|
75
|
+
* 5. Returns the updated EventLog
|
|
76
|
+
*
|
|
77
|
+
* @param peerLog - The event log from the peer layer to migrate
|
|
78
|
+
* @returns Promise resolving to an EventLog with the migration event appended
|
|
79
|
+
*
|
|
80
|
+
* @throws Error if the log is empty, deactivated, or not from peer layer
|
|
81
|
+
* @throws Error if signer produces invalid proof
|
|
82
|
+
* @throws Error if witness service fails (if witnesses configured)
|
|
83
|
+
*/
|
|
84
|
+
async migrate(peerLog) {
|
|
85
|
+
// Validate input log
|
|
86
|
+
if (!peerLog || !peerLog.events || peerLog.events.length === 0) {
|
|
87
|
+
throw new Error('Cannot migrate an empty event log');
|
|
88
|
+
}
|
|
89
|
+
// Get the create event to extract source DID
|
|
90
|
+
const createEvent = peerLog.events[0];
|
|
91
|
+
if (createEvent.type !== 'create') {
|
|
92
|
+
throw new Error('First event must be a create event');
|
|
93
|
+
}
|
|
94
|
+
// Extract source data
|
|
95
|
+
const createData = createEvent.data;
|
|
96
|
+
const sourceDid = createData.did;
|
|
97
|
+
if (!sourceDid) {
|
|
98
|
+
throw new Error('Create event must have a did field');
|
|
99
|
+
}
|
|
100
|
+
// Validate source is from peer layer
|
|
101
|
+
const sourceLayer = createData.layer;
|
|
102
|
+
if (sourceLayer && sourceLayer !== 'peer') {
|
|
103
|
+
throw new Error(`Cannot migrate from ${sourceLayer} layer to webvh layer. Expected peer layer.`);
|
|
104
|
+
}
|
|
105
|
+
// Check if log is already deactivated
|
|
106
|
+
const lastEvent = peerLog.events[peerLog.events.length - 1];
|
|
107
|
+
if (lastEvent.type === 'deactivate') {
|
|
108
|
+
throw new Error('Cannot migrate a deactivated event log');
|
|
109
|
+
}
|
|
110
|
+
// Generate did:webvh DID
|
|
111
|
+
const targetDid = this.generateWebVHDid(sourceDid);
|
|
112
|
+
// Prepare migration data
|
|
113
|
+
const migrationData = {
|
|
114
|
+
sourceDid,
|
|
115
|
+
targetDid,
|
|
116
|
+
layer: 'webvh',
|
|
117
|
+
domain: this.domain,
|
|
118
|
+
migratedAt: new Date().toISOString(),
|
|
119
|
+
};
|
|
120
|
+
// Build update options
|
|
121
|
+
const updateOptions = {
|
|
122
|
+
signer: this.signer,
|
|
123
|
+
verificationMethod: this.config.verificationMethod || `${targetDid}#key-0`,
|
|
124
|
+
proofPurpose: this.config.proofPurpose,
|
|
125
|
+
};
|
|
126
|
+
// Create the update event with migration data
|
|
127
|
+
let updatedLog = await updateEventLog(peerLog, migrationData, updateOptions);
|
|
128
|
+
// Add witness proofs if witnesses are configured
|
|
129
|
+
if (this.witnesses.length > 0) {
|
|
130
|
+
// Get the last event (the migration event we just added)
|
|
131
|
+
const lastEventIndex = updatedLog.events.length - 1;
|
|
132
|
+
let witnessedEvent = updatedLog.events[lastEventIndex];
|
|
133
|
+
// Add witness proofs from each configured witness
|
|
134
|
+
for (const witness of this.witnesses) {
|
|
135
|
+
witnessedEvent = await witnessEvent(witnessedEvent, witness);
|
|
136
|
+
}
|
|
137
|
+
// Replace the last event with the witnessed version
|
|
138
|
+
updatedLog = {
|
|
139
|
+
...updatedLog,
|
|
140
|
+
events: [
|
|
141
|
+
...updatedLog.events.slice(0, lastEventIndex),
|
|
142
|
+
witnessedEvent,
|
|
143
|
+
],
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
return updatedLog;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Generates a did:webvh DID for this domain
|
|
150
|
+
*
|
|
151
|
+
* The did:webvh format is: did:webvh:{domain}:{id}
|
|
152
|
+
* where {id} is derived from the source DID to maintain linkage.
|
|
153
|
+
*
|
|
154
|
+
* @param sourceDid - The source DID to derive the webvh DID from
|
|
155
|
+
* @returns A did:webvh string
|
|
156
|
+
*/
|
|
157
|
+
generateWebVHDid(sourceDid) {
|
|
158
|
+
// Extract a stable identifier from the source DID
|
|
159
|
+
// For did:peer, extract the key portion after the method
|
|
160
|
+
let idPart;
|
|
161
|
+
if (sourceDid.startsWith('did:peer:')) {
|
|
162
|
+
// For peer DIDs, use a hash-derived portion
|
|
163
|
+
// did:peer:4zQm... -> use the multibase portion
|
|
164
|
+
const peerPart = sourceDid.replace('did:peer:', '');
|
|
165
|
+
// Take first 32 chars of the peer DID identifier for brevity
|
|
166
|
+
idPart = peerPart.substring(0, Math.min(32, peerPart.length));
|
|
167
|
+
}
|
|
168
|
+
else if (sourceDid.startsWith('did:key:')) {
|
|
169
|
+
// For key DIDs, extract the key portion
|
|
170
|
+
idPart = sourceDid.replace('did:key:', '').substring(0, 32);
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
// For other DIDs, create a hash-based identifier
|
|
174
|
+
idPart = this.hashIdentifier(sourceDid);
|
|
175
|
+
}
|
|
176
|
+
// Sanitize for URL safety (replace invalid chars)
|
|
177
|
+
idPart = idPart.replace(/[^a-zA-Z0-9]/g, '');
|
|
178
|
+
return `did:webvh:${this.domain}:${idPart}`;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Creates a URL-safe hash-based identifier from a string
|
|
182
|
+
*/
|
|
183
|
+
hashIdentifier(input) {
|
|
184
|
+
// Simple hash for identifier generation (not cryptographic)
|
|
185
|
+
let hash = 0;
|
|
186
|
+
for (let i = 0; i < input.length; i++) {
|
|
187
|
+
const char = input.charCodeAt(i);
|
|
188
|
+
hash = ((hash << 5) - hash) + char;
|
|
189
|
+
hash = hash & hash; // Convert to 32bit integer
|
|
190
|
+
}
|
|
191
|
+
return Math.abs(hash).toString(36);
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Derives the current asset state by replaying all events in the log.
|
|
195
|
+
*
|
|
196
|
+
* @param log - The event log to derive state from
|
|
197
|
+
* @returns The current AssetState derived from replaying events
|
|
198
|
+
*/
|
|
199
|
+
getCurrentState(log) {
|
|
200
|
+
// Validate input log
|
|
201
|
+
if (!log || !log.events || log.events.length === 0) {
|
|
202
|
+
throw new Error('Cannot get state from an empty event log');
|
|
203
|
+
}
|
|
204
|
+
// First event must be a create event
|
|
205
|
+
const createEvent = log.events[0];
|
|
206
|
+
if (createEvent.type !== 'create') {
|
|
207
|
+
throw new Error('First event must be a create event');
|
|
208
|
+
}
|
|
209
|
+
// Extract initial state from create event
|
|
210
|
+
const createData = createEvent.data;
|
|
211
|
+
// Initialize state from create event
|
|
212
|
+
const state = {
|
|
213
|
+
did: createData.did,
|
|
214
|
+
name: createData.name,
|
|
215
|
+
layer: createData.layer || 'peer',
|
|
216
|
+
resources: createData.resources || [],
|
|
217
|
+
creator: createData.creator,
|
|
218
|
+
createdAt: createData.createdAt,
|
|
219
|
+
updatedAt: undefined,
|
|
220
|
+
deactivated: false,
|
|
221
|
+
metadata: {},
|
|
222
|
+
};
|
|
223
|
+
// Apply subsequent events
|
|
224
|
+
for (let i = 1; i < log.events.length; i++) {
|
|
225
|
+
const event = log.events[i];
|
|
226
|
+
if (event.type === 'update') {
|
|
227
|
+
const updateData = event.data;
|
|
228
|
+
// Check if this is a migration event
|
|
229
|
+
if (updateData.targetDid && updateData.layer) {
|
|
230
|
+
// Migration event - update DID and layer
|
|
231
|
+
state.did = updateData.targetDid;
|
|
232
|
+
state.layer = updateData.layer;
|
|
233
|
+
state.updatedAt = updateData.migratedAt;
|
|
234
|
+
// Store migration info in metadata
|
|
235
|
+
state.metadata = state.metadata || {};
|
|
236
|
+
state.metadata.sourceDid = updateData.sourceDid;
|
|
237
|
+
state.metadata.domain = updateData.domain;
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
// Regular update event
|
|
241
|
+
if (updateData.name !== undefined) {
|
|
242
|
+
state.name = updateData.name;
|
|
243
|
+
}
|
|
244
|
+
if (updateData.resources !== undefined) {
|
|
245
|
+
state.resources = updateData.resources;
|
|
246
|
+
}
|
|
247
|
+
if (updateData.updatedAt !== undefined) {
|
|
248
|
+
state.updatedAt = updateData.updatedAt;
|
|
249
|
+
}
|
|
250
|
+
if (updateData.did !== undefined) {
|
|
251
|
+
state.did = updateData.did;
|
|
252
|
+
}
|
|
253
|
+
if (updateData.layer !== undefined) {
|
|
254
|
+
state.layer = updateData.layer;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
// Store other fields in metadata
|
|
258
|
+
for (const [key, value] of Object.entries(updateData)) {
|
|
259
|
+
if (!['name', 'resources', 'updatedAt', 'did', 'layer', 'creator', 'createdAt', 'sourceDid', 'targetDid', 'domain', 'migratedAt'].includes(key)) {
|
|
260
|
+
state.metadata = state.metadata || {};
|
|
261
|
+
state.metadata[key] = value;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
else if (event.type === 'deactivate') {
|
|
266
|
+
state.deactivated = true;
|
|
267
|
+
const deactivateData = event.data;
|
|
268
|
+
if (deactivateData.deactivatedAt !== undefined) {
|
|
269
|
+
state.updatedAt = deactivateData.deactivatedAt;
|
|
270
|
+
}
|
|
271
|
+
if (deactivateData.reason !== undefined) {
|
|
272
|
+
state.metadata = state.metadata || {};
|
|
273
|
+
state.metadata.deactivationReason = deactivateData.reason;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return state;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Gets the domain this manager is configured for
|
|
281
|
+
*/
|
|
282
|
+
get domainName() {
|
|
283
|
+
return this.domain;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Gets the number of configured witnesses
|
|
287
|
+
*/
|
|
288
|
+
get witnessCount() {
|
|
289
|
+
return this.witnesses.length;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CEL Layer Managers
|
|
3
|
+
*
|
|
4
|
+
* Layer managers handle CEL-based asset creation and management at different
|
|
5
|
+
* trust/persistence layers of the Originals Protocol:
|
|
6
|
+
*
|
|
7
|
+
* - PeerCelManager: Layer 0 (did:peer) - Local control, no witnesses
|
|
8
|
+
* - WebVHCelManager: Layer 1 (did:webvh) - HTTP-based witnessing
|
|
9
|
+
* - BtcoCelManager: Layer 2 (did:btco) - Bitcoin-based witnessing
|
|
10
|
+
*/
|
|
11
|
+
export * from './PeerCelManager';
|
|
12
|
+
export { WebVHCelManager, type WebVHCelConfig, type WebVHMigrationData } from './WebVHCelManager';
|
|
13
|
+
export { BtcoCelManager, type BtcoCelConfig, type BtcoMigrationData } from './BtcoCelManager';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CEL Layer Managers
|
|
3
|
+
*
|
|
4
|
+
* Layer managers handle CEL-based asset creation and management at different
|
|
5
|
+
* trust/persistence layers of the Originals Protocol:
|
|
6
|
+
*
|
|
7
|
+
* - PeerCelManager: Layer 0 (did:peer) - Local control, no witnesses
|
|
8
|
+
* - WebVHCelManager: Layer 1 (did:webvh) - HTTP-based witnessing
|
|
9
|
+
* - BtcoCelManager: Layer 2 (did:btco) - Bitcoin-based witnessing
|
|
10
|
+
*/
|
|
11
|
+
// Export everything from PeerCelManager including CelSigner type
|
|
12
|
+
export * from './PeerCelManager';
|
|
13
|
+
// Export specific items from WebVHCelManager (CelSigner is imported from PeerCelManager)
|
|
14
|
+
export { WebVHCelManager } from './WebVHCelManager';
|
|
15
|
+
// Export specific items from BtcoCelManager (CelSigner is imported from PeerCelManager)
|
|
16
|
+
export { BtcoCelManager } from './BtcoCelManager';
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CBOR Serialization for CEL Event Logs
|
|
3
|
+
*
|
|
4
|
+
* Provides compact binary serialization and parsing of EventLog objects using CBOR format.
|
|
5
|
+
* CBOR provides ~50% size reduction compared to JSON for bandwidth-sensitive applications.
|
|
6
|
+
*/
|
|
7
|
+
import type { EventLog } from '../types';
|
|
8
|
+
/**
|
|
9
|
+
* Serialize an EventLog to CBOR binary format.
|
|
10
|
+
*
|
|
11
|
+
* CBOR provides a compact binary representation that is typically
|
|
12
|
+
* 30-50% smaller than JSON for event logs.
|
|
13
|
+
*
|
|
14
|
+
* @param log - The EventLog to serialize
|
|
15
|
+
* @returns Uint8Array containing the CBOR-encoded EventLog
|
|
16
|
+
* @throws Error if log is null or undefined
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const log = await createEventLog(data, options);
|
|
21
|
+
* const cbor = serializeEventLogCbor(log);
|
|
22
|
+
* console.log(cbor.length); // compact binary size
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare function serializeEventLogCbor(log: EventLog): Uint8Array;
|
|
26
|
+
/**
|
|
27
|
+
* Parse a CBOR binary into an EventLog.
|
|
28
|
+
*
|
|
29
|
+
* Validates the structure and types of the parsed object.
|
|
30
|
+
*
|
|
31
|
+
* @param cbor - CBOR binary data to parse
|
|
32
|
+
* @returns Parsed and validated EventLog
|
|
33
|
+
* @throws Error if CBOR is invalid or doesn't match EventLog structure
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* const cbor = readFileSync('asset.cel.cbor');
|
|
38
|
+
* const log = parseEventLogCbor(cbor);
|
|
39
|
+
* console.log(log.events.length);
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare function parseEventLogCbor(cbor: Uint8Array): EventLog;
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CBOR Serialization for CEL Event Logs
|
|
3
|
+
*
|
|
4
|
+
* Provides compact binary serialization and parsing of EventLog objects using CBOR format.
|
|
5
|
+
* CBOR provides ~50% size reduction compared to JSON for bandwidth-sensitive applications.
|
|
6
|
+
*/
|
|
7
|
+
import { encode, decode } from '../../utils/cbor';
|
|
8
|
+
/**
|
|
9
|
+
* Check if a proof object is a WitnessProof (has witnessedAt field)
|
|
10
|
+
*/
|
|
11
|
+
function isWitnessProof(proof) {
|
|
12
|
+
return 'witnessedAt' in proof && typeof proof.witnessedAt === 'string';
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Validate and reconstruct a DataIntegrityProof or WitnessProof
|
|
16
|
+
*/
|
|
17
|
+
function parseProof(proof) {
|
|
18
|
+
if (!proof || typeof proof !== 'object') {
|
|
19
|
+
throw new Error('Invalid proof: must be an object');
|
|
20
|
+
}
|
|
21
|
+
const p = proof;
|
|
22
|
+
// Validate required DataIntegrityProof fields
|
|
23
|
+
if (typeof p.type !== 'string') {
|
|
24
|
+
throw new Error('Invalid proof: missing or invalid type');
|
|
25
|
+
}
|
|
26
|
+
if (typeof p.cryptosuite !== 'string') {
|
|
27
|
+
throw new Error('Invalid proof: missing or invalid cryptosuite');
|
|
28
|
+
}
|
|
29
|
+
if (typeof p.created !== 'string') {
|
|
30
|
+
throw new Error('Invalid proof: missing or invalid created');
|
|
31
|
+
}
|
|
32
|
+
if (typeof p.verificationMethod !== 'string') {
|
|
33
|
+
throw new Error('Invalid proof: missing or invalid verificationMethod');
|
|
34
|
+
}
|
|
35
|
+
if (typeof p.proofPurpose !== 'string') {
|
|
36
|
+
throw new Error('Invalid proof: missing or invalid proofPurpose');
|
|
37
|
+
}
|
|
38
|
+
if (typeof p.proofValue !== 'string') {
|
|
39
|
+
throw new Error('Invalid proof: missing or invalid proofValue');
|
|
40
|
+
}
|
|
41
|
+
const baseProof = {
|
|
42
|
+
type: p.type,
|
|
43
|
+
cryptosuite: p.cryptosuite,
|
|
44
|
+
created: p.created,
|
|
45
|
+
verificationMethod: p.verificationMethod,
|
|
46
|
+
proofPurpose: p.proofPurpose,
|
|
47
|
+
proofValue: p.proofValue,
|
|
48
|
+
};
|
|
49
|
+
// Check for WitnessProof
|
|
50
|
+
if ('witnessedAt' in p) {
|
|
51
|
+
if (typeof p.witnessedAt !== 'string') {
|
|
52
|
+
throw new Error('Invalid witness proof: witnessedAt must be a string');
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
...baseProof,
|
|
56
|
+
witnessedAt: p.witnessedAt,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
return baseProof;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Validate and reconstruct a LogEntry
|
|
63
|
+
*/
|
|
64
|
+
function parseEntry(entry) {
|
|
65
|
+
if (!entry || typeof entry !== 'object') {
|
|
66
|
+
throw new Error('Invalid entry: must be an object');
|
|
67
|
+
}
|
|
68
|
+
const e = entry;
|
|
69
|
+
// Validate type
|
|
70
|
+
if (e.type !== 'create' && e.type !== 'update' && e.type !== 'deactivate') {
|
|
71
|
+
throw new Error(`Invalid entry type: ${e.type}`);
|
|
72
|
+
}
|
|
73
|
+
// Validate proof array
|
|
74
|
+
if (!Array.isArray(e.proof)) {
|
|
75
|
+
throw new Error('Invalid entry: proof must be an array');
|
|
76
|
+
}
|
|
77
|
+
const parsedEntry = {
|
|
78
|
+
type: e.type,
|
|
79
|
+
data: e.data,
|
|
80
|
+
proof: e.proof.map(parseProof),
|
|
81
|
+
};
|
|
82
|
+
// Optional previousEvent
|
|
83
|
+
if (e.previousEvent !== undefined) {
|
|
84
|
+
if (typeof e.previousEvent !== 'string') {
|
|
85
|
+
throw new Error('Invalid entry: previousEvent must be a string');
|
|
86
|
+
}
|
|
87
|
+
parsedEntry.previousEvent = e.previousEvent;
|
|
88
|
+
}
|
|
89
|
+
return parsedEntry;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Serialize an EventLog to CBOR binary format.
|
|
93
|
+
*
|
|
94
|
+
* CBOR provides a compact binary representation that is typically
|
|
95
|
+
* 30-50% smaller than JSON for event logs.
|
|
96
|
+
*
|
|
97
|
+
* @param log - The EventLog to serialize
|
|
98
|
+
* @returns Uint8Array containing the CBOR-encoded EventLog
|
|
99
|
+
* @throws Error if log is null or undefined
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* const log = await createEventLog(data, options);
|
|
104
|
+
* const cbor = serializeEventLogCbor(log);
|
|
105
|
+
* console.log(cbor.length); // compact binary size
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
export function serializeEventLogCbor(log) {
|
|
109
|
+
if (!log) {
|
|
110
|
+
throw new Error('Cannot serialize null or undefined EventLog');
|
|
111
|
+
}
|
|
112
|
+
return encode(log);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Parse a CBOR binary into an EventLog.
|
|
116
|
+
*
|
|
117
|
+
* Validates the structure and types of the parsed object.
|
|
118
|
+
*
|
|
119
|
+
* @param cbor - CBOR binary data to parse
|
|
120
|
+
* @returns Parsed and validated EventLog
|
|
121
|
+
* @throws Error if CBOR is invalid or doesn't match EventLog structure
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```typescript
|
|
125
|
+
* const cbor = readFileSync('asset.cel.cbor');
|
|
126
|
+
* const log = parseEventLogCbor(cbor);
|
|
127
|
+
* console.log(log.events.length);
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
export function parseEventLogCbor(cbor) {
|
|
131
|
+
if (!cbor || !(cbor instanceof Uint8Array)) {
|
|
132
|
+
throw new Error('Cannot parse null, undefined, or non-Uint8Array value');
|
|
133
|
+
}
|
|
134
|
+
if (cbor.length === 0) {
|
|
135
|
+
throw new Error('Cannot parse empty CBOR data');
|
|
136
|
+
}
|
|
137
|
+
let parsed;
|
|
138
|
+
try {
|
|
139
|
+
parsed = decode(cbor);
|
|
140
|
+
}
|
|
141
|
+
catch (e) {
|
|
142
|
+
throw new Error(`Invalid CBOR: ${e.message}`);
|
|
143
|
+
}
|
|
144
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
145
|
+
throw new Error('Invalid EventLog: must be an object');
|
|
146
|
+
}
|
|
147
|
+
const obj = parsed;
|
|
148
|
+
// Validate events array
|
|
149
|
+
if (!Array.isArray(obj.events)) {
|
|
150
|
+
throw new Error('Invalid EventLog: events must be an array');
|
|
151
|
+
}
|
|
152
|
+
const eventLog = {
|
|
153
|
+
events: obj.events.map(parseEntry),
|
|
154
|
+
};
|
|
155
|
+
// Optional previousLog
|
|
156
|
+
if (obj.previousLog !== undefined) {
|
|
157
|
+
if (typeof obj.previousLog !== 'string') {
|
|
158
|
+
throw new Error('Invalid EventLog: previousLog must be a string');
|
|
159
|
+
}
|
|
160
|
+
eventLog.previousLog = obj.previousLog;
|
|
161
|
+
}
|
|
162
|
+
return eventLog;
|
|
163
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON Serialization for CEL Event Logs
|
|
3
|
+
*
|
|
4
|
+
* Provides serialization and parsing of EventLog objects to/from JSON format.
|
|
5
|
+
* Uses deterministic key ordering for consistent hashes.
|
|
6
|
+
*/
|
|
7
|
+
import type { EventLog } from '../types';
|
|
8
|
+
/**
|
|
9
|
+
* Serialize an EventLog to JSON string.
|
|
10
|
+
*
|
|
11
|
+
* Uses deterministic key ordering for consistent output.
|
|
12
|
+
*
|
|
13
|
+
* @param log - The EventLog to serialize
|
|
14
|
+
* @returns JSON string representation of the EventLog
|
|
15
|
+
* @throws Error if log is null or undefined
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* const log = await createEventLog(data, options);
|
|
20
|
+
* const json = serializeEventLogJson(log);
|
|
21
|
+
* console.log(json); // '{"events":[...]}'
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare function serializeEventLogJson(log: EventLog): string;
|
|
25
|
+
/**
|
|
26
|
+
* Parse a JSON string into an EventLog.
|
|
27
|
+
*
|
|
28
|
+
* Validates the structure and types of the parsed object.
|
|
29
|
+
*
|
|
30
|
+
* @param json - JSON string to parse
|
|
31
|
+
* @returns Parsed and validated EventLog
|
|
32
|
+
* @throws Error if JSON is invalid or doesn't match EventLog structure
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```typescript
|
|
36
|
+
* const json = '{"events":[...]}';
|
|
37
|
+
* const log = parseEventLogJson(json);
|
|
38
|
+
* console.log(log.events.length);
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare function parseEventLogJson(json: string): EventLog;
|