@xchainjs/xchain-utxo 2.0.10 → 2.1.0

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/lib/client.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import { BaseXChainClient, ExplorerProviders, FeeEstimateOptions, FeeRate, FeeRates, Fees, FeesWithRates, Protocol, TxHash, TxHistoryParams } from '@xchainjs/xchain-client';
2
2
  import { Address, Asset, Chain } from '@xchainjs/xchain-util';
3
3
  import { UtxoOnlineDataProviders } from '@xchainjs/xchain-utxo-providers';
4
- import { Balance, Tx, TxParams, TxsPage, UTXO, UtxoClientParams } from './types';
4
+ import { Balance, PreparedTx, Tx, TxParams, TxsPage, UTXO, UtxoClientParams } from './types';
5
+ import { UtxoSelectionPreferences, UtxoSelectionResult } from './strategies';
5
6
  /**
6
7
  * Abstract base class for creating blockchain clients in the UTXO model.
7
8
  */
@@ -139,18 +140,117 @@ export declare abstract class Client extends BaseXChainClient {
139
140
  * @throws {Error} Throws an error if no provider is able to broadcast the transaction.
140
141
  */
141
142
  protected roundRobinBroadcastTx(txHex: string): Promise<string>;
143
+ /**
144
+ * Enhanced UTXO selection using the UtxoSelector with multiple strategies.
145
+ * This method is available to all UTXO chain implementations.
146
+ *
147
+ * @param utxos Available UTXOs to select from
148
+ * @param targetValue Target amount in satoshis
149
+ * @param feeRate Fee rate in satoshis per byte
150
+ * @param extraOutputs Number of extra outputs (default: 2 for recipient + change)
151
+ * @param preferences Selection preferences
152
+ * @returns Selection result with inputs, change, and fee
153
+ */
154
+ protected selectUtxosForTransaction(utxos: UTXO[], targetValue: number, feeRate: number, extraOutputs?: number, preferences?: UtxoSelectionPreferences): UtxoSelectionResult;
155
+ /**
156
+ * Validate transaction inputs using comprehensive validation.
157
+ * Chain implementations can override to add chain-specific validation.
158
+ *
159
+ * @param params Transaction parameters including sender and feeRate
160
+ */
161
+ protected validateTransactionInputs(params: TxParams & {
162
+ sender: Address;
163
+ feeRate: FeeRate;
164
+ }): void;
165
+ /**
166
+ * Calculate maximum sendable amount by using ALL available UTXOs.
167
+ *
168
+ * For a true sweep operation, we use all UTXOs to maximize the sent amount.
169
+ * This is simpler and more correct than binary search with UTXO selection.
170
+ *
171
+ * @param utxos Available UTXOs
172
+ * @param feeRate Fee rate in satoshis per byte
173
+ * @param hasMemo Whether transaction has a memo
174
+ * @param preferences UTXO selection preferences
175
+ * @returns Maximum sendable amount, fee, and selected inputs
176
+ */
177
+ protected calculateMaxSendableAmount(utxos: UTXO[], feeRate: number, hasMemo: boolean, preferences?: UtxoSelectionPreferences): {
178
+ amount: number;
179
+ fee: number;
180
+ inputs: UTXO[];
181
+ };
182
+ /**
183
+ * Get and validate UTXOs for transaction building.
184
+ *
185
+ * @param sender Sender address
186
+ * @param confirmedOnly Whether to only use confirmed UTXOs
187
+ * @returns Validated UTXO array
188
+ */
189
+ protected getValidatedUtxos(sender: Address, confirmedOnly: boolean): Promise<UTXO[]>;
190
+ /**
191
+ * Prepare transaction with enhanced UTXO selection.
192
+ * Chain implementations should override buildTxPsbt to provide chain-specific PSBT construction.
193
+ *
194
+ * @param params Transaction parameters
195
+ * @returns Prepared transaction with UTXO details
196
+ */
197
+ prepareTxEnhanced({ sender, memo, amount, recipient, spendPendingUTXO, feeRate, utxoSelectionPreferences, }: TxParams & {
198
+ sender: Address;
199
+ feeRate: FeeRate;
200
+ spendPendingUTXO?: boolean;
201
+ utxoSelectionPreferences?: UtxoSelectionPreferences;
202
+ }): Promise<PreparedTx>;
203
+ /**
204
+ * Prepare maximum amount transfer (sweep transaction).
205
+ *
206
+ * @param params Send max parameters
207
+ * @returns Prepared transaction with maximum sendable amount
208
+ */
209
+ prepareMaxTx({ sender, recipient, memo, feeRate, spendPendingUTXO, utxoSelectionPreferences, }: {
210
+ sender: Address;
211
+ recipient: Address;
212
+ memo?: string;
213
+ feeRate: FeeRate;
214
+ spendPendingUTXO?: boolean;
215
+ utxoSelectionPreferences?: UtxoSelectionPreferences;
216
+ }): Promise<PreparedTx & {
217
+ maxAmount: number;
218
+ fee: number;
219
+ }>;
220
+ /**
221
+ * Abstract method to validate an address for this chain.
222
+ * @param address The address to validate
223
+ * @returns true if valid, false otherwise
224
+ */
225
+ abstract validateAddress(address: string): boolean;
142
226
  /**
143
227
  * Abstract method to compile a memo.
144
- * @param {string} memo The memo string to compile.
145
- * @returns {Buffer} The compiled memo.
228
+ * @param memo The memo string to compile.
229
+ * @returns The compiled memo.
146
230
  */
147
231
  protected abstract compileMemo(memo: string): Buffer;
232
+ /**
233
+ * Build a PSBT for this chain.
234
+ * Chain implementations should override this to provide chain-specific PSBT construction.
235
+ * Default implementation throws - override in chain client to enable enhanced methods.
236
+ *
237
+ * @param params PSBT build parameters
238
+ * @returns Base64-encoded PSBT string
239
+ */
240
+ protected buildTxPsbt(_params: {
241
+ inputs: UTXO[];
242
+ recipient: Address;
243
+ amount: number;
244
+ changeAmount: number;
245
+ changeAddress: Address;
246
+ memo: Buffer | null;
247
+ }): Promise<string>;
148
248
  /**
149
249
  * Abstract method to calculate the fee from a list of UTXOs.
150
- * @param {UTXO[]} inputs The list of UTXOs.
151
- * @param {FeeRate} feeRate The fee rate.
152
- * @param {Buffer | null} data Optional data buffer.
153
- * @returns {number} The calculated fee.
250
+ * @param inputs The list of UTXOs.
251
+ * @param feeRate The fee rate.
252
+ * @param data Optional data buffer.
253
+ * @returns The calculated fee.
154
254
  */
155
255
  protected abstract getFeeFromUtxos(inputs: UTXO[], feeRate: FeeRate, data: Buffer | null): number;
156
256
  /**
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Standard UTXO constants used across the library
3
+ */
4
+ /**
5
+ * Bitcoin's standard dust threshold (546 satoshis)
6
+ *
7
+ * This is the minimum value for a UTXO to be considered economically spendable.
8
+ * The value comes from Bitcoin Core's calculation:
9
+ * - P2PKH output size: 34 bytes
10
+ * - Cost to spend: 34 bytes × 3 sat/byte = 102 satoshis
11
+ * - Dust threshold: 102 × 3 = 306 satoshis (theoretical)
12
+ * - Bitcoin Core uses 546 for safety margin and worst-case scenarios
13
+ *
14
+ * Note: Different UTXO chains may have different dust thresholds
15
+ */
16
+ export declare const DUST_THRESHOLD = 546;
17
+ /**
18
+ * Transaction size constants for fee calculation
19
+ */
20
+ export declare const TX_SIZE_CONSTANTS: {
21
+ /** Base transaction overhead in virtual bytes */
22
+ readonly BASE_TX_SIZE: 10;
23
+ /** Approximate virtual bytes per P2WPKH input */
24
+ readonly BYTES_PER_INPUT: 68;
25
+ /** Virtual bytes per P2WPKH output */
26
+ readonly BYTES_PER_OUTPUT: 31;
27
+ };
28
+ /**
29
+ * Maximum reasonable amount (21M BTC equivalent in satoshis)
30
+ * Used as a sanity check for transaction amounts
31
+ */
32
+ export declare const MAX_REASONABLE_AMOUNT = "2100000000000000";
33
+ /**
34
+ * Maximum decimal precision for UTXO-based cryptocurrencies
35
+ *
36
+ * Most UTXO chains (Bitcoin, Litecoin, Dogecoin, etc.) use 8 decimal places:
37
+ * - 1 BTC = 100,000,000 satoshis (10^8)
38
+ * - 1 LTC = 100,000,000 litoshi (10^8)
39
+ * - 1 DOGE = 100,000,000 koinu (10^8)
40
+ *
41
+ * This differs from Ethereum tokens which can have up to 18 decimals
42
+ */
43
+ export declare const MAX_UTXO_DECIMALS = 8;
@@ -0,0 +1,91 @@
1
+ /**
2
+ * UTXO-specific error codes for better error handling and debugging
3
+ */
4
+ export declare enum UtxoErrorCode {
5
+ INSUFFICIENT_BALANCE = "INSUFFICIENT_BALANCE",
6
+ INVALID_ADDRESS = "INVALID_ADDRESS",
7
+ INVALID_AMOUNT = "INVALID_AMOUNT",
8
+ INVALID_FEE_RATE = "INVALID_FEE_RATE",
9
+ INVALID_MEMO = "INVALID_MEMO",
10
+ INVALID_UTXO = "INVALID_UTXO",
11
+ PROVIDER_ERROR = "PROVIDER_ERROR",
12
+ NETWORK_ERROR = "NETWORK_ERROR",
13
+ VALIDATION_ERROR = "VALIDATION_ERROR",
14
+ TRANSACTION_TOO_LARGE = "TRANSACTION_TOO_LARGE",
15
+ UTXO_SELECTION_FAILED = "UTXO_SELECTION_FAILED",
16
+ BROADCAST_ERROR = "BROADCAST_ERROR",
17
+ SIGNING_ERROR = "SIGNING_ERROR"
18
+ }
19
+ /**
20
+ * Enhanced error class for UTXO operations with detailed context
21
+ */
22
+ export declare class UtxoError extends Error {
23
+ readonly code: UtxoErrorCode;
24
+ readonly details?: Record<string, unknown> | undefined;
25
+ readonly isUtxoError = true;
26
+ constructor(code: UtxoErrorCode, message: string, details?: Record<string, unknown> | undefined);
27
+ /**
28
+ * Create an insufficient balance error
29
+ */
30
+ static insufficientBalance(required: string, available: string, chain?: string): UtxoError;
31
+ /**
32
+ * Create an invalid address error
33
+ */
34
+ static invalidAddress(address: string, network?: string): UtxoError;
35
+ /**
36
+ * Create an invalid amount error
37
+ */
38
+ static invalidAmount(amount: string | number, reason?: string): UtxoError;
39
+ /**
40
+ * Create an invalid fee rate error
41
+ */
42
+ static invalidFeeRate(feeRate: number, reason?: string): UtxoError;
43
+ /**
44
+ * Create an invalid memo error
45
+ */
46
+ static invalidMemo(memo: string, reason: string): UtxoError;
47
+ /**
48
+ * Create a provider error
49
+ */
50
+ static providerError(providerName: string, originalError: Error): UtxoError;
51
+ /**
52
+ * Create a network error
53
+ */
54
+ static networkError(operation: string, originalError: Error): UtxoError;
55
+ /**
56
+ * Create a validation error
57
+ */
58
+ static validationError(message: string, details?: Record<string, unknown>): UtxoError;
59
+ /**
60
+ * Create a transaction too large error
61
+ */
62
+ static transactionTooLarge(currentSize: number, maxSize: number): UtxoError;
63
+ /**
64
+ * Create a UTXO selection failed error
65
+ */
66
+ static utxoSelectionFailed(targetAmount: number, availableAmount: number, strategy?: string): UtxoError;
67
+ /**
68
+ * Create a broadcast error
69
+ */
70
+ static broadcastError(txHash: string, originalError: Error): UtxoError;
71
+ /**
72
+ * Create a signing error
73
+ */
74
+ static signingError(reason: string, details?: Record<string, unknown>): UtxoError;
75
+ /**
76
+ * Convert unknown errors to typed UTXO errors
77
+ */
78
+ static fromUnknown(error: unknown, context?: string): UtxoError;
79
+ /**
80
+ * Check if an error is a UTXO error
81
+ */
82
+ static isUtxoError(error: unknown): error is UtxoError;
83
+ /**
84
+ * Get a user-friendly error message
85
+ */
86
+ getUserFriendlyMessage(): string;
87
+ /**
88
+ * Convert to JSON for logging
89
+ */
90
+ toJSON(): Record<string, unknown>;
91
+ }
package/lib/index.d.ts CHANGED
@@ -6,3 +6,8 @@ import { Balance, PreparedTx, Tx, TxFrom, TxParams, TxTo, TxsPage, UTXO, UtxoCli
6
6
  */
7
7
  export { Client, toBitcoinJS };
8
8
  export type { UTXO, UtxoClientParams, Witness, PreparedTx, Balance, Tx, TxsPage, TxParams, TxTo, TxFrom };
9
+ export { UtxoError, UtxoErrorCode } from './errors';
10
+ export { UtxoTransactionValidator } from './validators';
11
+ export { UtxoSelector } from './utxo-selector';
12
+ export * from './strategies';
13
+ export * from './constants';