@did-btcr2/cli 0.1.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/LICENSE +1 -0
- package/README.md +3 -0
- package/dist/cjs/cli.js +176 -0
- package/dist/cjs/cli.js.map +1 -0
- package/dist/cjs/command.js +41 -0
- package/dist/cjs/command.js.map +1 -0
- package/dist/cjs/index.js +3 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/esm/cli.js +176 -0
- package/dist/esm/cli.js.map +1 -0
- package/dist/esm/command.js +41 -0
- package/dist/esm/command.js.map +1 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/types/cli.d.ts +31 -0
- package/dist/types/cli.d.ts.map +1 -0
- package/dist/types/command.d.ts +14 -0
- package/dist/types/command.d.ts.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -0
- package/package.json +112 -0
- package/src/cli.ts +238 -0
- package/src/command.ts +49 -0
- package/src/index.ts +2 -0
package/LICENSE
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"key":"unlicense","name":"The Unlicense","spdx_id":"Unlicense","url":"https://api.github.com/licenses/unlicense","node_id":"MDc6TGljZW5zZTE1","html_url":"http://choosealicense.com/licenses/unlicense/","description":"A license with no conditions whatsoever which dedicates works to the public domain. Unlicensed works, modifications, and larger works may be distributed under different terms and without source code.","implementation":"Create a text file (typically named UNLICENSE or UNLICENSE.txt) in the root of your source code and copy the text of the license disclaimer into the file.","permissions":["private-use","commercial-use","modifications","distribution"],"conditions":[],"limitations":["liability","warranty"],"body":"This is free and unencumbered software released into the public domain.\n\nAnyone is free to copy, modify, publish, use, compile, sell, or\ndistribute this software, either in source code form or as a compiled\nbinary, for any purpose, commercial or non-commercial, and by any\nmeans.\n\nIn jurisdictions that recognize copyright laws, the author or authors\nof this software dedicate any and all copyright interest in the\nsoftware to the public domain. We make this dedication for the benefit\nof the public at large and to the detriment of our heirs and\nsuccessors. We intend this dedication to be an overt act of\nrelinquishment in perpetuity of all present and future rights to this\nsoftware under copyright law.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR\nOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\nFor more information, please refer to <https://unlicense.org>\n","featured":false}
|
package/README.md
ADDED
package/dist/cjs/cli.js
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { DidMethodError } from '@did-btcr2/common';
|
|
2
|
+
import { Identifier } from '@did-btcr2/method';
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import { readFile } from 'fs/promises';
|
|
5
|
+
import Btcr2Command from './command.js';
|
|
6
|
+
/**
|
|
7
|
+
* Custom CLI Error class extending DidMethodError.
|
|
8
|
+
*/
|
|
9
|
+
export class CLIError extends DidMethodError {
|
|
10
|
+
constructor(message, type = 'CLIError', data) {
|
|
11
|
+
super(message, { type, name: type, data });
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A class-based CLI using Commander.
|
|
16
|
+
* - No forced process.exit().
|
|
17
|
+
* - Configurable by calling `run(argv?)`.
|
|
18
|
+
*/
|
|
19
|
+
export class DidBtcr2Cli {
|
|
20
|
+
CLI;
|
|
21
|
+
constructor() {
|
|
22
|
+
// Create the main Commander program
|
|
23
|
+
this.CLI = new Command()
|
|
24
|
+
.name('btcr2')
|
|
25
|
+
.version('btcr2 0.1.0', '-v, --version', 'Output the current version')
|
|
26
|
+
.description('CLI tool for the did:btcr2 method');
|
|
27
|
+
// Configure top-level options and subcommands
|
|
28
|
+
this.configureCommands();
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Configure the CLI commands and options.
|
|
32
|
+
* @private
|
|
33
|
+
*/
|
|
34
|
+
configureCommands() {
|
|
35
|
+
/* CREATE */
|
|
36
|
+
this.CLI
|
|
37
|
+
.command('create')
|
|
38
|
+
.description('Create an identifier and initial DID document')
|
|
39
|
+
.requiredOption('-t, --type <type>', 'Identifier type <k|x>', 'k')
|
|
40
|
+
.requiredOption('-n, --network <network>', 'Identifier bitcoin network <bitcoin|testnet3|testnet4|signet|mutinynet|regtest>')
|
|
41
|
+
.requiredOption('-b, --bytes <bytes>', 'The genesis bytes used to create a DID and DID document as a hex string. ' +
|
|
42
|
+
'If type=k, MUST be secp256k1 public key. ' +
|
|
43
|
+
'If type=x, MUST be SHA-256 hash of a genesis document')
|
|
44
|
+
.action(async (options) => {
|
|
45
|
+
if (!['k', 'x'].includes(options.type)) {
|
|
46
|
+
throw new CLIError('Invalid type. Must be "k" or "x".', 'INVALID_ARGUMENT_ERROR', options);
|
|
47
|
+
}
|
|
48
|
+
if (!['bitcoin', 'testnet3', 'testnet4', 'signet', 'mutinynet', 'regtest'].includes(options.network)) {
|
|
49
|
+
throw new CLIError('Invalid network. Must be one of "bitcoin", "testnet3", ' +
|
|
50
|
+
'"testnet4", "signet", "mutinynet", or "regtest".', 'INVALID_ARGUMENT_ERROR', options);
|
|
51
|
+
}
|
|
52
|
+
if (Buffer.from(options.bytes, 'hex').length === 0) {
|
|
53
|
+
throw new CLIError('Invalid bytes. Must be a non-empty hex string.', 'INVALID_ARGUMENT_ERROR', options);
|
|
54
|
+
}
|
|
55
|
+
await this.invokeCommand({ options, action: 'create', command: new Btcr2Command() });
|
|
56
|
+
});
|
|
57
|
+
/* READ / RESOLVE */
|
|
58
|
+
this.CLI
|
|
59
|
+
.command('resolve')
|
|
60
|
+
.alias('read')
|
|
61
|
+
.description('Resolve the DID document of the identifier.')
|
|
62
|
+
.requiredOption('-i, --identifier <identifier>', 'did:btcr2 identifier')
|
|
63
|
+
.option('-r, --resolutionOptions <resolutionOptions>', 'JSON string containing resolution options')
|
|
64
|
+
.option('-p, --resolutionOptionsPath <resolutionOptionsPath>', 'Path to a JSON file containing resolution options')
|
|
65
|
+
.action(async (options) => {
|
|
66
|
+
try {
|
|
67
|
+
Identifier.decode(options.identifier);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
throw new CLIError('Invalid identifier. Must be a valid did:btcr2 identifier.', 'INVALID_ARGUMENT_ERROR', options);
|
|
71
|
+
}
|
|
72
|
+
if (options.resolutionOptions) {
|
|
73
|
+
try {
|
|
74
|
+
options.resolutionOptions = JSON.parse(options.resolutionOptions);
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
throw new CLIError('Invalid options. Must be a valid JSON string.', 'INVALID_ARGUMENT_ERROR', options);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (options.resolutionOptionsPath) {
|
|
81
|
+
try {
|
|
82
|
+
const data = await readFile(options.resolutionOptionsPath, 'utf-8');
|
|
83
|
+
options.resolutionOptions = JSON.parse(data);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
throw new CLIError('Invalid options path. Must be a valid path to a JSON file.', 'INVALID_ARGUMENT_ERROR', options);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
await this.invokeCommand({ options, action: 'resolve', command: new Btcr2Command() });
|
|
90
|
+
});
|
|
91
|
+
/* UPDATE */
|
|
92
|
+
this.CLI
|
|
93
|
+
.command('update')
|
|
94
|
+
.description('Update a did:btcr2 document.')
|
|
95
|
+
.requiredOption('-i, --identifier <identifier>', 'did:btcr2 identifier')
|
|
96
|
+
.requiredOption('-s, --sourceDocument <sourceDocument>', 'Source DID document as JSON string')
|
|
97
|
+
.requiredOption('-v, --sourceVersionId <sourceVersionId>', 'Source version ID as a number')
|
|
98
|
+
.requiredOption('-p, --patch <patch>', 'JSON Patch operations as a JSON string array')
|
|
99
|
+
.requiredOption('-m, --verificationMethodId <verificationMethodId>', 'Did document verification method ID as a string')
|
|
100
|
+
.requiredOption('-b, --beaconIds <beaconIds>', 'Beacon IDs as a JSON string array')
|
|
101
|
+
.action(async (options) => {
|
|
102
|
+
// Validate identifier by decoding
|
|
103
|
+
try {
|
|
104
|
+
Identifier.decode(options.identifier);
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
throw new CLIError('Invalid identifier. Must be a valid did:btcr2 identifier.', 'INVALID_ARGUMENT_ERROR', options);
|
|
108
|
+
}
|
|
109
|
+
// Validate source document JSON
|
|
110
|
+
if (options.sourceDocument) {
|
|
111
|
+
try {
|
|
112
|
+
options.sourceDocument = JSON.parse(options.sourceDocument);
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
throw new CLIError('Invalid options. Must be a valid JSON string.', 'INVALID_ARGUMENT_ERROR', options);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// Validate patch JSON
|
|
119
|
+
if (options.patch) {
|
|
120
|
+
try {
|
|
121
|
+
options.patch = JSON.parse(options.patch);
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
throw new CLIError('Invalid options. Must be a valid JSON string.', 'INVALID_ARGUMENT_ERROR', options);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Validate beacon IDs JSON
|
|
128
|
+
if (options.beaconIds) {
|
|
129
|
+
try {
|
|
130
|
+
options.beaconIds = JSON.parse(options.beaconIds);
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
throw new CLIError('Invalid options. Must be a valid JSON string.', 'INVALID_ARGUMENT_ERROR', options);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
await this.invokeCommand({ options, action: 'update', command: new Btcr2Command() });
|
|
137
|
+
});
|
|
138
|
+
/* DEACTIVATE / DELETE */
|
|
139
|
+
this.CLI
|
|
140
|
+
.command('deactivate')
|
|
141
|
+
.alias('delete')
|
|
142
|
+
.description('Deactivate the did:btcr2 identifier permanently.')
|
|
143
|
+
.action(async (options) => {
|
|
144
|
+
await this.invokeCommand({ options, action: 'deactivate', command: new Btcr2Command() });
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* A helper to invoke the command logic without forcibly exiting.
|
|
149
|
+
*/
|
|
150
|
+
async invokeCommand({ options, action, command }) {
|
|
151
|
+
try {
|
|
152
|
+
await command.execute({ options, action });
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
console.error('Error executing command:', error);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Parse and run the CLI.
|
|
160
|
+
*/
|
|
161
|
+
run(argv) {
|
|
162
|
+
if (argv) {
|
|
163
|
+
this.CLI.parse(argv, { from: 'user' });
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
// parse real process.argv
|
|
167
|
+
this.CLI.parse();
|
|
168
|
+
}
|
|
169
|
+
// If no subcommand was given, show help
|
|
170
|
+
if (!this.CLI.args.length) {
|
|
171
|
+
this.CLI.help();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
export default new DidBtcr2Cli().run();
|
|
176
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { IdentifierTypes, Logger, MethodError } from '@did-btcr2/common';
|
|
2
|
+
import { DidBtcr2 } from '@did-btcr2/method';
|
|
3
|
+
export default class Btcr2Command {
|
|
4
|
+
async execute({ options, action }) {
|
|
5
|
+
try {
|
|
6
|
+
switch (action) {
|
|
7
|
+
case 'create': {
|
|
8
|
+
const { type, bytes } = options;
|
|
9
|
+
const idType = type === 'k' ? IdentifierTypes.KEY : IdentifierTypes.EXTERNAL;
|
|
10
|
+
const genesisBytes = Buffer.from(bytes, 'hex').toArray().toUint8Array();
|
|
11
|
+
const did = await DidBtcr2.create({ idType, genesisBytes });
|
|
12
|
+
console.log(did);
|
|
13
|
+
break;
|
|
14
|
+
}
|
|
15
|
+
case 'read':
|
|
16
|
+
case 'resolve': {
|
|
17
|
+
const { identifier, options: resolutionOptions } = options;
|
|
18
|
+
const resolutionResult = await DidBtcr2.resolve(identifier, resolutionOptions);
|
|
19
|
+
console.log(JSON.stringify(resolutionResult, null, 2));
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
case 'update': {
|
|
23
|
+
const update = await DidBtcr2.update(options);
|
|
24
|
+
console.log(JSON.stringify(update, null, 2));
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
case 'delete':
|
|
28
|
+
case 'deactivate':
|
|
29
|
+
// await DidBtcr2.deactivate(options);
|
|
30
|
+
Logger.warn('// TODO: Update once DidBtcr2.deactivate implemented');
|
|
31
|
+
break;
|
|
32
|
+
default:
|
|
33
|
+
throw new MethodError(`Invalid command: ${action}`, 'INVALID_COMMAND');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
console.error(error);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command.js","sourceRoot":"","sources":["../../src/command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAwB,MAAM,mBAAmB,CAAC;AAWnE,MAAM,CAAC,OAAO,OAAO,YAAY;IAC/B,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,EAAiB;QAC9C,IAAI,CAAC;YACH,QAAQ,MAAM,EAAE,CAAC;gBACf,KAAK,QAAQ,CAAC,CAAA,CAAC;oBACb,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,OAA0C,CAAC;oBACnE,MAAM,MAAM,GAAG,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,eAAe,CAAC,QAAQ,CAAC;oBAC7E,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,YAAY,EAAE,CAAC;oBACxE,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC;oBAC5D,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;oBACjB,MAAM;gBACR,CAAC;gBACD,KAAK,MAAM,CAAC;gBACZ,KAAK,SAAS,CAAC,CAAC,CAAC;oBACf,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,iBAAiB,EAAE,GAAG,OAA+B,CAAC;oBACnF,MAAM,gBAAgB,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;oBAC/E,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;oBACvD,MAAM;gBACR,CAAC;gBACD,KAAK,QAAQ,CAAC,CAAC,CAAC;oBACd,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;oBAC9C,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;oBAC7C,MAAM;gBACR,CAAC;gBACD,KAAK,QAAQ,CAAC;gBACd,KAAK,YAAY;oBACf,sCAAsC;oBACtC,MAAM,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAC;oBACpE,MAAM;gBACR;oBACE,MAAM,IAAI,WAAW,CAAC,oBAAoB,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC;YAC3E,CAAC;QACH,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type": "commonjs"}
|
package/dist/esm/cli.js
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { DidMethodError } from '@did-btcr2/common';
|
|
2
|
+
import { Identifier } from '@did-btcr2/method';
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import { readFile } from 'fs/promises';
|
|
5
|
+
import Btcr2Command from './command.js';
|
|
6
|
+
/**
|
|
7
|
+
* Custom CLI Error class extending DidMethodError.
|
|
8
|
+
*/
|
|
9
|
+
export class CLIError extends DidMethodError {
|
|
10
|
+
constructor(message, type = 'CLIError', data) {
|
|
11
|
+
super(message, { type, name: type, data });
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A class-based CLI using Commander.
|
|
16
|
+
* - No forced process.exit().
|
|
17
|
+
* - Configurable by calling `run(argv?)`.
|
|
18
|
+
*/
|
|
19
|
+
export class DidBtcr2Cli {
|
|
20
|
+
CLI;
|
|
21
|
+
constructor() {
|
|
22
|
+
// Create the main Commander program
|
|
23
|
+
this.CLI = new Command()
|
|
24
|
+
.name('btcr2')
|
|
25
|
+
.version('btcr2 0.1.0', '-v, --version', 'Output the current version')
|
|
26
|
+
.description('CLI tool for the did:btcr2 method');
|
|
27
|
+
// Configure top-level options and subcommands
|
|
28
|
+
this.configureCommands();
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Configure the CLI commands and options.
|
|
32
|
+
* @private
|
|
33
|
+
*/
|
|
34
|
+
configureCommands() {
|
|
35
|
+
/* CREATE */
|
|
36
|
+
this.CLI
|
|
37
|
+
.command('create')
|
|
38
|
+
.description('Create an identifier and initial DID document')
|
|
39
|
+
.requiredOption('-t, --type <type>', 'Identifier type <k|x>', 'k')
|
|
40
|
+
.requiredOption('-n, --network <network>', 'Identifier bitcoin network <bitcoin|testnet3|testnet4|signet|mutinynet|regtest>')
|
|
41
|
+
.requiredOption('-b, --bytes <bytes>', 'The genesis bytes used to create a DID and DID document as a hex string. ' +
|
|
42
|
+
'If type=k, MUST be secp256k1 public key. ' +
|
|
43
|
+
'If type=x, MUST be SHA-256 hash of a genesis document')
|
|
44
|
+
.action(async (options) => {
|
|
45
|
+
if (!['k', 'x'].includes(options.type)) {
|
|
46
|
+
throw new CLIError('Invalid type. Must be "k" or "x".', 'INVALID_ARGUMENT_ERROR', options);
|
|
47
|
+
}
|
|
48
|
+
if (!['bitcoin', 'testnet3', 'testnet4', 'signet', 'mutinynet', 'regtest'].includes(options.network)) {
|
|
49
|
+
throw new CLIError('Invalid network. Must be one of "bitcoin", "testnet3", ' +
|
|
50
|
+
'"testnet4", "signet", "mutinynet", or "regtest".', 'INVALID_ARGUMENT_ERROR', options);
|
|
51
|
+
}
|
|
52
|
+
if (Buffer.from(options.bytes, 'hex').length === 0) {
|
|
53
|
+
throw new CLIError('Invalid bytes. Must be a non-empty hex string.', 'INVALID_ARGUMENT_ERROR', options);
|
|
54
|
+
}
|
|
55
|
+
await this.invokeCommand({ options, action: 'create', command: new Btcr2Command() });
|
|
56
|
+
});
|
|
57
|
+
/* READ / RESOLVE */
|
|
58
|
+
this.CLI
|
|
59
|
+
.command('resolve')
|
|
60
|
+
.alias('read')
|
|
61
|
+
.description('Resolve the DID document of the identifier.')
|
|
62
|
+
.requiredOption('-i, --identifier <identifier>', 'did:btcr2 identifier')
|
|
63
|
+
.option('-r, --resolutionOptions <resolutionOptions>', 'JSON string containing resolution options')
|
|
64
|
+
.option('-p, --resolutionOptionsPath <resolutionOptionsPath>', 'Path to a JSON file containing resolution options')
|
|
65
|
+
.action(async (options) => {
|
|
66
|
+
try {
|
|
67
|
+
Identifier.decode(options.identifier);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
throw new CLIError('Invalid identifier. Must be a valid did:btcr2 identifier.', 'INVALID_ARGUMENT_ERROR', options);
|
|
71
|
+
}
|
|
72
|
+
if (options.resolutionOptions) {
|
|
73
|
+
try {
|
|
74
|
+
options.resolutionOptions = JSON.parse(options.resolutionOptions);
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
throw new CLIError('Invalid options. Must be a valid JSON string.', 'INVALID_ARGUMENT_ERROR', options);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (options.resolutionOptionsPath) {
|
|
81
|
+
try {
|
|
82
|
+
const data = await readFile(options.resolutionOptionsPath, 'utf-8');
|
|
83
|
+
options.resolutionOptions = JSON.parse(data);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
throw new CLIError('Invalid options path. Must be a valid path to a JSON file.', 'INVALID_ARGUMENT_ERROR', options);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
await this.invokeCommand({ options, action: 'resolve', command: new Btcr2Command() });
|
|
90
|
+
});
|
|
91
|
+
/* UPDATE */
|
|
92
|
+
this.CLI
|
|
93
|
+
.command('update')
|
|
94
|
+
.description('Update a did:btcr2 document.')
|
|
95
|
+
.requiredOption('-i, --identifier <identifier>', 'did:btcr2 identifier')
|
|
96
|
+
.requiredOption('-s, --sourceDocument <sourceDocument>', 'Source DID document as JSON string')
|
|
97
|
+
.requiredOption('-v, --sourceVersionId <sourceVersionId>', 'Source version ID as a number')
|
|
98
|
+
.requiredOption('-p, --patch <patch>', 'JSON Patch operations as a JSON string array')
|
|
99
|
+
.requiredOption('-m, --verificationMethodId <verificationMethodId>', 'Did document verification method ID as a string')
|
|
100
|
+
.requiredOption('-b, --beaconIds <beaconIds>', 'Beacon IDs as a JSON string array')
|
|
101
|
+
.action(async (options) => {
|
|
102
|
+
// Validate identifier by decoding
|
|
103
|
+
try {
|
|
104
|
+
Identifier.decode(options.identifier);
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
throw new CLIError('Invalid identifier. Must be a valid did:btcr2 identifier.', 'INVALID_ARGUMENT_ERROR', options);
|
|
108
|
+
}
|
|
109
|
+
// Validate source document JSON
|
|
110
|
+
if (options.sourceDocument) {
|
|
111
|
+
try {
|
|
112
|
+
options.sourceDocument = JSON.parse(options.sourceDocument);
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
throw new CLIError('Invalid options. Must be a valid JSON string.', 'INVALID_ARGUMENT_ERROR', options);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// Validate patch JSON
|
|
119
|
+
if (options.patch) {
|
|
120
|
+
try {
|
|
121
|
+
options.patch = JSON.parse(options.patch);
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
throw new CLIError('Invalid options. Must be a valid JSON string.', 'INVALID_ARGUMENT_ERROR', options);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Validate beacon IDs JSON
|
|
128
|
+
if (options.beaconIds) {
|
|
129
|
+
try {
|
|
130
|
+
options.beaconIds = JSON.parse(options.beaconIds);
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
throw new CLIError('Invalid options. Must be a valid JSON string.', 'INVALID_ARGUMENT_ERROR', options);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
await this.invokeCommand({ options, action: 'update', command: new Btcr2Command() });
|
|
137
|
+
});
|
|
138
|
+
/* DEACTIVATE / DELETE */
|
|
139
|
+
this.CLI
|
|
140
|
+
.command('deactivate')
|
|
141
|
+
.alias('delete')
|
|
142
|
+
.description('Deactivate the did:btcr2 identifier permanently.')
|
|
143
|
+
.action(async (options) => {
|
|
144
|
+
await this.invokeCommand({ options, action: 'deactivate', command: new Btcr2Command() });
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* A helper to invoke the command logic without forcibly exiting.
|
|
149
|
+
*/
|
|
150
|
+
async invokeCommand({ options, action, command }) {
|
|
151
|
+
try {
|
|
152
|
+
await command.execute({ options, action });
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
console.error('Error executing command:', error);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Parse and run the CLI.
|
|
160
|
+
*/
|
|
161
|
+
run(argv) {
|
|
162
|
+
if (argv) {
|
|
163
|
+
this.CLI.parse(argv, { from: 'user' });
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
// parse real process.argv
|
|
167
|
+
this.CLI.parse();
|
|
168
|
+
}
|
|
169
|
+
// If no subcommand was given, show help
|
|
170
|
+
if (!this.CLI.args.length) {
|
|
171
|
+
this.CLI.help();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
export default new DidBtcr2Cli().run();
|
|
176
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { IdentifierTypes, Logger, MethodError } from '@did-btcr2/common';
|
|
2
|
+
import { DidBtcr2 } from '@did-btcr2/method';
|
|
3
|
+
export default class Btcr2Command {
|
|
4
|
+
async execute({ options, action }) {
|
|
5
|
+
try {
|
|
6
|
+
switch (action) {
|
|
7
|
+
case 'create': {
|
|
8
|
+
const { type, bytes } = options;
|
|
9
|
+
const idType = type === 'k' ? IdentifierTypes.KEY : IdentifierTypes.EXTERNAL;
|
|
10
|
+
const genesisBytes = Buffer.from(bytes, 'hex').toArray().toUint8Array();
|
|
11
|
+
const did = await DidBtcr2.create({ idType, genesisBytes });
|
|
12
|
+
console.log(did);
|
|
13
|
+
break;
|
|
14
|
+
}
|
|
15
|
+
case 'read':
|
|
16
|
+
case 'resolve': {
|
|
17
|
+
const { identifier, options: resolutionOptions } = options;
|
|
18
|
+
const resolutionResult = await DidBtcr2.resolve(identifier, resolutionOptions);
|
|
19
|
+
console.log(JSON.stringify(resolutionResult, null, 2));
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
case 'update': {
|
|
23
|
+
const update = await DidBtcr2.update(options);
|
|
24
|
+
console.log(JSON.stringify(update, null, 2));
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
case 'delete':
|
|
28
|
+
case 'deactivate':
|
|
29
|
+
// await DidBtcr2.deactivate(options);
|
|
30
|
+
Logger.warn('// TODO: Update once DidBtcr2.deactivate implemented');
|
|
31
|
+
break;
|
|
32
|
+
default:
|
|
33
|
+
throw new MethodError(`Invalid command: ${action}`, 'INVALID_COMMAND');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
console.error(error);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command.js","sourceRoot":"","sources":["../../src/command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAwB,MAAM,mBAAmB,CAAC;AAWnE,MAAM,CAAC,OAAO,OAAO,YAAY;IAC/B,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,EAAiB;QAC9C,IAAI,CAAC;YACH,QAAQ,MAAM,EAAE,CAAC;gBACf,KAAK,QAAQ,CAAC,CAAA,CAAC;oBACb,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,OAA0C,CAAC;oBACnE,MAAM,MAAM,GAAG,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,eAAe,CAAC,QAAQ,CAAC;oBAC7E,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,YAAY,EAAE,CAAC;oBACxE,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC;oBAC5D,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;oBACjB,MAAM;gBACR,CAAC;gBACD,KAAK,MAAM,CAAC;gBACZ,KAAK,SAAS,CAAC,CAAC,CAAC;oBACf,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,iBAAiB,EAAE,GAAG,OAA+B,CAAC;oBACnF,MAAM,gBAAgB,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;oBAC/E,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;oBACvD,MAAM;gBACR,CAAC;gBACD,KAAK,QAAQ,CAAC,CAAC,CAAC;oBACd,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;oBAC9C,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;oBAC7C,MAAM;gBACR,CAAC;gBACD,KAAK,QAAQ,CAAC;gBACd,KAAK,YAAY;oBACf,sCAAsC;oBACtC,MAAM,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAC;oBACpE,MAAM;gBACR;oBACE,MAAM,IAAI,WAAW,CAAC,oBAAoB,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC;YAC3E,CAAC;QACH,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { DidMethodError } from '@did-btcr2/common';
|
|
2
|
+
/**
|
|
3
|
+
* Custom CLI Error class extending DidMethodError.
|
|
4
|
+
*/
|
|
5
|
+
export declare class CLIError extends DidMethodError {
|
|
6
|
+
constructor(message: string, type?: string, data?: Record<string, any>);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* A class-based CLI using Commander.
|
|
10
|
+
* - No forced process.exit().
|
|
11
|
+
* - Configurable by calling `run(argv?)`.
|
|
12
|
+
*/
|
|
13
|
+
export declare class DidBtcr2Cli {
|
|
14
|
+
private CLI;
|
|
15
|
+
constructor();
|
|
16
|
+
/**
|
|
17
|
+
* Configure the CLI commands and options.
|
|
18
|
+
* @private
|
|
19
|
+
*/
|
|
20
|
+
private configureCommands;
|
|
21
|
+
/**
|
|
22
|
+
* A helper to invoke the command logic without forcibly exiting.
|
|
23
|
+
*/
|
|
24
|
+
private invokeCommand;
|
|
25
|
+
/**
|
|
26
|
+
* Parse and run the CLI.
|
|
27
|
+
*/
|
|
28
|
+
run(argv?: string[]): void;
|
|
29
|
+
}
|
|
30
|
+
declare const _default: void;
|
|
31
|
+
export default _default;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAMnD;;GAEG;AACH,qBAAa,QAAS,SAAQ,cAAc;gBAC9B,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,MAAmB,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;CAGnF;AAED;;;;GAIG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,GAAG,CAAU;;IAarB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAqKzB;;OAEG;YACW,aAAa;IAY3B;;OAEG;IACI,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI;CAalC;;AAGD,wBAAuC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface CommandInterface {
|
|
2
|
+
execute(params: {
|
|
3
|
+
options?: any;
|
|
4
|
+
action?: string;
|
|
5
|
+
}): Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
interface ExecuteParams {
|
|
8
|
+
options?: any;
|
|
9
|
+
action?: string;
|
|
10
|
+
}
|
|
11
|
+
export default class Btcr2Command implements CommandInterface {
|
|
12
|
+
execute({ options, action }: ExecuteParams): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/command.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,MAAM,EAAE;QAAE,OAAO,CAAC,EAAE,GAAG,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpE;AAED,UAAU,aAAa;IACrB,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,CAAC,OAAO,OAAO,YAAa,YAAW,gBAAgB;IACrD,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;CAmCjE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@did-btcr2/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "CLI for interacting with did-btcr2-js, the JavaScript/TypeScript reference implementation of the did:btcr2 method. Exposes various parts of multiple packages in the did-btcr2-js monorepo.",
|
|
6
|
+
"main": "./dist/cjs/index.js",
|
|
7
|
+
"module": "./dist/esm/index.js",
|
|
8
|
+
"types": "./dist/types/index.d.ts",
|
|
9
|
+
"bin": {
|
|
10
|
+
"btcr2": "./dist/esm/cli.js"
|
|
11
|
+
},
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/types/index.d.ts",
|
|
15
|
+
"import": "./dist/esm/index.js",
|
|
16
|
+
"require": "./dist/cjs/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"src"
|
|
22
|
+
],
|
|
23
|
+
"license": "MPL-2.0",
|
|
24
|
+
"contributors": [
|
|
25
|
+
{
|
|
26
|
+
"name": "dcdpr",
|
|
27
|
+
"url": "https://github.com/dcdpr"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"name": "jintekc",
|
|
31
|
+
"url": "https://github.com/jintekc",
|
|
32
|
+
"email": "github@jintek.consulting"
|
|
33
|
+
}
|
|
34
|
+
],
|
|
35
|
+
"homepage": "https://github.com/dcdpr/did-btcr2-js/tree/main/packages/cli",
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "git+ssh://git@github.com:dcdpr/did-btcr2-js.git",
|
|
39
|
+
"directory": "packages/cli"
|
|
40
|
+
},
|
|
41
|
+
"bugs": "https://github.com/dcdpr/did-btcr2-js/issues",
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public"
|
|
44
|
+
},
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=22.0.0"
|
|
47
|
+
},
|
|
48
|
+
"keywords": [
|
|
49
|
+
"did",
|
|
50
|
+
"dids",
|
|
51
|
+
"decentralized identity",
|
|
52
|
+
"decentralized identifiers",
|
|
53
|
+
"did method",
|
|
54
|
+
"did:btcr2",
|
|
55
|
+
"bitcoin",
|
|
56
|
+
"cli"
|
|
57
|
+
],
|
|
58
|
+
"dependencies": {
|
|
59
|
+
"commander": "^13.1.0",
|
|
60
|
+
"@did-btcr2/common": "2.2.2",
|
|
61
|
+
"@did-btcr2/method": "0.18.0"
|
|
62
|
+
},
|
|
63
|
+
"devDependencies": {
|
|
64
|
+
"@eslint/js": "^9.21.0",
|
|
65
|
+
"@types/chai": "^5.0.1",
|
|
66
|
+
"@types/chai-as-promised": "^8.0.1",
|
|
67
|
+
"@types/eslint": "^9.6.1",
|
|
68
|
+
"@types/mocha": "^10.0.10",
|
|
69
|
+
"@types/node": "^22.13.8",
|
|
70
|
+
"@typescript-eslint/eslint-plugin": "^8.25.0",
|
|
71
|
+
"@typescript-eslint/parser": "^8.25.0",
|
|
72
|
+
"c8": "^10.1.3",
|
|
73
|
+
"chai": "^5.2.0",
|
|
74
|
+
"chai-as-promised": "^8.0.1",
|
|
75
|
+
"esbuild": "^0.25.0",
|
|
76
|
+
"eslint": "^9.21.0",
|
|
77
|
+
"eslint-plugin-mocha": "^10.5.0",
|
|
78
|
+
"globals": "^16.0.0",
|
|
79
|
+
"mocha": "^11.1.0",
|
|
80
|
+
"mocha-junit-reporter": "^2.2.1",
|
|
81
|
+
"node-stdlib-browser": "^1.3.1",
|
|
82
|
+
"rimraf": "^6.0.1",
|
|
83
|
+
"tsup": "^8.5.1",
|
|
84
|
+
"typedoc-plugin-markdown": "^4.7.0",
|
|
85
|
+
"typescript": "~5.7.3",
|
|
86
|
+
"typescript-eslint": "^8.25.0"
|
|
87
|
+
},
|
|
88
|
+
"scripts": {
|
|
89
|
+
"clean": "rimraf dist coverage tests/compiled",
|
|
90
|
+
"wipe": "rimraf node_modules pnpm-lock.json",
|
|
91
|
+
"wipe:clean": "pnpm wipe && pnpm clean",
|
|
92
|
+
"wipe:install": "pnpm wipe && pnpm install",
|
|
93
|
+
"clean:install": "pnpm clean && pnpm install",
|
|
94
|
+
"wipe:clean:install": "pnpm wipe:clean && pnpm install",
|
|
95
|
+
"reinstall": "pnpm install --force",
|
|
96
|
+
"build": "pnpm clean && pnpm build:esm && pnpm build:cjs",
|
|
97
|
+
"build:esm": "rimraf dist/esm dist/types && pnpm tsc -p tsconfig.json",
|
|
98
|
+
"build:cjs": "rimraf dist/cjs && tsc -p tsconfig.cjs.json && echo '{\"type\": \"commonjs\"}' > ./dist/cjs/package.json",
|
|
99
|
+
"build:tests": "pnpm tsc -p tests/tsconfig.json",
|
|
100
|
+
"build:all": "pnpm build && pnpm build:tests",
|
|
101
|
+
"release": "pnpm build && pnpm pack && mv *.tgz ../../release/cli",
|
|
102
|
+
"lint": "eslint . --max-warnings 0",
|
|
103
|
+
"lint:fix": "eslint . --fix",
|
|
104
|
+
"test": "pnpm c8 --omit-relative mocha",
|
|
105
|
+
"build:test": "pnpm build && pnpm build:tests && pnpm c8 --omit-relative mocha",
|
|
106
|
+
"build:lint:test": "pnpm build && pnpm build:tests && pnpm lint:fix",
|
|
107
|
+
"prepublish": "pnpm build",
|
|
108
|
+
"version": "pnpm version",
|
|
109
|
+
"version:no-git": "pnpm version --no-commit-hooks --no-git-tag-version",
|
|
110
|
+
"version:new": "[ -z \"$NEW_VERSION\" ] && echo 'ERROR: NEW_VERSION is not set' && exit 1 || (git checkout -b $NEW_VERSION && git tag $NEW_VERSION && pnpm version:no-git $NEW_VERSION)"
|
|
111
|
+
}
|
|
112
|
+
}
|
package/src/cli.ts
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { DidMethodError } from '@did-btcr2/common';
|
|
2
|
+
import { Identifier } from '@did-btcr2/method';
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import { readFile } from 'fs/promises';
|
|
5
|
+
import Btcr2Command from './command.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Custom CLI Error class extending DidMethodError.
|
|
9
|
+
*/
|
|
10
|
+
export class CLIError extends DidMethodError {
|
|
11
|
+
constructor(message: string, type: string = 'CLIError', data?: Record<string, any>) {
|
|
12
|
+
super(message, { type, name: type, data });
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A class-based CLI using Commander.
|
|
18
|
+
* - No forced process.exit().
|
|
19
|
+
* - Configurable by calling `run(argv?)`.
|
|
20
|
+
*/
|
|
21
|
+
export class DidBtcr2Cli {
|
|
22
|
+
private CLI: Command;
|
|
23
|
+
|
|
24
|
+
constructor() {
|
|
25
|
+
// Create the main Commander program
|
|
26
|
+
this.CLI = new Command()
|
|
27
|
+
.name('btcr2')
|
|
28
|
+
.version('btcr2 0.1.0', '-v, --version', 'Output the current version')
|
|
29
|
+
.description('CLI tool for the did:btcr2 method');
|
|
30
|
+
|
|
31
|
+
// Configure top-level options and subcommands
|
|
32
|
+
this.configureCommands();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Configure the CLI commands and options.
|
|
37
|
+
* @private
|
|
38
|
+
*/
|
|
39
|
+
private configureCommands(): void {
|
|
40
|
+
/* CREATE */
|
|
41
|
+
this.CLI
|
|
42
|
+
.command('create')
|
|
43
|
+
.description('Create an identifier and initial DID document')
|
|
44
|
+
.requiredOption('-t, --type <type>', 'Identifier type <k|x>', 'k')
|
|
45
|
+
.requiredOption(
|
|
46
|
+
'-n, --network <network>',
|
|
47
|
+
'Identifier bitcoin network <bitcoin|testnet3|testnet4|signet|mutinynet|regtest>'
|
|
48
|
+
)
|
|
49
|
+
.requiredOption(
|
|
50
|
+
'-b, --bytes <bytes>',
|
|
51
|
+
'The genesis bytes used to create a DID and DID document as a hex string. ' +
|
|
52
|
+
'If type=k, MUST be secp256k1 public key. ' +
|
|
53
|
+
'If type=x, MUST be SHA-256 hash of a genesis document'
|
|
54
|
+
)
|
|
55
|
+
.action(
|
|
56
|
+
async (options: { type: string; network: string; bytes: string, [key: string]: any }) => {
|
|
57
|
+
if(!['k','x'].includes(options.type)) {
|
|
58
|
+
throw new CLIError(
|
|
59
|
+
'Invalid type. Must be "k" or "x".',
|
|
60
|
+
'INVALID_ARGUMENT_ERROR',
|
|
61
|
+
options
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
if(!['bitcoin','testnet3','testnet4','signet','mutinynet','regtest'].includes(options.network)) {
|
|
65
|
+
throw new CLIError(
|
|
66
|
+
'Invalid network. Must be one of "bitcoin", "testnet3", ' +
|
|
67
|
+
'"testnet4", "signet", "mutinynet", or "regtest".',
|
|
68
|
+
'INVALID_ARGUMENT_ERROR',
|
|
69
|
+
options
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
if(Buffer.from(options.bytes, 'hex').length === 0) {
|
|
73
|
+
throw new CLIError(
|
|
74
|
+
'Invalid bytes. Must be a non-empty hex string.',
|
|
75
|
+
'INVALID_ARGUMENT_ERROR',
|
|
76
|
+
options
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
await this.invokeCommand({ options, action: 'create', command: new Btcr2Command() });
|
|
80
|
+
}
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
/* READ / RESOLVE */
|
|
84
|
+
this.CLI
|
|
85
|
+
.command('resolve')
|
|
86
|
+
.alias('read')
|
|
87
|
+
.description('Resolve the DID document of the identifier.')
|
|
88
|
+
.requiredOption('-i, --identifier <identifier>', 'did:btcr2 identifier')
|
|
89
|
+
.option('-r, --resolutionOptions <resolutionOptions>', 'JSON string containing resolution options')
|
|
90
|
+
.option('-p, --resolutionOptionsPath <resolutionOptionsPath>', 'Path to a JSON file containing resolution options')
|
|
91
|
+
.action(async (options: { identifier: string; resolutionOptions?: string; resolutionOptionsPath?: string }) => {
|
|
92
|
+
try {
|
|
93
|
+
Identifier.decode(options.identifier);
|
|
94
|
+
} catch {
|
|
95
|
+
throw new CLIError(
|
|
96
|
+
'Invalid identifier. Must be a valid did:btcr2 identifier.',
|
|
97
|
+
'INVALID_ARGUMENT_ERROR',
|
|
98
|
+
options
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
if(options.resolutionOptions) {
|
|
102
|
+
try {
|
|
103
|
+
options.resolutionOptions = JSON.parse(options.resolutionOptions);
|
|
104
|
+
} catch {
|
|
105
|
+
throw new CLIError(
|
|
106
|
+
'Invalid options. Must be a valid JSON string.',
|
|
107
|
+
'INVALID_ARGUMENT_ERROR',
|
|
108
|
+
options
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if(options.resolutionOptionsPath) {
|
|
113
|
+
try {
|
|
114
|
+
const data = await readFile(options.resolutionOptionsPath, 'utf-8');
|
|
115
|
+
options.resolutionOptions = JSON.parse(data);
|
|
116
|
+
} catch {
|
|
117
|
+
throw new CLIError(
|
|
118
|
+
'Invalid options path. Must be a valid path to a JSON file.',
|
|
119
|
+
'INVALID_ARGUMENT_ERROR',
|
|
120
|
+
options
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
await this.invokeCommand({ options, action: 'resolve', command: new Btcr2Command() });
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
/* UPDATE */
|
|
128
|
+
this.CLI
|
|
129
|
+
.command('update')
|
|
130
|
+
.description('Update a did:btcr2 document.')
|
|
131
|
+
.requiredOption('-i, --identifier <identifier>', 'did:btcr2 identifier')
|
|
132
|
+
.requiredOption('-s, --sourceDocument <sourceDocument>', 'Source DID document as JSON string')
|
|
133
|
+
.requiredOption('-v, --sourceVersionId <sourceVersionId>', 'Source version ID as a number')
|
|
134
|
+
.requiredOption('-p, --patch <patch>', 'JSON Patch operations as a JSON string array')
|
|
135
|
+
.requiredOption('-m, --verificationMethodId <verificationMethodId>', 'Did document verification method ID as a string')
|
|
136
|
+
.requiredOption('-b, --beaconIds <beaconIds>', 'Beacon IDs as a JSON string array')
|
|
137
|
+
.action(async (options: {
|
|
138
|
+
identifier: string;
|
|
139
|
+
sourceDocument: string; // stringified DidDocument; e.g. '{ "@context": "...", "id": "did:btcr2:...", ... }'
|
|
140
|
+
sourceVersionId: number;
|
|
141
|
+
patch: string; // stringified PatchOperation[]; e.g. '[{ "op": "add", "path": "/foo", "value": "bar" }]'
|
|
142
|
+
verificationMethodId: string;
|
|
143
|
+
beaconIds: string // stringified string[]; e.g. '["beaconId1","beaconId2"]'
|
|
144
|
+
}) => {
|
|
145
|
+
// Validate identifier by decoding
|
|
146
|
+
try {
|
|
147
|
+
Identifier.decode(options.identifier);
|
|
148
|
+
} catch {
|
|
149
|
+
throw new CLIError(
|
|
150
|
+
'Invalid identifier. Must be a valid did:btcr2 identifier.',
|
|
151
|
+
'INVALID_ARGUMENT_ERROR',
|
|
152
|
+
options
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
// Validate source document JSON
|
|
156
|
+
if(options.sourceDocument) {
|
|
157
|
+
try {
|
|
158
|
+
options.sourceDocument = JSON.parse(options.sourceDocument);
|
|
159
|
+
} catch {
|
|
160
|
+
throw new CLIError(
|
|
161
|
+
'Invalid options. Must be a valid JSON string.',
|
|
162
|
+
'INVALID_ARGUMENT_ERROR',
|
|
163
|
+
options
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
// Validate patch JSON
|
|
168
|
+
if(options.patch) {
|
|
169
|
+
try {
|
|
170
|
+
options.patch = JSON.parse(options.patch);
|
|
171
|
+
} catch {
|
|
172
|
+
throw new CLIError(
|
|
173
|
+
'Invalid options. Must be a valid JSON string.',
|
|
174
|
+
'INVALID_ARGUMENT_ERROR',
|
|
175
|
+
options
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
// Validate beacon IDs JSON
|
|
180
|
+
if(options.beaconIds) {
|
|
181
|
+
try {
|
|
182
|
+
options.beaconIds = JSON.parse(options.beaconIds);
|
|
183
|
+
} catch {
|
|
184
|
+
throw new CLIError(
|
|
185
|
+
'Invalid options. Must be a valid JSON string.',
|
|
186
|
+
'INVALID_ARGUMENT_ERROR',
|
|
187
|
+
options
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
await this.invokeCommand({ options, action: 'update', command: new Btcr2Command() });
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
/* DEACTIVATE / DELETE */
|
|
195
|
+
this.CLI
|
|
196
|
+
.command('deactivate')
|
|
197
|
+
.alias('delete')
|
|
198
|
+
.description('Deactivate the did:btcr2 identifier permanently.')
|
|
199
|
+
.action(async (options) => {
|
|
200
|
+
await this.invokeCommand({ options, action: 'deactivate', command: new Btcr2Command() });
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* A helper to invoke the command logic without forcibly exiting.
|
|
206
|
+
*/
|
|
207
|
+
private async invokeCommand({ options, action, command }: {
|
|
208
|
+
options: any;
|
|
209
|
+
action: string;
|
|
210
|
+
command: Btcr2Command;
|
|
211
|
+
}): Promise<void> {
|
|
212
|
+
try {
|
|
213
|
+
await command.execute({ options, action });
|
|
214
|
+
} catch (error) {
|
|
215
|
+
console.error('Error executing command:', error);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Parse and run the CLI.
|
|
221
|
+
*/
|
|
222
|
+
public run(argv?: string[]): void {
|
|
223
|
+
if (argv) {
|
|
224
|
+
this.CLI.parse(argv, { from: 'user' });
|
|
225
|
+
} else {
|
|
226
|
+
// parse real process.argv
|
|
227
|
+
this.CLI.parse();
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// If no subcommand was given, show help
|
|
231
|
+
if (!this.CLI.args.length) {
|
|
232
|
+
this.CLI.help();
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
export default new DidBtcr2Cli().run();
|
package/src/command.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { IdentifierTypes, Logger, MethodError } from '@did-btcr2/common';
|
|
2
|
+
import { DidBtcr2, DidResolutionOptions } from '@did-btcr2/method';
|
|
3
|
+
|
|
4
|
+
export interface CommandInterface {
|
|
5
|
+
execute(params: { options?: any; action?: string }): Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface ExecuteParams {
|
|
9
|
+
options?: any;
|
|
10
|
+
action?: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default class Btcr2Command implements CommandInterface {
|
|
14
|
+
async execute({ options, action }: ExecuteParams): Promise<void> {
|
|
15
|
+
try {
|
|
16
|
+
switch (action) {
|
|
17
|
+
case 'create':{
|
|
18
|
+
const { type, bytes } = options as { type: string; bytes: string };
|
|
19
|
+
const idType = type === 'k' ? IdentifierTypes.KEY : IdentifierTypes.EXTERNAL;
|
|
20
|
+
const genesisBytes = Buffer.from(bytes, 'hex').toArray().toUint8Array();
|
|
21
|
+
const did = await DidBtcr2.create({ idType, genesisBytes });
|
|
22
|
+
console.log(did);
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
case 'read':
|
|
26
|
+
case 'resolve': {
|
|
27
|
+
const { identifier, options: resolutionOptions } = options as DidResolutionOptions;
|
|
28
|
+
const resolutionResult = await DidBtcr2.resolve(identifier, resolutionOptions);
|
|
29
|
+
console.log(JSON.stringify(resolutionResult, null, 2));
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
case 'update': {
|
|
33
|
+
const update = await DidBtcr2.update(options);
|
|
34
|
+
console.log(JSON.stringify(update, null, 2));
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
case 'delete':
|
|
38
|
+
case 'deactivate':
|
|
39
|
+
// await DidBtcr2.deactivate(options);
|
|
40
|
+
Logger.warn('// TODO: Update once DidBtcr2.deactivate implemented');
|
|
41
|
+
break;
|
|
42
|
+
default:
|
|
43
|
+
throw new MethodError(`Invalid command: ${action}`, 'INVALID_COMMAND');
|
|
44
|
+
}
|
|
45
|
+
} catch (error: any) {
|
|
46
|
+
console.error(error);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
package/src/index.ts
ADDED