Module: BSV::Wallet::Interface::UTXOPool

Defined in:
lib/bsv/wallet/interface/utxo_pool.rb

Overview

UTXO selection strategy for transaction construction.

The pool recommends which outputs to spend. The actual locking happens in Store#create_action (Phase 1) via INSERT INTO inputs with ON CONFLICT — the database enforces single-spend atomically.

Three tiers of implementation, same interface:

Tier 1 (default): delegates to Store#find_spendable — a database query on every call. Fine for single-user, low-frequency use.

Tier 2 (pre-split): selects from a dedicated basket. Still a database query, but scoped to a smaller set with less contention.

Tier 3 (TxCache): dequeues from a pre-warmed in-memory queue. The hot path is pure memory — no database query, no lock contention, sub-millisecond latency.

Instance Method Summary collapse

Instance Method Details

#balanceInteger

Total available (unreserved) balance in satoshis.

Returns:

  • (Integer)

Raises:

  • (NotImplementedError)


57
58
59
# File 'lib/bsv/wallet/interface/utxo_pool.rb', line 57

def balance
  raise NotImplementedError
end

#change_output_countInteger

How many change outputs the next transaction should create.

Uses a sizing formula to grow the pool toward a target count:

target = min(max_utxo_count, balance / min_utxo_sats)
deficit = target - spendable_count
result = clamp(deficit, 1, max_change_per_tx)

Always returns at least 1 (remainder has to go somewhere). Capped per transaction to avoid bloating any single tx.

Returns:

  • (Integer)

    number of change outputs to create (>= 1)

Raises:

  • (NotImplementedError)


79
80
81
# File 'lib/bsv/wallet/interface/utxo_pool.rb', line 79

def change_output_count
  raise NotImplementedError
end

#release(outputs:) ⇒ Object

Release outputs back to the pool after a failed or aborted action.

For tier 1/2: no-op — the Store’s CASCADE delete on abort frees the input rows, and the outputs were never reserved here.

For tier 3: re-enqueues outputs into the in-memory queue.

Parameters:

  • outputs (Array<Hash>)

    the outputs originally returned by #select

Raises:

  • (NotImplementedError)


50
51
52
# File 'lib/bsv/wallet/interface/utxo_pool.rb', line 50

def release(outputs:)
  raise NotImplementedError
end

#select(satoshis:, exclude: []) ⇒ Array<Hash>

Select candidate outputs for spending.

Returns output data sufficient for transaction construction. These candidates are NOT locked — locking happens when the Store creates the action and its input rows.

For tier 3, the dequeue IS the reservation — the output leaves the in-memory queue and won’t be offered to concurrent callers.

Parameters:

  • satoshis (Integer)

    minimum total value needed

  • exclude (Array<Integer>) (defaults to: [])

    output IDs to skip (e.g. from a retry)

Returns:

  • (Array<Hash>)

    candidates: :id, :satoshis, :vout, :locking_script, :action_id, :derivation_prefix, :derivation_suffix

Raises:



38
39
40
# File 'lib/bsv/wallet/interface/utxo_pool.rb', line 38

def select(satoshis:, exclude: [])
  raise NotImplementedError
end

#spendable_countInteger

Number of spendable outputs currently in the pool.

Returns:

  • (Integer)

Raises:

  • (NotImplementedError)


64
65
66
# File 'lib/bsv/wallet/interface/utxo_pool.rb', line 64

def spendable_count
  raise NotImplementedError
end