web5-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.
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+
3
+ import('../dist/index.js').catch(console.error)
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function createDidCommand(): Command;
@@ -0,0 +1,59 @@
1
+ import { Command } from 'commander';
2
+ import { didManagerWithExit } from '../utils/did.js';
3
+ export function createDidCommand() {
4
+ const command = new Command('did')
5
+ .description('Manage DID operations');
6
+ command
7
+ .command('build-create-tx')
8
+ .description('Build transaction to create a new DID')
9
+ .requiredOption('--username <username>', 'Username for the DID')
10
+ .requiredOption('--pds <pds>', 'PDS host (e.g., web5.bbsfans.dev)')
11
+ .requiredOption('--didkey <didkey>', 'DID key for atproto verification')
12
+ .requiredOption('--output-path <path>', 'Output path for transaction JSON')
13
+ .action(async (options) => {
14
+ await didManagerWithExit.buildCreateTx(options.username, options.pds, options.didkey, options.outputPath);
15
+ });
16
+ command
17
+ .command('build-destroy-tx')
18
+ .description('Build transaction to destroy a DID')
19
+ .requiredOption('--args <args>', 'DID args (type script args)')
20
+ .requiredOption('--output-path <path>', 'Output path for transaction JSON')
21
+ .action(async (options) => {
22
+ await didManagerWithExit.buildDestroyTx(options.args, options.outputPath);
23
+ });
24
+ command
25
+ .command('build-update-didkey-tx')
26
+ .description('Build transaction to update DID key')
27
+ .requiredOption('--args <args>', 'DID args (type script args)')
28
+ .requiredOption('--new-didkey <didKey>', 'New DID key')
29
+ .requiredOption('--output-path <path>', 'Output path for transaction JSON')
30
+ .action(async (options) => {
31
+ await didManagerWithExit.buildUpdateDidKeyTx(options.args, options.newDidkey, options.outputPath);
32
+ });
33
+ command
34
+ .command('build-update-handle-tx')
35
+ .description('Build transaction to update DID handle')
36
+ .requiredOption('--args <args>', 'DID args (type script args)')
37
+ .requiredOption('--new-handle <handle>', 'New handle (e.g., david1.web5.bbsfans.dev)')
38
+ .requiredOption('--output-path <path>', 'Output path for transaction JSON')
39
+ .action(async (options) => {
40
+ await didManagerWithExit.buildUpdateHandleTx(options.args, options.newHandle, options.outputPath);
41
+ });
42
+ command
43
+ .command('build-transfer-tx')
44
+ .description('Build transaction to transfer DID')
45
+ .requiredOption('--args <args>', 'DID args (type script args)')
46
+ .requiredOption('--receiver <address>', 'Receiver CKB address')
47
+ .requiredOption('--output-path <path>', 'Output path for transaction JSON')
48
+ .action(async (options) => {
49
+ await didManagerWithExit.buildTransferTx(options.args, options.receiver, options.outputPath);
50
+ });
51
+ command
52
+ .command('list')
53
+ .description('List DID cells for a CKB address')
54
+ .requiredOption('--ckb-addr <address>', 'CKB address')
55
+ .action(async (options) => {
56
+ await didManagerWithExit.list(options.ckbAddr);
57
+ });
58
+ return command;
59
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function createKeystoreCommand(): Command;
@@ -0,0 +1,48 @@
1
+ import { Command } from 'commander';
2
+ import { keystoreManager } from '../utils/keystore.js';
3
+ export function createKeystoreCommand() {
4
+ const command = new Command('keystore')
5
+ .description('Manage DID signing keys');
6
+ command
7
+ .command('new')
8
+ .description('Create a new keypair')
9
+ .action(async () => {
10
+ await keystoreManager.newKey();
11
+ });
12
+ command
13
+ .command('import')
14
+ .description('Import an existing private key')
15
+ .requiredOption('--sk <privateKey>', 'Private key to import (hex format)')
16
+ .action(async (options) => {
17
+ await keystoreManager.importKey(options.sk);
18
+ });
19
+ command
20
+ .command('clean')
21
+ .description('Remove the existing keypair')
22
+ .action(async () => {
23
+ await keystoreManager.clean();
24
+ });
25
+ command
26
+ .command('get')
27
+ .description('Get the DID key')
28
+ .action(async () => {
29
+ await keystoreManager.getDIDKey();
30
+ });
31
+ command
32
+ .command('sign')
33
+ .description('Sign a message')
34
+ .requiredOption('--message <message>', 'Message to sign (hex format)')
35
+ .action(async (options) => {
36
+ await keystoreManager.sign(options.message);
37
+ });
38
+ command
39
+ .command('verify')
40
+ .description('Verify a signature')
41
+ .requiredOption('--message <message>', 'Original message (hex format)')
42
+ .requiredOption('--signature <signature>', 'Signature to verify (hex format)')
43
+ .option('--didkey <didKey>', 'DID key (if not provided, uses local keypair)')
44
+ .action(async (options) => {
45
+ await keystoreManager.verify(options.message, options.signature, options.didkey);
46
+ });
47
+ return command;
48
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function createPdsCommand(): Command;
@@ -0,0 +1,144 @@
1
+ import { Command } from 'commander';
2
+ import { pdsManager } from '../utils/pds.js';
3
+ import { SIGNKEY_PATH, readKey } from '../utils/common.js';
4
+ async function getSignKey() {
5
+ return readKey(SIGNKEY_PATH);
6
+ }
7
+ export function createPdsCommand() {
8
+ const command = new Command('pds')
9
+ .description('Interact with PDS servers');
10
+ command
11
+ .command('check-username')
12
+ .description('Check if username is valid')
13
+ .requiredOption('--username <username>', 'Username to check')
14
+ .action(async (options) => {
15
+ await pdsManager.checkUsername(options.username);
16
+ });
17
+ command
18
+ .command('get-did-by-username')
19
+ .description('Get DID by username')
20
+ .requiredOption('--username <username>', 'Username')
21
+ .requiredOption('--pds <pds>', 'PDS host (e.g., web5.bbsfans.dev)')
22
+ .action(async (options) => {
23
+ await pdsManager.getDidByUsername(options.username, options.pds);
24
+ });
25
+ command
26
+ .command('create-account')
27
+ .description('Create an account on PDS')
28
+ .requiredOption('--pds <pds>', 'PDS host')
29
+ .requiredOption('--username <username>', 'Username')
30
+ .requiredOption('--didkey <didKey>', 'DID key')
31
+ .requiredOption('--did <did>', 'DID')
32
+ .requiredOption('--ckb-address <address>', 'CKB address')
33
+ .action(async (options) => {
34
+ const signKey = await getSignKey();
35
+ if (!signKey) {
36
+ console.log(JSON.stringify({ success: false, error: 'No signkey found. Use "keystore new" or "keystore import" first.' }, null, 2));
37
+ return;
38
+ }
39
+ await pdsManager.createAccount(options.pds, options.username, options.didkey, options.did, options.ckbAddress, signKey);
40
+ });
41
+ command
42
+ .command('delete-account')
43
+ .description('Delete an account on PDS')
44
+ .requiredOption('--pds <pds>', 'PDS host')
45
+ .requiredOption('--didkey <didKey>', 'DID key')
46
+ .requiredOption('--did <did>', 'DID')
47
+ .requiredOption('--ckb-address <address>', 'CKB address')
48
+ .action(async (options) => {
49
+ const signKey = await getSignKey();
50
+ if (!signKey) {
51
+ console.log(JSON.stringify({ success: false, error: 'No signkey found. Use "keystore new" or "keystore import" first.' }, null, 2));
52
+ return;
53
+ }
54
+ await pdsManager.deleteAccount(options.pds, options.didkey, options.did, options.ckbAddress, signKey);
55
+ });
56
+ command
57
+ .command('login')
58
+ .description('Login to PDS')
59
+ .requiredOption('--pds <pds>', 'PDS host')
60
+ .requiredOption('--didkey <didKey>', 'DID key')
61
+ .requiredOption('--did <did>', 'DID')
62
+ .requiredOption('--ckb-address <address>', 'CKB address')
63
+ .action(async (options) => {
64
+ const signKey = await getSignKey();
65
+ if (!signKey) {
66
+ console.log(JSON.stringify({ success: false, error: 'No signkey found. Use "keystore new" or "keystore import" first.' }, null, 2));
67
+ return;
68
+ }
69
+ await pdsManager.login(options.pds, options.didkey, options.did, options.ckbAddress, signKey);
70
+ });
71
+ command
72
+ .command('write')
73
+ .description('Write data to PDS')
74
+ .requiredOption('--pds <pds>', 'PDS host')
75
+ .requiredOption('--accessJwt <token>', 'Access JWT token')
76
+ .requiredOption('--didkey <didKey>', 'DID key')
77
+ .requiredOption('--did <did>', 'DID')
78
+ .requiredOption('--data <json>', 'Data to write (JSON string)')
79
+ .option('--rkey <rkey>', 'Record key (optional)')
80
+ .option('--type <type>', 'Write type: create, update, or delete (default: create)')
81
+ .action(async (options) => {
82
+ const signKey = await getSignKey();
83
+ if (!signKey) {
84
+ console.log(JSON.stringify({ success: false, error: 'No signkey found. Use "keystore new" or "keystore import" first.' }, null, 2));
85
+ return;
86
+ }
87
+ const writeType = options.type || 'create';
88
+ if (!['create', 'update', 'delete'].includes(writeType)) {
89
+ console.log(JSON.stringify({ success: false, error: 'Invalid type. Must be one of: create, update, delete' }, null, 2));
90
+ return;
91
+ }
92
+ await pdsManager.write(options.pds, options.accessJwt, options.didkey, options.did, options.data, signKey, options.rkey, writeType);
93
+ });
94
+ command
95
+ .command('repo')
96
+ .description('Get repo information')
97
+ .requiredOption('--pds <pds>', 'PDS host')
98
+ .requiredOption('--did <did>', 'DID')
99
+ .action(async (options) => {
100
+ await pdsManager.repo(options.pds, options.did);
101
+ });
102
+ command
103
+ .command('records')
104
+ .description('Get repo records')
105
+ .requiredOption('--pds <pds>', 'PDS host')
106
+ .requiredOption('--did <did>', 'DID')
107
+ .requiredOption('--collection <collection>', 'Collection name')
108
+ .option('--limit <limit>', 'Limit', '20')
109
+ .option('--cursor <cursor>', 'Cursor for pagination')
110
+ .action(async (options) => {
111
+ await pdsManager.records(options.pds, options.did, options.collection, parseInt(options.limit), options.cursor);
112
+ });
113
+ command
114
+ .command('blobs')
115
+ .description('Get repo blobs')
116
+ .requiredOption('--pds <pds>', 'PDS host')
117
+ .requiredOption('--did <did>', 'DID')
118
+ .option('--limit <limit>', 'Limit', '20')
119
+ .option('--cursor <cursor>', 'Cursor for pagination')
120
+ .action(async (options) => {
121
+ await pdsManager.blobs(options.pds, options.did, parseInt(options.limit), options.cursor);
122
+ });
123
+ command
124
+ .command('export')
125
+ .description('Export repo to CAR file')
126
+ .requiredOption('--pds <pds>', 'PDS host')
127
+ .requiredOption('--did <did>', 'DID')
128
+ .requiredOption('--data-file <path>', 'Output file path')
129
+ .option('--since <since>', 'Since CID (optional)')
130
+ .action(async (options) => {
131
+ await pdsManager.exportRepo(options.pds, options.did, options.dataFile, options.since);
132
+ });
133
+ command
134
+ .command('import')
135
+ .description('Import repo from CAR file')
136
+ .requiredOption('--pds <pds>', 'PDS host')
137
+ .requiredOption('--did <did>', 'DID')
138
+ .requiredOption('--accessJwt <token>', 'Access JWT token')
139
+ .requiredOption('--data-file <path>', 'Input file path')
140
+ .action(async (options) => {
141
+ await pdsManager.importRepo(options.pds, options.did, options.accessJwt, options.dataFile);
142
+ });
143
+ return command;
144
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function createWalletCommand(): Command;
@@ -0,0 +1,52 @@
1
+ import { Command } from 'commander';
2
+ import { walletManagerWithExit } from '../utils/wallet.js';
3
+ export function createWalletCommand() {
4
+ const command = new Command('wallet')
5
+ .description('Manage CKB wallet');
6
+ command
7
+ .command('new')
8
+ .description('Create a new CKB wallet')
9
+ .action(async () => {
10
+ await walletManagerWithExit.newWallet();
11
+ });
12
+ command
13
+ .command('import')
14
+ .description('Import an existing private key')
15
+ .requiredOption('--sk <privateKey>', 'Private key to import (hex format)')
16
+ .action(async (options) => {
17
+ await walletManagerWithExit.importWallet(options.sk);
18
+ });
19
+ command
20
+ .command('clean')
21
+ .description('Remove the existing wallet')
22
+ .action(async () => {
23
+ await walletManagerWithExit.clean();
24
+ });
25
+ command
26
+ .command('get')
27
+ .description('Get the CKB address')
28
+ .action(async () => {
29
+ await walletManagerWithExit.getAddress();
30
+ });
31
+ command
32
+ .command('send-tx')
33
+ .description('Send a transaction')
34
+ .requiredOption('--tx-path <path>', 'Path to the transaction JSON file')
35
+ .action(async (options) => {
36
+ await walletManagerWithExit.sendTx(options.txPath);
37
+ });
38
+ command
39
+ .command('check-tx')
40
+ .description('Check transaction status')
41
+ .requiredOption('--tx-hash <txHash>', 'Transaction hash')
42
+ .action(async (options) => {
43
+ await walletManagerWithExit.checkTx(options.txHash);
44
+ });
45
+ command
46
+ .command('balance')
47
+ .description('Check account balance')
48
+ .action(async () => {
49
+ await walletManagerWithExit.balance();
50
+ });
51
+ return command;
52
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { createKeystoreCommand } from './commands/keystore.js';
4
+ import { createWalletCommand } from './commands/wallet.js';
5
+ import { createDidCommand } from './commands/did.js';
6
+ import { createPdsCommand } from './commands/pds.js';
7
+ const program = new Command();
8
+ program
9
+ .name('web5-cli')
10
+ .description('Web5 CLI tool for interacting with Web5 infrastructure')
11
+ .version('0.0.1');
12
+ program.addCommand(createKeystoreCommand());
13
+ program.addCommand(createWalletCommand());
14
+ program.addCommand(createDidCommand());
15
+ program.addCommand(createPdsCommand());
16
+ program.parse();
@@ -0,0 +1,20 @@
1
+ export declare const CLI_DIR: string;
2
+ export declare const SIGNKEY_PATH: string;
3
+ export declare const CKB_SK_PATH: string;
4
+ export interface Output {
5
+ success: boolean;
6
+ data?: unknown;
7
+ error?: string;
8
+ }
9
+ export declare function outputJSON(result: Output): void;
10
+ export declare function success(data?: unknown): void;
11
+ export declare function error(message: string): void;
12
+ export declare function ensureDir(): Promise<void>;
13
+ export declare function readKey(path: string): Promise<string | null>;
14
+ export declare function writeKey(path: string, key: string): Promise<void>;
15
+ export declare function removeKey(path: string): Promise<boolean>;
16
+ export declare function keyExists(path: string): boolean;
17
+ export declare function bytesFromHex(hex: string): Uint8Array;
18
+ export declare function hexFromBytes(bytes: Uint8Array): string;
19
+ export declare function writeJsonFile(path: string, data: unknown): Promise<void>;
20
+ export declare function readJsonFile(path: string): Promise<unknown | null>;
@@ -0,0 +1,75 @@
1
+ import { mkdir, readFile, writeFile, unlink } from 'fs/promises';
2
+ import { existsSync } from 'fs';
3
+ import { dirname, join } from 'path';
4
+ import { homedir } from 'os';
5
+ export const CLI_DIR = join(homedir(), '.web5-cli');
6
+ export const SIGNKEY_PATH = join(CLI_DIR, 'signkey');
7
+ export const CKB_SK_PATH = join(CLI_DIR, 'ckb-sk');
8
+ export function outputJSON(result) {
9
+ console.log(JSON.stringify(result, null, 2));
10
+ }
11
+ export function success(data) {
12
+ outputJSON({ success: true, data });
13
+ }
14
+ export function error(message) {
15
+ outputJSON({ success: false, error: message });
16
+ }
17
+ export async function ensureDir() {
18
+ if (!existsSync(CLI_DIR)) {
19
+ await mkdir(CLI_DIR, { recursive: true });
20
+ }
21
+ }
22
+ export async function readKey(path) {
23
+ try {
24
+ const data = await readFile(path, 'utf-8');
25
+ return data.trim();
26
+ }
27
+ catch {
28
+ return null;
29
+ }
30
+ }
31
+ export async function writeKey(path, key) {
32
+ await ensureDir();
33
+ await writeFile(path, key, 'utf-8');
34
+ }
35
+ export async function removeKey(path) {
36
+ try {
37
+ await unlink(path);
38
+ return true;
39
+ }
40
+ catch {
41
+ return false;
42
+ }
43
+ }
44
+ export function keyExists(path) {
45
+ return existsSync(path);
46
+ }
47
+ export function bytesFromHex(hex) {
48
+ if (hex.startsWith('0x')) {
49
+ hex = hex.slice(2);
50
+ }
51
+ const match = hex.match(/.{1,2}/g);
52
+ if (!match) {
53
+ return new Uint8Array();
54
+ }
55
+ return new Uint8Array(match.map((byte) => parseInt(byte, 16)));
56
+ }
57
+ export function hexFromBytes(bytes) {
58
+ return '0x' + Array.from(bytes).map((byte) => byte.toString(16).padStart(2, '0')).join('');
59
+ }
60
+ export async function writeJsonFile(path, data) {
61
+ const dir = dirname(path);
62
+ if (!existsSync(dir)) {
63
+ await mkdir(dir, { recursive: true });
64
+ }
65
+ await writeFile(path, JSON.stringify(data, null, 2), 'utf-8');
66
+ }
67
+ export async function readJsonFile(path) {
68
+ try {
69
+ const data = await readFile(path, 'utf-8');
70
+ return JSON.parse(data);
71
+ }
72
+ catch {
73
+ return null;
74
+ }
75
+ }
@@ -0,0 +1,18 @@
1
+ export interface didCkbCellInfo {
2
+ txHash: string;
3
+ index: number;
4
+ args: string;
5
+ capacity: string;
6
+ did: string;
7
+ didMetadata: string;
8
+ }
9
+ export interface DidManager {
10
+ buildCreateTx(username: string, pds: string, didkey: string, outputPath: string): Promise<void>;
11
+ buildDestroyTx(args: string, outputPath: string): Promise<void>;
12
+ buildUpdateDidKeyTx(args: string, newDidKey: string, outputPath: string): Promise<void>;
13
+ buildUpdateHandleTx(args: string, newHandle: string, outputPath: string): Promise<void>;
14
+ buildTransferTx(args: string, receiver: string, outputPath: string): Promise<void>;
15
+ list(ckbAddr: string): Promise<void>;
16
+ }
17
+ export declare const didManager: DidManager;
18
+ export declare const didManagerWithExit: DidManager;