onchain 3.05 → 3.06
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|