fuego-cli 1.0.0 → 1.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/README.md CHANGED
@@ -25,7 +25,7 @@
25
25
 
26
26
  **The first Solana wallet CLI designed FOR autonomous agents.**
27
27
 
28
- - ⚡ **No passwords** — File permissions = real security
28
+ - ⚡ **Zero friction** — No prompts, no waiting, just instant signing
29
29
  - 🤖 **Agent-first** — Built for automated workflows
30
30
  - 🏠 **Local-only** — Keys never leave your machine
31
31
  - 🔄 **Auto-updating** — Stay current with `fuego update`
@@ -70,6 +70,9 @@ fuego dashboard
70
70
  | `fuego create` | Create a new Solana wallet |
71
71
  | `fuego address` | Show your wallet address |
72
72
  | `fuego balance` | Check SOL, USDC, USDT balances |
73
+ | `fuego addrpc` | Configure your Solana RPC endpoint |
74
+ | `fuego addbook` | Manage your address book |
75
+ | `fuego send` | Send SOL, USDC, or USDT to an address or contact |
73
76
 
74
77
  ### Project Management
75
78
 
@@ -101,7 +104,9 @@ fuego create --name prod-wallet
101
104
  ~/.fuego/
102
105
  ├── wallet.json # Private key (600 permissions)
103
106
  ├── wallet-config.json # Public key + metadata
