HoosatTxBuilder API Reference
Complete API reference for HoosatTxBuilder - the fluent transaction builder for Hoosat blockchain.
Overview
HoosatTxBuilder provides an intuitive, chainable API for building transactions with:
- Automatic change calculation
- Input/output management
- Built-in validation
- Spam protection compliance
- Fee management
Constructor
new HoosatTxBuilder(options?: TxBuilderOptions)
Create a new transaction builder.
Parameters:
interface TxBuilderOptions {
debug?: boolean; // Enable debug logging (default: false)
}
Example:
const builder = new HoosatTxBuilder({ debug: true });
Building Transactions
addInput(utxo: UtxoForSigning, privateKey?: Buffer)
Add an input to the transaction.
Parameters:
utxo- UTXO to spendprivateKey- Private key for signing this input (optional if signing later)
Returns: this (for chaining)
Example:
// Add input with key
builder.addInput(utxo, wallet.privateKey);
// Add input, sign later
builder.addInput(utxo);
UTXO format:
interface UtxoForSigning {
outpoint: {
transactionId: string;
index: number;
};
utxoEntry: {
amount: string;
scriptPublicKey: {
scriptPublicKey: string;
version: number;
};
blockDaaScore: string;
isCoinbase: boolean;
};
}
addOutput(address: string, amount: string | bigint)
Add an output (recipient).
Parameters:
address- Recipient Hoosat addressamount- Amount in sompi (string or bigint)
Returns: this (for chaining)
Examples:
// Send 1 HTN (100,000,000 sompi)
builder.addOutput('hoosat:qz7ulu...', '100000000');
// Send using bigint
builder.addOutput('hoosat:qz7ulu...', 100000000n);
// Convert HTN to sompi
const sompi = HoosatUtils.amountToSompi('1.5');
builder.addOutput('hoosat:qz7ulu...', sompi);
Validation:
// Validate address before adding
if (HoosatUtils.isValidAddress(address)) {
builder.addOutput(address, amount);
}
addChangeOutput(changeAddress: string)
Add change output (remaining funds back to sender).
Parameters:
changeAddress- Address to send change to (usually sender's address)
Returns: this (for chaining)
Example:
builder.addChangeOutput(wallet.address);
Automatic calculation:
- Change = Total Inputs - Total Outputs - Fee
- If change < 1000 sompi (dust), it's added to fee instead
- Change output is NOT added if resulting amount is dust
setFee(fee: string | bigint)
Set transaction fee.
Parameters:
fee- Fee amount in sompi (string or bigint)
Returns: this (for chaining)
Examples:
// Set fee from string
builder.setFee('1000');
// Set fee from bigint
builder.setFee(1000n);
// Set fee from estimator
const feeEstimate = await feeEstimator.estimateFee(
FeePriority.Normal,
2, // inputs
2 // outputs
);
builder.setFee(feeEstimate.totalFee);
setLockTime(lockTime: string | bigint)
Set transaction lock time.
Parameters:
lockTime- Lock time value (default: 0)
Returns: this (for chaining)
Example:
builder.setLockTime('0');
Note: Lock time is rarely needed for standard transactions.
Signing
sign(globalPrivateKey?: Buffer)
Sign the transaction.
Parameters:
globalPrivateKey- Private key to sign all inputs (optional if keys provided per-input)
Returns: Transaction - Signed transaction ready for submission
Examples:
// Sign with global key
const signedTx = builder.sign(wallet.privateKey);
// Sign if keys were provided per-input
const signedTx = builder.sign();
// Submit signed transaction
const result = await client.submitTransaction(signedTx);
build()
Build transaction without signing.
Returns: Transaction - Unsigned transaction
Example:
const unsignedTx = builder.build();
// Sign manually later
const signedTx = HoosatCrypto.signTransaction(unsignedTx, privateKey);
buildAndSign(globalPrivateKey?: Buffer)
Build and sign in one step (alias for sign()).
Returns: Transaction
Validation
validate()
Validate the transaction before building.
Throws: Error if validation fails
Validation checks:
- At least one input
- At least one output
- Maximum 2 recipient outputs (spam protection)
- Maximum 3 total outputs (2 recipients + 1 change)
- Fee is set
- Sufficient input amount
- Valid addresses
Example:
try {
builder.validate();
const signedTx = builder.sign(wallet.privateKey);
} catch (error) {
console.error('Invalid transaction:', error.message);
}
Note: sign() and build() call validate() automatically.
Information Methods
getTotalInputAmount()
Get total amount from all inputs.
Returns: bigint - Total input amount in sompi
Example:
const totalIn = builder.getTotalInputAmount();
console.log('Total inputs:', HoosatUtils.sompiToAmount(totalIn), 'HTN');
getTotalOutputAmount()
Get total amount from all outputs (excluding change).
Returns: bigint - Total output amount in sompi
Example:
const totalOut = builder.getTotalOutputAmount();
console.log('Total outputs:', HoosatUtils.sompiToAmount(totalOut), 'HTN');
getInputCount()
Get number of inputs.
Returns: number
getOutputCount()
Get number of outputs (including change if added).
Returns: number
estimateFee(feePerByte?: number)
Estimate fee based on transaction size.
Parameters:
feePerByte- Fee rate in sompi/byte (default: 1)
Returns: string - Estimated fee in sompi
Example:
const estimatedFee = builder.estimateFee(10); // 10 sompi/byte
builder.setFee(estimatedFee);
Note: For production use, prefer HoosatFeeEstimator for dynamic network-based fees.
State Management
clear()
Reset the builder to initial state.
Returns: this
Example:
builder.clear(); // Remove all inputs, outputs, reset fee
Use case: Reuse the same builder instance for multiple transactions.
Complete Example
import {
HoosatClient,
HoosatCrypto,
HoosatTxBuilder,
HoosatFeeEstimator,
HoosatUtils,
FeePriority
} from 'hoosat-sdk';
async function buildAndSendTransaction() {
// Setup
const client = new HoosatClient({ host: '54.38.176.95', port: 42420 });
const wallet = HoosatCrypto.generateKeyPair();
// Get UTXOs
const utxosResult = await client.getUtxosByAddresses([wallet.address]);
const utxos = utxosResult.result.utxos;
// Estimate fee
const feeEstimator = new HoosatFeeEstimator(client);
const feeEstimate = await feeEstimator.estimateFee(
FeePriority.Normal,
utxos.length, // inputs
2 // outputs
);
// Build transaction
const builder = new HoosatTxBuilder();
// Add all UTXOs as inputs
for (const utxo of utxos) {
builder.addInput(utxo, wallet.privateKey);
}
// Add recipient output
builder.addOutput(
'hoosat:qz95mwas8ja7ucsernv9z335rdxxqswff7wvzenl29qukn5qs3lsqfsa4pd74',
HoosatUtils.amountToSompi('0.1') // Send 0.1 HTN
);
// Set fee
builder.setFee(feeEstimate.totalFee);
// Add change
builder.addChangeOutput(wallet.address);
// Check amounts
console.log('Total in:', HoosatUtils.sompiToAmount(builder.getTotalInputAmount()), 'HTN');
console.log('Total out:', HoosatUtils.sompiToAmount(builder.getTotalOutputAmount()), 'HTN');
console.log('Fee:', HoosatUtils.sompiToAmount(feeEstimate.totalFee), 'HTN');
// Sign and submit
const signedTx = builder.sign();
const result = await client.submitTransaction(signedTx);
if (result.ok) {
console.log('Success! TX ID:', result.result.transactionId);
} else {
console.error('Failed:', result.error);
}
}
Spam Protection
Hoosat inherits spam protection from Kaspa:
Hard limits:
- Maximum 2 recipient outputs per transaction
- Maximum 3 total outputs (2 recipients + 1 change)
Examples:
// Valid - 1 recipient + change
builder
.addInput(utxo1, privateKey)
.addOutput('recipient1', '100000000')
.addChangeOutput(myAddress); // Total: 2 outputs
// Valid - 2 recipients + change
builder
.addInput(utxo1, privateKey)
.addOutput('recipient1', '100000000')
.addOutput('recipient2', '50000000')
.addChangeOutput(myAddress); // Total: 3 outputs
// Invalid - 3 recipients (will throw error)
builder
.addInput(utxo1, privateKey)
.addOutput('recipient1', '100000000')
.addOutput('recipient2', '50000000')
.addOutput('recipient3', '25000000'); // ERROR!
Sending to 3+ recipients: Use batch payments (multiple transactions)
See: Batch Payments Guide
Error Handling
Common errors:
Insufficient funds:
// Total outputs + fee > Total inputs
// Solution: Add more UTXOs or reduce send amount
Too many recipients:
// More than 2 recipient outputs
// Solution: Use batch payments
Invalid address:
// Malformed recipient address
// Solution: Validate with HoosatUtils.isValidAddress()
Missing fee:
// Fee not set
// Solution: Call setFee()
Advanced Patterns
UTXO Selection
// Select UTXOs strategically
const sorted = utxos.sort((a, b) =>
Number(BigInt(b.utxoEntry.amount) - BigInt(a.utxoEntry.amount))
);
// Add largest UTXOs first
for (const utxo of sorted) {
builder.addInput(utxo, wallet.privateKey);
// Stop when we have enough
if (builder.getTotalInputAmount() >= neededAmount) {
break;
}
}
Dynamic Fee Adjustment
// Build transaction to calculate size
builder.addInput(utxo, privateKey);
builder.addOutput(recipient, amount);
// Get actual size-based fee
const fee = builder.estimateFee(feeRate);
// Rebuild with correct fee
builder.clear();
builder.addInput(utxo, privateKey);
builder.addOutput(recipient, amount);
builder.setFee(fee);
builder.addChangeOutput(myAddress);
Next Steps
- HoosatFeeEstimator - Dynamic fee estimation
- Transaction Guide - Detailed transaction guide
- Batch Payments - Sending to multiple recipients