Class: BetterCoinbase::Client

Inherits:
Object
  • Object
show all
Includes:
HTTParty
Defined in:
lib/better-coinbase/client.rb

Direct Known Subclasses

OAuthClient

Defined Under Namespace

Classes: Error

Constant Summary collapse

BASE_URI =
'https://coinbase.com/api/v1'

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(api_key, api_secret, options = {}) ⇒ Client

Returns a new instance of Client.



15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/better-coinbase/client.rb', line 15

def initialize(api_key, api_secret, options={})
  @api_key = api_key
  @api_secret = api_secret

  # defaults
  options[:base_uri] ||= BASE_URI
  @base_uri = options[:base_uri]
  options[:format]   ||= :json
  options.each do |k,v|
    self.class.send k, v
  end
end

Class Method Details

.build_whitelisted_cert_storeObject



238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/better-coinbase/client.rb', line 238

def self.build_whitelisted_cert_store
  path = File.expand_path(File.join(File.dirname(__FILE__), 'ca-coinbase.crt'))

  certs = [ [] ]
  File.readlines(path).each{|line|
    next if ["\n","#"].include?(line[0])
    certs.last << line
    certs << [] if line == "-----END CERTIFICATE-----\n"
  }

  result = OpenSSL::X509::Store.new

  certs.each{|lines|
    next if lines.empty?
    cert = OpenSSL::X509::Certificate.new(lines.join)
    result.add_cert(cert)
  }

  result
end

.whitelisted_cert_storeObject



234
235
236
# File 'lib/better-coinbase/client.rb', line 234

def self.whitelisted_cert_store
  @@cert_store ||= build_whitelisted_cert_store
end

Instance Method Details

#accounts(options = {}) ⇒ Object



35
36
37
38
39
# File 'lib/better-coinbase/client.rb', line 35

def accounts options={}
  accts = get '/accounts', options
  accts = convert_money_objects(accts)
  accts
end

#addresses(page = 1, options = {}) ⇒ Object

Addresses



79
80
81
# File 'lib/better-coinbase/client.rb', line 79

def addresses page=1, options={}
  get '/addresses', {page: page}.merge(options)
end

#balance(options = {}) ⇒ Object

Account



30
31
32
33
# File 'lib/better-coinbase/client.rb', line 30

def balance options={}
  h = get '/account/balance', options
  h['amount'].to_money(h['currency'])
end

#buy!(qty) ⇒ Object

Buys



189
190
191
192
193
194
# File 'lib/better-coinbase/client.rb', line 189

def buy! qty
  r = post '/buys', {qty: qty}
  r = convert_money_objects(r)
  r.transfer.payout_date = Time.parse(r.transfer.payout_date) rescue nil
  r
end

#buy_price(qty = 1) ⇒ Object

Prices



172
173
174
175
# File 'lib/better-coinbase/client.rb', line 172

def buy_price qty=1
  r = get '/prices/buy', {qty: qty}
  r['amount'].to_money(r['currency'])
end

#cancel_request(transaction_id) ⇒ Object



149
150
151
# File 'lib/better-coinbase/client.rb', line 149

def cancel_request transaction_id
  delete "/transactions/#{transaction_id}/cancel_request"
end

#complete_request(transaction_id) ⇒ Object



153
154
155
# File 'lib/better-coinbase/client.rb', line 153

def complete_request transaction_id
  put "/transactions/#{transaction_id}/complete_request"
end

#create_button(name, price, description = nil, custom = nil, options = {}) ⇒ Object

Buttons



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/better-coinbase/client.rb', line 51