104
- └── config.json # CLI config with versions
107
+ ├── config.json # CLI config with versions
108
+ └── contacts/
109
+ └── address-book.json # Your saved contacts
105
110
  ```
106
111
 
107
112
  ---
@@ -186,6 +191,82 @@ fuego update --fuego
186
191
 
187
192
  ---
188
193
 
194
+ ### `fuego addrpc [options]`
195
+
196
+ Configure your Solana RPC endpoint for faster or more reliable connections.
197
+
198
+ ```bash
199
+ # Show current RPC configuration
200
+ fuego addrpc
201
+
202
+ # Set a custom RPC endpoint
203
+ fuego addrpc --url https://helius.xyz/... --network mainnet
204
+
205
+ # Use public mainnet
206
+ fuego addrpc --url https://api.mainnet-beta.solana.com
207
+ ```
208
+
209
+ **Options:**
210
+ - `-u, --url <url>` — RPC endpoint URL
211
+ - `-n, --network <network>` — Network type: `mainnet`, `devnet`, `testnet` (default: `mainnet`)
212
+
213
+ ---
214
+
215
+ ### `fuego addbook <subcommand>`
216
+
217
+ Manage your address book for quick access to frequently used addresses.
218
+
219
+ ```bash
220
+ # Add a contact
221
+ fuego addbook add melanie GvCoHGGBR97Yphzc6SrRycZyS31oUYBM8m9hLRtJT7r5 --label "Melanie's wallet"
222
+
223
+ # List all contacts
224
+ fuego addbook list
225
+
226
+ # Show specific contact
227
+ fuego addbook show melanie
228
+
229
+ # Remove contact (with confirmation)
230
+ fuego addbook remove melanie --yes
231
+ ```
232
+
233
+ **Storage:** `~/.fuego/contacts/address-book.json`
234
+
235
+ **Commands:**
236
+ - `add <name> <address> [--label "description"]` — Add a contact
237
+ - `list` — Show all contacts
238
+ - `show <name>` — Show contact details
239
+ - `remove <name> [--yes]` — Remove a contact
240
+
241
+ ---
242
+
243
+ ### `fuego send <recipient> <amount>`
244
+
245
+ Send SOL, USDC, or USDT to a Solana address or address book contact.
246
+
247
+ ```bash
248
+ # Send SOL to an address
249
+ fuego send GvCoHGGBR97Yphzc6SrRycZyS31oUYBM8m9hLRtJT7r5 0.5 --token SOL
250
+
251
+ # Send USDC to an address book contact
252
+ fuego send melanie 10 --token USDC
253
+
254
+ # Send and confirm immediately
255
+ fuego send melanie 5 --token USDT --yes
256
+ ```
257
+
258
+ **Options:**
259
+ - `-t, --token <token>` — **Required.** Token to send: `SOL`, `USDC`, or `USDT`
260
+ - `-y, --yes` — Skip confirmation prompt and send immediately
261
+
262
+ **Recipient can be:**
263
+ - A full Solana address (e.g., `GvCoHGGBR97Yphzc6SrRycZyS31oUYBM8m9hLRtJT7r5`)
264
+ - An address book contact name (e.g., `melanie`)
265
+
266
+ **Safety:** By default, `fuego send` shows a transaction preview and requires `--yes` to confirm. This prevents accidental sends.
267
+
268
+ ---
269
+
189
270
  ### `fuego install [options]`
190
271
 
191
272
  Install the [Fuego project](https://github.com/willmcdeezy/fuego) — Rust server, Python scripts, and dashboard.
@@ -0,0 +1,9 @@
1
+ export declare function addBookAddCommand(name: string, address: string, options: {
2
+ label?: string;
3
+ }): Promise<void>;
4
+ export declare function addBookListCommand(): Promise<void>;
5
+ export declare function addBookShowCommand(name: string): Promise<void>;
6
+ export declare function addBookRemoveCommand(name: string, options: {
7
+ yes?: boolean;
8
+ }): Promise<void>;
9
+ //# sourceMappingURL=addbook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"addbook.d.ts","sourceRoot":"","sources":["../../src/commands/addbook.ts"],"names":[],"mappings":"AAqCA,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAqCjH;AAGD,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAqBxD;AAGD,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBpE;AAGD,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA0BlG"}
@@ -0,0 +1,111 @@
1
+ import chalk from 'chalk';
2
+ import fs from 'fs-extra';
3
+ import path from 'path';
4
+ import os from 'os';
5
+ import { showSuccess, showInfo, showWarning, flameDivider } from '../lib/ascii.js';
6
+ const CONTACTS_DIR = path.join(os.homedir(), '.fuego', 'contacts');
7
+ const ADDRESS_BOOK_FILE = path.join(CONTACTS_DIR, 'address-book.json');
8
+ function loadAddressBook() {
9
+ if (!fs.existsSync(ADDRESS_BOOK_FILE)) {
10
+ return {};
11
+ }
12
+ return fs.readJsonSync(ADDRESS_BOOK_FILE);
13
+ }
14
+ function saveAddressBook(book) {
15
+ fs.ensureDirSync(CONTACTS_DIR);
16
+ fs.writeJsonSync(ADDRESS_BOOK_FILE, book, { spaces: 2 });
17
+ }
18
+ function isValidSolanaAddress(address) {
19
+ // Basic Solana address validation (32-44 chars, base58)
20
+ return /^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(address);
21
+ }
22
+ // Add a contact
23
+ export async function addBookAddCommand(name, address, options) {
24
+ console.log();
25
+ if (!name || !address) {
26
+ console.log(chalk.red('❌ Usage: fuego addbook add <name> <address> [--label "description"]'));
27
+ process.exit(1);
28
+ }
29
+ // Validate address
30
+ if (!isValidSolanaAddress(address)) {
31
+ console.log(chalk.red('❌ Invalid Solana address format.'));
32
+ process.exit(1);
33
+ }
34
+ const book = loadAddressBook();
35
+ // Check if name already exists
36
+ if (book[name]) {
37
+ showWarning(`Contact "${name}" already exists.\n\nUse a different name or remove the existing contact first.`);
38
+ return;
39
+ }
40
+ // Add contact
41
+ book[name] = {
42
+ address,
43
+ label: options.label,
44
+ addedAt: new Date().toISOString()
45
+ };
46
+ saveAddressBook(book);
47
+ showSuccess('✅ Contact Added', `Name: ${chalk.cyan(name)}\nAddress: ${chalk.cyan(address.slice(0, 8))}...${chalk.cyan(address.slice(-8))}${options.label ? '\nLabel: ' + chalk.cyan(options.label) : ''}`);
48
+ flameDivider();
49
+ }
50
+ // List all contacts
51
+ export async function addBookListCommand() {
52
+ console.log();
53
+ const book = loadAddressBook();
54
+ const contacts = Object.entries(book);
55
+ if (contacts.length === 0) {
56
+ showInfo('📒 Address Book', ['No contacts yet.', '', chalk.yellow('Add one: fuego addbook add <name> <address>')]);
57
+ flameDivider();
58
+ return;
59
+ }
60
+ const lines = [`${contacts.length} contact${contacts.length === 1 ? '' : 's'}\n`];
61
+ for (const [name, entry] of contacts) {
62
+ const shortAddr = `${entry.address.slice(0, 6)}...${entry.address.slice(-6)}`;
63
+ lines.push(`${chalk.cyan(name)}: ${chalk.white(shortAddr)}${entry.label ? chalk.gray(` (${entry.label})`) : ''}`);
64
+ }
65
+ showInfo('📒 Address Book', lines);
66
+ flameDivider();
67
+ }
68
+ // Show a specific contact
69
+ export async function addBookShowCommand(name) {
70
+ console.log();
71
+ if (!name) {
72
+ console.log(chalk.red('❌ Usage: fuego addbook show <name>'));
73
+ process.exit(1);
74
+ }
75
+ const book = loadAddressBook();
76
+ const entry = book[name];
77
+ if (!entry) {
78
+ console.log(chalk.red(`❌ Contact "${name}" not found.`));
79
+ console.log(chalk.gray('\nUse "fuego addbook list" to see all contacts.'));
80
+ process.exit(1);
81
+ }
82
+ showInfo(`📇 ${name}`, [
83
+ `Address: ${chalk.white(entry.address)}`,
84
+ entry.label ? `Label: ${chalk.cyan(entry.label)}` : '',
85
+ `Added: ${chalk.gray(new Date(entry.addedAt).toLocaleDateString())}`
86
+ ].filter(Boolean));
87
+ flameDivider();
88
+ }
89
+ // Remove a contact
90
+ export async function addBookRemoveCommand(name, options) {
91
+ console.log();
92
+ if (!name) {
93
+ console.log(chalk.red('❌ Usage: fuego addbook remove <name> [--yes]'));
94
+ process.exit(1);
95
+ }
96
+ const book = loadAddressBook();
97
+ if (!book[name]) {
98
+ console.log(chalk.red(`❌ Contact "${name}" not found.`));
99
+ process.exit(1);
100
+ }
101
+ // Confirm unless --yes flag
102
+ if (!options.yes) {
103
+ showWarning(`About to remove "${name}" (${book[name].address.slice(0, 8)}...${book[name].address.slice(-8)})\n\nUse --yes to confirm, or omit to review.`);
104
+ return;
105
+ }
106
+ delete book[name];
107
+ saveAddressBook(book);
108
+ showSuccess('✅ Contact Removed', `Removed "${chalk.cyan(name)}" from address book.`);
109
+ flameDivider();
110
+ }
111
+ //# sourceMappingURL=addbook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"addbook.js","sourceRoot":"","sources":["../../src/commands/addbook.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ interface AddRpcOptions {
2
+ url?: string;
3
+ network?: string;
4
+ }
5
+ export declare function addRpcCommand(options: AddRpcOptions): Promise<void>;
6
+ export {};
7
+ //# sourceMappingURL=addrpc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"addrpc.d.ts","sourceRoot":"","sources":["../../src/commands/addrpc.ts"],"names":[],"mappings":"AAIA,UAAU,aAAa;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA+CzE"}
@@ -0,0 +1,41 @@
1
+ import chalk from 'chalk';
2
+ import { setConfig, getConfig } from '../lib/config.js';
3
+ import { showSuccess, showInfo, flameDivider } from '../lib/ascii.js';
4
+ export async function addRpcCommand(options) {
5
+ console.log(); // spacer
6
+ // If no URL provided, show current config and help
7
+ if (!options.url) {
8
+ const currentRpc = getConfig('rpcUrl');
9
+ const currentNetwork = getConfig('network');
10
+ showInfo('⚙️ Current RPC Configuration', [
11
+ `RPC URL: ${currentRpc ? chalk.cyan(currentRpc) : chalk.gray('Not set')}`,
12
+ `Network: ${currentNetwork ? chalk.cyan(currentNetwork) : chalk.gray('mainnet')}`,
13
+ '',
14
+ `${chalk.yellow('Usage:')} fuego addrpc --url https://api.mainnet-beta.solana.com`,
15
+ `${chalk.yellow('Or:')} fuego addrpc --url https://helius.xyz/... --network mainnet`
16
+ ]);
17
+ flameDivider();
18
+ return;
19
+ }
20
+ // Validate URL
21
+ try {
22
+ new URL(options.url);
23
+ }
24
+ catch {
25
+ console.log(chalk.red('❌ Invalid URL. Please provide a valid RPC endpoint.'));
26
+ process.exit(1);
27
+ }
28
+ // Set the RPC URL
29
+ setConfig('rpcUrl', options.url);
30
+ // Set network if provided, default to mainnet
31
+ const network = options.network || 'mainnet';
32
+ setConfig('network', network);
33
+ showSuccess('✅ RPC Configuration Updated', `URL: ${chalk.cyan(options.url)}\nNetwork: ${chalk.cyan(network)}`);
34
+ showInfo('💡 Tips', [
35
+ 'Premium RPCs (Helius, QuickNode) offer better performance',
36
+ 'Free public RPCs may have rate limits',
37
+ 'Your wallet address remains the same across networks'
38
+ ]);
39
+ flameDivider();
40
+ }
41
+ //# sourceMappingURL=addrpc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"addrpc.js","sourceRoot":"","sources":["../../src/commands/addrpc.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,SAAS,EAAc,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAOtE,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAAsB;IACxD,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,SAAS;IAExB,mDAAmD;IACnD,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QACjB,MAAM,UAAU,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;QACvC,MAAM,cAAc,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;QAE5C,QAAQ,CAAC,+BAA+B,EAAE;YACxC,YAAY,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE;YACzE,YAAY,cAAc,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE;YACjF,EAAE;YACF,GAAG,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,yDAAyD;YAClF,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,kEAAkE;SACzF,CAAC,CAAC;QAEH,YAAY,EAAE,CAAC;QACf,OAAO;IACT,CAAC;IAED,eAAe;IACf,IAAI,CAAC;QACH,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC,CAAC;QAC9E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,kBAAkB;IAClB,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IAEjC,8CAA8C;IAC9C,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,SAAS,CAAC;IAC7C,SAAS,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAE9B,WAAW,CACT,6BAA6B,EAC7B,QAAQ,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CACnE,CAAC;IAEF,QAAQ,CAAC,SAAS,EAAE;QAClB,2DAA2D;QAC3D,uCAAuC;QACvC,sDAAsD;KACvD,CAAC,CAAC;IAEH,YAAY,EAAE,CAAC;AACjB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"AAOA,UAAU,aAAa;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA2EzE"}
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"AAQA,UAAU,aAAa;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAuFzE"}
@@ -1,5 +1,6 @@
1
1
  import chalk from 'chalk';
