@originals/sdk 1.8.0 → 1.8.2
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/utils/hash.js +1 -0
- package/package.json +6 -5
- package/src/adapters/FeeOracleMock.ts +9 -0
- package/src/adapters/index.ts +5 -0
- package/src/adapters/providers/OrdHttpProvider.ts +126 -0
- package/src/adapters/providers/OrdMockProvider.ts +101 -0
- package/src/adapters/types.ts +66 -0
- package/src/bitcoin/BitcoinManager.ts +329 -0
- package/src/bitcoin/BroadcastClient.ts +54 -0
- package/src/bitcoin/OrdinalsClient.ts +120 -0
- package/src/bitcoin/PSBTBuilder.ts +106 -0
- package/src/bitcoin/fee-calculation.ts +38 -0
- package/src/bitcoin/providers/OrdNodeProvider.ts +92 -0
- package/src/bitcoin/providers/OrdinalsProvider.ts +56 -0
- package/src/bitcoin/providers/types.ts +59 -0
- package/src/bitcoin/transactions/commit.ts +465 -0
- package/src/bitcoin/transactions/index.ts +13 -0
- package/src/bitcoin/transfer.ts +43 -0
- package/src/bitcoin/utxo-selection.ts +322 -0
- package/src/bitcoin/utxo.ts +113 -0
- package/src/cel/ExternalReferenceManager.ts +87 -0
- package/src/cel/OriginalsCel.ts +460 -0
- package/src/cel/algorithms/createEventLog.ts +68 -0
- package/src/cel/algorithms/deactivateEventLog.ts +109 -0
- package/src/cel/algorithms/index.ts +11 -0
- package/src/cel/algorithms/updateEventLog.ts +99 -0
- package/src/cel/algorithms/verifyEventLog.ts +306 -0
- package/src/cel/algorithms/witnessEvent.ts +87 -0
- package/src/cel/cli/create.ts +330 -0
- package/src/cel/cli/index.ts +383 -0
- package/src/cel/cli/inspect.ts +549 -0
- package/src/cel/cli/migrate.ts +473 -0
- package/src/cel/cli/verify.ts +249 -0
- package/src/cel/hash.ts +71 -0
- package/src/cel/index.ts +16 -0
- package/src/cel/layers/BtcoCelManager.ts +408 -0
- package/src/cel/layers/PeerCelManager.ts +371 -0
- package/src/cel/layers/WebVHCelManager.ts +361 -0
- package/src/cel/layers/index.ts +27 -0
- package/src/cel/serialization/cbor.ts +189 -0
- package/src/cel/serialization/index.ts +10 -0
- package/src/cel/serialization/json.ts +209 -0
- package/src/cel/types.ts +160 -0
- package/src/cel/witnesses/BitcoinWitness.ts +184 -0
- package/src/cel/witnesses/HttpWitness.ts +241 -0
- package/src/cel/witnesses/WitnessService.ts +51 -0
- package/src/cel/witnesses/index.ts +11 -0
- package/src/contexts/credentials-v1.json +237 -0
- package/src/contexts/credentials-v2-examples.json +5 -0
- package/src/contexts/credentials-v2.json +340 -0
- package/src/contexts/credentials.json +237 -0
- package/src/contexts/data-integrity-v2.json +81 -0
- package/src/contexts/dids.json +58 -0
- package/src/contexts/ed255192020.json +93 -0
- package/src/contexts/ordinals-plus.json +23 -0
- package/src/contexts/originals.json +22 -0
- package/src/core/OriginalsSDK.ts +420 -0
- package/src/crypto/Multikey.ts +194 -0
- package/src/crypto/Signer.ts +262 -0
- package/src/crypto/noble-init.ts +138 -0
- package/src/did/BtcoDidResolver.ts +231 -0
- package/src/did/DIDManager.ts +705 -0
- package/src/did/Ed25519Verifier.ts +68 -0
- package/src/did/KeyManager.ts +239 -0
- package/src/did/WebVHManager.ts +499 -0
- package/src/did/createBtcoDidDocument.ts +60 -0
- package/src/did/providers/OrdinalsClientProviderAdapter.ts +68 -0
- package/src/events/EventEmitter.ts +222 -0
- package/src/events/index.ts +19 -0
- package/src/events/types.ts +331 -0
- package/src/examples/basic-usage.ts +78 -0
- package/src/examples/create-module-original.ts +435 -0
- package/src/examples/full-lifecycle-flow.ts +514 -0
- package/src/examples/run.ts +60 -0
- package/src/index.ts +204 -0
- package/src/kinds/KindRegistry.ts +320 -0
- package/src/kinds/index.ts +74 -0
- package/src/kinds/types.ts +470 -0
- package/src/kinds/validators/AgentValidator.ts +257 -0
- package/src/kinds/validators/AppValidator.ts +211 -0
- package/src/kinds/validators/DatasetValidator.ts +242 -0
- package/src/kinds/validators/DocumentValidator.ts +311 -0
- package/src/kinds/validators/MediaValidator.ts +269 -0
- package/src/kinds/validators/ModuleValidator.ts +225 -0
- package/src/kinds/validators/base.ts +276 -0
- package/src/kinds/validators/index.ts +12 -0
- package/src/lifecycle/BatchOperations.ts +381 -0
- package/src/lifecycle/LifecycleManager.ts +2156 -0
- package/src/lifecycle/OriginalsAsset.ts +524 -0
- package/src/lifecycle/ProvenanceQuery.ts +280 -0
- package/src/lifecycle/ResourceVersioning.ts +163 -0
- package/src/migration/MigrationManager.ts +587 -0
- package/src/migration/audit/AuditLogger.ts +176 -0
- package/src/migration/checkpoint/CheckpointManager.ts +112 -0
- package/src/migration/checkpoint/CheckpointStorage.ts +101 -0
- package/src/migration/index.ts +33 -0
- package/src/migration/operations/BaseMigration.ts +126 -0
- package/src/migration/operations/PeerToBtcoMigration.ts +105 -0
- package/src/migration/operations/PeerToWebvhMigration.ts +62 -0
- package/src/migration/operations/WebvhToBtcoMigration.ts +105 -0
- package/src/migration/rollback/RollbackManager.ts +170 -0
- package/src/migration/state/StateMachine.ts +92 -0
- package/src/migration/state/StateTracker.ts +156 -0
- package/src/migration/types.ts +356 -0
- package/src/migration/validation/BitcoinValidator.ts +107 -0
- package/src/migration/validation/CredentialValidator.ts +62 -0
- package/src/migration/validation/DIDCompatibilityValidator.ts +151 -0
- package/src/migration/validation/LifecycleValidator.ts +64 -0
- package/src/migration/validation/StorageValidator.ts +79 -0
- package/src/migration/validation/ValidationPipeline.ts +213 -0
- package/src/resources/ResourceManager.ts +655 -0
- package/src/resources/index.ts +21 -0
- package/src/resources/types.ts +202 -0
- package/src/storage/LocalStorageAdapter.ts +64 -0
- package/src/storage/MemoryStorageAdapter.ts +29 -0
- package/src/storage/StorageAdapter.ts +25 -0
- package/src/storage/index.ts +3 -0
- package/src/types/bitcoin.ts +98 -0
- package/src/types/common.ts +92 -0
- package/src/types/credentials.ts +89 -0
- package/src/types/did.ts +31 -0
- package/src/types/external-shims.d.ts +53 -0
- package/src/types/index.ts +7 -0
- package/src/types/network.ts +178 -0
- package/src/utils/EventLogger.ts +298 -0
- package/src/utils/Logger.ts +324 -0
- package/src/utils/MetricsCollector.ts +358 -0
- package/src/utils/bitcoin-address.ts +132 -0
- package/src/utils/cbor.ts +31 -0
- package/src/utils/encoding.ts +135 -0
- package/src/utils/hash.ts +12 -0
- package/src/utils/retry.ts +46 -0
- package/src/utils/satoshi-validation.ts +196 -0
- package/src/utils/serialization.ts +102 -0
- package/src/utils/telemetry.ts +44 -0
- package/src/utils/validation.ts +123 -0
- package/src/vc/CredentialManager.ts +955 -0
- package/src/vc/Issuer.ts +105 -0
- package/src/vc/Verifier.ts +54 -0
- package/src/vc/cryptosuites/bbs.ts +253 -0
- package/src/vc/cryptosuites/bbsSimple.ts +21 -0
- package/src/vc/cryptosuites/eddsa.ts +99 -0
- package/src/vc/documentLoader.ts +81 -0
- package/src/vc/proofs/data-integrity.ts +33 -0
- package/src/vc/utils/jsonld.ts +18 -0
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BtcoCelManager - CEL Manager for did:btco Layer
|
|
3
|
+
*
|
|
4
|
+
* Manages migration of Originals assets to the did:btco layer (Layer 2).
|
|
5
|
+
* This layer provides Bitcoin-based witnessing for maximum immutability.
|
|
6
|
+
*
|
|
7
|
+
* The did:btco method anchors asset provenance on the Bitcoin blockchain
|
|
8
|
+
* using ordinals inscriptions, providing the highest level of trust
|
|
9
|
+
* and permanence in the Originals Protocol.
|
|
10
|
+
*
|
|
11
|
+
* @see https://github.com/aviarytech/did-btco
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { EventLog, ExternalReference, DataIntegrityProof, UpdateOptions, AssetState } from '../types';
|
|
15
|
+
import { updateEventLog } from '../algorithms/updateEventLog';
|
|
16
|
+
import { witnessEvent } from '../algorithms/witnessEvent';
|
|
17
|
+
import { BitcoinWitness } from '../witnesses/BitcoinWitness';
|
|
18
|
+
import type { BitcoinManager } from '../../bitcoin/BitcoinManager';
|
|
19
|
+
import type { CelSigner } from './PeerCelManager';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Configuration options for BtcoCelManager
|
|
23
|
+
*/
|
|
24
|
+
export interface BtcoCelConfig {
|
|
25
|
+
/** The DID URL of the verification method for signing */
|
|
26
|
+
verificationMethod?: string;
|
|
27
|
+
/** The purpose of proofs (defaults to 'assertionMethod') */
|
|
28
|
+
proofPurpose?: string;
|
|
29
|
+
/** Fee rate in sat/vB for Bitcoin transactions (optional - BitcoinManager will estimate if not provided) */
|
|
30
|
+
feeRate?: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Migration data stored in the update event when migrating to btco
|
|
35
|
+
*/
|
|
36
|
+
export interface BtcoMigrationData {
|
|
37
|
+
/** The source DID from the previous layer */
|
|
38
|
+
sourceDid: string;
|
|
39
|
+
/** The new did:btco DID */
|
|
40
|
+
targetDid: string;
|
|
41
|
+
/** The target layer */
|
|
42
|
+
layer: 'btco';
|
|
43
|
+
/** The Bitcoin transaction ID anchoring the migration */
|
|
44
|
+
txid?: string;
|
|
45
|
+
/** The inscription ID on Bitcoin */
|
|
46
|
+
inscriptionId?: string;
|
|
47
|
+
/** ISO 8601 timestamp of migration */
|
|
48
|
+
migratedAt: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* BtcoCelManager - Manages CEL-based asset migration to did:btco layer
|
|
53
|
+
*
|
|
54
|
+
* The btco layer is the final publication layer for Originals assets.
|
|
55
|
+
* Assets at this layer:
|
|
56
|
+
* - Have a did:btco identifier anchored on Bitcoin
|
|
57
|
+
* - Have mandatory Bitcoin witness attestations via ordinals
|
|
58
|
+
* - Provide maximum immutability and timestamping
|
|
59
|
+
* - Cannot be migrated to any other layer
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```typescript
|
|
63
|
+
* const bitcoinManager = new BitcoinManager(config);
|
|
64
|
+
* const manager = new BtcoCelManager(
|
|
65
|
+
* async (data) => createEdDsaProof(data, privateKey),
|
|
66
|
+
* bitcoinManager
|
|
67
|
+
* );
|
|
68
|
+
*
|
|
69
|
+
* const btcoLog = await manager.migrate(webvhLog);
|
|
70
|
+
* console.log(btcoLog.events[btcoLog.events.length - 1].data.txid);
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export class BtcoCelManager {
|
|
74
|
+
private signer: CelSigner;
|
|
75
|
+
private bitcoinManager: BitcoinManager;
|
|
76
|
+
private bitcoinWitness: BitcoinWitness;
|
|
77
|
+
private config: BtcoCelConfig;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Creates a new BtcoCelManager instance
|
|
81
|
+
*
|
|
82
|
+
* @param signer - Function that signs data and returns a DataIntegrityProof
|
|
83
|
+
* @param bitcoinManager - BitcoinManager instance for ordinals inscriptions
|
|
84
|
+
* @param config - Optional configuration options
|
|
85
|
+
*/
|
|
86
|
+
constructor(
|
|
87
|
+
signer: CelSigner,
|
|
88
|
+
bitcoinManager: BitcoinManager,
|
|
89
|
+
config: BtcoCelConfig = {}
|
|
90
|
+
) {
|
|
91
|
+
if (typeof signer !== 'function') {
|
|
92
|
+
throw new Error('BtcoCelManager requires a signer function');
|
|
93
|
+
}
|
|
94
|
+
if (!bitcoinManager) {
|
|
95
|
+
throw new Error('BtcoCelManager requires a BitcoinManager instance');
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
this.signer = signer;
|
|
99
|
+
this.bitcoinManager = bitcoinManager;
|
|
100
|
+
this.config = {
|
|
101
|
+
proofPurpose: 'assertionMethod',
|
|
102
|
+
...config,
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// Create Bitcoin witness service with optional fee rate
|
|
106
|
+
this.bitcoinWitness = new BitcoinWitness(bitcoinManager, {
|
|
107
|
+
feeRate: config.feeRate,
|
|
108
|
+
verificationMethod: config.verificationMethod,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Migrates a webvh layer event log to the did:btco layer
|
|
114
|
+
*
|
|
115
|
+
* This method:
|
|
116
|
+
* 1. Validates the input log (must have migrated to webvh layer)
|
|
117
|
+
* 2. Creates an update event with migration data
|
|
118
|
+
* 3. Adds mandatory Bitcoin witness proof via ordinals inscription
|
|
119
|
+
* 4. Generates a did:btco DID based on the inscription
|
|
120
|
+
* 5. Returns the updated EventLog
|
|
121
|
+
*
|
|
122
|
+
* Note: Bitcoin witness is REQUIRED at this layer - it cannot be skipped.
|
|
123
|
+
*
|
|
124
|
+
* @param webvhLog - The event log from the webvh layer to migrate
|
|
125
|
+
* @returns Promise resolving to an EventLog with the migration event appended
|
|
126
|
+
*
|
|
127
|
+
* @throws Error if the log is empty, deactivated, or not from webvh layer
|
|
128
|
+
* @throws Error if signer produces invalid proof
|
|
129
|
+
* @throws Error if Bitcoin inscription fails
|
|
130
|
+
*/
|
|
131
|
+
async migrate(webvhLog: EventLog): Promise<EventLog> {
|
|
132
|
+
// Validate input log
|
|
133
|
+
if (!webvhLog || !webvhLog.events || webvhLog.events.length === 0) {
|
|
134
|
+
throw new Error('Cannot migrate an empty event log');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Get the create event to extract source DID
|
|
138
|
+
const createEvent = webvhLog.events[0];
|
|
139
|
+
if (createEvent.type !== 'create') {
|
|
140
|
+
throw new Error('First event must be a create event');
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Find the current layer and DID by checking for migration events
|
|
144
|
+
let currentDid: string | undefined;
|
|
145
|
+
let currentLayer: string | undefined;
|
|
146
|
+
|
|
147
|
+
// Look through events to find the latest migration
|
|
148
|
+
for (const event of webvhLog.events) {
|
|
149
|
+
const eventData = event.data as Record<string, unknown>;
|
|
150
|
+
|
|
151
|
+
if (event.type === 'create') {
|
|
152
|
+
currentDid = eventData.did as string;
|
|
153
|
+
currentLayer = eventData.layer as string || 'peer';
|
|
154
|
+
} else if (event.type === 'update' && eventData.targetDid && eventData.layer) {
|
|
155
|
+
// This is a migration event
|
|
156
|
+
currentDid = eventData.targetDid as string;
|
|
157
|
+
currentLayer = eventData.layer as string;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (!currentDid) {
|
|
162
|
+
throw new Error('Could not determine current DID from event log');
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Validate source is from webvh layer (only webvh can migrate to btco)
|
|
166
|
+
if (currentLayer !== 'webvh') {
|
|
167
|
+
throw new Error(`Cannot migrate from ${currentLayer} layer to btco layer. Must migrate to webvh first.`);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Check if log is already deactivated
|
|
171
|
+
const lastEvent = webvhLog.events[webvhLog.events.length - 1];
|
|
172
|
+
if (lastEvent.type === 'deactivate') {
|
|
173
|
+
throw new Error('Cannot migrate a deactivated event log');
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Prepare initial migration data (will be updated with Bitcoin details after witnessing)
|
|
177
|
+
const migrationData: BtcoMigrationData = {
|
|
178
|
+
sourceDid: currentDid,
|
|
179
|
+
targetDid: '', // Will be set after inscription
|
|
180
|
+
layer: 'btco',
|
|
181
|
+
migratedAt: new Date().toISOString(),
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
// Build update options
|
|
185
|
+
const updateOptions: UpdateOptions = {
|
|
186
|
+
signer: this.signer,
|
|
187
|
+
verificationMethod: this.config.verificationMethod || `${currentDid}#key-0`,
|
|
188
|
+
proofPurpose: this.config.proofPurpose,
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
// Create the update event with migration data
|
|
192
|
+
let updatedLog = await updateEventLog(webvhLog, migrationData, updateOptions);
|
|
193
|
+
|
|
194
|
+
// Add Bitcoin witness proof (REQUIRED at btco layer)
|
|
195
|
+
const lastEventIndex = updatedLog.events.length - 1;
|
|
196
|
+
let witnessedEvent = updatedLog.events[lastEventIndex];
|
|
197
|
+
|
|
198
|
+
// Witness the event on Bitcoin
|
|
199
|
+
witnessedEvent = await witnessEvent(witnessedEvent, this.bitcoinWitness);
|
|
200
|
+
|
|
201
|
+
// Extract Bitcoin details from the witness proof
|
|
202
|
+
const bitcoinProof = witnessedEvent.proof.find(
|
|
203
|
+
p => p.cryptosuite === 'bitcoin-ordinals-2024'
|
|
204
|
+
) as Record<string, unknown> | undefined;
|
|
205
|
+
|
|
206
|
+
// Generate did:btco DID using inscription ID
|
|
207
|
+
let targetDid: string;
|
|
208
|
+
let txid: string | undefined;
|
|
209
|
+
let inscriptionId: string | undefined;
|
|
210
|
+
|
|
211
|
+
if (bitcoinProof) {
|
|
212
|
+
txid = bitcoinProof.txid as string;
|
|
213
|
+
inscriptionId = bitcoinProof.inscriptionId as string;
|
|
214
|
+
|
|
215
|
+
// did:btco format uses the inscription ID for identification
|
|
216
|
+
if (inscriptionId) {
|
|
217
|
+
// Sanitize inscription ID for DID (remove special chars)
|
|
218
|
+
const sanitizedId = inscriptionId.replace(/[^a-zA-Z0-9]/g, '');
|
|
219
|
+
targetDid = `did:btco:${sanitizedId}`;
|
|
220
|
+
} else if (txid) {
|
|
221
|
+
targetDid = `did:btco:${txid}`;
|
|
222
|
+
} else {
|
|
223
|
+
// Fallback: derive from source DID
|
|
224
|
+
targetDid = this.generateBtcoDid(currentDid);
|
|
225
|
+
}
|
|
226
|
+
} else {
|
|
227
|
+
// Fallback: derive from source DID (shouldn't happen since witness is required)
|
|
228
|
+
targetDid = this.generateBtcoDid(currentDid);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Update migration data with Bitcoin details
|
|
232
|
+
const updatedMigrationData: BtcoMigrationData = {
|
|
233
|
+
...migrationData,
|
|
234
|
+
targetDid,
|
|
235
|
+
txid,
|
|
236
|
+
inscriptionId,
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
// Replace the event data with updated migration data
|
|
240
|
+
witnessedEvent = {
|
|
241
|
+
...witnessedEvent,
|
|
242
|
+
data: updatedMigrationData,
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
// Replace the last event with the witnessed version
|
|
246
|
+
updatedLog = {
|
|
247
|
+
...updatedLog,
|
|
248
|
+
events: [
|
|
249
|
+
...updatedLog.events.slice(0, lastEventIndex),
|
|
250
|
+
witnessedEvent,
|
|
251
|
+
],
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
return updatedLog;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Generates a did:btco DID fallback from source DID
|
|
259
|
+
*
|
|
260
|
+
* @param sourceDid - The source DID to derive from
|
|
261
|
+
* @returns A did:btco string
|
|
262
|
+
*/
|
|
263
|
+
private generateBtcoDid(sourceDid: string): string {
|
|
264
|
+
// Extract identifier portion from source DID
|
|
265
|
+
let idPart: string;
|
|
266
|
+
|
|
267
|
+
if (sourceDid.startsWith('did:webvh:')) {
|
|
268
|
+
// For webvh DIDs, extract the identifier after domain
|
|
269
|
+
const parts = sourceDid.split(':');
|
|
270
|
+
idPart = parts.length > 3 ? parts.slice(3).join('') : this.hashIdentifier(sourceDid);
|
|
271
|
+
} else {
|
|
272
|
+
// For other DIDs, create a hash-based identifier
|
|
273
|
+
idPart = this.hashIdentifier(sourceDid);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Sanitize for DID (alphanumeric only)
|
|
277
|
+
idPart = idPart.replace(/[^a-zA-Z0-9]/g, '').substring(0, 64);
|
|
278
|
+
|
|
279
|
+
return `did:btco:${idPart}`;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Creates a URL-safe hash-based identifier from a string
|
|
284
|
+
*/
|
|
285
|
+
private hashIdentifier(input: string): string {
|
|
286
|
+
// Simple hash for identifier generation (not cryptographic)
|
|
287
|
+
let hash = 0;
|
|
288
|
+
for (let i = 0; i < input.length; i++) {
|
|
289
|
+
const char = input.charCodeAt(i);
|
|
290
|
+
hash = ((hash << 5) - hash) + char;
|
|
291
|
+
hash = hash & hash; // Convert to 32bit integer
|
|
292
|
+
}
|
|
293
|
+
return Math.abs(hash).toString(36);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Derives the current asset state by replaying all events in the log.
|
|
298
|
+
*
|
|
299
|
+
* @param log - The event log to derive state from
|
|
300
|
+
* @returns The current AssetState derived from replaying events
|
|
301
|
+
*/
|
|
302
|
+
getCurrentState(log: EventLog): AssetState {
|
|
303
|
+
// Validate input log
|
|
304
|
+
if (!log || !log.events || log.events.length === 0) {
|
|
305
|
+
throw new Error('Cannot get state from an empty event log');
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// First event must be a create event
|
|
309
|
+
const createEvent = log.events[0];
|
|
310
|
+
if (createEvent.type !== 'create') {
|
|
311
|
+
throw new Error('First event must be a create event');
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Extract initial state from create event
|
|
315
|
+
const createData = createEvent.data as Record<string, unknown>;
|
|
316
|
+
|
|
317
|
+
// Initialize state from create event
|
|
318
|
+
const state: AssetState = {
|
|
319
|
+
did: createData.did as string,
|
|
320
|
+
name: createData.name as string | undefined,
|
|
321
|
+
layer: (createData.layer as 'peer' | 'webvh' | 'btco') || 'peer',
|
|
322
|
+
resources: (createData.resources as ExternalReference[]) || [],
|
|
323
|
+
creator: createData.creator as string | undefined,
|
|
324
|
+
createdAt: createData.createdAt as string | undefined,
|
|
325
|
+
updatedAt: undefined,
|
|
326
|
+
deactivated: false,
|
|
327
|
+
metadata: {},
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
// Apply subsequent events
|
|
331
|
+
for (let i = 1; i < log.events.length; i++) {
|
|
332
|
+
const event = log.events[i];
|
|
333
|
+
|
|
334
|
+
if (event.type === 'update') {
|
|
335
|
+
const updateData = event.data as Record<string, unknown>;
|
|
336
|
+
|
|
337
|
+
// Check if this is a migration event
|
|
338
|
+
if (updateData.targetDid && updateData.layer) {
|
|
339
|
+
// Migration event - update DID and layer
|
|
340
|
+
state.did = updateData.targetDid as string;
|
|
341
|
+
state.layer = updateData.layer as 'peer' | 'webvh' | 'btco';
|
|
342
|
+
state.updatedAt = updateData.migratedAt as string;
|
|
343
|
+
|
|
344
|
+
// Store migration info in metadata
|
|
345
|
+
state.metadata = state.metadata || {};
|
|
346
|
+
state.metadata.sourceDid = updateData.sourceDid;
|
|
347
|
+
|
|
348
|
+
// Store Bitcoin-specific metadata for btco layer
|
|
349
|
+
if (updateData.layer === 'btco') {
|
|
350
|
+
if (updateData.txid) {
|
|
351
|
+
state.metadata.txid = updateData.txid;
|
|
352
|
+
}
|
|
353
|
+
if (updateData.inscriptionId) {
|
|
354
|
+
state.metadata.inscriptionId = updateData.inscriptionId;
|
|
355
|
+
}
|
|
356
|
+
} else if (updateData.domain) {
|
|
357
|
+
state.metadata.domain = updateData.domain;
|
|
358
|
+
}
|
|
359
|
+
} else {
|
|
360
|
+
// Regular update event
|
|
361
|
+
if (updateData.name !== undefined) {
|
|
362
|
+
state.name = updateData.name as string;
|
|
363
|
+
}
|
|
364
|
+
if (updateData.resources !== undefined) {
|
|
365
|
+
state.resources = updateData.resources as ExternalReference[];
|
|
366
|
+
}
|
|
367
|
+
if (updateData.updatedAt !== undefined) {
|
|
368
|
+
state.updatedAt = updateData.updatedAt as string;
|
|
369
|
+
}
|
|
370
|
+
if (updateData.did !== undefined) {
|
|
371
|
+
state.did = updateData.did as string;
|
|
372
|
+
}
|
|
373
|
+
if (updateData.layer !== undefined) {
|
|
374
|
+
state.layer = updateData.layer as 'peer' | 'webvh' | 'btco';
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// Store other fields in metadata
|
|
379
|
+
for (const [key, value] of Object.entries(updateData)) {
|
|
380
|
+
if (!['name', 'resources', 'updatedAt', 'did', 'layer', 'creator', 'createdAt', 'sourceDid', 'targetDid', 'domain', 'migratedAt', 'txid', 'inscriptionId'].includes(key)) {
|
|
381
|
+
state.metadata = state.metadata || {};
|
|
382
|
+
state.metadata[key] = value;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
} else if (event.type === 'deactivate') {
|
|
386
|
+
state.deactivated = true;
|
|
387
|
+
|
|
388
|
+
const deactivateData = event.data as Record<string, unknown>;
|
|
389
|
+
if (deactivateData.deactivatedAt !== undefined) {
|
|
390
|
+
state.updatedAt = deactivateData.deactivatedAt as string;
|
|
391
|
+
}
|
|
392
|
+
if (deactivateData.reason !== undefined) {
|
|
393
|
+
state.metadata = state.metadata || {};
|
|
394
|
+
state.metadata.deactivationReason = deactivateData.reason;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
return state;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Gets the BitcoinManager instance used by this manager
|
|
404
|
+
*/
|
|
405
|
+
get bitcoin(): BitcoinManager {
|
|
406
|
+
return this.bitcoinManager;
|
|
407
|
+
}
|
|
408
|
+
}
|