@originals/sdk 1.4.2 → 1.4.3

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 (212) hide show
  1. package/package.json +4 -1
  2. package/.eslintrc.json +0 -33
  3. package/src/adapters/FeeOracleMock.ts +0 -9
  4. package/src/adapters/index.ts +0 -5
  5. package/src/adapters/providers/OrdHttpProvider.ts +0 -126
  6. package/src/adapters/providers/OrdMockProvider.ts +0 -101
  7. package/src/adapters/types.ts +0 -66
  8. package/src/bitcoin/BitcoinManager.ts +0 -330
  9. package/src/bitcoin/BroadcastClient.ts +0 -54
  10. package/src/bitcoin/OrdinalsClient.ts +0 -119
  11. package/src/bitcoin/PSBTBuilder.ts +0 -106
  12. package/src/bitcoin/fee-calculation.ts +0 -38
  13. package/src/bitcoin/providers/OrdNodeProvider.ts +0 -92
  14. package/src/bitcoin/providers/OrdinalsProvider.ts +0 -56
  15. package/src/bitcoin/providers/types.ts +0 -59
  16. package/src/bitcoin/transactions/commit.ts +0 -465
  17. package/src/bitcoin/transactions/index.ts +0 -13
  18. package/src/bitcoin/transfer.ts +0 -43
  19. package/src/bitcoin/utxo-selection.ts +0 -322
  20. package/src/bitcoin/utxo.ts +0 -113
  21. package/src/contexts/credentials-v1.json +0 -237
  22. package/src/contexts/credentials-v2-examples.json +0 -5
  23. package/src/contexts/credentials-v2.json +0 -340
  24. package/src/contexts/credentials.json +0 -237
  25. package/src/contexts/data-integrity-v2.json +0 -81
  26. package/src/contexts/dids.json +0 -58
  27. package/src/contexts/ed255192020.json +0 -93
  28. package/src/contexts/ordinals-plus.json +0 -23
  29. package/src/contexts/originals.json +0 -22
  30. package/src/core/OriginalsSDK.ts +0 -416
  31. package/src/crypto/Multikey.ts +0 -194
  32. package/src/crypto/Signer.ts +0 -254
  33. package/src/crypto/noble-init.ts +0 -121
  34. package/src/did/BtcoDidResolver.ts +0 -227
  35. package/src/did/DIDManager.ts +0 -694
  36. package/src/did/Ed25519Verifier.ts +0 -68
  37. package/src/did/KeyManager.ts +0 -236
  38. package/src/did/WebVHManager.ts +0 -498
  39. package/src/did/createBtcoDidDocument.ts +0 -59
  40. package/src/did/providers/OrdinalsClientProviderAdapter.ts +0 -68
  41. package/src/events/EventEmitter.ts +0 -222
  42. package/src/events/index.ts +0 -19
  43. package/src/events/types.ts +0 -331
  44. package/src/examples/basic-usage.ts +0 -78
  45. package/src/examples/create-module-original.ts +0 -435
  46. package/src/examples/full-lifecycle-flow.ts +0 -514
  47. package/src/examples/run.ts +0 -60
  48. package/src/index.ts +0 -150
  49. package/src/kinds/KindRegistry.ts +0 -290
  50. package/src/kinds/index.ts +0 -74
  51. package/src/kinds/types.ts +0 -470
  52. package/src/kinds/validators/AgentValidator.ts +0 -257
  53. package/src/kinds/validators/AppValidator.ts +0 -211
  54. package/src/kinds/validators/DatasetValidator.ts +0 -242
  55. package/src/kinds/validators/DocumentValidator.ts +0 -311
  56. package/src/kinds/validators/MediaValidator.ts +0 -269
  57. package/src/kinds/validators/ModuleValidator.ts +0 -225
  58. package/src/kinds/validators/base.ts +0 -276
  59. package/src/kinds/validators/index.ts +0 -12
  60. package/src/lifecycle/BatchOperations.ts +0 -373
  61. package/src/lifecycle/LifecycleManager.ts +0 -2126
  62. package/src/lifecycle/OriginalsAsset.ts +0 -524
  63. package/src/lifecycle/ProvenanceQuery.ts +0 -280
  64. package/src/lifecycle/ResourceVersioning.ts +0 -163
  65. package/src/migration/MigrationManager.ts +0 -527
  66. package/src/migration/audit/AuditLogger.ts +0 -176
  67. package/src/migration/checkpoint/CheckpointManager.ts +0 -112
  68. package/src/migration/checkpoint/CheckpointStorage.ts +0 -101
  69. package/src/migration/index.ts +0 -33
  70. package/src/migration/operations/BaseMigration.ts +0 -126
  71. package/src/migration/operations/PeerToBtcoMigration.ts +0 -105
  72. package/src/migration/operations/PeerToWebvhMigration.ts +0 -62
  73. package/src/migration/operations/WebvhToBtcoMigration.ts +0 -105
  74. package/src/migration/rollback/RollbackManager.ts +0 -170
  75. package/src/migration/state/StateMachine.ts +0 -92
  76. package/src/migration/state/StateTracker.ts +0 -156
  77. package/src/migration/types.ts +0 -344
  78. package/src/migration/validation/BitcoinValidator.ts +0 -107
  79. package/src/migration/validation/CredentialValidator.ts +0 -62
  80. package/src/migration/validation/DIDCompatibilityValidator.ts +0 -151
  81. package/src/migration/validation/LifecycleValidator.ts +0 -64
  82. package/src/migration/validation/StorageValidator.ts +0 -79
  83. package/src/migration/validation/ValidationPipeline.ts +0 -213
  84. package/src/resources/ResourceManager.ts +0 -655
  85. package/src/resources/index.ts +0 -21
  86. package/src/resources/types.ts +0 -202
  87. package/src/storage/LocalStorageAdapter.ts +0 -61
  88. package/src/storage/MemoryStorageAdapter.ts +0 -29
  89. package/src/storage/StorageAdapter.ts +0 -25
  90. package/src/storage/index.ts +0 -3
  91. package/src/types/bitcoin.ts +0 -98
  92. package/src/types/common.ts +0 -92
  93. package/src/types/credentials.ts +0 -88
  94. package/src/types/did.ts +0 -31
  95. package/src/types/external-shims.d.ts +0 -53
  96. package/src/types/index.ts +0 -7
  97. package/src/types/network.ts +0 -175
  98. package/src/utils/EventLogger.ts +0 -298
  99. package/src/utils/Logger.ts +0 -322
  100. package/src/utils/MetricsCollector.ts +0 -358
  101. package/src/utils/bitcoin-address.ts +0 -130
  102. package/src/utils/cbor.ts +0 -12
  103. package/src/utils/encoding.ts +0 -127
  104. package/src/utils/hash.ts +0 -6
  105. package/src/utils/retry.ts +0 -46
  106. package/src/utils/satoshi-validation.ts +0 -196
  107. package/src/utils/serialization.ts +0 -96
  108. package/src/utils/telemetry.ts +0 -40
  109. package/src/utils/validation.ts +0 -119
  110. package/src/vc/CredentialManager.ts +0 -918
  111. package/src/vc/Issuer.ts +0 -100
  112. package/src/vc/Verifier.ts +0 -47
  113. package/src/vc/cryptosuites/bbs.ts +0 -253
  114. package/src/vc/cryptosuites/bbsSimple.ts +0 -21
  115. package/src/vc/cryptosuites/eddsa.ts +0 -99
  116. package/src/vc/documentLoader.ts +0 -67
  117. package/src/vc/proofs/data-integrity.ts +0 -33
  118. package/src/vc/utils/jsonld.ts +0 -18
  119. package/tests/__mocks__/bbs-signatures.js +0 -17
  120. package/tests/__mocks__/mf-base58.js +0 -24
  121. package/tests/fixtures/did-documents.ts +0 -247
  122. package/tests/index.test.ts +0 -21
  123. package/tests/integration/BatchOperations.test.ts +0 -531
  124. package/tests/integration/CompleteLifecycle.e2e.test.ts +0 -735
  125. package/tests/integration/CredentialManager.test.ts +0 -42
  126. package/tests/integration/DIDManager.test.ts +0 -41
  127. package/tests/integration/DidPeerToWebVhFlow.test.ts +0 -351
  128. package/tests/integration/Events.test.ts +0 -435
  129. package/tests/integration/Lifecycle.transfer.btco.integration.test.ts +0 -25
  130. package/tests/integration/LifecycleManager.test.ts +0 -21
  131. package/tests/integration/MultikeyFlow.test.ts +0 -52
  132. package/tests/integration/TelemetryIntegration.test.ts +0 -395
  133. package/tests/integration/WebVhPublish.test.ts +0 -48
  134. package/tests/integration/createTypedOriginal.test.ts +0 -379
  135. package/tests/integration/migration/peer-to-webvh.test.ts +0 -172
  136. package/tests/manual/test-commit-creation.ts +0 -323
  137. package/tests/mocks/MockKeyStore.ts +0 -38
  138. package/tests/mocks/adapters/MemoryStorageAdapter.ts +0 -24
  139. package/tests/mocks/adapters/MockFeeOracle.ts +0 -11
  140. package/tests/mocks/adapters/MockOrdinalsProvider.ts +0 -76
  141. package/tests/mocks/adapters/OrdMockProvider.test.ts +0 -176
  142. package/tests/mocks/adapters/index.ts +0 -6
  143. package/tests/performance/BatchOperations.perf.test.ts +0 -403
  144. package/tests/performance/logging.perf.test.ts +0 -336
  145. package/tests/sdk.test.ts +0 -43
  146. package/tests/security/bitcoin-penetration-tests.test.ts +0 -622
  147. package/tests/setup.bun.ts +0 -69
  148. package/tests/setup.jest.ts +0 -23
  149. package/tests/stress/batch-operations-stress.test.ts +0 -571
  150. package/tests/unit/adapters/FeeOracleMock.test.ts +0 -40
  151. package/tests/unit/bitcoin/BitcoinManager.test.ts +0 -293
  152. package/tests/unit/bitcoin/BroadcastClient.test.ts +0 -52
  153. package/tests/unit/bitcoin/OrdNodeProvider.test.ts +0 -53
  154. package/tests/unit/bitcoin/OrdinalsClient.test.ts +0 -381
  155. package/tests/unit/bitcoin/OrdinalsClientProvider.test.ts +0 -102
  156. package/tests/unit/bitcoin/PSBTBuilder.test.ts +0 -84
  157. package/tests/unit/bitcoin/fee-calculation.test.ts +0 -261
  158. package/tests/unit/bitcoin/transactions/commit.test.ts +0 -649
  159. package/tests/unit/bitcoin/transfer.test.ts +0 -31
  160. package/tests/unit/bitcoin/utxo-selection-new.test.ts +0 -502
  161. package/tests/unit/bitcoin/utxo.more.test.ts +0 -39
  162. package/tests/unit/bitcoin/utxo.selection.test.ts +0 -38
  163. package/tests/unit/core/OriginalsSDK.test.ts +0 -152
  164. package/tests/unit/crypto/Multikey.test.ts +0 -206
  165. package/tests/unit/crypto/Signer.test.ts +0 -408
  166. package/tests/unit/did/BtcoDidResolver.test.ts +0 -611
  167. package/tests/unit/did/DIDManager.more.test.ts +0 -43
  168. package/tests/unit/did/DIDManager.test.ts +0 -185
  169. package/tests/unit/did/Ed25519Verifier.test.ts +0 -160
  170. package/tests/unit/did/KeyManager.test.ts +0 -452
  171. package/tests/unit/did/OrdinalsClientProviderAdapter.test.ts +0 -45
  172. package/tests/unit/did/WebVHManager.test.ts +0 -435
  173. package/tests/unit/did/createBtcoDidDocument.test.ts +0 -67
  174. package/tests/unit/did/providers/OrdinalsClientProviderAdapter.test.ts +0 -159
  175. package/tests/unit/events/EventEmitter.test.ts +0 -407
  176. package/tests/unit/kinds/KindRegistry.test.ts +0 -329
  177. package/tests/unit/kinds/types.test.ts +0 -409
  178. package/tests/unit/kinds/validators.test.ts +0 -651
  179. package/tests/unit/lifecycle/BatchOperations.test.ts +0 -527
  180. package/tests/unit/lifecycle/LifecycleManager.cleanapi.test.ts +0 -441
  181. package/tests/unit/lifecycle/LifecycleManager.keymanagement.test.ts +0 -312
  182. package/tests/unit/lifecycle/LifecycleManager.prov.test.ts +0 -18
  183. package/tests/unit/lifecycle/LifecycleManager.test.ts +0 -213
  184. package/tests/unit/lifecycle/LifecycleManager.transfer.unit.test.ts +0 -30
  185. package/tests/unit/lifecycle/OriginalsAsset.test.ts +0 -176
  186. package/tests/unit/lifecycle/ProvenanceQuery.test.ts +0 -577
  187. package/tests/unit/lifecycle/ResourceVersioning.test.ts +0 -651
  188. package/tests/unit/resources/ResourceManager.test.ts +0 -740
  189. package/tests/unit/storage/MemoryStorageAdapter.test.ts +0 -93
  190. package/tests/unit/types/network.test.ts +0 -255
  191. package/tests/unit/utils/EventIntegration.test.ts +0 -384
  192. package/tests/unit/utils/Logger.test.ts +0 -473
  193. package/tests/unit/utils/MetricsCollector.test.ts +0 -358
  194. package/tests/unit/utils/bitcoin-address.test.ts +0 -250
  195. package/tests/unit/utils/cbor.test.ts +0 -35
  196. package/tests/unit/utils/encoding.test.ts +0 -318
  197. package/tests/unit/utils/hash.test.ts +0 -12
  198. package/tests/unit/utils/retry.test.ts +0 -100
  199. package/tests/unit/utils/satoshi-validation.test.ts +0 -354
  200. package/tests/unit/utils/serialization.test.ts +0 -124
  201. package/tests/unit/utils/telemetry.test.ts +0 -52
  202. package/tests/unit/utils/validation.test.ts +0 -141
  203. package/tests/unit/vc/CredentialManager.helpers.test.ts +0 -527
  204. package/tests/unit/vc/CredentialManager.test.ts +0 -487
  205. package/tests/unit/vc/Issuer.test.ts +0 -107
  206. package/tests/unit/vc/Verifier.test.ts +0 -525
  207. package/tests/unit/vc/bbs.test.ts +0 -282
  208. package/tests/unit/vc/cryptosuites/eddsa.test.ts +0 -398
  209. package/tests/unit/vc/documentLoader.test.ts +0 -121
  210. package/tests/unit/vc/proofs/data-integrity.test.ts +0 -24
  211. package/tsconfig.json +0 -31
  212. package/tsconfig.test.json +0 -15
