@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.
Files changed (105) hide show
  1. package/dist/adapters/FeeOracleMock.js +2 -2
  2. package/dist/bitcoin/OrdinalsClient.d.ts +1 -1
  3. package/dist/bitcoin/OrdinalsClient.js +10 -8
  4. package/dist/bitcoin/PSBTBuilder.js +1 -1
  5. package/dist/bitcoin/utxo-selection.js +2 -2
  6. package/dist/cel/ExternalReferenceManager.d.ts +57 -0
  7. package/dist/cel/ExternalReferenceManager.js +73 -0
  8. package/dist/cel/OriginalsCel.d.ts +245 -0
  9. package/dist/cel/OriginalsCel.js +349 -0
  10. package/dist/cel/algorithms/createEventLog.d.ts +32 -0
  11. package/dist/cel/algorithms/createEventLog.js +56 -0
  12. package/dist/cel/algorithms/deactivateEventLog.d.ts +35 -0
  13. package/dist/cel/algorithms/deactivateEventLog.js +91 -0
  14. package/dist/cel/algorithms/index.d.ts +10 -0
  15. package/dist/cel/algorithms/index.js +10 -0
  16. package/dist/cel/algorithms/updateEventLog.d.ts +34 -0
  17. package/dist/cel/algorithms/updateEventLog.js +82 -0
  18. package/dist/cel/algorithms/verifyEventLog.d.ts +45 -0
  19. package/dist/cel/algorithms/verifyEventLog.js +255 -0
  20. package/dist/cel/algorithms/witnessEvent.d.ts +29 -0
  21. package/dist/cel/algorithms/witnessEvent.js +75 -0
  22. package/dist/cel/cli/create.d.ts +36 -0
  23. package/dist/cel/cli/create.js +282 -0
  24. package/dist/cel/cli/index.d.ts +11 -0
  25. package/dist/cel/cli/index.js +351 -0
  26. package/dist/cel/cli/inspect.d.ts +30 -0
  27. package/dist/cel/cli/inspect.js +475 -0
  28. package/dist/cel/cli/migrate.d.ts +41 -0
  29. package/dist/cel/cli/migrate.js +405 -0
  30. package/dist/cel/cli/verify.d.ts +31 -0
  31. package/dist/cel/cli/verify.js +205 -0
  32. package/dist/cel/hash.d.ts +46 -0
  33. package/dist/cel/hash.js +66 -0
  34. package/dist/cel/index.d.ts +15 -0
  35. package/dist/cel/index.js +15 -0
  36. package/dist/cel/layers/BtcoCelManager.d.ts +121 -0
  37. package/dist/cel/layers/BtcoCelManager.js +329 -0
  38. package/dist/cel/layers/PeerCelManager.d.ts +151 -0
  39. package/dist/cel/layers/PeerCelManager.js +299 -0
  40. package/dist/cel/layers/WebVHCelManager.d.ts +122 -0
  41. package/dist/cel/layers/WebVHCelManager.js +291 -0
  42. package/dist/cel/layers/index.d.ts +13 -0
  43. package/dist/cel/layers/index.js +16 -0
  44. package/dist/cel/serialization/cbor.d.ts +42 -0
  45. package/dist/cel/serialization/cbor.js +163 -0
  46. package/dist/cel/serialization/index.d.ts +9 -0
  47. package/dist/cel/serialization/index.js +9 -0
  48. package/dist/cel/serialization/json.d.ts +41 -0
  49. package/dist/cel/serialization/json.js +180 -0
  50. package/dist/cel/types.d.ts +149 -0
  51. package/dist/cel/types.js +7 -0
  52. package/dist/cel/witnesses/BitcoinWitness.d.ts +83 -0
  53. package/dist/cel/witnesses/BitcoinWitness.js +116 -0
  54. package/dist/cel/witnesses/HttpWitness.d.ts +79 -0
  55. package/dist/cel/witnesses/HttpWitness.js +163 -0
  56. package/dist/cel/witnesses/WitnessService.d.ts +49 -0
  57. package/dist/cel/witnesses/WitnessService.js +10 -0
  58. package/dist/cel/witnesses/index.d.ts +10 -0
  59. package/dist/cel/witnesses/index.js +7 -0
  60. package/dist/core/OriginalsSDK.js +5 -1
  61. package/dist/crypto/Signer.js +14 -6
  62. package/dist/crypto/noble-init.js +20 -1
  63. package/dist/did/BtcoDidResolver.d.ts +2 -2
  64. package/dist/did/BtcoDidResolver.js +12 -8
  65. package/dist/did/DIDManager.js +6 -4
  66. package/dist/did/KeyManager.d.ts +1 -1
  67. package/dist/did/KeyManager.js +7 -4
  68. package/dist/did/WebVHManager.js +1 -1
  69. package/dist/did/createBtcoDidDocument.js +2 -1
  70. package/dist/events/types.d.ts +4 -1
  71. package/dist/examples/create-module-original.js +1 -1
  72. package/dist/examples/full-lifecycle-flow.js +2 -2
  73. package/dist/index.d.ts +13 -0
  74. package/dist/index.js +12 -0
  75. package/dist/kinds/KindRegistry.js +59 -29
  76. package/dist/lifecycle/BatchOperations.d.ts +5 -3
  77. package/dist/lifecycle/BatchOperations.js +11 -5
  78. package/dist/lifecycle/LifecycleManager.d.ts +1 -1
  79. package/dist/lifecycle/LifecycleManager.js +42 -33
  80. package/dist/lifecycle/OriginalsAsset.js +2 -2
  81. package/dist/migration/MigrationManager.js +67 -3
  82. package/dist/storage/LocalStorageAdapter.js +4 -1
  83. package/dist/storage/MemoryStorageAdapter.js +7 -7
  84. package/dist/types/network.js +6 -3
  85. package/dist/utils/Logger.d.ts +6 -6
  86. package/dist/utils/Logger.js +5 -3
  87. package/dist/utils/MetricsCollector.js +1 -1
  88. package/dist/utils/bitcoin-address.js +4 -2
  89. package/dist/utils/cbor.js +16 -3
  90. package/dist/utils/encoding.d.ts +4 -4
  91. package/dist/utils/encoding.js +7 -6
  92. package/dist/utils/hash.js +6 -1
  93. package/dist/utils/serialization.d.ts +2 -2
  94. package/dist/utils/serialization.js +7 -5
  95. package/dist/utils/telemetry.js +6 -2
  96. package/dist/utils/validation.js +8 -4
  97. package/dist/vc/CredentialManager.d.ts +8 -8
  98. package/dist/vc/CredentialManager.js +46 -33
  99. package/dist/vc/Issuer.d.ts +2 -2
  100. package/dist/vc/Issuer.js +5 -1
  101. package/dist/vc/Verifier.d.ts +2 -2
  102. package/dist/vc/Verifier.js +12 -6
  103. package/dist/vc/documentLoader.d.ts +5 -3
  104. package/dist/vc/documentLoader.js +5 -4
  105. package/package.json +4 -1
