onchain 3.05 → 3.06
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/onchain.rb +0 -2
- data/lib/onchain/providers/blockchaininfo_api.rb +1 -1
- data/lib/onchain/transaction.rb +13 -1
- metadata +2 -4
- data/lib/onchain/payments.rb +0 -88
- data/lib/onchain/sweeper.rb +0 -139
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bac73b0c0032d9c02ae6cf5e3a4c7c111c1b4c5c
|
4
|
+
data.tar.gz: c0aef18a689aa33e9fa74db3f991ce015c1ca8ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6aaea261efdffacd19147e3471883fed20ef73f1dfa5e60bc27aaf2b78478aca2b185ae303e28ac67f8c30a77bd846fc8a7bdbcbb3db712b748a9740d4a5c6da
|
7
|
+
data.tar.gz: 21debc6e32a3eb923ff38781ba2ddbaaa806cb9686829afc0780743fd7aa91a94ed215170b1956d3be00f01b87be985164ca314a8659515704e3c3597f3bae50
|
data/lib/onchain.rb
CHANGED
@@ -3,8 +3,6 @@ require 'onchain/providers/blockchaininfo_api.rb'
|
|
3
3
|
require 'onchain/providers/blockr_api.rb'
|
4
4
|
require 'onchain/providers/insight_api.rb'
|
5
5
|
require 'onchain/providers/bitcoind_api.rb'
|
6
|
-
require 'onchain/sweeper.rb'
|
7
|
-
require 'onchain/payments.rb'
|
8
6
|
require 'onchain/transaction.rb'
|
9
7
|
require 'money-tree'
|
10
8
|
require 'bitcoin'
|
@@ -129,7 +129,7 @@ class OnChain::BlockChain
|
|
129
129
|
|
130
130
|
def blockinfo_get_transaction(txhash)
|
131
131
|
base = "https://blockchain.info/rawtx/#{txhash}?format=hex"
|
132
|
-
return fetch_response(URI::encode(base))
|
132
|
+
return fetch_response(URI::encode(base), false)
|
133
133
|
end
|
134
134
|
|
135
135
|
def block_chain(cmd, address, params = "")
|
data/lib/onchain/transaction.rb
CHANGED
@@ -11,6 +11,7 @@ class OnChain::Transaction
|
|
11
11
|
input_amount = 0
|
12
12
|
# Let's add up the value of all the inputs.
|
13
13
|
tx.in.each_with_index do |txin, index|
|
14
|
+
|
14
15
|
prev_hash = txin.to_hash['prev_out']['hash']
|
15
16
|
prev_index = txin.to_hash['prev_out']['n']
|
16
17
|
|
@@ -116,6 +117,17 @@ class OnChain::Transaction
|
|
116
117
|
|
117
118
|
end
|
118
119
|
|
120
|
+
def generate_redemption_script(minimum_sigs, addresses)
|
121
|
+
address, redeem_script = Bitcoin.pubkeys_to_p2sh_multisig_address(minimum_sigs, *addresses)
|
122
|
+
return redeem_script.hth
|
123
|
+
end
|
124
|
+
|
125
|
+
def generate_address_of_redemption_script(redemption_script)
|
126
|
+
hash160 = Bitcoin.hash160(redemption_script)
|
127
|
+
|
128
|
+
return Bitcoin.hash160_to_p2sh_address(hash160)
|
129
|
+
end
|
130
|
+
|
119
131
|
# Like create_single_address_transaction but for multi sig wallets.
|
120
132
|
def create_transaction_with_fee(redemption_scripts, address, amount, fee_percent, fee_addr)
|
121
133
|
|
@@ -124,7 +136,7 @@ class OnChain::Transaction
|
|
124
136
|
total_amount = amount + fee
|
125
137
|
|
126
138
|
addresses = redemption_scripts.map { |rs|
|
127
|
-
|
139
|
+
generate_address_of_redemption_script(rs)
|
128
140
|
}
|
129
141
|
|
130
142
|
unspents, indexes, change = OnChain::BlockChain.get_unspent_for_amount(addresses, total_amount)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: onchain
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '3.
|
4
|
+
version: '3.06'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Number 6
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-11-
|
11
|
+
date: 2016-11-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -103,12 +103,10 @@ extra_rdoc_files: []
|
|
103
103
|
files:
|
104
104
|
- lib/onchain.rb
|
105
105
|
- lib/onchain/block_chain.rb
|
106
|
-
- lib/onchain/payments.rb
|
107
106
|
- lib/onchain/providers/bitcoind_api.rb
|
108
107
|
- lib/onchain/providers/blockchaininfo_api.rb
|
109
108
|
- lib/onchain/providers/blockr_api.rb
|
110
109
|
- lib/onchain/providers/insight_api.rb
|
111
|
-
- lib/onchain/sweeper.rb
|
112
110
|
- lib/onchain/transaction.rb
|
113
111
|
homepage: https://github.com/onchain/onchain-gem
|
114
112
|
licenses: []
|
data/lib/onchain/payments.rb
DELETED
@@ -1,88 +0,0 @@
|
|
1
|
-
class OnChain::Payments
|
2
|
-
class << self
|
3
|
-
|
4
|
-
FEE = 50000
|
5
|
-
|
6
|
-
def get_address_from_redemption_script(redemption_script)
|
7
|
-
|
8
|
-
sbin = OnChain.hex_to_bin(redemption_script)
|
9
|
-
hex = OnChain.bin_to_hex(sbin)
|
10
|
-
fund_address = Bitcoin.hash160_to_p2sh_address(Bitcoin.hash160(hex))
|
11
|
-
|
12
|
-
return fund_address
|
13
|
-
end
|
14
|
-
|
15
|
-
def hex_to_script(hex)
|
16
|
-
return Bitcoin::Script.new(OnChain::hex_to_bin(hex))
|
17
|
-
end
|
18
|
-
|
19
|
-
def create_payment_tx(redemption_script, payments)
|
20
|
-
|
21
|
-
begin
|
22
|
-
|
23
|
-
fund_address = get_address_from_redemption_script(redemption_script)
|
24
|
-
|
25
|
-
tx = Bitcoin::Protocol::Tx.new
|
26
|
-
|
27
|
-
total_amount = FEE
|
28
|
-
|
29
|
-
payments.each do |payment|
|
30
|
-
if payment[1].is_a?(String)
|
31
|
-
payment[1] = payment[1].to_i
|
32
|
-
end
|
33
|
-
total_amount = total_amount + payment[1]
|
34
|
-
end
|
35
|
-
|
36
|
-
total_in_fund = OnChain::BlockChain.get_balance_satoshi(fund_address)
|
37
|
-
|
38
|
-
# Do we have enough in the fund.
|
39
|
-
if(total_amount > total_in_fund)
|
40
|
-
return 'Balance is not enough to cover payment'
|
41
|
-
end
|
42
|
-
|
43
|
-
# OK, let's get some inputs
|
44
|
-
amount_so_far = 0
|
45
|
-
unspent = OnChain::BlockChain.get_unspent_outs(fund_address)
|
46
|
-
unspent.each do |spent|
|
47
|
-
|
48
|
-
txin = Bitcoin::Protocol::TxIn.new
|
49
|
-
|
50
|
-
txin.prev_out = spent[0].scan(/../).map { |x| x.hex }.pack('c*').reverse
|
51
|
-
txin.prev_out_index = spent[1]
|
52
|
-
txin.script = hex_to_script(redemption_script).to_payload
|
53
|
-
|
54
|
-
tx.add_in(txin)
|
55
|
-
|
56
|
-
amount_so_far = amount_so_far + spent[3].to_i
|
57
|
-
if amount_so_far >= total_amount
|
58
|
-
next
|
59
|
-
end
|
60
|
-
end
|
61
|
-
change = amount_so_far - total_amount
|
62
|
-
|
63
|
-
payments.each do |payment|
|
64
|
-
|
65
|
-
txout = Bitcoin::Protocol::TxOut.new(payment[1],
|
66
|
-
Bitcoin::Script.to_address_script(payment[0]))
|
67
|
-
|
68
|
-
tx.add_out(txout)
|
69
|
-
end
|
70
|
-
|
71
|
-
# Send the chnage back.
|
72
|
-
if total_in_fund > total_amount
|
73
|
-
|
74
|
-
txout = Bitcoin::Protocol::TxOut.new(total_in_fund - total_amount,
|
75
|
-
Bitcoin::Script.to_address_script(fund_address))
|
76
|
-
|
77
|
-
tx.add_out(txout)
|
78
|
-
end
|
79
|
-
|
80
|
-
return tx
|
81
|
-
|
82
|
-
rescue Exception => e
|
83
|
-
return 'Unable to parse payment :: ' + e.to_s
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
end
|
88
|
-
end
|
data/lib/onchain/sweeper.rb
DELETED
@@ -1,139 +0,0 @@
|
|
1
|
-
require 'httparty'
|
2
|
-
|
3
|
-
class OnChain::Sweeper
|
4
|
-
class << self
|
5
|
-
|
6
|
-
# Turn a bunch of master keys into a redemption scriopt
|
7
|
-
# i.e. derive the path.
|
8
|
-
def multi_sig_address_from_mpks(minimum_sigs, mpks, path)
|
9
|
-
|
10
|
-
rs = generate_redemption_script_from_mpks(minimum_sigs, mpks, path)
|
11
|
-
|
12
|
-
return generate_address_of_redemption_script(rs)
|
13
|
-
end
|
14
|
-
|
15
|
-
def generate_redemption_script_from_mpks(minimum_sigs, mpks, path)
|
16
|
-
|
17
|
-
addresses = []
|
18
|
-
mpks.each do |mpk|
|
19
|
-
master = MoneyTree::Node.from_serialized_address(mpk)
|
20
|
-
m = master.node_for_path(path)
|
21
|
-
addresses << m.public_key.to_hex
|
22
|
-
end
|
23
|
-
|
24
|
-
return generate_redemption_script(minimum_sigs, addresses)
|
25
|
-
end
|
26
|
-
|
27
|
-
def generate_redemption_script(minimum_sigs, addresses)
|
28
|
-
address, redeem_script = Bitcoin.pubkeys_to_p2sh_multisig_address(minimum_sigs, *addresses)
|
29
|
-
return redeem_script.hth
|
30
|
-
end
|
31
|
-
|
32
|
-
def generate_address_of_redemption_script(redemption_script)
|
33
|
-
hash160 = Bitcoin.hash160(redemption_script)
|
34
|
-
|
35
|
-
return Bitcoin.hash160_to_p2sh_address(hash160)
|
36
|
-
end
|
37
|
-
|
38
|
-
def get_block_height
|
39
|
-
return Chain.get_latest_block["height"].to_i
|
40
|
-
end
|
41
|
-
|
42
|
-
# With a bunch of HD wallet paths, build a transaction
|
43
|
-
# That pays all the coins to a certain address
|
44
|
-
def sweep(minimum_sigs, mpks, path, limit, last_block_checked)
|
45
|
-
|
46
|
-
block_height_now = get_block_height
|
47
|
-
|
48
|
-
to_sweep = {}
|
49
|
-
# Get all the addresses we are interested in.
|
50
|
-
for i in 0..limit do
|
51
|
-
r = path.sub('#{index}', i.to_s)
|
52
|
-
a = multi_sig_address_from_mpks(minimum_sigs, mpks, r)
|
53
|
-
# store address as lookup for path.
|
54
|
-
to_sweep[a] = r
|
55
|
-
end
|
56
|
-
|
57
|
-
incoming_coins = []
|
58
|
-
|
59
|
-
to_sweep.each do |address, path|
|
60
|
-
|
61
|
-
txs = Chain.get_address_transactions(address)
|
62
|
-
|
63
|
-
txs.each do |tx|
|
64
|
-
|
65
|
-
block_height = tx["block_height"].to_i
|
66
|
-
if block_height > last_block_checked
|
67
|
-
|
68
|
-
tx["outputs"].each do |output|
|
69
|
-
output["addresses"].each do |address|
|
70
|
-
if to_sweep[address] != nil
|
71
|
-
incoming_coins << [address,
|
72
|
-
to_sweep[address],
|
73
|
-
output["value"],
|
74
|
-
output["transaction_hash"],
|
75
|
-
output["output_index"],
|
76
|
-
output["script"]]
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
else
|
82
|
-
break
|
83
|
-
end
|
84
|
-
|
85
|
-
end
|
86
|
-
end
|
87
|
-
return incoming_coins, block_height_now
|
88
|
-
end
|
89
|
-
|
90
|
-
def create_payment_tx_from_sweep(minimum_sigs, incoming, destination_address, mpks)
|
91
|
-
|
92
|
-
tx = Bitcoin::Protocol::Tx.new
|
93
|
-
total_amount = 0
|
94
|
-
|
95
|
-
incoming.each do |output|
|
96
|
-
|
97
|
-
txin = Bitcoin::Protocol::TxIn.new
|
98
|
-
|
99
|
-
rs = generate_redemption_script_from_mpks(minimum_sigs, mpks, output[1])
|
100
|
-
|
101
|
-
txin.prev_out = OnChain.hex_to_bin(output[3]).reverse
|
102
|
-
txin.prev_out_index = output[4]
|
103
|
-
txin.script = OnChain.hex_to_bin(rs)
|
104
|
-
|
105
|
-
tx.add_in(txin)
|
106
|
-
|
107
|
-
total_amount = total_amount + output[2].to_i
|
108
|
-
|
109
|
-
end
|
110
|
-
|
111
|
-
total_amount = total_amount - 10000
|
112
|
-
|
113
|
-
if total_amount < 0
|
114
|
-
return "Not enough coins to create a transaction."
|
115
|
-
end
|
116
|
-
|
117
|
-
# Add an output and we're done.
|
118
|
-
txout = Bitcoin::Protocol::TxOut.new(total_amount,
|
119
|
-
Bitcoin::Script.to_address_script(destination_address))
|
120
|
-
|
121
|
-
tx.add_out(txout)
|
122
|
-
|
123
|
-
paths = incoming.map { |i| i[1] }
|
124
|
-
|
125
|
-
return OnChain.bin_to_hex(tx.to_payload), paths
|
126
|
-
end
|
127
|
-
|
128
|
-
def post_tx_for_signing(tx_hex, paths, address)
|
129
|
-
|
130
|
-
return HTTParty.post('https://onchain.herokuapp.com/api/v1/transaction',
|
131
|
-
:body => { :tx => tx_hex,
|
132
|
-
:address => address,
|
133
|
-
:meta_data => paths.join(','),
|
134
|
-
:user_email => ENV['ONCHAIN_EMAIL'],
|
135
|
-
:user_token => ENV['ONCHAIN_TOKEN'] })
|
136
|
-
end
|
137
|
-
|
138
|
-
end
|
139
|
-
end
|