class Pochette::BaseTransactionBuilder
Builds transactions from a list of source addresses and a list of recipients. Uses Pochette.backend to fetch unspent outputs and related transaction data. Instantiating will perform all the given queries, you'll be left with a TransactionBuilder object that is either valid? or not, and if valid you can query the results via to_hash.
Attributes
addresses[RW]
errors[RW]
inputs[RW]
options[RW]
outputs[RW]
Public Class Methods
backend()
click to toggle source
# File lib/pochette/base_transaction_builder.rb, line 11 def self.backend raise NotImplementedError end
new(options)
click to toggle source
# File lib/pochette/base_transaction_builder.rb, line 29 def initialize(options) self.backend = options[:backend] if options[:backend] initialize_options(options) initialize_fee initialize_outputs return unless valid? select_utxos add_change_output validate_final_amounts end
Public Instance Methods
as_hash()
click to toggle source
# File lib/pochette/base_transaction_builder.rb, line 48 def as_hash return nil unless valid? { input_total: inputs_amount.to_i, output_total: outputs_amount.to_i, fee: (inputs_amount - outputs_amount).to_i, inputs: inputs, outputs: outputs, utxos_to_blacklist: inputs.collect{|i| [i[1], i[2]] }, } end
valid?()
click to toggle source
# File lib/pochette/base_transaction_builder.rb, line 59 def valid? errors.size == 0 end
Protected Instance Methods
add_change_output()
click to toggle source
# File lib/pochette/base_transaction_builder.rb, line 135 def add_change_output change = inputs_amount - outputs_amount - minimum_fee(fee_for_bytes(output_size)) change_address = options[:change_address] || addresses.first if change > dust_size outputs << [change_address, change.to_i] add_output_fee end end
add_input_fee(count = 1)
click to toggle source
# File lib/pochette/base_transaction_builder.rb, line 83 def add_input_fee(count = 1) @minimum_fee += fee_for_bytes(input_size) * count end
add_output_fee(count = 1)
click to toggle source
# File lib/pochette/base_transaction_builder.rb, line 87 def add_output_fee(count = 1) @minimum_fee += fee_for_bytes(output_size) * count end
fee_for_bytes(bytes)
click to toggle source
# File lib/pochette/base_transaction_builder.rb, line 95 def fee_for_bytes(bytes) bytes.to_d / 1000.to_d * (options[:fee_per_kb] || default_fee_per_kb) end
initialize_fee()
click to toggle source
# File lib/pochette/base_transaction_builder.rb, line 79 def initialize_fee @minimum_fee = fee_for_bytes(10) end
initialize_options(options)
click to toggle source
# File lib/pochette/base_transaction_builder.rb, line 73 def initialize_options(options) self.options = options self.errors ||= [] self.addresses = options[:addresses] end
initialize_outputs()
click to toggle source
# File lib/pochette/base_transaction_builder.rb, line 99 def initialize_outputs self.outputs = options[:outputs] if (outputs.nil? || outputs.empty?) && !options[:spend_all] errors << :try_with_spend_all return end add_output_fee(outputs.size) if outputs.any?{|o| o[1] < dust_size } errors << :dust_in_outputs end end
inputs_amount()
click to toggle source
# File lib/pochette/base_transaction_builder.rb, line 145 def inputs_amount inputs.collect{|x| x[3] }.sum end
minimum_fee(stage=0)
click to toggle source
# File lib/pochette/base_transaction_builder.rb, line 91 def minimum_fee(stage=0) [@minimum_fee + stage, network_minimum_fee].max end
outputs_amount()
click to toggle source
# File lib/pochette/base_transaction_builder.rb, line 149 def outputs_amount outputs.collect(&:last).sum end
select_utxos()
click to toggle source
# File lib/pochette/base_transaction_builder.rb, line 112 def select_utxos utxo_blacklist = options[:utxo_blacklist] || [] all_utxos = backend.list_unspent(addresses) available_utxos = all_utxos.reject do |utxo| utxo_blacklist.include?([utxo[1], utxo[2]]) end self.inputs = [] if options[:spend_all] self.inputs = available_utxos add_input_fee(inputs.size) else needed = outputs.collect{|o| o.last }.sum collected = 0.to_d available_utxos.each do |utxo| break if collected >= needed + minimum_fee collected += utxo[3] self.inputs << utxo add_input_fee end end end
validate_final_amounts()
click to toggle source
# File lib/pochette/base_transaction_builder.rb, line 153 def validate_final_amounts if inputs_amount < (outputs_amount + minimum_fee) errors << :insufficient_funds end end