@originals/sdk 1.8.2 → 1.8.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 (144) hide show
  1. package/package.json +5 -6
  2. package/src/adapters/FeeOracleMock.ts +0 -9
  3. package/src/adapters/index.ts +0 -5
  4. package/src/adapters/providers/OrdHttpProvider.ts +0 -126
  5. package/src/adapters/providers/OrdMockProvider.ts +0 -101
  6. package/src/adapters/types.ts +0 -66
  7. package/src/bitcoin/BitcoinManager.ts +0 -329
  8. package/src/bitcoin/BroadcastClient.ts +0 -54
  9. package/src/bitcoin/OrdinalsClient.ts +0 -120
  10. package/src/bitcoin/PSBTBuilder.ts +0 -106
  11. package/src/bitcoin/fee-calculation.ts +0 -38
  12. package/src/bitcoin/providers/OrdNodeProvider.ts +0 -92
  13. package/src/bitcoin/providers/OrdinalsProvider.ts +0 -56
  14. package/src/bitcoin/providers/types.ts +0 -59
  15. package/src/bitcoin/transactions/commit.ts +0 -465
  16. package/src/bitcoin/transactions/index.ts +0 -13
  17. package/src/bitcoin/transfer.ts +0 -43
  18. package/src/bitcoin/utxo-selection.ts +0 -322
  19. package/src/bitcoin/utxo.ts +0 -113
  20. package/src/cel/ExternalReferenceManager.ts +0 -87
  21. package/src/cel/OriginalsCel.ts +0 -460
  22. package/src/cel/algorithms/createEventLog.ts +0 -68
  23. package/src/cel/algorithms/deactivateEventLog.ts +0 -109
  24. package/src/cel/algorithms/index.ts +0 -11
  25. package/src/cel/algorithms/updateEventLog.ts +0 -99
  26. package/src/cel/algorithms/verifyEventLog.ts +0 -306
  27. package/src/cel/algorithms/witnessEvent.ts +0 -87
  28. package/src/cel/cli/create.ts +0 -330
  29. package/src/cel/cli/index.ts +0 -383
  30. package/src/cel/cli/inspect.ts +0 -549
  31. package/src/cel/cli/migrate.ts +0 -473
  32. package/src/cel/cli/verify.ts +0 -249
  33. package/src/cel/hash.ts +0 -71
  34. package/src/cel/index.ts +0 -16
  35. package/src/cel/layers/BtcoCelManager.ts +0 -408
  36. package/src/cel/layers/PeerCelManager.ts +0 -371
  37. package/src/cel/layers/WebVHCelManager.ts +0 -361
  38. package/src/cel/layers/index.ts +0 -27
  39. package/src/cel/serialization/cbor.ts +0 -189
  40. package/src/cel/serialization/index.ts +0 -10
  41. package/src/cel/serialization/json.ts +0 -209
  42. package/src/cel/types.ts +0 -160
  43. package/src/cel/witnesses/BitcoinWitness.ts +0 -184
  44. package/src/cel/witnesses/HttpWitness.ts +0 -241
  45. package/src/cel/witnesses/WitnessService.ts +0 -51
  46. package/src/cel/witnesses/index.ts +0 -11
  47. package/src/contexts/credentials-v1.json +0 -237
  48. package/src/contexts/credentials-v2-examples.json +0 -5
  49. package/src/contexts/credentials-v2.json +0 -340
  50. package/src/contexts/credentials.json +0 -237
  51. package/src/contexts/data-integrity-v2.json +0 -81
  52. package/src/contexts/dids.json +0 -58
  53. package/src/contexts/ed255192020.json +0 -93
  54. package/src/contexts/ordinals-plus.json +0 -23
  55. package/src/contexts/originals.json +0 -22
  56. package/src/core/OriginalsSDK.ts +0 -420
  57. package/src/crypto/Multikey.ts +0 -194
  58. package/src/crypto/Signer.ts +0 -262
  59. package/src/crypto/noble-init.ts +0 -138
  60. package/src/did/BtcoDidResolver.ts +0 -231
  61. package/src/did/DIDManager.ts +0 -705
  62. package/src/did/Ed25519Verifier.ts +0 -68
  63. package/src/did/KeyManager.ts +0 -239
  64. package/src/did/WebVHManager.ts +0 -499
  65. package/src/did/createBtcoDidDocument.ts +0 -60
  66. package/src/did/providers/OrdinalsClientProviderAdapter.ts +0 -68
  67. package/src/events/EventEmitter.ts +0 -222
  68. package/src/events/index.ts +0 -19
  69. package/src/events/types.ts +0 -331
  70. package/src/examples/basic-usage.ts +0 -78
  71. package/src/examples/create-module-original.ts +0 -435
  72. package/src/examples/full-lifecycle-flow.ts +0 -514
  73. package/src/examples/run.ts +0 -60
  74. package/src/index.ts +0 -204
  75. package/src/kinds/KindRegistry.ts +0 -320
  76. package/src/kinds/index.ts +0 -74
  77. package/src/kinds/types.ts +0 -470
  78. package/src/kinds/validators/AgentValidator.ts +0 -257
  79. package/src/kinds/validators/AppValidator.ts +0 -211
  80. package/src/kinds/validators/DatasetValidator.ts +0 -242
  81. package/src/kinds/validators/DocumentValidator.ts +0 -311
  82. package/src/kinds/validators/MediaValidator.ts +0 -269
  83. package/src/kinds/validators/ModuleValidator.ts +0 -225
  84. package/src/kinds/validators/base.ts +0 -276
  85. package/src/kinds/validators/index.ts +0 -12
  86. package/src/lifecycle/BatchOperations.ts +0 -381
  87. package/src/lifecycle/LifecycleManager.ts +0 -2156
  88. package/src/lifecycle/OriginalsAsset.ts +0 -524
  89. package/src/lifecycle/ProvenanceQuery.ts +0 -280
  90. package/src/lifecycle/ResourceVersioning.ts +0 -163
  91. package/src/migration/MigrationManager.ts +0 -587
  92. package/src/migration/audit/AuditLogger.ts +0 -176
  93. package/src/migration/checkpoint/CheckpointManager.ts +0 -112
  94. package/src/migration/checkpoint/CheckpointStorage.ts +0 -101
  95. package/src/migration/index.ts +0 -33
  96. package/src/migration/operations/BaseMigration.ts +0 -126
  97. package/src/migration/operations/PeerToBtcoMigration.ts +0 -105
  98. package/src/migration/operations/PeerToWebvhMigration.ts +0 -62
  99. package/src/migration/operations/WebvhToBtcoMigration.ts +0 -105
  100. package/src/migration/rollback/RollbackManager.ts +0 -170
  101. package/src/migration/state/StateMachine.ts +0 -92
  102. package/src/migration/state/StateTracker.ts +0 -156
  103. package/src/migration/types.ts +0 -356
  104. package/src/migration/validation/BitcoinValidator.ts +0 -107
  105. package/src/migration/validation/CredentialValidator.ts +0 -62
  106. package/src/migration/validation/DIDCompatibilityValidator.ts +0 -151
  107. package/src/migration/validation/LifecycleValidator.ts +0 -64
  108. package/src/migration/validation/StorageValidator.ts +0 -79
  109. package/src/migration/validation/ValidationPipeline.ts +0 -213
  110. package/src/resources/ResourceManager.ts +0 -655
  111. package/src/resources/index.ts +0 -21
  112. package/src/resources/types.ts +0 -202
  113. package/src/storage/LocalStorageAdapter.ts +0 -64
  114. package/src/storage/MemoryStorageAdapter.ts +0 -29
  115. package/src/storage/StorageAdapter.ts +0 -25
  116. package/src/storage/index.ts +0 -3
  117. package/src/types/bitcoin.ts +0 -98
  118. package/src/types/common.ts +0 -92
  119. package/src/types/credentials.ts +0 -89
  120. package/src/types/did.ts +0 -31
  121. package/src/types/external-shims.d.ts +0 -53
  122. package/src/types/index.ts +0 -7
  123. package/src/types/network.ts +0 -178
  124. package/src/utils/EventLogger.ts +0 -298
  125. package/src/utils/Logger.ts +0 -324
  126. package/src/utils/MetricsCollector.ts +0 -358
  127. package/src/utils/bitcoin-address.ts +0 -132
  128. package/src/utils/cbor.ts +0 -31
  129. package/src/utils/encoding.ts +0 -135
  130. package/src/utils/hash.ts +0 -12
  131. package/src/utils/retry.ts +0 -46
  132. package/src/utils/satoshi-validation.ts +0 -196
  133. package/src/utils/serialization.ts +0 -102
  134. package/src/utils/telemetry.ts +0 -44
  135. package/src/utils/validation.ts +0 -123
  136. package/src/vc/CredentialManager.ts +0 -955
  137. package/src/vc/Issuer.ts +0 -105
  138. package/src/vc/Verifier.ts +0 -54
  139. package/src/vc/cryptosuites/bbs.ts +0 -253
  140. package/src/vc/cryptosuites/bbsSimple.ts +0 -21
  141. package/src/vc/cryptosuites/eddsa.ts +0 -99
  142. package/src/vc/documentLoader.ts +0 -81
  143. package/src/vc/proofs/data-integrity.ts +0 -33
  144. package/src/vc/utils/jsonld.ts +0 -18