2
2
  import ora from 'ora';
3
+ import path from 'path';
3
4
  import { FuegoWallet } from '../lib/wallet.js';
4
5
  import { getWalletPath, getConfigPath, getFuegoCliVersion, setFuegoCliVersion } from '../lib/config.js';
5
6
  import { showSuccess, showWarning, showInfo, formatPublicKey, flameDivider } from '../lib/ascii.js';
@@ -38,6 +39,15 @@ export async function createCommand(options) {
38
39
  network: existingConfig.network || 'mainnet',
39
40
  rpcUrl: existingConfig.rpcUrl || 'https://api.mainnet-beta.solana.com'
40
41
  }, { spaces: 2 });
42
+ // Create address book directory and empty file
43
+ const contactsDir = options.directory
44
+ ? `${options.directory}/contacts`
45
+ : path.join(path.dirname(getConfigPath()), 'contacts');
46
+ const addressBookPath = path.join(contactsDir, 'address-book.json');
47
+ if (!fs.existsSync(addressBookPath)) {
48
+ fs.ensureDirSync(contactsDir);
49
+ fs.writeJsonSync(addressBookPath, {}, { spaces: 2 });
50
+ }
41
51
  // Store fuego-cli version
42
52
  setFuegoCliVersion(getFuegoCliVersion());
43
53
  spinner.stop();
@@ -51,7 +61,8 @@ export async function createCommand(options) {
51
61
  // File locations
52
62
  showInfo('📁 Wallet Files', [
53
63
  'Keypair: ~/.fuego/wallet.json',
54
- 'Config: ~/.fuego/wallet-config.json'
64
+ 'Config: ~/.fuego/wallet-config.json',
65
+ 'Contacts: ~/.fuego/contacts/address-book.json'
55
66
  ]);
56
67
  flameDivider();
57
68
  }
