x402charity 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/bin/cli.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import '../dist/index.js';
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare const configCommand: Command;
@@ -0,0 +1,36 @@
1
+ import { Command } from 'commander';
2
+ import { saveCliConfig, loadCliConfig } from '../config.js';
3
+ export const configCommand = new Command('config')
4
+ .description('Configure x402charity CLI');
5
+ configCommand
6
+ .command('set-key <privateKey>')
7
+ .description('Set your wallet private key')
8
+ .action((privateKey) => {
9
+ const config = loadCliConfig();
10
+ config.privateKey = privateKey;
11
+ saveCliConfig(config);
12
+ console.log('Private key saved to ~/.x402charity/config.json');
13
+ });
14
+ configCommand
15
+ .command('set-network <network>')
16
+ .description('Set default network (base or base-sepolia)')
17
+ .action((network) => {
18
+ if (network !== 'base' && network !== 'base-sepolia') {
19
+ console.error('Network must be "base" or "base-sepolia"');
20
+ process.exit(1);
21
+ }
22
+ const config = loadCliConfig();
23
+ config.network = network;
24
+ saveCliConfig(config);
25
+ console.log(`Default network set to ${network}`);
26
+ });
27
+ configCommand
28
+ .command('show')
29
+ .description('Show current configuration')
30
+ .action(() => {
31
+ const config = loadCliConfig();
32
+ console.log('\nCurrent configuration:\n');
33
+ console.log(` Network: ${config.network || 'base-sepolia (default)'}`);
34
+ console.log(` Private Key: ${config.privateKey ? '****' + config.privateKey.slice(-4) : 'not set'}`);
35
+ console.log(` Config File: ~/.x402charity/config.json\n`);
36
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare const donateCommand: Command;
@@ -0,0 +1,29 @@
1
+ import { Command } from 'commander';
2
+ import { X402CharityClient } from '@x402charity/core';
3
+ import { getPrivateKey, getNetwork } from '../config.js';
4
+ export const donateCommand = new Command('donate')
5
+ .description('Donate USDC to a charity')
6
+ .argument('<cause>', 'Charity ID or name')
7
+ .argument('[amount]', 'Amount in USDC (default: 0.0001)')
8
+ .option('-n, --network <network>', 'Network: base or base-sepolia')
9
+ .action(async (cause, amount, options) => {
10
+ amount = amount || '0.0001';
11
+ try {
12
+ const privateKey = getPrivateKey();
13
+ const network = (options.network || getNetwork());
14
+ const client = new X402CharityClient({ privateKey, network });
15
+ console.log(`\nDonating ${amount} USDC to "${cause}" on ${network}...\n`);
16
+ const receipt = await client.donate(cause, amount);
17
+ console.log('Donation successful!\n');
18
+ console.log(` Charity: ${receipt.charity.name}`);
19
+ console.log(` Amount: ${receipt.amount} ${receipt.currency}`);
20
+ console.log(` Tx Hash: ${receipt.txHash}`);
21
+ console.log(` Chain: ${receipt.chain}`);
22
+ console.log(` From: ${receipt.from}`);
23
+ console.log(` To: ${receipt.to}\n`);
24
+ }
25
+ catch (error) {
26
+ console.error(`\nError: ${error.message}\n`);
27
+ process.exit(1);
28
+ }
29
+ });
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare const listCommand: Command;
@@ -0,0 +1,19 @@
1
+ import { Command } from 'commander';
2
+ import { listCharities } from '@x402charity/core';
3
+ export const listCommand = new Command('list')
4
+ .description('List available charities')
5
+ .action(() => {
6
+ const charities = listCharities();
7
+ console.log('\nAvailable charities:\n');
8
+ for (const charity of charities) {
9
+ const badge = charity.verified ? ' [verified]' : '';
10
+ console.log(` ${charity.id}${badge}`);
11
+ console.log(` ${charity.name}`);
12
+ console.log(` ${charity.description}`);
13
+ console.log(` Wallet: ${charity.walletAddress}`);
14
+ console.log(` Chain: ${charity.chain}`);
15
+ if (charity.website)
16
+ console.log(` Web: ${charity.website}`);
17
+ console.log('');
18
+ }
19
+ });
@@ -0,0 +1,9 @@
1
+ interface CliConfig {
2
+ privateKey?: string;
3
+ network?: 'base' | 'base-sepolia';
4
+ }
5
+ export declare function loadCliConfig(): CliConfig;
6
+ export declare function saveCliConfig(config: CliConfig): void;
7
+ export declare function getPrivateKey(): string;
8
+ export declare function getNetwork(): 'base' | 'base-sepolia';
9
+ export {};
package/dist/config.js ADDED
@@ -0,0 +1,31 @@
1
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { homedir } from 'node:os';
4
+ const CONFIG_DIR = join(homedir(), '.x402charity');
5
+ const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
6
+ export function loadCliConfig() {
7
+ if (!existsSync(CONFIG_FILE))
8
+ return {};
9
+ return JSON.parse(readFileSync(CONFIG_FILE, 'utf-8'));
10
+ }
11
+ export function saveCliConfig(config) {
12
+ mkdirSync(CONFIG_DIR, { recursive: true });
13
+ writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), { mode: 0o600 });
14
+ }
15
+ export function getPrivateKey() {
16
+ const envKey = process.env.X402_PRIVATE_KEY;
17
+ if (envKey)
18
+ return envKey;
19
+ const config = loadCliConfig();
20
+ if (config.privateKey)
21
+ return config.privateKey;
22
+ console.error('No private key found. Set X402_PRIVATE_KEY env var or run:\n x402charity config set-key <key>');
23
+ return process.exit(1);
24
+ }
25
+ export function getNetwork() {
26
+ const envNetwork = process.env.X402_NETWORK;
27
+ if (envNetwork === 'base' || envNetwork === 'base-sepolia')
28
+ return envNetwork;
29
+ const config = loadCliConfig();
30
+ return config.network || 'base-sepolia';
31
+ }
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ import { Command } from 'commander';
2
+ import { donateCommand } from './commands/donate.js';
3
+ import { listCommand } from './commands/list.js';
4
+ import { configCommand } from './commands/config.js';
5
+ const program = new Command();
6
+ program
7
+ .name('x402charity')
8
+ .description('Donate to charities via x402 stablecoin payments')
9
+ .version('0.1.0');
10
+ program.addCommand(donateCommand);
11
+ program.addCommand(listCommand);
12
+ program.addCommand(configCommand);
13
+ program.parse();
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "x402charity",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "bin": {
6
+ "x402charity": "./bin/cli.js"
7
+ },
8
+ "scripts": {
9
+ "build": "tsc",
10
+ "clean": "rm -rf dist"
11
+ },
12
+ "dependencies": {
13
+ "@x402charity/core": "workspace:*",
14
+ "commander": "^12.0.0"
15
+ },
16
+ "devDependencies": {
17
+ "@types/node": "^25.3.3",
18
+ "typescript": "^5.4.0"
19
+ },
20
+ "license": "MIT"
21
+ }
@@ -0,0 +1,40 @@
1
+ import { Command } from 'commander';
2
+ import { saveCliConfig, loadCliConfig } from '../config.js';
3
+
4
+ export const configCommand = new Command('config')
5
+ .description('Configure x402charity CLI');
6
+
7
+ configCommand
8
+ .command('set-key <privateKey>')
9
+ .description('Set your wallet private key')
10
+ .action((privateKey: string) => {
11
+ const config = loadCliConfig();
12
+ config.privateKey = privateKey;
13
+ saveCliConfig(config);
14
+ console.log('Private key saved to ~/.x402charity/config.json');
15
+ });
16
+
17
+ configCommand
18
+ .command('set-network <network>')
19
+ .description('Set default network (base or base-sepolia)')
20
+ .action((network: string) => {
21
+ if (network !== 'base' && network !== 'base-sepolia') {
22
+ console.error('Network must be "base" or "base-sepolia"');
23
+ process.exit(1);
24
+ }
25
+ const config = loadCliConfig();
26
+ config.network = network as 'base' | 'base-sepolia';
27
+ saveCliConfig(config);
28
+ console.log(`Default network set to ${network}`);
29
+ });
30
+
31
+ configCommand
32
+ .command('show')
33
+ .description('Show current configuration')
34
+ .action(() => {
35
+ const config = loadCliConfig();
36
+ console.log('\nCurrent configuration:\n');
37
+ console.log(` Network: ${config.network || 'base-sepolia (default)'}`);
38
+ console.log(` Private Key: ${config.privateKey ? '****' + config.privateKey.slice(-4) : 'not set'}`);
39
+ console.log(` Config File: ~/.x402charity/config.json\n`);
40
+ });
@@ -0,0 +1,33 @@
1
+ import { Command } from 'commander';
2
+ import { X402CharityClient } from '@x402charity/core';
3
+ import { getPrivateKey, getNetwork } from '../config.js';
4
+
5
+ export const donateCommand = new Command('donate')
6
+ .description('Donate USDC to a charity')
7
+ .argument('<cause>', 'Charity ID or name')
8
+ .argument('[amount]', 'Amount in USDC (default: 0.0001)')
9
+ .option('-n, --network <network>', 'Network: base or base-sepolia')
10
+ .action(async (cause: string, amount: string | undefined, options: { network?: string }) => {
11
+ amount = amount || '0.0001';
12
+ try {
13
+ const privateKey = getPrivateKey();
14
+ const network = (options.network || getNetwork()) as 'base' | 'base-sepolia';
15
+
16
+ const client = new X402CharityClient({ privateKey, network });
17
+
18
+ console.log(`\nDonating ${amount} USDC to "${cause}" on ${network}...\n`);
19
+
20
+ const receipt = await client.donate(cause, amount);
21
+
22
+ console.log('Donation successful!\n');
23
+ console.log(` Charity: ${receipt.charity.name}`);
24
+ console.log(` Amount: ${receipt.amount} ${receipt.currency}`);
25
+ console.log(` Tx Hash: ${receipt.txHash}`);
26
+ console.log(` Chain: ${receipt.chain}`);
27
+ console.log(` From: ${receipt.from}`);
28
+ console.log(` To: ${receipt.to}\n`);
29
+ } catch (error: any) {
30
+ console.error(`\nError: ${error.message}\n`);
31
+ process.exit(1);
32
+ }
33
+ });
@@ -0,0 +1,21 @@
1
+ import { Command } from 'commander';
2
+ import { listCharities } from '@x402charity/core';
3
+
4
+ export const listCommand = new Command('list')
5
+ .description('List available charities')
6
+ .action(() => {
7
+ const charities = listCharities();
8
+
9
+ console.log('\nAvailable charities:\n');
10
+
11
+ for (const charity of charities) {
12
+ const badge = charity.verified ? ' [verified]' : '';
13
+ console.log(` ${charity.id}${badge}`);
14
+ console.log(` ${charity.name}`);
15
+ console.log(` ${charity.description}`);
16
+ console.log(` Wallet: ${charity.walletAddress}`);
17
+ console.log(` Chain: ${charity.chain}`);
18
+ if (charity.website) console.log(` Web: ${charity.website}`);
19
+ console.log('');
20
+ }
21
+ });
package/src/config.ts ADDED
@@ -0,0 +1,42 @@
1
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { homedir } from 'node:os';
4
+
5
+ const CONFIG_DIR = join(homedir(), '.x402charity');
6
+ const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
7
+
8
+ interface CliConfig {
9
+ privateKey?: string;
10
+ network?: 'base' | 'base-sepolia';
11
+ }
12
+
13
+ export function loadCliConfig(): CliConfig {
14
+ if (!existsSync(CONFIG_FILE)) return {};
15
+ return JSON.parse(readFileSync(CONFIG_FILE, 'utf-8'));
16
+ }
17
+
18
+ export function saveCliConfig(config: CliConfig): void {
19
+ mkdirSync(CONFIG_DIR, { recursive: true });
20
+ writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), { mode: 0o600 });
21
+ }
22
+
23
+ export function getPrivateKey(): string {
24
+ const envKey = process.env.X402_PRIVATE_KEY;
25
+ if (envKey) return envKey;
26
+
27
+ const config = loadCliConfig();
28
+ if (config.privateKey) return config.privateKey;
29
+
30
+ console.error(
31
+ 'No private key found. Set X402_PRIVATE_KEY env var or run:\n x402charity config set-key <key>',
32
+ );
33
+ return process.exit(1) as never;
34
+ }
35
+
36
+ export function getNetwork(): 'base' | 'base-sepolia' {
37
+ const envNetwork = process.env.X402_NETWORK;
38
+ if (envNetwork === 'base' || envNetwork === 'base-sepolia') return envNetwork;
39
+
40
+ const config = loadCliConfig();
41
+ return config.network || 'base-sepolia';
42
+ }
package/src/index.ts ADDED
@@ -0,0 +1,17 @@
1
+ import { Command } from 'commander';
2
+ import { donateCommand } from './commands/donate.js';
3
+ import { listCommand } from './commands/list.js';
4
+ import { configCommand } from './commands/config.js';
5
+
6
+ const program = new Command();
7
+
8
+ program
9
+ .name('x402charity')
10
+ .description('Donate to charities via x402 stablecoin payments')
11
+ .version('0.1.0');
12
+
13
+ program.addCommand(donateCommand);
14
+ program.addCommand(listCommand);
15
+ program.addCommand(configCommand);
16
+
17
+ program.parse();
package/tsconfig.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "Node16",
5
+ "moduleResolution": "Node16",
6
+ "lib": ["ES2022"],
7
+ "declaration": true,
8
+ "outDir": "dist",
9
+ "rootDir": "src",
10
+ "strict": true,
11
+ "esModuleInterop": true,
12
+ "skipLibCheck": true,
13
+ "forceConsistentCasingInFileNames": true
14
+ },
15
+ "include": ["src"]
16
+ }