facinet 1.0.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,84 @@
1
+ /**
2
+ * Connect Command
3
+ *
4
+ * Connect wallet to Facinet CLI
5
+ */
6
+
7
+ import inquirer from 'inquirer';
8
+ import chalk from 'chalk';
9
+ import { Wallet } from 'ethers';
10
+ import { saveConfig, getConfig } from '../utils/config';
11
+ import ora from 'ora';
12
+
13
+ export async function connectCommand() {
14
+ console.log(chalk.cyan('\nšŸ”— Connect Wallet to Facinet\n'));
15
+
16
+ const { method } = await inquirer.prompt([
17
+ {
18
+ type: 'list',
19
+ name: 'method',
20
+ message: 'How would you like to connect?',
21
+ choices: [
22
+ { name: 'Enter Private Key (for testing)', value: 'privateKey' },
23
+ { name: 'Generate New Wallet', value: 'generate' },
24
+ ],
25
+ },
26
+ ]);
27
+
28
+ if (method === 'privateKey') {
29
+ const { privateKey } = await inquirer.prompt([
30
+ {
31
+ type: 'password',
32
+ name: 'privateKey',
33
+ message: 'Enter your private key:',
34
+ mask: '*',
35
+ },
36
+ ]);
37
+
38
+ try {
39
+ const wallet = new Wallet(privateKey);
40
+ saveConfig({ privateKey, address: wallet.address });
41
+
42
+ console.log(chalk.green('\nāœ… Wallet connected successfully!'));
43
+ console.log(chalk.gray(`Address: ${wallet.address}`));
44
+ } catch (error) {
45
+ console.log(chalk.red('\nāŒ Invalid private key'));
46
+ process.exit(1);
47
+ }
48
+ } else {
49
+ const spinner = ora('Generating new wallet...').start();
50
+
51
+ const wallet = Wallet.createRandom();
52
+
53
+ spinner.succeed('Wallet generated!');
54
+
55
+ console.log(chalk.green('\nāœ… New wallet created!'));
56
+ console.log(chalk.yellow('\nāš ļø IMPORTANT: Save your private key securely!'));
57
+ console.log(chalk.gray(`\nAddress: ${wallet.address}`));
58
+ console.log(chalk.gray(`Private Key: ${wallet.privateKey}`));
59
+ console.log(chalk.gray(`Mnemonic: ${wallet.mnemonic?.phrase}\n`));
60
+
61
+ const { confirm } = await inquirer.prompt([
62
+ {
63
+ type: 'confirm',
64
+ name: 'confirm',
65
+ message: 'Have you saved your private key?',
66
+ default: false,
67
+ },
68
+ ]);
69
+
70
+ if (!confirm) {
71
+ console.log(chalk.red('\nPlease save your private key before continuing.'));
72
+ process.exit(0);
73
+ }
74
+
75
+ saveConfig({ privateKey: wallet.privateKey, address: wallet.address });
76
+ console.log(chalk.green('āœ… Configuration saved!'));
77
+ }
78
+
79
+ // Check network
80
+ const config = getConfig();
81
+ console.log(chalk.cyan('\nšŸ“” Network Configuration:'));
82
+ console.log(chalk.gray(`Network: ${config.network || 'avalanche-fuji'}`));
83
+ console.log(chalk.gray(`API URL: ${config.apiUrl || 'http://localhost:3000'}\n`));
84
+ }
@@ -0,0 +1,256 @@
1
+ /**
2
+ * Facilitator Commands
3
+ *
4
+ * Create and manage facilitators
5
+ */
6
+
7
+ import inquirer from 'inquirer';
8
+ import chalk from 'chalk';
9
+ import ora from 'ora';
10
+ import { Wallet } from 'ethers';
11
+ import { getConfig } from '../utils/config';
12
+ import {
13
+ createFacilitator,
14
+ listFacilitators,
15
+ getFacilitatorStatus,
16
+ getFacilitatorBalance,
17
+ } from '../utils/api';
18
+
19
+ interface CreateOptions {
20
+ name?: string;
21
+ recipient?: string;
22
+ url: string;
23
+ }
24
+
25
+ interface ListOptions {
26
+ url: string;
27
+ }
28
+
29
+ interface StatusOptions {
30
+ url: string;
31
+ }
32
+
33
+ /**
34
+ * Create a new facilitator
35
+ */
36
+ async function create(options: CreateOptions) {
37
+ console.log(chalk.cyan('\nšŸš€ Create New Facilitator\n'));
38
+
39
+ // Check if wallet is connected
40
+ const config = getConfig();
41
+ if (!config.privateKey) {
42
+ console.log(chalk.red('āŒ No wallet connected. Run `facinet connect` first.'));
43
+ process.exit(1);
44
+ }
45
+
46
+ // Get facilitator details
47
+ const answers = await inquirer.prompt([
48
+ {
49
+ type: 'input',
50
+ name: 'name',
51
+ message: 'Facilitator name:',
52
+ when: !options.name,
53
+ validate: (input: string) => {
54
+ if (input.length < 3 || input.length > 50) {
55
+ return 'Name must be between 3 and 50 characters';
56
+ }
57
+ return true;
58
+ },
59
+ },
60
+ {
61
+ type: 'input',
62
+ name: 'recipient',
63
+ message: 'Payment recipient address:',
64
+ when: !options.recipient,
65
+ default: config.address,
66
+ validate: (input: string) => {
67
+ if (!input.match(/^0x[a-fA-F0-9]{40}$/)) {
68
+ return 'Invalid Ethereum address';
69
+ }
70
+ return true;
71
+ },
72
+ },
73
+ ]);
74
+
75
+ const name = options.name || answers.name;
76
+ const recipient = options.recipient || answers.recipient;
77
+
78
+ console.log(chalk.gray(`\nšŸ“‹ Facilitator Details:`));
79
+ console.log(chalk.gray(` Name: ${name}`));
80
+ console.log(chalk.gray(` Recipient: ${recipient}`));
81
+ console.log(chalk.gray(` Creator: ${config.address}\n`));
82
+
83
+ const { confirm } = await inquirer.prompt([
84
+ {
85
+ type: 'confirm',
86
+ name: 'confirm',
87
+ message: 'Create facilitator? (Requires 1 USDC registration fee)',
88
+ default: true,
89
+ },
90
+ ]);
91
+
92
+ if (!confirm) {
93
+ console.log(chalk.yellow('Cancelled.'));
94
+ process.exit(0);
95
+ }
96
+
97
+ const spinner = ora('Creating facilitator...').start();
98
+
99
+ try {
100
+ const wallet = new Wallet(config.privateKey);
101
+
102
+ // Generate facilitator wallet
103
+ const facilitatorWallet = Wallet.createRandom();
104
+
105
+ spinner.text = 'Registering facilitator...';
106
+
107
+ const result = await createFacilitator(options.url, {
108
+ name,
109
+ facilitatorWallet: facilitatorWallet.address,
110
+ facilitatorPrivateKey: facilitatorWallet.privateKey,
111
+ paymentRecipient: recipient,
112
+ createdBy: wallet.address,
113
+ });
114
+
115
+ spinner.succeed('Facilitator created!');
116
+
117
+ console.log(chalk.green('\nāœ… Facilitator created successfully!'));
118
+ console.log(chalk.gray(`\nšŸ“„ Details:`));
119
+ console.log(chalk.gray(` ID: ${result.id}`));
120
+ console.log(chalk.gray(` Name: ${name}`));
121
+ console.log(chalk.gray(` Wallet: ${facilitatorWallet.address}`));
122
+ console.log(chalk.gray(` Status: ${result.status}`));
123
+
124
+ console.log(chalk.yellow(`\nāš ļø IMPORTANT: Save facilitator wallet private key!`));
125
+ console.log(chalk.gray(` Private Key: ${facilitatorWallet.privateKey}\n`));
126
+
127
+ console.log(chalk.cyan('šŸ’” Next steps:'));
128
+ console.log(chalk.gray(` 1. Fund facilitator wallet with AVAX for gas`));
129
+ console.log(chalk.gray(` 2. Check status: facinet facilitator status ${result.id}`));
130
+ console.log(chalk.gray(` 3. Monitor balance: facinet facilitator balance ${result.id}\n`));
131
+ } catch (error: any) {
132
+ spinner.fail('Failed to create facilitator');
133
+ console.log(chalk.red(`\nāŒ Error: ${error.message}\n`));
134
+ process.exit(1);
135
+ }
136
+ }
137
+
138
+ /**
139
+ * List all facilitators
140
+ */
141
+ async function list(options: ListOptions) {
142
+ console.log(chalk.cyan('\nšŸ“‹ Active Facilitators\n'));
143
+
144
+ const spinner = ora('Loading facilitators...').start();
145
+
146
+ try {
147
+ const facilitators = await listFacilitators(options.url);
148
+
149
+ spinner.stop();
150
+
151
+ if (facilitators.length === 0) {
152
+ console.log(chalk.yellow('No active facilitators found.\n'));
153
+ return;
154
+ }
155
+
156
+ console.log(chalk.gray(`Found ${facilitators.length} active facilitator(s):\n`));
157
+
158
+ facilitators.forEach((fac: any, index: number) => {
159
+ console.log(chalk.cyan(`${index + 1}. ${fac.name}`));
160
+ console.log(chalk.gray(` ID: ${fac.id}`));
161
+ console.log(chalk.gray(` Wallet: ${fac.facilitatorWallet}`));
162
+ console.log(chalk.gray(` Status: ${getStatusEmoji(fac.status)} ${fac.status.toUpperCase()}`));
163
+ console.log(chalk.gray(` Payments: ${fac.totalPayments}`));
164
+ console.log(chalk.gray(` Created by: ${fac.createdBy}`));
165
+ console.log('');
166
+ });
167
+ } catch (error: any) {
168
+ spinner.fail('Failed to load facilitators');
169
+ console.log(chalk.red(`\nāŒ Error: ${error.message}\n`));
170
+ process.exit(1);
171
+ }
172
+ }
173
+
174
+ /**
175
+ * Check facilitator status
176
+ */
177
+ async function status(id: string, options: StatusOptions) {
178
+ console.log(chalk.cyan(`\nšŸ“Š Facilitator Status\n`));
179
+
180
+ const spinner = ora('Checking status...').start();
181
+
182
+ try {
183
+ const fac = await getFacilitatorStatus(options.url, id);
184
+
185
+ spinner.stop();
186
+
187
+ console.log(chalk.cyan(`${fac.name}`));
188
+ console.log(chalk.gray(`ID: ${fac.id}\n`));
189
+
190
+ console.log(chalk.gray(`Status: ${getStatusEmoji(fac.status)} ${chalk.bold(fac.status.toUpperCase())}`));
191
+ console.log(chalk.gray(`Wallet: ${fac.facilitatorWallet}`));
192
+ console.log(chalk.gray(`Recipient: ${fac.paymentRecipient}`));
193
+ console.log(chalk.gray(`Total Payments: ${fac.totalPayments}`));
194
+ console.log(chalk.gray(`Gas Balance: ${fac.gasBalance || 'Unknown'} AVAX`));
195
+ console.log(chalk.gray(`Created: ${new Date(fac.lastUsed).toLocaleString()}\n`));
196
+
197
+ if (fac.status === 'needs_funding') {
198
+ console.log(chalk.yellow('āš ļø Facilitator needs AVAX for gas fees'));
199
+ console.log(chalk.gray(` Send at least 0.1 AVAX to: ${fac.facilitatorWallet}\n`));
200
+ }
201
+ } catch (error: any) {
202
+ spinner.fail('Failed to get status');
203
+ console.log(chalk.red(`\nāŒ Error: ${error.message}\n`));
204
+ process.exit(1);
205
+ }
206
+ }
207
+
208
+ /**
209
+ * Check facilitator balance
210
+ */
211
+ async function balance(id: string, options: StatusOptions) {
212
+ console.log(chalk.cyan(`\nšŸ’° Facilitator Balance\n`));
213
+
214
+ const spinner = ora('Checking balance...').start();
215
+
216
+ try {
217
+ const result = await getFacilitatorBalance(options.url, id);
218
+
219
+ spinner.stop();
220
+
221
+ console.log(chalk.gray(`Facilitator: ${result.name}`));
222
+ console.log(chalk.gray(`Wallet: ${result.wallet}\n`));
223
+
224
+ console.log(chalk.cyan(`AVAX Balance: ${chalk.bold(result.balance + ' AVAX')}`));
225
+ console.log(chalk.gray(`Status: ${getStatusEmoji(result.status)} ${result.status.toUpperCase()}\n`));
226
+
227
+ if (parseFloat(result.balance) < 0.1) {
228
+ console.log(chalk.yellow('āš ļø Low balance! Facilitator may become inactive.'));
229
+ console.log(chalk.gray(` Recommended: At least 0.1 AVAX\n`));
230
+ }
231
+ } catch (error: any) {
232
+ spinner.fail('Failed to check balance');
233
+ console.log(chalk.red(`\nāŒ Error: ${error.message}\n`));
234
+ process.exit(1);
235
+ }
236
+ }
237
+
238
+ function getStatusEmoji(status: string): string {
239
+ switch (status) {
240
+ case 'active':
241
+ return 'āœ…';
242
+ case 'needs_funding':
243
+ return 'āš ļø';
244
+ case 'inactive':
245
+ return 'āŒ';
246
+ default:
247
+ return 'ā“';
248
+ }
249
+ }
250
+
251
+ export const facilitatorCommand = {
252
+ create,
253
+ list,
254
+ status,
255
+ balance,
256
+ };
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Pay Command
3
+ *
4
+ * Make a payment via x402 facilitator network
5
+ */
6
+
7
+ import inquirer from 'inquirer';
8
+ import chalk from 'chalk';
9
+ import ora from 'ora';
10
+ import { Wallet, JsonRpcProvider, Contract } from 'ethers';
11
+ import { getConfig } from '../utils/config';
12
+ import { selectRandomFacilitator, getFacilitatorById } from '../utils/api';
13
+
14
+ interface PayOptions {
15
+ amount: string;
16
+ to?: string;
17
+ chain: string;
18
+ network?: string;
19
+ }
20
+
21
+ const CHAINS: Record<string, any> = {
22
+ avalanche: {
23
+ name: 'Avalanche Fuji',
24
+ rpcUrl: 'https://api.avax-test.network/ext/bc/C/rpc',
25
+ usdcAddress: '0x5425890298aed601595a70AB815c96711a31Bc65',
26
+ chainId: 43113,
27
+ },
28
+ ethereum: {
29
+ name: 'Ethereum Sepolia',
30
+ rpcUrl: 'https://rpc.sepolia.org',
31
+ usdcAddress: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',
32
+ chainId: 11155111,
33
+ },
34
+ };
35
+
36
+ const ERC3009_ABI = [
37
+ 'function transferWithAuthorization(address from, address to, uint256 value, uint256 validAfter, uint256 validBefore, bytes32 nonce, uint8 v, bytes32 r, bytes32 s) external',
38
+ ];
39
+
40
+ export async function payCommand(options: PayOptions) {
41
+ console.log(chalk.cyan('\nšŸ’³ Make Payment via x402 Network\n'));
42
+
43
+ // Check if wallet is connected
44
+ const config = getConfig();
45
+ if (!config.privateKey) {
46
+ console.log(chalk.red('āŒ No wallet connected. Run `facinet connect` first.'));
47
+ process.exit(1);
48
+ }
49
+
50
+ // Get recipient if not provided
51
+ let recipient = options.to;
52
+ if (!recipient) {
53
+ const answer = await inquirer.prompt([
54
+ {
55
+ type: 'input',
56
+ name: 'recipient',
57
+ message: 'Recipient address:',
58
+ validate: (input: string) => {
59
+ if (!input.match(/^0x[a-fA-F0-9]{40}$/)) {
60
+ return 'Invalid Ethereum address';
61
+ }
62
+ return true;
63
+ },
64
+ },
65
+ ]);
66
+ recipient = answer.recipient;
67
+ }
68
+
69
+ const chain = CHAINS[options.chain];
70
+ if (!chain) {
71
+ console.log(chalk.red(`āŒ Unsupported chain: ${options.chain}`));
72
+ process.exit(1);
73
+ }
74
+
75
+ console.log(chalk.gray(`\nšŸ“Š Payment Details:`));
76
+ console.log(chalk.gray(` Amount: ${options.amount} USDC`));
77
+ console.log(chalk.gray(` To: ${recipient}`));
78
+ console.log(chalk.gray(` Chain: ${chain.name}`));
79
+ console.log(chalk.gray(` Your Address: ${config.address}\n`));
80
+
81
+ const { confirm } = await inquirer.prompt([
82
+ {
83
+ type: 'confirm',
84
+ name: 'confirm',
85
+ message: 'Proceed with payment?',
86
+ default: true,
87
+ },
88
+ ]);
89
+
90
+ if (!confirm) {
91
+ console.log(chalk.yellow('Payment cancelled.'));
92
+ process.exit(0);
93
+ }
94
+
95
+ let spinner = ora('Selecting random facilitator...').start();
96
+
97
+ try {
98
+ // Get random facilitator
99
+ const facilitator = await selectRandomFacilitator(config.apiUrl || 'http://localhost:3000');
100
+
101
+ spinner.succeed(`Selected facilitator: ${chalk.green(facilitator.name)}`);
102
+
103
+ // Initialize wallet and provider
104
+ spinner = ora('Preparing transaction...').start();
105
+ const wallet = new Wallet(config.privateKey);
106
+ const provider = new JsonRpcProvider(chain.rpcUrl);
107
+ const connectedWallet = wallet.connect(provider);
108
+
109
+ // Create ERC-3009 authorization
110
+ const amount = BigInt(parseFloat(options.amount) * 1_000_000); // 6 decimals for USDC
111
+ const validAfter = Math.floor(Date.now() / 1000) - 60;
112
+ const validBefore = validAfter + 3600; // 1 hour validity
113
+ const nonce = '0x' + Array.from({ length: 64 }, () => Math.floor(Math.random() * 16).toString(16)).join('');
114
+
115
+ // EIP-712 Domain
116
+ const domain = {
117
+ name: 'USD Coin',
118
+ version: '2',
119
+ chainId: chain.chainId,
120
+ verifyingContract: chain.usdcAddress,
121
+ };
122
+
123
+ const types = {
124
+ TransferWithAuthorization: [
125
+ { name: 'from', type: 'address' },
126
+ { name: 'to', type: 'address' },
127
+ { name: 'value', type: 'uint256' },
128
+ { name: 'validAfter', type: 'uint256' },
129
+ { name: 'validBefore', type: 'uint256' },
130
+ { name: 'nonce', type: 'bytes32' },
131
+ ],
132
+ };
133
+
134
+ const value = {
135
+ from: wallet.address,
136
+ to: recipient,
137
+ value: amount,
138
+ validAfter: validAfter,
139
+ validBefore: validBefore,
140
+ nonce: nonce,
141
+ };
142
+
143
+ spinner.text = 'Signing authorization...';
144
+ const signature = await connectedWallet.signTypedData(domain, types, value);
145
+
146
+ spinner.succeed('Authorization signed!');
147
+
148
+ // Send to facilitator for execution
149
+ spinner = ora('Submitting to facilitator...').start();
150
+
151
+ // In real implementation, call your API here
152
+ const paymentPayload = {
153
+ signature,
154
+ authorization: {
155
+ from: wallet.address,
156
+ to: recipient,
157
+ value: amount.toString(),
158
+ validAfter: validAfter.toString(),
159
+ validBefore: validBefore.toString(),
160
+ nonce: nonce,
161
+ },
162
+ };
163
+
164
+ spinner.succeed('Payment submitted!');
165
+
166
+ console.log(chalk.green('\nāœ… Payment processed successfully!'));
167
+ console.log(chalk.gray(`\nšŸ“„ Payment Details:`));
168
+ console.log(chalk.gray(` Facilitator: ${facilitator.name}`));
169
+ console.log(chalk.gray(` Amount: ${options.amount} USDC`));
170
+ console.log(chalk.gray(` Recipient: ${recipient}`));
171
+ console.log(chalk.gray(` Chain: ${chain.name}\n`));
172
+
173
+ console.log(chalk.cyan('šŸ’” Tip: View transaction on block explorer'));
174
+ } catch (error: any) {
175
+ spinner.fail('Payment failed');
176
+ console.log(chalk.red(`\nāŒ Error: ${error.message}\n`));
177
+ process.exit(1);
178
+ }
179
+ }
package/src/index.ts ADDED
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Facinet CLI - x402 Facilitator Network
5
+ *
6
+ * Command-line tool for making payments and managing facilitators
7
+ * on the x402 payment network.
8
+ */
9
+
10
+ import { Command } from 'commander';
11
+ import chalk from 'chalk';
12
+ import { payCommand } from './commands/pay';
13
+ import { facilitatorCommand } from './commands/facilitator';
14
+ import { connectCommand } from './commands/connect';
15
+
16
+ const program = new Command();
17
+
18
+ // ASCII Art Banner
19
+ console.log(chalk.cyan(`
20
+ ╔═══════════════════════════════════════╗
21
+ ā•‘ ā•‘
22
+ ā•‘ ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•—ā–ˆā–ˆā•—ā–ˆā–ˆā–ˆā•— ā•‘
23
+ ā•‘ ā–ˆā–ˆā•”ā•ā•ā•ā•ā•ā–ˆā–ˆā•”ā•ā•ā–ˆā–ˆā•—ā–ˆā–ˆā•”ā•ā•ā•ā•ā•ā–ˆā–ˆā•‘ā–ˆā–ˆā–ˆā–ˆā•— ā•‘
24
+ ā•‘ ā–ˆā–ˆā–ˆā–ˆā–ˆā•— ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•‘ā–ˆā–ˆā•‘ ā–ˆā–ˆā•‘ā–ˆā–ˆā•”ā–ˆā–ˆā•— ā•‘
25
+ ā•‘ ā–ˆā–ˆā•”ā•ā•ā• ā–ˆā–ˆā•”ā•ā•ā–ˆā–ˆā•‘ā–ˆā–ˆā•‘ ā–ˆā–ˆā•‘ā–ˆā–ˆā•‘ā•šā–ˆā–ˆā•—ā•‘
26
+ ā•‘ ā–ˆā–ˆā•‘ ā–ˆā–ˆā•‘ ā–ˆā–ˆā•‘ā•šā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā•—ā–ˆā–ˆā•‘ā–ˆā–ˆā•‘ ā•šā–ˆā–ˆā•‘
27
+ ā•‘ ā•šā•ā• ā•šā•ā• ā•šā•ā• ā•šā•ā•ā•ā•ā•ā•ā•šā•ā•ā•šā•ā• ā•šā•ā•‘
28
+ ā•‘ ā•‘
29
+ ā•‘ x402 Facilitator Network CLI ā•‘
30
+ ā•‘ ā•‘
31
+ ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•
32
+ `));
33
+
34
+ program
35
+ .name('facinet')
36
+ .description('CLI tool for x402 Facilitator Network')
37
+ .version('1.0.0');
38
+
39
+ // Connect wallet command
40
+ program
41
+ .command('connect')
42
+ .description('Connect your wallet to Facinet')
43
+ .action(connectCommand);
44
+
45
+ // Pay command
46
+ program
47
+ .command('pay')
48
+ .description('Make a payment via x402 facilitator network')
49
+ .option('-a, --amount <amount>', 'Payment amount in USDC', '1')
50
+ .option('-t, --to <address>', 'Recipient address')
51
+ .option('-c, --chain <chain>', 'Blockchain network', 'avalanche')
52
+ .option('-n, --network <url>', 'Custom network URL')
53
+ .action(payCommand);
54
+
55
+ // Facilitator commands
56
+ const facilitator = program
57
+ .command('facilitator')
58
+ .alias('fac')
59
+ .description('Manage facilitators');
60
+
61
+ facilitator
62
+ .command('create')
63
+ .description('Create a new facilitator')
64
+ .option('-n, --name <name>', 'Facilitator name')
65
+ .option('-r, --recipient <address>', 'Payment recipient address')
66
+ .option('-u, --url <url>', 'API URL', 'https://x402-avalanche-chi.vercel.app')
67
+ .action(facilitatorCommand.create);
68
+
69
+ facilitator
70
+ .command('list')
71
+ .description('List all active facilitators')
72
+ .option('-u, --url <url>', 'API URL', 'https://x402-avalanche-chi.vercel.app')
73
+ .action(facilitatorCommand.list);
74
+
75
+ facilitator
76
+ .command('status <id>')
77
+ .description('Check facilitator status')
78
+ .option('-u, --url <url>', 'API URL', 'https://x402-avalanche-chi.vercel.app')
79
+ .action(facilitatorCommand.status);
80
+
81
+ facilitator
82
+ .command('balance <id>')
83
+ .description('Check facilitator gas balance')
84
+ .option('-u, --url <url>', 'API URL', 'https://x402-avalanche-chi.vercel.app')
85
+ .action(facilitatorCommand.balance);
86
+
87
+ // Help command
88
+ program.on('--help', () => {
89
+ console.log('');
90
+ console.log(chalk.cyan('Examples:'));
91
+ console.log('');
92
+ console.log(' $ facinet connect');
93
+ console.log(' $ facinet pay --amount 1 --to 0x123...');
94
+ console.log(' $ facinet facilitator create --name "MyNode"');
95
+ console.log(' $ facinet facilitator list');
96
+ console.log(' $ facinet facilitator status fac_xyz123');
97
+ console.log('');
98
+ console.log(chalk.cyan('Documentation:'));
99
+ console.log(' https://github.com/your-repo/facinet');
100
+ console.log('');
101
+ });
102
+
103
+ program.parse(process.argv);
104
+
105
+ // Show help if no command provided
106
+ if (!process.argv.slice(2).length) {
107
+ program.outputHelp();
108
+ }