@originals/sdk 1.5.0 → 1.6.1

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 (105) hide show
  1. package/dist/adapters/FeeOracleMock.js +2 -2
  2. package/dist/bitcoin/OrdinalsClient.d.ts +1 -1
  3. package/dist/bitcoin/OrdinalsClient.js +10 -8
  4. package/dist/bitcoin/PSBTBuilder.js +1 -1
  5. package/dist/bitcoin/utxo-selection.js +2 -2
  6. package/dist/cel/ExternalReferenceManager.d.ts +57 -0
  7. package/dist/cel/ExternalReferenceManager.js +73 -0
  8. package/dist/cel/OriginalsCel.d.ts +245 -0
  9. package/dist/cel/OriginalsCel.js +349 -0
  10. package/dist/cel/algorithms/createEventLog.d.ts +32 -0
  11. package/dist/cel/algorithms/createEventLog.js +56 -0
  12. package/dist/cel/algorithms/deactivateEventLog.d.ts +35 -0
  13. package/dist/cel/algorithms/deactivateEventLog.js +91 -0
  14. package/dist/cel/algorithms/index.d.ts +10 -0
  15. package/dist/cel/algorithms/index.js +10 -0
  16. package/dist/cel/algorithms/updateEventLog.d.ts +34 -0
  17. package/dist/cel/algorithms/updateEventLog.js +82 -0
  18. package/dist/cel/algorithms/verifyEventLog.d.ts +45 -0
  19. package/dist/cel/algorithms/verifyEventLog.js +255 -0
  20. package/dist/cel/algorithms/witnessEvent.d.ts +29 -0
  21. package/dist/cel/algorithms/witnessEvent.js +75 -0
  22. package/dist/cel/cli/create.d.ts +36 -0
  23. package/dist/cel/cli/create.js +282 -0
  24. package/dist/cel/cli/index.d.ts +11 -0
  25. package/dist/cel/cli/index.js +351 -0
  26. package/dist/cel/cli/inspect.d.ts +30 -0
  27. package/dist/cel/cli/inspect.js +475 -0
  28. package/dist/cel/cli/migrate.d.ts +41 -0
  29. package/dist/cel/cli/migrate.js +405 -0
  30. package/dist/cel/cli/verify.d.ts +31 -0
  31. package/dist/cel/cli/verify.js +205 -0
  32. package/dist/cel/hash.d.ts +46 -0
  33. package/dist/cel/hash.js +66 -0
  34. package/dist/cel/index.d.ts +15 -0
  35. package/dist/cel/index.js +15 -0
  36. package/dist/cel/layers/BtcoCelManager.d.ts +121 -0
  37. package/dist/cel/layers/BtcoCelManager.js +329 -0
  38. package/dist/cel/layers/PeerCelManager.d.ts +151 -0
  39. package/dist/cel/layers/PeerCelManager.js +299 -0
  40. package/dist/cel/layers/WebVHCelManager.d.ts +122 -0
  41. package/dist/cel/layers/WebVHCelManager.js +291 -0
  42. package/dist/cel/layers/index.d.ts +13 -0
  43. package/dist/cel/layers/index.js +16 -0
  44. package/dist/cel/serialization/cbor.d.ts +42 -0
  45. package/dist/cel/serialization/cbor.js +163 -0
  46. package/dist/cel/serialization/index.d.ts +9 -0
  47. package/dist/cel/serialization/index.js +9 -0
  48. package/dist/cel/serialization/json.d.ts +41 -0
  49. package/dist/cel/serialization/json.js +180 -0
  50. package/dist/cel/types.d.ts +149 -0
  51. package/dist/cel/types.js +7 -0
  52. package/dist/cel/witnesses/BitcoinWitness.d.ts +83 -0
  53. package/dist/cel/witnesses/BitcoinWitness.js +116 -0
  54. package/dist/cel/witnesses/HttpWitness.d.ts +79 -0
  55. package/dist/cel/witnesses/HttpWitness.js +163 -0
  56. package/dist/cel/witnesses/WitnessService.d.ts +49 -0
  57. package/dist/cel/witnesses/WitnessService.js +10 -0
  58. package/dist/cel/witnesses/index.d.ts +10 -0
  59. package/dist/cel/witnesses/index.js +7 -0
  60. package/dist/core/OriginalsSDK.js +5 -1
  61. package/dist/crypto/Signer.js +14 -6
  62. package/dist/crypto/noble-init.js +20 -1
  63. package/dist/did/BtcoDidResolver.d.ts +2 -2
  64. package/dist/did/BtcoDidResolver.js +12 -8
  65. package/dist/did/DIDManager.js +6 -4
  66. package/dist/did/KeyManager.d.ts +1 -1
  67. package/dist/did/KeyManager.js +7 -4
  68. package/dist/did/WebVHManager.js +1 -1
  69. package/dist/did/createBtcoDidDocument.js +2 -1
  70. package/dist/events/types.d.ts +4 -1
  71. package/dist/examples/create-module-original.js +1 -1
  72. package/dist/examples/full-lifecycle-flow.js +2 -2
  73. package/dist/index.d.ts +13 -0
  74. package/dist/index.js +12 -0
  75. package/dist/kinds/KindRegistry.js +59 -29
  76. package/dist/lifecycle/BatchOperations.d.ts +5 -3
  77. package/dist/lifecycle/BatchOperations.js +11 -5
  78. package/dist/lifecycle/LifecycleManager.d.ts +1 -1
  79. package/dist/lifecycle/LifecycleManager.js +42 -33
  80. package/dist/lifecycle/OriginalsAsset.js +2 -2
  81. package/dist/migration/MigrationManager.js +67 -3
  82. package/dist/storage/LocalStorageAdapter.js +4 -1
  83. package/dist/storage/MemoryStorageAdapter.js +7 -7
  84. package/dist/types/network.js +6 -3
  85. package/dist/utils/Logger.d.ts +6 -6
  86. package/dist/utils/Logger.js +5 -3
  87. package/dist/utils/MetricsCollector.js +1 -1
  88. package/dist/utils/bitcoin-address.js +4 -2
  89. package/dist/utils/cbor.js +16 -3
  90. package/dist/utils/encoding.d.ts +4 -4
  91. package/dist/utils/encoding.js +7 -6
  92. package/dist/utils/hash.js +6 -1
  93. package/dist/utils/serialization.d.ts +2 -2
  94. package/dist/utils/serialization.js +7 -5
  95. package/dist/utils/telemetry.js +6 -2
  96. package/dist/utils/validation.js +8 -4
  97. package/dist/vc/CredentialManager.d.ts +8 -8
  98. package/dist/vc/CredentialManager.js +46 -33
  99. package/dist/vc/Issuer.d.ts +2 -2
  100. package/dist/vc/Issuer.js +5 -1
  101. package/dist/vc/Verifier.d.ts +2 -2
  102. package/dist/vc/Verifier.js +12 -6
  103. package/dist/vc/documentLoader.d.ts +5 -3
  104. package/dist/vc/documentLoader.js +5 -4
  105. package/package.json +4 -1
