Module: CoinOp::Bit::Fee
- Defined in:
- lib/coin-op/bit/fee.rb
Constant Summary collapse
- AVG_P2PKH_BYTES =
From bitcoinfees.com
148
- AVG_OUTPUT_SIZE =
34
- AVG_P2SH_BYTES =
From rough tests of Gem p2sh txs on 2015-09-08
300
- PRIORITY_THRESHOLD =
en.bitcoin.it/wiki/Transaction_fees#Including_in_Blocks
en.bitcoin.it/wiki/Transaction_fees#Technical_info > Transactions need to have a priority above 57,600,000 to avoid the > enforced limit.… This threshold is written in the code as > COIN * 144 / 250, suggesting that the threshold represents a one day > old, 1 btc coin (144 is the expected number of blocks per day) and a > transaction size of 250 bytes.
57_600_000
Class Method Summary collapse
-
.estimate(unspents, payees, network:, tx_size: nil, fee_per_kb: nil) ⇒ Object
Given an array of unspent Outputs and an array of Outputs for a Transaction, estimate the fee required for the transaction to be included in a block.
- .estimate_tx_size(inputs, outputs) ⇒ Object
- .fee_for_bytes(bytes, network:, fee_per_kb: nil) ⇒ Object
- .priority(params) ⇒ Object
Class Method Details
.estimate(unspents, payees, network:, tx_size: nil, fee_per_kb: nil) ⇒ Object
Given an array of unspent Outputs and an array of Outputs for a Transaction, estimate the fee required for the transaction to be included in a block.
Optionally takes an Integer tx_size specifying the transaction size in bytes
This is useful if you have the scriptSigs for the unspents, because
you can get a more accurate size than the estimate which is generated
here by default
Optionally takes an Integer fee_per_kb specifying the chosen cost per 1000
bytes to use
Returns the estimated fee in satoshis.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/coin-op/bit/fee.rb', line 28 def estimate(unspents, payees, network:, tx_size: nil, fee_per_kb: nil) # https://en.bitcoin.it/wiki/Transaction_fees # dupe because we'll need to add a change output payees = payees.dup unspent_total = unspents.inject(0) { |sum, output| sum += output.value } payee_total = payees.inject(0) { |sum, payee| sum += payee.value } nominal_change = unspent_total - payee_total payees << Output.new(value: nominal_change, network: network) if nominal_change > 0 tx_size ||= estimate_tx_size(unspents, payees) # conditions for 0-fee transactions small = tx_size < 1000 min_payee = payees.min_by { |payee| payee.value } big_outputs = min_payee.value > 1_000_000 high_priority = priority( size: tx_size, unspents: unspents.map { |output| { value: output.value, age: output.confirmations } } ) > PRIORITY_THRESHOLD # 0-fee requirements met return 0 if small && big_outputs && high_priority # Otherwise, calculate the fee by size fee_for_bytes(tx_size, network: network, fee_per_kb: fee_per_kb) end |
.estimate_tx_size(inputs, outputs) ⇒ Object
68 69 70 71 72 73 74 75 76 |
# File 'lib/coin-op/bit/fee.rb', line 68 def estimate_tx_size(inputs, outputs) # tx overhead 10 + # outputs don't vary much in size (AVG_OUTPUT_SIZE * outputs.size) + # p2sh outputs are usually larger than p2pkh outputs, which don't vary much inputs.inject(0) { |sum, input| sum += input.script.type == :script_hash ? AVG_P2SH_BYTES : AVG_P2PKH_BYTES } end |
.fee_for_bytes(bytes, network:, fee_per_kb: nil) ⇒ Object
59 60 61 62 63 64 65 66 |
# File 'lib/coin-op/bit/fee.rb', line 59 def fee_for_bytes(bytes, network:, fee_per_kb: nil) # https://en.bitcoin.it/wiki/Transaction_fees # > the reference implementation will round up the transaction size to the # > next thousand bytes and add a fee of 0.1 mBTC (0.0001 BTC) per thousand bytes size = (bytes / 1000) + 1 return size * fee_per_kb if fee_per_kb CoinOp.syncbit(network) { Bitcoin.network[:min_tx_fee] * size } end |
.priority(params) ⇒ Object
89 90 91 92 93 94 95 96 97 |
# File 'lib/coin-op/bit/fee.rb', line 89 def priority(params) tx_size, unspents = params.values_at :size, :unspents sum = unspents.inject(0) do |sum, output| age = output[:age] || 0 sum += (output[:value] * age) sum end sum / tx_size end |