/**
* Blockchain API - Phase 6.3
*
* Wrapper around WDK blockchain queries.
* Provides unified interface for querying UTXOs, transactions, and fees.
*/
/**
* Query UTXOs for a Bitcoin address
* @param {Object} btcWallet - WDK Bitcoin wallet instance
* @param {string} address - Bitcoin address (tb1q... for testnet)
* @returns {Array} Array of UTXO objects
*/
async function getUTXOsForAddress(btcWallet, address) {
try {
const utxos = await btcWallet.getUTXOs(address)
// Normalize UTXO format
return utxos.map(utxo => ({
txid: utxo.txid,
vout: utxo.vout,
address: address,
value: utxo.value, // satoshis
scriptPubKey: utxo.scriptPubKey || null,
confirmations: utxo.confirmations || 0,
blockHeight: utxo.height || null
}))
} catch (err) {
console.error(`Error fetching UTXOs for ${address}:`, err.message)
return []
}
}
/**
* Query UTXOs for multiple addresses
* @param {Object} btcWallet - WDK Bitcoin wallet instance
* @param {Array} addresses - Array of address strings
* @returns {Array} Combined array of UTXOs from all addresses
*/
async function getUTXOsForAddresses(btcWallet, addresses) {
const allUTXOs = []
for (const address of addresses) {
const utxos = await getUTXOsForAddress(btcWallet, address)
allUTXOs.push(...utxos)
}
return allUTXOs
}
/**
* Get current fee rates from network
* @param {Object} btcWallet - WDK Bitcoin wallet instance
* @returns {Object} Fee rates in sat/vbyte
*/
async function getFeeRates(btcWallet) {
try {
const rates = await btcWallet.getFeeRates()
return {
low: rates.low || 1,
medium: rates.medium || 5,
high: rates.high || 10
}
} catch (err) {
console.error('Error fetching fee rates:', err.message)
// Return default rates on error
return {
low: 1,
medium: 5,
high: 10
}
}
}
/**
* Get transaction details from blockchain
* @param {Object} btcWallet - WDK Bitcoin wallet instance
* @param {string} txid - Transaction ID
* @returns {Object|null} Transaction details or null if not found
*/
async function getTransaction(btcWallet, txid) {
try {
const tx = await btcWallet.getTransaction(txid)
return {
txid: tx.txid,
confirmations: tx.confirmations || 0,
blockHeight: tx.blockHeight || null,
blockHash: tx.blockHash || null,
timestamp: tx.timestamp || null,
inputs: tx.inputs || [],
outputs: tx.outputs || [],
fee: tx.fee || null
}
} catch (err) {
console.error(`Error fetching transaction ${txid}:`, err.message)
return null
}
}
/**
* Get balance for a single address (direct query)
* @param {Object} btcWallet - WDK Bitcoin wallet instance
* @param {string} address - Bitcoin address
* @returns {number} Balance in satoshis
*/
async function getAddressBalance(btcWallet, address) {
try {
const balance = await btcWallet.getBalance(address)
return balance || 0
} catch (err) {
console.error(`Error fetching balance for ${address}:`, err.message)
return 0
}
}
/**
* Broadcast transaction to network
* @param {Object} btcWallet - WDK Bitcoin wallet instance
* @param {string} txHex - Signed transaction hex
* @returns {Object} Broadcast result
*/
async function broadcastTransaction(btcWallet, txHex) {
try {
const result = await btcWallet.broadcast(txHex)
return {
success: true,
txid: result.txid,
message: 'Transaction broadcasted successfully'
}
} catch (err) {
return {
success: false,
error: err.message,
message: 'Failed to broadcast transaction'
}
}
}
/**
* Check if blockchain API is reachable
* @param {Object} btcWallet - WDK Bitcoin wallet instance
* @returns {boolean} True if API is reachable
*/
async function checkConnection(btcWallet) {
try {
// Try to get fee rates as a connectivity check
await btcWallet.getFeeRates()
return true
} catch (err) {
return false
}
}
module.exports = {
getUTXOsForAddress,
getUTXOsForAddresses,
getFeeRates,
getTransaction,
getAddressBalance,
broadcastTransaction,
checkConnection
}