@@ -0,0 +1,180 @@
1
+ /**
2
+ * JSON Serialization for CEL Event Logs
3
+ *
4
+ * Provides serialization and parsing of EventLog objects to/from JSON format.
5
+ * Uses deterministic key ordering for consistent hashes.
6
+ */
7
+ /**
8
+ * Sort object keys recursively for deterministic JSON output.
9
+ * This ensures consistent serialization for hash computations.
10
+ */
11
+ function sortKeys(obj) {
12
+ if (obj === null || obj === undefined) {
13
+ return obj;
14
+ }
15
+ if (Array.isArray(obj)) {
16
+ return obj.map(sortKeys);
17
+ }
18
+ if (typeof obj === 'object') {
19
+ const sorted = {};
20
+ const keys = Object.keys(obj).sort();
21
+ for (const key of keys) {
22
+ sorted[key] = sortKeys(obj[key]);
23
+ }
24
+ return sorted;
25
+ }
26
+ return obj;
27
+ }
28
+ /**
29
+ * Serialize an EventLog to JSON string.
30
+ *
31
+ * Uses deterministic key ordering for consistent output.
32
+ *
33
+ * @param log - The EventLog to serialize
34
+ * @returns JSON string representation of the EventLog
35
+ * @throws Error if log is null or undefined
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * const log = await createEventLog(data, options);
40
+ * const json = serializeEventLogJson(log);
41
+ * console.log(json); // '{"events":[...]}'
42
+ * ```
43
+ */
44
+ export function serializeEventLogJson(log) {
45
+ if (!log) {
46
+ throw new Error('Cannot serialize null or undefined EventLog');
47
+ }
48
+ const sorted = sortKeys(log);
49
+ return JSON.stringify(sorted, null, 2);
50
+ }
51
+ /**
52
+ * Check if a proof object is a WitnessProof (has witnessedAt field)
53
+ */
54
+ function isWitnessProof(proof) {
55
+ return 'witnessedAt' in proof && typeof proof.witnessedAt === 'string';
56
+ }
57
+ /**
58
+ * Validate and reconstruct a DataIntegrityProof or WitnessProof
59
+ */
60
+ function parseProof(proof) {
61
+ if (!proof || typeof proof !== 'object') {
62
+ throw new Error('Invalid proof: must be an object');
63
+ }
64
+ const p = proof;
65
+ // Validate required DataIntegrityProof fields
66
+ if (typeof p.type !== 'string') {
67
+ throw new Error('Invalid proof: missing or invalid type');
68
+ }
69
+ if (typeof p.cryptosuite !== 'string') {
70
+ throw new Error('Invalid proof: missing or invalid cryptosuite');
71
+ }
72
+ if (typeof p.created !== 'string') {
73
+ throw new Error('Invalid proof: missing or invalid created');
74
+ }
75
+ if (typeof p.verificationMethod !== 'string') {
76
+ throw new Error('Invalid proof: missing or invalid verificationMethod');
77
+ }
78
+ if (typeof p.proofPurpose !== 'string') {
79
+ throw new Error('Invalid proof: missing or invalid proofPurpose');
80
+ }
81
+ if (typeof p.proofValue !== 'string') {
82
+ throw new Error('Invalid proof: missing or invalid proofValue');
83
+ }
84
+ const baseProof = {
85
+ type: p.type,
86
+ cryptosuite: p.cryptosuite,
87
+ created: p.created,
88
+ verificationMethod: p.verificationMethod,
89
+ proofPurpose: p.proofPurpose,
90
+ proofValue: p.proofValue,
91
+ };
92
+ // Check for WitnessProof
93
+ if ('witnessedAt' in p) {
94
+ if (typeof p.witnessedAt !== 'string') {
95
+ throw new Error('Invalid witness proof: witnessedAt must be a string');
96
+ }
97
+ return {
98
+ ...baseProof,
99
+ witnessedAt: p.witnessedAt,
100
+ };
101
+ }
102
+ return baseProof;
103
+ }
104
+ /**
105
+ * Validate and reconstruct a LogEntry
106
+ */
107
+ function parseEntry(entry) {
108
+ if (!entry || typeof entry !== 'object') {
109
+ throw new Error('Invalid entry: must be an object');
110
+ }
111
+ const e = entry;
112
+ // Validate type
113
+ if (e.type !== 'create' && e.type !== 'update' && e.type !== 'deactivate') {
114
+ throw new Error(`Invalid entry type: ${e.type}`);
115
+ }
116
+ // Validate proof array
117
+ if (!Array.isArray(e.proof)) {
118
+ throw new Error('Invalid entry: proof must be an array');
119
+ }
120
+ const parsedEntry = {
121
+ type: e.type,
122
+ data: e.data,
123
+ proof: e.proof.map(parseProof),
124
+ };
125
+ // Optional previousEvent
126
+ if (e.previousEvent !== undefined) {
127
+ if (typeof e.previousEvent !== 'string') {
128
+ throw new Error('Invalid entry: previousEvent must be a string');
129
+ }
130
+ parsedEntry.previousEvent = e.previousEvent;
131
+ }
132
+ return parsedEntry;
133
+ }
134
+ /**
135
+ * Parse a JSON string into an EventLog.
136
+ *
137
+ * Validates the structure and types of the parsed object.
138
+ *
139
+ * @param json - JSON string to parse
140
+ * @returns Parsed and validated EventLog
141
+ * @throws Error if JSON is invalid or doesn't match EventLog structure
142
+ *
143
+ * @example
144
+ * ```typescript
145
+ * const json = '{"events":[...]}';
146
+ * const log = parseEventLogJson(json);
147
+ * console.log(log.events.length);
148
+ * ```
149
+ */
150
+ export function parseEventLogJson(json) {
151
+ if (!json || typeof json !== 'string') {
152
+ throw new Error('Cannot parse null, undefined, or non-string value');
153
+ }
154
+ let parsed;
155
+ try {
156
+ parsed = JSON.parse(json);
157
+ }
158
+ catch (e) {
159
+ throw new Error(`Invalid JSON: ${e.message}`);
160
+ }
161
+ if (!parsed || typeof parsed !== 'object') {
162
+ throw new Error('Invalid EventLog: must be an object');
163
+ }
164
+ const obj = parsed;
165
+ // Validate events array
166
+ if (!Array.isArray(obj.events)) {
167
+ throw new Error('Invalid EventLog: events must be an array');
168
+ }
169
+ const eventLog = {
170
+ events: obj.events.map(parseEntry),
171
+ };
172
+ // Optional previousLog
173
+ if (obj.previousLog !== undefined) {
174
+ if (typeof obj.previousLog !== 'string') {
175
+ throw new Error('Invalid EventLog: previousLog must be a string');
176
+ }
177
+ eventLog.previousLog = obj.previousLog;
178
+ }
179
+ return eventLog;
180
+ }
@@ -0,0 +1,149 @@
1
+ /**
2
+ * CEL (Cryptographic Event Log) Types
3
+ *
4
+ * Based on W3C CCG CEL Specification v0.1
5
+ * @see https://w3c-ccg.github.io/cel-spec/
6
+ */
7
+ /**
8
+ * Data Integrity Proof as defined in W3C Data Integrity spec
9
+ * Used for signing events and witness attestations
10
+ */
11
+ export interface DataIntegrityProof {
12
+ /** The type of proof (e.g., "DataIntegrityProof") */
13
+ type: string;
14
+ /** The cryptosuite used (e.g., "eddsa-jcs-2022") */
15
+ cryptosuite: string;
16
+ /** ISO 8601 timestamp when the proof was created */
17
+ created: string;
18
+ /** DID URL of the verification method used to create the proof */
19
+ verificationMethod: string;
20
+ /** The purpose of the proof (e.g., "assertionMethod") */
21
+ proofPurpose: string;
22
+ /** The multibase-encoded proof value */
23
+ proofValue: string;
24
+ }
25
+ /**
26
+ * Witness Proof - extends DataIntegrityProof with witness-specific fields
27
+ * Used when a third party attests to the existence of an event at a point in time
28
+ */
29
+ export interface WitnessProof extends DataIntegrityProof {
30
+ /** ISO 8601 timestamp when the witness attested to the event */
31
+ witnessedAt: string;
32
+ }
33
+ /**
34
+ * External Reference - points to data outside the event log
35
+ * Used for large resources that shouldn't be embedded in the log
36
+ */
37
+ export interface ExternalReference {
38
+ /** Optional URLs where the data can be retrieved */
39
+ url?: string[];
40
+ /** Optional MIME type of the data */
41
+ mediaType?: string;
42
+ /** Required Multibase-encoded (base64url-nopad) Multihash (sha2-256) of the data */
43
+ digestMultibase: string;
44
+ }
45
+ /**
46
+ * Event type for log entries
47
+ */
48
+ export type EventType = 'create' | 'update' | 'deactivate';
49
+ /**
50
+ * Log Entry - a single event in the cryptographic event log
51
+ * Contains the event data, proof(s), and chain reference
52
+ */
53
+ export interface LogEntry {
54
+ /** The type of event */
55
+ type: EventType;
56
+ /** The event data (schema varies by event type) */
57
+ data: unknown;
58
+ /** Multibase-encoded hash of the previous event (omitted for first event) */
59
+ previousEvent?: string;
60
+ /** One or more proofs attesting to this event (controller proof + optional witness proofs) */
61
+ proof: (DataIntegrityProof | WitnessProof)[];
62
+ }
63
+ /**
64
+ * Event Log - the complete cryptographic event log
65
+ * Contains a list of hash-chained events with optional chunking support
66
+ */
67
+ export interface EventLog {
68
+ /** The list of events in chronological order */
69
+ events: LogEntry[];
70
+ /** Optional reference to a previous log file (for chunking long histories) */
71
+ previousLog?: string;
72
+ }
73
+ /**
74
+ * Verification result for a single event
75
+ */
76
+ export interface EventVerification {
77
+ /** Index of the event in the log */
78
+ index: number;
79
+ /** The event type */
80
+ type: EventType;
81
+ /** Whether the event's proofs are valid */
82
+ proofValid: boolean;
83
+ /** Whether the hash chain link is valid (previousEvent matches) */
84
+ chainValid: boolean;
85
+ /** Any errors encountered during verification */
86
+ errors: string[];
87
+ }
88
+ /**
89
+ * Result of verifying an entire event log
90
+ */
91
+ export interface VerificationResult {
92
+ /** Whether the entire log is valid */
93
+ verified: boolean;
94
+ /** List of errors encountered */
95
+ errors: string[];
96
+ /** Per-event verification details */
97
+ events: EventVerification[];
98
+ }
99
+ /**
100
+ * Options for creating a new event log
101
+ */
102
+ export interface CreateOptions {
103
+ /** Signer function that produces a proof */
104
+ signer: (data: unknown) => Promise<DataIntegrityProof>;
105
+ /** The verification method DID URL */
106
+ verificationMethod: string;
107
+ /** The proof purpose (defaults to "assertionMethod") */
108
+ proofPurpose?: string;
109
+ }
110
+ /**
111
+ * Options for updating an event log
112
+ */
113
+ export interface UpdateOptions extends CreateOptions {
114
+ }
115
+ /**
116
+ * Options for deactivating an event log
117
+ */
118
+ export interface DeactivateOptions extends CreateOptions {
119
+ }
120
+ /**
121
+ * Options for verifying an event log
122
+ */
123
+ export interface VerifyOptions {
124
+ /** Optional custom proof verifier */
125
+ verifier?: (proof: DataIntegrityProof, data: unknown) => Promise<boolean>;
126
+ }
127
+ /**
128
+ * Asset state derived from replaying event log
129
+ */
130
+ export interface AssetState {
131
+ /** Current DID of the asset */
132
+ did: string;
133
+ /** Asset name */
134
+ name?: string;
135
+ /** Current layer (peer, webvh, btco) */
136
+ layer: 'peer' | 'webvh' | 'btco';
137
+ /** External resources associated with the asset */
138
+ resources: ExternalReference[];
139
+ /** Creator DID */
140
+ creator?: string;
141
+ /** Creation timestamp */
142
+ createdAt?: string;
143
+ /** Last update timestamp */
144
+ updatedAt?: string;
145
+ /** Whether the asset has been deactivated */
146
+ deactivated: boolean;
147
+ /** Custom metadata */
148
+ metadata?: Record<string, unknown>;
149
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * CEL (Cryptographic Event Log) Types
3
+ *
4
+ * Based on W3C CCG CEL Specification v0.1
5
+ * @see https://w3c-ccg.github.io/cel-spec/
6
+ */
7
+ export {};
@@ -0,0 +1,83 @@
1
+ /**
2
+ * BitcoinWitness - Bitcoin-based witness service for CEL event logs
3
+ *
4
+ * Implements the WitnessService interface using Bitcoin ordinals inscriptions.
5
+ * Used for the did:btco layer to anchor events on the Bitcoin blockchain,
6
+ * providing the highest level of immutability and timestamping.
7
+ *
8
+ * @see https://w3c-ccg.github.io/cel-spec/
9
+ */
10
+ import type { WitnessProof } from '../types';
11
+ import type { WitnessService } from './WitnessService';
12
+ import type { BitcoinManager } from '../../bitcoin/BitcoinManager';
13
+ /**
14
+ * Configuration options for BitcoinWitness
15
+ */
16
+ export interface BitcoinWitnessOptions {
17
+ /** Fee rate in sat/vB for inscription transactions (optional - BitcoinManager will estimate if not provided) */
18
+ feeRate?: number;
19
+ /** Verification method DID URL for the witness proof */
20
+ verificationMethod?: string;
21
+ }
22
+ /**
23
+ * Error thrown when the Bitcoin witness service fails
24
+ */
25
+ export declare class BitcoinWitnessError extends Error {
26
+ /** The digest that failed to be witnessed */
27
+ readonly digest?: string;
28
+ /** The underlying error message if available */
29
+ readonly cause?: Error;
30
+ constructor(message: string, digest?: string, cause?: Error);
31
+ }
32
+ /**
33
+ * Bitcoin inscription witness proof with additional Bitcoin-specific fields
34
+ */
35
+ export interface BitcoinWitnessProof extends WitnessProof {
36
+ /** The Bitcoin transaction ID containing the witness inscription */
37
+ txid: string;
38
+ /** The block height where the inscription was confirmed (if available) */
39
+ blockHeight?: number;
40
+ /** The satoshi ordinal number anchoring the inscription */
41
+ satoshi: string;
42
+ /** The inscription ID in the format {txid}i{index} */
43
+ inscriptionId: string;
44
+ }
45
+ /**
46
+ * Bitcoin-based witness service implementation
47
+ *
48
+ * Inscribes digestMultibase on Bitcoin via ordinals and returns a WitnessProof
49
+ * containing the transaction details and satoshi ordinal as anchor.
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * const bitcoinManager = new BitcoinManager(config);
54
+ * const witness = new BitcoinWitness(bitcoinManager);
55
+ * const proof = await witness.witness('uEiD...');
56
+ * console.log(proof.txid); // Bitcoin transaction ID
57
+ * console.log(proof.satoshi); // Satoshi ordinal anchor
58
+ * ```
59
+ */
60
+ export declare class BitcoinWitness implements WitnessService {
61
+ private readonly bitcoinManager;
62
+ private readonly feeRate?;
63
+ private readonly verificationMethod;
64
+ /**
65
+ * Creates a new BitcoinWitness instance
66
+ *
67
+ * @param bitcoinManager - BitcoinManager instance configured with an ordinals provider
68
+ * @param options - Optional configuration options
69
+ */
70
+ constructor(bitcoinManager: BitcoinManager, options?: BitcoinWitnessOptions);
71
+ /**
72
+ * Witnesses a digest by inscribing it on the Bitcoin blockchain
73
+ *
74
+ * @param digestMultibase - The Multibase-encoded digest to witness
75
+ * @returns A BitcoinWitnessProof containing the inscription details and witnessedAt timestamp
76
+ * @throws BitcoinWitnessError if the inscription fails
77
+ */
78
+ witness(digestMultibase: string): Promise<BitcoinWitnessProof>;
79
+ /**
80
+ * Gets the fee rate configured for this witness (if any)
81
+ */
82
+ get configuredFeeRate(): number | undefined;
83
+ }
@@ -0,0 +1,116 @@
1
+ /**
2
+ * BitcoinWitness - Bitcoin-based witness service for CEL event logs
3
+ *
4
+ * Implements the WitnessService interface using Bitcoin ordinals inscriptions.
5
+ * Used for the did:btco layer to anchor events on the Bitcoin blockchain,
6
+ * providing the highest level of immutability and timestamping.
7
+ *
8
+ * @see https://w3c-ccg.github.io/cel-spec/
9
+ */
10
+ /**
11
+ * Error thrown when the Bitcoin witness service fails
12
+ */
13
+ export class BitcoinWitnessError extends Error {
14
+ constructor(message, digest, cause) {
15
+ super(message);
16
+ this.name = 'BitcoinWitnessError';
17
+ this.digest = digest;
18
+ this.cause = cause;
19
+ }
20
+ }
21
+ /**
22
+ * Bitcoin-based witness service implementation
23
+ *
24
+ * Inscribes digestMultibase on Bitcoin via ordinals and returns a WitnessProof
25
+ * containing the transaction details and satoshi ordinal as anchor.
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * const bitcoinManager = new BitcoinManager(config);
30
+ * const witness = new BitcoinWitness(bitcoinManager);
31
+ * const proof = await witness.witness('uEiD...');
32
+ * console.log(proof.txid); // Bitcoin transaction ID
33
+ * console.log(proof.satoshi); // Satoshi ordinal anchor
34
+ * ```
35
+ */
36
+ export class BitcoinWitness {
37
+ /**
38
+ * Creates a new BitcoinWitness instance
39
+ *
40
+ * @param bitcoinManager - BitcoinManager instance configured with an ordinals provider
41
+ * @param options - Optional configuration options
42
+ */
43
+ constructor(bitcoinManager, options = {}) {
44
+ if (!bitcoinManager) {
45
+ throw new Error('BitcoinManager instance is required');
46
+ }
47
+ this.bitcoinManager = bitcoinManager;
48
+ this.feeRate = options.feeRate;
49
+ this.verificationMethod = options.verificationMethod ?? 'did:btco:witness';
50
+ }
51
+ /**
52
+ * Witnesses a digest by inscribing it on the Bitcoin blockchain
53
+ *
54
+ * @param digestMultibase - The Multibase-encoded digest to witness
55
+ * @returns A BitcoinWitnessProof containing the inscription details and witnessedAt timestamp
56
+ * @throws BitcoinWitnessError if the inscription fails
57
+ */
58
+ async witness(digestMultibase) {
59
+ if (!digestMultibase || typeof digestMultibase !== 'string') {
60
+ throw new BitcoinWitnessError('digestMultibase must be a non-empty string', digestMultibase);
61
+ }
62
+ // Validate multibase prefix (should start with 'u' for base64url-nopad or 'z' for base58btc)
63
+ const validPrefixes = ['u', 'z'];
64
+ if (!validPrefixes.includes(digestMultibase[0])) {
65
+ throw new BitcoinWitnessError(`Invalid digestMultibase encoding: expected prefix 'u' or 'z', got '${digestMultibase[0]}'`, digestMultibase);
66
+ }
67
+ try {
68
+ // Create witness attestation data
69
+ const witnessData = {
70
+ '@context': 'https://w3id.org/cel/v1',
71
+ type: 'BitcoinWitnessAttestation',
72
+ digestMultibase,
73
+ witnessedAt: new Date().toISOString(),
74
+ };
75
+ // Inscribe the witness data on Bitcoin
76
+ const inscription = await this.bitcoinManager.inscribeData(witnessData, 'application/json', this.feeRate);
77
+ // Validate inscription result
78
+ if (!inscription.inscriptionId) {
79
+ throw new BitcoinWitnessError('Bitcoin inscription did not return a valid inscription ID', digestMultibase);
80
+ }
81
+ if (!inscription.txid) {
82
+ throw new BitcoinWitnessError('Bitcoin inscription did not return a transaction ID', digestMultibase);
83
+ }
84
+ const now = new Date().toISOString();
85
+ // Build the WitnessProof with Bitcoin-specific extensions
86
+ const proof = {
87
+ type: 'DataIntegrityProof',
88
+ cryptosuite: 'bitcoin-ordinals-2024',
89
+ created: now,
90
+ verificationMethod: this.verificationMethod,
91
+ proofPurpose: 'assertionMethod',
92
+ proofValue: `z${inscription.inscriptionId}`, // Use inscription ID as proof value with multibase prefix
93
+ witnessedAt: now,
94
+ txid: inscription.txid,
95
+ blockHeight: inscription.blockHeight,
96
+ satoshi: inscription.satoshi,
97
+ inscriptionId: inscription.inscriptionId,
98
+ };
99
+ return proof;
100
+ }
101
+ catch (error) {
102
+ // Re-throw BitcoinWitnessError as-is
103
+ if (error instanceof BitcoinWitnessError) {
104
+ throw error;
105
+ }
106
+ // Wrap other errors
107
+ throw new BitcoinWitnessError(`Failed to inscribe witness on Bitcoin: ${error instanceof Error ? error.message : String(error)}`, digestMultibase, error instanceof Error ? error : undefined);
108
+ }
109
+ }
110
+ /**
111
+ * Gets the fee rate configured for this witness (if any)
112
+ */
113
+ get configuredFeeRate() {
114
+ return this.feeRate;
115
+ }
116
+ }
@@ -0,0 +1,79 @@
1
+ /**
2
+ * HttpWitness - HTTP-based witness service for CEL event logs
3
+ *
4
+ * Implements the WitnessService interface for HTTP-based witness endpoints.
5
+ * Used primarily for the did:webvh layer to obtain third-party attestations
6
+ * from remote witness services.
7
+ *
8
+ * @see https://w3c-ccg.github.io/cel-spec/
9
+ */
10
+ import type { WitnessProof } from '../types';
11
+ import type { WitnessService } from './WitnessService';
12
+ /**
13
+ * Configuration options for HttpWitness
14
+ */
15
+ export interface HttpWitnessOptions {
16
+ /** Request timeout in milliseconds (default: 30000) */
17
+ timeout?: number;
18
+ /** Custom headers to include in requests */
19
+ headers?: Record<string, string>;
20
+ /** Custom fetch implementation (for testing or alternative HTTP clients) */
21
+ fetch?: typeof globalThis.fetch;
22
+ }
23
+ /**
24
+ * Error thrown when the HTTP witness service is unavailable or returns an error
25
+ */
26
+ export declare class HttpWitnessError extends Error {
27
+ /** HTTP status code if available */
28
+ readonly statusCode?: number;
29
+ /** Response body if available */
30
+ readonly responseBody?: string;
31
+ /** The witness URL that failed */
32
+ readonly witnessUrl: string;
33
+ constructor(message: string, witnessUrl: string, statusCode?: number, responseBody?: string);
34
+ }
35
+ /**
36
+ * HTTP-based witness service implementation
37
+ *
38
+ * Posts digestMultibase to a witness endpoint and parses the WitnessProof response.
39
+ *
40
+ * @example
41
+ * ```typescript
42
+ * const witness = new HttpWitness('https://witness.example.com/api/attest');
43
+ * const proof = await witness.witness('uEiD...');
44
+ * console.log(proof.witnessedAt); // ISO timestamp of attestation
45
+ * ```
46
+ */
47
+ export declare class HttpWitness implements WitnessService {
48
+ private readonly witnessUrl;
49
+ private readonly timeout;
50
+ private readonly headers;
51
+ private readonly fetchFn;
52
+ /**
53
+ * Creates a new HttpWitness instance
54
+ *
55
+ * @param witnessUrl - The URL of the witness endpoint to POST to
56
+ * @param options - Optional configuration options
57
+ */
58
+ constructor(witnessUrl: string, options?: HttpWitnessOptions);
59
+ /**
60
+ * Witnesses a digest by posting to the HTTP endpoint
61
+ *
62
+ * @param digestMultibase - The Multibase-encoded digest to witness
63
+ * @returns A WitnessProof containing the attestation and witnessedAt timestamp
64
+ * @throws HttpWitnessError if the witness service is unavailable or returns an error
65
+ */
66
+ witness(digestMultibase: string): Promise<WitnessProof>;
67
+ /**
68
+ * Validates that the response data is a valid WitnessProof
69
+ *
70
+ * @param data - The parsed JSON response
71
+ * @returns A validated WitnessProof
72
+ * @throws HttpWitnessError if the response is not a valid WitnessProof
73
+ */
74
+ private validateWitnessProof;
75
+ /**
76
+ * Gets the witness URL this instance is configured to use
77
+ */
78
+ get url(): string;
79
+ }