@originals/sdk 1.5.0 → 1.6.0
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.
- package/dist/adapters/FeeOracleMock.js +2 -2
- package/dist/bitcoin/OrdinalsClient.d.ts +1 -1
- package/dist/bitcoin/OrdinalsClient.js +10 -8
- package/dist/bitcoin/PSBTBuilder.js +1 -1
- package/dist/bitcoin/utxo-selection.js +2 -2
- package/dist/cel/ExternalReferenceManager.d.ts +57 -0
- package/dist/cel/ExternalReferenceManager.js +73 -0
- package/dist/cel/OriginalsCel.d.ts +245 -0
- package/dist/cel/OriginalsCel.js +349 -0
- package/dist/cel/algorithms/createEventLog.d.ts +32 -0
- package/dist/cel/algorithms/createEventLog.js +56 -0
- package/dist/cel/algorithms/deactivateEventLog.d.ts +35 -0
- package/dist/cel/algorithms/deactivateEventLog.js +91 -0
- package/dist/cel/algorithms/index.d.ts +10 -0
- package/dist/cel/algorithms/index.js +10 -0
- package/dist/cel/algorithms/updateEventLog.d.ts +34 -0
- package/dist/cel/algorithms/updateEventLog.js +82 -0
- package/dist/cel/algorithms/verifyEventLog.d.ts +45 -0
- package/dist/cel/algorithms/verifyEventLog.js +255 -0
- package/dist/cel/algorithms/witnessEvent.d.ts +29 -0
- package/dist/cel/algorithms/witnessEvent.js +75 -0
- package/dist/cel/cli/create.d.ts +36 -0
- package/dist/cel/cli/create.js +282 -0
- package/dist/cel/cli/index.d.ts +11 -0
- package/dist/cel/cli/index.js +351 -0
- package/dist/cel/cli/inspect.d.ts +30 -0
- package/dist/cel/cli/inspect.js +475 -0
- package/dist/cel/cli/migrate.d.ts +41 -0
- package/dist/cel/cli/migrate.js +405 -0
- package/dist/cel/cli/verify.d.ts +31 -0
- package/dist/cel/cli/verify.js +205 -0
- package/dist/cel/hash.d.ts +46 -0
- package/dist/cel/hash.js +66 -0
- package/dist/cel/index.d.ts +15 -0
- package/dist/cel/index.js +15 -0
- package/dist/cel/layers/BtcoCelManager.d.ts +121 -0
- package/dist/cel/layers/BtcoCelManager.js +329 -0
- package/dist/cel/layers/PeerCelManager.d.ts +151 -0
- package/dist/cel/layers/PeerCelManager.js +299 -0
- package/dist/cel/layers/WebVHCelManager.d.ts +122 -0
- package/dist/cel/layers/WebVHCelManager.js +291 -0
- package/dist/cel/layers/index.d.ts +13 -0
- package/dist/cel/layers/index.js +16 -0
- package/dist/cel/serialization/cbor.d.ts +42 -0
- package/dist/cel/serialization/cbor.js +163 -0
- package/dist/cel/serialization/index.d.ts +9 -0
- package/dist/cel/serialization/index.js +9 -0
- package/dist/cel/serialization/json.d.ts +41 -0
- package/dist/cel/serialization/json.js +180 -0
- package/dist/cel/types.d.ts +149 -0
- package/dist/cel/types.js +7 -0
- package/dist/cel/witnesses/BitcoinWitness.d.ts +83 -0
- package/dist/cel/witnesses/BitcoinWitness.js +116 -0
- package/dist/cel/witnesses/HttpWitness.d.ts +79 -0
- package/dist/cel/witnesses/HttpWitness.js +163 -0
- package/dist/cel/witnesses/WitnessService.d.ts +49 -0
- package/dist/cel/witnesses/WitnessService.js +10 -0
- package/dist/cel/witnesses/index.d.ts +10 -0
- package/dist/cel/witnesses/index.js +7 -0
- package/dist/core/OriginalsSDK.js +5 -1
- package/dist/crypto/Signer.js +14 -6
- package/dist/crypto/noble-init.js +20 -1
- package/dist/did/BtcoDidResolver.d.ts +2 -2
- package/dist/did/BtcoDidResolver.js +12 -8
- package/dist/did/DIDManager.js +6 -4
- package/dist/did/KeyManager.d.ts +1 -1
- package/dist/did/KeyManager.js +7 -4
- package/dist/did/WebVHManager.js +1 -1
- package/dist/did/createBtcoDidDocument.js +2 -1
- package/dist/events/types.d.ts +4 -1
- package/dist/examples/create-module-original.js +1 -1
- package/dist/examples/full-lifecycle-flow.js +2 -2
- package/dist/index.d.ts +13 -0
- package/dist/index.js +12 -0
- package/dist/kinds/KindRegistry.js +59 -29
- package/dist/lifecycle/BatchOperations.d.ts +5 -3
- package/dist/lifecycle/BatchOperations.js +11 -5
- package/dist/lifecycle/LifecycleManager.d.ts +1 -1
- package/dist/lifecycle/LifecycleManager.js +42 -33
- package/dist/lifecycle/OriginalsAsset.js +2 -2
- package/dist/migration/MigrationManager.js +67 -3
- package/dist/storage/LocalStorageAdapter.js +4 -1
- package/dist/storage/MemoryStorageAdapter.js +7 -7
- package/dist/types/network.js +6 -3
- package/dist/utils/Logger.d.ts +6 -6
- package/dist/utils/Logger.js +5 -3
- package/dist/utils/MetricsCollector.js +1 -1
- package/dist/utils/bitcoin-address.js +4 -2
- package/dist/utils/cbor.js +16 -3
- package/dist/utils/encoding.d.ts +4 -4
- package/dist/utils/encoding.js +7 -6
- package/dist/utils/hash.js +6 -1
- package/dist/utils/serialization.d.ts +2 -2
- package/dist/utils/serialization.js +7 -5
- package/dist/utils/telemetry.js +6 -2
- package/dist/utils/validation.js +8 -4
- package/dist/vc/CredentialManager.d.ts +8 -8
- package/dist/vc/CredentialManager.js +46 -33
- package/dist/vc/Issuer.d.ts +2 -2
- package/dist/vc/Issuer.js +5 -1
- package/dist/vc/Verifier.d.ts +2 -2
- package/dist/vc/Verifier.js +12 -6
- package/dist/vc/documentLoader.d.ts +5 -3
- package/dist/vc/documentLoader.js +5 -4
- 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,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
|
+
}
|