@originals/sdk 1.2.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 (244) hide show
  1. package/package.json +1 -1
  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/.turbo/turbo-build.log +0 -1
  34. package/dist/adapters/FeeOracleMock.d.ts +0 -6
  35. package/dist/adapters/FeeOracleMock.js +0 -8
  36. package/dist/adapters/index.d.ts +0 -4
  37. package/dist/adapters/index.js +0 -4
  38. package/dist/adapters/providers/OrdHttpProvider.d.ts +0 -56
  39. package/dist/adapters/providers/OrdHttpProvider.js +0 -110
  40. package/dist/adapters/providers/OrdMockProvider.d.ts +0 -70
  41. package/dist/adapters/providers/OrdMockProvider.js +0 -75
  42. package/dist/adapters/types.d.ts +0 -71
  43. package/dist/adapters/types.js +0 -1
  44. package/dist/bitcoin/BitcoinManager.d.ts +0 -15
  45. package/dist/bitcoin/BitcoinManager.js +0 -262
  46. package/dist/bitcoin/BroadcastClient.d.ts +0 -30
  47. package/dist/bitcoin/BroadcastClient.js +0 -35
  48. package/dist/bitcoin/OrdinalsClient.d.ts +0 -21
  49. package/dist/bitcoin/OrdinalsClient.js +0 -105
  50. package/dist/bitcoin/PSBTBuilder.d.ts +0 -24
  51. package/dist/bitcoin/PSBTBuilder.js +0 -80
  52. package/dist/bitcoin/fee-calculation.d.ts +0 -14
  53. package/dist/bitcoin/fee-calculation.js +0 -31
  54. package/dist/bitcoin/providers/OrdNodeProvider.d.ts +0 -38
  55. package/dist/bitcoin/providers/OrdNodeProvider.js +0 -67
  56. package/dist/bitcoin/providers/OrdinalsProvider.d.ts +0 -33
  57. package/dist/bitcoin/providers/OrdinalsProvider.js +0 -50
  58. package/dist/bitcoin/providers/types.d.ts +0 -63
  59. package/dist/bitcoin/providers/types.js +0 -1
  60. package/dist/bitcoin/transactions/commit.d.ts +0 -89
  61. package/dist/bitcoin/transactions/commit.js +0 -311
  62. package/dist/bitcoin/transactions/index.d.ts +0 -7
  63. package/dist/bitcoin/transactions/index.js +0 -8
  64. package/dist/bitcoin/transfer.d.ts +0 -9
  65. package/dist/bitcoin/transfer.js +0 -26
  66. package/dist/bitcoin/utxo-selection.d.ts +0 -78
  67. package/dist/bitcoin/utxo-selection.js +0 -237
  68. package/dist/bitcoin/utxo.d.ts +0 -26
  69. package/dist/bitcoin/utxo.js +0 -78
  70. package/dist/contexts/credentials-v1.json +0 -195
  71. package/dist/contexts/credentials-v2-examples.json +0 -5
  72. package/dist/contexts/credentials-v2.json +0 -301
  73. package/dist/contexts/credentials.json +0 -195
  74. package/dist/contexts/data-integrity-v2.json +0 -81
  75. package/dist/contexts/dids.json +0 -57
  76. package/dist/contexts/ed255192020.json +0 -93
  77. package/dist/contexts/ordinals-plus.json +0 -23
  78. package/dist/contexts/originals.json +0 -22
  79. package/dist/core/OriginalsSDK.d.ts +0 -158
  80. package/dist/core/OriginalsSDK.js +0 -274
  81. package/dist/crypto/Multikey.d.ts +0 -30
  82. package/dist/crypto/Multikey.js +0 -149
  83. package/dist/crypto/Signer.d.ts +0 -21
  84. package/dist/crypto/Signer.js +0 -196
  85. package/dist/crypto/noble-init.d.ts +0 -18
  86. package/dist/crypto/noble-init.js +0 -106
  87. package/dist/did/BtcoDidResolver.d.ts +0 -57
  88. package/dist/did/BtcoDidResolver.js +0 -166
  89. package/dist/did/DIDManager.d.ts +0 -101
  90. package/dist/did/DIDManager.js +0 -493
  91. package/dist/did/Ed25519Verifier.d.ts +0 -30
  92. package/dist/did/Ed25519Verifier.js +0 -59
  93. package/dist/did/KeyManager.d.ts +0 -17
  94. package/dist/did/KeyManager.js +0 -207
  95. package/dist/did/WebVHManager.d.ts +0 -100
  96. package/dist/did/WebVHManager.js +0 -304
  97. package/dist/did/createBtcoDidDocument.d.ts +0 -10
  98. package/dist/did/createBtcoDidDocument.js +0 -42
  99. package/dist/did/providers/OrdinalsClientProviderAdapter.d.ts +0 -23
  100. package/dist/did/providers/OrdinalsClientProviderAdapter.js +0 -51
  101. package/dist/events/EventEmitter.d.ts +0 -115
  102. package/dist/events/EventEmitter.js +0 -198
  103. package/dist/events/index.d.ts +0 -7
  104. package/dist/events/index.js +0 -6
  105. package/dist/events/types.d.ts +0 -286
  106. package/dist/events/types.js +0 -9
  107. package/dist/examples/basic-usage.d.ts +0 -3
  108. package/dist/examples/basic-usage.js +0 -62
  109. package/dist/examples/run.d.ts +0 -1
  110. package/dist/examples/run.js +0 -4
  111. package/dist/index.d.ts +0 -39
  112. package/dist/index.js +0 -47
  113. package/dist/lifecycle/BatchOperations.d.ts +0 -147
  114. package/dist/lifecycle/BatchOperations.js +0 -251
  115. package/dist/lifecycle/LifecycleManager.d.ts +0 -116
  116. package/dist/lifecycle/LifecycleManager.js +0 -971
  117. package/dist/lifecycle/OriginalsAsset.d.ts +0 -164
  118. package/dist/lifecycle/OriginalsAsset.js +0 -380
  119. package/dist/lifecycle/ProvenanceQuery.d.ts +0 -126
  120. package/dist/lifecycle/ProvenanceQuery.js +0 -220
  121. package/dist/lifecycle/ResourceVersioning.d.ts +0 -73
  122. package/dist/lifecycle/ResourceVersioning.js +0 -127
  123. package/dist/migration/MigrationManager.d.ts +0 -86
  124. package/dist/migration/MigrationManager.js +0 -412
  125. package/dist/migration/audit/AuditLogger.d.ts +0 -51
  126. package/dist/migration/audit/AuditLogger.js +0 -156
  127. package/dist/migration/checkpoint/CheckpointManager.d.ts +0 -31
  128. package/dist/migration/checkpoint/CheckpointManager.js +0 -96
  129. package/dist/migration/checkpoint/CheckpointStorage.d.ts +0 -26
  130. package/dist/migration/checkpoint/CheckpointStorage.js +0 -89
  131. package/dist/migration/index.d.ts +0 -22
  132. package/dist/migration/index.js +0 -27
  133. package/dist/migration/operations/BaseMigration.d.ts +0 -48
  134. package/dist/migration/operations/BaseMigration.js +0 -83
  135. package/dist/migration/operations/PeerToBtcoMigration.d.ts +0 -25
  136. package/dist/migration/operations/PeerToBtcoMigration.js +0 -67
  137. package/dist/migration/operations/PeerToWebvhMigration.d.ts +0 -19
  138. package/dist/migration/operations/PeerToWebvhMigration.js +0 -46
  139. package/dist/migration/operations/WebvhToBtcoMigration.d.ts +0 -25
  140. package/dist/migration/operations/WebvhToBtcoMigration.js +0 -67
  141. package/dist/migration/rollback/RollbackManager.d.ts +0 -29
  142. package/dist/migration/rollback/RollbackManager.js +0 -146
  143. package/dist/migration/state/StateMachine.d.ts +0 -25
  144. package/dist/migration/state/StateMachine.js +0 -76
  145. package/dist/migration/state/StateTracker.d.ts +0 -36
  146. package/dist/migration/state/StateTracker.js +0 -123
  147. package/dist/migration/types.d.ts +0 -306
  148. package/dist/migration/types.js +0 -33
  149. package/dist/migration/validation/BitcoinValidator.d.ts +0 -13
  150. package/dist/migration/validation/BitcoinValidator.js +0 -83
  151. package/dist/migration/validation/CredentialValidator.d.ts +0 -13
  152. package/dist/migration/validation/CredentialValidator.js +0 -46
  153. package/dist/migration/validation/DIDCompatibilityValidator.d.ts +0 -16
  154. package/dist/migration/validation/DIDCompatibilityValidator.js +0 -127
  155. package/dist/migration/validation/LifecycleValidator.d.ts +0 -10
  156. package/dist/migration/validation/LifecycleValidator.js +0 -52
  157. package/dist/migration/validation/StorageValidator.d.ts +0 -10
  158. package/dist/migration/validation/StorageValidator.js +0 -65
  159. package/dist/migration/validation/ValidationPipeline.d.ts +0 -29
  160. package/dist/migration/validation/ValidationPipeline.js +0 -180
  161. package/dist/storage/LocalStorageAdapter.d.ts +0 -11
  162. package/dist/storage/LocalStorageAdapter.js +0 -53
  163. package/dist/storage/MemoryStorageAdapter.d.ts +0 -6
  164. package/dist/storage/MemoryStorageAdapter.js +0 -21
  165. package/dist/storage/StorageAdapter.d.ts +0 -16
  166. package/dist/storage/StorageAdapter.js +0 -1
  167. package/dist/storage/index.d.ts +0 -2
  168. package/dist/storage/index.js +0 -2
  169. package/dist/types/bitcoin.d.ts +0 -84
  170. package/dist/types/bitcoin.js +0 -1
  171. package/dist/types/common.d.ts +0 -82
  172. package/dist/types/common.js +0 -1
  173. package/dist/types/credentials.d.ts +0 -75
  174. package/dist/types/credentials.js +0 -1
  175. package/dist/types/did.d.ts +0 -26
  176. package/dist/types/did.js +0 -1
  177. package/dist/types/index.d.ts +0 -5
  178. package/dist/types/index.js +0 -5
  179. package/dist/types/network.d.ts +0 -78
  180. package/dist/types/network.js +0 -145
  181. package/dist/utils/EventLogger.d.ts +0 -71
  182. package/dist/utils/EventLogger.js +0 -232
  183. package/dist/utils/Logger.d.ts +0 -106
  184. package/dist/utils/Logger.js +0 -257
  185. package/dist/utils/MetricsCollector.d.ts +0 -110
  186. package/dist/utils/MetricsCollector.js +0 -264
  187. package/dist/utils/bitcoin-address.d.ts +0 -38
  188. package/dist/utils/bitcoin-address.js +0 -113
  189. package/dist/utils/cbor.d.ts +0 -2
  190. package/dist/utils/cbor.js +0 -9
  191. package/dist/utils/encoding.d.ts +0 -37
  192. package/dist/utils/encoding.js +0 -120
  193. package/dist/utils/hash.d.ts +0 -1
  194. package/dist/utils/hash.js +0 -5
  195. package/dist/utils/retry.d.ts +0 -10
  196. package/dist/utils/retry.js +0 -35
  197. package/dist/utils/satoshi-validation.d.ts +0 -60
  198. package/dist/utils/satoshi-validation.js +0 -156
  199. package/dist/utils/serialization.d.ts +0 -14
  200. package/dist/utils/serialization.js +0 -76
  201. package/dist/utils/telemetry.d.ts +0 -17
  202. package/dist/utils/telemetry.js +0 -24
  203. package/dist/utils/validation.d.ts +0 -5
  204. package/dist/utils/validation.js +0 -98
  205. package/dist/vc/CredentialManager.d.ts +0 -22
  206. package/dist/vc/CredentialManager.js +0 -227
  207. package/dist/vc/Issuer.d.ts +0 -27
  208. package/dist/vc/Issuer.js +0 -70
  209. package/dist/vc/Verifier.d.ts +0 -16
  210. package/dist/vc/Verifier.js +0 -50
  211. package/dist/vc/cryptosuites/bbs.d.ts +0 -44
  212. package/dist/vc/cryptosuites/bbs.js +0 -213
  213. package/dist/vc/cryptosuites/bbsSimple.d.ts +0 -9
  214. package/dist/vc/cryptosuites/bbsSimple.js +0 -12
  215. package/dist/vc/cryptosuites/eddsa.d.ts +0 -30
  216. package/dist/vc/cryptosuites/eddsa.js +0 -81
  217. package/dist/vc/documentLoader.d.ts +0 -16
  218. package/dist/vc/documentLoader.js +0 -59
  219. package/dist/vc/proofs/data-integrity.d.ts +0 -21
  220. package/dist/vc/proofs/data-integrity.js +0 -15
  221. package/dist/vc/utils/jsonld.d.ts +0 -2
  222. package/dist/vc/utils/jsonld.js +0 -15
  223. package/test/logs/did_webvh_QmNTn9Kkp8dQ75WrF9xqJ2kuDp9QhKc3aPiERRMj8XoTBN_example_com.jsonl +0 -1
  224. package/test/logs/did_webvh_QmNu4MNr8Lr5txx5gYNhuhZDchXsZEu3hJXKYuphpWTPDp_example_com_users_etc_passwd.jsonl +0 -1
  225. package/test/logs/did_webvh_QmR9MrGZACzjKETA8SBRNCKG11HxU85c4bVR2qN5eDCfsD_example_com.jsonl +0 -1
  226. package/test/logs/did_webvh_QmUc5suaqRM2P4nrXxZwqYMfqzhdMqjuL7oJaJbEpCQVCd_example_com_users_etc_passwd.jsonl +0 -1
  227. package/test/logs/did_webvh_QmUkiB2RCV2VZ1RTXsCebWN25Eiy9TLvpzDWAJNjhgvB4X_example_com_etc_passwd.jsonl +0 -1
  228. package/test/logs/did_webvh_QmUoRTe8UMwpAQXZSAW7pjAgZK1tq2X3C6Kfxq3UXGcaGy_example_com_secret.jsonl +0 -1
  229. package/test/logs/did_webvh_QmWWot3chx1t6KwTmcE5i2FeDZ5JMkQw3qXycsKDVmJ9Be_example_com_users_alice.jsonl +0 -1
  230. package/test/logs/did_webvh_QmWvVgALL5kjZdpgR7KZay7J8UiiUr834kkRmWeFAxjAuC_example_com_users_etc_passwd.jsonl +0 -1
  231. package/test/logs/did_webvh_QmWwaRQHUZAFcKihFC6xR6tRTTrQhHPTku6azf1egWbpy1_example_com_users_alice.jsonl +0 -1
  232. package/test/logs/did_webvh_QmXJLtkz23r7AozbtXsZMKWnVU6rd38CkVtjdWuATU3Yp6_example_com_users_alice123_profile.jsonl +0 -1
  233. package/test/logs/did_webvh_QmYsce448po14oDE1wXbyaP6wY9HQgHSKLwdezn1k577SF_example_com_my_org_user_name_test_123.jsonl +0 -1
  234. package/test/logs/did_webvh_QmZBeNzzqajxdfwcDUPZ4P8C5YSXyRztrAwmPiKuKUxmAK_example_com.jsonl +0 -1
  235. package/test/logs/did_webvh_QmZhJsqxizwVbRtqCUkmE6XQunSxtxMt3gbTYadVBNAaEq_example_com.jsonl +0 -1
  236. package/test/logs/did_webvh_QmZk7NHU2D57RzzbMq4tWW9gBa9AqtVTWfiRM6RFdwGVj2_example_com.jsonl +0 -1
  237. package/test/logs/did_webvh_QmZshSXp9w8ovH62zGGBS1b5pGGPsuYiu1VQ935sga2hWF_example_com_level1_level2.jsonl +0 -1
  238. package/test/logs/did_webvh_QmbWAmw7HQL7vKJyCsctZihXf1rmT4sGvggKCPKWcUWjw1_example_com.jsonl +0 -1
  239. package/test/logs/did_webvh_QmbdLUMbYs3juR39TLB6hhrFWLcNg45ybUzeBJCS1MhCh1_example_com_C_Windows_System32.jsonl +0 -1
  240. package/test/logs/did_webvh_QmcaQ1Ma4gkSbae85aCm8Mv4rvdT2Sb2RR3JzYwrm5XBq8_example_com_etc_passwd.jsonl +0 -1
  241. package/test/logs/did_webvh_QmcbA7WQhsBqZSoDpKJHjV8Q5o53h8vmgJhQfo6rqTY5ho_example_com.jsonl +0 -1
  242. package/test/logs/did_webvh_Qmdy8uWr2gkUJrXsThynAug3DASTWwb3onEj89LKmMGZYB_example_com.jsonl +0 -1
  243. package/tests/e2e/README.md +0 -97
  244. package/tests/e2e/example.spec.ts +0 -78
@@ -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
+