UNPKG

@btc-stamps/tx-builder

Version:

Transaction builder for Bitcoin Stamps and SRC-20 tokens with advanced UTXO selection

817 lines (800 loc) 27.5 kB
import { U as UTXO } from './provider.interface-53Rg30ZJ.js'; import { I as IUTXOSelector, S as SelectionOptions, E as EnhancedSelectionResult, c as SelectionSuccess, b as SelectorAlgorithm } from './selector.interface-vD2d-t2t.js'; import { I as IProtectionDetector, a as ProtectedAssetData } from './protection.interface-DWbXoL2W.js'; /** * Base UTXO Selector * Common functionality for all selection algorithms */ declare abstract class BaseSelector implements IUTXOSelector { protected readonly DUST_THRESHOLD = 546; protected readonly INPUT_SIZE = 148; protected readonly OUTPUT_SIZE = 34; protected readonly TRANSACTION_OVERHEAD = 10; abstract select(utxos: UTXO[], options: SelectionOptions): EnhancedSelectionResult; abstract getName(): string; /** * Filter UTXOs based on confirmation requirements */ protected filterUTXOs(utxos: UTXO[], minConfirmations?: number): UTXO[]; /** * Filter UTXOs with protection and confirmation checks */ protected filterEligibleUTXOs(utxos: UTXO[], options: SelectionOptions): UTXO[]; /** * Sort UTXOs by value (ascending) */ protected sortByValue(utxos: UTXO[], descending?: boolean): UTXO[]; /** * Sort UTXOs by confirmations (most confirmed first) */ protected sortByConfirmations(utxos: UTXO[]): UTXO[]; /** * Calculate total value of UTXOs */ protected sumUTXOs(utxos: UTXO[]): number; /** * Estimate transaction fee */ estimateFee(numInputs: number, numOutputs: number, feeRate: number): number; /** * Estimate transaction size in vBytes */ protected estimateTransactionSize(numInputs: number, numOutputs: number): number; /** * Check if amount is dust */ protected isDust(amount: number, dustThreshold?: number): boolean; /** * Calculate change amount */ protected calculateChange(inputValue: number, targetValue: number, fee: number): number; /** * Create selection result */ protected createResult(inputs: UTXO[], targetValue: number, feeRate: number, hasChange: boolean): SelectionSuccess; /** * Validate selection options */ protected validateOptions(options: SelectionOptions): void; /** * Check if options are valid and return failure result if not */ protected checkOptionsValidity(options: SelectionOptions): EnhancedSelectionResult | null; /** * Calculate waste metric for coin selection * Lower waste is better */ protected calculateWaste(inputs: UTXO[], targetValue: number, feeRate: number, longTermFeeRate?: number): number; } /** * Knapsack UTXO Selection Algorithm - Legacy stochastic approximation * * The Knapsack selector implements Bitcoin Core's legacy UTXO selection algorithm * (pre-2018) using a stochastic approximation approach. It runs multiple random * iterations to find good solutions, making it highly reliable and capable of * finding valid selections even when more sophisticated algorithms fail. * * @remarks * The algorithm operates through multiple phases: * 1. **Exact Match Search**: First attempts to find precise combinations for changeless transactions * 2. **Stochastic Iteration**: Runs up to 1000 random trials, each selecting UTXOs with 50% probability * 3. **Accumulative Fallback**: If stochastic approach fails, uses simple largest-first accumulation * * Each iteration processes UTXOs from largest to smallest value, randomly including each with * a configurable probability (default 50%). The algorithm tracks the best solution found across * all iterations, preferring selections that minimize excess value over the target amount. * * The algorithm includes intelligent early exit conditions and prefers solutions that avoid * creating dust outputs (change below 1000 satoshis threshold). * * Key features: * - Highly reliable - always finds a solution when sufficient funds are available * - Stochastic approach avoids local optima that deterministic algorithms might encounter * - Configurable iteration count and inclusion probability for fine-tuning * - Built-in exact match optimization for small UTXO combinations * - Dust threshold handling to prevent unspendable change outputs * - Accumulative fallback ensures solution availability * - Maximum input constraints respected throughout selection process * * Performance characteristics: * - Moderate performance, scales well with UTXO set size * - Consistent execution time due to fixed iteration limit * - Less optimal than modern algorithms but more predictable * - Excellent fallback algorithm when others fail due to constraints * * @example * ```typescript * const selector = new KnapsackSelector(); * const result = selector.select(utxos, { * targetValue: 250000, // 250,000 satoshis * feeRate: 20, // 20 sat/vB * maxInputs: 8, // Limit to 8 inputs max * minConfirmations: 1 // Require confirmed UTXOs * }); * * if (result.success) { * console.log(`Selected ${result.inputCount} UTXOs`); * console.log(`Total value: ${result.totalValue} satoshis`); * console.log(`Change: ${result.change} satoshis`); * } * * // Configurable version with custom parameters * const customSelector = new ConfigurableKnapsackSelector({ * iterations: 2000, // More iterations for better results * inclusionProbability: 0.3 // Lower probability for tighter selection * }); * ``` */ declare class KnapsackSelector extends BaseSelector { protected MAX_ITERATIONS: number; private readonly MIN_CHANGE_THRESHOLD; select(utxos: UTXO[], options: SelectionOptions): EnhancedSelectionResult; /** * Try to find an exact match for the target amount plus fees */ private findExactMatch; /** * Simple accumulative selection as fallback */ private accumulativeSelection; /** * Sum values of UTXOs */ private sumValues; getName(): string; } /** * Branch and Bound UTXO Selection Algorithm * Bitcoin Core compatible implementation with efficient O(n²) pruning * Optimized for changeless transactions with 40% target success rate */ /** * Branch and Bound UTXO selection algorithm for optimal coin selection * * @remarks * Implements the Branch and Bound algorithm to find the optimal set of UTXOs * that minimizes transaction fees. This algorithm explores different combinations * to find exact matches or minimal change amounts. * * Features: * - Finds changeless solutions when possible (40% target success rate) * - Minimizes total fees over time using waste metric * - Bitcoin Core compatible implementation * - O(n²) pruning for efficiency * * @example * ```typescript * const selector = new BranchAndBoundSelector(); * const result = selector.select(utxos, { * targetValue: 100000, * feeRate: 10, * changeAddress: 'bc1q...' * }); * ``` */ declare class BranchAndBoundSelector extends BaseSelector { private readonly MAX_ITERATIONS; private readonly MAX_DEPTH; private readonly COST_OF_CHANGE; private readonly LONG_TERM_FEE_RATE; getName(): string; estimateFee(numInputs: number, numOutputs: number, feeRate: number): number; select(utxos: UTXO[], options: SelectionOptions): EnhancedSelectionResult; /** * Find changeless transaction using optimized branch and bound * This is the core algorithm matching Bitcoin Core's implementation */ private findChangelessTransaction; /** * Compute cumulative values for efficient pruning */ private computeCumulativeValues; /** * Recursive branch and bound implementation with efficient pruning */ private branchAndBoundRecursive; /** * Calculate required value for target plus fees */ private calculateRequiredValue; /** * Check if candidate is suitable for changeless transaction */ private isChangelessCandidate; /** * Calculate waste for changeless transactions */ private calculateChangelessWaste; /** * Find best selection when change is needed * Uses a more efficient approach than exhaustive search */ private findBestWithChange; /** * Check if candidate is valid for transaction with change */ private isValidWithChange; /** * Calculate waste for transactions with change */ private calculateWasteWithChange; /** * Fallback to accumulative selection if B&B fails */ private fallbackAccumulative; /** * Simple accumulative selection as ultimate fallback * This method tries to find optimal solutions by considering changeless first */ private simpleAccumulativeSelection; /** * Try to find optimal changeless solutions */ private findOptimalChangeless; /** * Fallback accumulative selection with change */ private fallbackAccumulativeWithChange; /** * Enhanced waste calculation with Bitcoin Core alignment */ protected calculateWaste(inputs: UTXO[], targetValue: number, feeRate: number, longTermFeeRate?: number): number; /** * Get algorithm performance metrics */ getPerformanceMetrics(): { maxIterations: number; maxDepth: number; costOfChange: number; longTermFeeRate: number; }; } /** * Accumulative UTXO Selection Algorithm * Simple selection that accumulates UTXOs until target is met */ /** * Simple accumulative UTXO selection algorithm * * @remarks * Selects UTXOs in order (typically largest first) until the target amount is reached. * This is the simplest and fastest selection algorithm, suitable for most basic transactions. * * Features: * - Fast O(n) selection * - Deterministic results * - Minimal computational overhead * - Good for time-sensitive operations * * @example * ```typescript * const selector = new AccumulativeSelector(); * const result = selector.select(utxos, { * targetValue: 100000, * feeRate: 10 * }); * ``` */ declare class AccumulativeSelector extends BaseSelector { getName(): string; select(utxos: UTXO[], options: SelectionOptions): EnhancedSelectionResult; /** * Variant that prioritizes older UTXOs (FIFO) */ selectFIFO(utxos: UTXO[], options: SelectionOptions): EnhancedSelectionResult; /** * Variant that consolidates UTXOs */ selectForConsolidation(utxos: UTXO[], options: SelectionOptions): EnhancedSelectionResult; /** * Helper method to select from pre-sorted UTXOs */ private selectFromSorted; } /** * Blackjack UTXO Selection Algorithm * Exact value matching algorithm inspired by the card game * Optimized for finding combinations that match target exactly */ /** * Blackjack UTXO Selection Algorithm - Exact value matching optimization * * The Blackjack algorithm is inspired by the card game where the goal is to get as close * to a target value as possible without going over. This selector prioritizes finding UTXO * combinations that exactly match the target amount plus fees, minimizing change outputs * and transaction waste. * * @remarks * The algorithm works in two phases: * 1. **Exact Match Phase**: Systematically searches for combinations that create changeless * transactions (total input = target + fee exactly) * 2. **Closest Match Phase**: If no exact match exists, finds the combination closest to the * target while still covering the required amount * * Key features: * - Prioritizes changeless transactions to minimize fees and UTXO set bloat * - Uses combinatorial search with configurable limits (MAX_COMBINATIONS = 10,000) * - Supports both single-output (no change) and dual-output (with change) transactions * - Implements "exactness" scoring to measure how close combinations are to the target * - Falls back to subset sum dynamic programming for optimization * - Handles dust threshold validation to prevent unspendable outputs * * Performance characteristics: * - Excellent for small to medium UTXO sets (< 20 UTXOs) * - May be slower for large UTXO sets due to combinatorial complexity * - Optimal when exact matches are likely (e.g., consolidation scenarios) * * @example * ```typescript * const selector = new BlackjackSelector(); * const result = selector.select(utxos, { * targetValue: 100000, // 100,000 satoshis * feeRate: 10, // 10 sat/vB * maxInputs: 5, // Limit search space * dustThreshold: 546 // Bitcoin dust threshold * }); * * if (result.success) { * console.log(`Selected ${result.inputCount} UTXOs`); * console.log(`Change: ${result.change} satoshis`); * console.log(`Fee: ${result.fee} satoshis`); * } * ``` */ declare class BlackjackSelector extends BaseSelector { private readonly MAX_COMBINATIONS; private readonly EXACT_MATCH_TOLERANCE; getName(): string; select(utxos: UTXO[], options: SelectionOptions): EnhancedSelectionResult; /** * Find exact match for changeless transaction */ private findExactMatch; /** * Find exact combination of specific size */ private findExactCombination; /** * Find closest match when exact match is not possible */ private findClosestMatch; /** * Find best combination of specific size */ private findBestCombinationOfSize; /** * Generate combinations of UTXOs */ private generateCombinations; /** * Recursive combination generation with limit */ private generateCombinationsRecursive; /** * Calculate binomial coefficient (n choose k) */ private binomialCoefficient; /** * Check if candidate is valid for transaction */ private isValidCandidate; /** * Compare two candidates to determine which is better */ private isBetterCandidate; /** * Optimized selection for specific target amounts * Uses dynamic programming approach for better performance */ selectOptimized(utxos: UTXO[], options: SelectionOptions): EnhancedSelectionResult; /** * Subset sum algorithm for exact matching */ private subsetSum; /** * Get algorithm statistics */ getStats(): { maxCombinations: number; exactMatchTolerance: number; }; } /** * Waste-Optimized UTXO Selection Algorithm * Uses parallel algorithm execution with waste scoring * Combines multiple algorithms and selects the best result based on waste metrics */ interface WasteOptimizationConfig { algorithms: string[]; maxExecutionTime: number; parallelExecution: boolean; wasteWeighting: { changeCost: number; excessCost: number; inputCost: number; }; } /** * Waste-Optimized UTXO Selection Algorithm - Multi-algorithm optimization with waste scoring * * The Waste-Optimized selector is a meta-algorithm that runs multiple UTXO selection algorithms * in parallel and chooses the result with the lowest "waste" score. This approach combines the * strengths of different algorithms to find the most efficient UTXO selection for any given scenario. * * @remarks * The algorithm works by executing multiple selection strategies simultaneously: * 1. **Branch-and-Bound**: Optimal for small UTXO sets, finds mathematically best solutions * 2. **Accumulative**: Fast greedy approach, good for consolidation and large transactions * 3. **Blackjack**: Excels at finding exact matches and minimizing change outputs * * Each result is scored using a comprehensive waste metric that considers: * - **Change Cost**: Fee cost of creating change outputs (34 * feeRate per output) * - **Excess Cost**: Penalty for selecting more value than needed (encourages precision) * - **Input Cost**: Fee overhead from using multiple inputs (68 * feeRate per input * 0.1) * * The selector uses configurable weighting factors to balance these costs based on use case. * Advanced features include timeout protection, detailed error categorization, and * comprehensive performance tracking. * * Key features: * - Parallel execution of multiple algorithms with timeout protection (default 5s) * - Sophisticated waste scoring with configurable weighting factors * - Detailed UTXO filtering with categorization (dust, low confirmations, protected) * - Adaptive algorithm selection based on UTXO set characteristics * - Performance benchmarking and algorithm usage statistics * - Graceful fallback handling when algorithms fail * - Rich error reporting with failure reason categorization * * Performance characteristics: * - Slower than individual algorithms due to parallel execution overhead * - Provides best overall results across diverse scenarios * - Excellent for production systems where optimal selection is critical * - Configurable execution time limits prevent hanging on large UTXO sets * * @example * ```typescript * const selector = new WasteOptimizedSelector({ * algorithms: ['branch-and-bound', 'blackjack', 'accumulative'], * maxExecutionTime: 3000, // 3 second timeout * wasteWeighting: { * changeCost: 1.0, // Full penalty for change outputs * excessCost: 0.5, // Moderate penalty for excess value * inputCost: 0.1 // Light penalty for multiple inputs * } * }); * * const result = selector.select(utxos, { * targetValue: 500000, * feeRate: 15, * maxInputs: 10, * dustThreshold: 546 * }); * * if (result.success) { * console.log(`Best algorithm: ${result.metadata.selectedAlgorithm}`); * console.log(`Waste score: ${result.wasteMetric}`); * console.log(`Execution time: ${result.metadata.executionTime}ms`); * } * ``` */ declare class WasteOptimizedSelector extends BaseSelector { private algorithms; private config; constructor(config?: Partial<WasteOptimizationConfig>); getName(): string; select(utxos: UTXO[], options: SelectionOptions): EnhancedSelectionResult; /** * Run a specific algorithm and return the result with metadata */ private runAlgorithm; /** * Select best result based on waste scoring */ private selectBestResult; /** * Calculate waste metric for an enhanced selection result */ private calculateEnhancedWaste; /** * Calculate detailed waste metrics */ private calculateWasteMetrics; /** * Filter UTXOs that are usable for selection with detailed categorization */ private filterUsableUtxos; /** * Create a structured failure result */ private createFailureResult; /** * Configure the waste optimized selector */ configure(newConfig: Partial<WasteOptimizationConfig>): void; /** * Get current configuration */ getConfiguration(): WasteOptimizationConfig; /** * Add a custom algorithm */ addAlgorithm(name: string, algorithm: BaseSelector): void; /** * Remove an algorithm */ removeAlgorithm(name: string): boolean; /** * Get optimal algorithm recommendation for given UTXOs and options */ getOptimalAlgorithm(utxos: UTXO[], options: SelectionOptions): string; private performanceStats; /** * Get performance statistics */ getPerformanceStats(): { algorithmsCount: number; totalExecutions: number; averageExecutionTime: number; successRate: number; maxExecutionTime: number; parallelExecution: boolean; }; /** * Benchmark algorithms against test data */ benchmark(utxos: UTXO[], options: SelectionOptions, runs?: number): Array<{ algorithm: string; avgWaste: number; avgExecutionTime: number; successRate: number; results: Array<{ success: boolean; wasteScore: number; executionTime: number; }>; }>; /** * Select using adaptive algorithm selection */ selectAdaptive(utxos: UTXO[], options: SelectionOptions): EnhancedSelectionResult; } /** * Mock implementation for testing and development * Allows manual specification of protected UTXOs */ declare class MockProtectionDetector implements IProtectionDetector { private protectedUtxos; private assetData; constructor(protectedUtxos?: string[], assetData?: Map<string, ProtectedAssetData>); isProtectedUtxo(utxo: UTXO): Promise<boolean>; getAssetData(utxo: UTXO): Promise<ProtectedAssetData | null>; addProtectedUtxo(utxoId: string, assetData?: ProtectedAssetData): void; removeProtectedUtxo(utxoId: string): void; clearProtectedUtxos(): void; getProtectedUtxoIds(): string[]; } /** * Protection-aware UTXO selector * * Wraps another selector and filters out UTXOs that contain * valuable ordinals, stamps, or other protected assets. * * Can use different protection strategies: * - Strict: Never use protected UTXOs (safest) * - Careful: Use dummy UTXOs from protected assets if needed * - Emergency: Use any UTXO as last resort (not recommended) */ declare class ProtectionAwareSelector extends BaseSelector { private detector; private fallbackSelector; private allowProtectedIfNecessary; private dummyUtxoAmount; constructor(detector: IProtectionDetector, fallbackSelector: BaseSelector, allowProtectedIfNecessary?: boolean, dummyUtxoAmount?: number); getName(): string; select(utxos: UTXO[], options: SelectionOptions): EnhancedSelectionResult; /** * Check if a specific UTXO is protected */ isProtected(utxo: UTXO): Promise<boolean>; /** * Get asset data for a UTXO */ getAssetData(utxo: UTXO): Promise<ProtectedAssetData | null>; /** * Filter UTXOs into protected and spendable categories */ private categorizeUtxos; /** * Get protection summary for a set of UTXOs */ getProtectionSummary(utxos: UTXO[]): Promise<{ totalUtxos: number; protectedCount: number; spendableCount: number; totalValue: number; protectedValue: number; spendableValue: number; protectedAssets: ProtectedAssetData[]; }>; /** * Set whether to allow protected UTXOs if necessary */ setAllowProtectedIfNecessary(allow: boolean): void; /** * Set the dummy UTXO amount for ordinal protection */ setDummyUtxoAmount(amount: number): void; /** * Get the current fallback selector */ getFallbackSelector(): BaseSelector; /** * Set a new fallback selector */ setFallbackSelector(selector: BaseSelector): void; /** * Get the current protection detector */ getProtectionDetector(): IProtectionDetector; /** * Set a new protection detector */ setProtectionDetector(detector: IProtectionDetector): void; } /** * Tax optimization strategies */ type TaxStrategy = 'FIFO' | 'LIFO' | 'HIFO' | 'LOFO' | 'SPECIFIC_ID'; /** * UTXO metadata for tax calculations */ interface UTXOTaxMetadata { txid: string; vout: number; acquisitionDate: Date; costBasis: number; acquisitionPrice?: number; description?: string; taxLot?: string; } /** * Tax calculation result */ interface TaxCalculation { totalCostBasis: number; totalProceeds: number; realizedGainLoss: number; shortTermGainLoss: number; longTermGainLoss: number; selectedLots: UTXOTaxMetadata[]; } /** * Tax-Optimized UTXO Selection Algorithm * * Selects UTXOs based on tax optimization strategies commonly used * for capital gains calculations in various jurisdictions. * * Strategies: * - FIFO (First In, First Out): Spend oldest UTXOs first * - LIFO (Last In, First Out): Spend newest UTXOs first * - HIFO (Highest In, First Out): Spend highest cost basis first (minimize gains) * - LOFO (Lowest In, First Out): Spend lowest cost basis first (maximize gains) * - SPECIFIC_ID: Manual selection of specific tax lots * * Important for: * - Institutional compliance * - Tax reporting * - Capital gains optimization * - Regulatory requirements */ declare class TaxOptimizedSelector extends BaseSelector { private strategy; private taxMetadata; private currentBTCPrice; private longTermThresholdDays; private fallbackSelector?; protected readonly DUST_THRESHOLD = 546; constructor(options?: { strategy?: TaxStrategy; taxMetadata?: UTXOTaxMetadata[]; currentBTCPrice?: number; longTermThresholdDays?: number; fallbackSelector?: BaseSelector; }); select(utxos: UTXO[], options: SelectionOptions): EnhancedSelectionResult; /** * Sort UTXOs according to tax strategy */ private sortByTaxStrategy; /** * Calculate tax implications of the selection */ private calculateTaxImplications; /** * Calculate fee for selection */ private calculateFee; /** * Get tax optimization report */ getTaxReport(utxos: UTXO[]): TaxCalculation | null; /** * Fallback selection using confirmations as proxy for age */ private selectByConfirmations; getName(): string; } /** * UTXO Selector Factory * Creates selector instances based on algorithm type */ declare class SelectorFactory { private static instance; private selectorCache; private protectionDetector; private taxMetadata; private currentBTCPrice; /** * Get singleton instance */ static getInstance(): SelectorFactory; /** * Configure protection detector for protection-aware selection */ setProtectionDetector(detector: IProtectionDetector): void; /** * Configure tax metadata for tax-optimized selection */ setTaxMetadata(metadata: UTXOTaxMetadata[], btcPrice: number): void; /** * Create selector instance with optional configuration */ create(algorithm: SelectorAlgorithm | string, config?: { protectionDetector?: IProtectionDetector; fallbackSelector?: IUTXOSelector; taxStrategy?: TaxStrategy; taxMetadata?: UTXOTaxMetadata[]; btcPrice?: number; privacyLevel?: 'low' | 'medium' | 'high'; consolidationThreshold?: number; longTermFeeRate?: number; }): IUTXOSelector; /** * Generate cache key for selector with config */ private getCacheKey; /** * Simple hash function for cache keys */ private simpleHash; /** * Get all available algorithms */ getAvailableAlgorithms(): string[]; /** * Get recommended algorithm based on scenario */ getRecommendedAlgorithm(scenario: { utxoCount: number; targetValue: number; feeRate: number; dustThreshold?: number | undefined; }): SelectorAlgorithm; /** * Check if scenario is likely to benefit from exact matching */ private isLikelyExactMatch; /** * Clear selector cache */ clearCache(): void; /** * Get cache statistics */ private isValidSelectorAlgorithm; getCacheStats(): { size: number; algorithms: SelectorAlgorithm[]; }; } export { AccumulativeSelector as A, BaseSelector as B, KnapsackSelector as K, MockProtectionDetector as M, ProtectionAwareSelector as P, SelectorFactory as S, TaxOptimizedSelector as T, WasteOptimizedSelector as W, BranchAndBoundSelector as a, BlackjackSelector as b };