@originals/sdk 1.4.5 → 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,282 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI Create Command
|
|
4
|
+
*
|
|
5
|
+
* Creates a new CEL asset with an initial event.
|
|
6
|
+
* Generates Ed25519 key pair if --key not provided.
|
|
7
|
+
*
|
|
8
|
+
* Usage: originals-cel create --name <name> --file <path> [options]
|
|
9
|
+
*/
|
|
10
|
+
import * as fs from 'fs';
|
|
11
|
+
import * as path from 'path';
|
|
12
|
+
import { PeerCelManager } from '../layers/PeerCelManager';
|
|
13
|
+
import { createExternalReference } from '../ExternalReferenceManager';
|
|
14
|
+
import { serializeEventLogJson } from '../serialization/json';
|
|
15
|
+
import { serializeEventLogCbor } from '../serialization/cbor';
|
|
16
|
+
import { multikey } from '../../crypto/Multikey';
|
|
17
|
+
/**
|
|
18
|
+
* Lookup table for common file extensions to MIME types
|
|
19
|
+
*/
|
|
20
|
+
const MIME_TYPES = {
|
|
21
|
+
'.png': 'image/png',
|
|
22
|
+
'.jpg': 'image/jpeg',
|
|
23
|
+
'.jpeg': 'image/jpeg',
|
|
24
|
+
'.gif': 'image/gif',
|
|
25
|
+
'.webp': 'image/webp',
|
|
26
|
+
'.svg': 'image/svg+xml',
|
|
27
|
+
'.pdf': 'application/pdf',
|
|
28
|
+
'.json': 'application/json',
|
|
29
|
+
'.txt': 'text/plain',
|
|
30
|
+
'.html': 'text/html',
|
|
31
|
+
'.css': 'text/css',
|
|
32
|
+
'.js': 'application/javascript',
|
|
33
|
+
'.mp3': 'audio/mpeg',
|
|
34
|
+
'.mp4': 'video/mp4',
|
|
35
|
+
'.webm': 'video/webm',
|
|
36
|
+
'.wav': 'audio/wav',
|
|
37
|
+
'.ogg': 'audio/ogg',
|
|
38
|
+
'.zip': 'application/zip',
|
|
39
|
+
'.bin': 'application/octet-stream',
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Gets MIME type from file extension
|
|
43
|
+
*/
|
|
44
|
+
function getMimeType(filePath) {
|
|
45
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
46
|
+
return MIME_TYPES[ext] || 'application/octet-stream';
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Generates an Ed25519 key pair for signing
|
|
50
|
+
*/
|
|
51
|
+
async function generateKeyPair() {
|
|
52
|
+
const ed25519 = await import('@noble/ed25519');
|
|
53
|
+
const privateKeyBytes = ed25519.utils.randomPrivateKey();
|
|
54
|
+
const publicKeyBytes = await ed25519.getPublicKeyAsync(privateKeyBytes);
|
|
55
|
+
return {
|
|
56
|
+
privateKey: multikey.encodePrivateKey(privateKeyBytes, 'Ed25519'),
|
|
57
|
+
publicKey: multikey.encodePublicKey(publicKeyBytes, 'Ed25519'),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Loads an Ed25519 private key from a file
|
|
62
|
+
* Supports both raw multibase format and JSON format { privateKey: "z..." }
|
|
63
|
+
*/
|
|
64
|
+
async function loadPrivateKey(keyPath) {
|
|
65
|
+
if (!fs.existsSync(keyPath)) {
|
|
66
|
+
throw new Error(`Key file not found: ${keyPath}`);
|
|
67
|
+
}
|
|
68
|
+
const content = fs.readFileSync(keyPath, 'utf-8').trim();
|
|
69
|
+
let privateKey;
|
|
70
|
+
// Try parsing as JSON first
|
|
71
|
+
try {
|
|
72
|
+
const parsed = JSON.parse(content);
|
|
73
|
+
if (parsed.privateKey) {
|
|
74
|
+
privateKey = parsed.privateKey;
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
throw new Error('JSON key file must contain "privateKey" field');
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch (e) {
|
|
81
|
+
// Not JSON, treat as raw multibase key
|
|
82
|
+
if (content.startsWith('z')) {
|
|
83
|
+
privateKey = content;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
throw new Error('Key file must contain a z-base58btc multibase-encoded Ed25519 private key');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Validate and decode to get public key
|
|
90
|
+
const decoded = multikey.decodePrivateKey(privateKey);
|
|
91
|
+
if (decoded.type !== 'Ed25519') {
|
|
92
|
+
throw new Error(`Expected Ed25519 key, got ${decoded.type}`);
|
|
93
|
+
}
|
|
94
|
+
// Derive public key from private key
|
|
95
|
+
const ed25519 = await import('@noble/ed25519');
|
|
96
|
+
const publicKeyBytes = await ed25519.getPublicKeyAsync(decoded.key);
|
|
97
|
+
const publicKey = multikey.encodePublicKey(publicKeyBytes, 'Ed25519');
|
|
98
|
+
return { privateKey, publicKey };
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Creates a signer function from a private key
|
|
102
|
+
*/
|
|
103
|
+
function createSigner(privateKey, publicKey) {
|
|
104
|
+
return async (data) => {
|
|
105
|
+
const ed25519 = await import('@noble/ed25519');
|
|
106
|
+
const decoded = multikey.decodePrivateKey(privateKey);
|
|
107
|
+
// Serialize data for signing (deterministic JSON)
|
|
108
|
+
const dataStr = JSON.stringify(data, Object.keys(data).sort());
|
|
109
|
+
const dataBytes = new TextEncoder().encode(dataStr);
|
|
110
|
+
// Sign the data
|
|
111
|
+
const signature = await ed25519.signAsync(dataBytes, decoded.key);
|
|
112
|
+
const proofValue = multikey.encodeMultibase(new Uint8Array(signature));
|
|
113
|
+
return {
|
|
114
|
+
type: 'DataIntegrityProof',
|
|
115
|
+
cryptosuite: 'eddsa-jcs-2022',
|
|
116
|
+
created: new Date().toISOString(),
|
|
117
|
+
verificationMethod: `did:key:${publicKey}#${publicKey}`,
|
|
118
|
+
proofPurpose: 'assertionMethod',
|
|
119
|
+
proofValue,
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Execute the create command
|
|
125
|
+
*/
|
|
126
|
+
export async function createCommand(flags) {
|
|
127
|
+
// Check for help flag
|
|
128
|
+
if (flags.help || flags.h) {
|
|
129
|
+
return {
|
|
130
|
+
success: true,
|
|
131
|
+
message: 'Use --help with the main CLI for full help text',
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
// Validate required arguments
|
|
135
|
+
if (!flags.name) {
|
|
136
|
+
return {
|
|
137
|
+
success: false,
|
|
138
|
+
message: 'Error: --name is required. Usage: originals-cel create --name <name> --file <path>',
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
if (!flags.file) {
|
|
142
|
+
return {
|
|
143
|
+
success: false,
|
|
144
|
+
message: 'Error: --file is required. Usage: originals-cel create --name <name> --file <path>',
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
// Validate format flag
|
|
148
|
+
const format = (flags.format || 'json').toLowerCase();
|
|
149
|
+
if (format !== 'json' && format !== 'cbor') {
|
|
150
|
+
return {
|
|
151
|
+
success: false,
|
|
152
|
+
message: 'Error: --format must be "json" or "cbor"',
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
// Check if file exists
|
|
156
|
+
if (!fs.existsSync(flags.file)) {
|
|
157
|
+
return {
|
|
158
|
+
success: false,
|
|
159
|
+
message: `Error: File not found: ${flags.file}`,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
// Read file content
|
|
163
|
+
let fileContent;
|
|
164
|
+
try {
|
|
165
|
+
fileContent = new Uint8Array(fs.readFileSync(flags.file));
|
|
166
|
+
}
|
|
167
|
+
catch (e) {
|
|
168
|
+
return {
|
|
169
|
+
success: false,
|
|
170
|
+
message: `Error: Failed to read file: ${e.message}`,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
// Get or generate key pair
|
|
174
|
+
let privateKey;
|
|
175
|
+
let publicKey;
|
|
176
|
+
let keyGenerated = false;
|
|
177
|
+
if (flags.key) {
|
|
178
|
+
try {
|
|
179
|
+
const loaded = await loadPrivateKey(flags.key);
|
|
180
|
+
privateKey = loaded.privateKey;
|
|
181
|
+
publicKey = loaded.publicKey;
|
|
182
|
+
}
|
|
183
|
+
catch (e) {
|
|
184
|
+
return {
|
|
185
|
+
success: false,
|
|
186
|
+
message: `Error: Failed to load key: ${e.message}`,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
// Generate new key pair
|
|
192
|
+
const generated = await generateKeyPair();
|
|
193
|
+
privateKey = generated.privateKey;
|
|
194
|
+
publicKey = generated.publicKey;
|
|
195
|
+
keyGenerated = true;
|
|
196
|
+
}
|
|
197
|
+
// Create signer
|
|
198
|
+
const signer = createSigner(privateKey, publicKey);
|
|
199
|
+
// Determine media type from file extension
|
|
200
|
+
const mediaType = getMimeType(flags.file);
|
|
201
|
+
// Create external reference for the file
|
|
202
|
+
const resource = createExternalReference(fileContent, mediaType);
|
|
203
|
+
// Create PeerCelManager and create the asset
|
|
204
|
+
const manager = new PeerCelManager(signer, {
|
|
205
|
+
verificationMethod: `did:key:${publicKey}#${publicKey}`,
|
|
206
|
+
proofPurpose: 'assertionMethod',
|
|
207
|
+
});
|
|
208
|
+
let eventLog;
|
|
209
|
+
try {
|
|
210
|
+
eventLog = await manager.create(flags.name, [resource]);
|
|
211
|
+
}
|
|
212
|
+
catch (e) {
|
|
213
|
+
return {
|
|
214
|
+
success: false,
|
|
215
|
+
message: `Error: Failed to create asset: ${e.message}`,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
// Serialize output
|
|
219
|
+
let output;
|
|
220
|
+
try {
|
|
221
|
+
if (format === 'cbor') {
|
|
222
|
+
output = serializeEventLogCbor(eventLog);
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
output = serializeEventLogJson(eventLog);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
catch (e) {
|
|
229
|
+
return {
|
|
230
|
+
success: false,
|
|
231
|
+
message: `Error: Failed to serialize event log: ${e.message}`,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
// Write output
|
|
235
|
+
if (flags.output) {
|
|
236
|
+
try {
|
|
237
|
+
if (format === 'cbor') {
|
|
238
|
+
fs.writeFileSync(flags.output, output);
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
fs.writeFileSync(flags.output, output, 'utf-8');
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
catch (e) {
|
|
245
|
+
return {
|
|
246
|
+
success: false,
|
|
247
|
+
message: `Error: Failed to write output file: ${e.message}`,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
// Write to stdout
|
|
253
|
+
if (format === 'cbor') {
|
|
254
|
+
// For CBOR, output as base64 to stdout since it's binary
|
|
255
|
+
const base64 = Buffer.from(output).toString('base64');
|
|
256
|
+
process.stdout.write(base64);
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
process.stdout.write(output);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
// Build result
|
|
263
|
+
const result = {
|
|
264
|
+
success: true,
|
|
265
|
+
message: flags.output
|
|
266
|
+
? `Created CEL asset "${flags.name}" and saved to ${flags.output}`
|
|
267
|
+
: `Created CEL asset "${flags.name}"`,
|
|
268
|
+
log: eventLog,
|
|
269
|
+
keyGenerated,
|
|
270
|
+
};
|
|
271
|
+
// Include key info if generated
|
|
272
|
+
if (keyGenerated) {
|
|
273
|
+
result.privateKey = privateKey;
|
|
274
|
+
result.publicKey = publicKey;
|
|
275
|
+
// Print key info to stderr so it doesn't mix with JSON output
|
|
276
|
+
console.error(`\n⚠️ New Ed25519 key pair generated. Save these keys securely!`);
|
|
277
|
+
console.error(`Private Key: ${privateKey}`);
|
|
278
|
+
console.error(`Public Key: ${publicKey}`);
|
|
279
|
+
console.error(`\nTo reuse this key, save it to a file and use --key <path>\n`);
|
|
280
|
+
}
|
|
281
|
+
return result;
|
|
282
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Originals CEL CLI
|
|
4
|
+
*
|
|
5
|
+
* Command-line interface for working with CEL (Cryptographic Event Log) assets.
|
|
6
|
+
* Part of the Originals Protocol SDK.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Main CLI entry point
|
|
10
|
+
*/
|
|
11
|
+
export declare function main(args?: string[]): void;
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Originals CEL CLI
|
|
4
|
+
*
|
|
5
|
+
* Command-line interface for working with CEL (Cryptographic Event Log) assets.
|
|
6
|
+
* Part of the Originals Protocol SDK.
|
|
7
|
+
*/
|
|
8
|
+
import { createCommand } from './create';
|
|
9
|
+
import { verifyCommand } from './verify';
|
|
10
|
+
import { inspectCommand } from './inspect';
|
|
11
|
+
import { migrateCommand } from './migrate';
|
|
12
|
+
// Version from package.json - will be replaced at build time or read dynamically
|
|
13
|
+
const VERSION = '1.5.0';
|
|
14
|
+
const HELP_TEXT = `
|
|
15
|
+
originals-cel - Cryptographic Event Log CLI for Originals Protocol
|
|
16
|
+
|
|
17
|
+
USAGE:
|
|
18
|
+
originals-cel <command> [options]
|
|
19
|
+
|
|
20
|
+
COMMANDS:
|
|
21
|
+
create Create a new CEL asset with an initial event
|
|
22
|
+
verify Verify an existing CEL event log
|
|
23
|
+
inspect Inspect a CEL log in human-readable format
|
|
24
|
+
migrate Migrate a CEL asset between layers (peer → webvh → btco)
|
|
25
|
+
|
|
26
|
+
GLOBAL OPTIONS:
|
|
27
|
+
--help, -h Show help for a command
|
|
28
|
+
--version, -v Show version number
|
|
29
|
+
|
|
30
|
+
EXAMPLES:
|
|
31
|
+
originals-cel create --name "My Asset" --file ./image.png
|
|
32
|
+
originals-cel verify --log ./asset.cel.json
|
|
33
|
+
originals-cel inspect --log ./asset.cel.json
|
|
34
|
+
originals-cel migrate --log ./asset.cel.json --to webvh --domain example.com
|
|
35
|
+
|
|
36
|
+
For more information on a specific command:
|
|
37
|
+
originals-cel <command> --help
|
|
38
|
+
`;
|
|
39
|
+
const CREATE_HELP = `
|
|
40
|
+
originals-cel create - Create a new CEL asset
|
|
41
|
+
|
|
42
|
+
USAGE:
|
|
43
|
+
originals-cel create --name <name> --file <path> [options]
|
|
44
|
+
|
|
45
|
+
REQUIRED:
|
|
46
|
+
--name <name> Name of the asset
|
|
47
|
+
--file <path> Path to the content file
|
|
48
|
+
|
|
49
|
+
OPTIONS:
|
|
50
|
+
--key <path> Path to Ed25519 private key (generates new if not provided)
|
|
51
|
+
--output <path> Output file path (stdout if not provided)
|
|
52
|
+
--format <type> Output format: json (default) or cbor
|
|
53
|
+
--help, -h Show this help message
|
|
54
|
+
|
|
55
|
+
EXAMPLES:
|
|
56
|
+
originals-cel create --name "My Art" --file ./artwork.png
|
|
57
|
+
originals-cel create --name "Document" --file ./doc.pdf --output ./doc.cel.json
|
|
58
|
+
originals-cel create --name "Asset" --file ./data.bin --format cbor --output ./asset.cel.cbor
|
|
59
|
+
`;
|
|
60
|
+
const VERIFY_HELP = `
|
|
61
|
+
originals-cel verify - Verify a CEL event log
|
|
62
|
+
|
|
63
|
+
USAGE:
|
|
64
|
+
originals-cel verify --log <path> [options]
|
|
65
|
+
|
|
66
|
+
REQUIRED:
|
|
67
|
+
--log <path> Path to the CEL event log file (.cel.json or .cel.cbor)
|
|
68
|
+
|
|
69
|
+
OPTIONS:
|
|
70
|
+
--help, -h Show this help message
|
|
71
|
+
|
|
72
|
+
OUTPUT:
|
|
73
|
+
Displays verification result with event-by-event breakdown.
|
|
74
|
+
Shows witness attestations if present.
|
|
75
|
+
Exit code 0 on success, 1 on verification failure.
|
|
76
|
+
|
|
77
|
+
EXAMPLES:
|
|
78
|
+
originals-cel verify --log ./asset.cel.json
|
|
79
|
+
originals-cel verify --log ./asset.cel.cbor
|
|
80
|
+
`;
|
|
81
|
+
const INSPECT_HELP = `
|
|
82
|
+
originals-cel inspect - Inspect a CEL log in human-readable format
|
|
83
|
+
|
|
84
|
+
USAGE:
|
|
85
|
+
originals-cel inspect --log <path> [options]
|
|
86
|
+
|
|
87
|
+
REQUIRED:
|
|
88
|
+
--log <path> Path to the CEL event log file
|
|
89
|
+
|
|
90
|
+
OPTIONS:
|
|
91
|
+
--help, -h Show this help message
|
|
92
|
+
|
|
93
|
+
OUTPUT:
|
|
94
|
+
Pretty-prints event timeline with timestamps.
|
|
95
|
+
Shows current state derived from events.
|
|
96
|
+
Lists witnesses and attestation times.
|
|
97
|
+
Shows layer history if migrations are present.
|
|
98
|
+
|
|
99
|
+
EXAMPLES:
|
|
100
|
+
originals-cel inspect --log ./asset.cel.json
|
|
101
|
+
`;
|
|
102
|
+
const MIGRATE_HELP = `
|
|
103
|
+
originals-cel migrate - Migrate a CEL asset between layers
|
|
104
|
+
|
|
105
|
+
USAGE:
|
|
106
|
+
originals-cel migrate --log <path> --to <layer> [options]
|
|
107
|
+
|
|
108
|
+
REQUIRED:
|
|
109
|
+
--log <path> Path to the CEL event log file
|
|
110
|
+
--to <layer> Target layer: webvh or btco
|
|
111
|
+
|
|
112
|
+
OPTIONS:
|
|
113
|
+
--domain <domain> Domain for webvh layer (required for --to webvh)
|
|
114
|
+
--wallet <path> Path to Bitcoin wallet key (required for --to btco)
|
|
115
|
+
--output <path> Output file path (stdout if not provided)
|
|
116
|
+
--help, -h Show this help message
|
|
117
|
+
|
|
118
|
+
MIGRATION PATHS:
|
|
119
|
+
peer → webvh Requires --domain
|
|
120
|
+
webvh → btco Requires --wallet
|
|
121
|
+
|
|
122
|
+
EXAMPLES:
|
|
123
|
+
originals-cel migrate --log ./asset.cel.json --to webvh --domain example.com
|
|
124
|
+
originals-cel migrate --log ./asset.cel.json --to btco --wallet ./wallet.key
|
|
125
|
+
originals-cel migrate --log ./asset.cel.json --to webvh --domain example.com --output ./migrated.cel.json
|
|
126
|
+
`;
|
|
127
|
+
/**
|
|
128
|
+
* Parse command line arguments into a structured object
|
|
129
|
+
*/
|
|
130
|
+
function parseArgs(args) {
|
|
131
|
+
const flags = {};
|
|
132
|
+
let command = null;
|
|
133
|
+
for (let i = 0; i < args.length; i++) {
|
|
134
|
+
const arg = args[i];
|
|
135
|
+
if (arg.startsWith('--')) {
|
|
136
|
+
const key = arg.slice(2);
|
|
137
|
+
const nextArg = args[i + 1];
|
|
138
|
+
// Check if next arg exists and doesn't start with --
|
|
139
|
+
if (nextArg && !nextArg.startsWith('-')) {
|
|
140
|
+
flags[key] = nextArg;
|
|
141
|
+
i++; // Skip the value
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
flags[key] = true;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
else if (arg.startsWith('-')) {
|
|
148
|
+
const key = arg.slice(1);
|
|
149
|
+
flags[key] = true;
|
|
150
|
+
}
|
|
151
|
+
else if (!command) {
|
|
152
|
+
command = arg;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return { command, flags };
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Print message to stdout
|
|
159
|
+
*/
|
|
160
|
+
function print(message) {
|
|
161
|
+
console.log(message);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Print error message to stderr and exit
|
|
165
|
+
*/
|
|
166
|
+
function error(message, exitCode = 1) {
|
|
167
|
+
console.error(`Error: ${message}`);
|
|
168
|
+
process.exit(exitCode);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Show help for a specific command
|
|
172
|
+
*/
|
|
173
|
+
function showCommandHelp(command) {
|
|
174
|
+
switch (command) {
|
|
175
|
+
case 'create':
|
|
176
|
+
print(CREATE_HELP);
|
|
177
|
+
break;
|
|
178
|
+
case 'verify':
|
|
179
|
+
print(VERIFY_HELP);
|
|
180
|
+
break;
|
|
181
|
+
case 'inspect':
|
|
182
|
+
print(INSPECT_HELP);
|
|
183
|
+
break;
|
|
184
|
+
case 'migrate':
|
|
185
|
+
print(MIGRATE_HELP);
|
|
186
|
+
break;
|
|
187
|
+
default:
|
|
188
|
+
error(`Unknown command: ${command}`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Run the create command asynchronously
|
|
193
|
+
*/
|
|
194
|
+
async function runCreateCommand(flags) {
|
|
195
|
+
try {
|
|
196
|
+
const createFlags = {
|
|
197
|
+
name: typeof flags.name === 'string' ? flags.name : undefined,
|
|
198
|
+
file: typeof flags.file === 'string' ? flags.file : undefined,
|
|
199
|
+
key: typeof flags.key === 'string' ? flags.key : undefined,
|
|
200
|
+
output: typeof flags.output === 'string' ? flags.output : undefined,
|
|
201
|
+
format: typeof flags.format === 'string' ? flags.format : undefined,
|
|
202
|
+
help: flags.help === true,
|
|
203
|
+
h: flags.h === true,
|
|
204
|
+
};
|
|
205
|
+
const result = await createCommand(createFlags);
|
|
206
|
+
if (!result.success) {
|
|
207
|
+
error(result.message.replace('Error: ', ''));
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
catch (e) {
|
|
211
|
+
error(e.message);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Run the verify command asynchronously
|
|
216
|
+
*/
|
|
217
|
+
async function runVerifyCommand(flags) {
|
|
218
|
+
try {
|
|
219
|
+
const verifyFlags = {
|
|
220
|
+
log: typeof flags.log === 'string' ? flags.log : undefined,
|
|
221
|
+
help: flags.help === true,
|
|
222
|
+
h: flags.h === true,
|
|
223
|
+
};
|
|
224
|
+
const result = await verifyCommand(verifyFlags);
|
|
225
|
+
if (!result.success) {
|
|
226
|
+
error(result.message.replace('Error: ', ''));
|
|
227
|
+
}
|
|
228
|
+
// Exit with appropriate code based on verification result
|
|
229
|
+
if (result.verified === false) {
|
|
230
|
+
process.exit(1);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
catch (e) {
|
|
234
|
+
error(e.message);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Run the inspect command asynchronously
|
|
239
|
+
*/
|
|
240
|
+
async function runInspectCommand(flags) {
|
|
241
|
+
try {
|
|
242
|
+
const inspectFlags = {
|
|
243
|
+
log: typeof flags.log === 'string' ? flags.log : undefined,
|
|
244
|
+
help: flags.help === true,
|
|
245
|
+
h: flags.h === true,
|
|
246
|
+
};
|
|
247
|
+
const result = await inspectCommand(inspectFlags);
|
|
248
|
+
if (!result.success) {
|
|
249
|
+
error(result.message.replace('Error: ', ''));
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
catch (e) {
|
|
253
|
+
error(e.message);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Run the migrate command asynchronously
|
|
258
|
+
*/
|
|
259
|
+
async function runMigrateCommand(flags) {
|
|
260
|
+
try {
|
|
261
|
+
const migrateFlags = {
|
|
262
|
+
log: typeof flags.log === 'string' ? flags.log : undefined,
|
|
263
|
+
to: typeof flags.to === 'string' ? flags.to : undefined,
|
|
264
|
+
domain: typeof flags.domain === 'string' ? flags.domain : undefined,
|
|
265
|
+
wallet: typeof flags.wallet === 'string' ? flags.wallet : undefined,
|
|
266
|
+
output: typeof flags.output === 'string' ? flags.output : undefined,
|
|
267
|
+
format: typeof flags.format === 'string' ? flags.format : undefined,
|
|
268
|
+
help: flags.help === true,
|
|
269
|
+
h: flags.h === true,
|
|
270
|
+
};
|
|
271
|
+
const result = await migrateCommand(migrateFlags);
|
|
272
|
+
if (!result.success) {
|
|
273
|
+
error(result.message.replace('Error: ', ''));
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
catch (e) {
|
|
277
|
+
error(e.message);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Main CLI entry point
|
|
282
|
+
*/
|
|
283
|
+
export function main(args = process.argv.slice(2)) {
|
|
284
|
+
const { command, flags } = parseArgs(args);
|
|
285
|
+
// Handle --version / -v
|
|
286
|
+
if (flags.version || flags.v) {
|
|
287
|
+
print(`originals-cel v${VERSION}`);
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
// Handle --help / -h without command
|
|
291
|
+
if (!command || flags.help || flags.h) {
|
|
292
|
+
if (command && command !== 'help') {
|
|
293
|
+
showCommandHelp(command);
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
print(HELP_TEXT);
|
|
297
|
+
}
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
// Route to subcommands
|
|
301
|
+
switch (command) {
|
|
302
|
+
case 'create':
|
|
303
|
+
if (flags.help || flags.h) {
|
|
304
|
+
print(CREATE_HELP);
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
// Run create command asynchronously
|
|
308
|
+
runCreateCommand(flags);
|
|
309
|
+
return;
|
|
310
|
+
case 'verify':
|
|
311
|
+
if (flags.help || flags.h) {
|
|
312
|
+
print(VERIFY_HELP);
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
// Run verify command asynchronously
|
|
316
|
+
runVerifyCommand(flags);
|
|
317
|
+
return;
|
|
318
|
+
case 'inspect':
|
|
319
|
+
if (flags.help || flags.h) {
|
|
320
|
+
print(INSPECT_HELP);
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
// Run inspect command asynchronously
|
|
324
|
+
runInspectCommand(flags);
|
|
325
|
+
return;
|
|
326
|
+
case 'migrate':
|
|
327
|
+
if (flags.help || flags.h) {
|
|
328
|
+
print(MIGRATE_HELP);
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
// Run migrate command asynchronously
|
|
332
|
+
runMigrateCommand(flags);
|
|
333
|
+
return;
|
|
334
|
+
case 'help':
|
|
335
|
+
// Handle "originals-cel help <command>"
|
|
336
|
+
const helpTarget = args[1];
|
|
337
|
+
if (helpTarget && !helpTarget.startsWith('-')) {
|
|
338
|
+
showCommandHelp(helpTarget);
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
print(HELP_TEXT);
|
|
342
|
+
}
|
|
343
|
+
break;
|
|
344
|
+
default:
|
|
345
|
+
error(`Unknown command: ${command}\n\nRun 'originals-cel --help' for usage.`);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
// Run if executed directly
|
|
349
|
+
if (typeof process !== 'undefined' && process.argv[1]?.includes('cli')) {
|
|
350
|
+
main();
|
|
351
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI Inspect Command
|
|
4
|
+
*
|
|
5
|
+
* Inspects a CEL event log in human-readable format.
|
|
6
|
+
* Displays event timeline, current state, witness attestations, and layer history.
|
|
7
|
+
*
|
|
8
|
+
* Usage: originals-cel inspect --log <path> [options]
|
|
9
|
+
*/
|
|
10
|
+
import type { AssetState } from '../types';
|
|
11
|
+
/**
|
|
12
|
+
* Flags parsed from command line arguments
|
|
13
|
+
*/
|
|
14
|
+
export interface InspectFlags {
|
|
15
|
+
log?: string;
|
|
16
|
+
help?: boolean;
|
|
17
|
+
h?: boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Result of the inspect command
|
|
21
|
+
*/
|
|
22
|
+
export interface InspectResult {
|
|
23
|
+
success: boolean;
|
|
24
|
+
message: string;
|
|
25
|
+
state?: AssetState;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Execute the inspect command
|
|
29
|
+
*/
|
|
30
|
+
export declare function inspectCommand(flags: InspectFlags): Promise<InspectResult>;
|