Skip to content

Class BSV::Wallet::ChangeGenerator

Inherits: Object

Generates BRC-29 change outputs for excess satoshis in a transaction.

Handles the full lifecycle of change output creation: - Dust-floor enforcement (a change output is only worthwhile if its value covers at least 2× the cost to spend it later) - Optional distribution across multiple outputs with randomised splits - BRC-29 key derivation metadata attached to each output so the wallet can later identify and spend the change

@example Single change output

generator = BSV::Wallet::ChangeGenerator.new(key_deriver: deriver, fee_estimator: estimator)
outputs = generator.generate(excess_satoshis: 5000)
# => [{ satoshis: 5000, locking_script: ..., derivation_prefix: ..., ... }]

@example Spread across multiple outputs

generator = BSV::Wallet::ChangeGenerator.new(key_deriver: deriver, fee_estimator: estimator, max_outputs: 4)
outputs = generator.generate(excess_satoshis: 10_000)
# => up to 4 outputs summing to 10_000

Constants

BRC29_PROTOCOL_ID

BRC-29 protocol identifier used for change key derivation.

Attributes

max_outputs [R]

  • @return [Integer] maximum number of change outputs that may be created

Public Instance Methods

generate(excess_satoshis:, num_existing_outputs: = 0, pool_size: = nil, change_params: = nil)

Generates change outputs for the given excess satoshis.

Returns an empty array when the excess is zero or below the dust floor. Otherwise returns between 1 and {#max_outputs} output hashes, each with: - +:satoshis+ — value of the output - +:locking_script+ — P2PKH locking script for the derived key - +:derivation_prefix+ — random hex string for BRC-29 key derivation - +:derivation_suffix+ — random hex string for BRC-29 key derivation - +:sender_identity_key+ — wallet's own identity key (self-payment)

When pool_size: and change_params: are both provided, the number of change outputs is adjusted based on the pool's health: - Pool below target count: produce more outputs (up to +max_outputs+) to build up the UTXO pool. - Pool at or above target count: produce fewer outputs (1-2) to avoid unnecessary fragmentation. - @param excess_satoshis [Integer] satoshis remaining after inputs minus outputs minus fee - @param num_existing_outputs [Integer] number of outputs already in the transaction (unused here but kept for interface symmetry with future callers) - @param pool_size [Integer, nil] current number of spendable UTXOs in the pool - @param change_params [Hash, nil] pool targets with +:count+ and +:satoshis+ keys - @return [Array] change output descriptors (may be empty)

initialize(key_deriver:, fee_estimator: = nil, fee_model: = nil, identity_key: = nil, max_outputs: = 8)

  • @param key_deriver [BSV::Wallet::KeyDeriver] derives child keys for each change output
  • @param fee_estimator [BSV::Wallet::FeeEstimator] used to compute the dust floor (also accepted as +fee_model:+ for backwards compatibility)
  • @param identity_key [String, nil] override identity key for change derivation; defaults to key_deriver.identity_key when nil
  • @param max_outputs [Integer] upper bound on change outputs (default: 8)
  • @raise [ArgumentError] if max_outputs is less than 1
  • @return [ChangeGenerator] a new instance of ChangeGenerator