def create_button name, price, description=nil, custom=nil, options={}
  options[:button]                        ||= {}
  options[:button][:name]                 ||= name
  price = price.to_money("BTC") unless price.is_a?(Money)
  options[:button][:price_string]         ||= price.to_s
  options[:button][:price_currency_iso]   ||= price.currency.iso_code
  options[:button][:description]          ||= description
  options[:button][:custom]               ||= custom
  r = post '/buttons', options
  if r.success?
    r.embed_html = case options[:button_mode]
                   when 'page'
                     %[<a href="https://coinbase.com/checkouts/#{r.button.code}" target="_blank"><img alt="#{r.button.text}" src="https://coinbase.com/assets/buttons/#{r.button.style}.png"></a>]
                   when 'iframe'
                      %[<iframe src="https://coinbase.com/inline_payments/#{r.button.code}" style="width:500px;height:160px;border:none;box-shadow:0 1px 3px rgba(0,0,0,0.25);overflow:hidden;" scrolling="no" allowtransparency="true" frameborder="0"></iframe>]
                   else
                     %[<div class="coinbase-button" data-code="#{r.button.code}"></div><script src="https://coinbase.com/assets/button.js" type="text/javascript"></script>]
                   end
  end
  r
end

#create_order_for_button(button_id) ⇒ Object



73
74
75
# File 'lib/better-coinbase/client.rb', line 73

def create_order_for_button button_id
  post "/buttons/#{button_id}/create_order"
end

#create_user(email, password = nil, client_id = nil, scopes = nil) ⇒ Object

Users



159
160
161
162
163
164
165
166
167
168
# File 'lib/better-coinbase/client.rb', line 159

def create_user email, password=nil, client_id=nil, scopes=nil
  password ||= SecureRandom.urlsafe_base64(12)
  options = {user: {email: email, password: password}}
  if client_id
    options[:client_id] = client_id
    raise Error.new("Invalid scopes parameter; must be an array") if !scopes.is_a?(Array)
    options[:scopes] = scopes.join(' ')
  end
  post '/users', options
end

#currencies_longObject



93
94
95
# File 'lib/better-coinbase/client.rb', line 93

def currencies_long
  currencies.collect { |c| c[0] }
end

#currencies_shortObject



89
90
91
# File 'lib/better-coinbase/client.rb', line 89

def currencies_short
  currencies.collect { |c| c[1] }
end

#delete(path, options = {}) ⇒ Object



230
231
232
# File 'lib/better-coinbase/client.rb', line 230

def delete(path, options={})
  http_verb :delete, path, options
end

#exchange_ratesObject

Currencies



85
86
87
# File 'lib/better-coinbase/client.rb', line 85

def exchange_rates
  get('/currencies/exchange_rates')
end

#generate_receive_address(options = {}) ⇒ Object



45
46
47
# File 'lib/better-coinbase/client.rb', line 45

def generate_receive_address options={}
  post '/account/generate_receive_address', options
end

#get(path, options = {}) ⇒ Object

Wrappers for the main HTTP verbs



218
219
220
# File 'lib/better-coinbase/client.rb', line 218

def get(path, options={})
  http_verb :get, path, options
end

#http_verb(verb, path, options = {}) ⇒ Object

Raises:



263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'lib/better-coinbase/client.rb', line 263

def http_verb(verb, path, options={})

  nonce = options[:nonce] || (Time.now.to_f * 1e6).to_i

  if [:get, :delete].include? verb
    request_options = {}
    path = "#{path}?#{URI.encode_www_form(options)}" if !options.empty?
    hmac_message = nonce.to_s + @base_uri + path
  else
    request_options = {body: options.to_json}
    hmac_message = nonce.to_s + @base_uri + path + options.to_json
  end

  signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), @api_secret, hmac_message)

  headers = {
    'ACCESS_KEY' => @api_key,
    'ACCESS_SIGNATURE' => signature,
    'ACCESS_NONCE' => nonce.to_s,
    "Content-Type" => "application/json",
  }

  request_options[:headers] = headers

  r = self.class.send(verb, path, request_options.merge(ssl_options))
  hash = Hashie::Mash.new(JSON.parse(r.body))
  raise Error.new(hash.error) if hash.error
  raise Error.new(hash.errors.join(", ")) if hash.errors
  hash
end

#post(path, options = {}) ⇒ Object



222
223
224
# File 'lib/better-coinbase/client.rb', line 222

