@originals/sdk 1.1.0 → 1.4.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 (247) hide show
  1. package/package.json +3 -2
  2. package/src/did/DIDManager.ts +1 -1
  3. package/src/did/WebVHManager.ts +11 -2
  4. package/src/examples/create-module-original.ts +435 -0
  5. package/src/examples/full-lifecycle-flow.ts +514 -0
  6. package/src/examples/run.ts +59 -4
  7. package/src/index.ts +69 -3
  8. package/src/kinds/KindRegistry.ts +290 -0
  9. package/src/kinds/index.ts +74 -0
  10. package/src/kinds/types.ts +470 -0
  11. package/src/kinds/validators/AgentValidator.ts +257 -0
  12. package/src/kinds/validators/AppValidator.ts +211 -0
  13. package/src/kinds/validators/DatasetValidator.ts +242 -0
  14. package/src/kinds/validators/DocumentValidator.ts +311 -0
  15. package/src/kinds/validators/MediaValidator.ts +269 -0
  16. package/src/kinds/validators/ModuleValidator.ts +225 -0
  17. package/src/kinds/validators/base.ts +276 -0
  18. package/src/kinds/validators/index.ts +12 -0
  19. package/src/lifecycle/LifecycleManager.ts +909 -1
  20. package/src/resources/ResourceManager.ts +655 -0
  21. package/src/resources/index.ts +21 -0
  22. package/src/resources/types.ts +202 -0
  23. package/src/types/common.ts +1 -1
  24. package/src/vc/CredentialManager.ts +647 -2
  25. package/tests/integration/createTypedOriginal.test.ts +379 -0
  26. package/tests/performance/BatchOperations.perf.test.ts +2 -2
  27. package/tests/unit/kinds/KindRegistry.test.ts +329 -0
  28. package/tests/unit/kinds/types.test.ts +409 -0
  29. package/tests/unit/kinds/validators.test.ts +651 -0
  30. package/tests/unit/lifecycle/LifecycleManager.cleanapi.test.ts +441 -0
  31. package/tests/unit/resources/ResourceManager.test.ts +740 -0
  32. package/tests/unit/vc/CredentialManager.helpers.test.ts +527 -0
  33. package/tsconfig.json +0 -1
  34. package/.turbo/turbo-build.log +0 -1
  35. package/.turbo/turbo-test.log +0 -68353
  36. package/dist/adapters/FeeOracleMock.d.ts +0 -6
  37. package/dist/adapters/FeeOracleMock.js +0 -8
  38. package/dist/adapters/index.d.ts +0 -4
  39. package/dist/adapters/index.js +0 -4
  40. package/dist/adapters/providers/OrdHttpProvider.d.ts +0 -56
  41. package/dist/adapters/providers/OrdHttpProvider.js +0 -110
  42. package/dist/adapters/providers/OrdMockProvider.d.ts +0 -70
  43. package/dist/adapters/providers/OrdMockProvider.js +0 -75
  44. package/dist/adapters/types.d.ts +0 -71
  45. package/dist/adapters/types.js +0 -1
  46. package/dist/bitcoin/BitcoinManager.d.ts +0 -15
  47. package/dist/bitcoin/BitcoinManager.js +0 -262
  48. package/dist/bitcoin/BroadcastClient.d.ts +0 -30
  49. package/dist/bitcoin/BroadcastClient.js +0 -35
  50. package/dist/bitcoin/OrdinalsClient.d.ts +0 -21
  51. package/dist/bitcoin/OrdinalsClient.js +0 -105
  52. package/dist/bitcoin/PSBTBuilder.d.ts +0 -24
  53. package/dist/bitcoin/PSBTBuilder.js +0 -80
  54. package/dist/bitcoin/fee-calculation.d.ts +0 -14
  55. package/dist/bitcoin/fee-calculation.js +0 -31
  56. package/dist/bitcoin/providers/OrdNodeProvider.d.ts +0 -38
  57. package/dist/bitcoin/providers/OrdNodeProvider.js +0 -67
  58. package/dist/bitcoin/providers/OrdinalsProvider.d.ts +0 -33
  59. package/dist/bitcoin/providers/OrdinalsProvider.js +0 -50
  60. package/dist/bitcoin/providers/types.d.ts +0 -63
  61. package/dist/bitcoin/providers/types.js +0 -1
  62. package/dist/bitcoin/transactions/commit.d.ts +0 -89
  63. package/dist/bitcoin/transactions/commit.js +0 -311
  64. package/dist/bitcoin/transactions/index.d.ts +0 -7
  65. package/dist/bitcoin/transactions/index.js +0 -8
  66. package/dist/bitcoin/transfer.d.ts +0 -9
  67. package/dist/bitcoin/transfer.js +0 -26
  68. package/dist/bitcoin/utxo-selection.d.ts +0 -78
  69. package/dist/bitcoin/utxo-selection.js +0 -237
  70. package/dist/bitcoin/utxo.d.ts +0 -26
  71. package/dist/bitcoin/utxo.js +0 -78
  72. package/dist/contexts/credentials-v1.json +0 -195
  73. package/dist/contexts/credentials-v2-examples.json +0 -5
  74. package/dist/contexts/credentials-v2.json +0 -301
  75. package/dist/contexts/credentials.json +0 -195
  76. package/dist/contexts/data-integrity-v2.json +0 -81
  77. package/dist/contexts/dids.json +0 -57
  78. package/dist/contexts/ed255192020.json +0 -93
  79. package/dist/contexts/ordinals-plus.json +0 -23
  80. package/dist/contexts/originals.json +0 -22
  81. package/dist/core/OriginalsSDK.d.ts +0 -158
  82. package/dist/core/OriginalsSDK.js +0 -274
  83. package/dist/crypto/Multikey.d.ts +0 -30
  84. package/dist/crypto/Multikey.js +0 -149
  85. package/dist/crypto/Signer.d.ts +0 -21
  86. package/dist/crypto/Signer.js +0 -196
  87. package/dist/crypto/noble-init.d.ts +0 -18
  88. package/dist/crypto/noble-init.js +0 -106
  89. package/dist/did/BtcoDidResolver.d.ts +0 -57
  90. package/dist/did/BtcoDidResolver.js +0 -166
  91. package/dist/did/DIDManager.d.ts +0 -101
  92. package/dist/did/DIDManager.js +0 -493
  93. package/dist/did/Ed25519Verifier.d.ts +0 -30
  94. package/dist/did/Ed25519Verifier.js +0 -59
  95. package/dist/did/KeyManager.d.ts +0 -17
  96. package/dist/did/KeyManager.js +0 -207
  97. package/dist/did/WebVHManager.d.ts +0 -100
  98. package/dist/did/WebVHManager.js +0 -304
  99. package/dist/did/createBtcoDidDocument.d.ts +0 -10
  100. package/dist/did/createBtcoDidDocument.js +0 -42
  101. package/dist/did/providers/OrdinalsClientProviderAdapter.d.ts +0 -23
  102. package/dist/did/providers/OrdinalsClientProviderAdapter.js +0 -51
  103. package/dist/events/EventEmitter.d.ts +0 -115
  104. package/dist/events/EventEmitter.js +0 -198
  105. package/dist/events/index.d.ts +0 -7
  106. package/dist/events/index.js +0 -6
  107. package/dist/events/types.d.ts +0 -286
  108. package/dist/events/types.js +0 -9
  109. package/dist/examples/basic-usage.d.ts +0 -3
  110. package/dist/examples/basic-usage.js +0 -62
  111. package/dist/examples/run.d.ts +0 -1
  112. package/dist/examples/run.js +0 -4
  113. package/dist/index.d.ts +0 -39
  114. package/dist/index.js +0 -47
  115. package/dist/lifecycle/BatchOperations.d.ts +0 -147
  116. package/dist/lifecycle/BatchOperations.js +0 -251
  117. package/dist/lifecycle/LifecycleManager.d.ts +0 -116
  118. package/dist/lifecycle/LifecycleManager.js +0 -971
  119. package/dist/lifecycle/OriginalsAsset.d.ts +0 -164
  120. package/dist/lifecycle/OriginalsAsset.js +0 -380
  121. package/dist/lifecycle/ProvenanceQuery.d.ts +0 -126
  122. package/dist/lifecycle/ProvenanceQuery.js +0 -220
  123. package/dist/lifecycle/ResourceVersioning.d.ts +0 -73
  124. package/dist/lifecycle/ResourceVersioning.js +0 -127
  125. package/dist/migration/MigrationManager.d.ts +0 -86
  126. package/dist/migration/MigrationManager.js +0 -412
  127. package/dist/migration/audit/AuditLogger.d.ts +0 -51
  128. package/dist/migration/audit/AuditLogger.js +0 -156
  129. package/dist/migration/checkpoint/CheckpointManager.d.ts +0 -31
  130. package/dist/migration/checkpoint/CheckpointManager.js +0 -96
  131. package/dist/migration/checkpoint/CheckpointStorage.d.ts +0 -26
  132. package/dist/migration/checkpoint/CheckpointStorage.js +0 -89
  133. package/dist/migration/index.d.ts +0 -22
  134. package/dist/migration/index.js +0 -27
  135. package/dist/migration/operations/BaseMigration.d.ts +0 -48
  136. package/dist/migration/operations/BaseMigration.js +0 -83
  137. package/dist/migration/operations/PeerToBtcoMigration.d.ts +0 -25
  138. package/dist/migration/operations/PeerToBtcoMigration.js +0 -67
  139. package/dist/migration/operations/PeerToWebvhMigration.d.ts +0 -19
  140. package/dist/migration/operations/PeerToWebvhMigration.js +0 -46
  141. package/dist/migration/operations/WebvhToBtcoMigration.d.ts +0 -25
  142. package/dist/migration/operations/WebvhToBtcoMigration.js +0 -67
  143. package/dist/migration/rollback/RollbackManager.d.ts +0 -29
  144. package/dist/migration/rollback/RollbackManager.js +0 -146
  145. package/dist/migration/state/StateMachine.d.ts +0 -25
  146. package/dist/migration/state/StateMachine.js +0 -76
  147. package/dist/migration/state/StateTracker.d.ts +0 -36
  148. package/dist/migration/state/StateTracker.js +0 -123
  149. package/dist/migration/types.d.ts +0 -306
  150. package/dist/migration/types.js +0 -33
  151. package/dist/migration/validation/BitcoinValidator.d.ts +0 -13
  152. package/dist/migration/validation/BitcoinValidator.js +0 -83
  153. package/dist/migration/validation/CredentialValidator.d.ts +0 -13
  154. package/dist/migration/validation/CredentialValidator.js +0 -46
  155. package/dist/migration/validation/DIDCompatibilityValidator.d.ts +0 -16
  156. package/dist/migration/validation/DIDCompatibilityValidator.js +0 -127
  157. package/dist/migration/validation/LifecycleValidator.d.ts +0 -10
  158. package/dist/migration/validation/LifecycleValidator.js +0 -52
  159. package/dist/migration/validation/StorageValidator.d.ts +0 -10
  160. package/dist/migration/validation/StorageValidator.js +0 -65
  161. package/dist/migration/validation/ValidationPipeline.d.ts +0 -29
  162. package/dist/migration/validation/ValidationPipeline.js +0 -180
  163. package/dist/storage/LocalStorageAdapter.d.ts +0 -11
  164. package/dist/storage/LocalStorageAdapter.js +0 -53
  165. package/dist/storage/MemoryStorageAdapter.d.ts +0 -6
  166. package/dist/storage/MemoryStorageAdapter.js +0 -21
  167. package/dist/storage/StorageAdapter.d.ts +0 -16
  168. package/dist/storage/StorageAdapter.js +0 -1
  169. package/dist/storage/index.d.ts +0 -2
  170. package/dist/storage/index.js +0 -2
  171. package/dist/types/bitcoin.d.ts +0 -84
  172. package/dist/types/bitcoin.js +0 -1
  173. package/dist/types/common.d.ts +0 -82
  174. package/dist/types/common.js +0 -1
  175. package/dist/types/credentials.d.ts +0 -75
  176. package/dist/types/credentials.js +0 -1
  177. package/dist/types/did.d.ts +0 -26
  178. package/dist/types/did.js +0 -1
  179. package/dist/types/index.d.ts +0 -5
  180. package/dist/types/index.js +0 -5
  181. package/dist/types/network.d.ts +0 -78
  182. package/dist/types/network.js +0 -145
  183. package/dist/utils/EventLogger.d.ts +0 -71
  184. package/dist/utils/EventLogger.js +0 -232
  185. package/dist/utils/Logger.d.ts +0 -106
  186. package/dist/utils/Logger.js +0 -257
  187. package/dist/utils/MetricsCollector.d.ts +0 -110
  188. package/dist/utils/MetricsCollector.js +0 -264
  189. package/dist/utils/bitcoin-address.d.ts +0 -38
  190. package/dist/utils/bitcoin-address.js +0 -113
  191. package/dist/utils/cbor.d.ts +0 -2
  192. package/dist/utils/cbor.js +0 -9
  193. package/dist/utils/encoding.d.ts +0 -37
  194. package/dist/utils/encoding.js +0 -120
  195. package/dist/utils/hash.d.ts +0 -1
  196. package/dist/utils/hash.js +0 -5
  197. package/dist/utils/retry.d.ts +0 -10
  198. package/dist/utils/retry.js +0 -35
  199. package/dist/utils/satoshi-validation.d.ts +0 -60
  200. package/dist/utils/satoshi-validation.js +0 -156
  201. package/dist/utils/serialization.d.ts +0 -14
  202. package/dist/utils/serialization.js +0 -76
  203. package/dist/utils/telemetry.d.ts +0 -17
  204. package/dist/utils/telemetry.js +0 -24
  205. package/dist/utils/validation.d.ts +0 -5
  206. package/dist/utils/validation.js +0 -98
  207. package/dist/vc/CredentialManager.d.ts +0 -22
  208. package/dist/vc/CredentialManager.js +0 -227
  209. package/dist/vc/Issuer.d.ts +0 -27
  210. package/dist/vc/Issuer.js +0 -70
  211. package/dist/vc/Verifier.d.ts +0 -16
  212. package/dist/vc/Verifier.js +0 -50
  213. package/dist/vc/cryptosuites/bbs.d.ts +0 -44
  214. package/dist/vc/cryptosuites/bbs.js +0 -213
  215. package/dist/vc/cryptosuites/bbsSimple.d.ts +0 -9
  216. package/dist/vc/cryptosuites/bbsSimple.js +0 -12
  217. package/dist/vc/cryptosuites/eddsa.d.ts +0 -30
  218. package/dist/vc/cryptosuites/eddsa.js +0 -81
  219. package/dist/vc/documentLoader.d.ts +0 -16
  220. package/dist/vc/documentLoader.js +0 -59
  221. package/dist/vc/proofs/data-integrity.d.ts +0 -21
  222. package/dist/vc/proofs/data-integrity.js +0 -15
  223. package/dist/vc/utils/jsonld.d.ts +0 -2
  224. package/dist/vc/utils/jsonld.js +0 -15
  225. package/test/logs/did_webvh_QmQsRNhXxPSCSeLjpbKYcNMZj8b1kBQAoC6cZmkFAgmpHt_example_com.jsonl +0 -1
  226. package/test/logs/did_webvh_QmSQkpD58qxcqMWHYcEmDUn3wk7hHvJwzYTrZmhh6zjPQ8_example_com_users_alice123_profile.jsonl +0 -1
  227. package/test/logs/did_webvh_QmTMda6VW3cUPdKk5Yc3onnv1vdgEumvWWdP2noAYFSjeG_example_com.jsonl +0 -1
  228. package/test/logs/did_webvh_QmTkb8KnCYcsnKKDCY4eUQuKQdKJLrCinvhw13v3zETxpE_example_com_users_etc_passwd.jsonl +0 -1
  229. package/test/logs/did_webvh_QmTn9FdCfpXFDrxHH52pwB4iNrDFVvNDjJ5FQTcDbmM3Fg_example_com.jsonl +0 -1
  230. package/test/logs/did_webvh_QmUCQUi1xjtJjnSQ1XJZgKqcWgErx1v7E2dz4DAPraAyJP_example_com_etc_passwd.jsonl +0 -1
  231. package/test/logs/did_webvh_QmUENQJCDKBJVRS5BkL6zjaUvcRjkb9xHmy7foCgRjmv3W_example_com.jsonl +0 -1
  232. package/test/logs/did_webvh_QmUPdGyjYBEnQ3aQUkmqyyBKTyjvCP5RZQGiaEDeTtf6dc_example_com.jsonl +0 -1
  233. package/test/logs/did_webvh_QmUoHTuHMWzQM29ZFrE9VLtMxkZ5u869yqee8LwcCLN39M_example_com.jsonl +0 -1
  234. package/test/logs/did_webvh_QmUrnms8G65ggVKsr9oQeWrLUBuGChwQPPb2LCFvaoNxaw_example_com_users_alice.jsonl +0 -1
  235. package/test/logs/did_webvh_QmUwiw3eSXdHG1hPvoAGu3cuK5jF4aXRYDLBAjPXfv1qzb_example_com_level1_level2.jsonl +0 -1
  236. package/test/logs/did_webvh_QmW7bzKh6yFEKNAtmVsrPGvvsMHTUQdzJSNsTZkbuGFpbj_example_com_secret.jsonl +0 -1
  237. package/test/logs/did_webvh_QmXbFTFBBJ8zpjdz9WE1DNN44A2wprFmdvAubjSffeyoAG_example_com.jsonl +0 -1
  238. package/test/logs/did_webvh_QmXyVXFPCTffGb2mTUFDeMCsScjnpLWkyUkVkB6q6QoeBf_example_com_C_Windows_System32.jsonl +0 -1
  239. package/test/logs/did_webvh_QmZK9B81gxZtvo5fYHYKDtKt8zZfZZPhmCMhbujBJuRRzE_example_com_etc_passwd.jsonl +0 -1
  240. package/test/logs/did_webvh_QmbNLCVSdXSVLrwFBvCBQPAabjtRb1SGHjkGVyw3QUbfBL_example_com_users_etc_passwd.jsonl +0 -1
  241. package/test/logs/did_webvh_QmbeaicmGW3Q7Yzbqmftc8a9jLBngokveb5A2KVKfVGZRb_example_com_my_org_user_name_test_123.jsonl +0 -1
  242. package/test/logs/did_webvh_Qmdv7c7AjUreUfoKyvkN2UpAWTozxKsv99srQetPJMJEnp_example_com_users_etc_passwd.jsonl +0 -1
  243. package/test/logs/did_webvh_QmeioWY3uypYLkYpCXe9eCYnn4xBVruP9C1d79azMrTEHG_example_com.jsonl +0 -1
  244. package/test/logs/did_webvh_Qmf4QH5dsA6Ecr5HJ6KaJL9uJRyY8RxrQdqoRCM25DzvPi_example_com_users_alice.jsonl +0 -1
  245. package/tests/e2e/README.md +0 -97
  246. package/tests/e2e/example.spec.ts +0 -78
  247. package/tsconfig.tsbuildinfo +0 -1
