0
1
I'm using this library: https://github.com/lian/bitcoin-ruby
And here's my code:
require 'open-uri'
require 'net/http'
require 'net/https'
require 'json'
require 'bitcoin'
Bitcoin.network = :testnet3
def get_response(prev_tx)
url = "https://testnet.blockexplorer.com/api/rawtx/#{prev_tx}"
uri = URI(url)
response = Net::HTTP.get(uri)
response = JSON.parse(response)
response = response['rawtx'].to_s
return response
end
def build_transaction(prev_tx, prev_out_index, key, satoshi_to_spend, addr, message)
include Bitcoin::Builder
new_tx = build_tx do |t|
t.input do |i|
i.prev_out prev_tx
i.prev_out_index prev_out_index
i.signature_key key
end
t.output do |o|
o.value satoshi_to_spend
o.script {|s| s.type :address; s.recipient addr }
end
end
puts ""
puts "--- new tx ---"
puts new_tx.to_json
return new_tx
end
def bin_to_hex(s)
s.unpack('H*').first
end
bitcoin_key_1_pub = "0367e6251a89c5afc1212c3e2169866ccfe9d6059a4cfc15dc139b534b974fd7ca"
bitcoin_key_1_priv = "*****24c56528becd02d23076123a2edc2f3cf52c3c0202178c1b7fa9ac*****"
bitcoin_key_1_addr = "mxz4hu6JrTHevn22W4GDVjS3ko9MwXuHND"
# the previous transaction that has an output to your address #1
prev_tx_1 = "427138ed5f2443fbfbf8065e990f1bf9ce0236e14376e8abca0b2876eabca653"
# the number of the output you want to use
prev_out_index = 1
# 0.5 BTC in satoshis
btc_to_spend = 0.5
satoshi_to_spend = btc_to_spend * 100000000
bitcoin_key_2_pub = "02989d0578f715a1980d4d6e968bcba487077e74aaf8a219d11ee4384ea1fc1eda"
bitcoin_key_2_priv = "*****cb521a27f9782cc503b461bf5c6b470469ca00ba1d7dc26f4ab61b*****"
bitcoin_key_2_addr = "n4SYP6TJyK7pUouW65fnC1hDBrbb7Za8RR"
# fetch the tx from whereever you like and parse it
response = get_response(prev_tx_1)
$prev_tx = Bitcoin::P::Tx.new(response.htb)
prev_tx = $prev_tx
tx_value = prev_tx.outputs[prev_out_index].value
puts "tx_value: #{tx_value}"
key = Bitcoin::Key.new(bitcoin_key_1_priv, bitcoin_key_1_pub)
tx = build_transaction(prev_tx, prev_out_index, key, satoshi_to_spend, bitcoin_key_2_addr, "hello")
puts ""
puts "--- bin_to_hex ---"
puts bin_to_hex(tx.to_payload)
Here's the output:
➜ examples git:(master) ✗ ruby sandbox.rb
tx_value: 75972791
/Users/glaksmono/.rvm/gems/ruby-2.4.2/gems/bitcoin-ruby-0.0.18/lib/bitcoin/script.rb:281: warning: constant ::Fixnum is deprecated
/Users/glaksmono/.rvm/gems/ruby-2.4.2/gems/bitcoin-ruby-0.0.18/lib/bitcoin/script.rb:455: warning: constant ::Fixnum is deprecated
--- new tx ---
/Users/glaksmono/.rvm/gems/ruby-2.4.2/gems/bitcoin-ruby-0.0.18/lib/bitcoin/script.rb:261: warning: constant ::Fixnum is deprecated
{
"hash":"88217866a40829f144e2d2c19b2e506812ae013d08d9335ce8fa839582f1b18e",
"ver":1,
"vin_sz":1,
"vout_sz":1,
"lock_time":0,
"size":191,
"in":[
{
"prev_out":{
"hash":"427138ed5f2443fbfbf8065e990f1bf9ce0236e14376e8abca0b2876eabca653",
"n":1
},
"scriptSig":"304402201cf2d99b7f10c71a1c77ae629ec134a3f255c0027f47815aff3e43d500e6da46022008409ea148d6cce6876910c7a7218b8197c3a827a6a7bf3d5f064a3ed3a0616701 0367e6251a89c5afc1212c3e2169866ccfe9d6059a4cfc15dc139b534b974fd7ca"
}
],
"out":[
{
"value":"0.50000000",
"scriptPubKey":"OP_DUP OP_HASH160 fb75447d6038b05bb736e5b05f18a3c9da2b34db OP_EQUALVERIFY OP_CHECKSIG"
}
]
}
--- bin_to_hex ---
010000000153a6bcea76280bcaabe87643e13602cef91b0f995e06f8fbfb43245fed387142010000006a47304402201cf2d99b7f10c71a1c77ae629ec134a3f255c0027f47815aff3e43d500e6da46022008409ea148d6cce6876910c7a7218b8197c3a827a6a7bf3d5f064a3ed3a0616701210367e6251a89c5afc1212c3e2169866ccfe9d6059a4cfc15dc139b534b974fd7caffffffff0180f0fa02000000001976a914fb75447d6038b05bb736e5b05f18a3c9da2b34db88ac00000000
It seems to be successful, but I don't see the BTC actually transferred from bitcoin_key_1_addr to bitcoin_key_2_addr on the Blockcypher Explorer:
bitcoin_key_1_addrURL: https://live.blockcypher.com/btc-testnet/address/mxz4hu6JrTHevn22W4GDVjS3ko9MwXuHND/bitcoin_key_2_addrURL: https://live.blockcypher.com/btc-testnet/address/n4SYP6TJyK7pUouW65fnC1hDBrbb7Za8RR/
As you notice in the Blockcypher Explorer, the BTC amount is not yet transferred from bitcoin_key_1_addr to bitcoin_key_2_addr. Ideas?
Did you broadcast the transaction? I don't see any code that looks like the transaction is actually being sent to the network. A transaction needs to be broadcast before it can be seen by block explorers and included in the blockchain by miners. – Andrew Chow – 2018-04-26T16:50:22.683
@AndrewChow very good point - any ideas how to do that in bitcoin-ruby? – Grady – 2018-04-26T17:04:33.247
I figured, you need to use this: https://live.blockcypher.com/btc-testnet/pushtx/ but then I'm getting an error saying that the transaction has "too high fees", ideas? @AndrewChow
– Grady – 2018-04-26T17:11:19.060You can use that to broadcast. If you get an error, then you probably built your transaction wrong. Too-high-fees usually means that you did not create a change output so the change ends up all going to fees. – Andrew Chow – 2018-04-26T17:14:50.167
Did you see anything wrong with my code above? Not really sure which part of it was wrong @AndrewChow – Grady – 2018-04-27T03:54:27.303
The problem is that you are only creating one output whereas you need to have two outputs, the second being for the change output. The change output is exactly like any other output except that the output is spendable by you, not by your recipient. – Andrew Chow – 2018-04-27T03:57:03.933
@AndrewChow I don't understand. Do you have a sample code I can take a look? – Grady – 2018-04-27T05:02:04.607
It seems you are having a hard time grasping the idea of change. Since this is testnet, just make your output value almost match the input value. I say almost match because you will still need a transaction fee. – Andrew Chow – 2018-04-27T05:17:49.150