UNPKG

@caravan/clients

Version:

A package for querying different bitcoin blockchain backends

269 lines (264 loc) 9.61 kB
import { Network } from '@caravan/bitcoin'; interface UTXO { txid: string; vout: number; value: number; status: { confirmed: boolean; block_time: number; }; } interface Transaction { txid: string; vin: Input[]; vout: Output[]; size: number; weight: number; fee: number; isSend: boolean; amount: number; block_time: number; } interface Input { prevTxId: string; vout: number; sequence: number; } interface Output { scriptPubkeyHex: string; scriptPubkeyAddress: string; value: number; } interface FeeRatePercentile { avgHeight: number; timestamp: number; avgFee_0: number; avgFee_10: number; avgFee_25: number; avgFee_50: number; avgFee_75: number; avgFee_90: number; avgFee_100: number; } interface TransactionDetails { txid: string; version: number; locktime: number; vin: Array<{ txid: string; vout: number; sequence: number; }>; vout: Array<{ value: number; scriptPubkey: string; scriptPubkeyAddress?: string; }>; size: number; vsize?: number; weight: number; fee: number; status: { confirmed: boolean; blockHeight?: number; blockHash?: string; blockTime?: number; }; isReceived?: boolean; } interface WalletTransactionDetails extends TransactionDetails { amount?: number; confirmations?: number; category?: string; address?: string; abandoned?: boolean; time?: number; } /** * Interface for RPC response structure */ interface RPCResponse<T = unknown> { result: T; error?: { code: number; message: string; }; id: number; } declare function bitcoindImportDescriptors({ url, auth, walletName, receive, change, rescan, }: { url: string; auth: { username: string; password: string; }; walletName?: string; receive: string; change: string; rescan: boolean; }): Promise<RPCResponse<unknown>>; declare enum ClientType { PRIVATE = "private", PUBLIC = "public", MEMPOOL = "mempool", BLOCKSTREAM = "blockstream" } declare enum PublicBitcoinProvider { BLOCKSTREAM = "blockstream", MEMPOOL = "mempool" } declare class ClientBase { private readonly throttled; readonly host: string; constructor(throttled: boolean, host: string); private throttle; private Request; Get(path: string): Promise<any>; Post(path: string, data?: any): Promise<any>; } interface BitcoindClientConfig { url: string; username: string; password: string; walletName?: string; } interface BitcoindParams { url: string; auth: { username: string; password: string; }; walletName?: string; } interface BlockchainClientParams { type: ClientType; provider?: PublicBitcoinProvider; network?: Network; throttled?: boolean; client?: BitcoindClientConfig; } declare class BlockchainClient extends ClientBase { readonly type: ClientType; readonly provider?: PublicBitcoinProvider; readonly network?: Network; readonly bitcoindParams: BitcoindParams; constructor({ type, provider, network, throttled, client, }: BlockchainClientParams); getAddressUtxos(address: string): Promise<any>; getAddressTransactions(address: string): Promise<Transaction[]>; broadcastTransaction(rawTx: string): Promise<any>; formatUtxo(utxo: UTXO): Promise<any>; fetchAddressUtxos(address: string): Promise<any>; getAddressStatus(address: string): Promise<any>; getFeeEstimate(blocks?: number): Promise<any>; getBlockFeeRatePercentileHistory(): Promise<FeeRatePercentile[]>; getTransactionHex(txid: string): Promise<any>; /** * Retrieves transaction history for one or more addresses (public clients only) * * This method is designed for public blockchain explorers (Mempool/Blockstream) that * maintain address indexes, allowing efficient address-specific queries. * * Why this method is PUBLIC CLIENT ONLY: * - Public APIs maintain address indexes for efficient lookups * - Bitcoin Core doesn't support address-specific queries (see getWalletTransactionHistory) * - Allows querying multiple addresses with Promise.all for efficiency * * For PRIVATE clients: Use getWalletTransactionHistory() which returns all wallet transactions * * @param address - Single address or array of addresses to query * @param count - Number of transactions to return per address (1-100) * @param skip - Number of transactions to skip for pagination * @returns Combined array of transactions sorted by time (newest first) * @throws Error if called on private client * * @example * // Single address * const txs = await client.getAddressTransactionHistory("bc1q..."); * * // Multiple addresses * const txs = await client.getAddressTransactionHistory(["bc1q...", "bc1p..."]); * * @see getWalletTransactionHistory - For private clients */ getAddressTransactionHistory(address: string | string[], count?: number, skip?: number): Promise<TransactionDetails[]>; /** * Retrieves transaction history for a Bitcoin Core wallet (private client only) * * This method returns only "send" (spent) transactions from the wallet. This design * decision was made after extensive discussion about Bitcoin Core's limitations: * * 1. Bitcoin Core doesn't maintain an address index for performance/privacy reasons * 2. The `listtransactions` RPC returns ALL wallet transactions with no address filtering * 3. Filtering by address after fetching would be O(n*m) complexity for multiple addresses * * Why this method is PRIVATE CLIENT ONLY: * - Public APIs (Mempool/Blockstream) support direct address querying * - Bitcoin Core requires different approach due to lack of address indexing * - This inconsistency is intentional to optimize for each client type's capabilities * * Why only "send" transactions: * - Unspent "receive" transactions are already available via fetchAddressUtxos() * - Avoids duplication of data that's accessible through UTXO methods * - Focuses on spent transactions which are needed for transaction history * - Coordinator can combine this with UTXO data for complete history * * For PUBLIC clients: Use getAddressTransactionHistory() which supports address filtering * * @param count - Number of transactions to return (1-1000) * @param skip - Number of transactions to skip for pagination * @param includeWatchOnly - Include watch-only addresses in results * @returns Array of spent transactions from the wallet * @throws Error if called on public client or if wallet name is missing * * @example * // For private client - get last 100 spent transactions * const spentTxs = await client.getWalletTransactionHistory(100); * * // For public client - use getAddressTransactionHistory instead * const addressTxs = await client.getAddressTransactionHistory(address); * * @see getAddressTransactionHistory - For public clients * @see fetchAddressUtxos - For unspent transactions */ getWalletTransactionHistory(count?: number, skip?: number, includeWatchOnly?: boolean): Promise<WalletTransactionDetails[]>; /** * Gets detailed information about a wallet transaction including fee information * * This method is specifically for transactions that are tracked by the wallet, * and provides fee information that isn't available in the general getTransaction * method. This is especially useful for private nodes where fee information is * critical for UI display. * * @see https://developer.bitcoin.org/reference/rpc/gettransaction.html * * @param txid - Transaction ID to retrieve * @returns Normalized transaction details with fee information */ getWalletTransaction(txid: string): Promise<TransactionDetails>; getTransaction(txid: string, forceRawTx?: boolean): Promise<TransactionDetails>; importDescriptors({ receive, change, rescan, }: { receive: string; change: string; rescan: boolean; }): Promise<object>; getWalletInfo(): Promise<RPCResponse<unknown>>; /** * Retrieves the fee information for a pending (incoming) transaction . * * Standard methods like `getTransaction` do not provide fee details for transactions * where the user is the recipient. However, this information is required for * fee bumping strategies like CPFP (Child Pays For Parent). * * This method : * - For private nodes: Uses `getmempoolentry` to fetch fee data from the node's mempool * - For public APIs: Uses mempool.space transaction endpoint to get fee information * - Returns null if the transaction is not pending (not in mempool) * * @see https://developer.bitcoin.org/reference/rpc/getmempoolentry.html?highlight=getmempoolentry * @see https://mempool.space/docs/api/rest#get-transaction * * @param txid - Transaction ID to get fees * @returns Tx fees in satoshis, or null if transaction is not pending */ getFeesForPendingTransaction(txid: string): Promise<string | null>; } export { BlockchainClient, ClientType, type FeeRatePercentile, PublicBitcoinProvider, type Transaction, type TransactionDetails, type UTXO, type WalletTransactionDetails, bitcoindImportDescriptors };