pochette 0.2.3 → 0.3.0
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/README.md +0 -3
- data/lib/pochette.rb +4 -0
- data/lib/pochette/backends/base.rb +88 -0
- data/lib/pochette/backends/bitcoin_core.rb +2 -2
- data/lib/pochette/backends/blockchain_info.rb +9 -3
- data/lib/pochette/backends/trendy.rb +2 -77
- data/lib/pochette/trezor_transaction_builder.rb +0 -1
- data/lib/pochette/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d61a337d84f849c127e76e2d06db768306d3d050
|
4
|
+
data.tar.gz: 8ab1cb06f94a3bc4f88c0e641094ec8f54474d5a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 466b1a81cb4f6a2a5e302d613ddd0ddb994edc1312dc3c6d7a6bf6bcee6487956146e8645a6a0a8471b97a169daa4df9727ba7e31cf992d73ffb6d4f00c25aca
|
7
|
+
data.tar.gz: 54a663b538f938b1a2efc86f0d9ac46f95c454a783611b01152a3165bc4db2d01f4dcfe117a63878ddddda7caf035896ca2378f61ea9bf008a82804baa540e3f
|
data/README.md
CHANGED
@@ -291,7 +291,6 @@ A hash with
|
|
291
291
|
depth: 0,
|
292
292
|
child_num: 0,
|
293
293
|
fingerprint: 0,
|
294
|
-
path: [],
|
295
294
|
public_key: '03142b0a6fa6943e7276ddc42582c6b169243d289ff17e7c8101797047eed90c9b',
|
296
295
|
}
|
297
296
|
},
|
@@ -301,7 +300,6 @@ A hash with
|
|
301
300
|
depth: 0,
|
302
301
|
child_num: 0,
|
303
302
|
fingerprint: 0,
|
304
|
-
path: [],
|
305
303
|
public_key: '027565ceb190647ec5c566805ebc5cb6166ae2ee1d4995495f61b9eff371ec0e61',
|
306
304
|
}
|
307
305
|
},
|
@@ -311,7 +309,6 @@ A hash with
|
|
311
309
|
depth: 0,
|
312
310
|
child_num: 0,
|
313
311
|
fingerprint: 0,
|
314
|
-
path: [],
|
315
312
|
public_key: '028776ff18f0f3808d6d42749a6e2baee5c75c3f7ae07445403a3a5690d580a0af',
|
316
313
|
}
|
317
314
|
}
|
data/lib/pochette.rb
CHANGED
@@ -30,8 +30,12 @@ module Pochette
|
|
30
30
|
|
31
31
|
module Backends
|
32
32
|
end
|
33
|
+
|
34
|
+
class InvalidSignatureError < StandardError
|
35
|
+
end
|
33
36
|
end
|
34
37
|
|
38
|
+
require "pochette/backends/base"
|
35
39
|
require "pochette/backends/bitcoin_core"
|
36
40
|
require "pochette/backends/blockchain_info"
|
37
41
|
require "pochette/backends/trendy"
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# All Pochette backends must conform to this interface.
|
2
|
+
class Pochette::Backends::Base
|
3
|
+
# Lists all bitcoins received by a list of addresses
|
4
|
+
# after a given date. Includes both confirmed and unconfirmed
|
5
|
+
# transactions, unconfirmed transactions have a nil block height.
|
6
|
+
# Returns a list of lists as following:
|
7
|
+
# amount: Amount received (in satoshis)
|
8
|
+
# address: Public address receiving the amount.
|
9
|
+
# txid: The hash for the transaction that received it.
|
10
|
+
# confirmations: Transaction confirmations
|
11
|
+
# output position: To disambiguate in case address received more than once.
|
12
|
+
# sender addresses: Comma separated list of input addresses,
|
13
|
+
# used to identify deposits from trusted parties.
|
14
|
+
# can be used to identify deposits from trusted parties.
|
15
|
+
def incoming_for(addresses, min_date)
|
16
|
+
raise NotImplementedError
|
17
|
+
end
|
18
|
+
|
19
|
+
# Gets the total received, spent and balance for
|
20
|
+
# a list of addresses. Confirmed balances are enforced to have a number
|
21
|
+
# of confirmation, appearing in a block is not enough.
|
22
|
+
# Returns a hash with:
|
23
|
+
# { address: [received, sent, total,
|
24
|
+
# unconfirmed_received, unconfirmed_sent, unconfirmed_total],
|
25
|
+
# ...}
|
26
|
+
def balances_for(addresses, confirmations)
|
27
|
+
raise NotImplementedError
|
28
|
+
end
|
29
|
+
|
30
|
+
# Get unspent utxos for the given addresses,
|
31
|
+
# returns a list of lists like so:
|
32
|
+
# [[address, txid, position (vout), amount (in satoshis)], ...]
|
33
|
+
def list_unspent(addresses)
|
34
|
+
raise NotImplementedError
|
35
|
+
end
|
36
|
+
|
37
|
+
# Gets information for the given transactions
|
38
|
+
# returns a list of objects, like so:
|
39
|
+
# [
|
40
|
+
# { hash: txid,
|
41
|
+
# version: 1,
|
42
|
+
# lock_time: 0,
|
43
|
+
# inputs: [
|
44
|
+
# { prev_hash: txid,
|
45
|
+
# prev_index: 0,
|
46
|
+
# sequence: 0,
|
47
|
+
# script_sig: hex_signature
|
48
|
+
# },
|
49
|
+
# ...
|
50
|
+
# ],
|
51
|
+
# bin_outputs: [
|
52
|
+
# { amount: amount (as satoshis),
|
53
|
+
# script_pubkey: hex_script
|
54
|
+
# },
|
55
|
+
# ...
|
56
|
+
# ]
|
57
|
+
# }
|
58
|
+
def list_transactions(txids)
|
59
|
+
raise NotImplementedError
|
60
|
+
end
|
61
|
+
|
62
|
+
def pushtx(hex, options = { })
|
63
|
+
verify_signatures(hex, options) if options[:verify_signatures]
|
64
|
+
propagate(hex)
|
65
|
+
Bitcoin::Protocol::Tx.new(hex.htb).hash
|
66
|
+
end
|
67
|
+
|
68
|
+
def propagate(hex)
|
69
|
+
raise NotImplementedError
|
70
|
+
end
|
71
|
+
|
72
|
+
def block_height
|
73
|
+
raise NotImplementedError
|
74
|
+
end
|
75
|
+
|
76
|
+
def verify_signatures(hex, options = { })
|
77
|
+
tx = Bitcoin::P::Tx.new(hex.htb)
|
78
|
+
tx.inputs.each_with_index do |input, idx|
|
79
|
+
prev_tx = list_transactions([ input.previous_output ]).first
|
80
|
+
outputs = prev_tx[:bin_outputs]
|
81
|
+
script_pubkey = outputs[input.prev_out_index][:script_pubkey].htb
|
82
|
+
unless tx.verify_input_signature(idx, script_pubkey, Time.now.to_i, options)
|
83
|
+
raise Pochette::InvalidSignatureError, "Signature for input #{idx} is invalid."
|
84
|
+
end
|
85
|
+
end
|
86
|
+
true
|
87
|
+
end
|
88
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# A bitcoin backend that uses bitcoin-core to retrieve information.
|
2
2
|
# See Pochette::Backends::Trendy to learn more about the backend
|
3
3
|
# interface and contract.
|
4
|
-
class Pochette::Backends::BitcoinCore
|
4
|
+
class Pochette::Backends::BitcoinCore < Pochette::Backends::Base
|
5
5
|
def initialize(rpc_url)
|
6
6
|
@rpc_url = rpc_url
|
7
7
|
end
|
@@ -103,7 +103,7 @@ class Pochette::Backends::BitcoinCore
|
|
103
103
|
client.getinfo[:blocks]
|
104
104
|
end
|
105
105
|
|
106
|
-
def
|
106
|
+
def propagate(hex)
|
107
107
|
client.sendrawtransaction(hex)
|
108
108
|
end
|
109
109
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
# interface and contract.
|
4
4
|
require 'open-uri'
|
5
5
|
|
6
|
-
class Pochette::Backends::BlockchainInfo
|
6
|
+
class Pochette::Backends::BlockchainInfo < Pochette::Backends::Base
|
7
7
|
cattr_accessor(:cooldown){1}
|
8
8
|
attr_accessor :api_key
|
9
9
|
|
@@ -17,6 +17,13 @@ class Pochette::Backends::BlockchainInfo
|
|
17
17
|
address = Bitcoin::Script.new(utxo['script'].htb).get_address
|
18
18
|
[address, utxo['tx_hash_big_endian'], utxo['tx_output_n'].to_i, utxo['value'], utxo['script']]
|
19
19
|
end
|
20
|
+
rescue OpenURI::HTTPError => e
|
21
|
+
# Blockchain.info returns 500 when there are no unspent outputs
|
22
|
+
if e.io.read == "No free outputs to spend"
|
23
|
+
return []
|
24
|
+
else
|
25
|
+
raise
|
26
|
+
end
|
20
27
|
end
|
21
28
|
|
22
29
|
def balances_for(addresses, confirmations)
|
@@ -85,13 +92,12 @@ class Pochette::Backends::BlockchainInfo
|
|
85
92
|
get_json("latestblock", {format: 'json'})['height'].to_i
|
86
93
|
end
|
87
94
|
|
88
|
-
def
|
95
|
+
def propagate(hex)
|
89
96
|
uri = URI.parse("https://blockchain.info/pushtx")
|
90
97
|
params = { "tx" => hex }
|
91
98
|
params['api_code'] = api_key if api_key
|
92
99
|
response = Net::HTTP.post_form(uri, params)
|
93
100
|
raise StandardError.new(response) if response.code.to_i != 200
|
94
|
-
Bitcoin::Protocol::Tx.new(hex.htb).hash
|
95
101
|
end
|
96
102
|
|
97
103
|
def get_json(path, params={})
|
@@ -2,87 +2,12 @@
|
|
2
2
|
# to list unspent outputs, incoming payments, etcetera.
|
3
3
|
# It chooses the backend to use based on its latest block, trying
|
4
4
|
# to always use the most up to date one.
|
5
|
-
|
6
|
-
# other backend, all Pochette backends must define
|
7
|
-
# thes public methods (Except for the initializer).
|
8
|
-
class Pochette::Backends::Trendy
|
5
|
+
class Pochette::Backends::Trendy < Pochette::Backends::Base
|
9
6
|
def initialize(backends)
|
10
7
|
@backends = backends
|
11
8
|
end
|
12
|
-
|
13
|
-
# Lists all bitcoins received by a list of addresses
|
14
|
-
# after a given date. Includes both confirmed and unconfirmed
|
15
|
-
# transactions, unconfirmed transactions have a nil block height.
|
16
|
-
# Returns a list of lists as following:
|
17
|
-
# amount: Amount received (in satoshis)
|
18
|
-
# address: Public address receiving the amount.
|
19
|
-
# txid: The hash for the transaction that received it.
|
20
|
-
# confirmations: Transaction confirmations
|
21
|
-
# output position: To disambiguate in case address received more than once.
|
22
|
-
# sender addresses: Comma separated list of input addresses,
|
23
|
-
# used to identify deposits from trusted parties.
|
24
|
-
# can be used to identify deposits from trusted parties.
|
25
|
-
def incoming_for(addresses, min_date)
|
26
|
-
backend.incoming_for(addresses, min_date)
|
27
|
-
end
|
28
|
-
|
29
|
-
# Gets the total received, spent and balance for
|
30
|
-
# a list of addresses. Confirmed balances are enforced to have a number
|
31
|
-
# of confirmation, appearing in a block is not enough.
|
32
|
-
# Returns a hash with:
|
33
|
-
# { address: [received, sent, total,
|
34
|
-
# unconfirmed_received, unconfirmed_sent, unconfirmed_total],
|
35
|
-
# ...}
|
36
|
-
def balances_for(addresses, confirmations)
|
37
|
-
backend.balances_for(addresses, confirmations)
|
38
|
-
end
|
39
9
|
|
40
|
-
|
41
|
-
# returns a list of lists like so:
|
42
|
-
# [[address, txid, position (vout), amount (in satoshis)], ...]
|
43
|
-
def list_unspent(addresses)
|
44
|
-
backend.list_unspent(addresses)
|
45
|
-
rescue OpenURI::HTTPError => e
|
46
|
-
# Blockchain.info returns 500 when there are no unspent outputs
|
47
|
-
if e.io.read == "No free outputs to spend"
|
48
|
-
return []
|
49
|
-
else
|
50
|
-
raise
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
# Gets information for the given transactions
|
55
|
-
# returns a list of objects, like so:
|
56
|
-
# [
|
57
|
-
# { hash: txid,
|
58
|
-
# version: 1,
|
59
|
-
# lock_time: 0,
|
60
|
-
# inputs: [
|
61
|
-
# { prev_hash: txid,
|
62
|
-
# prev_index: 0,
|
63
|
-
# sequence: 0,
|
64
|
-
# script_sig: hex_signature
|
65
|
-
# },
|
66
|
-
# ...
|
67
|
-
# ],
|
68
|
-
# bin_outputs: [
|
69
|
-
# { amount: amount (as satoshis),
|
70
|
-
# script_pubkey: hex_script
|
71
|
-
# },
|
72
|
-
# ...
|
73
|
-
# ]
|
74
|
-
# }
|
75
|
-
def list_transactions(txids)
|
76
|
-
backend.list_transactions(txids)
|
77
|
-
end
|
78
|
-
|
79
|
-
def pushtx(hex)
|
80
|
-
backend.pushtx(hex)
|
81
|
-
end
|
82
|
-
|
83
|
-
def block_height
|
84
|
-
backend.block_height
|
85
|
-
end
|
10
|
+
delegate :incoming_for, :balances_for, :list_unspent, :list_transactions, :pushtx, :block_height, to: :backend
|
86
11
|
|
87
12
|
protected
|
88
13
|
|
data/lib/pochette/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pochette
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nubis
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2016-10-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -173,6 +173,7 @@ files:
|
|
173
173
|
- bin/console
|
174
174
|
- bin/setup
|
175
175
|
- lib/pochette.rb
|
176
|
+
- lib/pochette/backends/base.rb
|
176
177
|
- lib/pochette/backends/bitcoin_core.rb
|
177
178
|
- lib/pochette/backends/blockchain_info.rb
|
178
179
|
- lib/pochette/backends/trendy.rb
|