@@ -1,132 +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
- const exhaustiveCheck: never = network;
25
- throw new Error(`Unsupported network: ${String(exhaustiveCheck)}`);
26
- }
27
- }
28
- };
29
-
30
- /**
31
- * Validates a Bitcoin address format and checksum for the given network.
32
- *
33
- * This function uses bitcoinjs-lib's address.toOutputScript() which performs:
34
- * - Format validation (bech32, base58check)
35
- * - Checksum verification
36
- * - Network prefix validation
37
- *
38
- * @param address - The Bitcoin address to validate
39
- * @param network - The network to validate against ('mainnet', 'regtest', 'signet')
40
- * @returns true if the address is valid for the network
41
- * @throws Error with descriptive message if validation fails
42
- *
43
- * @example
44
- * ```typescript
45
- * // Valid mainnet address
46
- * validateBitcoinAddress('bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq', 'mainnet'); // true
47
- *
48
- * // Invalid checksum
49
- * validateBitcoinAddress('bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdd', 'mainnet'); // throws
50
- *
51
- * // Wrong network
52
- * validateBitcoinAddress('bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq', 'testnet'); // throws
53
- * ```
54
- */
55
- export function validateBitcoinAddress(address: string, network: BitcoinNetwork): boolean {
56
- // Input validation
57
- if (!address || typeof address !== 'string') {
58
- throw new Error('Address must be a non-empty string');
59
- }
60
-
61
- const trimmedAddress = address.trim();
62
-
63
- if (trimmedAddress.length === 0) {
64
- throw new Error('Address cannot be empty');
65
- }
66
-
67
- // Check for mock/test addresses that should not be allowed in production
68
- if (/^(mock-|test-)/i.test(trimmedAddress)) {
69
- throw new Error('Mock or test addresses are not valid Bitcoin addresses');
70
- }
71
-
72
- // Validate address length (Bitcoin addresses are typically 26-90 characters)
73
- if (trimmedAddress.length < 26 || trimmedAddress.length > 90) {
74
- throw new Error(`Invalid address length: ${trimmedAddress.length} characters (expected 26-90)`);
75
- }
76
-
77
- try {
78
- // Get the appropriate network configuration
79
- const networkConfig = getNetwork(network);
80
-
81
- // Use bitcoinjs-lib to validate the address format and checksum
82
- // This will throw if the address is invalid
83
- bitcoin.address.toOutputScript(trimmedAddress, networkConfig);
84
-
85
- return true;
86
- } catch (error) {
87
- // For regtest, also try testnet network as many tools use testnet addresses for regtest
88
- if (network === 'regtest') {
89
- try {
90
- bitcoin.address.toOutputScript(trimmedAddress, bitcoin.networks.testnet);
91
- return true;
92
- } catch {
93
- // Fall through to error handling below
94
- }
95
- }
96
-
97
- // Parse the error to provide more specific feedback
98
- const errorMessage = error instanceof Error ? error.message : String(error);
99
-
100
- // Check for common error patterns and provide helpful messages
101
- if (errorMessage.includes('Invalid checksum') || errorMessage.includes('checksum')) {
102
- throw new Error(`Invalid Bitcoin address checksum for address: ${trimmedAddress}`);
103
- }
104
-
105
- if (errorMessage.includes('Invalid prefix') || errorMessage.includes('prefix')) {
106
- throw new Error(`Invalid address prefix for ${network} network: ${trimmedAddress}`);
107
- }
108
-
109
- if (errorMessage.includes('too short') || errorMessage.includes('too long')) {
110
- throw new Error(`Invalid address length for ${network}: ${trimmedAddress}`);
111
- }
112
-
113
- // Generic invalid address error
114
- throw new Error(`Invalid Bitcoin address for ${network} network: ${trimmedAddress} (${errorMessage})`);
115
- }
116
- }
117
-
118
- /**
119
- * Validates a Bitcoin address and returns a boolean instead of throwing
120
- *
121
- * @param address - The Bitcoin address to validate
122
- * @param network - The network to validate against
123
- * @returns true if valid, false otherwise
124
- */
125
- export function isValidBitcoinAddress(address: string, network: BitcoinNetwork): boolean {
126
- try {
127
- validateBitcoinAddress(address, network);
128
- return true;
129
- } catch {
130
- return false;
131
- }
132
- }
package/src/utils/cbor.ts DELETED
@@ -1,31 +0,0 @@
1
- import * as cbor from 'cbor-js';
2
-
3
- interface CborModule {
4
- encode: (input: unknown) => ArrayBuffer;
5
- decode: (buffer: ArrayBuffer) => unknown;
6
- }
7
-
8
- export function encode(input: unknown): Uint8Array {
9
- const cborTyped = cbor as unknown as CborModule;
10
- const encoded = cborTyped.encode(input);
11
- return new Uint8Array(encoded);
12
- }
13
-
14
- export function decode<T = unknown>(bytes: Uint8Array | ArrayBuffer | Buffer): T {
15
- const cborTyped = cbor as unknown as CborModule;
16
- let arrayBuffer: ArrayBuffer;
17
- if (bytes instanceof ArrayBuffer) {
18
- arrayBuffer = bytes;
19
- } else if (bytes instanceof Uint8Array) {
20
- arrayBuffer = bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength) as ArrayBuffer;
21
- } else {
22
- // Buffer - explicitly handle Buffer type
23
- const bufferInstance = bytes as Buffer;
24
- arrayBuffer = bufferInstance.buffer.slice(
25
- bufferInstance.byteOffset,
26
- bufferInstance.byteOffset + bufferInstance.byteLength
27
- ) as ArrayBuffer;
28
- }
29
- return cborTyped.decode(arrayBuffer) as T;
30
- }
31
-
@@ -1,135 +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: string | Uint8Array): string => {
54
- return Buffer.from(unencoded || '').toString('base64');
55
- },
56
- decode: (encoded: string): 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: string | Uint8Array): string => {
72
- const encoded = base64.encode(unencoded);
73
- return encoded.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, '');
74
- },
75
- decode: (encoded: string): Uint8Array => {
76
- let padded = encoded.replace(/-/g, '+').replace(/_/g, '/');
77
- while (padded.length % 4) padded += '=';
78
- return base64.decode(padded);
79
- }
80
- };
81
-
82
- // Type assertion for b58 library which doesn't have proper types
83
- interface B58Module {
84
- encode: (unencoded: Uint8Array) => string;
85
- decode: (encoded: string) => Uint8Array;
86
- }
87
-
88
- const b58Typed = b58 as unknown as B58Module;
89
-
90
- export const base58 = {
91
- encode: (unencoded: Uint8Array): string => {
92
- return b58Typed.encode(unencoded);
93
- },
94
- decode: (encoded: string): Uint8Array => {
95
- return b58Typed.decode(encoded);
96
- }
97
- };
98
-
99
- export const multibase = {
100
- encode: (val: Uint8Array, encoding: 'base58btc' | 'base64url'): string => {
101
- if (encoding === 'base58btc') {
102
- const baseEncoded = base58.encode(val);
103
- return MULTIBASE_BASE58BTC_HEADER + baseEncoded;
104
- } else if (encoding === 'base64url') {
105
- return MULTIBASE_BASE64URL_HEADER + base64url.encode(val);
106
- }
107
- throw new Error('Invalid multibase encoding.');
108
- },
109
- decode: (val: string): Uint8Array => {
110
- if (val.startsWith(MULTIBASE_BASE58BTC_HEADER)) {
111
- return base58.decode(val.substring(1));
112
- } else if (val.startsWith(MULTIBASE_BASE64URL_HEADER)) {
113
- return base64url.decode(val.substring(1));
114
- }
115
- throw new Error('Multibase value does not have expected header.');
116
- }
117
- };
118
-
119
- export const multikey = {
120
- encode: (header: Uint8Array, val: Uint8Array): string => {
121
- const mcBytes = new Uint8Array(header.length + val.length);
122
- mcBytes.set(header);
123
- mcBytes.set(val, header.length);
124
- return multibase.encode(mcBytes, 'base58btc');
125
- },
126
- decode: (header: Uint8Array, val: string): Uint8Array => {
127
- const mcValue = multibase.decode(val);
128
- for (let i = 0; i < header.length; i++) {
129
- if (mcValue[i] !== header[i]) {
130
- throw new Error('Multikey value does not have expected header.');
131
- }
132
- }
133
- return mcValue.slice(header.length);
134
- }
135
- }
package/src/utils/hash.ts DELETED
@@ -1,12 +0,0 @@
1
- export async function sha256Bytes(input: string | Uint8Array): Promise<Uint8Array> {
2
- const data = typeof input === 'string' ? new TextEncoder().encode(input) : input;
3
- // Type assertion for subtle crypto which exists in modern environments
4
- const subtle = globalThis.crypto?.subtle as SubtleCrypto | undefined;
5
- if (!subtle) {
6
- throw new Error('SubtleCrypto not available in this environment');
7
- }
8
- // Use type assertion to handle Uint8Array<ArrayBufferLike> compatibility with SubtleCrypto
9
- const digest = await subtle.digest('SHA-256', data as unknown as ArrayBuffer);
10
- return new Uint8Array(digest);
11
- }
12
-
@@ -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 Partial<Required<RetryOptions>> };
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,102 +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: unknown;
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, unknown> = {
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 = (url: string) => {
40
- const preloaded = PRELOADED_CONTEXTS[url];
41
- if (preloaded) {
42
- return Promise.resolve({ documentUrl: url, document: preloaded, contextUrl: null });
43
- }
44
- return Promise.reject(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: unknown = 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: unknown = 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: unknown,
79
- options: { documentLoader?: DocumentLoader } = {}
80
- ): Promise<string> {
81
- try {
82
- // Type assertion needed due to jsonld library's loose typing
83
- interface JsonLdModule {
84
- canonize: (doc: unknown, options: Record<string, unknown>) => Promise<string>;
85
- }
86
- const jsonldTyped = jsonld as unknown as JsonLdModule;
87
- const result = await jsonldTyped.canonize(doc, {
88
- algorithm: 'URDNA2015',
89
- format: 'application/n-quads',
90
- documentLoader: options.documentLoader ?? defaultDocumentLoader,
91
- useNative: false,
92
- rdfDirection: 'i18n-datatype',
93
- safe: false // Disable safe mode to allow custom contexts
94
- });
95
- return result;
96
- } catch (error: unknown) {
97
- const message = error instanceof Error ? error.message : String(error);
98
- throw new Error(`Failed to canonicalize document: ${message}`);
99
- }
100
- }
101
-
102
-