@@ -1,130 +0,0 @@
1
- import * as bitcoin from 'bitcoinjs-lib';
2
-
3
- /**
4
- * Bitcoin network types supported by the validation
5
- */
6
- export type BitcoinNetwork = 'mainnet' | 'regtest' | 'signet';
7
-
8
- /**
9
- * Maps our network names to bitcoinjs-lib network configurations
10
- */
11
- const getNetwork = (network: BitcoinNetwork): bitcoin.Network => {
12
- switch (network) {
13
- case 'mainnet':
14
- return bitcoin.networks.bitcoin;
15
- case 'regtest':
16
- // Regtest uses testnet parameters but with bcrt prefix
17
- // However, since many regtest addresses in tests use testnet format,
18
- // we accept both testnet and regtest addresses for regtest network
19
- return bitcoin.networks.regtest;
20
- case 'signet':
21
- // Signet uses the same bech32 prefix as testnet (tb1)
22
- return bitcoin.networks.testnet;
23
- default:
24
- throw new Error(`Unsupported network: ${network}`);
25
- }
26
- };
27
-
28
- /**
29
- * Validates a Bitcoin address format and checksum for the given network.
30
- *
31
- * This function uses bitcoinjs-lib's address.toOutputScript() which performs:
32
- * - Format validation (bech32, base58check)
33
- * - Checksum verification
34
- * - Network prefix validation
35
- *
36
- * @param address - The Bitcoin address to validate
37
- * @param network - The network to validate against ('mainnet', 'regtest', 'signet')
38
- * @returns true if the address is valid for the network
39
- * @throws Error with descriptive message if validation fails
40
- *
41
- * @example
42
- * ```typescript
43
- * // Valid mainnet address
44
- * validateBitcoinAddress('bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq', 'mainnet'); // true
45
- *
46
- * // Invalid checksum
47
- * validateBitcoinAddress('bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdd', 'mainnet'); // throws
48
- *
49
- * // Wrong network
50
- * validateBitcoinAddress('bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq', 'testnet'); // throws
51
- * ```
52
- */
53
- export function validateBitcoinAddress(address: string, network: BitcoinNetwork): boolean {
54
- // Input validation
55
- if (!address || typeof address !== 'string') {
56
- throw new Error('Address must be a non-empty string');
57
- }
58
-
59
- const trimmedAddress = address.trim();
60
-
61
- if (trimmedAddress.length === 0) {
62
- throw new Error('Address cannot be empty');
63
- }
64
-
65
- // Check for mock/test addresses that should not be allowed in production
66
- if (/^(mock-|test-)/i.test(trimmedAddress)) {
67
- throw new Error('Mock or test addresses are not valid Bitcoin addresses');
68
- }
69
-
70
- // Validate address length (Bitcoin addresses are typically 26-90 characters)
71
- if (trimmedAddress.length < 26 || trimmedAddress.length > 90) {
72
- throw new Error(`Invalid address length: ${trimmedAddress.length} characters (expected 26-90)`);
73
- }
74
-
75
- try {
76
- // Get the appropriate network configuration
77
- const networkConfig = getNetwork(network);
78
-
79
- // Use bitcoinjs-lib to validate the address format and checksum
80
- // This will throw if the address is invalid
81
- bitcoin.address.toOutputScript(trimmedAddress, networkConfig);
82
-
83
- return true;
84
- } catch (error) {
85
- // For regtest, also try testnet network as many tools use testnet addresses for regtest
86
- if (network === 'regtest') {
87
- try {
88
- bitcoin.address.toOutputScript(trimmedAddress, bitcoin.networks.testnet);
89
- return true;
90
- } catch {
91
- // Fall through to error handling below
92
- }
93
- }
94
-
95
- // Parse the error to provide more specific feedback
96
- const errorMessage = error instanceof Error ? error.message : String(error);
97
-
98
- // Check for common error patterns and provide helpful messages
99
- if (errorMessage.includes('Invalid checksum') || errorMessage.includes('checksum')) {
100
- throw new Error(`Invalid Bitcoin address checksum for address: ${trimmedAddress}`);
101
- }
102
-
103
- if (errorMessage.includes('Invalid prefix') || errorMessage.includes('prefix')) {
104
- throw new Error(`Invalid address prefix for ${network} network: ${trimmedAddress}`);
105
- }
106
-
107
- if (errorMessage.includes('too short') || errorMessage.includes('too long')) {
108
- throw new Error(`Invalid address length for ${network}: ${trimmedAddress}`);
109
- }
110
-
111
- // Generic invalid address error
112
- throw new Error(`Invalid Bitcoin address for ${network} network: ${trimmedAddress} (${errorMessage})`);
113
- }
114
- }
115
-
116
- /**
117
- * Validates a Bitcoin address and returns a boolean instead of throwing
118
- *
119
- * @param address - The Bitcoin address to validate
120
- * @param network - The network to validate against
121
- * @returns true if valid, false otherwise
122
- */
123
- export function isValidBitcoinAddress(address: string, network: BitcoinNetwork): boolean {
124
- try {
125
- validateBitcoinAddress(address, network);
126
- return true;
127
- } catch {
128
- return false;
129
- }
130
- }
package/src/utils/cbor.ts DELETED
@@ -1,12 +0,0 @@
1
- import * as cbor from 'cbor-js';
2
-
3
- export function encode(input: unknown): Uint8Array {
4
- const encoded: any = (cbor as any).encode(input);
5
- return new Uint8Array(encoded);
6
- }
7
-
8
- export function decode<T = unknown>(bytes: Uint8Array | ArrayBuffer | Buffer): T {
9
- const view = new Uint8Array(bytes as any);
10
- return (cbor as any).decode(view.buffer) as T;
11
- }
12
-
@@ -1,127 +0,0 @@
1
- import b58 from 'b58';
2
-
3
- export function encodeBase64UrlMultibase(bytes: Uint8Array): string {
4
- return 'z' + Buffer.from(bytes).toString('base64url');
5
- }
6
-
7
- export function decodeBase64UrlMultibase(s: string): Uint8Array {
8
- if (!s || s[0] !== 'z') {
9
- throw new Error('Invalid Multibase encoding');
10
- }
11
- return Buffer.from(s.slice(1), 'base64url');
12
- }
13
-
14
- export function hexToBytes(hex: string): Uint8Array {
15
- const clean = hex.startsWith('0x') ? hex.slice(2) : hex;
16
- if (clean.length % 2 !== 0) {
17
- throw new Error('Invalid hex string length');
18
- }
19
- const out = new Uint8Array(clean.length / 2);
20
- for (let i = 0; i < clean.length; i += 2) {
21
- const byteStr = clean.substring(i, i + 2);
22
- const value = parseInt(byteStr, 16);
23
- if (Number.isNaN(value)) {
24
- throw new Error('Invalid hex string');
25
- }
26
- out[i / 2] = value;
27
- }
28
- return out;
29
- }
30
-
31
- // multibase base58-btc header
32
- export const MULTIBASE_BASE58BTC_HEADER = 'z';
33
- // multibase base64url header
34
- export const MULTIBASE_BASE64URL_HEADER = 'u';
35
- // multicodec ed25519-pub header as varint
36
- export const MULTICODEC_ED25519_PUB_HEADER = new Uint8Array([0xed, 0x01]);
37
- // multicodec ed25519-priv header as varint
38
- export const MULTICODEC_ED25519_PRIV_HEADER = new Uint8Array([0x80, 0x26]);
39
- // multicodec x25519-pub header as varint
40
- export const MULTICODEC_X25519_PUB_HEADER = new Uint8Array([0xec, 0x01]);
41
- // multicodec x25519-priv header as varint
42
- export const MULTICODEC_X25519_PRIV_HEADER = new Uint8Array([0x82, 0x26]);
43
- // multicode secp256k1-pub header as varint
44
- export const MULTICODEC_SECP256K1_PUB_HEADER = new Uint8Array([0xe7, 0x01]);
45
- // multicode secp256k1-priv header as varint
46
- export const MULTICODEC_SECP256K1_PRIV_HEADER = new Uint8Array([0x13, 0x01]);
47
- // multicodec bls12381g2-pub header as varint
48
- export const MULTICODEC_BLS12381_G2_PUB_HEADER = new Uint8Array([0xeb, 0x01]);
49
- // multicodec bls12381g2-priv header as varint
50
- export const MULTICODEC_BLS12381_G2_PRIV_HEADER = new Uint8Array([0x8a, 0x26]);
51
-
52
- export const base64 = {
53
- encode: (unencoded: any): string => {
54
- return Buffer.from(unencoded || '').toString('base64');
55
- },
56
- decode: (encoded: any): Uint8Array => {
57
- return new Uint8Array(Buffer.from(encoded || '', 'base64').buffer);
58
- }
59
- };
60
-
61
- export const utf8 = {
62
- encode: (unencoded: string): Uint8Array => {
63
- return new TextEncoder().encode(unencoded)
64
- },
65
- decode: (encoded: Uint8Array): string => {
66
- return new TextDecoder().decode(encoded);
67
- }
68
- }
69
-
70
- export const base64url = {
71
- encode: (unencoded: any): string => {
72
- const encoded = base64.encode(unencoded);
73
- return encoded.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, '');
74
- },
75
- decode: (encoded: any): Uint8Array => {
76
- encoded = encoded.replace(/-/g, '+').replace(/_/g, '/');
77
- while (encoded.length % 4) encoded += '=';
78
- return base64.decode(encoded);
79
- }
80
- };
81
-
82
- export const base58 = {
83
- encode: (unencoded: Uint8Array): string => {
84
- return b58.encode(unencoded);
85
- },
86
- decode: (encoded: string): Uint8Array => {
87
- return b58.decode(encoded);
88
- }
89
- };
90
-
91
- export const multibase = {
92
- encode: (val: Uint8Array, encoding: 'base58btc' | 'base64url'): string => {
93
- if (encoding === 'base58btc') {
94
- const baseEncoded = base58.encode(val);
95
- return MULTIBASE_BASE58BTC_HEADER + baseEncoded;
96
- } else if (encoding === 'base64url') {
97
- return MULTIBASE_BASE64URL_HEADER + base64url.encode(val);
98
- }
99
- throw new Error('Invalid multibase encoding.');
100
- },
101
- decode: (val: string): Uint8Array => {
102
- if (val.startsWith(MULTIBASE_BASE58BTC_HEADER)) {
103
- return base58.decode(val.substring(1));
104
- } else if (val.startsWith(MULTIBASE_BASE64URL_HEADER)) {
105
- return base64url.decode(val.substring(1));
106
- }
107
- throw new Error('Multibase value does not have expected header.');
108
- }
109
- };
110
-
111
- export const multikey = {
112
- encode: (header: Uint8Array, val: Uint8Array): string => {
113
- const mcBytes = new Uint8Array(header.length + val.length);
114
- mcBytes.set(header);
115
- mcBytes.set(val, header.length);
116
- return multibase.encode(mcBytes, 'base58btc');
117
- },
118
- decode: (header: Uint8Array, val: string): Uint8Array => {
119
- const mcValue = multibase.decode(val);
120
- for (let i = 0; i < header.length; i++) {
121
- if (mcValue[i] !== header[i]) {
122
- throw new Error('Multikey value does not have expected header.');
123
- }
124
- }
125
- return mcValue.slice(header.length);
126
- }
127
- }
package/src/utils/hash.ts DELETED
@@ -1,6 +0,0 @@
1
- export async function sha256Bytes(input: string | Uint8Array): Promise<Uint8Array> {
2
- const data = typeof input === 'string' ? new TextEncoder().encode(input) : input;
3
- const digest = await (globalThis.crypto as any).subtle.digest('SHA-256', data);
4
- return new Uint8Array(digest);
5
- }
6
-
@@ -1,46 +0,0 @@
1
- export interface RetryOptions {
2
- maxRetries?: number;
3
- baseDelayMs?: number;
4
- maxDelayMs?: number;
5
- backoffFactor?: number;
6
- jitterFactor?: number; // 0..1
7
- isRetriable?: (error: unknown) => boolean;
8
- onRetry?: (attempt: number, delayMs: number, error: unknown) => void;
9
- }
10
-
11
- const DEFAULTS: Required<RetryOptions> = {
12
- maxRetries: 3,
13
- baseDelayMs: 300,
14
- maxDelayMs: 10_000,
15
- backoffFactor: 2,
16
- jitterFactor: 0.1,
17
- isRetriable: () => true,
18
- onRetry: () => {}
19
- };
20
-
21
- function sleep(ms: number): Promise<void> {
22
- return new Promise(resolve => setTimeout(resolve, ms));
23
- }
24
-
25
- function computeDelay(attempt: number, opts: Required<RetryOptions>): number {
26
- const exp = opts.baseDelayMs * Math.pow(opts.backoffFactor, attempt);
27
- const withJitter = exp + ((Math.random() * 2 - 1) * opts.jitterFactor * exp);
28
- return Math.min(Math.max(0, Math.floor(withJitter)), opts.maxDelayMs);
29
- }
30
-
31
- export async function withRetry<T>(fn: () => Promise<T>, options: RetryOptions = {}): Promise<T> {
32
- const opts: Required<RetryOptions> = { ...DEFAULTS, ...options } as any;
33
- let lastError: unknown;
34
- for (let attempt = 0; attempt <= opts.maxRetries; attempt++) {
35
- try {
36
- return await fn();
37
- } catch (err) {
38
- lastError = err;
39
- if (attempt >= opts.maxRetries || !opts.isRetriable(err)) break;
40
- const delay = computeDelay(attempt, opts);
41
- opts.onRetry(attempt + 1, delay, err);
42
- await sleep(delay);
43
- }
44
- }
45
- throw lastError;
46
- }
@@ -1,196 +0,0 @@
1
- import { StructuredError } from './telemetry';
2
-
3
- /**
4
- * Maximum number of satoshis in Bitcoin's total supply (21 million BTC)
5
- * 21,000,000 BTC * 100,000,000 satoshis/BTC = 2,100,000,000,000,000 satoshis
6
- */
7
- export const MAX_SATOSHI_SUPPLY = 2_100_000_000_000_000;
8
-
9
- /**
10
- * Validation result interface for satoshi number validation
11
- */
12
- export interface SatoshiValidationResult {
13
- valid: boolean;
14
- error?: string;
15
- }
16
-
17
- /**
18
- * Validates a satoshi number for use in Bitcoin ordinals and did:btco DIDs.
19
- *
20
- * @param satoshi - The satoshi identifier to validate (string or number)
21
- * @returns Validation result with descriptive error if invalid
22
- *
23
- * @example
24
- * ```typescript
25
- * const result = validateSatoshiNumber('123456');
26
- * if (!result.valid) {
27
- * throw new Error(result.error);
28
- * }
29
- * ```
30
- */
31
- export function validateSatoshiNumber(satoshi: string | number): SatoshiValidationResult {
32
- // Check for null, undefined, or empty string
33
- if (satoshi === null || satoshi === undefined || satoshi === '') {
34
- return {
35
- valid: false,
36
- error: 'Satoshi identifier cannot be null, undefined, or empty string'
37
- };
38
- }
39
-
40
- // Convert to string for validation
41
- const satoshiStr = String(satoshi).trim();
42
-
43
- // Check for empty string after trimming
44
- if (satoshiStr === '') {
45
- return {
46
- valid: false,
47
- error: 'Satoshi identifier cannot be empty or whitespace-only string'
48
- };
49
- }
50
-
51
- // Check for numeric format (must be all digits, no decimals, no scientific notation)
52
- if (!/^[0-9]+$/.test(satoshiStr)) {
53
- return {
54
- valid: false,
55
- error: 'Satoshi identifier must be a non-negative integer (no decimals, no scientific notation, no non-numeric characters)'
56
- };
57
- }
58
-
59
- // Convert to number for range validation
60
- const satoshiNum = Number(satoshiStr);
61
-
62
- // Check for valid number conversion
63
- if (!Number.isFinite(satoshiNum)) {
64
- return {
65
- valid: false,
66
- error: 'Satoshi identifier must be a finite number'
67
- };
68
- }
69
-
70
- // Check for decimals (would be truncated by Number())
71
- if (satoshiNum !== Math.floor(satoshiNum)) {
72
- return {
73
- valid: false,
74
- error: 'Satoshi identifier cannot contain decimal places'
75
- };
76
- }
77
-
78
- // Check for negative numbers
79
- if (satoshiNum < 0) {
80
- return {
81
- valid: false,
82
- error: 'Satoshi identifier must be non-negative (>= 0)'
83
- };
84
- }
85
-
86
- // Check for maximum supply range
87
- if (satoshiNum > MAX_SATOSHI_SUPPLY) {
88
- return {
89
- valid: false,
90
- error: `Satoshi identifier must be within Bitcoin's total supply (0 to ${MAX_SATOSHI_SUPPLY.toLocaleString()})`
91
- };
92
- }
93
-
94
- return { valid: true };
95
- }
96
-
97
- /**
98
- * Parses a satoshi identifier from various formats and validates it.
99
- *
100
- * Supported formats:
101
- * - Plain satoshi number: "123456"
102
- * - did:btco DID: "did:btco:123456", "did:btco:test:123456", "did:btco:sig:123456"
103
- * - Ordinal notation: "123456" (same as plain number, for future extensions)
104
- *
105
- * @param identifier - The identifier to parse
106
- * @returns The extracted satoshi number
107
- * @throws {StructuredError} If the identifier format is invalid or satoshi is invalid
108
- *
109
- * @example
110
- * ```typescript
111
- * const satoshi = parseSatoshiIdentifier('did:btco:123456');
112
- * console.log(satoshi); // 123456
113
- * ```
114
- */
115
- export function parseSatoshiIdentifier(identifier: string): number {
116
- if (!identifier || typeof identifier !== 'string') {
117
- throw new StructuredError(
118
- 'INVALID_SATOSHI_IDENTIFIER',
119
- 'Satoshi identifier must be a non-empty string'
120
- );
121
- }
122
-
123
- const trimmed = identifier.trim();
124
-
125
- if (trimmed === '') {
126
- throw new StructuredError(
127
- 'INVALID_SATOSHI_IDENTIFIER',
128
- 'Satoshi identifier cannot be empty or whitespace-only'
129
- );
130
- }
131
-
132
- let satoshiStr: string;
133
-
134
- // Check if it's a did:btco DID
135
- if (trimmed.startsWith('did:btco:')) {
136
- const parts = trimmed.split(':');
137
-
138
- // Handle different network prefixes:
139
- // did:btco:123456 (mainnet)
140
- // did:btco:test:123456 (testnet)
141
- // did:btco:sig:123456 (signet)
142
- if (parts.length === 3) {
143
- // Mainnet format: did:btco:satoshi
144
- satoshiStr = parts[2];
145
- } else if (parts.length === 4) {
146
- // Network-specific format: did:btco:network:satoshi
147
- const network = parts[2];
148
- if (network !== 'test' && network !== 'sig') {
149
- throw new StructuredError(
150
- 'INVALID_SATOSHI_IDENTIFIER',
151
- `Invalid did:btco DID format: unsupported network "${network}"`
152
- );
153
- }
154
- satoshiStr = parts[3];
155
- } else {
156
- throw new StructuredError(
157
- 'INVALID_SATOSHI_IDENTIFIER',
158
- 'Invalid did:btco DID format: expected "did:btco:satoshi" or "did:btco:network:satoshi"'
159
- );
160
- }
161
- } else {
162
- // Assume it's a plain satoshi number
163
- satoshiStr = trimmed;
164
- }
165
-
166
- // Validate the extracted satoshi
167
- const validation = validateSatoshiNumber(satoshiStr);
168
- if (!validation.valid) {
169
- throw new StructuredError(
170
- 'INVALID_SATOSHI_IDENTIFIER',
171
- validation.error || 'Invalid satoshi identifier'
172
- );
173
- }
174
-
175
- return Number(satoshiStr);
176
- }
177
-
178
- /**
179
- * Validates a satoshi number and throws an error if invalid.
180
- * Convenience wrapper around validateSatoshiNumber for code that expects exceptions.
181
- *
182
- * @param satoshi - The satoshi identifier to validate
183
- * @throws {StructuredError} If the satoshi is invalid
184
- *
185
- * @example
186
- * ```typescript
187
- * assertValidSatoshi('123456'); // OK
188
- * assertValidSatoshi(''); // throws StructuredError
189
- * ```
190
- */
191
- export function assertValidSatoshi(satoshi: string | number): void {
192
- const result = validateSatoshiNumber(satoshi);
193
- if (!result.valid) {
194
- throw new StructuredError('INVALID_SATOSHI', result.error || 'Invalid satoshi identifier');
195
- }
196
- }
@@ -1,96 +0,0 @@
1
- import jsonld from 'jsonld';
2
- import { DIDDocument, VerifiableCredential } from '../types';
3
-
4
- type DocumentLoader = (url: string) => Promise<{
5
- documentUrl: string;
6
- document: any;
7
- contextUrl: string | null;
8
- }>;
9
-
10
- // Import context documents from src/contexts
11
- import credentialsV1Context from '../contexts/credentials-v1.json';
12
- import credentialsV2Context from '../contexts/credentials-v2.json';
13
- import dataIntegrityV2Context from '../contexts/data-integrity-v2.json';
14
- import didsContext from '../contexts/dids.json';
15
- import ed255192020Context from '../contexts/ed255192020.json';
16
- import ordinalsContext from '../contexts/ordinals-plus.json';
17
- import originalsContext from '../contexts/originals.json';
18
-
19
- // Full context documents for proper canonicalization
20
- const PRELOADED_CONTEXTS: Record<string, any> = {
21
- // W3C and standard contexts
22
- 'https://www.w3.org/2018/credentials/v1': credentialsV1Context,
23
- 'https://www.w3.org/ns/credentials/v2': credentialsV2Context,
24
- 'https://w3id.org/security/data-integrity/v2': dataIntegrityV2Context,
25
- 'https://www.w3.org/ns/did/v1': didsContext,
26
- 'https://w3id.org/security/suites/ed25519-2020/v1': ed255192020Context,
27
-
28
- // Custom contexts
29
- 'https://ordinals.plus/vocab/v1': ordinalsContext,
30
-
31
- // Originals network contexts (all three networks use the same context document)
32
- 'https://originals.build/context': originalsContext, // Legacy
33
- 'https://pichu.originals.build/context': originalsContext, // Production
34
- 'https://cleffa.originals.build/context': originalsContext, // Staging
35
- 'https://magby.originals.build/context': originalsContext, // Development
36
- };
37
-
38
-
39
- const defaultDocumentLoader: DocumentLoader = async (url: string) => {
40
- const preloaded = PRELOADED_CONTEXTS[url];
41
- if (preloaded) {
42
- return { documentUrl: url, document: preloaded, contextUrl: null };
43
- }
44
- throw new Error(`Document not found in PRELOADED_CONTEXTS: ${url}`);
45
- };
46
-
47
- export function serializeDIDDocument(didDoc: DIDDocument): string {
48
- // Serialize to JSON-LD with proper context
49
- return JSON.stringify(didDoc, null, 2);
50
- }
51
-
52
- export function deserializeDIDDocument(data: string): DIDDocument {
53
- // Parse from JSON-LD
54
- try {
55
- const parsed = JSON.parse(data);
56
- return parsed as DIDDocument;
57
- } catch (error) {
58
- throw new Error('Invalid DID Document JSON');
59
- }
60
- }
61
-
62
- export function serializeCredential(vc: VerifiableCredential): string {
63
- // Serialize VC to JSON-LD
64
- return JSON.stringify(vc, null, 2);
65
- }
66
-
67
- export function deserializeCredential(data: string): VerifiableCredential {
68
- // Parse VC from JSON-LD
69
- try {
70
- const parsed = JSON.parse(data);
71
- return parsed as VerifiableCredential;
72
- } catch (error) {
73
- throw new Error('Invalid Verifiable Credential JSON');
74
- }
75
- }
76
-
77
- export async function canonicalizeDocument(
78
- doc: any,
79
- options: { documentLoader?: DocumentLoader } = {}
80
- ): Promise<string> {
81
- try {
82
- return await jsonld.canonize(doc, {
83
- algorithm: 'URDNA2015',
84
- format: 'application/n-quads',
85
- documentLoader: options.documentLoader ?? defaultDocumentLoader,
86
- useNative: false,
87
- rdfDirection: 'i18n-datatype',
88
- safe: false // Disable safe mode to allow custom contexts
89
- } as any);
90
- } catch (error: any) {
91
- const message = error?.message ?? String(error);
92
- throw new Error(`Failed to canonicalize document: ${message}`);
93
- }
94
- }
95
-
96
-
@@ -1,40 +0,0 @@
1
- export type TelemetryLevel = 'debug' | 'info' | 'warn' | 'error';
2
-
3
- export interface TelemetryEvent {
4
- name: string;
5
- level?: TelemetryLevel;
6
- attributes?: Record<string, unknown>;
7
- }
8
-
9
- export interface TelemetryHooks {
10
- onEvent?: (event: TelemetryEvent) => void;
11
- onError?: (error: StructuredError) => void;
12
- }
13
-
14
- export class StructuredError extends Error {
15
- public readonly code: string;
16
- public readonly details?: Record<string, unknown>;
17
- constructor(code: string, message: string, details?: Record<string, unknown>) {
18
- super(message);
19
- this.name = 'StructuredError';
20
- this.code = code;
21
- this.details = details;
22
- }
23
- }
24
-
25
- export function emitTelemetry(hooks: TelemetryHooks | undefined, event: TelemetryEvent): void {
26
- if (hooks && typeof hooks.onEvent === 'function') {
27
- try {
28
- hooks.onEvent({ level: 'info', ...event });
29
- } catch (_) {}
30
- }
31
- }
32
-
33
- export function emitError(hooks: TelemetryHooks | undefined, error: StructuredError): void {
34
- if (hooks && typeof hooks.onError === 'function') {
35
- try {
36
- hooks.onError(error);
37
- } catch (_) {}
38
- }
39
- }
40
-