@@ -0,0 +1,66 @@
1
+ /**
2
+ * CEL Hash Utilities
3
+ *
4
+ * Computes and verifies Multibase-encoded Multihash digests as specified
5
+ * in the CEL specification for external references.
6
+ *
7
+ * @see https://w3c-ccg.github.io/cel-spec/
8
+ */
9
+ import { sha256 } from '@noble/hashes/sha2.js';
10
+ import { multibase } from '../utils/encoding';
11
+ /**
12
+ * Computes a CEL-compliant digestMultibase from content.
13
+ *
14
+ * Uses sha2-256 hash algorithm and encodes as Multibase base64url-nopad (prefix 'u').
15
+ *
16
+ * @param content - The raw bytes to hash
17
+ * @returns Multibase-encoded digest string (e.g., "uEiDm9F...")
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * const digest = computeDigestMultibase(new TextEncoder().encode("hello"));
22
+ * // Returns: "uLCA..."
23
+ * ```
24
+ */
25
+ export function computeDigestMultibase(content) {
26
+ // Compute SHA-256 hash
27
+ const hash = sha256(content);
28
+ // Encode as Multibase base64url-nopad (prefix 'u')
29
+ return multibase.encode(hash, 'base64url');
30
+ }
31
+ /**
32
+ * Verifies that content matches a given digestMultibase.
33
+ *
34
+ * @param content - The raw bytes to verify
35
+ * @param digest - The expected digestMultibase string
36
+ * @returns True if the content hash matches the digest, false otherwise
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * const content = new TextEncoder().encode("hello");
41
+ * const digest = computeDigestMultibase(content);
42
+ * const isValid = verifyDigestMultibase(content, digest); // true
43
+ * ```
44
+ */
45
+ export function verifyDigestMultibase(content, digest) {
46
+ try {
47
+ // Compute hash of content
48
+ const computedDigest = computeDigestMultibase(content);
49
+ // Compare with expected digest
50
+ return computedDigest === digest;
51
+ }
52
+ catch {
53
+ // Invalid digest format or encoding error
54
+ return false;
55
+ }
56
+ }
57
+ /**
58
+ * Decodes a digestMultibase string back to raw hash bytes.
59
+ *
60
+ * @param digest - The Multibase-encoded digest string
61
+ * @returns The raw SHA-256 hash bytes
62
+ * @throws Error if the digest is not a valid Multibase base64url string
63
+ */
64
+ export function decodeDigestMultibase(digest) {
65
+ return multibase.decode(digest);
66
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * CEL (Cryptographic Event Log) Module
3
+ *
4
+ * Implements W3C CCG CEL Specification for Originals Protocol
5
+ * @see https://w3c-ccg.github.io/cel-spec/
6
+ */
7
+ export * from './types';
8
+ export * from './hash';
9
+ export * from './algorithms';
10
+ export * from './witnesses';
11
+ export * from './serialization';
12
+ export * from './ExternalReferenceManager';
13
+ export * from './layers';
14
+ export * from './OriginalsCel';
15
+ export { main as celCli } from './cli/index';
@@ -0,0 +1,15 @@
1
+ /**
2
+ * CEL (Cryptographic Event Log) Module
3
+ *
4
+ * Implements W3C CCG CEL Specification for Originals Protocol
5
+ * @see https://w3c-ccg.github.io/cel-spec/
6
+ */
7
+ export * from './types';
8
+ export * from './hash';
9
+ export * from './algorithms';
10
+ export * from './witnesses';
11
+ export * from './serialization';
12
+ export * from './ExternalReferenceManager';
13
+ export * from './layers';
14
+ export * from './OriginalsCel';
15
+ export { main as celCli } from './cli/index';
@@ -0,0 +1,121 @@
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
+ import type { EventLog, AssetState } from '../types';
14
+ import type { BitcoinManager } from '../../bitcoin/BitcoinManager';
15
+ import type { CelSigner } from './PeerCelManager';
16
+ /**
17
+ * Configuration options for BtcoCelManager
18
+ */
19
+ export interface BtcoCelConfig {
20
+ /** The DID URL of the verification method for signing */
21
+ verificationMethod?: string;
22
+ /** The purpose of proofs (defaults to 'assertionMethod') */
23
+ proofPurpose?: string;
24
+ /** Fee rate in sat/vB for Bitcoin transactions (optional - BitcoinManager will estimate if not provided) */
25
+ feeRate?: number;
26
+ }
27
+ /**
28
+ * Migration data stored in the update event when migrating to btco
29
+ */
30
+ export interface BtcoMigrationData {
31
+ /** The source DID from the previous layer */
32
+ sourceDid: string;
33
+ /** The new did:btco DID */
34
+ targetDid: string;
35
+ /** The target layer */
36
+ layer: 'btco';
37
+ /** The Bitcoin transaction ID anchoring the migration */
38
+ txid?: string;
39
+ /** The inscription ID on Bitcoin */
40
+ inscriptionId?: string;
41
+ /** ISO 8601 timestamp of migration */
42
+ migratedAt: string;
43
+ }
44
+ /**
45
+ * BtcoCelManager - Manages CEL-based asset migration to did:btco layer
46
+ *
47
+ * The btco layer is the final publication layer for Originals assets.
48
+ * Assets at this layer:
49
+ * - Have a did:btco identifier anchored on Bitcoin
50
+ * - Have mandatory Bitcoin witness attestations via ordinals
51
+ * - Provide maximum immutability and timestamping
52
+ * - Cannot be migrated to any other layer
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * const bitcoinManager = new BitcoinManager(config);
57
+ * const manager = new BtcoCelManager(
58
+ * async (data) => createEdDsaProof(data, privateKey),
59
+ * bitcoinManager
60
+ * );
61
+ *
62
+ * const btcoLog = await manager.migrate(webvhLog);
63
+ * console.log(btcoLog.events[btcoLog.events.length - 1].data.txid);
64
+ * ```
65
+ */
66
+ export declare class BtcoCelManager {
67
+ private signer;
68
+ private bitcoinManager;
69
+ private bitcoinWitness;
70
+ private config;
71
+ /**
72
+ * Creates a new BtcoCelManager instance
73
+ *
74
+ * @param signer - Function that signs data and returns a DataIntegrityProof
75
+ * @param bitcoinManager - BitcoinManager instance for ordinals inscriptions
76
+ * @param config - Optional configuration options
77
+ */
78
+ constructor(signer: CelSigner, bitcoinManager: BitcoinManager, config?: BtcoCelConfig);
79
+ /**
80
+ * Migrates a webvh layer event log to the did:btco layer
81
+ *
82
+ * This method:
83
+ * 1. Validates the input log (must have migrated to webvh layer)
84
+ * 2. Creates an update event with migration data
85
+ * 3. Adds mandatory Bitcoin witness proof via ordinals inscription
86
+ * 4. Generates a did:btco DID based on the inscription
87
+ * 5. Returns the updated EventLog
88
+ *
89
+ * Note: Bitcoin witness is REQUIRED at this layer - it cannot be skipped.
90
+ *
91
+ * @param webvhLog - The event log from the webvh layer to migrate
92
+ * @returns Promise resolving to an EventLog with the migration event appended
93
+ *
94
+ * @throws Error if the log is empty, deactivated, or not from webvh layer
95
+ * @throws Error if signer produces invalid proof
96
+ * @throws Error if Bitcoin inscription fails
97
+ */
98
+ migrate(webvhLog: EventLog): Promise<EventLog>;
99
+ /**
100
+ * Generates a did:btco DID fallback from source DID
101
+ *
102
+ * @param sourceDid - The source DID to derive from
103
+ * @returns A did:btco string
104
+ */
105
+ private generateBtcoDid;
106
+ /**
107
+ * Creates a URL-safe hash-based identifier from a string
108
+ */
109
+ private hashIdentifier;
110
+ /**
111
+ * Derives the current asset state by replaying all events in the log.
112
+ *
113
+ * @param log - The event log to derive state from
114
+ * @returns The current AssetState derived from replaying events
115
+ */
116
+ getCurrentState(log: EventLog): AssetState;
117
+ /**
118
+ * Gets the BitcoinManager instance used by this manager
119
+ */
120
+ get bitcoin(): BitcoinManager;
121
+ }
@@ -0,0 +1,329 @@
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
+ import { updateEventLog } from '../algorithms/updateEventLog';
14
+ import { witnessEvent } from '../algorithms/witnessEvent';
15
+ import { BitcoinWitness } from '../witnesses/BitcoinWitness';
16
+ /**
17
+ * BtcoCelManager - Manages CEL-based asset migration to did:btco layer
18
+ *
19
+ * The btco layer is the final publication layer for Originals assets.
20
+ * Assets at this layer:
21
+ * - Have a did:btco identifier anchored on Bitcoin
22
+ * - Have mandatory Bitcoin witness attestations via ordinals
23
+ * - Provide maximum immutability and timestamping
24
+ * - Cannot be migrated to any other layer
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * const bitcoinManager = new BitcoinManager(config);
29
+ * const manager = new BtcoCelManager(
30
+ * async (data) => createEdDsaProof(data, privateKey),
31
+ * bitcoinManager
32
+ * );
33
+ *
34
+ * const btcoLog = await manager.migrate(webvhLog);
35
+ * console.log(btcoLog.events[btcoLog.events.length - 1].data.txid);
36
+ * ```
37
+ */
38
+ export class BtcoCelManager {
39
+ /**
40
+ * Creates a new BtcoCelManager instance
41
+ *
42
+ * @param signer - Function that signs data and returns a DataIntegrityProof
43
+ * @param bitcoinManager - BitcoinManager instance for ordinals inscriptions
44
+ * @param config - Optional configuration options
45
+ */
46
+ constructor(signer, bitcoinManager, config = {}) {
47
+ if (typeof signer !== 'function') {
48
+ throw new Error('BtcoCelManager requires a signer function');
49
+ }
50
+ if (!bitcoinManager) {
51
+ throw new Error('BtcoCelManager requires a BitcoinManager instance');
52
+ }
53
+ this.signer = signer;
54
+ this.bitcoinManager = bitcoinManager;
55
+ this.config = {
56
+ proofPurpose: 'assertionMethod',
57
+ ...config,
58
+ };
59
+ // Create Bitcoin witness service with optional fee rate
60
+ this.bitcoinWitness = new BitcoinWitness(bitcoinManager, {
61
+ feeRate: config.feeRate,
62
+ verificationMethod: config.verificationMethod,
63
+ });
64
+ }
65
+ /**
66
+ * Migrates a webvh layer event log to the did:btco layer
67
+ *
68
+ * This method:
69
+ * 1. Validates the input log (must have migrated to webvh layer)
70
+ * 2. Creates an update event with migration data
71
+ * 3. Adds mandatory Bitcoin witness proof via ordinals inscription
72
+ * 4. Generates a did:btco DID based on the inscription
73
+ * 5. Returns the updated EventLog
74
+ *
75
+ * Note: Bitcoin witness is REQUIRED at this layer - it cannot be skipped.
76
+ *
77
+ * @param webvhLog - The event log from the webvh 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 webvh layer
81
+ * @throws Error if signer produces invalid proof
82
+ * @throws Error if Bitcoin inscription fails
83
+ */
84
+ async migrate(webvhLog) {
85
+ // Validate input log
86
+ if (!webvhLog || !webvhLog.events || webvhLog.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 = webvhLog.events[0];
91
+ if (createEvent.type !== 'create') {
92
+ throw new Error('First event must be a create event');
93
+ }
94
+ // Find the current layer and DID by checking for migration events
95
+ let currentDid;
96
+ let currentLayer;
97
+ // Look through events to find the latest migration
98
+ for (const event of webvhLog.events) {
99
+ const eventData = event.data;
100
+ if (event.type === 'create') {
101
+ currentDid = eventData.did;
102
+ currentLayer = eventData.layer || 'peer';
103
+ }
104
+ else if (event.type === 'update' && eventData.targetDid && eventData.layer) {
105
+ // This is a migration event
106
+ currentDid = eventData.targetDid;
107
+ currentLayer = eventData.layer;
108
+ }
109
+ }
110
+ if (!currentDid) {
111
+ throw new Error('Could not determine current DID from event log');
112
+ }
113
+ // Validate source is from webvh layer (only webvh can migrate to btco)
114
+ if (currentLayer !== 'webvh') {
115
+ throw new Error(`Cannot migrate from ${currentLayer} layer to btco layer. Must migrate to webvh first.`);
116
+ }
117
+ // Check if log is already deactivated
118
+ const lastEvent = webvhLog.events[webvhLog.events.length - 1];
119
+ if (lastEvent.type === 'deactivate') {
120
+ throw new Error('Cannot migrate a deactivated event log');
121
+ }
122
+ // Prepare initial migration data (will be updated with Bitcoin details after witnessing)
123
+ const migrationData = {
124
+ sourceDid: currentDid,
125
+ targetDid: '', // Will be set after inscription
126
+ layer: 'btco',
127
+ migratedAt: new Date().toISOString(),
128
+ };
129
+ // Build update options
130
+ const updateOptions = {
131
+ signer: this.signer,
132
+ verificationMethod: this.config.verificationMethod || `${currentDid}#key-0`,
133
+ proofPurpose: this.config.proofPurpose,
134
+ };
135
+ // Create the update event with migration data
136
+ let updatedLog = await updateEventLog(webvhLog, migrationData, updateOptions);
137
+ // Add Bitcoin witness proof (REQUIRED at btco layer)
138
+ const lastEventIndex = updatedLog.events.length - 1;
139
+ let witnessedEvent = updatedLog.events[lastEventIndex];
140
+ // Witness the event on Bitcoin
141
+ witnessedEvent = await witnessEvent(witnessedEvent, this.bitcoinWitness);
142
+ // Extract Bitcoin details from the witness proof
143
+ const bitcoinProof = witnessedEvent.proof.find(p => p.cryptosuite === 'bitcoin-ordinals-2024');
144
+ // Generate did:btco DID using inscription ID
145
+ let targetDid;
146
+ let txid;
147
+ let inscriptionId;
148
+ if (bitcoinProof) {
149
+ txid = bitcoinProof.txid;
150
+ inscriptionId = bitcoinProof.inscriptionId;
151
+ // did:btco format uses the inscription ID for identification
152
+ if (inscriptionId) {
153
+ // Sanitize inscription ID for DID (remove special chars)
154
+ const sanitizedId = inscriptionId.replace(/[^a-zA-Z0-9]/g, '');
155
+ targetDid = `did:btco:${sanitizedId}`;
156
+ }
157
+ else if (txid) {
158
+ targetDid = `did:btco:${txid}`;
159
+ }
160
+ else {
161
+ // Fallback: derive from source DID
162
+ targetDid = this.generateBtcoDid(currentDid);
163
+ }
164
+ }
165
+ else {
166
+ // Fallback: derive from source DID (shouldn't happen since witness is required)
167
+ targetDid = this.generateBtcoDid(currentDid);
168
+ }
169
+ // Update migration data with Bitcoin details
170
+ const updatedMigrationData = {
171
+ ...migrationData,
172
+ targetDid,
173
+ txid,
174
+ inscriptionId,
175
+ };
176
+ // Replace the event data with updated migration data
177
+ witnessedEvent = {
178
+ ...witnessedEvent,
179
+ data: updatedMigrationData,
180
+ };
181
+ // Replace the last event with the witnessed version
182
+ updatedLog = {
183
+ ...updatedLog,
184
+ events: [
185
+ ...updatedLog.events.slice(0, lastEventIndex),
186
+ witnessedEvent,
187
+ ],
188
+ };
189
+ return updatedLog;
190
+ }
191
+ /**
192
+ * Generates a did:btco DID fallback from source DID
193
+ *
194
+ * @param sourceDid - The source DID to derive from
195
+ * @returns A did:btco string
196
+ */
197
+ generateBtcoDid(sourceDid) {
198
+ // Extract identifier portion from source DID
199
+ let idPart;
200
+ if (sourceDid.startsWith('did:webvh:')) {
201
+ // For webvh DIDs, extract the identifier after domain
202
+ const parts = sourceDid.split(':');
203
+ idPart = parts.length > 3 ? parts.slice(3).join('') : this.hashIdentifier(sourceDid);
204
+ }
205
+ else {
206
+ // For other DIDs, create a hash-based identifier
207
+ idPart = this.hashIdentifier(sourceDid);
208
+ }
209
+ // Sanitize for DID (alphanumeric only)
210
+ idPart = idPart.replace(/[^a-zA-Z0-9]/g, '').substring(0, 64);
211
+ return `did:btco:${idPart}`;
212
+ }
213
+ /**
214
+ * Creates a URL-safe hash-based identifier from a string
215
+ */
216
+ hashIdentifier(input) {
217
+ // Simple hash for identifier generation (not cryptographic)
218
+ let hash = 0;
219
+ for (let i = 0; i < input.length; i++) {
220
+ const char = input.charCodeAt(i);
221
+ hash = ((hash << 5) - hash) + char;
222
+ hash = hash & hash; // Convert to 32bit integer
223
+ }
224
+ return Math.abs(hash).toString(36);
225
+ }
226
+ /**
227
+ * Derives the current asset state by replaying all events in the log.
228
+ *
229
+ * @param log - The event log to derive state from
230
+ * @returns The current AssetState derived from replaying events
231
+ */
232
+ getCurrentState(log) {
233
+ // Validate input log
234
+ if (!log || !log.events || log.events.length === 0) {
235
+ throw new Error('Cannot get state from an empty event log');
236
+ }
237
+ // First event must be a create event
238
+ const createEvent = log.events[0];
239
+ if (createEvent.type !== 'create') {
240
+ throw new Error('First event must be a create event');
241
+ }
242
+ // Extract initial state from create event
243
+ const createData = createEvent.data;
244
+ // Initialize state from create event
245
+ const state = {
246
+ did: createData.did,
247
+ name: createData.name,
248
+ layer: createData.layer || 'peer',
249
+ resources: createData.resources || [],
250
+ creator: createData.creator,
251
+ createdAt: createData.createdAt,
252
+ updatedAt: undefined,
253
+ deactivated: false,
254
+ metadata: {},
255
+ };
256
+ // Apply subsequent events
257
+ for (let i = 1; i < log.events.length; i++) {
258
+ const event = log.events[i];
259
+ if (event.type === 'update') {
260
+ const updateData = event.data;
261
+ // Check if this is a migration event
262
+ if (updateData.targetDid && updateData.layer) {
263
+ // Migration event - update DID and layer
264
+ state.did = updateData.targetDid;
265
+ state.layer = updateData.layer;
266
+ state.updatedAt = updateData.migratedAt;
267
+ // Store migration info in metadata
268
+ state.metadata = state.metadata || {};
269
+ state.metadata.sourceDid = updateData.sourceDid;
270
+ // Store Bitcoin-specific metadata for btco layer
271
+ if (updateData.layer === 'btco') {
272
+ if (updateData.txid) {
273
+ state.metadata.txid = updateData.txid;
274
+ }
275
+ if (updateData.inscriptionId) {
276
+ state.metadata.inscriptionId = updateData.inscriptionId;
277
+ }
278
+ }
279
+ else if (updateData.domain) {
280
+ state.metadata.domain = updateData.domain;
281
+ }
282
+ }
283
+ else {
284
+ // Regular update event
285
+ if (updateData.name !== undefined) {
286
+ state.name = updateData.name;
287
+ }
288
+ if (updateData.resources !== undefined) {
289
+ state.resources = updateData.resources;
290
+ }
291
+ if (updateData.updatedAt !== undefined) {
292
+ state.updatedAt = updateData.updatedAt;
293
+ }
294
+ if (updateData.did !== undefined) {
295
+ state.did = updateData.did;
296
+ }
297
+ if (updateData.layer !== undefined) {
298
+ state.layer = updateData.layer;
299
+ }
300
+ }
301
+ // Store other fields in metadata
302
+ for (const [key, value] of Object.entries(updateData)) {
303
+ if (!['name', 'resources', 'updatedAt', 'did', 'layer', 'creator', 'createdAt', 'sourceDid', 'targetDid', 'domain', 'migratedAt', 'txid', 'inscriptionId'].includes(key)) {
304
+ state.metadata = state.metadata || {};
305
+ state.metadata[key] = value;
306
+ }
307
+ }
308
+ }
309
+ else if (event.type === 'deactivate') {
310
+ state.deactivated = true;
311
+ const deactivateData = event.data;
312
+ if (deactivateData.deactivatedAt !== undefined) {
313
+ state.updatedAt = deactivateData.deactivatedAt;
314
+ }
315
+ if (deactivateData.reason !== undefined) {
316
+ state.metadata = state.metadata || {};
317
+ state.metadata.deactivationReason = deactivateData.reason;
318
+ }
319
+ }
320
+ }
321
+ return state;
322
+ }
323
+ /**
324
+ * Gets the BitcoinManager instance used by this manager
325
+ */
326
+ get bitcoin() {
327
+ return this.bitcoinManager;
328
+ }
329
+ }