Class: BSV::Wallet::ChangeGenerator
- Inherits:
-
Object
- Object
- BSV::Wallet::ChangeGenerator
- Defined in:
- lib/bsv/wallet_interface/change_generator.rb
Overview
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
Constant Summary collapse
- BRC29_PROTOCOL_ID =
BRC-29 protocol identifier used for change key derivation.
[2, '3241645161d8'].freeze
Instance Attribute Summary collapse
-
#max_outputs ⇒ Integer
readonly
Maximum number of change outputs that may be created.
Instance Method Summary collapse
-
#generate(excess_satoshis:, num_existing_outputs: 0, pool_size: nil, change_params: nil) ⇒ Array<Hash>
Generates change outputs for the given excess satoshis.
-
#initialize(key_deriver:, fee_estimator: nil, fee_model: nil, identity_key: nil, max_outputs: 8) ⇒ ChangeGenerator
constructor
A new instance of ChangeGenerator.
Constructor Details
#initialize(key_deriver:, fee_estimator: nil, fee_model: nil, identity_key: nil, max_outputs: 8) ⇒ ChangeGenerator
Returns a new instance of ChangeGenerator.
39 40 41 42 43 44 45 46 47 |
# File 'lib/bsv/wallet_interface/change_generator.rb', line 39 def initialize(key_deriver:, fee_estimator: nil, fee_model: nil, identity_key: nil, max_outputs: 8) raise ArgumentError, 'max_outputs must be at least 1' unless max_outputs >= 1 raise ArgumentError, 'provide fee_estimator: or fee_model:, not both' if fee_estimator && fee_model @key_deriver = key_deriver @fee_model = fee_estimator || fee_model || raise(ArgumentError, 'fee_estimator: (or fee_model:) is required') @identity_key_override = identity_key @max_outputs = max_outputs end |
Instance Attribute Details
#max_outputs ⇒ Integer (readonly)
Returns maximum number of change outputs that may be created.
30 31 32 |
# File 'lib/bsv/wallet_interface/change_generator.rb', line 30 def max_outputs @max_outputs end |
Instance Method Details
#generate(excess_satoshis:, num_existing_outputs: 0, pool_size: nil, change_params: nil) ⇒ Array<Hash>
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.
72 73 74 75 76 77 78 79 |
# File 'lib/bsv/wallet_interface/change_generator.rb', line 72 def generate(excess_satoshis:, num_existing_outputs: 0, pool_size: nil, change_params: nil) # rubocop:disable Lint/UnusedMethodArgument return [] if excess_satoshis <= 0 return [] if excess_satoshis < dust_floor effective_max = pool_aware_max_outputs(pool_size, change_params) amounts = split_amounts(excess_satoshis, effective_max) amounts.map { |amount| build_output(amount) } end |