@@ -0,0 +1,441 @@
1
+ import { describe, test, expect } from 'bun:test';
2
+ import { OriginalsSDK, LifecycleManager, type LifecycleProgress, type CostEstimate, type MigrationValidation } from '../../../src';
3
+ import { MockOrdinalsProvider } from '../../mocks/adapters';
4
+ import { DIDManager } from '../../../src/did/DIDManager';
5
+ import { CredentialManager } from '../../../src/vc/CredentialManager';
6
+
7
+ const resources = [
8
+ {
9
+ id: 'res1',
10
+ type: 'text',
11
+ content: 'hello world',
12
+ contentType: 'text/plain',
13
+ hash: 'deadbeef'
14
+ }
15
+ ];
16
+
17
+ describe('LifecycleManager - Clean API', () => {
18
+ describe('createDraft', () => {
19
+ test('creates a peer-layer asset', async () => {
20
+ const sdk = OriginalsSDK.create({ network: 'regtest' });
21
+ const asset = await sdk.lifecycle.createDraft(resources);
22
+ expect(asset.currentLayer).toBe('did:peer');
23
+ expect(asset.id.startsWith('did:peer:')).toBe(true);
24
+ });
25
+
26
+ test('reports progress during creation', async () => {
27
+ const sdk = OriginalsSDK.create({ network: 'regtest' });
28
+ const progressEvents: LifecycleProgress[] = [];
29
+
30
+ const asset = await sdk.lifecycle.createDraft(resources, {
31
+ onProgress: (p) => progressEvents.push({ ...p })
32
+ });
33
+
34
+ expect(asset.currentLayer).toBe('did:peer');
35
+ expect(progressEvents.length).toBeGreaterThan(0);
36
+ expect(progressEvents[0].phase).toBe('preparing');
37
+ expect(progressEvents[progressEvents.length - 1].phase).toBe('complete');
38
+ expect(progressEvents[progressEvents.length - 1].percentage).toBe(100);
39
+ });
40
+
41
+ test('reports failure progress on error', async () => {
42
+ const sdk = OriginalsSDK.create({ network: 'regtest' });
43
+ const progressEvents: LifecycleProgress[] = [];
44
+
45
+ // Pass invalid resources to trigger error
46
+ await expect(
47
+ sdk.lifecycle.createDraft([], {
48
+ onProgress: (p) => progressEvents.push({ ...p })
49
+ })
50
+ ).rejects.toThrow();
51
+
52
+ // Should have a failed progress event
53
+ const failedEvent = progressEvents.find(p => p.phase === 'failed');
54
+ expect(failedEvent).toBeDefined();
55
+ });
56
+ });
57
+
58
+ describe('publish', () => {
59
+ test('migrates asset to webvh layer', async () => {
60
+ const sdk = OriginalsSDK.create({ network: 'regtest' });
61
+ const draft = await sdk.lifecycle.createDraft(resources);
62
+ const published = await sdk.lifecycle.publish(draft, 'example.com');
63
+
64
+ expect(published.currentLayer).toBe('did:webvh');
65
+ expect(published.bindings?.['did:webvh']).toContain('example.com');
66
+ });
67
+
68
+ test('reports progress during publish', async () => {
69
+ const sdk = OriginalsSDK.create({ network: 'regtest' });
70
+ const draft = await sdk.lifecycle.createDraft(resources);
71
+ const progressEvents: LifecycleProgress[] = [];
72
+
73
+ await sdk.lifecycle.publish(draft, 'example.com', {
74
+ onProgress: (p) => progressEvents.push({ ...p })
75
+ });
76
+
77
+ expect(progressEvents.length).toBeGreaterThan(0);
78
+ expect(progressEvents[progressEvents.length - 1].phase).toBe('complete');
79
+ });
80
+
81
+ test('validates before publishing', async () => {
82
+ const sdk = OriginalsSDK.create({ network: 'regtest' });
83
+ const draft = await sdk.lifecycle.createDraft(resources);
84
+
85
+ // Migrate to webvh first (can't publish from webvh)
86
+ await sdk.lifecycle.publish(draft, 'example.com');
87
+
88
+ // Try to publish again - should fail validation
89
+ await expect(
90
+ sdk.lifecycle.publish(draft, 'other.com')
91
+ ).rejects.toThrow(/validation failed/i);
92
+ });
93
+ });
94
+
95
+ describe('inscribe', () => {
96
+ test('inscribes asset on Bitcoin', async () => {
97
+ const provider = new MockOrdinalsProvider();
98
+ const sdk = OriginalsSDK.create({
99
+ network: 'regtest',
100
+ ordinalsProvider: provider
101
+ } as any);
102
+
103
+ const draft = await sdk.lifecycle.createDraft(resources);
104
+ await sdk.lifecycle.publish(draft, 'example.com');
105
+ const inscribed = await sdk.lifecycle.inscribe(draft, { feeRate: 10 });
106
+
107
+ expect(inscribed.currentLayer).toBe('did:btco');
108
+ });
109
+
110
+ test('reports progress during inscription', async () => {
111
+ const provider = new MockOrdinalsProvider();
112
+ const sdk = OriginalsSDK.create({
113
+ network: 'regtest',
114
+ ordinalsProvider: provider
115
+ } as any);
116
+
117
+ const draft = await sdk.lifecycle.createDraft(resources);
118
+ await sdk.lifecycle.publish(draft, 'example.com');
119
+ const progressEvents: LifecycleProgress[] = [];
120
+
121
+ await sdk.lifecycle.inscribe(draft, {
122
+ feeRate: 10,
123
+ onProgress: (p) => progressEvents.push({ ...p })
124
+ });
125
+
126
+ expect(progressEvents.length).toBeGreaterThan(0);
127
+ // Should include cost estimate in messages
128
+ const preparingEvent = progressEvents.find(p =>
129
+ p.phase === 'preparing' && p.message.includes('sats')
130
+ );
131
+ expect(preparingEvent).toBeDefined();
132
+ });
133
+
134
+ test('fails validation without ordinals provider', async () => {
135
+ const sdk = OriginalsSDK.create({ network: 'regtest' });
136
+ const draft = await sdk.lifecycle.createDraft(resources);
137
+ await sdk.lifecycle.publish(draft, 'example.com');
138
+
139
+ await expect(
140
+ sdk.lifecycle.inscribe(draft)
141
+ ).rejects.toThrow(/ordinalsProvider/i);
142
+ });
143
+ });
144
+
145
+ describe('transfer', () => {
146
+ test('transfers inscribed asset', async () => {
147
+ const provider = new MockOrdinalsProvider();
148
+ const sdk = OriginalsSDK.create({
149
+ network: 'regtest',
150
+ ordinalsProvider: provider
151
+ } as any);
152
+
153
+ const draft = await sdk.lifecycle.createDraft(resources);
154
+ await sdk.lifecycle.publish(draft, 'example.com');
155
+ await sdk.lifecycle.inscribe(draft, { feeRate: 10 });
156
+
157
+ const tx = await sdk.lifecycle.transfer(
158
+ draft,
159
+ 'tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx'
160
+ );
161
+
162
+ expect(tx.txid).toBeDefined();
163
+ });
164
+
165
+ test('reports progress during transfer', async () => {
166
+ const provider = new MockOrdinalsProvider();
167
+ const sdk = OriginalsSDK.create({
168
+ network: 'regtest',
169
+ ordinalsProvider: provider
170
+ } as any);
171
+
172
+ const draft = await sdk.lifecycle.createDraft(resources);
173
+ await sdk.lifecycle.publish(draft, 'example.com');
174
+ await sdk.lifecycle.inscribe(draft, { feeRate: 10 });
175
+
176
+ const progressEvents: LifecycleProgress[] = [];
177
+
178
+ await sdk.lifecycle.transfer(
179
+ draft,
180
+ 'tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx',
181
+ { onProgress: (p) => progressEvents.push({ ...p }) }
182
+ );
183
+
184
+ expect(progressEvents.length).toBeGreaterThan(0);
185
+ expect(progressEvents[progressEvents.length - 1].details?.transactionId).toBeDefined();
186
+ });
187
+
188
+ test('fails if asset not inscribed', async () => {
189
+ const sdk = OriginalsSDK.create({ network: 'regtest' });
190
+ const draft = await sdk.lifecycle.createDraft(resources);
191
+
192
+ await expect(
193
+ sdk.lifecycle.transfer(draft, 'tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx')
194
+ ).rejects.toThrow(/must be inscribed/i);
195
+ });
196
+ });
197
+ });
198
+
199
+ describe('LifecycleManager - Cost Estimation', () => {
200
+ describe('estimateCost', () => {
201
+ test('returns zero cost for webvh migration', async () => {
202
+ const sdk = OriginalsSDK.create({ network: 'regtest' });
203
+ const draft = await sdk.lifecycle.createDraft(resources);
204
+
205
+ const cost = await sdk.lifecycle.estimateCost(draft, 'did:webvh');
206
+
207
+ expect(cost.totalSats).toBe(0);
208
+ expect(cost.targetLayer).toBe('did:webvh');
209
+ expect(cost.confidence).toBe('high');
210
+ });
211
+
212
+ test('estimates btco inscription cost', async () => {
213
+ const sdk = OriginalsSDK.create({ network: 'regtest' });
214
+ const draft = await sdk.lifecycle.createDraft(resources);
215
+
216
+ const cost = await sdk.lifecycle.estimateCost(draft, 'did:btco', 10);
217
+
218
+ expect(cost.totalSats).toBeGreaterThan(0);
219
+ expect(cost.feeRate).toBe(10);
220
+ expect(cost.targetLayer).toBe('did:btco');
221
+ expect(cost.breakdown.networkFee).toBeGreaterThan(0);
222
+ expect(cost.breakdown.dustValue).toBe(546);
223
+ expect(cost.dataSize).toBeGreaterThan(0);
224
+ });
225
+
226
+ test('uses fee oracle when available', async () => {
227
+ const mockFeeOracle = {
228
+ estimateFeeRate: async (blocks: number) => 15
229
+ };
230
+ const sdk = OriginalsSDK.create({
231
+ network: 'regtest',
232
+ feeOracle: mockFeeOracle as any
233
+ });
234
+ const draft = await sdk.lifecycle.createDraft(resources);
235
+
236
+ const cost = await sdk.lifecycle.estimateCost(draft, 'did:btco');
237
+
238
+ expect(cost.feeRate).toBe(15);
239
+ expect(cost.confidence).toBe('high');
240
+ });
241
+
242
+ test('uses ordinals provider when fee oracle unavailable', async () => {
243
+ const provider = new MockOrdinalsProvider();
244
+ const sdk = OriginalsSDK.create({
245
+ network: 'regtest',
246
+ ordinalsProvider: provider
247
+ } as any);
248
+ const draft = await sdk.lifecycle.createDraft(resources);
249
+
250
+ const cost = await sdk.lifecycle.estimateCost(draft, 'did:btco');
251
+
252
+ expect(cost.feeRate).toBeGreaterThan(0);
253
+ expect(cost.confidence).toBe('medium');
254
+ });
255
+
256
+ test('falls back to default fee rate', async () => {
257
+ const sdk = OriginalsSDK.create({ network: 'regtest' });
258
+ const draft = await sdk.lifecycle.createDraft(resources);
259
+
260
+ const cost = await sdk.lifecycle.estimateCost(draft, 'did:btco');
261
+
262
+ expect(cost.feeRate).toBe(10); // Default
263
+ expect(cost.confidence).toBe('low');
264
+ });
265
+
266
+ test('returns zero for peer layer (no migration needed)', async () => {
267
+ const sdk = OriginalsSDK.create({ network: 'regtest' });
268
+ const draft = await sdk.lifecycle.createDraft(resources);
269
+
270
+ const cost = await sdk.lifecycle.estimateCost(draft, 'did:peer');
271
+
272
+ expect(cost.totalSats).toBe(0);
273
+ expect(cost.confidence).toBe('high');
274
+ });
275
+ });
276
+ });
277
+
278
+ describe('LifecycleManager - Migration Validation', () => {
279
+ describe('validateMigration', () => {
280
+ test('validates peer to webvh migration', async () => {
281
+ const sdk = OriginalsSDK.create({ network: 'regtest' });
282
+ const draft = await sdk.lifecycle.createDraft(resources);
283
+
284
+ const validation = await sdk.lifecycle.validateMigration(draft, 'did:webvh');
285
+
286
+ expect(validation.valid).toBe(true);
287
+ expect(validation.errors).toHaveLength(0);
288
+ expect(validation.currentLayer).toBe('did:peer');
289
+ expect(validation.targetLayer).toBe('did:webvh');
290
+ expect(validation.checks.layerTransition).toBe(true);
291
+ expect(validation.checks.resourcesValid).toBe(true);
292
+ expect(validation.checks.didDocumentValid).toBe(true);
293
+ });
294
+
295
+ test('validates peer to btco migration with provider', async () => {
296
+ const provider = new MockOrdinalsProvider();
297
+ const sdk = OriginalsSDK.create({
298
+ network: 'regtest',
299
+ ordinalsProvider: provider
300
+ } as any);
301
+ const draft = await sdk.lifecycle.createDraft(resources);
302
+
303
+ const validation = await sdk.lifecycle.validateMigration(draft, 'did:btco');
304
+
305
+ expect(validation.valid).toBe(true);
306
+ expect(validation.checks.bitcoinReadiness).toBe(true);
307
+ });
308
+
309
+ test('fails validation for btco without provider', async () => {
310
+ const sdk = OriginalsSDK.create({ network: 'regtest' });
311
+ const draft = await sdk.lifecycle.createDraft(resources);
312
+
313
+ const validation = await sdk.lifecycle.validateMigration(draft, 'did:btco');
314
+
315
+ expect(validation.valid).toBe(false);
316
+ expect(validation.errors).toContain('Bitcoin inscription requires an ordinalsProvider to be configured');
317
+ expect(validation.checks.bitcoinReadiness).toBe(false);
318
+ });
319
+
320
+ test('rejects invalid layer transition (btco to webvh)', async () => {
321
+ const provider = new MockOrdinalsProvider();
322
+ const sdk = OriginalsSDK.create({
323
+ network: 'regtest',
324
+ ordinalsProvider: provider
325
+ } as any);
326
+
327
+ const draft = await sdk.lifecycle.createDraft(resources);
328
+ await sdk.lifecycle.publish(draft, 'example.com');
329
+ await sdk.lifecycle.inscribe(draft, { feeRate: 10 });
330
+
331
+ const validation = await sdk.lifecycle.validateMigration(draft, 'did:webvh');
332
+
333
+ expect(validation.valid).toBe(false);
334
+ expect(validation.errors.some(e => e.includes('Invalid migration'))).toBe(true);
335
+ expect(validation.checks.layerTransition).toBe(false);
336
+ });
337
+
338
+ test('rejects asset with no resources', async () => {
339
+ const config: any = { network: 'regtest', defaultKeyType: 'Ed25519' };
340
+ const didManager = new DIDManager(config);
341
+ const credentialManager = new CredentialManager(config);
342
+ const lm = new LifecycleManager(config, didManager, credentialManager);
343
+
344
+ // Create a fake asset with no resources
345
+ const fakeAsset = {
346
+ currentLayer: 'did:peer' as const,
347
+ resources: [],
348
+ did: { id: 'did:peer:test' },
349
+ credentials: []
350
+ };
351
+
352
+ const validation = await lm.validateMigration(fakeAsset as any, 'did:webvh');
353
+
354
+ expect(validation.valid).toBe(false);
355
+ expect(validation.errors.some(e => e.includes('at least one resource'))).toBe(true);
356
+ });
357
+
358
+ test('rejects asset with invalid resource hash', async () => {
359
+ const config: any = { network: 'regtest', defaultKeyType: 'Ed25519' };
360
+ const didManager = new DIDManager(config);
361
+ const credentialManager = new CredentialManager(config);
362
+ const lm = new LifecycleManager(config, didManager, credentialManager);
363
+
364
+ const fakeAsset = {
365
+ currentLayer: 'did:peer' as const,
366
+ resources: [{ id: 'r1', type: 'text', contentType: 'text/plain', hash: 'not-hex!' }],
367
+ did: { id: 'did:peer:test' },
368
+ credentials: []
369
+ };
370
+
371
+ const validation = await lm.validateMigration(fakeAsset as any, 'did:webvh');
372
+
373
+ expect(validation.valid).toBe(false);
374
+ expect(validation.errors.some(e => e.includes('invalid hash'))).toBe(true);
375
+ });
376
+
377
+ test('warns about large manifest sizes', async () => {
378
+ const provider = new MockOrdinalsProvider();
379
+ const sdk = OriginalsSDK.create({
380
+ network: 'regtest',
381
+ ordinalsProvider: provider
382
+ } as any);
383
+
384
+ // Create asset with many resources to increase manifest size
385
+ // Need 1000+ resources to exceed 100KB threshold (each resource adds ~100 bytes)
386
+ const manyResources = Array.from({ length: 1200 }, (_, i) => ({
387
+ id: `resource-${i}-with-longer-name`,
388
+ type: 'text',
389
+ content: 'x'.repeat(200),
390
+ contentType: 'text/plain',
391
+ hash: 'a'.repeat(64)
392
+ }));
393
+
394
+ const draft = await sdk.lifecycle.createDraft(manyResources);
395
+ const validation = await sdk.lifecycle.validateMigration(draft, 'did:btco');
396
+
397
+ expect(validation.warnings.some(w => w.includes('Large manifest'))).toBe(true);
398
+ });
399
+
400
+ test('validates credentials structure', async () => {
401
+ const config: any = { network: 'regtest', defaultKeyType: 'Ed25519' };
402
+ const didManager = new DIDManager(config);
403
+ const credentialManager = new CredentialManager(config);
404
+ const lm = new LifecycleManager(config, didManager, credentialManager);
405
+
406
+ const fakeAsset = {
407
+ currentLayer: 'did:peer' as const,
408
+ resources: [{ id: 'r1', type: 'text', contentType: 'text/plain', hash: 'deadbeef' }],
409
+ did: { id: 'did:peer:test' },
410
+ credentials: [
411
+ { type: ['VerifiableCredential'], issuer: 'did:test:issuer', issuanceDate: '2024-01-01' }
412
+ ]
413
+ };
414
+
415
+ const validation = await lm.validateMigration(fakeAsset as any, 'did:webvh');
416
+
417
+ expect(validation.checks.credentialsValid).toBe(true);
418
+ });
419
+
420
+ test('warns about credentials with missing fields', async () => {
421
+ const config: any = { network: 'regtest', defaultKeyType: 'Ed25519' };
422
+ const didManager = new DIDManager(config);
423
+ const credentialManager = new CredentialManager(config);
424
+ const lm = new LifecycleManager(config, didManager, credentialManager);
425
+
426
+ const fakeAsset = {
427
+ currentLayer: 'did:peer' as const,
428
+ resources: [{ id: 'r1', type: 'text', contentType: 'text/plain', hash: 'deadbeef' }],
429
+ did: { id: 'did:peer:test' },
430
+ credentials: [
431
+ { type: ['VerifiableCredential'] } // Missing issuer and issuanceDate
432
+ ]
433
+ };
434
+
435
+ const validation = await lm.validateMigration(fakeAsset as any, 'did:webvh');
436
+
437
+ expect(validation.warnings.some(w => w.includes('missing fields'))).toBe(true);
438
+ });
439
+ });
440
+ });
441
+