@originals/sdk 1.8.1 → 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.
Files changed (145) hide show
  1. package/dist/utils/hash.js +1 -0
  2. package/package.json +6 -5
  3. package/src/adapters/FeeOracleMock.ts +9 -0
  4. package/src/adapters/index.ts +5 -0
  5. package/src/adapters/providers/OrdHttpProvider.ts +126 -0
  6. package/src/adapters/providers/OrdMockProvider.ts +101 -0
  7. package/src/adapters/types.ts +66 -0
  8. package/src/bitcoin/BitcoinManager.ts +329 -0
  9. package/src/bitcoin/BroadcastClient.ts +54 -0
  10. package/src/bitcoin/OrdinalsClient.ts +120 -0
  11. package/src/bitcoin/PSBTBuilder.ts +106 -0
  12. package/src/bitcoin/fee-calculation.ts +38 -0
  13. package/src/bitcoin/providers/OrdNodeProvider.ts +92 -0
  14. package/src/bitcoin/providers/OrdinalsProvider.ts +56 -0
  15. package/src/bitcoin/providers/types.ts +59 -0
  16. package/src/bitcoin/transactions/commit.ts +465 -0
  17. package/src/bitcoin/transactions/index.ts +13 -0
  18. package/src/bitcoin/transfer.ts +43 -0
  19. package/src/bitcoin/utxo-selection.ts +322 -0
  20. package/src/bitcoin/utxo.ts +113 -0
  21. package/src/cel/ExternalReferenceManager.ts +87 -0
  22. package/src/cel/OriginalsCel.ts +460 -0
  23. package/src/cel/algorithms/createEventLog.ts +68 -0
  24. package/src/cel/algorithms/deactivateEventLog.ts +109 -0
  25. package/src/cel/algorithms/index.ts +11 -0
  26. package/src/cel/algorithms/updateEventLog.ts +99 -0
  27. package/src/cel/algorithms/verifyEventLog.ts +306 -0
  28. package/src/cel/algorithms/witnessEvent.ts +87 -0
  29. package/src/cel/cli/create.ts +330 -0
  30. package/src/cel/cli/index.ts +383 -0
  31. package/src/cel/cli/inspect.ts +549 -0
  32. package/src/cel/cli/migrate.ts +473 -0
  33. package/src/cel/cli/verify.ts +249 -0
  34. package/src/cel/hash.ts +71 -0
  35. package/src/cel/index.ts +16 -0
  36. package/src/cel/layers/BtcoCelManager.ts +408 -0
  37. package/src/cel/layers/PeerCelManager.ts +371 -0
  38. package/src/cel/layers/WebVHCelManager.ts +361 -0
  39. package/src/cel/layers/index.ts +27 -0
  40. package/src/cel/serialization/cbor.ts +189 -0
  41. package/src/cel/serialization/index.ts +10 -0
  42. package/src/cel/serialization/json.ts +209 -0
  43. package/src/cel/types.ts +160 -0
  44. package/src/cel/witnesses/BitcoinWitness.ts +184 -0
  45. package/src/cel/witnesses/HttpWitness.ts +241 -0
  46. package/src/cel/witnesses/WitnessService.ts +51 -0
  47. package/src/cel/witnesses/index.ts +11 -0
  48. package/src/contexts/credentials-v1.json +237 -0
  49. package/src/contexts/credentials-v2-examples.json +5 -0
  50. package/src/contexts/credentials-v2.json +340 -0
  51. package/src/contexts/credentials.json +237 -0
  52. package/src/contexts/data-integrity-v2.json +81 -0
  53. package/src/contexts/dids.json +58 -0
  54. package/src/contexts/ed255192020.json +93 -0
  55. package/src/contexts/ordinals-plus.json +23 -0
  56. package/src/contexts/originals.json +22 -0
  57. package/src/core/OriginalsSDK.ts +420 -0
  58. package/src/crypto/Multikey.ts +194 -0
  59. package/src/crypto/Signer.ts +262 -0
  60. package/src/crypto/noble-init.ts +138 -0
  61. package/src/did/BtcoDidResolver.ts +231 -0
  62. package/src/did/DIDManager.ts +705 -0
  63. package/src/did/Ed25519Verifier.ts +68 -0
  64. package/src/did/KeyManager.ts +239 -0
  65. package/src/did/WebVHManager.ts +499 -0
  66. package/src/did/createBtcoDidDocument.ts +60 -0
  67. package/src/did/providers/OrdinalsClientProviderAdapter.ts +68 -0
  68. package/src/events/EventEmitter.ts +222 -0
  69. package/src/events/index.ts +19 -0
  70. package/src/events/types.ts +331 -0
  71. package/src/examples/basic-usage.ts +78 -0
  72. package/src/examples/create-module-original.ts +435 -0
  73. package/src/examples/full-lifecycle-flow.ts +514 -0
  74. package/src/examples/run.ts +60 -0
  75. package/src/index.ts +204 -0
  76. package/src/kinds/KindRegistry.ts +320 -0
  77. package/src/kinds/index.ts +74 -0
  78. package/src/kinds/types.ts +470 -0
  79. package/src/kinds/validators/AgentValidator.ts +257 -0
  80. package/src/kinds/validators/AppValidator.ts +211 -0
  81. package/src/kinds/validators/DatasetValidator.ts +242 -0
  82. package/src/kinds/validators/DocumentValidator.ts +311 -0
  83. package/src/kinds/validators/MediaValidator.ts +269 -0
  84. package/src/kinds/validators/ModuleValidator.ts +225 -0
  85. package/src/kinds/validators/base.ts +276 -0
  86. package/src/kinds/validators/index.ts +12 -0
  87. package/src/lifecycle/BatchOperations.ts +381 -0
  88. package/src/lifecycle/LifecycleManager.ts +2156 -0
  89. package/src/lifecycle/OriginalsAsset.ts +524 -0
  90. package/src/lifecycle/ProvenanceQuery.ts +280 -0
  91. package/src/lifecycle/ResourceVersioning.ts +163 -0
  92. package/src/migration/MigrationManager.ts +587 -0
  93. package/src/migration/audit/AuditLogger.ts +176 -0
  94. package/src/migration/checkpoint/CheckpointManager.ts +112 -0
  95. package/src/migration/checkpoint/CheckpointStorage.ts +101 -0
  96. package/src/migration/index.ts +33 -0
  97. package/src/migration/operations/BaseMigration.ts +126 -0
  98. package/src/migration/operations/PeerToBtcoMigration.ts +105 -0
  99. package/src/migration/operations/PeerToWebvhMigration.ts +62 -0
  100. package/src/migration/operations/WebvhToBtcoMigration.ts +105 -0
  101. package/src/migration/rollback/RollbackManager.ts +170 -0
  102. package/src/migration/state/StateMachine.ts +92 -0
  103. package/src/migration/state/StateTracker.ts +156 -0
  104. package/src/migration/types.ts +356 -0
  105. package/src/migration/validation/BitcoinValidator.ts +107 -0
  106. package/src/migration/validation/CredentialValidator.ts +62 -0
  107. package/src/migration/validation/DIDCompatibilityValidator.ts +151 -0
  108. package/src/migration/validation/LifecycleValidator.ts +64 -0
  109. package/src/migration/validation/StorageValidator.ts +79 -0
  110. package/src/migration/validation/ValidationPipeline.ts +213 -0
  111. package/src/resources/ResourceManager.ts +655 -0
  112. package/src/resources/index.ts +21 -0
  113. package/src/resources/types.ts +202 -0
  114. package/src/storage/LocalStorageAdapter.ts +64 -0
  115. package/src/storage/MemoryStorageAdapter.ts +29 -0
  116. package/src/storage/StorageAdapter.ts +25 -0
  117. package/src/storage/index.ts +3 -0
  118. package/src/types/bitcoin.ts +98 -0
  119. package/src/types/common.ts +92 -0
  120. package/src/types/credentials.ts +89 -0
  121. package/src/types/did.ts +31 -0
  122. package/src/types/external-shims.d.ts +53 -0
  123. package/src/types/index.ts +7 -0
  124. package/src/types/network.ts +178 -0
  125. package/src/utils/EventLogger.ts +298 -0
  126. package/src/utils/Logger.ts +324 -0
  127. package/src/utils/MetricsCollector.ts +358 -0
  128. package/src/utils/bitcoin-address.ts +132 -0
  129. package/src/utils/cbor.ts +31 -0
  130. package/src/utils/encoding.ts +135 -0
  131. package/src/utils/hash.ts +12 -0
  132. package/src/utils/retry.ts +46 -0
  133. package/src/utils/satoshi-validation.ts +196 -0
  134. package/src/utils/serialization.ts +102 -0
  135. package/src/utils/telemetry.ts +44 -0
  136. package/src/utils/validation.ts +123 -0
  137. package/src/vc/CredentialManager.ts +955 -0
  138. package/src/vc/Issuer.ts +105 -0
  139. package/src/vc/Verifier.ts +54 -0
  140. package/src/vc/cryptosuites/bbs.ts +253 -0
  141. package/src/vc/cryptosuites/bbsSimple.ts +21 -0
  142. package/src/vc/cryptosuites/eddsa.ts +99 -0
  143. package/src/vc/documentLoader.ts +81 -0
  144. package/src/vc/proofs/data-integrity.ts +33 -0
  145. 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
+ }