Class: OnChain::BlockChain

Inherits:
Object
  • Object
show all
Defined in:
lib/onchain/block_chain.rb,
lib/onchain/providers/blockr_api.rb,
lib/onchain/providers/chaincom_api.rb,
lib/onchain/providers/blockchaininfo_api.rb

Constant Summary collapse

ALL_SUPPLIERS =

ALL_SUPPLIERS = [:chaincom, :blockr, :blockinfo ]

[ :blockr, :blockinfo ]
BALANCE_CACHE_FOR =
120
API_CACHE_FOR =
60
SERVICE_DOWN_FOR =
60
@@cache =
{}

Class Method Summary collapse

Class Method Details

.block_chain(cmd, address, params = "") ⇒ Object



55
56
57
58
59
# File 'lib/onchain/providers/blockchaininfo_api.rb', line 55

def block_chain(cmd, address, params = "")
  base_url = "http://blockchain.info/#{cmd}/#{address}?format=json" + params
  
  fetch_response(base_url, true)
end

.blockinfo_get_all_balances(addresses) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
# File 'lib/onchain/providers/blockchaininfo_api.rb', line 5

def blockinfo_get_all_balances(addresses)
  base = "https://blockchain.info/multiaddr?&simple=true&active="
  
  addresses.each do |address|
    base = base + address + '|'
  end
  
  json = fetch_response(URI::encode(base))
  
  addresses.each do |address|
    bal = json[address]['final_balance'] / 100000000.0
    cache_write(address, bal, BALANCE_CACHE_FOR)
  end
end

.blockinfo_get_balance(address) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/onchain/providers/blockchaininfo_api.rb', line 38

def blockinfo_get_balance(address)
  if cache_read(address) == nil
    json = block_chain('address', address, "&limit=0")
    if json.key?('final_balance')
      bal = json['final_balance'] / 100000000.0
      cache_write(address, bal, BALANCE_CACHE_FOR)
    else
      cache_write(address, 'Error', BALANCE_CACHE_FOR)
    end
  end
  bal = cache_read(address)
  if bal.class == Fixnum
    bal = bal.to_f
  end
  return bal
end

.blockinfo_get_unspent_outs(address) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/onchain/providers/blockchaininfo_api.rb', line 20

def blockinfo_get_unspent_outs(address)
  base_url = "http://blockchain.info/unspent?active=#{address}"
  json = fetch_response(base_url, true)
  
  unspent = []
  
  json['unspent_outputs'].each do |data|
    line = []
    line << reverse_blockchain_tx(data['tx_hash'])
    line << data['tx_output_n']
    line << data['script']
    line << data['value']
    unspent << line
  end
  
  return unspent
end

.blockr(cmd, address, params = "") ⇒ Object



67
68
69
70
71
72
# File 'lib/onchain/providers/blockr_api.rb', line 67

def blockr(cmd, address, params = "")

  base_url = "http://blockr.io/api/v1/#{cmd}/#{address}" + params
  fetch_response(base_url, true)

end

.blockr_get_all_balances(addresses) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/onchain/providers/blockr_api.rb', line 51

def blockr_get_all_balances(addresses)
  base = "https://blockr.io/api/v1/address/balance/"
  
  addresses.each do |address|
    base = base + address + ','
  end
  
  json = fetch_response(URI::encode(base))
  
  json['data'].each do |data|
    bal = data['balance']
    addr = data['address']
    cache_write(addr, bal, BALANCE_CACHE_FOR)
  end
end

.blockr_get_balance(address) ⇒ Object



4
5
6
7
8
9
10
11
12
13
14
15
# File 'lib/onchain/providers/blockr_api.rb', line 4

def blockr_get_balance(address)
  if cache_read(address) == nil
    json = blockr('address/balance', address)
    if json.key?('data')
      bal = json['data']['balance'].to_f
      cache_write(address, bal, BALANCE_CACHE_FOR)
    else
      cache_write(address, 'Error', BALANCE_CACHE_FOR)
    end
  end
  return cache_read(address) 
end

.blockr_get_transactions(address) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/onchain/providers/blockr_api.rb', line 17

def blockr_get_transactions(address)
  base_url = "http://btc.blockr.io/api/v1/address/txs/#{address}"
  json = fetch_response(base_url, true)
  
  unspent = []
  
  json['data']['txs'].each do |data|
    line = []
    line << data['tx']
    line << (data['amount'].to_f * 100000000).to_i
    unspent << line
  end
  
  return unspent
end

.blockr_get_unspent_outs(address) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/onchain/providers/blockr_api.rb', line 33

def blockr_get_unspent_outs(address)
  base_url = "http://btc.blockr.io/api/v1/address/unspent/#{address}"
  json = fetch_response(base_url, true)
  
  unspent = []
  
  json['data']['unspent'].each do |data|
    line = []
    line << data['tx']
    line << data['n']
    line << data['script']
    line << (data['amount'].to_f * 100000000).to_i
    unspent << line
  end
  
  return unspent
end

.cache_read(key) ⇒ Object



71
72
73
74
75
76
77
# File 'lib/onchain/block_chain.rb', line 71

def cache_read(key)
   # if the API URL exists as a key in cache, we just return it
   # we also make sure the data is fresh
   if @@cache.has_key? key
      return @@cache[key][1] if Time.now-@@cache[key][0] < @@cache[key][2]
   end
end

.cache_write(key, data, max_age = 0) ⇒ Object



67
68
69
# File 'lib/onchain/block_chain.rb', line 67

def cache_write(key, data, max_age=0)
   @@cache[key] = [Time.now, data, max_age]
end

.fetch_response(url, do_json = true) ⇒ Object



79
80
81
82
83
84
85
86
87
88
# File 'lib/onchain/block_chain.rb', line 79

def fetch_response(url, do_json=true)
  resp = Net::HTTP.get_response(URI.parse(url))
  data = resp.body

  if do_json
    result = JSON.parse(data)
  else
    data
  end
end

.get_available_suppliersObject



51
52
53
54
55
56
57
58
59
# File 'lib/onchain/block_chain.rb', line 51

def get_available_suppliers
  available = []
  ALL_SUPPLIERS.each do |supplier|
    if cache_read(supplier.to_s) == nil
      available << supplier
    end
  end
  return available
end

.get_balance_satoshi(address) ⇒ Object



47
48
49
# File 'lib/onchain/block_chain.rb', line 47

def get_balance_satoshi(address)
  return (get_balance(address).to_f * 100000000).to_i
end

.method_missing(method_name, *args, &block) ⇒ Object



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/onchain/block_chain.rb', line 23

def method_missing (method_name, *args, &block)
  
  get_available_suppliers.each do |supplier|

    real_method = "#{supplier.to_s}_#{method_name}"
    begin
      method = self.method(real_method)
      begin
        result = method.call(*args)
        return result
      rescue => e2
        # We have the method but it errored. Assume
        # service is down.
        cache_write(supplier.to_s, 'down', SERVICE_DOWN_FOR)
        puts e2.to_s
      end
    rescue => e
      puts "there's no method called '#{real_method}'"
      puts e.backtrace
    end
  end
  
end

.reverse_blockchain_tx(hash) ⇒ Object



61
62
63
64
65
66
67
# File 'lib/onchain/providers/blockchaininfo_api.rb', line 61

def reverse_blockchain_tx(hash)
   bytes = hash.scan(/../).map { |x| x.hex.chr }.join
   
   bytes = bytes.reverse
   
   return hash.scan(/../).reverse.join
end