def post(path, options={})
  http_verb :post, path, options
end

#put(path, options = {}) ⇒ Object



226
227
228
# File 'lib/better-coinbase/client.rb', line 226

def put(path, options={})
  http_verb :put, path, options
end

#receive_address(options = {}) ⇒ Object



41
42
43
# File 'lib/better-coinbase/client.rb', line 41

def receive_address options={}
  get '/account/receive_address', options
end

#request_money(from, amount, notes = nil, options = {}) ⇒ Object



131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/better-coinbase/client.rb', line 131

def request_money from, amount, notes=nil, options={}
  options[:transaction]                         ||= {}
  options[:transaction][:from]                  ||= from
  amount = amount.to_money("BTC") unless amount.is_a?(Money)
  options[:transaction][:amount_string]         ||= amount.to_s
  options[:transaction][:amount_currency_iso]   ||= amount.currency.iso_code
  options[:transaction][:notes]                 ||= notes
  r = post '/transactions/request_money', options
  if amt = r.transaction.amount
    r.transaction.amount = amt.amount.to_money(amt.currency)
  end
  r
end

#resend_request(transaction_id) ⇒ Object



145
146
147
# File 'lib/better-coinbase/client.rb', line 145

def resend_request transaction_id
  put "/transactions/#{transaction_id}/resend_request"
end

#sell!(qty) ⇒ Object

Sells



198
199
200
201
202
203
# File 'lib/better-coinbase/client.rb', line 198

def sell! qty
  r = post '/sells', {qty: qty}
  r = convert_money_objects(r)
  r.transfer.payout_date = Time.parse(r.transfer.payout_date) rescue nil
  r
end

#sell_price(qty = 1) ⇒ Object



177
178
179
180
# File 'lib/better-coinbase/client.rb', line 177

def sell_price qty=1
  r = get '/prices/sell', {qty: qty}
  r['amount'].to_money(r['currency'])
end

#send_money(to, amount, notes = nil, options = {}) ⇒ Object



117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/better-coinbase/client.rb', line 117

def send_money to, amount, notes=nil, options={}
  options[:transaction]                         ||= {}
  options[:transaction][:to]                    ||= to
  amount = amount.to_money("BTC") unless amount.is_a?(Money)
  options[:transaction][:amount_string]         ||= amount.to_s
  options[:transaction][:amount_currency_iso]   ||= amount.currency.iso_code
  options[:transaction][:notes]                 ||= notes
  r = post '/transactions/send_money', options
  if amt = r.transaction.amount
    r.transaction.amount = amt.amount.to_money(amt.currency)
  end
  r
end

#spot_price(currency = 'USD') ⇒ Object



182
183
184
185
# File 'lib/better-coinbase/client.rb', line 182

def spot_price currency='USD'
  r = get '/prices/spot_rate', {currency: currency}
  r['amount'].to_money(r['currency'])
end

#ssl_optionsObject



259
260
261
# File 'lib/better-coinbase/client.rb', line 259

def ssl_options
  { verify: true, cert_store: self.class.whitelisted_cert_store }
end

#transaction(transaction_id) ⇒ Object



111
112
113
114
115
# File 'lib/better-coinbase/client.rb', line 111

def transaction transaction_id
  r = get "/transactions/#{transaction_id}"
  convert_money_objects(r.transaction)
  r
end

#transactions(page = 1, options = {}) ⇒ Object

Transactions



104
105
106
107
108
109
# File 'lib/better-coinbase/client.rb', line 104

def transactions page=1, options ={}
  r = get '/transactions', {page: page}.merge(options)
  r.transactions ||= []
  convert_money_objects(r.transactions)
  r
end

#transfers(options = {}) ⇒ Object

Transfers



207
208
209
210
211
212
213
214
# File 'lib/better-coinbase/client.rb', line 207

def transfers options={}
  r = get '/transfers', options
  r = convert_money_objects(r)
  r.transfers.each do |t|
    t.transfer.payout_date = Time.parse(t.transfer.payout_date) rescue nil
  end
  r
end