Class: CoinOp::Blockchain::Blockr

Inherits:
Object
  • Object
show all
Includes:
Encodings
Defined in:
lib/coin-op/blockchain/blockr.rb

Overview

Blockr.io API documentation: blockr.io/documentation/api

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Encodings

#base58, #decode_base58, #decode_hex, #hex

Constructor Details

#initialize(env = :test) ⇒ Blockr

Returns a new instance of Blockr.



14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/coin-op/blockchain/blockr.rb', line 14

def initialize(env=:test)
  subdomain = (env.to_sym == :test) ? "tbtc" : "btc"
  @base_url = "http://#{subdomain}.blockr.io/api/v1"

  # Testing says 20 is the absolute max
  @max_per_request = 20

  @http = HTTP.with_headers(
    "User-Agent" => "bv-blockchain-worker v0.1.0",
    "Accept" => "application/json"
  )
end

Instance Attribute Details

#max_per_requestObject

Returns the value of attribute max_per_request.



28
29
30
# File 'lib/coin-op/blockchain/blockr.rb', line 28

def max_per_request
  @max_per_request
end

Instance Method Details

#address_info(addresses, confirmations = 6) ⇒ Object



81
82
83
84
85
86
87
# File 'lib/coin-op/blockchain/blockr.rb', line 81

def address_info(addresses, confirmations=6)
  # Useful for testing transactions()
  request(
    :address, :info, addresses,
    :confirmations => confirmations
  )
end

#balance(addresses) ⇒ Object



60
61
62
63
64
65
66
67
68
# File 'lib/coin-op/blockchain/blockr.rb', line 60

def balance(addresses)
  result = request(:address, :balance, addresses)
  balances = {}
  result.each do |record|
    balances[record[:address]] = float_to_satoshis(record[:balance])
  end

  balances
end

#bitcoins_to_satoshis(string) ⇒ Object

Helper methods



102
103
104
# File 'lib/coin-op/blockchain/blockr.rb', line 102

def bitcoins_to_satoshis(string)
  string.gsub(".", "").to_i
end

#block_info(block_list) ⇒ Object



90
91
92
# File 'lib/coin-op/blockchain/blockr.rb', line 90

def block_info(block_list)
  request(:block, :info, block_list)
end

#block_txs(block_list) ⇒ Object



95
96
97
# File 'lib/coin-op/blockchain/blockr.rb', line 95

def block_txs(block_list)
  request(:block, :txs, block_list)
end

#float_to_satoshis(float) ⇒ Object



106
107
108
# File 'lib/coin-op/blockchain/blockr.rb', line 106

def float_to_satoshis(float)
  (float * 100_000_000).to_i
end

#request(from_type, to_type, args, query = nil) ⇒ Object

Queries the Blockr Bitcoin from_type => to_type API with list, returning the results or throwing an exception on failure.



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/coin-op/blockchain/blockr.rb', line 114

def request(from_type, to_type, args, query=nil)

  unless args.is_a? Array
    args = [args]
  end

  data = []
  args.each_slice(@max_per_request) do |arg_slice|
    # Permit calling with either an array or a scalar
      slice_string = arg_slice.join(",")
    url = "#{@base_url}/#{from_type}/#{to_type}/#{slice_string}"

    # Construct query string if any params were passed.
    if query
      # TODO: validation.  The value of the "confirmations" parameter
      # must be an integer.
      params = query.map { |name, value| "#{name}=#{value}" }.join("&")
      url = "#{url}?#{params}"
    end

    response = @http.request "GET", url, :response => :object
    # FIXME:  rescue any JSON parsing exception and raise an
    # exception explaining that it's blockr's fault.
    begin
      content = JSON.parse(response.body, :symbolize_names => true)
    rescue JSON::ParserError => e
      raise "Blockr returned invalid JSON: #{e}"
    end

    if content[:status] != "success"
      raise "Blockr.io failure: #{content.to_json}"
    end

    slice_data = content[:data]
    if content[:data].is_a? Array
      data.concat slice_data
    else
      data << slice_data
    end
  end

  data
end

#transactions(tx_ids) ⇒ Object



71
72
73
74
75
76
77
78
# File 'lib/coin-op/blockchain/blockr.rb', line 71

def transactions(tx_ids)
  results = request(:tx, :raw, tx_ids)
  results.map do |record|
    hex = record[:tx][:hex]

    transaction = CoinOp::Bit::Transaction.hex(hex)
  end
end

#unspent(addresses, confirmations = 6) ⇒ Object



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/blockchain/blockr.rb', line 31

def unspent(addresses, confirmations=6)

  result = request(
    :address, :unspent, addresses,
    :confirmations => confirmations
  )

  outputs = []
  result.each do |record|
    record[:unspent].each do |output|
      address = record[:address]

      transaction_hex, index, value, script_hex =
        output.values_at :tx, :n, :amount, :script

      outputs << CoinOp::Bit::Output.new(
        :transaction_hex => transaction_hex,
        :index => index,
        :value => bitcoins_to_satoshis(value),
        :script => {:hex => script_hex},
        :address => address
      )
    end
  end

  outputs.sort_by {|output| -output.value }
end