@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,587 @@
1
+ /**
2
+ * MigrationManager - Main orchestrator for DID layer migrations
3
+ * Coordinates validation, checkpoints, rollbacks, state tracking, and audit logging
4
+ */
5
+
6
+ import {
7
+ MigrationOptions,
8
+ MigrationResult,
9
+ MigrationStateEnum,
10
+ MigrationError,
11
+ MigrationErrorType,
12
+ BatchMigrationOptions,
13
+ BatchMigrationResult,
14
+ CostEstimate
15
+ } from './types';
16
+ import { OriginalsConfig } from '../types';
17
+ import { DIDManager } from '../did/DIDManager';
18
+ import { CredentialManager } from '../vc/CredentialManager';
19
+ import { BitcoinManager } from '../bitcoin/BitcoinManager';
20
+ import { ValidationPipeline } from './validation/ValidationPipeline';
21
+ import { CheckpointManager } from './checkpoint/CheckpointManager';
22
+ import { RollbackManager } from './rollback/RollbackManager';
23
+ import { StateTracker } from './state/StateTracker';
24
+ // TODO: AuditLogger temporarily disabled for v1.0 release
25
+ // Will be re-enabled in v1.1 with proper Ed25519 digital signatures
26
+ // import { AuditLogger } from './audit/AuditLogger';
27
+ import { PeerToWebvhMigration } from './operations/PeerToWebvhMigration';
28
+ import { WebvhToBtcoMigration } from './operations/WebvhToBtcoMigration';
29
+ import { PeerToBtcoMigration } from './operations/PeerToBtcoMigration';
30
+ import { EventEmitter } from '../events/EventEmitter';
31
+
32
+ export class MigrationManager {
33
+ private static instance: MigrationManager | null = null;
34
+
35
+ private validationPipeline: ValidationPipeline;
36
+ private checkpointManager: CheckpointManager;
37
+ private rollbackManager: RollbackManager;
38
+ private stateTracker: StateTracker;
39
+ // TODO: AuditLogger temporarily disabled for v1.0 release
40
+ // private auditLogger: AuditLogger;
41
+ private eventEmitter: EventEmitter;
42
+
43
+ // Temporary in-memory audit storage for v1.0 (unsigned records)
44
+ // Will be replaced by proper AuditLogger with signatures in v1.1
45
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
46
+ private inMemoryAuditRecords: Map<string, any[]>;
47
+
48
+ // Migration operation handlers
49
+ private peerToWebvh: PeerToWebvhMigration;
50
+ private webvhToBtco: WebvhToBtcoMigration;
51
+ private peerToBtco: PeerToBtcoMigration;
52
+
53
+ private constructor(
54
+ private config: OriginalsConfig,
55
+ private didManager: DIDManager,
56
+ private credentialManager: CredentialManager,
57
+ private bitcoinManager?: BitcoinManager
58
+ ) {
59
+ // Initialize components
60
+ this.validationPipeline = new ValidationPipeline(
61
+ config,
62
+ didManager,
63
+ credentialManager,
64
+ bitcoinManager
65
+ );
66
+ this.checkpointManager = new CheckpointManager(config, didManager, credentialManager);
67
+ this.stateTracker = new StateTracker(config);
68
+ this.rollbackManager = new RollbackManager(config, this.checkpointManager, didManager);
69
+ // TODO: AuditLogger temporarily disabled for v1.0 release
70
+ // this.auditLogger = new AuditLogger(config);
71
+ this.eventEmitter = new EventEmitter();
72
+
73
+ // Initialize in-memory audit storage for v1.0
74
+ this.inMemoryAuditRecords = new Map();
75
+
76
+ // Initialize migration operations
77
+ this.peerToWebvh = new PeerToWebvhMigration(config, didManager, credentialManager, this.stateTracker);
78
+
79
+ if (bitcoinManager) {
80
+ this.webvhToBtco = new WebvhToBtcoMigration(config, didManager, credentialManager, this.stateTracker, bitcoinManager);
81
+ this.peerToBtco = new PeerToBtcoMigration(config, didManager, credentialManager, this.stateTracker, bitcoinManager);
82
+ } else {
83
+ // Create stub implementations that throw errors
84
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any
85
+ this.webvhToBtco = null as any;
86
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any
87
+ this.peerToBtco = null as any;
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Get singleton instance
93
+ */
94
+ static getInstance(
95
+ config?: OriginalsConfig,
96
+ didManager?: DIDManager,
97
+ credentialManager?: CredentialManager,
98
+ bitcoinManager?: BitcoinManager
99
+ ): MigrationManager {
100
+ if (!MigrationManager.instance) {
101
+ if (!config || !didManager || !credentialManager) {
102
+ throw new Error('Configuration and managers required for first initialization');
103
+ }
104
+ MigrationManager.instance = new MigrationManager(config, didManager, credentialManager, bitcoinManager);
105
+ }
106
+ return MigrationManager.instance;
107
+ }
108
+
109
+ /**
110
+ * Reset singleton instance (primarily for testing)
111
+ */
112
+ static resetInstance(): void {
113
+ MigrationManager.instance = null;
114
+ }
115
+
116
+ /**
117
+ * Main migration method
118
+ */
119
+ async migrate(options: MigrationOptions): Promise<MigrationResult> {
120
+ const startTime = Date.now();
121
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
122
+ let migrationState: any;
123
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
124
+ let checkpoint: any;
125
+
126
+ try {
127
+ // Step 1: Create migration state
128
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
129
+ migrationState = await this.stateTracker.createMigration(options);
130
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
131
+ const migrationId = migrationState.migrationId;
132
+
133
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
134
+ await this.emitEvent('migration:started', { migrationId, options });
135
+
136
+ // Step 2: Validate migration
137
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
138
+ await this.stateTracker.updateState(migrationId, {
139
+ state: MigrationStateEnum.VALIDATING,
140
+ currentOperation: 'Validating migration',
141
+ progress: 10
142
+ });
143
+
144
+ const validationResult = await this.validationPipeline.validate(options);
145
+
146
+ if (!validationResult.valid) {
147
+ throw this.createMigrationError(
148
+ MigrationErrorType.VALIDATION_ERROR,
149
+ 'VALIDATION_FAILED',
150
+ `Migration validation failed: ${validationResult.errors.map(e => e.message).join(', ')}`,
151
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
152
+ migrationId,
153
+ { errors: validationResult.errors }
154
+ );
155
+ }
156
+
157
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
158
+ await this.emitEvent('migration:validated', { migrationId, validationResult });
159
+
160
+ // Step 3: Create checkpoint
161
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
162
+ await this.stateTracker.updateState(migrationId, {
163
+ state: MigrationStateEnum.CHECKPOINTED,
164
+ currentOperation: 'Creating checkpoint',
165
+ progress: 20
166
+ });
167
+
168
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-assignment
169
+ checkpoint = await this.checkpointManager.createCheckpoint(migrationId, options);
170
+
171
+ // Persist checkpointId immediately so rollback can locate it
172
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
173
+ await this.stateTracker.updateState(migrationId, {
174
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
175
+ checkpointId: checkpoint.checkpointId
176
+ });
177
+
178
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
179
+ await this.emitEvent('migration:checkpointed', { migrationId, checkpointId: checkpoint.checkpointId });
180
+
181
+ // Step 4: Execute migration
182
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
183
+ const migration = this.getMigrationOperation(options);
184
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-argument
185
+ const result = await migration.executeMigration(options, migrationId);
186
+
187
+ // Step 5: Complete migration
188
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
189
+ await this.stateTracker.updateState(migrationId, {
190
+ state: MigrationStateEnum.COMPLETED,
191
+ currentOperation: 'Completed',
192
+ progress: 100,
193
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
194
+ targetDid: result.targetDid
195
+ });
196
+
197
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
198
+ await this.emitEvent('migration:completed', { migrationId, targetDid: result.targetDid });
199
+
200
+ // Step 6: Create audit record
201
+ const duration = Date.now() - startTime;
202
+ const auditRecord = {
203
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
204
+ migrationId,
205
+ timestamp: startTime,
206
+ initiator: 'system',
207
+ sourceDid: options.sourceDid,
208
+ sourceLayer: this.extractLayer(options.sourceDid),
209
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
210
+ targetDid: result.targetDid,
211
+ targetLayer: options.targetLayer,
212
+ finalState: MigrationStateEnum.COMPLETED,
213
+ validationResults: validationResult,
214
+ costActual: validationResult.estimatedCost,
215
+ duration,
216
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
217
+ checkpointId: checkpoint.checkpointId,
218
+ errors: [],
219
+ metadata: options.metadata || {}
220
+ };
221
+
222
+ // TODO: AuditLogger temporarily disabled for v1.0 release
223
+ // Store in-memory for v1.0 (unsigned, will be replaced with signed records in v1.1)
224
+ this.storeAuditRecordInMemory(auditRecord);
225
+
226
+ // Clean up checkpoint after successful migration
227
+ setTimeout(() => {
228
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-floating-promises
229
+ this.checkpointManager.deleteCheckpoint(checkpoint.checkpointId);
230
+ }, 24 * 60 * 60 * 1000); // Delete after 24 hours
231
+
232
+ return {
233
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
234
+ migrationId,
235
+ success: true,
236
+ sourceDid: options.sourceDid,
237
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
238
+ targetDid: result.targetDid,
239
+ sourceLayer: this.extractLayer(options.sourceDid),
240
+ targetLayer: options.targetLayer,
241
+ state: MigrationStateEnum.COMPLETED,
242
+ duration,
243
+ cost: validationResult.estimatedCost,
244
+ auditRecord
245
+ };
246
+ } catch (error) {
247
+ // Handle migration failure
248
+ return await this.handleMigrationFailure(
249
+ error,
250
+ options,
251
+ migrationState,
252
+ checkpoint,
253
+ startTime
254
+ );
255
+ }
256
+ }
257
+
258
+ /**
259
+ * Estimate migration cost without executing
260
+ */
261
+ async estimateMigrationCost(sourceDid: string, targetLayer: string, feeRate?: number): Promise<CostEstimate> {
262
+ const options: MigrationOptions = {
263
+ sourceDid,
264
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any
265
+ targetLayer: targetLayer as any,
266
+ feeRate,
267
+ estimateCostOnly: true
268
+ };
269
+
270
+ const validationResult = await this.validationPipeline.validate(options);
271
+ return validationResult.estimatedCost;
272
+ }
273
+
274
+ /**
275
+ * Get migration status
276
+ */
277
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
278
+ async getMigrationStatus(migrationId: string): Promise<any> {
279
+ return await this.stateTracker.getState(migrationId);
280
+ }
281
+
282
+ /**
283
+ * Rollback a migration
284
+ */
285
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
286
+ async rollback(migrationId: string): Promise<any> {
287
+ const state = await this.stateTracker.getState(migrationId);
288
+ if (!state || !state.checkpointId) {
289
+ throw new Error(`Migration ${migrationId} not found or has no checkpoint`);
290
+ }
291
+
292
+ const rollbackResult = await this.rollbackManager.rollback(migrationId, state.checkpointId);
293
+
294
+ await this.emitEvent('migration:rolledback', { migrationId, rollbackResult });
295
+
296
+ return rollbackResult;
297
+ }
298
+
299
+ /**
300
+ * Get migration history for a DID
301
+ * TODO: AuditLogger temporarily disabled for v1.0 release
302
+ * Returns in-memory audit records (unsigned) - will use proper AuditLogger in v1.1
303
+ */
304
+ // eslint-disable-next-line @typescript-eslint/require-await, @typescript-eslint/no-explicit-any
305
+ async getMigrationHistory(did: string): Promise<any[]> {
306
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
307
+ return this.inMemoryAuditRecords.get(did) || [];
308
+ }
309
+
310
+ /**
311
+ * Batch migration
312
+ */
313
+ async migrateBatch(dids: string[], targetLayer: string, options?: BatchMigrationOptions): Promise<BatchMigrationResult> {
314
+ const batchId = `batch_${Date.now()}`;
315
+ const results = new Map<string, MigrationResult>();
316
+ const errors: MigrationError[] = [];
317
+
318
+ let completed = 0;
319
+ let failed = 0;
320
+ const total = dids.length;
321
+
322
+ for (const did of dids) {
323
+ try {
324
+ const migrationOptions: MigrationOptions = {
325
+ sourceDid: did,
326
+ targetLayer: targetLayer as any,
327
+ ...options
328
+ };
329
+
330
+ const result = await this.migrate(migrationOptions);
331
+ results.set(did, result);
332
+
333
+ if (result.success) {
334
+ completed++;
335
+ } else {
336
+ failed++;
337
+ }
338
+ } catch (error) {
339
+ failed++;
340
+ const migrationError: MigrationError = {
341
+ type: MigrationErrorType.UNKNOWN_ERROR,
342
+ code: 'BATCH_MIGRATION_ERROR',
343
+ message: error instanceof Error ? error.message : String(error),
344
+ sourceDid: did,
345
+ timestamp: Date.now()
346
+ };
347
+ errors.push(migrationError);
348
+
349
+ if (!options?.continueOnError) {
350
+ break;
351
+ }
352
+ }
353
+ }
354
+
355
+ return {
356
+ batchId,
357
+ total,
358
+ completed,
359
+ failed,
360
+ inProgress: 0,
361
+ results,
362
+ overallProgress: (completed + failed) / total * 100,
363
+ startTime: Date.now(),
364
+ errors
365
+ };
366
+ }
367
+
368
+ /**
369
+ * Handle migration failure with automatic rollback
370
+ */
371
+ private async handleMigrationFailure(
372
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
373
+ error: any,
374
+ options: MigrationOptions,
375
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
376
+ migrationState: any,
377
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
378
+ checkpoint: any,
379
+ startTime: number
380
+ ): Promise<MigrationResult> {
381
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
382
+ const migrationId = migrationState?.migrationId || `mig_failed_${Date.now()}`;
383
+
384
+ const migrationError: MigrationError = {
385
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
386
+ type: error.type || MigrationErrorType.UNKNOWN_ERROR,
387
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
388
+ code: error.code || 'MIGRATION_FAILED',
389
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
390
+ message: error.message || String(error),
391
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
392
+ technicalDetails: error.stack,
393
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
394
+ migrationId,
395
+ sourceDid: options.sourceDid,
396
+ timestamp: Date.now()
397
+ };
398
+
399
+ // Update state to failed
400
+ if (migrationState) {
401
+ try {
402
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
403
+ await this.stateTracker.updateState(migrationId, {
404
+ state: MigrationStateEnum.FAILED,
405
+ error: migrationError
406
+ });
407
+ } catch (updateError) {
408
+ console.error('Failed to update migration state:', updateError);
409
+ }
410
+ }
411
+
412
+ await this.emitEvent('migration:failed', { migrationId, error: migrationError });
413
+
414
+ // Attempt rollback if checkpoint exists
415
+ let rollbackSuccess = false;
416
+ if (checkpoint) {
417
+ try {
418
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
419
+ const rollbackResult = await this.rollbackManager.rollback(migrationId, checkpoint.checkpointId);
420
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
421
+ rollbackSuccess = rollbackResult.success;
422
+
423
+ if (!rollbackSuccess) {
424
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
425
+ await this.emitEvent('migration:quarantine', {
426
+ migrationId,
427
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
428
+ checkpointId: checkpoint.checkpointId,
429
+ reason: 'Rollback failed'
430
+ });
431
+ }
432
+ } catch (rollbackError) {
433
+ console.error('Rollback failed:', rollbackError);
434
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
435
+ await this.emitEvent('migration:quarantine', {
436
+ migrationId,
437
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
438
+ checkpointId: checkpoint.checkpointId,
439
+ reason: rollbackError instanceof Error ? rollbackError.message : String(rollbackError)
440
+ });
441
+ }
442
+ }
443
+
444
+ // Create audit record
445
+ const duration = Date.now() - startTime;
446
+ const auditRecord = {
447
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
448
+ migrationId,
449
+ timestamp: startTime,
450
+ initiator: 'system',
451
+ sourceDid: options.sourceDid,
452
+ sourceLayer: this.extractLayer(options.sourceDid),
453
+ targetDid: null,
454
+ targetLayer: options.targetLayer,
455
+ finalState: rollbackSuccess ? MigrationStateEnum.ROLLED_BACK : MigrationStateEnum.FAILED,
456
+ validationResults: {
457
+ valid: false,
458
+ errors: [],
459
+ warnings: [],
460
+ estimatedCost: { storageCost: 0, networkFees: 0, totalCost: 0, estimatedDuration: 0, currency: 'sats' },
461
+ estimatedDuration: 0
462
+ },
463
+ costActual: { storageCost: 0, networkFees: 0, totalCost: 0, estimatedDuration: duration, currency: 'sats' },
464
+ duration,
465
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
466
+ checkpointId: checkpoint?.checkpointId || '',
467
+ errors: [migrationError],
468
+ metadata: options.metadata || {}
469
+ };
470
+
471
+ // TODO: AuditLogger temporarily disabled for v1.0 release
472
+ // Store in-memory for v1.0 (unsigned, will be replaced with signed records in v1.1)
473
+ this.storeAuditRecordInMemory(auditRecord);
474
+
475
+ return {
476
+ migrationId,
477
+ success: false,
478
+ sourceDid: options.sourceDid,
479
+ sourceLayer: this.extractLayer(options.sourceDid),
480
+ targetLayer: options.targetLayer,
481
+ state: rollbackSuccess ? MigrationStateEnum.ROLLED_BACK : MigrationStateEnum.FAILED,
482
+ duration,
483
+ cost: { storageCost: 0, networkFees: 0, totalCost: 0, currency: 'sats' },
484
+ auditRecord,
485
+ error: migrationError
486
+ };
487
+ }
488
+
489
+ /**
490
+ * Get appropriate migration operation handler
491
+ */
492
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
493
+ private getMigrationOperation(options: MigrationOptions): any {
494
+ const sourceLayer = this.extractLayer(options.sourceDid);
495
+
496
+ if (sourceLayer === 'peer' && options.targetLayer === 'webvh') {
497
+ return this.peerToWebvh;
498
+ }
499
+
500
+ if (sourceLayer === 'webvh' && options.targetLayer === 'btco') {
501
+ if (!this.webvhToBtco) {
502
+ throw new Error('Bitcoin manager required for btco migrations');
503
+ }
504
+ return this.webvhToBtco;
505
+ }
506
+
507
+ if (sourceLayer === 'peer' && options.targetLayer === 'btco') {
508
+ if (!this.peerToBtco) {
509
+ throw new Error('Bitcoin manager required for btco migrations');
510
+ }
511
+ return this.peerToBtco;
512
+ }
513
+
514
+ throw new Error(`Unsupported migration path: ${sourceLayer} → ${options.targetLayer}`);
515
+ }
516
+
517
+ /**
518
+ * Store audit record in memory for v1.0
519
+ * Stores by both source and target DID for easy lookup
520
+ * TODO: Remove in v1.1 when AuditLogger is re-enabled with signatures
521
+ */
522
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
523
+ private storeAuditRecordInMemory(record: any): void {
524
+ // Store by source DID
525
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
526
+ const sourceRecords = this.inMemoryAuditRecords.get(record.sourceDid) || [];
527
+ sourceRecords.push(record);
528
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
529
+ this.inMemoryAuditRecords.set(record.sourceDid, sourceRecords);
530
+
531
+ // Also store by target DID if available
532
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
533
+ if (record.targetDid) {
534
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
535
+ const targetRecords = this.inMemoryAuditRecords.get(record.targetDid) || [];
536
+ targetRecords.push(record);
537
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
538
+ this.inMemoryAuditRecords.set(record.targetDid, targetRecords);
539
+ }
540
+ }
541
+
542
+ /**
543
+ * Extract layer from DID
544
+ */
545
+ private extractLayer(did: string): 'peer' | 'webvh' | 'btco' {
546
+ if (did.startsWith('did:peer:')) return 'peer';
547
+ if (did.startsWith('did:webvh:')) return 'webvh';
548
+ if (did.startsWith('did:btco:')) return 'btco';
549
+ throw new Error(`Unsupported DID method: ${did}`);
550
+ }
551
+
552
+ /**
553
+ * Create migration error
554
+ */
555
+ private createMigrationError(
556
+ type: MigrationErrorType,
557
+ code: string,
558
+ message: string,
559
+ migrationId?: string,
560
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
561
+ details?: any
562
+ ): Error & { type: MigrationErrorType; code: string } {
563
+ const error = new Error(message) as any;
564
+ error.type = type;
565
+ error.code = code;
566
+ error.migrationId = migrationId;
567
+ error.details = details;
568
+ return error;
569
+ }
570
+
571
+ /**
572
+ * Emit event
573
+ */
574
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument
575
+ private async emitEvent(type: string, data: any): Promise<void> {
576
+ try {
577
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
578
+ await this.eventEmitter.emit({
579
+ type,
580
+ timestamp: new Date().toISOString(),
581
+ ...data
582
+ });
583
+ } catch (error) {
584
+ console.error(`Error emitting event ${type}:`, error);
585
+ }
586
+ }
587
+ }