@fiber-pay/agent 0.1.0-rc.1

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 @@
1
+ {"version":3,"sources":["../src/fiber-pay.ts","../src/mcp-tools.ts"],"sourcesContent":["/**\n * FiberPay - AI Agent-Friendly Payment Interface\n * High-level, LLM-friendly commands for payment operations\n *\n * This is the primary interface designed for AI agents to manage\n * payments on the CKB Lightning Network (Fiber Network).\n */\n\nimport { randomUUID } from 'node:crypto';\nimport { join } from 'node:path';\nimport type { DownloadProgress } from '@fiber-pay/node';\nimport { ensureFiberBinary, ProcessManager } from '@fiber-pay/node';\nimport { JobManager, type RuntimeJob, SqliteJobStore } from '@fiber-pay/runtime';\nimport type {\n Attribute,\n CkbInvoice,\n CkbInvoiceStatus,\n HexString,\n InvoiceVerificationResult,\n LiquidityReport,\n PaymentProof,\n PaymentProofSummary,\n PolicyCheckResult,\n SecurityPolicy,\n} from '@fiber-pay/sdk';\nimport {\n ChannelState,\n ckbToShannons,\n createKeyManager,\n FiberRpcClient,\n fromHex,\n InvoiceVerifier,\n type KeyManager,\n LiquidityAnalyzer,\n PaymentProofManager,\n PolicyEngine,\n randomBytes32,\n shannonsToCkb,\n toHex,\n} from '@fiber-pay/sdk';\n\n// =============================================================================\n// Agent-Friendly Result Types\n// =============================================================================\n\n/**\n * Standard result format for all operations\n * Designed to be easily parsed by AI agents\n */\nexport interface AgentResult<T = unknown> {\n success: boolean;\n data?: T;\n error?: {\n code: string;\n message: string;\n recoverable: boolean;\n suggestion?: string;\n };\n metadata?: {\n timestamp: number;\n policyCheck?: PolicyCheckResult;\n };\n}\n\n/**\n * Balance information in human-readable format\n */\nexport interface BalanceInfo {\n /** Total balance across all channels (in CKB) */\n totalCkb: number;\n /** Available to send (in CKB) */\n availableToSend: number;\n /** Available to receive (in CKB) */\n availableToReceive: number;\n /** Number of active channels */\n channelCount: number;\n /** Remaining spending allowance this period (in CKB) */\n spendingAllowance: number;\n}\n\n/**\n * Payment result with tracking info\n */\nexport interface PaymentResult {\n /** Payment hash for tracking */\n paymentHash: string;\n /** Status of the payment */\n status: 'pending' | 'success' | 'failed';\n /** Amount sent (in CKB) */\n amountCkb: number;\n /** Fee paid (in CKB) */\n feeCkb: number;\n /** Error message if failed */\n failureReason?: string;\n}\n\n/**\n * Invoice result\n */\nexport interface InvoiceResult {\n /** Invoice string to share with payer */\n invoice: string;\n /** Payment hash for tracking */\n paymentHash: string;\n /** Amount to receive (in CKB) */\n amountCkb: number;\n /** Expiry time (ISO string) */\n expiresAt: string;\n /** Status */\n status: 'open' | 'accepted' | 'settled' | 'cancelled';\n}\n\n/**\n * Hold invoice result (for escrow / conditional payments)\n */\nexport interface HoldInvoiceResult {\n /** Invoice string to share with payer */\n invoice: string;\n /** Payment hash for tracking */\n paymentHash: string;\n /** Amount to receive (in CKB) */\n amountCkb: number;\n /** Expiry time (ISO string) */\n expiresAt: string;\n /** Status — starts as 'open', becomes 'accepted' when payer sends */\n status: 'open' | 'accepted' | 'settled' | 'cancelled';\n}\n\n/**\n * Channel summary\n */\nexport interface ChannelSummary {\n /** Channel ID */\n id: string;\n /** Peer node ID */\n peerId: string;\n /** Local balance (in CKB) */\n localBalanceCkb: number;\n /** Remote balance (in CKB) */\n remoteBalanceCkb: number;\n /** Channel state */\n state: string;\n /** Is public channel */\n isPublic: boolean;\n}\n\n/**\n * Verification result for invoices\n */\nexport type InvoiceValidationResult = InvoiceVerificationResult;\n\n/**\n * Liquidity analysis result\n */\nexport type LiquidityAnalysisResult = LiquidityReport;\n\n// =============================================================================\n// FiberPay Agent Interface\n// =============================================================================\n\nexport interface FiberPayConfig {\n /** Path to the fnn binary (optional - will auto-download if not provided) */\n binaryPath?: string;\n /** Base directory for all data */\n dataDir: string;\n /** Path to the config file (optional - will use built-in testnet config if not provided) */\n configFilePath?: string;\n /** Security policy */\n policy?: SecurityPolicy;\n /** Key encryption password (recommended: set via FIBER_KEY_PASSWORD env var) */\n keyPassword?: string;\n /** CKB RPC URL */\n ckbRpcUrl?: string;\n /** Chain: mainnet or testnet */\n chain?: 'mainnet' | 'testnet';\n /** Bootstrap nodes */\n bootnodes?: string[];\n /** Auto-start the node */\n autoStart?: boolean;\n /** RPC port */\n rpcPort?: number;\n /** P2P port */\n p2pPort?: number;\n /** Auto-download binary if not found */\n autoDownload?: boolean;\n /** RPC URL for connecting to an existing node (when autoStart is false) */\n rpcUrl?: string;\n /** Enable runtime job orchestration for payments/invoices/channels (default: true) */\n useRuntimeJobs?: boolean;\n /** Optional sqlite path for runtime jobs */\n runtimeJobsDbPath?: string;\n}\n\n/**\n * FiberPay - Main interface for AI agents\n *\n * @example\n * ```typescript\n * const fiber = new FiberPay({\n * binaryPath: '/usr/local/bin/fnn',\n * dataDir: '~/.fiber-pay',\n * });\n *\n * await fiber.initialize();\n *\n * // Check balance\n * const balance = await fiber.getBalance();\n *\n * // Send payment\n * const result = await fiber.pay({\n * invoice: 'fibt1...',\n * });\n *\n * // Create invoice to receive payment\n * const invoice = await fiber.createInvoice({\n * amountCkb: 10,\n * description: 'Payment for services',\n * });\n * ```\n */\nexport class FiberPay {\n private config: FiberPayConfig;\n private process: ProcessManager | null = null;\n private rpc: FiberRpcClient | null = null;\n private policy: PolicyEngine;\n private keys: KeyManager;\n private initialized = false;\n private invoiceVerifier: InvoiceVerifier | null = null;\n private paymentProofManager: PaymentProofManager | null = null;\n private liquidityAnalyzer: LiquidityAnalyzer | null = null;\n private runtimeJobStore: SqliteJobStore | null = null;\n private runtimeJobManager: JobManager | null = null;\n\n constructor(config: FiberPayConfig) {\n this.config = {\n chain: 'testnet',\n autoStart: true,\n rpcPort: 8227,\n p2pPort: 8228,\n useRuntimeJobs: true,\n ...config,\n };\n\n // Initialize policy engine with default or custom policy\n const defaultPolicy: SecurityPolicy = {\n name: 'default',\n version: '1.0.0',\n enabled: true,\n spending: {\n maxPerTransaction: '0x2540be400', // 100 CKB\n maxPerWindow: '0x174876e800', // 1000 CKB\n windowSeconds: 3600,\n },\n rateLimit: {\n maxTransactions: 100,\n windowSeconds: 3600,\n cooldownSeconds: 1,\n },\n recipients: {\n allowUnknown: true,\n },\n channels: {\n allowOpen: true,\n allowClose: true,\n allowForceClose: false,\n maxChannels: 10,\n },\n auditLogging: true,\n };\n\n this.policy = new PolicyEngine(config.policy || defaultPolicy);\n\n // Initialize key manager\n this.keys = createKeyManager(config.dataDir, {\n encryptionPassword: config.keyPassword,\n autoGenerate: true,\n });\n }\n\n // ===========================================================================\n // Lifecycle Methods\n // ===========================================================================\n\n /**\n * Initialize the FiberPay instance\n * - Downloads the binary if needed (and autoDownload is true)\n * - Generates or loads keys\n * - Starts the Fiber node (if autoStart is true)\n * - Connects to RPC\n */\n async initialize(options?: {\n onDownloadProgress?: (progress: DownloadProgress) => void;\n }): Promise<AgentResult<{ nodeId: string }>> {\n try {\n // Resolve binary path - download if needed\n let binaryPath = this.config.binaryPath;\n\n if (!binaryPath) {\n if (this.config.autoDownload !== false) {\n // Auto-download the binary\n binaryPath = await ensureFiberBinary({\n installDir: `${this.config.dataDir}/bin`,\n onProgress: options?.onDownloadProgress,\n });\n } else {\n return this.errorResult(\n new Error('Binary path not provided and autoDownload is disabled'),\n 'BINARY_NOT_FOUND',\n true,\n );\n }\n }\n\n // Initialize keys\n const _keyInfo = await this.keys.initialize();\n\n // Create process manager\n this.process = new ProcessManager({\n binaryPath,\n dataDir: this.config.dataDir,\n configFilePath: this.config.configFilePath,\n chain: this.config.chain,\n ckbRpcUrl: this.config.ckbRpcUrl,\n keyPassword: this.config.keyPassword,\n rpcListeningAddr: `127.0.0.1:${this.config.rpcPort}`,\n fiberListeningAddr: `/ip4/0.0.0.0/tcp/${this.config.p2pPort}`,\n bootnodeAddrs: this.config.bootnodes,\n });\n\n // Create RPC client - use provided rpcUrl or construct from rpcPort\n const rpcUrl = this.config.rpcUrl || `http://127.0.0.1:${this.config.rpcPort}`;\n this.rpc = new FiberRpcClient({\n url: rpcUrl,\n });\n\n // Start node if autoStart\n if (this.config.autoStart) {\n await this.process.start();\n await this.rpc.waitForReady({ timeout: 60000 });\n }\n\n // Initialize verification and analysis systems\n this.invoiceVerifier = new InvoiceVerifier(this.rpc);\n this.paymentProofManager = new PaymentProofManager(this.config.dataDir);\n await this.paymentProofManager.load();\n this.liquidityAnalyzer = new LiquidityAnalyzer(this.rpc);\n\n if (this.config.useRuntimeJobs !== false) {\n this.runtimeJobStore = new SqliteJobStore(\n this.config.runtimeJobsDbPath ?? join(this.config.dataDir, 'runtime-jobs.db'),\n );\n this.runtimeJobManager = new JobManager(this.rpc, this.runtimeJobStore);\n this.runtimeJobManager.start();\n }\n\n this.initialized = true;\n\n // Get node info\n const nodeInfo = await this.rpc.nodeInfo();\n\n this.policy.addAuditEntry('NODE_STARTED', true, {\n nodeId: nodeInfo.node_id,\n });\n\n return {\n success: true,\n data: {\n nodeId: nodeInfo.node_id,\n },\n metadata: { timestamp: Date.now() },\n };\n } catch (error) {\n return this.errorResult(error, 'INIT_FAILED', false);\n }\n }\n\n /**\n * Shutdown the FiberPay instance\n */\n async shutdown(): Promise<AgentResult<void>> {\n try {\n // Save payment proofs before shutdown\n if (this.paymentProofManager) {\n await this.paymentProofManager.save();\n }\n\n if (this.runtimeJobManager) {\n await this.runtimeJobManager.stop();\n }\n if (this.runtimeJobStore) {\n this.runtimeJobStore.close();\n }\n\n if (this.process?.isRunning()) {\n await this.process.stop();\n }\n this.policy.addAuditEntry('NODE_STOPPED', true, {});\n this.initialized = false;\n return { success: true, metadata: { timestamp: Date.now() } };\n } catch (error) {\n return this.errorResult(error, 'SHUTDOWN_FAILED', true);\n }\n }\n\n // ===========================================================================\n // Payment Methods (AI Agent Friendly)\n // ===========================================================================\n\n /**\n * Pay an invoice or send directly to a node\n *\n * @example\n * // Pay invoice\n * await fiber.pay({ invoice: 'fibt1...' });\n *\n * // Send directly (keysend)\n * await fiber.pay({\n * recipientNodeId: 'QmXXX...',\n * amountCkb: 10,\n * });\n */\n async pay(params: {\n /** Invoice string to pay */\n invoice?: string;\n /** Recipient node ID for keysend */\n recipientNodeId?: string;\n /** Amount in CKB (for keysend) */\n amountCkb?: number;\n /** Maximum fee in CKB */\n maxFeeCkb?: number;\n /** Custom TLV records to attach (up to 2KB) */\n customRecords?: Record<string, HexString>;\n /** Maximum number of MPP parts (e.g. 4) */\n maxParts?: number;\n }): Promise<AgentResult<PaymentResult>> {\n this.ensureInitialized();\n\n try {\n // Determine amount\n let amountHex: HexString;\n let recipient: string | undefined;\n\n if (params.invoice) {\n // Parse invoice to get amount\n const parsed = await this.getRpc().parseInvoice({ invoice: params.invoice });\n amountHex = parsed.invoice.amount || '0x0';\n recipient = params.invoice; // Use invoice as recipient identifier for policy\n } else if (params.recipientNodeId && params.amountCkb) {\n amountHex = ckbToShannons(params.amountCkb);\n recipient = params.recipientNodeId;\n } else {\n return this.errorResult(\n new Error('Either invoice or (recipientNodeId + amountCkb) required'),\n 'INVALID_PARAMS',\n true,\n );\n }\n\n // Check policy\n const policyCheck = this.policy.checkPayment({\n amount: amountHex,\n recipient,\n });\n\n if (!policyCheck.allowed) {\n this.policy.addAuditEntry('POLICY_VIOLATION', false, params, policyCheck.violations);\n return {\n success: false,\n error: {\n code: 'POLICY_VIOLATION',\n message: policyCheck.violations.map((v) => v.message).join('; '),\n recoverable: false,\n suggestion: 'Reduce amount or wait for spending window to reset',\n },\n metadata: { timestamp: Date.now(), policyCheck },\n };\n }\n\n const paymentParams = {\n invoice: params.invoice,\n target_pubkey: params.recipientNodeId as HexString | undefined,\n amount: params.recipientNodeId ? amountHex : undefined,\n keysend: params.recipientNodeId ? true : undefined,\n max_fee_amount: params.maxFeeCkb ? ckbToShannons(params.maxFeeCkb) : undefined,\n custom_records: params.customRecords,\n max_parts: params.maxParts ? toHex(params.maxParts) : undefined,\n };\n\n // Execute payment through runtime job manager when enabled\n let result: Awaited<ReturnType<FiberRpcClient['sendPayment']>>;\n if (this.runtimeJobManager) {\n const job = await this.runtimeJobManager.ensurePayment(\n {\n invoice: params.invoice,\n sendPaymentParams: paymentParams,\n },\n {\n idempotencyKey: params.invoice ? `payment:invoice:${params.invoice}` : undefined,\n },\n );\n const terminal = await this.waitForRuntimeJobTerminal(job.id, 120_000);\n if (terminal.type !== 'payment' || terminal.state !== 'succeeded' || !terminal.result) {\n throw new Error(terminal.error?.message ?? 'Runtime payment job failed');\n }\n result = {\n payment_hash: terminal.result.paymentHash as HexString,\n status: terminal.result.status as 'Success' | 'Failed' | 'Inflight' | 'Created',\n fee: terminal.result.fee as HexString,\n failed_error: terminal.result.failedError,\n created_at: '0x0',\n last_updated_at: '0x0',\n custom_records: undefined,\n routers: undefined,\n };\n } else {\n result = await this.getRpc().sendPayment(paymentParams);\n }\n\n // Record successful payment\n if (result.status === 'Success') {\n this.policy.recordPayment(amountHex);\n }\n\n const paymentResult: PaymentResult = {\n paymentHash: result.payment_hash,\n status:\n result.status === 'Success'\n ? 'success'\n : result.status === 'Failed'\n ? 'failed'\n : 'pending',\n amountCkb: shannonsToCkb(amountHex),\n feeCkb: shannonsToCkb(result.fee),\n failureReason: result.failed_error,\n };\n\n // Record payment proof\n if (this.paymentProofManager && result.status === 'Success') {\n this.paymentProofManager.recordPaymentProof(\n result.payment_hash,\n params.invoice || '',\n {\n paymentHash: result.payment_hash,\n amountCkb: paymentResult.amountCkb,\n description: '',\n },\n {\n amountCkb: paymentResult.amountCkb,\n feeCkb: paymentResult.feeCkb,\n actualTimestamp: Date.now(),\n requestTimestamp: Date.now(),\n },\n result.status,\n {\n preimage: undefined, // Would need to get from RPC if available\n },\n );\n // Save asynchronously (don't wait)\n this.paymentProofManager.save().catch(() => {\n // Ignore save errors\n });\n }\n\n this.policy.addAuditEntry('PAYMENT_SENT', result.status === 'Success', {\n ...paymentResult,\n recipient,\n });\n\n return {\n success: result.status === 'Success',\n data: paymentResult,\n metadata: { timestamp: Date.now(), policyCheck },\n };\n } catch (error) {\n return this.errorResult(error, 'PAYMENT_FAILED', true);\n }\n }\n\n /**\n * Create an invoice to receive payment\n *\n * @example\n * const invoice = await fiber.createInvoice({\n * amountCkb: 10,\n * description: 'For coffee',\n * expiryMinutes: 60,\n * });\n * console.log(invoice.data?.invoice); // Share this with payer\n */\n async createInvoice(params: {\n /** Amount to receive in CKB */\n amountCkb: number;\n /** Description for the payer */\n description?: string;\n /** Expiry time in minutes (default: 60) */\n expiryMinutes?: number;\n }): Promise<AgentResult<InvoiceResult>> {\n this.ensureInitialized();\n\n try {\n const amountHex = ckbToShannons(params.amountCkb);\n const expirySeconds = (params.expiryMinutes || 60) * 60;\n const preimage = randomBytes32();\n const invoiceParams: Parameters<FiberRpcClient['newInvoice']>[0] = {\n amount: amountHex,\n currency: this.config.chain === 'mainnet' ? 'Fibb' : 'Fibt',\n description: params.description,\n expiry: toHex(expirySeconds),\n payment_preimage: preimage,\n };\n\n let invoiceAddress: string;\n let paymentHash: string;\n\n if (this.runtimeJobManager) {\n const job = await this.runtimeJobManager.manageInvoice({\n action: 'create',\n newInvoiceParams: invoiceParams,\n waitForTerminal: false,\n });\n const terminal = await this.waitForRuntimeJobTerminal(job.id, 120_000);\n if (\n terminal.type !== 'invoice' ||\n terminal.state !== 'succeeded' ||\n !terminal.result?.invoiceAddress ||\n !terminal.result.paymentHash\n ) {\n throw new Error(terminal.error?.message ?? 'Runtime invoice job failed');\n }\n invoiceAddress = terminal.result.invoiceAddress;\n paymentHash = terminal.result.paymentHash;\n } else {\n const result = await this.getRpc().newInvoice(invoiceParams);\n invoiceAddress = result.invoice_address;\n paymentHash = result.invoice.data.payment_hash;\n }\n\n const expiresAt = new Date(Date.now() + expirySeconds * 1000).toISOString();\n\n const invoiceResult: InvoiceResult = {\n invoice: invoiceAddress,\n paymentHash,\n amountCkb: params.amountCkb,\n expiresAt,\n status: 'open',\n };\n\n this.policy.addAuditEntry('INVOICE_CREATED', true, { ...invoiceResult });\n\n return {\n success: true,\n data: invoiceResult,\n metadata: { timestamp: Date.now() },\n };\n } catch (error) {\n return this.errorResult(error, 'INVOICE_FAILED', true);\n }\n }\n\n /**\n * Get current balance information\n */\n async getBalance(): Promise<AgentResult<BalanceInfo>> {\n this.ensureInitialized();\n\n try {\n const channels = await this.getRpc().listChannels({});\n\n let totalLocal = 0n;\n let totalRemote = 0n;\n let activeChannels = 0;\n\n for (const channel of channels.channels) {\n if (channel.state.state_name === ChannelState.ChannelReady) {\n totalLocal += fromHex(channel.local_balance);\n totalRemote += fromHex(channel.remote_balance);\n activeChannels++;\n }\n }\n\n const allowance = this.policy.getRemainingAllowance();\n\n return {\n success: true,\n data: {\n totalCkb: Number(totalLocal) / 1e8,\n availableToSend: Number(totalLocal) / 1e8,\n availableToReceive: Number(totalRemote) / 1e8,\n channelCount: activeChannels,\n spendingAllowance: Number(allowance.perWindow) / 1e8,\n },\n metadata: { timestamp: Date.now() },\n };\n } catch (error) {\n return this.errorResult(error, 'BALANCE_FAILED', true);\n }\n }\n\n /**\n * Check payment status\n */\n async getPaymentStatus(paymentHash: string): Promise<AgentResult<PaymentResult>> {\n this.ensureInitialized();\n\n try {\n const result = await this.getRpc().getPayment({ payment_hash: paymentHash as HexString });\n\n return {\n success: true,\n data: {\n paymentHash: result.payment_hash,\n status:\n result.status === 'Success'\n ? 'success'\n : result.status === 'Failed'\n ? 'failed'\n : 'pending',\n amountCkb: 0, // Amount not returned from get_payment\n feeCkb: shannonsToCkb(result.fee),\n failureReason: result.failed_error,\n },\n metadata: { timestamp: Date.now() },\n };\n } catch (error) {\n return this.errorResult(error, 'STATUS_CHECK_FAILED', true);\n }\n }\n\n /**\n * Check invoice status\n */\n async getInvoiceStatus(paymentHash: string): Promise<AgentResult<InvoiceResult>> {\n this.ensureInitialized();\n\n try {\n const result = await this.getRpc().getInvoice({ payment_hash: paymentHash as HexString });\n\n const amountCkb = result.invoice.amount ? shannonsToCkb(result.invoice.amount) : 0;\n const expiresAt = this.getInvoiceExpiryIso(result.invoice);\n\n return {\n success: true,\n data: {\n invoice: result.invoice_address,\n paymentHash: result.invoice.data.payment_hash,\n amountCkb,\n expiresAt,\n status: this.mapInvoiceStatus(result.status),\n },\n metadata: { timestamp: Date.now() },\n };\n } catch (error) {\n return this.errorResult(error, 'INVOICE_STATUS_FAILED', true);\n }\n }\n\n // ===========================================================================\n // Channel Management\n // ===========================================================================\n\n /**\n * List all channels\n */\n async listChannels(): Promise<AgentResult<ChannelSummary[]>> {\n this.ensureInitialized();\n\n try {\n const result = await this.getRpc().listChannels({});\n\n const channels: ChannelSummary[] = result.channels.map((ch) => ({\n id: ch.channel_id,\n peerId: ch.peer_id,\n localBalanceCkb: shannonsToCkb(ch.local_balance),\n remoteBalanceCkb: shannonsToCkb(ch.remote_balance),\n state: ch.state.state_name,\n isPublic: ch.is_public,\n }));\n\n return {\n success: true,\n data: channels,\n metadata: { timestamp: Date.now() },\n };\n } catch (error) {\n return this.errorResult(error, 'LIST_CHANNELS_FAILED', true);\n }\n }\n\n /**\n * Open a new channel\n */\n async openChannel(params: {\n /** Peer node ID or address */\n peer: string;\n /** Funding amount in CKB */\n fundingCkb: number;\n /** Make channel public */\n isPublic?: boolean;\n /**\n * Optional idempotency key for retries.\n * Reuse the same key when retrying the same open intent; use a new key for a distinct open request.\n */\n idempotencyKey?: string;\n }): Promise<AgentResult<{ channelId: string }>> {\n this.ensureInitialized();\n\n try {\n const fundingHex = ckbToShannons(params.fundingCkb);\n const channels = await this.getRpc().listChannels({});\n\n // Check policy\n const policyCheck = this.policy.checkChannelOperation({\n operation: 'open',\n fundingAmount: fundingHex,\n currentChannelCount: channels.channels.length,\n });\n\n if (!policyCheck.allowed) {\n this.policy.addAuditEntry('POLICY_VIOLATION', false, params, policyCheck.violations);\n return {\n success: false,\n error: {\n code: 'POLICY_VIOLATION',\n message: policyCheck.violations.map((v) => v.message).join('; '),\n recoverable: false,\n },\n metadata: { timestamp: Date.now(), policyCheck },\n };\n }\n\n // Connect to peer if address provided\n if (params.peer.includes('/')) {\n await this.getRpc().connectPeer({ address: params.peer });\n // Extract peer ID from multiaddr\n const peerIdMatch = params.peer.match(/\\/p2p\\/([^/]+)/);\n if (peerIdMatch) {\n params.peer = peerIdMatch[1];\n }\n }\n\n const openParams = {\n peer_id: params.peer,\n funding_amount: fundingHex,\n public: params.isPublic ?? true,\n };\n const idempotencyKey = params.idempotencyKey ?? `open:${openParams.peer_id}:${randomUUID()}`;\n\n let temporaryChannelId: string;\n if (this.runtimeJobManager) {\n const job = await this.runtimeJobManager.manageChannel(\n {\n action: 'open',\n openChannelParams: openParams,\n waitForReady: false,\n peerId: params.peer,\n },\n { idempotencyKey },\n );\n const terminal = await this.waitForRuntimeJobTerminal(job.id, 120_000);\n if (\n terminal.type !== 'channel' ||\n terminal.state !== 'succeeded' ||\n !terminal.result?.temporaryChannelId\n ) {\n throw new Error(terminal.error?.message ?? 'Runtime channel open job failed');\n }\n temporaryChannelId = terminal.result.temporaryChannelId;\n } else {\n const result = await this.getRpc().openChannel(openParams);\n temporaryChannelId = result.temporary_channel_id;\n }\n\n this.policy.addAuditEntry('CHANNEL_OPENED', true, {\n channelId: temporaryChannelId,\n peer: params.peer,\n fundingCkb: params.fundingCkb,\n });\n\n return {\n success: true,\n data: { channelId: temporaryChannelId },\n metadata: { timestamp: Date.now(), policyCheck },\n };\n } catch (error) {\n return this.errorResult(error, 'OPEN_CHANNEL_FAILED', true);\n }\n }\n\n /**\n * Close a channel\n */\n async closeChannel(params: {\n /** Channel ID */\n channelId: string;\n /** Force close (unilateral) */\n force?: boolean;\n }): Promise<AgentResult<void>> {\n this.ensureInitialized();\n\n try {\n const operation = params.force ? 'force_close' : 'close';\n const policyCheck = this.policy.checkChannelOperation({ operation });\n\n if (!policyCheck.allowed) {\n this.policy.addAuditEntry('POLICY_VIOLATION', false, params, policyCheck.violations);\n return {\n success: false,\n error: {\n code: 'POLICY_VIOLATION',\n message: policyCheck.violations.map((v) => v.message).join('; '),\n recoverable: false,\n },\n metadata: { timestamp: Date.now(), policyCheck },\n };\n }\n\n if (this.runtimeJobManager) {\n const job = await this.runtimeJobManager.manageChannel(\n {\n action: 'shutdown',\n channelId: params.channelId as HexString,\n shutdownChannelParams: {\n channel_id: params.channelId as HexString,\n force: params.force,\n },\n waitForClosed: false,\n },\n { idempotencyKey: `channel:shutdown:${params.channelId}` },\n );\n const terminal = await this.waitForRuntimeJobTerminal(job.id, 120_000);\n if (terminal.type !== 'channel' || terminal.state !== 'succeeded') {\n throw new Error(terminal.error?.message ?? 'Runtime channel close job failed');\n }\n } else {\n await this.getRpc().shutdownChannel({\n channel_id: params.channelId as HexString,\n force: params.force,\n });\n }\n\n this.policy.addAuditEntry('CHANNEL_CLOSED', true, params);\n\n return {\n success: true,\n metadata: { timestamp: Date.now(), policyCheck },\n };\n } catch (error) {\n return this.errorResult(error, 'CLOSE_CHANNEL_FAILED', true);\n }\n }\n\n // ===========================================================================\n // Node Information\n // ===========================================================================\n\n /**\n * Get node information\n */\n async getNodeInfo(): Promise<\n AgentResult<{\n nodeId: string;\n version: string;\n channelCount: number;\n peersCount: number;\n }>\n > {\n this.ensureInitialized();\n\n try {\n const info = await this.getRpc().nodeInfo();\n\n return {\n success: true,\n data: {\n nodeId: info.node_id,\n version: info.version,\n channelCount: parseInt(info.channel_count, 16),\n peersCount: parseInt(info.peers_count, 16),\n },\n metadata: { timestamp: Date.now() },\n };\n } catch (error) {\n return this.errorResult(error, 'NODE_INFO_FAILED', true);\n }\n }\n\n // ===========================================================================\n // Verification & Validation Methods\n // ===========================================================================\n\n /**\n * Validate an invoice before payment\n * Checks format, expiry, amount, cryptographic correctness, and peer connectivity\n *\n * @example\n * ```typescript\n * const validation = await fiber.validateInvoice('fibt1...');\n * if (validation.data?.recommendation === 'reject') {\n * console.log('Do not pay:', validation.data.reason);\n * }\n * ```\n */\n async validateInvoice(invoice: string): Promise<AgentResult<InvoiceValidationResult>> {\n this.ensureInitialized();\n\n try {\n if (!this.invoiceVerifier) {\n throw new Error('Invoice verifier not initialized');\n }\n\n const result = await this.invoiceVerifier.verifyInvoice(invoice);\n\n this.policy.addAuditEntry('INVOICE_VALIDATED', true, {\n paymentHash: result.details.paymentHash,\n amountCkb: result.details.amountCkb,\n valid: result.valid,\n });\n\n return {\n success: true,\n data: result,\n metadata: {\n timestamp: Date.now(),\n },\n };\n } catch (error) {\n return this.errorResult(error, 'INVOICE_VALIDATION_FAILED', true);\n }\n }\n\n /**\n * Get payment proof (cryptographic evidence of payment)\n * Returns stored proof if available, or creates one from RPC status\n */\n async getPaymentProof(paymentHash: string): Promise<\n AgentResult<{\n proof: PaymentProof | null;\n verified: boolean;\n status: string;\n }>\n > {\n this.ensureInitialized();\n\n try {\n if (!this.paymentProofManager) {\n throw new Error('Payment proof manager not initialized');\n }\n\n const storedProof = this.paymentProofManager.getProof(paymentHash);\n\n if (storedProof) {\n const verification = this.paymentProofManager.verifyProof(storedProof);\n await this.paymentProofManager.save();\n\n return {\n success: true,\n data: {\n proof: storedProof,\n verified: verification.valid,\n status: verification.reason,\n },\n metadata: { timestamp: Date.now() },\n };\n }\n\n // Try to fetch from RPC\n const paymentStatus = await this.getRpc().getPayment({\n payment_hash: paymentHash as HexString,\n });\n\n return {\n success: true,\n data: {\n proof: null,\n verified: paymentStatus.status === 'Success',\n status: `Payment status: ${paymentStatus.status}`,\n },\n metadata: { timestamp: Date.now() },\n };\n } catch (error) {\n return this.errorResult(error, 'PROOF_FETCH_FAILED', true);\n }\n }\n\n /**\n * Get payment proof summary for audit trail\n */\n async getPaymentProofSummary(): Promise<AgentResult<PaymentProofSummary>> {\n this.ensureInitialized();\n\n try {\n if (!this.paymentProofManager) {\n throw new Error('Payment proof manager not initialized');\n }\n\n const summary = this.paymentProofManager.getSummary();\n\n return {\n success: true,\n data: summary,\n metadata: { timestamp: Date.now() },\n };\n } catch (error) {\n return this.errorResult(error, 'PROOF_SUMMARY_FAILED', true);\n }\n }\n\n /**\n * Export payment audit report\n */\n async getPaymentAuditReport(options?: {\n startTime?: number;\n endTime?: number;\n }): Promise<AgentResult<string>> {\n this.ensureInitialized();\n\n try {\n if (!this.paymentProofManager) {\n throw new Error('Payment proof manager not initialized');\n }\n\n const report = this.paymentProofManager.exportAuditReport(\n options?.startTime,\n options?.endTime,\n );\n\n return {\n success: true,\n data: report,\n metadata: { timestamp: Date.now() },\n };\n } catch (error) {\n return this.errorResult(error, 'AUDIT_REPORT_FAILED', true);\n }\n }\n\n // ===========================================================================\n // Hold Invoice & Settlement Methods\n // ===========================================================================\n\n /**\n * Create a hold invoice (for escrow / conditional payments)\n * The payer's funds are held until you explicitly settle with the preimage,\n * or cancelled if you don't settle before expiry.\n *\n * @example\n * ```typescript\n * const invoice = await fiber.createHoldInvoice({\n * amountCkb: 10,\n * paymentHash: '0x...', // SHA-256 hash of your secret preimage\n * description: 'Escrow for service',\n * });\n * // Share invoice.data.invoice with the payer\n * // When conditions are met, call settleInvoice() with the preimage\n * ```\n */\n async createHoldInvoice(params: {\n /** Amount to receive in CKB */\n amountCkb: number;\n /** Payment hash (SHA-256 of preimage you control) */\n paymentHash: string;\n /** Description for the payer */\n description?: string;\n /** Expiry time in minutes (default: 60) */\n expiryMinutes?: number;\n }): Promise<AgentResult<HoldInvoiceResult>> {\n this.ensureInitialized();\n\n try {\n const amountHex = ckbToShannons(params.amountCkb);\n const expirySeconds = (params.expiryMinutes || 60) * 60;\n const holdInvoiceParams: Parameters<FiberRpcClient['newInvoice']>[0] = {\n amount: amountHex,\n currency: this.config.chain === 'mainnet' ? 'Fibb' : 'Fibt',\n description: params.description,\n expiry: toHex(expirySeconds),\n payment_hash: params.paymentHash as HexString,\n };\n\n let invoiceAddress: string;\n let paymentHash: string;\n if (this.runtimeJobManager) {\n const job = await this.runtimeJobManager.manageInvoice(\n {\n action: 'create',\n newInvoiceParams: holdInvoiceParams,\n waitForTerminal: false,\n },\n { idempotencyKey: `invoice:create:${params.paymentHash}` },\n );\n const terminal = await this.waitForRuntimeJobTerminal(job.id, 120_000);\n if (\n terminal.type !== 'invoice' ||\n terminal.state !== 'succeeded' ||\n !terminal.result?.invoiceAddress ||\n !terminal.result.paymentHash\n ) {\n throw new Error(terminal.error?.message ?? 'Runtime hold invoice job failed');\n }\n invoiceAddress = terminal.result.invoiceAddress;\n paymentHash = terminal.result.paymentHash;\n } else {\n const result = await this.getRpc().newInvoice(holdInvoiceParams);\n invoiceAddress = result.invoice_address;\n paymentHash = result.invoice.data.payment_hash;\n }\n\n const expiresAt = new Date(Date.now() + expirySeconds * 1000).toISOString();\n\n const invoiceResult: HoldInvoiceResult = {\n invoice: invoiceAddress,\n paymentHash,\n amountCkb: params.amountCkb,\n expiresAt,\n status: 'open',\n };\n\n this.policy.addAuditEntry('HOLD_INVOICE_CREATED', true, { ...invoiceResult });\n\n return {\n success: true,\n data: invoiceResult,\n metadata: { timestamp: Date.now() },\n };\n } catch (error) {\n return this.errorResult(error, 'HOLD_INVOICE_FAILED', true);\n }\n }\n\n /**\n * Settle a hold invoice by revealing the preimage\n * This releases the held funds to you. No policy check needed since\n * settling receives money, it doesn't spend it.\n *\n * @example\n * ```typescript\n * await fiber.settleInvoice({\n * paymentHash: '0x...',\n * preimage: '0x...', // The secret preimage whose hash matches paymentHash\n * });\n * ```\n */\n async settleInvoice(params: {\n /** Payment hash of the hold invoice */\n paymentHash: string;\n /** Preimage that hashes to the payment hash */\n preimage: string;\n }): Promise<AgentResult<void>> {\n this.ensureInitialized();\n\n try {\n if (this.runtimeJobManager) {\n const job = await this.runtimeJobManager.manageInvoice(\n {\n action: 'settle',\n settleInvoiceParams: {\n payment_hash: params.paymentHash as HexString,\n payment_preimage: params.preimage as HexString,\n },\n },\n { idempotencyKey: `invoice:settle:${params.paymentHash}` },\n );\n const terminal = await this.waitForRuntimeJobTerminal(job.id, 120_000);\n if (terminal.type !== 'invoice' || terminal.state !== 'succeeded') {\n throw new Error(terminal.error?.message ?? 'Runtime settle invoice job failed');\n }\n } else {\n await this.getRpc().settleInvoice({\n payment_hash: params.paymentHash as HexString,\n payment_preimage: params.preimage as HexString,\n });\n }\n\n this.policy.addAuditEntry('HOLD_INVOICE_SETTLED', true, {\n paymentHash: params.paymentHash,\n });\n\n return {\n success: true,\n metadata: { timestamp: Date.now() },\n };\n } catch (error) {\n return this.errorResult(error, 'SETTLE_INVOICE_FAILED', true);\n }\n }\n\n // ===========================================================================\n // Waiting / Watching Methods\n // ===========================================================================\n\n /**\n * Wait for a payment to complete (Success or Failed)\n * Wraps the SDK-level polling helper with AgentResult return type.\n */\n async waitForPayment(\n paymentHash: string,\n options?: {\n /** Timeout in ms (default: 120000) */\n timeoutMs?: number;\n },\n ): Promise<AgentResult<PaymentResult>> {\n this.ensureInitialized();\n\n try {\n const result = await this.getRpc().waitForPayment(paymentHash as HexString, {\n timeout: options?.timeoutMs,\n });\n\n return {\n success: result.status === 'Success',\n data: {\n paymentHash: result.payment_hash,\n status:\n result.status === 'Success'\n ? 'success'\n : result.status === 'Failed'\n ? 'failed'\n : 'pending',\n amountCkb: 0, // Amount not returned from get_payment\n feeCkb: shannonsToCkb(result.fee),\n failureReason: result.failed_error,\n },\n metadata: { timestamp: Date.now() },\n };\n } catch (error) {\n return this.errorResult(error, 'WAIT_PAYMENT_FAILED', true);\n }\n }\n\n /**\n * Wait for a channel to become ready (ChannelReady state)\n * Useful after opening a channel — waits for on-chain confirmation.\n */\n async waitForChannelReady(\n channelId: string,\n options?: {\n /** Timeout in ms (default: 300000 = 5 min) */\n timeoutMs?: number;\n },\n ): Promise<AgentResult<ChannelSummary>> {\n this.ensureInitialized();\n\n try {\n const channel = await this.getRpc().waitForChannelReady(channelId as HexString, {\n timeout: options?.timeoutMs,\n });\n\n return {\n success: true,\n data: {\n id: channel.channel_id,\n peerId: channel.peer_id,\n localBalanceCkb: shannonsToCkb(channel.local_balance),\n remoteBalanceCkb: shannonsToCkb(channel.remote_balance),\n state: channel.state.state_name,\n isPublic: channel.is_public,\n },\n metadata: { timestamp: Date.now() },\n };\n } catch (error) {\n return this.errorResult(error, 'WAIT_CHANNEL_FAILED', true);\n }\n }\n\n // ===========================================================================\n // Liquidity & Fund Management Methods\n // ===========================================================================\n\n /**\n * Analyze liquidity across all channels\n * Provides detailed health metrics and recommendations\n *\n * @example\n * ```typescript\n * const analysis = await fiber.analyzeLiquidity();\n * console.log(`Health score: ${analysis.data?.channels.averageHealthScore}`);\n * console.log(analysis.data?.summary);\n * ```\n */\n async analyzeLiquidity(): Promise<AgentResult<LiquidityAnalysisResult>> {\n this.ensureInitialized();\n\n try {\n if (!this.liquidityAnalyzer) {\n throw new Error('Liquidity analyzer not initialized');\n }\n\n const report = await this.liquidityAnalyzer.analyzeLiquidity();\n\n return {\n success: true,\n data: report,\n metadata: { timestamp: Date.now() },\n };\n } catch (error) {\n return this.errorResult(error, 'LIQUIDITY_ANALYSIS_FAILED', true);\n }\n }\n\n /**\n * Check if you have enough liquidity to send a specific amount\n */\n async canSend(amountCkb: number): Promise<\n AgentResult<{\n canSend: boolean;\n shortfallCkb: number;\n availableCkb: number;\n recommendation: string;\n }>\n > {\n this.ensureInitialized();\n\n try {\n if (!this.liquidityAnalyzer) {\n throw new Error('Liquidity analyzer not initialized');\n }\n\n const result = await this.liquidityAnalyzer.getMissingLiquidityForAmount(amountCkb);\n\n const balance = await this.getBalance();\n const availableCkb = balance.data?.availableToSend || 0;\n\n return {\n success: true,\n data: {\n canSend: result.canSend,\n shortfallCkb: result.shortfallCkb,\n availableCkb,\n recommendation: result.recommendation,\n },\n metadata: { timestamp: Date.now() },\n };\n } catch (error) {\n return this.errorResult(error, 'LIQUIDITY_CHECK_FAILED', true);\n }\n }\n\n // ===========================================================================\n // Policy Management\n // ===========================================================================\n\n /**\n * Get remaining spending allowance\n */\n getSpendingAllowance(): { perTransactionCkb: number; perWindowCkb: number } {\n const allowance = this.policy.getRemainingAllowance();\n return {\n perTransactionCkb: Number(allowance.perTransaction) / 1e8,\n perWindowCkb: Number(allowance.perWindow) / 1e8,\n };\n }\n\n /**\n * Get audit log\n */\n getAuditLog(options?: { limit?: number; since?: number }) {\n return this.policy.getAuditLog(options);\n }\n\n // ===========================================================================\n // Private Helpers\n // ===========================================================================\n\n private ensureInitialized(): void {\n if (!this.initialized) {\n throw new Error('FiberPay not initialized. Call initialize() first.');\n }\n }\n\n private getRpc(): FiberRpcClient {\n if (!this.rpc) {\n throw new Error('RPC client not initialized. Call initialize() first.');\n }\n return this.rpc;\n }\n\n private async waitForRuntimeJobTerminal(jobId: string, timeoutMs: number): Promise<RuntimeJob> {\n const startedAt = Date.now();\n while (Date.now() - startedAt < timeoutMs) {\n const job = this.runtimeJobManager?.getJob(jobId);\n if (!job) {\n throw new Error(`Runtime job not found: ${jobId}`);\n }\n if (job.state === 'succeeded' || job.state === 'failed' || job.state === 'cancelled') {\n return job;\n }\n await new Promise((resolve) => setTimeout(resolve, 300));\n }\n throw new Error(`Runtime job ${jobId} timed out after ${timeoutMs}ms`);\n }\n\n /**\n * Map RPC CkbInvoiceStatus to agent-level status string\n */\n private mapInvoiceStatus(\n status: CkbInvoiceStatus,\n ): 'open' | 'accepted' | 'settled' | 'cancelled' {\n switch (status) {\n case 'Open':\n return 'open';\n case 'Received':\n return 'accepted';\n case 'Paid':\n return 'settled';\n case 'Cancelled':\n case 'Expired':\n return 'cancelled';\n default:\n return 'open';\n }\n }\n\n private getInvoiceExpiryIso(invoice: CkbInvoice): string {\n // Spec: InvoiceData.timestamp is seconds since UNIX epoch, ExpiryTime attribute is seconds duration.\n try {\n const createdSeconds = fromHex(invoice.data.timestamp as HexString);\n const expiryDeltaSeconds =\n this.getAttributeU64(invoice.data.attrs, 'ExpiryTime') ?? BigInt(60 * 60);\n return new Date(Number(createdSeconds + expiryDeltaSeconds) * 1000).toISOString();\n } catch {\n return '';\n }\n }\n\n private getAttributeU64(\n attrs: Attribute[],\n key: 'ExpiryTime' | 'FinalHtlcTimeout' | 'FinalHtlcMinimumExpiryDelta',\n ): bigint | undefined {\n for (const attr of attrs) {\n if (key in attr) {\n return fromHex((attr as Record<string, HexString>)[key] as HexString);\n }\n }\n return undefined;\n }\n\n private errorResult<T>(error: unknown, code: string, recoverable: boolean): AgentResult<T> {\n const message = error instanceof Error ? error.message : String(error);\n return {\n success: false,\n error: {\n code,\n message,\n recoverable,\n },\n metadata: { timestamp: Date.now() },\n };\n }\n}\n\n// =============================================================================\n// Factory Function\n// =============================================================================\n\n/**\n * Create a FiberPay instance with sensible defaults\n * Binary will be auto-downloaded if not provided\n */\nexport function createFiberPay(options?: {\n /** Path to the fnn binary (optional - will auto-download if not provided) */\n binaryPath?: string;\n /** Base directory for data */\n dataDir?: string;\n /** Path to the config file (optional - will use built-in testnet config if not provided) */\n configFilePath?: string;\n /** Network: testnet or mainnet */\n network?: 'testnet' | 'mainnet';\n /** Chain: testnet or mainnet (alias for network) */\n chain?: 'testnet' | 'mainnet';\n /** Auto-download binary if not found (default: true) */\n autoDownload?: boolean;\n /** Auto-start the Fiber node on initialize (default: true) */\n autoStart?: boolean;\n /** RPC URL to connect to an existing node (overrides autoStart) */\n rpcUrl?: string;\n /** Key encryption password */\n keyPassword?: string;\n}): FiberPay {\n const dataDir = options?.dataDir || `${process.env.HOME}/.fiber-pay`;\n\n return new FiberPay({\n binaryPath: options?.binaryPath,\n dataDir,\n configFilePath: options?.configFilePath,\n chain: options?.chain || options?.network || 'testnet',\n autoDownload: options?.autoDownload ?? true,\n autoStart: options?.autoStart ?? true,\n rpcUrl: options?.rpcUrl,\n keyPassword: options?.keyPassword,\n });\n}\n\n// Re-export types for MCP tools\nexport type { PaymentProof, PaymentProofSummary } from '@fiber-pay/sdk';\n","/**\n * MCP (Model Context Protocol) Tool Definitions\n * These schemas are compatible with Claude, OpenClaw, and other MCP agents\n */\n\nimport type {\n AgentResult,\n BalanceInfo,\n ChannelSummary,\n HoldInvoiceResult,\n InvoiceResult,\n PaymentResult,\n} from './fiber-pay.js';\n\n// =============================================================================\n// MCP Tool Schema Definitions\n// =============================================================================\n\n/**\n * Tool definitions for MCP integration\n * Each tool has:\n * - name: unique identifier\n * - description: what the tool does (shown to the LLM)\n * - inputSchema: JSON Schema for parameters\n */\nexport const MCP_TOOLS = {\n fiber_pay: {\n name: 'fiber_pay',\n description: `Pay an invoice or send CKB directly to a node on the Lightning Network.\n \nExamples:\n- Pay an invoice: fiber_pay({ invoice: \"fibt1...\" })\n- Send directly: fiber_pay({ recipientNodeId: \"QmXXX...\", amountCkb: 10 })\n\nReturns payment status and tracking hash.`,\n inputSchema: {\n type: 'object',\n properties: {\n invoice: {\n type: 'string',\n description: 'Lightning invoice string to pay (starts with fibt or fibb)',\n },\n recipientNodeId: {\n type: 'string',\n description: 'Recipient node ID for direct payment (keysend)',\n },\n amountCkb: {\n type: 'number',\n description: 'Amount to send in CKB (required for keysend)',\n },\n maxFeeCkb: {\n type: 'number',\n description: 'Maximum fee willing to pay in CKB',\n },\n },\n oneOf: [{ required: ['invoice'] }, { required: ['recipientNodeId', 'amountCkb'] }],\n },\n },\n\n fiber_create_invoice: {\n name: 'fiber_create_invoice',\n description: `Create an invoice to receive payment.\n \nExample: fiber_create_invoice({ amountCkb: 10, description: \"For coffee\" })\n\nReturns invoice string to share with payer.`,\n inputSchema: {\n type: 'object',\n properties: {\n amountCkb: {\n type: 'number',\n description: 'Amount to receive in CKB',\n },\n description: {\n type: 'string',\n description: 'Description for the payer',\n },\n expiryMinutes: {\n type: 'number',\n description: 'Invoice expiry time in minutes (default: 60)',\n },\n },\n required: ['amountCkb'],\n },\n },\n\n fiber_get_balance: {\n name: 'fiber_get_balance',\n description: `Get current balance information including:\n- Total balance in CKB\n- Available to send\n- Available to receive\n- Number of channels\n- Remaining spending allowance\n\nNo parameters required.`,\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n\n fiber_get_payment_status: {\n name: 'fiber_get_payment_status',\n description: `Check the status of a payment by its hash.\n \nExample: fiber_get_payment_status({ paymentHash: \"0x...\" })`,\n inputSchema: {\n type: 'object',\n properties: {\n paymentHash: {\n type: 'string',\n description: 'Payment hash to check',\n },\n },\n required: ['paymentHash'],\n },\n },\n\n fiber_get_invoice_status: {\n name: 'fiber_get_invoice_status',\n description: `Check the status of an invoice (whether it's been paid).\n \nExample: fiber_get_invoice_status({ paymentHash: \"0x...\" })`,\n inputSchema: {\n type: 'object',\n properties: {\n paymentHash: {\n type: 'string',\n description: 'Payment hash of the invoice',\n },\n },\n required: ['paymentHash'],\n },\n },\n\n fiber_list_channels: {\n name: 'fiber_list_channels',\n description: `List all payment channels with their balances and states.\n\nNo parameters required.`,\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n\n fiber_open_channel: {\n name: 'fiber_open_channel',\n description: `Open a new payment channel with a peer.\n \nExample: fiber_open_channel({ \n peer: \"/ip4/x.x.x.x/tcp/8228/p2p/QmXXX...\", \n fundingCkb: 100 \n})\n\nNote: This requires on-chain CKB for funding.`,\n inputSchema: {\n type: 'object',\n properties: {\n peer: {\n type: 'string',\n description: 'Peer multiaddr or node ID',\n },\n fundingCkb: {\n type: 'number',\n description: 'Amount of CKB to fund the channel',\n },\n isPublic: {\n type: 'boolean',\n description: 'Whether to make the channel public (default: true)',\n },\n },\n required: ['peer', 'fundingCkb'],\n },\n },\n\n fiber_close_channel: {\n name: 'fiber_close_channel',\n description: `Close a payment channel and settle funds on-chain.\n \nExample: fiber_close_channel({ channelId: \"0x...\" })\n\nUse force: true only if peer is unresponsive.`,\n inputSchema: {\n type: 'object',\n properties: {\n channelId: {\n type: 'string',\n description: 'Channel ID to close',\n },\n force: {\n type: 'boolean',\n description: 'Force close (unilateral, use only if peer unresponsive)',\n },\n },\n required: ['channelId'],\n },\n },\n\n fiber_get_node_info: {\n name: 'fiber_get_node_info',\n description: `Get information about this node including node ID, public key, and statistics.\n\nNo parameters required.`,\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n\n fiber_get_spending_allowance: {\n name: 'fiber_get_spending_allowance',\n description: `Get remaining spending allowance based on security policy.\n\nReturns:\n- Per-transaction limit in CKB\n- Remaining allowance for current time window\n\nNo parameters required.`,\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n\n fiber_download_binary: {\n name: 'fiber_download_binary',\n description: `Download and install the Fiber Network Node (fnn) binary for the current platform.\n\nThis is required before using any Fiber payment features. The binary will be automatically \ndownloaded from GitHub releases and installed to the data directory.\n\nExamples:\n- Download latest: fiber_download_binary({})\n- Download specific version: fiber_download_binary({ version: \"v0.4.0\" })\n- Force re-download: fiber_download_binary({ force: true })\n\nReturns the path to the installed binary.`,\n inputSchema: {\n type: 'object',\n properties: {\n version: {\n type: 'string',\n description: 'Specific version to download (e.g., \"v0.4.0\"). Defaults to latest.',\n },\n force: {\n type: 'boolean',\n description: 'Force re-download even if binary already exists',\n },\n },\n },\n },\n\n fiber_validate_invoice: {\n name: 'fiber_validate_invoice',\n description: `Validate an invoice before payment. Checks format, cryptographic correctness, expiry, \namount, and peer connectivity. Returns recommendation to proceed, warn, or reject.\n\nUse this BEFORE paying an invoice to ensure safety.\n\nExample: fiber_validate_invoice({ invoice: \"fibt1...\" })\n\nReturns:\n- valid: boolean (overall validity)\n- details: parsed invoice details (amount, expiry, payment hash)\n- checks: individual validation results (format, expiry, amount, preimage, peer)\n- issues: list of warnings and critical issues found\n- recommendation: 'proceed' | 'warn' | 'reject'\n- reason: human-readable recommendation reason`,\n inputSchema: {\n type: 'object',\n properties: {\n invoice: {\n type: 'string',\n description: 'Invoice string to validate (starts with fibt or fibb)',\n },\n },\n required: ['invoice'],\n },\n },\n\n fiber_get_payment_proof: {\n name: 'fiber_get_payment_proof',\n description: `Get cryptographic proof of payment execution. Useful for audit trail and reconciliation.\n\nExample: fiber_get_payment_proof({ paymentHash: \"0x...\" })\n\nReturns stored payment proof including:\n- Invoice original\n- Preimage (if available)\n- Fee breakdown\n- Verification status\n- Proof metadata`,\n inputSchema: {\n type: 'object',\n properties: {\n paymentHash: {\n type: 'string',\n description: 'Payment hash to retrieve proof for',\n },\n },\n required: ['paymentHash'],\n },\n },\n\n fiber_analyze_liquidity: {\n name: 'fiber_analyze_liquidity',\n description: `Comprehensive liquidity analysis across all channels. Provides health metrics,\nidentifies issues, and generates recommendations for rebalancing and funding.\n\nUse this to:\n- Understand current channel health\n- Identify liquidity gaps\n- Get rebalancing recommendations\n- Estimate available runway\n\nNo parameters required.\n\nReturns:\n- balance: total, available to send/receive\n- channels: health metrics for each channel\n- liquidity: gaps and runway estimation\n- recommendations: rebalance suggestions and funding needs\n- summary: human-readable status`,\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n\n fiber_can_send: {\n name: 'fiber_can_send',\n description: `Check if you have enough liquidity to send a specific amount. Returns shortfall \nif insufficient and recommendations.\n\nUse this BEFORE attempting a payment to verify you have enough liquidity.\n\nExample: fiber_can_send({ amountCkb: 100 })\n\nReturns:\n- canSend: boolean\n- shortfallCkb: missing amount (0 if can send)\n- availableCkb: current available balance\n- recommendation: what to do if insufficient`,\n inputSchema: {\n type: 'object',\n properties: {\n amountCkb: {\n type: 'number',\n description: 'Amount in CKB to check',\n },\n },\n required: ['amountCkb'],\n },\n },\n\n fiber_create_hold_invoice: {\n name: 'fiber_create_hold_invoice',\n description: `Create a hold invoice for escrow or conditional payments.\n \nA hold invoice locks the payer's funds until you explicitly settle with the preimage,\nor the invoice expires. This enables escrow patterns without a trusted third party.\n\nExample: fiber_create_hold_invoice({ \n amountCkb: 10, \n paymentHash: \"0x...\", \n description: \"Escrow for service delivery\" \n})\n\nFlow:\n1. Generate a secret preimage and compute its SHA-256 hash\n2. Create hold invoice with the hash\n3. Share invoice with payer — their funds are held when they pay\n4. When conditions are met, call fiber_settle_invoice with the preimage\n5. If conditions are NOT met, let the invoice expire (funds return to payer)\n\nReturns invoice string and payment hash.`,\n inputSchema: {\n type: 'object',\n properties: {\n amountCkb: {\n type: 'number',\n description: 'Amount to receive in CKB',\n },\n paymentHash: {\n type: 'string',\n description: 'SHA-256 hash of your secret preimage (0x-prefixed hex)',\n },\n description: {\n type: 'string',\n description: 'Description for the payer',\n },\n expiryMinutes: {\n type: 'number',\n description: 'Invoice expiry time in minutes (default: 60)',\n },\n },\n required: ['amountCkb', 'paymentHash'],\n },\n },\n\n fiber_settle_invoice: {\n name: 'fiber_settle_invoice',\n description: `Settle a hold invoice by revealing the preimage.\n \nThis releases the held funds to you. Only call this after conditions are met.\nThe preimage must hash (SHA-256) to the payment_hash used when creating the hold invoice.\n\nExample: fiber_settle_invoice({ \n paymentHash: \"0x...\", \n preimage: \"0x...\" \n})`,\n inputSchema: {\n type: 'object',\n properties: {\n paymentHash: {\n type: 'string',\n description: 'Payment hash of the hold invoice',\n },\n preimage: {\n type: 'string',\n description: 'Secret preimage (0x-prefixed hex, 32 bytes)',\n },\n },\n required: ['paymentHash', 'preimage'],\n },\n },\n\n fiber_wait_for_payment: {\n name: 'fiber_wait_for_payment',\n description: `Wait for a payment to complete (reach Success or Failed status).\n \nPolls the payment status until it reaches a terminal state. Useful after sending\na payment to wait for confirmation.\n\nExample: fiber_wait_for_payment({ paymentHash: \"0x...\", timeoutMs: 60000 })\n\nReturns the final payment status.`,\n inputSchema: {\n type: 'object',\n properties: {\n paymentHash: {\n type: 'string',\n description: 'Payment hash to wait for',\n },\n timeoutMs: {\n type: 'number',\n description: 'Timeout in milliseconds (default: 120000 = 2 min)',\n },\n },\n required: ['paymentHash'],\n },\n },\n\n fiber_wait_for_channel_ready: {\n name: 'fiber_wait_for_channel_ready',\n description: `Wait for a channel to become ready after opening.\n \nAfter opening a channel, it takes time for the funding transaction to be confirmed\non-chain. This tool polls until the channel reaches ChannelReady state.\n\nExample: fiber_wait_for_channel_ready({ channelId: \"0x...\", timeoutMs: 300000 })\n\nReturns channel info once ready.`,\n inputSchema: {\n type: 'object',\n properties: {\n channelId: {\n type: 'string',\n description: 'Channel ID to wait for',\n },\n timeoutMs: {\n type: 'number',\n description: 'Timeout in milliseconds (default: 300000 = 5 min)',\n },\n },\n required: ['channelId'],\n },\n },\n} as const;\n\n// =============================================================================\n// Type Helpers\n// =============================================================================\n\nexport type McpToolName = keyof typeof MCP_TOOLS;\ntype EmptyInput = Record<string, never>;\n\nexport type McpToolInput<T extends McpToolName> = T extends 'fiber_pay'\n ? {\n invoice?: string;\n recipientNodeId?: string;\n amountCkb?: number;\n maxFeeCkb?: number;\n customRecords?: Record<string, string>;\n maxParts?: number;\n }\n : T extends 'fiber_create_invoice'\n ? { amountCkb: number; description?: string; expiryMinutes?: number }\n : T extends 'fiber_get_balance'\n ? EmptyInput\n : T extends 'fiber_get_payment_status'\n ? { paymentHash: string }\n : T extends 'fiber_get_invoice_status'\n ? { paymentHash: string }\n : T extends 'fiber_list_channels'\n ? EmptyInput\n : T extends 'fiber_open_channel'\n ? { peer: string; fundingCkb: number; isPublic?: boolean }\n : T extends 'fiber_close_channel'\n ? { channelId: string; force?: boolean }\n : T extends 'fiber_get_node_info'\n ? EmptyInput\n : T extends 'fiber_get_spending_allowance'\n ? EmptyInput\n : T extends 'fiber_download_binary'\n ? { version?: string; force?: boolean }\n : T extends 'fiber_validate_invoice'\n ? { invoice: string }\n : T extends 'fiber_get_payment_proof'\n ? { paymentHash: string }\n : T extends 'fiber_analyze_liquidity'\n ? EmptyInput\n : T extends 'fiber_can_send'\n ? { amountCkb: number }\n : T extends 'fiber_create_hold_invoice'\n ? {\n amountCkb: number;\n paymentHash: string;\n description?: string;\n expiryMinutes?: number;\n }\n : T extends 'fiber_settle_invoice'\n ? { paymentHash: string; preimage: string }\n : T extends 'fiber_wait_for_payment'\n ? { paymentHash: string; timeoutMs?: number }\n : T extends 'fiber_wait_for_channel_ready'\n ? { channelId: string; timeoutMs?: number }\n : never;\n\nexport type McpToolResult<T extends McpToolName> = T extends 'fiber_pay'\n ? AgentResult<PaymentResult>\n : T extends 'fiber_create_invoice'\n ? AgentResult<InvoiceResult>\n : T extends 'fiber_get_balance'\n ? AgentResult<BalanceInfo>\n : T extends 'fiber_get_payment_status'\n ? AgentResult<PaymentResult>\n : T extends 'fiber_get_invoice_status'\n ? AgentResult<InvoiceResult>\n : T extends 'fiber_list_channels'\n ? AgentResult<ChannelSummary[]>\n : T extends 'fiber_open_channel'\n ? AgentResult<{ channelId: string }>\n : T extends 'fiber_close_channel'\n ? AgentResult<void>\n : T extends 'fiber_get_node_info'\n ? AgentResult<{\n nodeId: string;\n publicKey: string;\n version: string;\n channelCount: number;\n peersCount: number;\n }>\n : T extends 'fiber_get_spending_allowance'\n ? { perTransactionCkb: number; perWindowCkb: number }\n : T extends 'fiber_download_binary'\n ? AgentResult<{\n path: string;\n version: string;\n platform: string;\n arch: string;\n }>\n : T extends 'fiber_validate_invoice'\n ? AgentResult<import('./fiber-pay.js').InvoiceValidationResult>\n : T extends 'fiber_get_payment_proof'\n ? AgentResult<{\n proof: import('./fiber-pay.js').PaymentProof | null;\n verified: boolean;\n status: string;\n }>\n : T extends 'fiber_analyze_liquidity'\n ? AgentResult<import('./fiber-pay.js').LiquidityAnalysisResult>\n : T extends 'fiber_can_send'\n ? AgentResult<{\n canSend: boolean;\n shortfallCkb: number;\n availableCkb: number;\n recommendation: string;\n }>\n : T extends 'fiber_create_hold_invoice'\n ? AgentResult<HoldInvoiceResult>\n : T extends 'fiber_settle_invoice'\n ? AgentResult<void>\n : T extends 'fiber_wait_for_payment'\n ? AgentResult<PaymentResult>\n : T extends 'fiber_wait_for_channel_ready'\n ? AgentResult<ChannelSummary>\n : never;\n"],"mappings":"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","names":[]}