UNPKG

@pod-protocol/cli

Version:

Command-line interface for PoD Protocol (Prompt or Die) AI Agent Communication Protocol

168 lines (167 loc) 4.97 kB
import { PublicKey } from "@solana/web3.js"; import chalk from "chalk"; /** * Validation error class for CLI operations */ export class ValidationError extends Error { constructor(message) { super(message); this.name = "ValidationError"; } } /** * Validate a Solana public key address */ export function validatePublicKey(address, fieldName = "address") { try { return new PublicKey(address); } catch { throw new ValidationError(`Invalid ${fieldName}: ${address}`); } } /** * Validate SOL amount (must be positive) */ export function validateSolAmount(amount, fieldName = "amount") { const numAmount = typeof amount === "string" ? parseFloat(amount) : amount; if (isNaN(numAmount)) { throw new ValidationError(`Invalid ${fieldName}: must be a number`); } if (numAmount <= 0) { throw new ValidationError(`Invalid ${fieldName}: must be positive`); } if (numAmount > 1000000) { throw new ValidationError(`Invalid ${fieldName}: amount too large`); } return numAmount; } /** * Validate capabilities bitmask */ export function validateCapabilities(capabilities) { const numCaps = typeof capabilities === "string" ? parseInt(capabilities, 10) : capabilities; if (isNaN(numCaps)) { throw new ValidationError("Invalid capabilities: must be a number"); } if (numCaps < 0) { throw new ValidationError("Invalid capabilities: must be non-negative"); } if (numCaps > 255) { throw new ValidationError("Invalid capabilities: value too large"); } return numCaps; } /** * Validate URI format */ export function validateUri(uri, fieldName = "URI") { if (!uri.trim()) { throw new ValidationError(`${fieldName} cannot be empty`); } try { new URL(uri); return uri.trim(); } catch { // Allow relative paths and simple strings for metadata URIs if (uri.length > 500) { throw new ValidationError(`${fieldName} too long (max 500 characters)`); } return uri.trim(); } } /** * Validate channel name */ export function validateChannelName(name) { if (!name.trim()) { throw new ValidationError("Channel name cannot be empty"); } if (name.length > 32) { throw new ValidationError("Channel name too long (max 32 characters)"); } if (!/^[a-zA-Z0-9_-]+$/.test(name)) { throw new ValidationError("Channel name can only contain letters, numbers, underscores, and hyphens"); } return name.trim(); } /** * Validate message content */ export function validateMessage(content) { if (!content.trim()) { throw new ValidationError("Message content cannot be empty"); } if (content.length > 10000) { throw new ValidationError("Message too long (max 10,000 characters)"); } return content.trim(); } /** * Validate network name */ export function validateNetwork(network) { const validNetworks = ["devnet", "testnet", "mainnet-beta", "localnet"]; if (!validNetworks.includes(network)) { throw new ValidationError(`Invalid network: ${network}. Must be one of: ${validNetworks.join(", ")}`); } return network; } /** * Validate file path exists and is readable */ export function validateFilePath(filePath, fieldName = "file") { if (!filePath.trim()) { throw new ValidationError(`${fieldName} path cannot be empty`); } // Basic path validation - more thorough checks should be done with fs if (filePath.includes("..") && !filePath.startsWith("~/")) { console.warn(chalk.yellow(`Warning: ${fieldName} path contains '..' - ensure this is intentional`)); } return filePath.trim(); } /** * Validate positive integer */ export function validatePositiveInteger(value, fieldName = "value") { const num = typeof value === "string" ? parseInt(value, 10) : value; if (isNaN(num) || !Number.isInteger(num)) { throw new ValidationError(`Invalid ${fieldName}: must be an integer`); } if (num <= 0) { throw new ValidationError(`Invalid ${fieldName}: must be positive`); } return num; } /** * Validate enum value */ export function validateEnum(value, validValues, fieldName = "value") { if (!validValues.includes(value)) { throw new ValidationError(`Invalid ${fieldName}: ${value}. Must be one of: ${validValues.join(", ")}`); } return value; } /** * Safe validation wrapper that catches and formats errors */ export function safeValidate(validator, onError) { try { return validator(); } catch (error) { if (error instanceof ValidationError) { if (onError) { onError(error); } else { console.error(chalk.red("Validation Error:"), error.message); } return null; } throw error; } }