@@ -1 +1 @@
1
- {"version":3,"file":"create.js","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"create.js","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ interface SendOptions {
2
+ token?: string;
3
+ yes?: boolean;
4
+ }
5
+ export declare function sendCommand(recipient: string, amount: string, options: SendOptions): Promise<void>;
6
+ export {};
7
+ //# sourceMappingURL=send.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send.d.ts","sourceRoot":"","sources":["../../src/commands/send.ts"],"names":[],"mappings":"AAUA,UAAU,WAAW;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAiCD,wBAAsB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAmHxG"}
@@ -0,0 +1,128 @@
1
+ import chalk from 'chalk';
2
+ import { spawn } from 'child_process';
3
+ import path from 'path';
4
+ import os from 'os';
5
+ import { loadWalletConfig, findFuegoPath } from '../lib/config.js';
6
+ import { showSuccess, showInfo, showError, formatPublicKey, flameDivider } from '../lib/ascii.js';
7
+ import fs from 'fs-extra';
8
+ const ADDRESS_BOOK_FILE = path.join(os.homedir(), '.fuego', 'contacts', 'address-book.json');
9
+ function loadAddressBook() {
10
+ if (!fs.existsSync(ADDRESS_BOOK_FILE)) {
11
+ return {};
12
+ }
13
+ return fs.readJsonSync(ADDRESS_BOOK_FILE);
14
+ }
15
+ function resolveRecipient(recipient) {
16
+ // Check if it's a direct address (32-44 chars, base58)
17
+ if (/^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(recipient)) {
18
+ return recipient;
19
+ }
20
+ // Check address book
21
+ const book = loadAddressBook();
22
+ if (book[recipient]) {
23
+ return book[recipient].address;
24
+ }
25
+ // Not found
26
+ return '';
27
+ }
28
+ export async function sendCommand(recipient, amount, options) {
29
+ console.log();
30
+ // Validate inputs
31
+ if (!recipient || !amount) {
32
+ console.log(chalk.red('❌ Usage: fuego send <recipient> <amount> --token SOL|USDC|USDT [--yes]'));
33
+ console.log(chalk.gray('\nExamples:'));
34
+ console.log(chalk.gray(' fuego send GvCo... 0.5 --token SOL'));
35
+ console.log(chalk.gray(' fuego send melanie 10 --token USDC'));
36
+ console.log(chalk.gray(' fuego send melanie 5 --token USDT --yes'));
37
+ console.log(chalk.gray('\nRecipient can be an address or address book contact name.'));
38
+ process.exit(1);
39
+ }
40
+ // Load wallet
41
+ const walletConfig = loadWalletConfig();
42
+ if (!walletConfig) {
43
+ console.log(chalk.red('❌ No wallet found. Run "fuego create" first.'));
44
+ process.exit(1);
45
+ }
46
+ // Resolve recipient
47
+ const resolvedAddress = resolveRecipient(recipient);
48
+ if (!resolvedAddress) {
49
+ console.log(chalk.red(`❌ Recipient "${recipient}" not found.`));
50
+ console.log(chalk.gray('\nCheck your address book: fuego addbook list'));
51
+ console.log(chalk.gray('Or use a full Solana address.'));
52
+ process.exit(1);
53
+ }
54
+ // Validate amount
55
+ const amountNum = parseFloat(amount);
56
+ if (isNaN(amountNum) || amountNum <= 0) {
57
+ console.log(chalk.red('❌ Invalid amount. Please provide a positive number.'));
58
+ process.exit(1);
59
+ }
60
+ // Determine token
61
+ const token = (options.token || '').toUpperCase();
62
+ if (!token) {
63
+ console.log(chalk.red('❌ Token is required. Use: --token SOL, --token USDC, or --token USDT'));
64
+ process.exit(1);
65
+ }
66
+ if (!['SOL', 'USDC', 'USDT'].includes(token)) {
67
+ console.log(chalk.red('❌ Invalid token. Use: SOL, USDC, or USDT'));
68
+ process.exit(1);
69
+ }
70
+ // Show transaction details
71
+ const isContact = recipient !== resolvedAddress;
72
+ showInfo('📝 Transaction Preview', [
73
+ `From: ${chalk.cyan(formatPublicKey(walletConfig.publicKey))}`,
74
+ `To: ${chalk.cyan(formatPublicKey(resolvedAddress))}${isContact ? chalk.gray(` (${recipient})`) : ''}`,
75
+ `Amount: ${chalk.yellow(amount)} ${chalk.cyan(token)}`,
76
+ `Network: ${chalk.gray('mainnet-beta')}`
77
+ ]);
78
+ // Confirm unless --yes
79
+ if (!options.yes) {
80
+ console.log();
81
+ console.log(chalk.yellow('⚠️ Add --yes to confirm and send'));
82
+ flameDivider();
83
+ return;
84
+ }
85
+ console.log();
86
+ console.log(chalk.blue('⏳ Executing transaction via Fuego...'));
87
+ // Find fuego installation path and call Python script
88
+ const fuegoPath = findFuegoPath();
89
+ if (!fuegoPath) {
90
+ showError('Fuego installation not found. Run "fuego install" first.');
91
+ process.exit(1);
92
+ }
93
+ const scriptPath = path.join(fuegoPath, 'scripts', 'fuego_transfer.py');
94
+ const pythonProcess = spawn('python3', [
95
+ scriptPath,
96
+ '--from', walletConfig.publicKey,
97
+ '--to', resolvedAddress,
98
+ '--amount', amount,
99
+ '--token', token
100
+ ]);
101
+ let output = '';
102
+ let errorOutput = '';
103
+ pythonProcess.stdout.on('data', (data) => {
104
+ output += data.toString();
105
+ process.stdout.write(data);
106
+ });
107
+ pythonProcess.stderr.on('data', (data) => {
108
+ errorOutput += data.toString();
109
+ });
110
+ pythonProcess.on('close', (code) => {
111
+ if (code === 0) {
112
+ // Extract signature from output if present
113
+ const sigMatch = output.match(/Signature: ([A-Za-z0-9]+)/);
114
+ if (sigMatch) {
115
+ showSuccess('✅ Transaction Sent!', `Amount: ${chalk.yellow(amount)} ${chalk.cyan(token)}\nTo: ${chalk.cyan(isContact ? recipient : formatPublicKey(resolvedAddress))}`);
116
+ }
117
+ else {
118
+ showSuccess('✅ Transaction Complete!', '');
119
+ }
120
+ flameDivider();
121
+ }
122
+ else {
123
+ showError(`Transaction failed: ${errorOutput || 'Unknown error'}`);
124
+ process.exit(1);
125
+ }
126
+ });
127
+ }
128
+ //# sourceMappingURL=send.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send.js","sourceRoot":"","sources":["../../src/commands/send.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -8,6 +8,9 @@ import { balanceCommand } from './commands/balance.js';
8
8
  import { serveCommand } from './commands/serve.js';
9
9
  import { dashboardCommand } from './commands/dashboard.js';
10
10
  import { updateCommand } from './commands/update.js';
11
+ import { addRpcCommand } from './commands/addrpc.js';
12
+ import { addBookAddCommand, addBookListCommand, addBookShowCommand, addBookRemoveCommand } from './commands/addbook.js';
13
+ import { sendCommand } from './commands/send.js';
11
14
  import { showBanner } from './lib/ascii.js';
12
15
  async function main() {
13
16
  // Show banner for help and when no args provided
@@ -60,6 +63,39 @@ async function main() {
60
63
  .option('--cli', 'Update only fuego-cli')
61
64
  .option('--fuego', 'Update only the fuego project')
62
65
  .action(updateCommand);
66
+ program
67
+ .command('addrpc')
68
+ .description('Add or update your Solana RPC endpoint')
69
+ .option('-u, --url <url>', 'RPC endpoint URL (e.g., https://api.mainnet-beta.solana.com)')
70
+ .option('-n, --network <network>', 'Network type (mainnet, devnet, testnet)', 'mainnet')
71
+ .action(addRpcCommand);
72
+ const addbook = program
73
+ .command('addbook')
74
+ .description('Manage your address book (stored in ~/.fuego/contacts/address-book.json)');
75
+ addbook
76
+ .command('add <name> <address>')
77
+ .description('Add a contact to your address book')
78
+ .option('-l, --label <label>', 'Optional description/label for this contact')
79
+ .action(addBookAddCommand);
80
+ addbook
81
+ .command('list')
82
+ .description('List all contacts in your address book')
83
+ .action(addBookListCommand);
84
+ addbook
85
+ .command('show <name>')
86
+ .description('Show details for a specific contact')
87
+ .action(addBookShowCommand);
88
+ addbook
89
+ .command('remove <name>')
90
+ .description('Remove a contact from your address book')
91
+ .option('-y, --yes', 'Skip confirmation prompt')
92
+ .action(addBookRemoveCommand);
93
+ program
94
+ .command('send <recipient> <amount>')
95
+ .description('Send SOL, USDC, or USDT to an address or contact')
96
+ .requiredOption('-t, --token <token>', 'Token to send (SOL, USDC, USDT)')
97
+ .option('-y, --yes', 'Skip confirmation and send immediately')
98
+ .action(sendCommand);
63
99
  await program.parseAsync(process.argv);
64
100
  }
65
101
  main().catch((error) => {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fuego-cli",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Command-line interface for Fuego - the sovereign Solana wallet for AI agents",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -0,0 +1,155 @@
1
+ import chalk from 'chalk';
2
+ import fs from 'fs-extra';
3
+ import path from 'path';
4
+ import os from 'os';
5
+ import { showSuccess, showInfo, showWarning, flameDivider } from '../lib/ascii.js';
6
+
7
+ const CONTACTS_DIR = path.join(os.homedir(), '.fuego', 'contacts');
8
+ const ADDRESS_BOOK_FILE = path.join(CONTACTS_DIR, 'address-book.json');
9
+
10
+ interface ContactEntry {
11
+ address: string;
12
+ label?: string;
13
+ addedAt: string;
14
+ }
15
+
16
+ interface AddressBook {
17
+ [name: string]: ContactEntry;
18
+ }
19
+
20
+ function loadAddressBook(): AddressBook {
21
+ if (!fs.existsSync(ADDRESS_BOOK_FILE)) {
22
+ return {};
23
+ }
24
+ return fs.readJsonSync(ADDRESS_BOOK_FILE);
25
+ }
26
+
27
+ function saveAddressBook(book: AddressBook): void {
28
+ fs.ensureDirSync(CONTACTS_DIR);
29
+ fs.writeJsonSync(ADDRESS_BOOK_FILE, book, { spaces: 2 });
30
+ }
31
+
32
+ function isValidSolanaAddress(address: string): boolean {
33
+ // Basic Solana address validation (32-44 chars, base58)
34
+ return /^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(address);
35
+ }
36
+
37
+ // Add a contact
38
+ export async function addBookAddCommand(name: string, address: string, options: { label?: string }): Promise<void> {
39
+ console.log();
40
+
41
+ if (!name || !address) {
42
+ console.log(chalk.red('❌ Usage: fuego addbook add <name> <address> [--label "description"]'));
43
+ process.exit(1);
44
+ }
45
+
46
+ // Validate address
47
+ if (!isValidSolanaAddress(address)) {
48
+ console.log(chalk.red('❌ Invalid Solana address format.'));
49
+ process.exit(1);
50
+ }
51
+
52
+ const book = loadAddressBook();
53
+
54
+ // Check if name already exists
55
+ if (book[name]) {
56
+ showWarning(`Contact "${name}" already exists.\n\nUse a different name or remove the existing contact first.`);
57
+ return;
58
+ }
59
+
60
+ // Add contact
61
+ book[name] = {
62
+ address,
63
+ label: options.label,
64
+ addedAt: new Date().toISOString()
65
+ };
66
+
67
+ saveAddressBook(book);
68
+
69
+ showSuccess(
70
+ '✅ Contact Added',
71
+ `Name: ${chalk.cyan(name)}\nAddress: ${chalk.cyan(address.slice(0, 8))}...${chalk.cyan(address.slice(-8))}${options.label ? '\nLabel: ' + chalk.cyan(options.label) : ''}`
72
+ );
73
+
74
+ flameDivider();
75
+ }
76
+
77
+ // List all contacts
78
+ export async function addBookListCommand(): Promise<void> {
79
+ console.log();
80
+
81
+ const book = loadAddressBook();
82
+ const contacts = Object.entries(book);
83
+
84
+ if (contacts.length === 0) {
85
+ showInfo('📒 Address Book', ['No contacts yet.', '', chalk.yellow('Add one: fuego addbook add <name> <address>')]);
86
+ flameDivider();
87
+ return;
88
+ }
89
+
90
+ const lines: string[] = [`${contacts.length} contact${contacts.length === 1 ? '' : 's'}\n`];
91
+
92
+ for (const [name, entry] of contacts) {
93
+ const shortAddr = `${entry.address.slice(0, 6)}...${entry.address.slice(-6)}`;
94
+ lines.push(`${chalk.cyan(name)}: ${chalk.white(shortAddr)}${entry.label ? chalk.gray(` (${entry.label})`) : ''}`);
95
+ }
96
+
97
+ showInfo('📒 Address Book', lines);
98
+ flameDivider();
99
+ }
100
+
101
+ // Show a specific contact
102
+ export async function addBookShowCommand(name: string): Promise<void> {
103
+ console.log();
104
+
105
+ if (!name) {
106
+ console.log(chalk.red('❌ Usage: fuego addbook show <name>'));
107
+ process.exit(1);
108
+ }
109
+
110
+ const book = loadAddressBook();
111
+ const entry = book[name];
112
+
113
+ if (!entry) {
114
+ console.log(chalk.red(`❌ Contact "${name}" not found.`));
115
+ console.log(chalk.gray('\nUse "fuego addbook list" to see all contacts.'));
116
+ process.exit(1);
117
+ }
118
+
119
+ showInfo(`📇 ${name}`, [
120
+ `Address: ${chalk.white(entry.address)}`,
121
+ entry.label ? `Label: ${chalk.cyan(entry.label)}` : '',
122
+ `Added: ${chalk.gray(new Date(entry.addedAt).toLocaleDateString())}`
123
+ ].filter(Boolean));
124
+
125
+ flameDivider();
126
+ }
127
+
128
+ // Remove a contact
129
+ export async function addBookRemoveCommand(name: string, options: { yes?: boolean }): Promise<void> {
130
+ console.log();
131
+
132
+ if (!name) {
133
+ console.log(chalk.red('❌ Usage: fuego addbook remove <name> [--yes]'));
134
+ process.exit(1);
135
+ }
136
+
137
+ const book = loadAddressBook();
138
+
139
+ if (!book[name]) {
140
+ console.log(chalk.red(`❌ Contact "${name}" not found.`));
141
+ process.exit(1);
142
+ }
143
+
144
+ // Confirm unless --yes flag
145
+ if (!options.yes) {
146
+ showWarning(`About to remove "${name}" (${book[name].address.slice(0, 8)}...${book[name].address.slice(-8)})\n\nUse --yes to confirm, or omit to review.`);
147
+ return;
148
+ }
149
+
150
+ delete book[name];
151
+ saveAddressBook(book);
152
+
153
+ showSuccess('✅ Contact Removed', `Removed "${chalk.cyan(name)}" from address book.`);
154
+ flameDivider();
155
+ }
@@ -0,0 +1,57 @@
1
+ import chalk from 'chalk';
2
+ import { setConfig, getConfig, listConfig } from '../lib/config.js';
3
+ import { showSuccess, showInfo, flameDivider } from '../lib/ascii.js';
4
+
5
+ interface AddRpcOptions {
6
+ url?: string;
7
+ network?: string;
8
+ }
9
+
10
+ export async function addRpcCommand(options: AddRpcOptions): Promise<void> {
11
+ console.log(); // spacer
12
+
13
+ // If no URL provided, show current config and help
14
+ if (!options.url) {
15
+ const currentRpc = getConfig('rpcUrl');
16
+ const currentNetwork = getConfig('network');
17
+
18
+ showInfo('⚙️ Current RPC Configuration', [
19
+ `RPC URL: ${currentRpc ? chalk.cyan(currentRpc) : chalk.gray('Not set')}`,
20
+ `Network: ${currentNetwork ? chalk.cyan(currentNetwork) : chalk.gray('mainnet')}`,
21
+ '',
22
+ `${chalk.yellow('Usage:')} fuego addrpc --url https://api.mainnet-beta.solana.com`,
23
+ `${chalk.yellow('Or:')} fuego addrpc --url https://helius.xyz/... --network mainnet`
24
+ ]);
25
+
26
+ flameDivider();
27
+ return;
28
+ }
29
+
30
+ // Validate URL
31
+ try {
32
+ new URL(options.url);
33
+ } catch {
34
+ console.log(chalk.red('❌ Invalid URL. Please provide a valid RPC endpoint.'));
35
+ process.exit(1);
36
+ }
37
+
38
+ // Set the RPC URL
39
+ setConfig('rpcUrl', options.url);
40
+
41
+ // Set network if provided, default to mainnet
42
+ const network = options.network || 'mainnet';
43
+ setConfig('network', network);
44
+
45
+ showSuccess(
46
+ '✅ RPC Configuration Updated',
47
+ `URL: ${chalk.cyan(options.url)}\nNetwork: ${chalk.cyan(network)}`
48
+ );
49
+
50
+ showInfo('💡 Tips', [
51
+ 'Premium RPCs (Helius, QuickNode) offer better performance',
52
+ 'Free public RPCs may have rate limits',
53
+ 'Your wallet address remains the same across networks'
54
+ ]);
55
+
56
+ flameDivider();
57
+ }
@@ -1,5 +1,6 @@
1
1
  import chalk from 'chalk';
2
2
  import ora from 'ora';
3
+ import path from 'path';
3
4
  import { FuegoWallet } from '../lib/wallet.js';
4
5
  import { getWalletPath, getConfigPath, getFuegoCliVersion, setFuegoCliVersion } from '../lib/config.js';
5
6
  import { showSuccess, showWarning, showInfo, formatPublicKey, flameDivider } from '../lib/ascii.js';
@@ -55,6 +56,17 @@ export async function createCommand(options: CreateOptions): Promise<void> {
55
56
  rpcUrl: existingConfig.rpcUrl || 'https://api.mainnet-beta.solana.com'
56
57
  }, { spaces: 2 });
57
58
 
59
+ // Create address book directory and empty file
60
+ const contactsDir = options.directory
61
+ ? `${options.directory}/contacts`
62
+ : path.join(path.dirname(getConfigPath()), 'contacts');
63
+ const addressBookPath = path.join(contactsDir, 'address-book.json');
64
+
65
+ if (!fs.existsSync(addressBookPath)) {
66
+ fs.ensureDirSync(contactsDir);
67
+ fs.writeJsonSync(addressBookPath, {}, { spaces: 2 });
68
+ }
69
+
58
70
  // Store fuego-cli version
59
71
  setFuegoCliVersion(getFuegoCliVersion());
60
72
 
@@ -77,7 +89,8 @@ export async function createCommand(options: CreateOptions): Promise<void> {
77
89
  // File locations
78
90
  showInfo('📁 Wallet Files', [
79
91
  'Keypair: ~/.fuego/wallet.json',
80
- 'Config: ~/.fuego/wallet-config.json'
92
+ 'Config: ~/.fuego/wallet-config.json',
93
+ 'Contacts: ~/.fuego/contacts/address-book.json'
81
94
  ]);
82
95
 
83
96
  flameDivider();
@@ -0,0 +1,162 @@
1
+ import chalk from 'chalk';
2
+ import { spawn } from 'child_process';
3
+ import path from 'path';
4
+ import os from 'os';
5
+ import { loadWalletConfig, findFuegoPath } from '../lib/config.js';
6
+ import { showSuccess, showInfo, showError, formatPublicKey, flameDivider } from '../lib/ascii.js';
7
+ import fs from 'fs-extra';
8
+
9
+ const ADDRESS_BOOK_FILE = path.join(os.homedir(), '.fuego', 'contacts', 'address-book.json');
10
+
11
+ interface SendOptions {
12
+ token?: string;
13
+ yes?: boolean;
14
+ }
15
+
16
+ interface AddressBook {
17
+ [name: string]: {
18
+ address: string;
19
+ label?: string;
20
+ addedAt: string;
21
+ };
22
+ }
23
+
24
+ function loadAddressBook(): AddressBook {
25
+ if (!fs.existsSync(ADDRESS_BOOK_FILE)) {
26
+ return {};
27
+ }
28
+ return fs.readJsonSync(ADDRESS_BOOK_FILE);
29
+ }
30
+
31
+ function resolveRecipient(recipient: string): string {
32
+ // Check if it's a direct address (32-44 chars, base58)
33
+ if (/^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(recipient)) {
34
+ return recipient;
35
+ }
36
+
37
+ // Check address book
38
+ const book = loadAddressBook();
39
+ if (book[recipient]) {
40
+ return book[recipient].address;
41
+ }
42
+
43
+ // Not found
44
+ return '';
45
+ }
46
+
47
+ export async function sendCommand(recipient: string, amount: string, options: SendOptions): Promise<void> {
48
+ console.log();
49
+
50
+ // Validate inputs
51
+ if (!recipient || !amount) {
52
+ console.log(chalk.red('❌ Usage: fuego send <recipient> <amount> --token SOL|USDC|USDT [--yes]'));
53
+ console.log(chalk.gray('\nExamples:'));
54
+ console.log(chalk.gray(' fuego send GvCo... 0.5 --token SOL'));
55
+ console.log(chalk.gray(' fuego send melanie 10 --token USDC'));
56
+ console.log(chalk.gray(' fuego send melanie 5 --token USDT --yes'));
57
+ console.log(chalk.gray('\nRecipient can be an address or address book contact name.'));
58
+ process.exit(1);
59
+ }
60
+
61
+ // Load wallet
62
+ const walletConfig = loadWalletConfig();
63
+ if (!walletConfig) {
64
+ console.log(chalk.red('❌ No wallet found. Run "fuego create" first.'));
65
+ process.exit(1);
66
+ }
67
+
68
+ // Resolve recipient
69
+ const resolvedAddress = resolveRecipient(recipient);
70
+ if (!resolvedAddress) {
71
+ console.log(chalk.red(`❌ Recipient "${recipient}" not found.`));
72
+ console.log(chalk.gray('\nCheck your address book: fuego addbook list'));
73
+ console.log(chalk.gray('Or use a full Solana address.'));
74
+ process.exit(1);
75
+ }
76
+
77
+ // Validate amount
78
+ const amountNum = parseFloat(amount);
79
+ if (isNaN(amountNum) || amountNum <= 0) {
80
+ console.log(chalk.red('❌ Invalid amount. Please provide a positive number.'));
81
+ process.exit(1);
82
+ }
83
+
84
+ // Determine token
85
+ const token = (options.token || '').toUpperCase();
86
+ if (!token) {
87
+ console.log(chalk.red('❌ Token is required. Use: --token SOL, --token USDC, or --token USDT'));
88
+ process.exit(1);
89
+ }
90
+ if (!['SOL', 'USDC', 'USDT'].includes(token)) {
91
+ console.log(chalk.red('❌ Invalid token. Use: SOL, USDC, or USDT'));
92
+ process.exit(1);
93
+ }
94
+
95
+ // Show transaction details
96
+ const isContact = recipient !== resolvedAddress;
97
+ showInfo('📝 Transaction Preview', [
98
+ `From: ${chalk.cyan(formatPublicKey(walletConfig.publicKey))}`,
99
+ `To: ${chalk.cyan(formatPublicKey(resolvedAddress))}${isContact ? chalk.gray(` (${recipient})`) : ''}`,
100
+ `Amount: ${chalk.yellow(amount)} ${chalk.cyan(token)}`,
101
+ `Network: ${chalk.gray('mainnet-beta')}`
102
+ ]);
103
+
104
+ // Confirm unless --yes
105
+ if (!options.yes) {
106
+ console.log();
107
+ console.log(chalk.yellow('⚠️ Add --yes to confirm and send'));
108
+ flameDivider();
109
+ return;
110
+ }
111
+
112
+ console.log();
113
+ console.log(chalk.blue('⏳ Executing transaction via Fuego...'));
114
+
115
+ // Find fuego installation path and call Python script
116
+ const fuegoPath = findFuegoPath();
117
+ if (!fuegoPath) {
118
+ showError('Fuego installation not found. Run "fuego install" first.');
119
+ process.exit(1);
120
+ }
121
+
122
+ const scriptPath = path.join(fuegoPath, 'scripts', 'fuego_transfer.py');
123
+
124
+ const pythonProcess = spawn('python3', [
125
+ scriptPath,
126
+ '--from', walletConfig.publicKey,
127
+ '--to', resolvedAddress,
128
+ '--amount', amount,
129
+ '--token', token
130
+ ]);
131
+
132
+ let output = '';
133
+ let errorOutput = '';
134
+
135
+ pythonProcess.stdout.on('data', (data) => {
136
+ output += data.toString();
137
+ process.stdout.write(data);
138
+ });
139
+
140
+ pythonProcess.stderr.on('data', (data) => {
141
+ errorOutput += data.toString();
142
+ });
143
+
144
+ pythonProcess.on('close', (code) => {
145
+ if (code === 0) {
146
+ // Extract signature from output if present
147
+ const sigMatch = output.match(/Signature: ([A-Za-z0-9]+)/);
148
+ if (sigMatch) {
149
+ showSuccess(
150
+ '✅ Transaction Sent!',
151
+ `Amount: ${chalk.yellow(amount)} ${chalk.cyan(token)}\nTo: ${chalk.cyan(isContact ? recipient : formatPublicKey(resolvedAddress))}`
152
+ );
153
+ } else {
154
+ showSuccess('✅ Transaction Complete!', '');
155
+ }
156
+ flameDivider();
157
+ } else {
158
+ showError(`Transaction failed: ${errorOutput || 'Unknown error'}`);
159
+ process.exit(1);
160
+ }
161
+ });
162
+ }
package/src/index.ts CHANGED
@@ -9,6 +9,9 @@ import { balanceCommand } from './commands/balance.js';
9
9
  import { serveCommand } from './commands/serve.js';
10
10
  import { dashboardCommand } from './commands/dashboard.js';
11
11
  import { updateCommand } from './commands/update.js';
12
+ import { addRpcCommand } from './commands/addrpc.js';
13
+ import { addBookAddCommand, addBookListCommand, addBookShowCommand, addBookRemoveCommand } from './commands/addbook.js';
14
+ import { sendCommand } from './commands/send.js';
12
15
  import { showBanner } from './lib/ascii.js';
13
16
 
14
17
  async function main() {
@@ -72,6 +75,46 @@ async function main() {
72
75
  .option('--fuego', 'Update only the fuego project')
73
76
  .action(updateCommand);
74
77
 
78
+ program
79
+ .command('addrpc')
80
+ .description('Add or update your Solana RPC endpoint')
81
+ .option('-u, --url <url>', 'RPC endpoint URL (e.g., https://api.mainnet-beta.solana.com)')
82
+ .option('-n, --network <network>', 'Network type (mainnet, devnet, testnet)', 'mainnet')
83
+ .action(addRpcCommand);
84
+
85
+ const addbook = program
86
+ .command('addbook')
87
+ .description('Manage your address book (stored in ~/.fuego/contacts/address-book.json)');
88
+
89
+ addbook
90
+ .command('add <name> <address>')
91
+ .description('Add a contact to your address book')
92
+ .option('-l, --label <label>', 'Optional description/label for this contact')
93
+ .action(addBookAddCommand);
94
+
95
+ addbook
96
+ .command('list')
97
+ .description('List all contacts in your address book')
98
+ .action(addBookListCommand);
99
+
100
+ addbook
101
+ .command('show <name>')
102
+ .description('Show details for a specific contact')
103
+ .action(addBookShowCommand);
104
+
105
+ addbook
106
+ .command('remove <name>')
107
+ .description('Remove a contact from your address book')
108
+ .option('-y, --yes', 'Skip confirmation prompt')
109
+ .action(addBookRemoveCommand);
110
+
111
+ program
112
+ .command('send <recipient> <amount>')
113
+ .description('Send SOL, USDC, or USDT to an address or contact')
114
+ .requiredOption('-t, --token <token>', 'Token to send (SOL, USDC, USDT)')
115
+ .option('-y, --yes', 'Skip confirmation and send immediately')
116
+ .action(sendCommand);
117
+
75
118
  await program.parseAsync(process.argv);
76
119
  }
77
120
 
Binary file
Binary file