@fiber-pay/sdk 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.
- package/README.md +20 -0
- package/dist/browser.d.ts +895 -0
- package/dist/browser.js +29 -0
- package/dist/browser.js.map +1 -0
- package/dist/chunk-QQDMPGVR.js +723 -0
- package/dist/chunk-QQDMPGVR.js.map +1 -0
- package/dist/index.d.ts +492 -0
- package/dist/index.js +1336 -0
- package/dist/index.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/address.ts","../src/types/rpc.ts","../src/types/policy.ts","../src/utils.ts","../src/rpc/client.ts"],"sourcesContent":["/**\n * CKB Address Encoding (Bech32m)\n * Encode CKB lock scripts to human-readable addresses\n */\n\n// Bech32m charset\nconst BECH32_CHARSET = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l';\n\nfunction bech32mPolymod(values: number[]): number {\n const GEN = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];\n let chk = 1;\n for (const v of values) {\n const top = chk >> 25;\n chk = ((chk & 0x1ffffff) << 5) ^ v;\n for (let i = 0; i < 5; i++) {\n if ((top >> i) & 1) {\n chk ^= GEN[i];\n }\n }\n }\n return chk;\n}\n\nfunction bech32mHrpExpand(hrp: string): number[] {\n const ret: number[] = [];\n for (let i = 0; i < hrp.length; i++) {\n ret.push(hrp.charCodeAt(i) >> 5);\n }\n ret.push(0);\n for (let i = 0; i < hrp.length; i++) {\n ret.push(hrp.charCodeAt(i) & 31);\n }\n return ret;\n}\n\nfunction bech32mCreateChecksum(hrp: string, data: number[]): number[] {\n const values = bech32mHrpExpand(hrp).concat(data).concat([0, 0, 0, 0, 0, 0]);\n const polymod = bech32mPolymod(values) ^ 0x2bc830a3; // Bech32m constant\n const ret: number[] = [];\n for (let i = 0; i < 6; i++) {\n ret.push((polymod >> (5 * (5 - i))) & 31);\n }\n return ret;\n}\n\nfunction convertBits(data: Uint8Array, fromBits: number, toBits: number, pad: boolean): number[] {\n let acc = 0;\n let bits = 0;\n const ret: number[] = [];\n const maxv = (1 << toBits) - 1;\n\n for (const value of data) {\n acc = (acc << fromBits) | value;\n bits += fromBits;\n while (bits >= toBits) {\n bits -= toBits;\n ret.push((acc >> bits) & maxv);\n }\n }\n\n if (pad && bits > 0) {\n ret.push((acc << (toBits - bits)) & maxv);\n }\n\n return ret;\n}\n\nfunction bech32mEncode(hrp: string, data: number[]): string {\n const checksum = bech32mCreateChecksum(hrp, data);\n const combined = data.concat(checksum);\n let result = `${hrp}1`;\n for (const d of combined) {\n result += BECH32_CHARSET[d];\n }\n return result;\n}\n\nexport interface Script {\n code_hash: string;\n hash_type: 'type' | 'data' | 'data1' | 'data2';\n args: string;\n}\n\n/**\n * Convert a CKB lock script to a bech32m-encoded address\n * @param script - The lock script to encode\n * @param network - The CKB network ('testnet' or 'mainnet')\n * @returns Bech32m-encoded CKB address\n */\nexport function scriptToAddress(script: Script, network: 'testnet' | 'mainnet'): string {\n const hrp = network === 'mainnet' ? 'ckb' : 'ckt';\n\n // CKB full address format (2021)\n // Format: 0x00 | code_hash | hash_type | args\n const hashTypeByte =\n script.hash_type === 'type'\n ? 0x01\n : script.hash_type === 'data'\n ? 0x00\n : script.hash_type === 'data1'\n ? 0x02\n : 0x04; // data2\n\n const codeHash = script.code_hash.startsWith('0x') ? script.code_hash.slice(2) : script.code_hash;\n const args = script.args.startsWith('0x') ? script.args.slice(2) : script.args;\n\n // Construct the payload: format_type(0x00) + code_hash(32) + hash_type(1) + args\n const payload = new Uint8Array(1 + 32 + 1 + args.length / 2);\n payload[0] = 0x00; // Full format type\n\n // code_hash\n for (let i = 0; i < 32; i++) {\n payload[1 + i] = parseInt(codeHash.slice(i * 2, i * 2 + 2), 16);\n }\n\n // hash_type\n payload[33] = hashTypeByte;\n\n // args\n for (let i = 0; i < args.length / 2; i++) {\n payload[34 + i] = parseInt(args.slice(i * 2, i * 2 + 2), 16);\n }\n\n // Convert to 5-bit groups and encode with bech32m\n const data = convertBits(payload, 8, 5, true);\n return bech32mEncode(hrp, data);\n}\n","/**\n * Fiber Network Node RPC Types (Fiber v0.6.1)\n *\n * The types in this file are intended to align with the upstream RPC spec:\n * https://github.com/nervosnetwork/fiber/blob/v0.6.1/crates/fiber-lib/src/rpc/README.md\n */\n\n// =============================================================================\n// Common Types\n// =============================================================================\n\n/** Hex-encoded string (prefixed with 0x). The RPC serializes most numeric values as hex strings. */\nexport type HexString = `0x${string}`;\n\n/** A 256-bit hash digest (Hash256 in the RPC spec). */\nexport type Hash256 = HexString;\n\n/** Public key for a node (Pubkey in the RPC spec). */\nexport type Pubkey = HexString;\n\n/** Private key (Privkey in the RPC spec). */\nexport type Privkey = HexString;\n\n/** Peer ID in libp2p format. */\nexport type PeerId = string;\n\n/** Multiaddr format for network addresses. */\nexport type Multiaddr = string;\n\n/** Channel ID (Hash256). */\nexport type ChannelId = Hash256;\n\n/** Payment hash (Hash256). */\nexport type PaymentHash = Hash256;\n\n/** Script structure for CKB. */\nexport interface Script {\n code_hash: HexString;\n hash_type: 'type' | 'data' | 'data1' | 'data2';\n args: HexString;\n}\n\n/** Transaction out point. */\nexport interface OutPoint {\n tx_hash: Hash256;\n index: HexString;\n}\n\n/** UDT (User Defined Token) script (UdtScript in the RPC spec). */\nexport type UdtScript = Script;\n\n// =============================================================================\n// Invoice Types\n// =============================================================================\n\nexport type Currency = 'Fibb' | 'Fibt' | 'Fibd';\n\nexport type HashAlgorithm = 'CkbHash' | 'Sha256';\n\n/** Recoverable signature (InvoiceSignature in the RPC spec). */\nexport type InvoiceSignature = HexString;\n\n/**\n * Invoice attribute types as returned by the RPC.\n * Each attribute is an object with a single key indicating the attribute type.\n */\nexport type Attribute =\n /** Deprecated since v0.6.0, preserved for compatibility. */\n | { FinalHtlcTimeout: HexString }\n /** Final TLC minimum expiry delta in milliseconds. */\n | { FinalHtlcMinimumExpiryDelta: HexString }\n /** Invoice expiry time in seconds. */\n | { ExpiryTime: HexString }\n /** Human-readable invoice description. */\n | { Description: string }\n /** Fallback address for on-chain settlement. */\n | { FallbackAddr: string }\n /** UDT script for token invoices. */\n | { UdtScript: UdtScript }\n /** Payee public key. */\n | { PayeePublicKey: Pubkey }\n /** Hash algorithm used in the payment hash lock. */\n | { HashAlgorithm: HashAlgorithm }\n /** Feature flags list. */\n | { Feature: string[] }\n /** Payment secret. */\n | { PaymentSecret: Hash256 };\n\nexport interface InvoiceData {\n timestamp: HexString;\n payment_hash: PaymentHash;\n attrs: Attribute[];\n}\n\nexport interface CkbInvoice {\n currency: Currency;\n amount?: HexString;\n signature?: InvoiceSignature;\n data: InvoiceData;\n}\n\nexport type CkbInvoiceStatus = 'Open' | 'Cancelled' | 'Expired' | 'Received' | 'Paid';\n\n// =============================================================================\n// Channel Types\n// =============================================================================\n\nexport enum ChannelState {\n NegotiatingFunding = 'NEGOTIATING_FUNDING',\n CollaboratingFundingTx = 'COLLABORATING_FUNDING_TX',\n SigningCommitment = 'SIGNING_COMMITMENT',\n AwaitingTxSignatures = 'AWAITING_TX_SIGNATURES',\n AwaitingChannelReady = 'AWAITING_CHANNEL_READY',\n ChannelReady = 'CHANNEL_READY',\n ShuttingDown = 'SHUTTING_DOWN',\n Closed = 'CLOSED',\n}\n\n/** Channel state flags are serialized as flag names by upstream RPC and may evolve. */\nexport type ChannelStateFlags = string[];\n\n/** TLC status. The upstream spec defines OutboundTlcStatus / InboundTlcStatus, which may evolve. */\nexport type TlcStatus = { Outbound: unknown } | { Inbound: unknown };\n\nexport interface Htlc {\n id: HexString;\n amount: HexString;\n payment_hash: PaymentHash;\n expiry: HexString;\n forwarding_channel_id?: Hash256;\n forwarding_tlc_id?: HexString;\n status: TlcStatus;\n}\n\nexport interface Channel {\n channel_id: ChannelId;\n is_public: boolean;\n channel_outpoint: OutPoint | null;\n peer_id: PeerId;\n funding_udt_type_script: Script | null;\n state: {\n state_name: ChannelState;\n state_flags?: ChannelStateFlags;\n };\n local_balance: HexString;\n offered_tlc_balance: HexString;\n remote_balance: HexString;\n received_tlc_balance: HexString;\n pending_tlcs: Htlc[];\n latest_commitment_transaction_hash: Hash256 | null;\n created_at: HexString;\n enabled: boolean;\n tlc_expiry_delta: HexString;\n tlc_fee_proportional_millionths: HexString;\n shutdown_transaction_hash: Hash256 | null;\n}\n\n// =============================================================================\n// Peer Types\n// =============================================================================\n\nexport interface PeerInfo {\n pubkey: Pubkey;\n peer_id: PeerId;\n address: Multiaddr;\n}\n\n// =============================================================================\n// Payment Types\n// =============================================================================\n\nexport type PaymentStatus = 'Created' | 'Inflight' | 'Success' | 'Failed';\n\n/**\n * Custom records for payments.\n *\n * Keys are hex-encoded u32 values (e.g. `0x1`, range 0..=65535),\n * values are hex-encoded byte arrays (0x-prefixed).\n */\nexport type PaymentCustomRecords = Record<string, HexString>;\n\nexport interface SessionRouteNode {\n pubkey: Pubkey;\n amount: HexString;\n channel_outpoint: OutPoint;\n}\n\nexport interface SessionRoute {\n nodes: SessionRouteNode[];\n}\n\nexport interface PaymentInfo {\n payment_hash: PaymentHash;\n status: PaymentStatus;\n created_at: HexString;\n last_updated_at: HexString;\n failed_error?: string;\n fee: HexString;\n custom_records?: PaymentCustomRecords;\n routers?: SessionRoute[];\n}\n\nexport interface HopHint {\n pubkey: Pubkey;\n channel_outpoint: OutPoint;\n fee_rate: HexString;\n tlc_expiry_delta: HexString;\n}\n\n// =============================================================================\n// Node / UDT Types\n// =============================================================================\n\nexport interface UdtCellDep {\n out_point: OutPoint;\n dep_type: 'code' | 'dep_group';\n}\n\nexport interface UdtDep {\n cell_dep?: UdtCellDep | null;\n type_id?: Script | null;\n}\n\nexport interface UdtArgInfo {\n name: string;\n script: UdtScript;\n auto_accept_amount?: HexString;\n cell_deps: UdtDep[];\n}\n\nexport type UdtCfgInfos = UdtArgInfo[];\n\nexport interface NodeInfo {\n version: string;\n commit_hash: string;\n node_id: Pubkey;\n features: string[];\n node_name: string | null;\n addresses: Multiaddr[];\n chain_hash: Hash256;\n open_channel_auto_accept_min_ckb_funding_amount: HexString;\n auto_accept_channel_ckb_funding_amount: HexString;\n default_funding_lock_script: Script;\n tlc_expiry_delta: HexString;\n tlc_min_value: HexString;\n tlc_fee_proportional_millionths: HexString;\n channel_count: HexString;\n pending_channel_count: HexString;\n peers_count: HexString;\n udt_cfg_infos: UdtCfgInfos;\n}\n\n// =============================================================================\n// Graph Types\n// =============================================================================\n\nexport interface ChannelUpdateInfo {\n timestamp: HexString;\n enabled: boolean;\n outbound_liquidity?: HexString;\n tlc_expiry_delta: HexString;\n tlc_minimum_value: HexString;\n fee_rate: HexString;\n}\n\nexport interface GraphNodeInfo {\n node_name: string;\n version: string;\n addresses: Multiaddr[];\n features: string[];\n node_id: Pubkey;\n timestamp: HexString;\n chain_hash: Hash256;\n auto_accept_min_ckb_funding_amount: HexString;\n udt_cfg_infos: UdtCfgInfos;\n}\n\nexport interface GraphChannelInfo {\n channel_outpoint: OutPoint;\n node1: Pubkey;\n node2: Pubkey;\n created_timestamp: HexString;\n update_info_of_node1?: ChannelUpdateInfo | null;\n update_info_of_node2?: ChannelUpdateInfo | null;\n capacity: HexString;\n chain_hash: Hash256;\n udt_type_script?: Script | null;\n}\n\n// =============================================================================\n// RPC Request/Response Types\n// =============================================================================\n\n// --- Peer Module ---\n\nexport interface ConnectPeerParams {\n address: Multiaddr;\n save?: boolean;\n}\n\n/** connect_peer returns None in v0.6.1 */\nexport type ConnectPeerResult = null;\n\nexport interface DisconnectPeerParams {\n peer_id: PeerId;\n}\n\nexport interface ListPeersResult {\n peers: PeerInfo[];\n}\n\n// --- Channel Module ---\n\nexport interface OpenChannelParams {\n peer_id: PeerId;\n funding_amount: HexString;\n public?: boolean;\n funding_udt_type_script?: Script;\n shutdown_script?: Script;\n commitment_delay_epoch?: HexString;\n commitment_fee_rate?: HexString;\n funding_fee_rate?: HexString;\n tlc_expiry_delta?: HexString;\n tlc_min_value?: HexString;\n tlc_fee_proportional_millionths?: HexString;\n max_tlc_value_in_flight?: HexString;\n max_tlc_number_in_flight?: HexString;\n}\n\nexport interface OpenChannelResult {\n temporary_channel_id: ChannelId;\n}\n\nexport interface AcceptChannelParams {\n temporary_channel_id: ChannelId;\n funding_amount: HexString;\n shutdown_script?: Script;\n max_tlc_value_in_flight?: HexString;\n max_tlc_number_in_flight?: HexString;\n tlc_min_value?: HexString;\n tlc_fee_proportional_millionths?: HexString;\n tlc_expiry_delta?: HexString;\n}\n\nexport interface AcceptChannelResult {\n channel_id: ChannelId;\n}\n\nexport interface ListChannelsParams {\n peer_id?: PeerId;\n include_closed?: boolean;\n}\n\nexport interface ListChannelsResult {\n channels: Channel[];\n}\n\nexport interface ShutdownChannelParams {\n channel_id: ChannelId;\n close_script?: Script;\n fee_rate?: HexString;\n force?: boolean;\n}\n\nexport interface AbandonChannelParams {\n channel_id: ChannelId;\n}\n\nexport interface UpdateChannelParams {\n channel_id: ChannelId;\n enabled?: boolean;\n tlc_expiry_delta?: HexString;\n tlc_minimum_value?: HexString;\n tlc_fee_proportional_millionths?: HexString;\n}\n\n// --- Payment Module ---\n\nexport interface SendPaymentParams {\n target_pubkey?: Pubkey;\n amount?: HexString;\n payment_hash?: PaymentHash;\n final_tlc_expiry_delta?: HexString;\n tlc_expiry_limit?: HexString;\n invoice?: string;\n timeout?: HexString;\n max_fee_amount?: HexString;\n max_parts?: HexString;\n keysend?: boolean;\n udt_type_script?: Script;\n allow_self_payment?: boolean;\n custom_records?: PaymentCustomRecords;\n hop_hints?: HopHint[];\n dry_run?: boolean;\n}\n\nexport interface SendPaymentResult extends PaymentInfo {}\n\nexport interface GetPaymentParams {\n payment_hash: PaymentHash;\n}\n\nexport interface GetPaymentResult extends PaymentInfo {}\n\n// --- Invoice Module ---\n\nexport interface NewInvoiceParams {\n amount: HexString;\n description?: string;\n currency: Currency;\n payment_preimage?: Hash256;\n payment_hash?: PaymentHash;\n expiry?: HexString;\n fallback_address?: string;\n final_expiry_delta?: HexString;\n udt_type_script?: Script;\n hash_algorithm?: HashAlgorithm;\n allow_mpp?: boolean;\n}\n\nexport interface NewInvoiceResult {\n invoice_address: string;\n invoice: CkbInvoice;\n}\n\nexport interface ParseInvoiceParams {\n invoice: string;\n}\n\nexport interface ParseInvoiceResult {\n invoice: CkbInvoice;\n}\n\nexport interface GetInvoiceParams {\n payment_hash: PaymentHash;\n}\n\nexport interface GetInvoiceResult {\n invoice_address: string;\n invoice: CkbInvoice;\n status: CkbInvoiceStatus;\n}\n\nexport interface CancelInvoiceParams {\n payment_hash: PaymentHash;\n}\n\nexport interface CancelInvoiceResult {\n invoice_address: string;\n invoice: CkbInvoice;\n status: CkbInvoiceStatus;\n}\n\nexport interface SettleInvoiceParams {\n payment_hash: PaymentHash;\n payment_preimage: Hash256;\n}\n\n// --- Router Module ---\n\nexport interface HopRequire {\n pubkey: Pubkey;\n channel_outpoint?: OutPoint | null;\n}\n\nexport interface BuildRouterParams {\n amount?: HexString;\n udt_type_script?: Script;\n hops_info: HopRequire[];\n final_tlc_expiry_delta?: HexString;\n}\n\nexport interface RouterHop {\n target: Pubkey;\n channel_outpoint: OutPoint;\n amount_received: HexString;\n incoming_tlc_expiry: HexString;\n}\n\nexport interface BuildRouterResult {\n router_hops: RouterHop[];\n}\n\nexport interface SendPaymentWithRouterParams {\n payment_hash?: PaymentHash;\n router: RouterHop[];\n invoice?: string;\n custom_records?: PaymentCustomRecords;\n keysend?: boolean;\n udt_type_script?: Script;\n dry_run?: boolean;\n}\n\n// --- Graph Module ---\n\nexport interface GraphNodesParams {\n limit?: HexString;\n after?: HexString;\n}\n\nexport interface GraphNodesResult {\n nodes: GraphNodeInfo[];\n last_cursor: HexString;\n}\n\nexport interface GraphChannelsParams {\n limit?: HexString;\n after?: HexString;\n}\n\nexport interface GraphChannelsResult {\n channels: GraphChannelInfo[];\n last_cursor: HexString;\n}\n\n// =============================================================================\n// Additional Upstream RPC Types (for advanced custom call usage)\n// =============================================================================\n\n/** Cross-chain hub invoice variant. */\nexport type CchInvoice = { Fiber: string } | { Lightning: string };\n\n/** Cross-chain hub order status. */\nexport type CchOrderStatus =\n | 'Pending'\n | 'IncomingAccepted'\n | 'OutgoingInFlight'\n | 'OutgoingSettled'\n | 'Succeeded'\n | 'Failed';\n\n/** Reason for removing a TLC in Dev module APIs. */\nexport type RemoveTlcReason = { RemoveTlcFulfill: Hash256 } | { RemoveTlcFail: HexString };\n\n/** TLC id wrapper in watchtower-related types. */\nexport type TLCId = { Offered: HexString } | { Received: HexString };\n\n/** Minimal CKB cell output representation used by watchtower revocation data. */\nexport interface CellOutput {\n capacity: HexString;\n lock: Script;\n type?: Script | null;\n}\n\n/** Settlement TLC data used by watchtower operations. */\nexport interface SettlementTlc {\n tlc_id: TLCId;\n hash_algorithm: HashAlgorithm;\n payment_amount: HexString;\n payment_hash: Hash256;\n expiry: HexString;\n local_key: Privkey;\n remote_key: Pubkey;\n}\n\n/** Settlement data used by watchtower operations. */\nexport interface SettlementData {\n local_amount: HexString;\n remote_amount: HexString;\n tlcs: SettlementTlc[];\n}\n\n/** Revocation data used by watchtower operations. */\nexport interface RevocationData {\n commitment_number: HexString;\n aggregated_signature: HexString;\n output: CellOutput;\n output_data: HexString;\n}\n\n// --- Info Module ---\n\nexport interface NodeInfoResult extends NodeInfo {}\n\n// =============================================================================\n// JSON-RPC Types\n// =============================================================================\n\nexport interface JsonRpcRequest<T = unknown> {\n jsonrpc: '2.0';\n id: number | string;\n method: string;\n params: T[];\n}\n\nexport interface JsonRpcResponse<T = unknown> {\n jsonrpc: '2.0';\n id: number | string;\n result?: T;\n error?: JsonRpcError;\n}\n\nexport interface JsonRpcError {\n code: number;\n message: string;\n data?: unknown;\n}\n","/**\n * Security Policy Types\n * Configuration for AI agent spending limits and guardrails\n */\n\nimport { z } from 'zod';\nimport type { HexString } from './rpc.js';\n\n// =============================================================================\n// Policy Configuration Schema\n// =============================================================================\n\nexport const SpendingLimitSchema = z.object({\n /** Maximum amount per single transaction (in shannons for CKB, or base units for UDT) */\n maxPerTransaction: z.string().regex(/^0x[0-9a-fA-F]+$/),\n /** Maximum total amount per time window */\n maxPerWindow: z.string().regex(/^0x[0-9a-fA-F]+$/),\n /** Time window in seconds */\n windowSeconds: z.number().positive(),\n /** Current spent amount in window (runtime state) */\n currentSpent: z\n .string()\n .regex(/^0x[0-9a-fA-F]+$/)\n .optional(),\n /** Window start timestamp (runtime state) */\n windowStart: z.number().optional(),\n});\n\nexport type SpendingLimit = z.infer<typeof SpendingLimitSchema>;\n\nexport const RecipientPolicySchema = z.object({\n /** Allowlist mode: only allow payments to these recipients */\n allowlist: z.array(z.string()).optional(),\n /** Blocklist mode: block payments to these recipients */\n blocklist: z.array(z.string()).optional(),\n /** Allow payments to unknown recipients (not in allowlist) */\n allowUnknown: z.boolean().default(true),\n});\n\nexport type RecipientPolicy = z.infer<typeof RecipientPolicySchema>;\n\nexport const RateLimitSchema = z.object({\n /** Maximum number of transactions per window */\n maxTransactions: z.number().positive(),\n /** Time window in seconds */\n windowSeconds: z.number().positive(),\n /** Cooldown between transactions in seconds */\n cooldownSeconds: z.number().nonnegative().default(0),\n /** Current transaction count in window (runtime state) */\n currentCount: z.number().optional(),\n /** Window start timestamp (runtime state) */\n windowStart: z.number().optional(),\n /** Last transaction timestamp (runtime state) */\n lastTransaction: z.number().optional(),\n});\n\nexport type RateLimit = z.infer<typeof RateLimitSchema>;\n\nexport const ChannelPolicySchema = z.object({\n /** Allow opening new channels */\n allowOpen: z.boolean().default(true),\n /** Allow closing channels */\n allowClose: z.boolean().default(true),\n /** Allow force close */\n allowForceClose: z.boolean().default(false),\n /** Maximum funding amount for new channels */\n maxFundingAmount: z\n .string()\n .regex(/^0x[0-9a-fA-F]+$/)\n .optional(),\n /** Minimum funding amount for new channels */\n minFundingAmount: z\n .string()\n .regex(/^0x[0-9a-fA-F]+$/)\n .optional(),\n /** Maximum number of channels */\n maxChannels: z.number().positive().optional(),\n});\n\nexport type ChannelPolicy = z.infer<typeof ChannelPolicySchema>;\n\nexport const SecurityPolicySchema = z.object({\n /** Policy name for identification */\n name: z.string(),\n /** Policy version */\n version: z.string().default('1.0.0'),\n /** Whether this policy is active */\n enabled: z.boolean().default(true),\n /** Spending limits configuration */\n spending: SpendingLimitSchema.optional(),\n /** Recipient restrictions */\n recipients: RecipientPolicySchema.optional(),\n /** Rate limiting configuration */\n rateLimit: RateLimitSchema.optional(),\n /** Channel operation policy */\n channels: ChannelPolicySchema.optional(),\n /** Require confirmation for amounts above this threshold */\n confirmationThreshold: z\n .string()\n .regex(/^0x[0-9a-fA-F]+$/)\n .optional(),\n /** Log all transactions to audit log */\n auditLogging: z.boolean().default(true),\n /** Custom metadata */\n metadata: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport type SecurityPolicy = z.infer<typeof SecurityPolicySchema>;\n\n// =============================================================================\n// Policy Violation Types\n// =============================================================================\n\nexport type ViolationType =\n | 'SPENDING_LIMIT_PER_TX'\n | 'SPENDING_LIMIT_PER_WINDOW'\n | 'RATE_LIMIT_EXCEEDED'\n | 'RATE_LIMIT_COOLDOWN'\n | 'RECIPIENT_NOT_ALLOWED'\n | 'RECIPIENT_BLOCKED'\n | 'CHANNEL_OPEN_NOT_ALLOWED'\n | 'CHANNEL_CLOSE_NOT_ALLOWED'\n | 'CHANNEL_FORCE_CLOSE_NOT_ALLOWED'\n | 'CHANNEL_FUNDING_EXCEEDS_MAX'\n | 'CHANNEL_FUNDING_BELOW_MIN'\n | 'MAX_CHANNELS_REACHED'\n | 'REQUIRES_CONFIRMATION';\n\nexport interface PolicyViolation {\n type: ViolationType;\n message: string;\n details: {\n requested?: string;\n limit?: string;\n recipient?: string;\n remaining?: string;\n cooldownRemaining?: number;\n };\n}\n\nexport interface PolicyCheckResult {\n allowed: boolean;\n violations: PolicyViolation[];\n requiresConfirmation: boolean;\n}\n\n// =============================================================================\n// Audit Log Types\n// =============================================================================\n\nexport type AuditAction =\n | 'PAYMENT_SENT'\n | 'PAYMENT_RECEIVED'\n | 'INVOICE_CREATED'\n | 'INVOICE_VALIDATED'\n | 'HOLD_INVOICE_CREATED'\n | 'HOLD_INVOICE_SETTLED'\n | 'CHANNEL_OPENED'\n | 'CHANNEL_CLOSED'\n | 'POLICY_VIOLATION'\n | 'POLICY_UPDATED'\n | 'NODE_STARTED'\n | 'NODE_STOPPED';\n\nexport interface AuditLogEntry {\n timestamp: number;\n action: AuditAction;\n success: boolean;\n details: Record<string, unknown>;\n policyViolations?: PolicyViolation[];\n sessionId?: string;\n agentId?: string;\n}\n\n// =============================================================================\n// Key Management Types\n// =============================================================================\n\nexport interface KeyConfig {\n /** Base directory for key storage */\n baseDir: string;\n /** Password for key encryption (should come from secure source) */\n encryptionPassword?: string;\n /** Whether to generate keys if they don't exist */\n autoGenerate: boolean;\n}\n\nexport interface KeyInfo {\n /** Public key (hex) */\n publicKey: HexString;\n /** Whether the key is encrypted */\n encrypted: boolean;\n /** Key file path */\n path: string;\n /** Key creation timestamp */\n createdAt?: number;\n}\n\n// =============================================================================\n// Session Types (for multi-agent scenarios)\n// =============================================================================\n\nexport interface AgentSession {\n /** Unique session ID */\n sessionId: string;\n /** Agent identifier */\n agentId: string;\n /** Session start time */\n startedAt: number;\n /** Session expiry time */\n expiresAt?: number;\n /** Session-specific policy overrides */\n policyOverrides?: Partial<SecurityPolicy>;\n /** Session metadata */\n metadata?: Record<string, unknown>;\n}\n\n// =============================================================================\n// Default Policy\n// =============================================================================\n\nexport const DEFAULT_SECURITY_POLICY: SecurityPolicy = {\n name: 'default',\n version: '1.0.0',\n enabled: true,\n spending: {\n // 100 CKB per transaction\n maxPerTransaction: '0x2540be400',\n // 1000 CKB per hour\n maxPerWindow: '0x174876e800',\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 * Utility Functions\n * Common utilities for hex conversion, CKB amount calculation, and random generation\n */\n\nimport type { HexString } from './types/index.js';\n\nconst BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';\n\n/**\n * Convert number to hex string\n */\nexport function toHex(value: number | bigint): HexString {\n return `0x${value.toString(16)}`;\n}\n\n/**\n * Convert hex string to bigint\n */\nexport function fromHex(hex: HexString): bigint {\n return BigInt(hex);\n}\n\n/**\n * Convert CKB amount (in CKB units) to shannons (hex)\n */\nexport function ckbToShannons(ckb: number | string): HexString {\n const amount = typeof ckb === 'string' ? parseFloat(ckb) : ckb;\n const shannons = BigInt(Math.floor(amount * 1e8));\n return toHex(shannons);\n}\n\n/**\n * Convert shannons (hex) to CKB amount\n */\nexport function shannonsToCkb(shannons: HexString): number {\n return Number(fromHex(shannons)) / 1e8;\n}\n\n/**\n * Generate a random 32-byte hex string (for payment preimage)\n */\nexport function randomBytes32(): HexString {\n const bytes = new Uint8Array(32);\n crypto.getRandomValues(bytes);\n return `0x${Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')}`;\n}\n\nfunction base58btcEncode(bytes: Uint8Array): string {\n if (bytes.length === 0) return '';\n\n let number = 0n;\n for (const byte of bytes) {\n number = (number << 8n) + BigInt(byte);\n }\n\n let encoded = '';\n while (number > 0n) {\n const remainder = Number(number % 58n);\n encoded = BASE58_ALPHABET[remainder] + encoded;\n number /= 58n;\n }\n\n for (let i = 0; i < bytes.length && bytes[i] === 0; i++) {\n encoded = `1${encoded}`;\n }\n\n return encoded || '1';\n}\n\n/**\n * Convert a Fiber node id (hex-encoded compressed secp256k1 pubkey, 33 bytes)\n * to a libp2p peer id (base58btc encoded sha2-256 multihash).\n */\nexport async function nodeIdToPeerId(nodeId: string): Promise<string> {\n const normalized = nodeId.trim().replace(/^0x/i, '');\n\n if (!/^[0-9a-fA-F]+$/.test(normalized)) {\n throw new Error('Invalid node id: expected hex string');\n }\n if (normalized.length !== 66) {\n throw new Error(\n `Invalid node id: expected 33-byte compressed pubkey, got ${normalized.length / 2} bytes`,\n );\n }\n\n const raw = Uint8Array.from(\n normalized.match(/.{1,2}/g)?.map((byte) => Number.parseInt(byte, 16)) ?? [],\n );\n\n if (raw.length !== 33) {\n throw new Error(`Invalid node id: expected 33-byte compressed pubkey, got ${raw.length} bytes`);\n }\n\n const digestBuffer = await crypto.subtle.digest('SHA-256', raw);\n const digest = new Uint8Array(digestBuffer);\n const multihash = new Uint8Array(2 + digest.length);\n multihash[0] = 0x12;\n multihash[1] = 0x20;\n multihash.set(digest, 2);\n\n return base58btcEncode(multihash);\n}\n\n/**\n * Build a canonical multiaddr by appending/replacing /p2p/<peerId>.\n */\nexport function buildMultiaddr(address: string, peerId: string): string {\n const normalizedAddress = address.trim();\n const normalizedPeerId = peerId.trim();\n\n if (!normalizedAddress.startsWith('/')) {\n throw new Error('Invalid multiaddr: expected address starting with \"/\"');\n }\n if (!normalizedPeerId) {\n throw new Error('Invalid peer id: empty value');\n }\n\n const withoutPeerSuffix = normalizedAddress.replace(/\\/p2p\\/[^/]+$/, '');\n return `${withoutPeerSuffix}/p2p/${normalizedPeerId}`;\n}\n\n/**\n * Build a canonical multiaddr from a node id and base address.\n */\nexport async function buildMultiaddrFromNodeId(address: string, nodeId: string): Promise<string> {\n const peerId = await nodeIdToPeerId(nodeId);\n return buildMultiaddr(address, peerId);\n}\n\n/**\n * Build a best-effort local multiaddr from an RPC URL and peer id.\n * Uses rpcPort + 1 as inferred P2P port when advertised addresses are unavailable.\n */\nexport function buildMultiaddrFromRpcUrl(rpcUrl: string, peerId: string): string {\n let parsed: URL;\n try {\n parsed = new URL(rpcUrl);\n } catch {\n throw new Error(`Invalid RPC URL: ${rpcUrl}`);\n }\n\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n throw new Error(`Unsupported RPC protocol: ${parsed.protocol}`);\n }\n\n const port = parsed.port\n ? Number.parseInt(parsed.port, 10)\n : parsed.protocol === 'https:'\n ? 443\n : 80;\n if (!Number.isFinite(port) || port <= 0 || port > 65535) {\n throw new Error(`Invalid RPC port in URL: ${rpcUrl}`);\n }\n\n const p2pPort = port + 1;\n if (p2pPort > 65535) {\n throw new Error(`Cannot infer P2P port from RPC port ${port}`);\n }\n\n const host = parsed.hostname;\n const isIpv4 = /^\\d{1,3}(?:\\.\\d{1,3}){3}$/.test(host);\n const isIpv6 = host.includes(':');\n const base = isIpv4\n ? `/ip4/${host}/tcp/${p2pPort}`\n : isIpv6\n ? `/ip6/${host}/tcp/${p2pPort}`\n : `/dns/${host}/tcp/${p2pPort}`;\n\n return buildMultiaddr(base, peerId);\n}\n","/**\n * Fiber RPC Client\n * Type-safe JSON-RPC client for Fiber Network Node\n */\n\nimport type {\n AbandonChannelParams,\n AcceptChannelParams,\n AcceptChannelResult,\n // Router methods\n BuildRouterParams,\n BuildRouterResult,\n CancelInvoiceParams,\n CancelInvoiceResult,\n Channel,\n ChannelId,\n CkbInvoiceStatus,\n // Peer methods\n ConnectPeerParams,\n ConnectPeerResult,\n DisconnectPeerParams,\n GetInvoiceParams,\n GetInvoiceResult,\n GetPaymentParams,\n GetPaymentResult,\n GraphChannelsParams,\n GraphChannelsResult,\n // Graph methods\n GraphNodesParams,\n GraphNodesResult,\n JsonRpcError,\n JsonRpcRequest,\n JsonRpcResponse,\n ListChannelsParams,\n ListChannelsResult,\n ListPeersResult,\n // Invoice methods\n NewInvoiceParams,\n NewInvoiceResult,\n // Info methods\n NodeInfoResult,\n // Channel methods\n OpenChannelParams,\n OpenChannelResult,\n ParseInvoiceParams,\n ParseInvoiceResult,\n PaymentHash,\n // Payment methods\n SendPaymentParams,\n SendPaymentResult,\n SendPaymentWithRouterParams,\n SettleInvoiceParams,\n ShutdownChannelParams,\n UpdateChannelParams,\n} from '../types/index.js';\nimport { ChannelState } from '../types/index.js';\n\n// =============================================================================\n// RPC Client Configuration\n// =============================================================================\n\nexport interface RpcClientConfig {\n /** RPC endpoint URL */\n url: string;\n /** Request timeout in milliseconds */\n timeout?: number;\n /** Custom headers */\n headers?: Record<string, string>;\n /**\n * Biscuit token for authentication.\n *\n * Prefer server-side usage. In browser apps, avoid embedding long-lived\n * privileged tokens and use a trusted backend/proxy where possible.\n */\n biscuitToken?: string;\n}\n\n// =============================================================================\n// RPC Error\n// =============================================================================\n\nexport class FiberRpcError extends Error {\n constructor(\n public code: number,\n message: string,\n public data?: unknown,\n ) {\n super(message);\n this.name = 'FiberRpcError';\n }\n\n static fromJsonRpcError(error: JsonRpcError): FiberRpcError {\n return new FiberRpcError(error.code, error.message, error.data);\n }\n}\n\n// =============================================================================\n// RPC Client\n// =============================================================================\n\nexport class FiberRpcClient {\n private requestId = 0;\n private config: Required<Pick<RpcClientConfig, 'url' | 'timeout'>> & RpcClientConfig;\n\n private readonly channelStateAliases: Record<string, ChannelState> = {\n NEGOTIATING_FUNDING: ChannelState.NegotiatingFunding,\n COLLABORATING_FUNDING_TX: ChannelState.CollaboratingFundingTx,\n SIGNING_COMMITMENT: ChannelState.SigningCommitment,\n AWAITING_TX_SIGNATURES: ChannelState.AwaitingTxSignatures,\n AWAITING_CHANNEL_READY: ChannelState.AwaitingChannelReady,\n CHANNEL_READY: ChannelState.ChannelReady,\n SHUTTING_DOWN: ChannelState.ShuttingDown,\n CLOSED: ChannelState.Closed,\n };\n\n constructor(config: RpcClientConfig) {\n this.config = {\n timeout: 30000,\n ...config,\n };\n }\n\n /**\n * Make a raw JSON-RPC call\n *\n * Useful for advanced/experimental RPCs not wrapped by convenience methods.\n *\n * @example\n * ```ts\n * const result = await client.call<MyResult>('some_method', [{ foo: 'bar' }]);\n * ```\n */\n async call<TResult>(method: string, params: unknown[] = []): Promise<TResult> {\n const request: JsonRpcRequest = {\n jsonrpc: '2.0',\n id: ++this.requestId,\n method,\n params,\n };\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...this.config.headers,\n };\n\n if (this.config.biscuitToken) {\n headers.Authorization = `Bearer ${this.config.biscuitToken}`;\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const response = await fetch(this.config.url, {\n method: 'POST',\n headers,\n body: JSON.stringify(request),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new FiberRpcError(-32000, `HTTP error: ${response.status} ${response.statusText}`);\n }\n\n const json = (await response.json()) as JsonRpcResponse<TResult>;\n\n if (json.error) {\n throw FiberRpcError.fromJsonRpcError(json.error);\n }\n\n if (json.result === undefined) {\n throw new FiberRpcError(-32000, 'Invalid JSON-RPC response: missing result and error');\n }\n\n return json.result as TResult;\n } catch (error) {\n if (error instanceof FiberRpcError) {\n throw error;\n }\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new FiberRpcError(-32000, 'Request timeout');\n }\n throw new FiberRpcError(-32000, error.message);\n }\n throw new FiberRpcError(-32000, 'Unknown error');\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n // ===========================================================================\n // Peer Module\n // ===========================================================================\n\n /**\n * Connect to a peer\n */\n async connectPeer(params: ConnectPeerParams): Promise<ConnectPeerResult> {\n return this.call<ConnectPeerResult>('connect_peer', [params]);\n }\n\n /**\n * Disconnect from a peer\n */\n async disconnectPeer(params: DisconnectPeerParams): Promise<null> {\n return this.call<null>('disconnect_peer', [params]);\n }\n\n /**\n * List all connected peers\n */\n async listPeers(): Promise<ListPeersResult> {\n return this.call<ListPeersResult>('list_peers', []);\n }\n\n // ===========================================================================\n // Channel Module\n // ===========================================================================\n\n /**\n * Open a new channel with a peer\n */\n async openChannel(params: OpenChannelParams): Promise<OpenChannelResult> {\n return this.call<OpenChannelResult>('open_channel', [params]);\n }\n\n /**\n * Accept a channel opening request\n */\n async acceptChannel(params: AcceptChannelParams): Promise<AcceptChannelResult> {\n return this.call<AcceptChannelResult>('accept_channel', [params]);\n }\n\n /**\n * List all channels\n */\n async listChannels(params?: ListChannelsParams): Promise<ListChannelsResult> {\n const result = await this.call<ListChannelsResult>('list_channels', params ? [params] : [{}]);\n return {\n ...result,\n channels: result.channels.map((channel) => this.normalizeChannel(channel)),\n };\n }\n\n private normalizeChannelStateName(stateName: string): ChannelState {\n const alias = this.channelStateAliases[stateName];\n if (alias) return alias;\n\n const normalizedInput = stateName.replace(/[^a-zA-Z0-9]/g, '').toLowerCase();\n for (const value of Object.values(ChannelState)) {\n const normalizedValue = value.replace(/[^a-zA-Z0-9]/g, '').toLowerCase();\n if (normalizedValue === normalizedInput) {\n return value;\n }\n }\n\n return stateName as ChannelState;\n }\n\n private normalizeChannel(channel: Channel): Channel {\n return {\n ...channel,\n state: {\n ...channel.state,\n state_name: this.normalizeChannelStateName(channel.state.state_name),\n },\n };\n }\n\n /**\n * Shutdown (close) a channel\n */\n async shutdownChannel(params: ShutdownChannelParams): Promise<null> {\n return this.call<null>('shutdown_channel', [params]);\n }\n\n /**\n * Abandon a pending channel\n */\n async abandonChannel(params: AbandonChannelParams): Promise<null> {\n return this.call<null>('abandon_channel', [params]);\n }\n\n /**\n * Update channel parameters\n */\n async updateChannel(params: UpdateChannelParams): Promise<null> {\n return this.call<null>('update_channel', [params]);\n }\n\n // ===========================================================================\n // Payment Module\n // ===========================================================================\n\n /**\n * Send a payment\n */\n async sendPayment(params: SendPaymentParams): Promise<SendPaymentResult> {\n return this.call<SendPaymentResult>('send_payment', [params]);\n }\n\n /**\n * Get payment status\n */\n async getPayment(params: GetPaymentParams): Promise<GetPaymentResult> {\n return this.call<GetPaymentResult>('get_payment', [params]);\n }\n\n // ===========================================================================\n // Invoice Module\n // ===========================================================================\n\n /**\n * Create a new invoice\n */\n async newInvoice(params: NewInvoiceParams): Promise<NewInvoiceResult> {\n return this.call<NewInvoiceResult>('new_invoice', [params]);\n }\n\n /**\n * Parse an invoice string\n */\n async parseInvoice(params: ParseInvoiceParams): Promise<ParseInvoiceResult> {\n return this.call<ParseInvoiceResult>('parse_invoice', [params]);\n }\n\n /**\n * Get invoice by payment hash\n */\n async getInvoice(params: GetInvoiceParams): Promise<GetInvoiceResult> {\n return this.call<GetInvoiceResult>('get_invoice', [params]);\n }\n\n /**\n * Cancel an open invoice\n */\n async cancelInvoice(params: CancelInvoiceParams): Promise<CancelInvoiceResult> {\n return this.call<CancelInvoiceResult>('cancel_invoice', [params]);\n }\n\n /**\n * Settle a hold invoice with the preimage\n * Used for conditional/escrow payments where the invoice was created\n * with a payment_hash (no preimage provided upfront)\n */\n async settleInvoice(params: SettleInvoiceParams): Promise<null> {\n return this.call<null>('settle_invoice', [params]);\n }\n\n // ===========================================================================\n // Router Module\n // ===========================================================================\n\n /**\n * Build a custom route for payment\n * Useful for channel rebalancing (circular payments) and advanced routing\n */\n async buildRouter(params: BuildRouterParams): Promise<BuildRouterResult> {\n return this.call<BuildRouterResult>('build_router', [params]);\n }\n\n /**\n * Send a payment using a pre-built route from buildRouter()\n * Use with allow_self_payment for channel rebalancing\n */\n async sendPaymentWithRouter(params: SendPaymentWithRouterParams): Promise<SendPaymentResult> {\n return this.call<SendPaymentResult>('send_payment_with_router', [params]);\n }\n\n // ===========================================================================\n // Graph Module\n // ===========================================================================\n\n /**\n * List nodes in the network graph\n */\n async graphNodes(params?: GraphNodesParams): Promise<GraphNodesResult> {\n return this.call<GraphNodesResult>('graph_nodes', params ? [params] : [{}]);\n }\n\n /**\n * List channels in the network graph\n */\n async graphChannels(params?: GraphChannelsParams): Promise<GraphChannelsResult> {\n return this.call<GraphChannelsResult>('graph_channels', params ? [params] : [{}]);\n }\n\n // ===========================================================================\n // Info Module\n // ===========================================================================\n\n /**\n * Get local node information\n */\n async nodeInfo(): Promise<NodeInfoResult> {\n return this.call<NodeInfoResult>('node_info', []);\n }\n\n // ===========================================================================\n // Utility Methods\n // ===========================================================================\n\n /**\n * Check if the node is reachable\n */\n async ping(): Promise<boolean> {\n try {\n await this.nodeInfo();\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Wait for the node to be ready\n */\n async waitForReady(options: { timeout?: number; interval?: number } = {}): Promise<void> {\n const { timeout = 60000, interval = 1000 } = options;\n const start = Date.now();\n\n while (Date.now() - start < timeout) {\n if (await this.ping()) {\n return;\n }\n await new Promise((resolve) => setTimeout(resolve, interval));\n }\n\n throw new FiberRpcError(-32000, 'Node not ready within timeout');\n }\n\n // ===========================================================================\n // Polling / Watching Helpers\n // ===========================================================================\n\n /**\n * Wait for a payment to reach a terminal state (Success or Failed)\n * Polls get_payment at the specified interval.\n *\n * @returns The final payment result\n * @throws FiberRpcError on timeout\n */\n async waitForPayment(\n paymentHash: PaymentHash,\n options: { timeout?: number; interval?: number } = {},\n ): Promise<GetPaymentResult> {\n const { timeout = 120000, interval = 2000 } = options;\n const start = Date.now();\n\n while (Date.now() - start < timeout) {\n const result = await this.getPayment({ payment_hash: paymentHash });\n if (result.status === 'Success' || result.status === 'Failed') {\n return result;\n }\n await new Promise((resolve) => setTimeout(resolve, interval));\n }\n\n throw new FiberRpcError(-32000, `Payment ${paymentHash} did not complete within ${timeout}ms`);\n }\n\n /**\n * Wait for a channel to reach ChannelReady state.\n * Polls list_channels at the specified interval.\n *\n * @returns The channel info once ready\n * @throws FiberRpcError on timeout or if channel disappears\n */\n async waitForChannelReady(\n channelId: ChannelId,\n options: { timeout?: number; interval?: number } = {},\n ): Promise<Channel> {\n const { timeout = 300000, interval = 5000 } = options;\n const start = Date.now();\n\n while (Date.now() - start < timeout) {\n const result = await this.listChannels({});\n const channel = result.channels.find((ch) => ch.channel_id === channelId);\n\n if (!channel) {\n // Channel may use temporary_channel_id initially, check all\n const allChannels = result.channels;\n const found = allChannels.find((ch) => ch.channel_id === channelId);\n if (!found) {\n // Channel not yet visible or was abandoned - keep waiting\n await new Promise((resolve) => setTimeout(resolve, interval));\n continue;\n }\n }\n\n if (channel && channel.state.state_name === ChannelState.ChannelReady) {\n return channel;\n }\n\n if (channel && channel.state.state_name === ChannelState.Closed) {\n throw new FiberRpcError(-32000, `Channel ${channelId} was closed before becoming ready`);\n }\n\n await new Promise((resolve) => setTimeout(resolve, interval));\n }\n\n throw new FiberRpcError(\n -32000,\n `Channel ${channelId} did not become ready within ${timeout}ms`,\n );\n }\n\n /**\n * Wait for an invoice to reach a specific status.\n * Useful for hold invoice workflows: wait for 'Received' before settling.\n *\n * @returns The invoice info once the target status is reached\n * @throws FiberRpcError on timeout\n */\n async waitForInvoiceStatus(\n paymentHash: PaymentHash,\n targetStatus: CkbInvoiceStatus | CkbInvoiceStatus[],\n options: { timeout?: number; interval?: number } = {},\n ): Promise<GetInvoiceResult> {\n const { timeout = 120000, interval = 2000 } = options;\n const statuses = Array.isArray(targetStatus) ? targetStatus : [targetStatus];\n const start = Date.now();\n\n while (Date.now() - start < timeout) {\n const result = await this.getInvoice({ payment_hash: paymentHash });\n if (statuses.includes(result.status)) {\n return result;\n }\n // If cancelled, stop waiting\n if (result.status === 'Cancelled') {\n throw new FiberRpcError(-32000, `Invoice ${paymentHash} was cancelled`);\n }\n await new Promise((resolve) => setTimeout(resolve, interval));\n }\n\n throw new FiberRpcError(\n -32000,\n `Invoice ${paymentHash} did not reach status [${statuses.join(', ')}] within ${timeout}ms`,\n );\n }\n\n /**\n * Watch for incoming payments on specified invoices.\n * Polls invoice statuses and calls the callback when a status changes.\n * Use an AbortSignal to stop watching.\n *\n * @example\n * ```typescript\n * const controller = new AbortController();\n * client.watchIncomingPayments({\n * paymentHashes: [hash1, hash2],\n * onPayment: (invoice) => console.log('Payment received!', invoice),\n * signal: controller.signal,\n * });\n * // Later: controller.abort(); to stop watching\n * ```\n */\n async watchIncomingPayments(options: {\n /** Payment hashes of invoices to watch */\n paymentHashes: PaymentHash[];\n /** Callback when an invoice status changes to Received or Paid */\n onPayment: (invoice: GetInvoiceResult) => void;\n /** Polling interval in ms (default: 3000) */\n interval?: number;\n /** AbortSignal to stop watching */\n signal?: AbortSignal;\n }): Promise<void> {\n const { paymentHashes, onPayment, interval = 3000, signal } = options;\n const knownStatuses = new Map<string, CkbInvoiceStatus>();\n\n // Initialize known statuses\n for (const hash of paymentHashes) {\n try {\n const invoice = await this.getInvoice({ payment_hash: hash });\n knownStatuses.set(hash, invoice.status);\n } catch {\n knownStatuses.set(hash, 'Open');\n }\n }\n\n while (!signal?.aborted) {\n for (const hash of paymentHashes) {\n if (signal?.aborted) return;\n\n try {\n const invoice = await this.getInvoice({ payment_hash: hash });\n const previousStatus = knownStatuses.get(hash);\n\n if (\n invoice.status !== previousStatus &&\n (invoice.status === 'Received' || invoice.status === 'Paid')\n ) {\n knownStatuses.set(hash, invoice.status);\n onPayment(invoice);\n } else if (invoice.status !== previousStatus) {\n knownStatuses.set(hash, invoice.status);\n }\n } catch {\n // Invoice may not exist yet or node unreachable — skip this round\n }\n }\n\n await new Promise<void>((resolve) => {\n if (signal?.aborted) {\n resolve();\n return;\n }\n const timer = setTimeout(resolve, interval);\n signal?.addEventListener(\n 'abort',\n () => {\n clearTimeout(timer);\n resolve();\n },\n { once: true },\n );\n });\n }\n }\n}\n\n// =============================================================================\n// Re-export utility functions\n// =============================================================================\n\nexport { ckbToShannons, fromHex, randomBytes32, shannonsToCkb, toHex } from '../utils.js';\n"],"mappings":"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","names":["ChannelState"]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
import { FiberRpcClient, ChannelState, KeyConfig, KeyInfo, SecurityPolicy, PolicyCheckResult, AuditAction, PolicyViolation, AuditLogEntry, PaymentStatus, HexString } from './browser.js';
|
|
2
|
+
export { AbandonChannelParams, AcceptChannelParams, AcceptChannelResult, AgentSession, Attribute, BuildRouterParams, BuildRouterResult, CancelInvoiceParams, CancelInvoiceResult, CchInvoice, CchOrderStatus, CellOutput, Channel, ChannelId, ChannelPolicy, ChannelPolicySchema, ChannelStateFlags, ChannelUpdateInfo, CkbInvoice, CkbInvoiceStatus, ConnectPeerParams, ConnectPeerResult, Currency, DEFAULT_SECURITY_POLICY, DisconnectPeerParams, FiberRpcError, GetInvoiceParams, GetInvoiceResult, GetPaymentParams, GetPaymentResult, GraphChannelInfo, GraphChannelsParams, GraphChannelsResult, GraphNodeInfo, GraphNodesParams, GraphNodesResult, Hash256, HashAlgorithm, HopHint, HopRequire, Htlc, InvoiceData, InvoiceSignature, JsonRpcError, JsonRpcRequest, JsonRpcResponse, ListChannelsParams, ListChannelsResult, ListPeersResult, Multiaddr, NewInvoiceParams, NewInvoiceResult, NodeInfo, NodeInfoResult, OpenChannelParams, OpenChannelResult, OutPoint, ParseInvoiceParams, ParseInvoiceResult, PaymentCustomRecords, PaymentHash, PaymentInfo, PeerId, PeerInfo, Privkey, Pubkey, RateLimit, RateLimitSchema, RecipientPolicy, RecipientPolicySchema, RemoveTlcReason, RevocationData, RouterHop, Script, SecurityPolicySchema, SendPaymentParams, SendPaymentResult, SendPaymentWithRouterParams, SessionRoute, SessionRouteNode, SettleInvoiceParams, SettlementData, SettlementTlc, ShutdownChannelParams, SpendingLimit, SpendingLimitSchema, TLCId, TlcStatus, UdtArgInfo, UdtCellDep, UdtCfgInfos, UdtDep, UdtScript, UpdateChannelParams, ViolationType, buildMultiaddr, buildMultiaddrFromNodeId, buildMultiaddrFromRpcUrl, ckbToShannons, fromHex, nodeIdToPeerId, randomBytes32, scriptToAddress, shannonsToCkb, toHex } from './browser.js';
|
|
3
|
+
import 'zod';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Fund Management & Liquidity Analyzer
|
|
7
|
+
* Analyzes channel health, identifies liquidity gaps, and provides funding recommendations
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Channel health score breakdown
|
|
12
|
+
*/
|
|
13
|
+
interface ChannelHealthMetrics {
|
|
14
|
+
channelId: string;
|
|
15
|
+
peerId: string;
|
|
16
|
+
localBalanceCkb: number;
|
|
17
|
+
remoteBalanceCkb: number;
|
|
18
|
+
totalCapacityCkb: number;
|
|
19
|
+
utilizationPercent: number;
|
|
20
|
+
balanceRatioPercent: number;
|
|
21
|
+
isBalanced: boolean;
|
|
22
|
+
pendingLocalCkb: number;
|
|
23
|
+
pendingRemoteCkb: number;
|
|
24
|
+
availableToSendCkb: number;
|
|
25
|
+
availableToReceiveCkb: number;
|
|
26
|
+
healthScore: number;
|
|
27
|
+
state: ChannelState;
|
|
28
|
+
}
|
|
29
|
+
interface LiquidityGap {
|
|
30
|
+
amount: number;
|
|
31
|
+
reason: string;
|
|
32
|
+
severity: 'low' | 'medium' | 'high';
|
|
33
|
+
affectedChannels: string[];
|
|
34
|
+
}
|
|
35
|
+
interface RebalanceRecommendation {
|
|
36
|
+
from: string;
|
|
37
|
+
to: string;
|
|
38
|
+
amountCkb: number;
|
|
39
|
+
reason: string;
|
|
40
|
+
benefit: string;
|
|
41
|
+
estimatedRoutingFeeCkb: number;
|
|
42
|
+
priority: number;
|
|
43
|
+
}
|
|
44
|
+
interface FundingNeed {
|
|
45
|
+
amount: number;
|
|
46
|
+
reason: string;
|
|
47
|
+
optimalChannelPeerId?: string;
|
|
48
|
+
urgency: 'low' | 'normal' | 'high';
|
|
49
|
+
estimatedTimeToDepletion?: number;
|
|
50
|
+
}
|
|
51
|
+
interface LiquidityReport {
|
|
52
|
+
timestamp: number;
|
|
53
|
+
balance: {
|
|
54
|
+
totalCkb: number;
|
|
55
|
+
availableToSendCkb: number;
|
|
56
|
+
availableToReceiveCkb: number;
|
|
57
|
+
lockedInChannelsCkb: number;
|
|
58
|
+
};
|
|
59
|
+
channels: {
|
|
60
|
+
count: number;
|
|
61
|
+
health: ChannelHealthMetrics[];
|
|
62
|
+
averageHealthScore: number;
|
|
63
|
+
balancedCount: number;
|
|
64
|
+
imbalancedCount: number;
|
|
65
|
+
};
|
|
66
|
+
liquidity: {
|
|
67
|
+
gaps: LiquidityGap[];
|
|
68
|
+
hasCriticalGaps: boolean;
|
|
69
|
+
runway: {
|
|
70
|
+
daysAtCurrentRate?: number;
|
|
71
|
+
estimatedDailySpendCkb?: number;
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
recommendations: {
|
|
75
|
+
rebalances: RebalanceRecommendation[];
|
|
76
|
+
funding: FundingNeed[];
|
|
77
|
+
};
|
|
78
|
+
summary: string;
|
|
79
|
+
}
|
|
80
|
+
declare class LiquidityAnalyzer {
|
|
81
|
+
private rpc;
|
|
82
|
+
constructor(rpc: FiberRpcClient);
|
|
83
|
+
/**
|
|
84
|
+
* Comprehensive liquidity analysis
|
|
85
|
+
*/
|
|
86
|
+
analyzeLiquidity(): Promise<LiquidityReport>;
|
|
87
|
+
/**
|
|
88
|
+
* Analyze individual channel health
|
|
89
|
+
*/
|
|
90
|
+
private analyzeChannelHealth;
|
|
91
|
+
/**
|
|
92
|
+
* Identify liquidity shortfalls and gaps
|
|
93
|
+
*/
|
|
94
|
+
private identifyLiquidityGaps;
|
|
95
|
+
/**
|
|
96
|
+
* Generate rebalance recommendations between channels
|
|
97
|
+
*/
|
|
98
|
+
private generateRebalanceRecommendations;
|
|
99
|
+
/**
|
|
100
|
+
* Estimate funding needs for future operations
|
|
101
|
+
*/
|
|
102
|
+
private estimateFundingNeeds;
|
|
103
|
+
/**
|
|
104
|
+
* Estimate runway (days until liquidity depleted at current spending rate)
|
|
105
|
+
*/
|
|
106
|
+
private estimateRunway;
|
|
107
|
+
/**
|
|
108
|
+
* Generate human-readable summary
|
|
109
|
+
*/
|
|
110
|
+
private generateSummary;
|
|
111
|
+
/**
|
|
112
|
+
* Get missing liquidity for a specific amount
|
|
113
|
+
*/
|
|
114
|
+
getMissingLiquidityForAmount(targetCkb: number): Promise<{
|
|
115
|
+
canSend: boolean;
|
|
116
|
+
shortfallCkb: number;
|
|
117
|
+
recommendation: string;
|
|
118
|
+
}>;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* CORS Proxy Server
|
|
123
|
+
* Simple HTTP proxy that adds CORS headers to Fiber RPC requests
|
|
124
|
+
*/
|
|
125
|
+
interface CorsProxyConfig {
|
|
126
|
+
/** Port to listen on */
|
|
127
|
+
port: number;
|
|
128
|
+
/** Target RPC URL to proxy to */
|
|
129
|
+
targetUrl: string;
|
|
130
|
+
/** Allowed origins (default: '*') */
|
|
131
|
+
allowedOrigins?: string | string[];
|
|
132
|
+
}
|
|
133
|
+
declare class CorsProxy {
|
|
134
|
+
private server;
|
|
135
|
+
private config;
|
|
136
|
+
constructor(config: CorsProxyConfig);
|
|
137
|
+
/**
|
|
138
|
+
* Start the CORS proxy server
|
|
139
|
+
*/
|
|
140
|
+
start(): Promise<void>;
|
|
141
|
+
/**
|
|
142
|
+
* Stop the CORS proxy server
|
|
143
|
+
*/
|
|
144
|
+
stop(): Promise<void>;
|
|
145
|
+
/**
|
|
146
|
+
* Get the allowed origin based on config
|
|
147
|
+
*/
|
|
148
|
+
private getAllowedOrigin;
|
|
149
|
+
/**
|
|
150
|
+
* Get the proxy URL
|
|
151
|
+
*/
|
|
152
|
+
getUrl(): string;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Key Manager
|
|
157
|
+
* Handles generation, storage, and encryption of Fiber node keys
|
|
158
|
+
* Keys are isolated from LLM context for security
|
|
159
|
+
*/
|
|
160
|
+
|
|
161
|
+
declare class KeyManager {
|
|
162
|
+
private config;
|
|
163
|
+
private fiberKeyPath;
|
|
164
|
+
private ckbKeyPath;
|
|
165
|
+
constructor(config: KeyConfig);
|
|
166
|
+
/**
|
|
167
|
+
* Initialize keys - generate if they don't exist and autoGenerate is true
|
|
168
|
+
*/
|
|
169
|
+
initialize(): Promise<{
|
|
170
|
+
fiber: KeyInfo;
|
|
171
|
+
ckb: KeyInfo;
|
|
172
|
+
}>;
|
|
173
|
+
/**
|
|
174
|
+
* Generate a new key
|
|
175
|
+
*/
|
|
176
|
+
generateKey(type: 'fiber' | 'ckb'): Promise<KeyInfo>;
|
|
177
|
+
/**
|
|
178
|
+
* Get information about a key (without exposing the private key)
|
|
179
|
+
*/
|
|
180
|
+
getKeyInfo(type: 'fiber' | 'ckb'): Promise<KeyInfo>;
|
|
181
|
+
/**
|
|
182
|
+
* Load and decrypt a private key (for internal use only)
|
|
183
|
+
* This should NEVER be exposed to the LLM context
|
|
184
|
+
*/
|
|
185
|
+
private loadPrivateKey;
|
|
186
|
+
/**
|
|
187
|
+
* Export keys for use with the Fiber node process
|
|
188
|
+
* Returns the password to use for FIBER_SECRET_KEY_PASSWORD env var
|
|
189
|
+
*/
|
|
190
|
+
getNodeKeyConfig(): {
|
|
191
|
+
password?: string;
|
|
192
|
+
};
|
|
193
|
+
/**
|
|
194
|
+
* Check if key data is encrypted
|
|
195
|
+
*/
|
|
196
|
+
private isEncrypted;
|
|
197
|
+
/**
|
|
198
|
+
* Decrypt a key
|
|
199
|
+
*/
|
|
200
|
+
private decryptKey;
|
|
201
|
+
/**
|
|
202
|
+
* Derive public key from private key (secp256k1)
|
|
203
|
+
* This is a simplified version - in production, use a proper secp256k1 library
|
|
204
|
+
*/
|
|
205
|
+
private derivePublicKey;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Create a key manager with environment-based configuration
|
|
209
|
+
*/
|
|
210
|
+
declare function createKeyManager(baseDir: string, options?: Partial<KeyConfig>): KeyManager;
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Policy Engine
|
|
214
|
+
* Enforces spending limits, rate limits, and other security policies
|
|
215
|
+
* This operates at the SDK level and cannot be bypassed via prompts
|
|
216
|
+
*/
|
|
217
|
+
|
|
218
|
+
declare class PolicyEngine {
|
|
219
|
+
private policy;
|
|
220
|
+
private auditLog;
|
|
221
|
+
private spendingState;
|
|
222
|
+
private rateLimitState;
|
|
223
|
+
constructor(policy: SecurityPolicy);
|
|
224
|
+
/**
|
|
225
|
+
* Check if a payment is allowed by the policy
|
|
226
|
+
*/
|
|
227
|
+
checkPayment(params: {
|
|
228
|
+
amount: string;
|
|
229
|
+
recipient?: string;
|
|
230
|
+
}): PolicyCheckResult;
|
|
231
|
+
/**
|
|
232
|
+
* Check if a channel operation is allowed
|
|
233
|
+
*/
|
|
234
|
+
checkChannelOperation(params: {
|
|
235
|
+
operation: 'open' | 'close' | 'force_close';
|
|
236
|
+
fundingAmount?: string;
|
|
237
|
+
currentChannelCount?: number;
|
|
238
|
+
}): PolicyCheckResult;
|
|
239
|
+
/**
|
|
240
|
+
* Record a successful payment (updates spending and rate limit state)
|
|
241
|
+
*/
|
|
242
|
+
recordPayment(amount: string): void;
|
|
243
|
+
/**
|
|
244
|
+
* Add an entry to the audit log
|
|
245
|
+
*/
|
|
246
|
+
addAuditEntry(action: AuditAction, success: boolean, details: Record<string, unknown>, violations?: PolicyViolation[]): void;
|
|
247
|
+
/**
|
|
248
|
+
* Get the audit log
|
|
249
|
+
*/
|
|
250
|
+
getAuditLog(options?: {
|
|
251
|
+
limit?: number;
|
|
252
|
+
since?: number;
|
|
253
|
+
}): AuditLogEntry[];
|
|
254
|
+
/**
|
|
255
|
+
* Get remaining spending allowance
|
|
256
|
+
*/
|
|
257
|
+
getRemainingAllowance(): {
|
|
258
|
+
perTransaction: bigint;
|
|
259
|
+
perWindow: bigint;
|
|
260
|
+
};
|
|
261
|
+
/**
|
|
262
|
+
* Update the policy
|
|
263
|
+
*/
|
|
264
|
+
updatePolicy(newPolicy: Partial<SecurityPolicy>): void;
|
|
265
|
+
/**
|
|
266
|
+
* Get the current policy
|
|
267
|
+
*/
|
|
268
|
+
getPolicy(): SecurityPolicy;
|
|
269
|
+
private refreshSpendingWindow;
|
|
270
|
+
private refreshRateLimitWindow;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Invoice Verification Engine
|
|
275
|
+
* Validates invoice legitimacy, format, cryptographic correctness, and peer connectivity
|
|
276
|
+
* This ensures the agent only pays valid invoices
|
|
277
|
+
*/
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Invoice verification result
|
|
281
|
+
*/
|
|
282
|
+
interface InvoiceVerificationResult {
|
|
283
|
+
/** Overall validity (true = safe to pay) */
|
|
284
|
+
valid: boolean;
|
|
285
|
+
/** Invoice parsed details */
|
|
286
|
+
details: {
|
|
287
|
+
paymentHash: string;
|
|
288
|
+
amountCkb: number;
|
|
289
|
+
expiresAt: number;
|
|
290
|
+
description?: string;
|
|
291
|
+
isExpired: boolean;
|
|
292
|
+
};
|
|
293
|
+
/** Peer information */
|
|
294
|
+
peer: {
|
|
295
|
+
nodeId?: string;
|
|
296
|
+
isConnected: boolean;
|
|
297
|
+
trustScore: number;
|
|
298
|
+
};
|
|
299
|
+
/** Validation checks performed */
|
|
300
|
+
checks: {
|
|
301
|
+
validFormat: boolean;
|
|
302
|
+
notExpired: boolean;
|
|
303
|
+
validAmount: boolean;
|
|
304
|
+
peerConnected: boolean;
|
|
305
|
+
};
|
|
306
|
+
/** Issues found */
|
|
307
|
+
issues: VerificationIssue[];
|
|
308
|
+
/** Recommendation for agent */
|
|
309
|
+
recommendation: 'proceed' | 'warn' | 'reject';
|
|
310
|
+
/** Human-readable reason for recommendation */
|
|
311
|
+
reason: string;
|
|
312
|
+
}
|
|
313
|
+
interface VerificationIssue {
|
|
314
|
+
type: 'warning' | 'critical';
|
|
315
|
+
code: string;
|
|
316
|
+
message: string;
|
|
317
|
+
}
|
|
318
|
+
declare class InvoiceVerifier {
|
|
319
|
+
private rpc;
|
|
320
|
+
constructor(rpc: FiberRpcClient);
|
|
321
|
+
/**
|
|
322
|
+
* Fully validate an invoice before payment
|
|
323
|
+
*/
|
|
324
|
+
verifyInvoice(invoiceString: string): Promise<InvoiceVerificationResult>;
|
|
325
|
+
/**
|
|
326
|
+
* Quick format validation (regex-based, before RPC call)
|
|
327
|
+
*/
|
|
328
|
+
private validateInvoiceFormat;
|
|
329
|
+
/**
|
|
330
|
+
* Validate amount is positive and reasonable
|
|
331
|
+
*/
|
|
332
|
+
private validateAmount;
|
|
333
|
+
/**
|
|
334
|
+
* Check if invoice has expired
|
|
335
|
+
*/
|
|
336
|
+
private isInvoiceExpired;
|
|
337
|
+
/**
|
|
338
|
+
* Get expiry timestamp in milliseconds
|
|
339
|
+
*/
|
|
340
|
+
private getExpiryTimestamp;
|
|
341
|
+
private getAttributeU64;
|
|
342
|
+
private getDescription;
|
|
343
|
+
/**
|
|
344
|
+
* Try to extract payee node public key from invoice attributes
|
|
345
|
+
* The payee public key is embedded in the invoice as a PayeePublicKey attribute
|
|
346
|
+
*/
|
|
347
|
+
private extractNodeIdFromInvoice;
|
|
348
|
+
/**
|
|
349
|
+
* Calculate trust score (0-100) based on various factors
|
|
350
|
+
*/
|
|
351
|
+
private calculateTrustScore;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Payment Proof & Tracking System
|
|
356
|
+
* Records, stores, and verifies payment evidence for audit trail and reconciliation
|
|
357
|
+
*
|
|
358
|
+
* IMPORTANT LIMITATION:
|
|
359
|
+
* Fiber Network RPC currently does NOT return the payment preimage to the sender
|
|
360
|
+
* after a successful payment. In standard Lightning protocol, the preimage serves
|
|
361
|
+
* as cryptographic proof of payment (SHA256(preimage) === payment_hash).
|
|
362
|
+
*
|
|
363
|
+
* Until Fiber exposes the preimage in send_payment/get_payment responses:
|
|
364
|
+
* - Payment proofs are based on RPC status (Success/Failed) rather than preimage
|
|
365
|
+
* - For invoices YOU create (as receiver), preimage IS available
|
|
366
|
+
* - This limitation affects sender-side proof verification only
|
|
367
|
+
*
|
|
368
|
+
* Tracking issue: Preimage not exposed in Fiber RPC send_payment result
|
|
369
|
+
*/
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Complete payment proof record
|
|
373
|
+
*/
|
|
374
|
+
interface PaymentProof {
|
|
375
|
+
/** Unique identifier (payment hash) */
|
|
376
|
+
id: string;
|
|
377
|
+
/** Status at time of recording */
|
|
378
|
+
status: PaymentStatus;
|
|
379
|
+
/** Original invoice string */
|
|
380
|
+
invoice: string;
|
|
381
|
+
/** Invoice details extracted */
|
|
382
|
+
invoiceDetails: {
|
|
383
|
+
paymentHash: string;
|
|
384
|
+
amountCkb: number;
|
|
385
|
+
description?: string;
|
|
386
|
+
};
|
|
387
|
+
/** Payment execution details */
|
|
388
|
+
execution: {
|
|
389
|
+
amountCkb: number;
|
|
390
|
+
feeCkb: number;
|
|
391
|
+
actualTimestamp: number;
|
|
392
|
+
requestTimestamp: number;
|
|
393
|
+
};
|
|
394
|
+
/** Proof of payment */
|
|
395
|
+
proof: {
|
|
396
|
+
preimage?: HexString;
|
|
397
|
+
peerAddress?: string;
|
|
398
|
+
channelUsed?: string;
|
|
399
|
+
routePath?: string[];
|
|
400
|
+
};
|
|
401
|
+
/** Verification status */
|
|
402
|
+
verified: boolean;
|
|
403
|
+
verifiedAt?: number;
|
|
404
|
+
verificationMethod?: 'preimage_hash' | 'rpc_status' | 'manual';
|
|
405
|
+
/** Metadata for audit trail */
|
|
406
|
+
metadata: {
|
|
407
|
+
createdAt: number;
|
|
408
|
+
updatedAt: number;
|
|
409
|
+
notes?: string;
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
interface PaymentProofSummary {
|
|
413
|
+
totalProofs: number;
|
|
414
|
+
verifiedCount: number;
|
|
415
|
+
pendingCount: number;
|
|
416
|
+
failedCount: number;
|
|
417
|
+
totalAmountCkb: number;
|
|
418
|
+
totalFeesCkb: number;
|
|
419
|
+
timeRange: {
|
|
420
|
+
earliest?: number;
|
|
421
|
+
latest?: number;
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
declare class PaymentProofManager {
|
|
425
|
+
private proofs;
|
|
426
|
+
private proofFilePath;
|
|
427
|
+
private maxStoredProofs;
|
|
428
|
+
constructor(dataDir: string);
|
|
429
|
+
/**
|
|
430
|
+
* Load proofs from disk
|
|
431
|
+
*/
|
|
432
|
+
load(): Promise<void>;
|
|
433
|
+
/**
|
|
434
|
+
* Save proofs to disk
|
|
435
|
+
*/
|
|
436
|
+
save(): Promise<void>;
|
|
437
|
+
/**
|
|
438
|
+
* Record a payment proof after successful execution
|
|
439
|
+
*/
|
|
440
|
+
recordPaymentProof(paymentHash: string, invoice: string, invoiceDetails: {
|
|
441
|
+
paymentHash: string;
|
|
442
|
+
amountCkb: number;
|
|
443
|
+
description?: string;
|
|
444
|
+
}, execution: {
|
|
445
|
+
amountCkb: number;
|
|
446
|
+
feeCkb: number;
|
|
447
|
+
actualTimestamp: number;
|
|
448
|
+
requestTimestamp: number;
|
|
449
|
+
}, status: PaymentStatus, proof?: {
|
|
450
|
+
preimage?: HexString;
|
|
451
|
+
peerAddress?: string;
|
|
452
|
+
channelUsed?: string;
|
|
453
|
+
routePath?: string[];
|
|
454
|
+
}): PaymentProof;
|
|
455
|
+
/**
|
|
456
|
+
* Get proof by payment hash
|
|
457
|
+
*/
|
|
458
|
+
getProof(paymentHash: string): PaymentProof | undefined;
|
|
459
|
+
/**
|
|
460
|
+
* Verify a proof's authenticity
|
|
461
|
+
*/
|
|
462
|
+
verifyProof(proof: PaymentProof): {
|
|
463
|
+
valid: boolean;
|
|
464
|
+
reason: string;
|
|
465
|
+
};
|
|
466
|
+
/**
|
|
467
|
+
* Get payment timeline between two timestamps
|
|
468
|
+
*/
|
|
469
|
+
getPaymentChain(startTime: number, endTime: number): PaymentProof[];
|
|
470
|
+
/**
|
|
471
|
+
* Get summary statistics
|
|
472
|
+
*/
|
|
473
|
+
getSummary(): PaymentProofSummary;
|
|
474
|
+
/**
|
|
475
|
+
* Export proofs as audit report
|
|
476
|
+
*/
|
|
477
|
+
exportAuditReport(startTime?: number, endTime?: number): string;
|
|
478
|
+
/**
|
|
479
|
+
* Verify preimage hash (SHA256 of preimage = payment_hash)
|
|
480
|
+
*/
|
|
481
|
+
private verifyPreimageHash;
|
|
482
|
+
/**
|
|
483
|
+
* Remove oldest proofs to keep storage bounded
|
|
484
|
+
*/
|
|
485
|
+
private pruneOldestProofs;
|
|
486
|
+
/**
|
|
487
|
+
* Ensure directory exists
|
|
488
|
+
*/
|
|
489
|
+
private ensureDirectory;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
export { AuditAction, AuditLogEntry, ChannelState, CorsProxy, FiberRpcClient, HexString, type InvoiceVerificationResult, InvoiceVerifier, KeyConfig, KeyInfo, KeyManager, LiquidityAnalyzer, type LiquidityReport, type PaymentProof, PaymentProofManager, type PaymentProofSummary, PaymentStatus, PolicyCheckResult, PolicyEngine, PolicyViolation, SecurityPolicy, createKeyManager };
|