feat: get, show, clear wallet command

This commit is contained in:
ngoc 2026-02-01 15:18:27 +07:00
parent 2f1368bb9c
commit 048206d1da
No known key found for this signature in database
GPG Key ID: 51FE6110113A5C32
7 changed files with 184 additions and 16 deletions

View File

@ -12,7 +12,7 @@ import { existsSync, readFileSync } from "fs";
import { resolve, dirname, join } from "path";
import { fileURLToPath } from "url";
import { makeClient } from "alkahest-ts";
import { getChainFromNetwork, loadDeploymentWithDefaults } from "../utils.js";
import { getChainFromNetwork, loadDeploymentWithDefaults, getPrivateKey } from "../utils.js";
// Get the directory of the current module
const __filename = fileURLToPath(import.meta.url);
@ -84,7 +84,7 @@ async function main() {
// Get configuration
const escrowUid = args["escrow-uid"];
const fulfillmentUid = args["fulfillment-uid"];
const privateKey = args["private-key"] || process.env.PRIVATE_KEY;
const privateKey = args["private-key"] || getPrivateKey();
const deploymentPath = args.deployment;
// Validate required parameters
@ -101,8 +101,12 @@ async function main() {
}
if (!privateKey) {
console.error("❌ Error: Private key is required. Use --private-key or set PRIVATE_KEY");
console.error("Run with --help for usage information.");
console.error("❌ Error: Private key is required");
console.error("\n💡 You can either:");
console.error(" 1. Set it globally: nla wallet:set --private-key <your-key>");
console.error(" 2. Use for this command only: --private-key <your-key>");
console.error(" 3. Set PRIVATE_KEY environment variable");
console.error("\nRun with --help for usage information.");
process.exit(1);
}

View File

@ -15,7 +15,7 @@ import { fileURLToPath } from "url";
import { makeClient } from "alkahest-ts";
import { makeLLMClient } from "../..";
import {fixtures} from "alkahest-ts";
import { getCurrentEnvironment, getChainFromNetwork, loadDeploymentWithDefaults } from "../utils.js";
import { getCurrentEnvironment, getChainFromNetwork, loadDeploymentWithDefaults, getPrivateKey } from "../utils.js";
// Get the directory of the current module
const __filename = fileURLToPath(import.meta.url);
@ -104,7 +104,7 @@ async function main() {
const amount = args.amount;
const tokenAddress = args.token;
const oracleAddress = args.oracle;
const privateKey = args["private-key"] || process.env.PRIVATE_KEY;
const privateKey = args["private-key"] || getPrivateKey();
const deploymentPath = args.deployment;
// Arbitration configuration with defaults
@ -143,8 +143,12 @@ Fulfillment: {{obligation}}`;
}
if (!privateKey) {
console.error("❌ Error: Private key is required. Use --private-key or set PRIVATE_KEY");
console.error("Run with --help for usage information.");
console.error("❌ Error: Private key is required");
console.error("\n💡 You can either:");
console.error(" 1. Set it globally: nla wallet:set --private-key <your-key>");
console.error(" 2. Use for this command only: --private-key <your-key>");
console.error(" 3. Set PRIVATE_KEY environment variable");
console.error("\nRun with --help for usage information.");
process.exit(1);
}

View File

@ -14,7 +14,7 @@ import { resolve, dirname, join } from "path";
import { fileURLToPath } from "url";
import { makeClient } from "alkahest-ts";
import { makeLLMClient } from "../..";
import { getChainFromNetwork, loadDeploymentWithDefaults } from "../utils.js";
import { getChainFromNetwork, loadDeploymentWithDefaults, getPrivateKey } from "../utils.js";
// Get the directory of the current module
const __filename = fileURLToPath(import.meta.url);
@ -90,7 +90,7 @@ async function main() {
const escrowUid = args["escrow-uid"];
const fulfillment = args.fulfillment;
const oracleAddress = args.oracle;
const privateKey = args["private-key"] || process.env.PRIVATE_KEY;
const privateKey = args["private-key"] || getPrivateKey();
const deploymentPath = args.deployment ;
// Validate required parameters
@ -113,8 +113,12 @@ async function main() {
}
if (!privateKey) {
console.error("❌ Error: Private key is required. Use --private-key or set PRIVATE_KEY");
console.error("Run with --help for usage information.");
console.error("❌ Error: Private key is required");
console.error("\n💡 You can either:");
console.error(" 1. Set it globally: nla wallet:set --private-key <your-key>");
console.error(" 2. Use for this command only: --private-key <your-key>");
console.error(" 3. Set PRIVATE_KEY environment variable");
console.error("\nRun with --help for usage information.");
process.exit(1);
}

72
cli/commands/wallet.ts Normal file
View File

@ -0,0 +1,72 @@
/**
* Wallet management commands
*/
import { setPrivateKey, clearPrivateKey, getPrivateKey } from "../utils.js";
import { privateKeyToAddress } from "viem/accounts";
/**
* Set wallet private key
*/
export async function setWallet(privateKey: string): Promise<void> {
// Validate private key format
if (!privateKey.startsWith('0x')) {
console.error('❌ Private key must start with 0x');
process.exit(1);
}
if (privateKey.length !== 66) {
console.error('❌ Invalid private key length. Expected 66 characters (0x + 64 hex chars)');
process.exit(1);
}
try {
// Validate by deriving address
const address = privateKeyToAddress(privateKey as `0x${string}`);
// Store in config
setPrivateKey(privateKey);
console.log('✅ Wallet configured successfully');
console.log(`📍 Address: ${address}`);
console.log('\n💡 Your private key is stored in ~/.nla/config.json');
console.log(' It will be used automatically for all transactions');
} catch (error) {
console.error('❌ Invalid private key format');
process.exit(1);
}
}
/**
* Show current wallet address
*/
export async function showWallet(): Promise<void> {
const privateKey = getPrivateKey();
if (!privateKey) {
console.log(' No wallet configured');
console.log('\n💡 Set your wallet with:');
console.log(' nla wallet:set --private-key <your-key>');
return;
}
try {
const address = privateKeyToAddress(privateKey as `0x${string}`);
console.log('✅ Wallet configured');
console.log(`📍 Address: ${address}`);
} catch (error) {
console.error('❌ Invalid private key in config');
console.log('\n💡 Update your wallet with:');
console.log(' nla wallet:set --private-key <your-key>');
}
}
/**
* Clear wallet from config
*/
export async function clearWallet(): Promise<void> {
clearPrivateKey();
console.log('✅ Wallet cleared from config');
console.log('\n💡 Set a new wallet with:');
console.log(' nla wallet:set --private-key <your-key>');
}

View File

@ -12,6 +12,7 @@ import { contracts } from "alkahest-ts";
import { runDevCommand } from "./commands/dev.js";
import { runStopCommand } from "./commands/stop.js";
import { runSwitchCommand } from "./commands/switch.js";
import { setWallet, showWallet, clearWallet } from "./commands/wallet.js";
// Get the directory name for ESM modules (compatible with both Node and Bun)
const __filename = fileURLToPath(import.meta.url);
@ -31,6 +32,9 @@ Commands:
stop Stop all services (Anvil + Oracle)
switch [env] Switch between environments (devnet, sepolia, base-sepolia, mainnet)
network Show current network/environment
wallet:set Set wallet private key
wallet:show Show current wallet address
wallet:clear Clear wallet from config
escrow:create Create a new escrow with natural language demand
escrow:fulfill Fulfill an existing escrow
escrow:collect Collect an approved escrow
@ -182,6 +186,27 @@ async function main() {
return;
}
// Handle wallet commands
if (command === "wallet:set") {
const privateKey = args["private-key"] as string | undefined;
if (!privateKey) {
console.error("❌ Missing required option: --private-key");
process.exit(1);
}
await setWallet(privateKey);
return;
}
if (command === "wallet:show") {
await showWallet();
return;
}
if (command === "wallet:clear") {
await clearWallet();
return;
}
// Handle TypeScript commands that can run directly
if (command === "deploy") {
await runServerCommand("deploy.js", process.argv.slice(3));

View File

@ -15,7 +15,8 @@ import {
getDeploymentPath,
loadEnvFile,
loadDeploymentWithDefaults,
getChainFromNetwork
getChainFromNetwork,
getPrivateKey
} from "../utils.js";
// Get the directory name for ESM modules
@ -131,7 +132,7 @@ async function main() {
const deployment = loadDeploymentWithDefaults(deploymentFile);
console.log(`✅ Loaded deployment (${deployment.network})\n`);
const privateKey = args["private-key"] || process.env.ORACLE_PRIVATE_KEY;
const privateKey = args["private-key"] || getPrivateKey();
const openaiApiKey = args["openai-api-key"] || process.env.OPENAI_API_KEY;
const anthropicApiKey = args["anthropic-api-key"] || process.env.ANTHROPIC_API_KEY;
const openrouterApiKey = args["openrouter-api-key"] || process.env.OPENROUTER_API_KEY;
@ -149,8 +150,12 @@ async function main() {
if (!privateKey) {
console.error("❌ Error: Private key is required.");
console.error(" Set ORACLE_PRIVATE_KEY in .env file or use --private-key");
console.error("Run with --help for usage information.");
console.error("\n💡 You can either:");
console.error(" 1. Set it globally: nla wallet:set --private-key <your-key>");
console.error(" 2. Use for this command only: --private-key <your-key>");
console.error(" 3. Set ORACLE_PRIVATE_KEY in .env file");
console.error(" 4. Set PRIVATE_KEY environment variable");
console.error("\nRun with --help for usage information.");
process.exit(1);
}

View File

@ -115,6 +115,60 @@ export function setCurrentEnvironment(env: string): void {
writeFileSync(configPath, JSON.stringify(config, null, 2));
}
/**
* Get private key from config or environment
*/
export function getPrivateKey(): string | undefined {
// First check environment variable
if (process.env.PRIVATE_KEY) {
return process.env.PRIVATE_KEY;
}
// Then check config file
const configPath = join(getNLAConfigDir(), 'config.json');
if (!existsSync(configPath)) {
return undefined;
}
try {
const config = JSON.parse(readFileSync(configPath, 'utf-8'));
return config.privateKey;
} catch (e) {
return undefined;
}
}
/**
* Set private key in config
*/
export function setPrivateKey(privateKey: string): void {
const configPath = join(getNLAConfigDir(), 'config.json');
const config = existsSync(configPath)
? JSON.parse(readFileSync(configPath, 'utf-8'))
: {};
config.privateKey = privateKey;
writeFileSync(configPath, JSON.stringify(config, null, 2));
}
/**
* Clear private key from config
*/
export function clearPrivateKey(): void {
const configPath = join(getNLAConfigDir(), 'config.json');
if (!existsSync(configPath)) {
return;
}
try {
const config = JSON.parse(readFileSync(configPath, 'utf-8'));
delete config.privateKey;
writeFileSync(configPath, JSON.stringify(config, null, 2));
} catch (e) {
// Ignore errors
}
}
/**
* Get deployment path for environment
*/