better-coinbase 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +336 -0
- data/Rakefile +6 -0
- data/better-coinbase.gemspec +33 -0
- data/lib/better-coinbase.rb +5 -0
- data/lib/better-coinbase/ca-coinbase.crt +629 -0
- data/lib/better-coinbase/client.rb +315 -0
- data/lib/better-coinbase/oauth_client.rb +77 -0
- data/lib/better-coinbase/version.rb +3 -0
- data/spec/client_spec.rb +429 -0
- data/spec/oauth_client_spec.rb +81 -0
- data/supported_currencies.json +163 -0
- metadata +185 -0
@@ -0,0 +1,315 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'multi_json'
|
3
|
+
require 'hashie'
|
4
|
+
require 'money'
|
5
|
+
require 'monetize'
|
6
|
+
require 'time'
|
7
|
+
require 'securerandom'
|
8
|
+
|
9
|
+
module BetterCoinbase
|
10
|
+
class Client
|
11
|
+
include HTTParty
|
12
|
+
|
13
|
+
BASE_URI = 'https://coinbase.com/api/v1'
|
14
|
+
|
15
|
+
def initialize(api_key, api_secret, options={})
|
16
|
+
@api_key = api_key
|
17
|
+
@api_secret = api_secret
|
18
|
+
|
19
|
+
# defaults
|
20
|
+
options[:base_uri] ||= BASE_URI
|
21
|
+
@base_uri = options[:base_uri]
|
22
|
+
options[:format] ||= :json
|
23
|
+
options.each do |k,v|
|
24
|
+
self.class.send k, v
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Account
|
29
|
+
|
30
|
+
def balance options={}
|
31
|
+
h = get '/account/balance', options
|
32
|
+
h['amount'].to_money(h['currency'])
|
33
|
+
end
|
34
|
+
|
35
|
+
def accounts options={}
|
36
|
+
accts = get '/accounts', options
|
37
|
+
accts = convert_money_objects(accts)
|
38
|
+
accts
|
39
|
+
end
|
40
|
+
|
41
|
+
def receive_address options={}
|
42
|
+
get '/account/receive_address', options
|
43
|
+
end
|
44
|
+
|
45
|
+
def generate_receive_address options={}
|
46
|
+
post '/account/generate_receive_address', options
|
47
|
+
end
|
48
|
+
|
49
|
+
# Buttons
|
50
|
+
|
51
|
+
def create_button name, price, description=nil, custom=nil, options={}
|
52
|
+
options[:button] ||= {}
|
53
|
+
options[:button][:name] ||= name
|
54
|
+
price = price.to_money("BTC") unless price.is_a?(Money)
|
55
|
+
options[:button][:price_string] ||= price.to_s
|
56
|
+
options[:button][:price_currency_iso] ||= price.currency.iso_code
|
57
|
+
options[:button][:description] ||= description
|
58
|
+
options[:button][:custom] ||= custom
|
59
|
+
r = post '/buttons', options
|
60
|
+
if r.success?
|
61
|
+
r.embed_html = case options[:button_mode]
|
62
|
+
when 'page'
|
63
|
+
%[<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>]
|
64
|
+
when 'iframe'
|
65
|
+
%[<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>]
|
66
|
+
else
|
67
|
+
%[<div class="coinbase-button" data-code="#{r.button.code}"></div><script src="https://coinbase.com/assets/button.js" type="text/javascript"></script>]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
r
|
71
|
+
end
|
72
|
+
|
73
|
+
def create_order_for_button button_id
|
74
|
+
post "/buttons/#{button_id}/create_order"
|
75
|
+
end
|
76
|
+
|
77
|
+
# Addresses
|
78
|
+
|
79
|
+
def addresses page=1, options={}
|
80
|
+
get '/addresses', {page: page}.merge(options)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Currencies
|
84
|
+
|
85
|
+
def exchange_rates
|
86
|
+
get('/currencies/exchange_rates')
|
87
|
+
end
|
88
|
+
|
89
|
+
def currencies_short
|
90
|
+
currencies.collect { |c| c[1] }
|
91
|
+
end
|
92
|
+
|
93
|
+
def currencies_long
|
94
|
+
currencies.collect { |c| c[0] }
|
95
|
+
end
|
96
|
+
|
97
|
+
def currencies
|
98
|
+
eval(self.class.send(:get, '/currencies'))
|
99
|
+
end
|
100
|
+
private :currencies
|
101
|
+
|
102
|
+
# Transactions
|
103
|
+
|
104
|
+
def transactions page=1, options ={}
|
105
|
+
r = get '/transactions', {page: page}.merge(options)
|
106
|
+
r.transactions ||= []
|
107
|
+
convert_money_objects(r.transactions)
|
108
|
+
r
|
109
|
+
end
|
110
|
+
|
111
|
+
def transaction transaction_id
|
112
|
+
r = get "/transactions/#{transaction_id}"
|
113
|
+
convert_money_objects(r.transaction)
|
114
|
+
r
|
115
|
+
end
|
116
|
+
|
117
|
+
def send_money to, amount, notes=nil, options={}
|
118
|
+
options[:transaction] ||= {}
|
119
|
+
options[:transaction][:to] ||= to
|
120
|
+
amount = amount.to_money("BTC") unless amount.is_a?(Money)
|
121
|
+
options[:transaction][:amount_string] ||= amount.to_s
|
122
|
+
options[:transaction][:amount_currency_iso] ||= amount.currency.iso_code
|
123
|
+
options[:transaction][:notes] ||= notes
|
124
|
+
r = post '/transactions/send_money', options
|
125
|
+
if amt = r.transaction.amount
|
126
|
+
r.transaction.amount = amt.amount.to_money(amt.currency)
|
127
|
+
end
|
128
|
+
r
|
129
|
+
end
|
130
|
+
|
131
|
+
def request_money from, amount, notes=nil, options={}
|
132
|
+
options[:transaction] ||= {}
|
133
|
+
options[:transaction][:from] ||= from
|
134
|
+
amount = amount.to_money("BTC") unless amount.is_a?(Money)
|
135
|
+
options[:transaction][:amount_string] ||= amount.to_s
|
136
|
+
options[:transaction][:amount_currency_iso] ||= amount.currency.iso_code
|
137
|
+
options[:transaction][:notes] ||= notes
|
138
|
+
r = post '/transactions/request_money', options
|
139
|
+
if amt = r.transaction.amount
|
140
|
+
r.transaction.amount = amt.amount.to_money(amt.currency)
|
141
|
+
end
|
142
|
+
r
|
143
|
+
end
|
144
|
+
|
145
|
+
def resend_request transaction_id
|
146
|
+
put "/transactions/#{transaction_id}/resend_request"
|
147
|
+
end
|
148
|
+
|
149
|
+
def cancel_request transaction_id
|
150
|
+
delete "/transactions/#{transaction_id}/cancel_request"
|
151
|
+
end
|
152
|
+
|
153
|
+
def complete_request transaction_id
|
154
|
+
put "/transactions/#{transaction_id}/complete_request"
|
155
|
+
end
|
156
|
+
|
157
|
+
# Users
|
158
|
+
|
159
|
+
def create_user email, password=nil, client_id=nil, scopes=nil
|
160
|
+
password ||= SecureRandom.urlsafe_base64(12)
|
161
|
+
options = {user: {email: email, password: password}}
|
162
|
+
if client_id
|
163
|
+
options[:client_id] = client_id
|
164
|
+
raise Error.new("Invalid scopes parameter; must be an array") if !scopes.is_a?(Array)
|
165
|
+
options[:scopes] = scopes.join(' ')
|
166
|
+
end
|
167
|
+
post '/users', options
|
168
|
+
end
|
169
|
+
|
170
|
+
# Prices
|
171
|
+
|
172
|
+
def buy_price qty=1
|
173
|
+
r = get '/prices/buy', {qty: qty}
|
174
|
+
r['amount'].to_money(r['currency'])
|
175
|
+
end
|
176
|
+
|
177
|
+
def sell_price qty=1
|
178
|
+
r = get '/prices/sell', {qty: qty}
|
179
|
+
r['amount'].to_money(r['currency'])
|
180
|
+
end
|
181
|
+
|
182
|
+
def spot_price currency='USD'
|
183
|
+
r = get '/prices/spot_rate', {currency: currency}
|
184
|
+
r['amount'].to_money(r['currency'])
|
185
|
+
end
|
186
|
+
|
187
|
+
# Buys
|
188
|
+
|
189
|
+
def buy! qty
|
190
|
+
r = post '/buys', {qty: qty}
|
191
|
+
r = convert_money_objects(r)
|
192
|
+
r.transfer.payout_date = Time.parse(r.transfer.payout_date) rescue nil
|
193
|
+
r
|
194
|
+
end
|
195
|
+
|
196
|
+
# Sells
|
197
|
+
|
198
|
+
def sell! qty
|
199
|
+
r = post '/sells', {qty: qty}
|
200
|
+
r = convert_money_objects(r)
|
201
|
+
r.transfer.payout_date = Time.parse(r.transfer.payout_date) rescue nil
|
202
|
+
r
|
203
|
+
end
|
204
|
+
|
205
|
+
# Transfers
|
206
|
+
|
207
|
+
def transfers options={}
|
208
|
+
r = get '/transfers', options
|
209
|
+
r = convert_money_objects(r)
|
210
|
+
r.transfers.each do |t|
|
211
|
+
t.transfer.payout_date = Time.parse(t.transfer.payout_date) rescue nil
|
212
|
+
end
|
213
|
+
r
|
214
|
+
end
|
215
|
+
|
216
|
+
# Wrappers for the main HTTP verbs
|
217
|
+
|
218
|
+
def get(path, options={})
|
219
|
+
http_verb :get, path, options
|
220
|
+
end
|
221
|
+
|
222
|
+
def post(path, options={})
|
223
|
+
http_verb :post, path, options
|
224
|
+
end
|
225
|
+
|
226
|
+
def put(path, options={})
|
227
|
+
http_verb :put, path, options
|
228
|
+
end
|
229
|
+
|
230
|
+
def delete(path, options={})
|
231
|
+
http_verb :delete, path, options
|
232
|
+
end
|
233
|
+
|
234
|
+
def self.whitelisted_cert_store
|
235
|
+
@@cert_store ||= build_whitelisted_cert_store
|
236
|
+
end
|
237
|
+
|
238
|
+
def self.build_whitelisted_cert_store
|
239
|
+
path = File.expand_path(File.join(File.dirname(__FILE__), 'ca-coinbase.crt'))
|
240
|
+
|
241
|
+
certs = [ [] ]
|
242
|
+
File.readlines(path).each{|line|
|
243
|
+
next if ["\n","#"].include?(line[0])
|
244
|
+
certs.last << line
|
245
|
+
certs << [] if line == "-----END CERTIFICATE-----\n"
|
246
|
+
}
|
247
|
+
|
248
|
+
result = OpenSSL::X509::Store.new
|
249
|
+
|
250
|
+
certs.each{|lines|
|
251
|
+
next if lines.empty?
|
252
|
+
cert = OpenSSL::X509::Certificate.new(lines.join)
|
253
|
+
result.add_cert(cert)
|
254
|
+
}
|
255
|
+
|
256
|
+
result
|
257
|
+
end
|
258
|
+
|
259
|
+
def ssl_options
|
260
|
+
{ verify: true, cert_store: self.class.whitelisted_cert_store }
|
261
|
+
end
|
262
|
+
|
263
|
+
def http_verb(verb, path, options={})
|
264
|
+
|
265
|
+
nonce = options[:nonce] || (Time.now.to_f * 1e6).to_i
|
266
|
+
|
267
|
+
if [:get, :delete].include? verb
|
268
|
+
request_options = {}
|
269
|
+
path = "#{path}?#{URI.encode_www_form(options)}" if !options.empty?
|
270
|
+
hmac_message = nonce.to_s + @base_uri + path
|
271
|
+
else
|
272
|
+
request_options = {body: options.to_json}
|
273
|
+
hmac_message = nonce.to_s + @base_uri + path + options.to_json
|
274
|
+
end
|
275
|
+
|
276
|
+
signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), @api_secret, hmac_message)
|
277
|
+
|
278
|
+
headers = {
|
279
|
+
'ACCESS_KEY' => @api_key,
|
280
|
+
'ACCESS_SIGNATURE' => signature,
|
281
|
+
'ACCESS_NONCE' => nonce.to_s,
|
282
|
+
"Content-Type" => "application/json",
|
283
|
+
}
|
284
|
+
|
285
|
+
request_options[:headers] = headers
|
286
|
+
|
287
|
+
r = self.class.send(verb, path, request_options.merge(ssl_options))
|
288
|
+
hash = Hashie::Mash.new(JSON.parse(r.body))
|
289
|
+
raise Error.new(hash.error) if hash.error
|
290
|
+
raise Error.new(hash.errors.join(", ")) if hash.errors
|
291
|
+
hash
|
292
|
+
end
|
293
|
+
|
294
|
+
class Error < StandardError; end
|
295
|
+
|
296
|
+
private
|
297
|
+
|
298
|
+
def convert_money_objects obj
|
299
|
+
if obj.is_a?(Array)
|
300
|
+
obj.each_with_index do |o, i|
|
301
|
+
obj[i] = convert_money_objects(o)
|
302
|
+
end
|
303
|
+
elsif obj.is_a?(Hash)
|
304
|
+
if obj[:amount] && (obj[:currency] || obj[:currency_iso])
|
305
|
+
obj = obj[:amount].to_money((obj[:currency] || obj[:currency_iso]))
|
306
|
+
else
|
307
|
+
obj.each do |k,v|
|
308
|
+
obj[k] = convert_money_objects(v)
|
309
|
+
end
|
310
|
+
end
|
311
|
+
end
|
312
|
+
obj
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'oauth2'
|
2
|
+
|
3
|
+
module BetterCoinbase
|
4
|
+
class OAuthClient < Client
|
5
|
+
|
6
|
+
AUTHORIZE_URL = 'https://coinbase.com/oauth/authorize'
|
7
|
+
TOKEN_URL = 'https://coinbase.com/oauth/token'
|
8
|
+
|
9
|
+
# Initializes a Coinbase Client using OAuth 2.0 credentials
|
10
|
+
#
|
11
|
+
# @param [String] client_id this application's Coinbase OAuth2 CLIENT_ID
|
12
|
+
# @param [String] client_secret this application's Coinbase OAuth2 CLIENT_SECRET
|
13
|
+
# @param [Hash] user_credentials OAuth 2.0 credentials to use
|
14
|
+
# @option user_credentials [String] access_token Must pass either this or token
|
15
|
+
# @option user_credentials [String] token Must pass either this or access_token
|
16
|
+
# @option user_credentials [String] refresh_token Optional
|
17
|
+
# @option user_credentials [Integer] expires_at Optional
|
18
|
+
# @option user_credentials [Integer] expires_in Optional
|
19
|
+
#
|
20
|
+
# Please note access tokens will be automatically refreshed when expired
|
21
|
+
# Use the credentials method when finished with the client to retrieve up-to-date credentials
|
22
|
+
def initialize(client_id, client_secret, user_credentials, options={})
|
23
|
+
client_opts = {
|
24
|
+
:site => options[:base_uri] || BASE_URI,
|
25
|
+
:authorize_url => options[:authorize_url] || AUTHORIZE_URL,
|
26
|
+
:token_url => options[:token_url] || TOKEN_URL,
|
27
|
+
:ssl => {
|
28
|
+
:verify => true,
|
29
|
+
:cert_store => ::BetterCoinbase::Client.whitelisted_cert_store
|
30
|
+
}
|
31
|
+
}
|
32
|
+
@oauth_client = OAuth2::Client.new(client_id, client_secret, client_opts)
|
33
|
+
token_hash = user_credentials.dup
|
34
|
+
token_hash[:access_token] ||= token_hash[:token]
|
35
|
+
token_hash.delete :expires
|
36
|
+
raise "No access token provided" unless token_hash[:access_token]
|
37
|
+
@oauth_token = OAuth2::AccessToken.from_hash(@oauth_client, token_hash)
|
38
|
+
end
|
39
|
+
|
40
|
+
def http_verb(verb, path, options={})
|
41
|
+
path = remove_leading_slash(path)
|
42
|
+
|
43
|
+
if [:get, :delete].include? verb
|
44
|
+
request_options = {params: options}
|
45
|
+
else
|
46
|
+
request_options = {headers: {"Content-Type" => "application/json"}, body: options.to_json}
|
47
|
+
end
|
48
|
+
response = oauth_token.request(verb, path, request_options)
|
49
|
+
|
50
|
+
hash = Hashie::Mash.new(JSON.parse(response.body))
|
51
|
+
raise Error.new(hash.error) if hash.error
|
52
|
+
raise Error.new(hash.errors.join(", ")) if hash.errors
|
53
|
+
hash
|
54
|
+
end
|
55
|
+
|
56
|
+
def refresh!
|
57
|
+
raise "Access token not initialized." unless @oauth_token
|
58
|
+
@oauth_token = @oauth_token.refresh!
|
59
|
+
end
|
60
|
+
|
61
|
+
def oauth_token
|
62
|
+
raise "Access token not initialized." unless @oauth_token
|
63
|
+
refresh! if @oauth_token.expired?
|
64
|
+
@oauth_token
|
65
|
+
end
|
66
|
+
|
67
|
+
def credentials
|
68
|
+
@oauth_token.to_hash
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def remove_leading_slash(path)
|
74
|
+
path.sub(/^\//, '')
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
data/spec/client_spec.rb
ADDED
@@ -0,0 +1,429 @@
|
|
1
|
+
require 'fakeweb'
|
2
|
+
require 'better-coinbase'
|
3
|
+
|
4
|
+
describe BetterCoinbase::Client do
|
5
|
+
BASE_URI = 'http://fake.com/api/v1' # switching to http (instead of https) seems to help FakeWeb
|
6
|
+
|
7
|
+
before :all do
|
8
|
+
@c = BetterCoinbase::Client.new 'api key', 'api secret', {base_uri: BASE_URI}
|
9
|
+
FakeWeb.allow_net_connect = false
|
10
|
+
end
|
11
|
+
|
12
|
+
# Auth and Errors
|
13
|
+
|
14
|
+
it "raise errors" do
|
15
|
+
fake :get, '/account/balance', {error: "some error"}
|
16
|
+
expect{ @c.balance }.to raise_error(BetterCoinbase::Client::Error, 'some error')
|
17
|
+
fake :get, '/account/balance', {errors: ["some", "error"]}
|
18
|
+
expect{ @c.balance }.to raise_error(BetterCoinbase::Client::Error, 'some, error')
|
19
|
+
end
|
20
|
+
|
21
|
+
# Account
|
22
|
+
|
23
|
+
it "should get balance" do
|
24
|
+
fake :get, '/account/balance', {amount: "50.00000000", currency: 'BTC'}
|
25
|
+
@c.balance.should == 50.to_money('BTC')
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should get a receive address" do
|
29
|
+
fake :get, '/account/receive_address', {address: "muVu2JZo8PbewBHRp6bpqFvVD87qvqEHWA", callback_url: nil}
|
30
|
+
a = @c.receive_address
|
31
|
+
a.address.should == "muVu2JZo8PbewBHRp6bpqFvVD87qvqEHWA"
|
32
|
+
a.callback_url.should == nil
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should generate new receive addresses" do
|
36
|
+
fake :post, '/account/generate_receive_address', {address: "mmxJyTdxHUJUDoptwLHAGxLEd1rAxDJ7EV", callback_url: "http://example.com/callback"}
|
37
|
+
a = @c.generate_receive_address
|
38
|
+
a.address.should == "mmxJyTdxHUJUDoptwLHAGxLEd1rAxDJ7EV"
|
39
|
+
a.callback_url.should == "http://example.com/callback"
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should list accounts" do
|
43
|
+
accounts_response = <<-eos
|
44
|
+
{
|
45
|
+
"accounts": [
|
46
|
+
{
|
47
|
+
"id": "536a541fa9393bb3c7000023",
|
48
|
+
"name": "My Wallet",
|
49
|
+
"balance": {
|
50
|
+
"amount": "50.00000000",
|
51
|
+
"currency": "BTC"
|
52
|
+
},
|
53
|
+
"native_balance": {
|
54
|
+
"amount": "500.12",
|
55
|
+
"currency": "USD"
|
56
|
+
},
|
57
|
+
"created_at": "2014-05-07T08:41:19-07:00",
|
58
|
+
"primary": true,
|
59
|
+
"active": true
|
60
|
+
},
|
61
|
+
{
|
62
|
+
"id": "536a541fa9393bb3c7000034",
|
63
|
+
"name": "Savings",
|
64
|
+
"balance": {
|
65
|
+
"amount": "0.00000000",
|
66
|
+
"currency": "BTC"
|
67
|
+
},
|
68
|
+
"native_balance": {
|
69
|
+
"amount": "0.00",
|
70
|
+
"currency": "USD"
|
71
|
+
},
|
72
|
+
"created_at": "2014-05-07T08:50:10-07:00",
|
73
|
+
"primary": false,
|
74
|
+
"active": true
|
75
|
+
}
|
76
|
+
],
|
77
|
+
"total_count": 2,
|
78
|
+
"num_pages": 1,
|
79
|
+
"current_page": 1
|
80
|
+
}
|
81
|
+
eos
|
82
|
+
|
83
|
+
fake :get, '/accounts', JSON.parse(accounts_response)
|
84
|
+
r = @c.accounts
|
85
|
+
r.total_count.should == 2
|
86
|
+
primary_account = r.accounts.select { |acct| acct.primary }.first
|
87
|
+
primary_account.id.should == "536a541fa9393bb3c7000023"
|
88
|
+
primary_account.balance.should == 50.to_money("BTC")
|
89
|
+
|
90
|
+
# Make sure paging works
|
91
|
+
fake :get, '/accounts?page=2', JSON.parse(accounts_response)
|
92
|
+
r = @c.accounts :page => 2
|
93
|
+
FakeWeb.last_request.path.should include("page=2")
|
94
|
+
end
|
95
|
+
|
96
|
+
# Buttons
|
97
|
+
|
98
|
+
it "should create a new button" do
|
99
|
+
response = {:success=>true, :button=>{:code=>"93865b9cae83706ae59220c013bc0afd", :type=>"buy_now", :style=>"custom_large", :text=>"Pay With Bitcoin", :name=>"Order 123", :description=>"Sample description", :custom=>"Order123", :price=>{:cents=>123, :currency_iso=>"BTC"}}}
|
100
|
+
fake :post, '/buttons', response
|
101
|
+
r = @c.create_button "Order 123", 1.23, "Sample description"
|
102
|
+
|
103
|
+
# Ensure BTC is assumed to be the default currency
|
104
|
+
post_params = JSON.parse(FakeWeb.last_request.body)
|
105
|
+
post_params['button']['price_currency_iso'].should == "BTC"
|
106
|
+
post_params['button']['price_string'].should == "1.23000000"
|
107
|
+
|
108
|
+
r.success?.should == true
|
109
|
+
r.button.name.should == "Order 123"
|
110
|
+
r.embed_html.should == %[<div class="coinbase-button" data-code="93865b9cae83706ae59220c013bc0afd"></div><script src="https://coinbase.com/assets/button.js" type="text/javascript"></script>]
|
111
|
+
|
112
|
+
r = @c.create_button "Order 123", 1.23, "Sample description", nil, button_mode: 'page'
|
113
|
+
r.success?.should == true
|
114
|
+
r.button.name.should == "Order 123"
|
115
|
+
r.embed_html.should == %[<a href="https://coinbase.com/checkouts/93865b9cae83706ae59220c013bc0afd" target="_blank"><img alt="Pay With Bitcoin" src="https://coinbase.com/assets/buttons/custom_large.png"></a>]
|
116
|
+
|
117
|
+
r = @c.create_button "Order 123", 1.23, "Sample description", nil, button_mode: 'iframe'
|
118
|
+
r.success?.should == true
|
119
|
+
r.button.name.should == "Order 123"
|
120
|
+
r.embed_html.should == %[<iframe src="https://coinbase.com/inline_payments/93865b9cae83706ae59220c013bc0afd" 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>]
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should create a new button with price in USD" do
|
124
|
+
response = {:success=>true, :button=>{:code=>"93865b9cae83706ae59220c013bc0afd", :type=>"buy_now", :style=>"custom_large", :text=>"Pay With Bitcoin", :name=>"Order 123", :description=>"Sample description", :custom=>"Order123", :price=>{:cents=>123, :currency_iso=>"USD"}}}
|
125
|
+
fake :post, '/buttons', response
|
126
|
+
r = @c.create_button "Order 123", 1.23.to_money("USD"), "Sample description"
|
127
|
+
|
128
|
+
post_params = JSON.parse(FakeWeb.last_request.body)
|
129
|
+
post_params['button']['price_currency_iso'].should == "USD"
|
130
|
+
post_params['button']['price_string'].should == "1.23"
|
131
|
+
|
132
|
+
r.success?.should == true
|
133
|
+
r.button.name.should == "Order 123"
|
134
|
+
r.embed_html.should == %[<div class="coinbase-button" data-code="93865b9cae83706ae59220c013bc0afd"></div><script src="https://coinbase.com/assets/button.js" type="text/javascript"></script>]
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should create order for the button" do
|
138
|
+
response = {"success"=>true, "order"=>{"id"=>"UAHXEK24", "created_at"=>"2013-12-13T01:15:56-08:00", "status"=>"new", "total_btc"=>{"cents"=>123, "currency_iso"=>"BTC"}, "total_native"=>{"cents"=>123, "currency_iso"=>"BTC"}, "custom"=>"Order123", "receive_address"=>"1EWxf61QGAkQDNUDq6XynH2PdFRyZUm111", "button"=>{"type"=>"buy_now", "name"=>"Order 123", "description"=>"Sample description", "id"=>"93865b9cae83706ae59220c013bc0afd"}, "transaction"=>nil}}
|
139
|
+
fake :post, '/buttons/93865b9cae83706ae59220c013bc0afd/create_order', response
|
140
|
+
r = @c.create_order_for_button "93865b9cae83706ae59220c013bc0afd"
|
141
|
+
r.order.button.id.should == "93865b9cae83706ae59220c013bc0afd"
|
142
|
+
r.order.status.should == "new"
|
143
|
+
end
|
144
|
+
|
145
|
+
# Transactions
|
146
|
+
|
147
|
+
it "should get transaction list" do
|
148
|
+
response = {"current_user"=>{"id"=>"5011f33df8182b142400000e", "email"=>"user2@example.com", "name"=>"user2@example.com"}, "balance"=>{"amount"=>"50.00000000", "currency"=>"BTC"}, "total_count"=>2, "num_pages"=>1, "current_page"=>1, "transactions"=>[{"transaction"=>{"id"=>"5018f833f8182b129c00002f", "created_at"=>"2012-08-01T02:34:43-07:00", "amount"=>{"amount"=>"-1.10000000", "currency"=>"BTC"}, "request"=>true, "status"=>"pending", "sender"=>{"id"=>"5011f33df8182b142400000e", "name"=>"User Two", "email"=>"user2@example.com"}, "recipient"=>{"id"=>"5011f33df8182b142400000a", "name"=>"User One", "email"=>"user1@example.com"}}}, {"transaction"=>{"id"=>"5018f833f8182b129c00002e", "created_at"=>"2012-08-01T02:36:43-07:00", "hsh" => "9d6a7d1112c3db9de5315b421a5153d71413f5f752aff75bf504b77df4e646a3", "amount"=>{"amount"=>"-1.00000000", "currency"=>"BTC"}, "request"=>false, "status"=>"complete", "sender"=>{"id"=>"5011f33df8182b142400000e", "name"=>"User Two", "email"=>"user2@example.com"}, "recipient_address"=>"37muSN5ZrukVTvyVh3mT5Zc5ew9L9CBare"}}]}
|
149
|
+
fake :get, '/transactions?page=1', response
|
150
|
+
r = @c.transactions
|
151
|
+
r.transactions.first.transaction.id.should == '5018f833f8182b129c00002f'
|
152
|
+
r.transactions.last.transaction.hsh.should == '9d6a7d1112c3db9de5315b421a5153d71413f5f752aff75bf504b77df4e646a3'
|
153
|
+
r.transactions.first.transaction.amount.should == "-1.1".to_money("BTC")
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should get transaction detail" do
|
157
|
+
response = {"transaction"=>{"id"=>"5011f33df8182b142400000e", "created_at"=>"2013-12-19T05:20:15-08:00", "hsh"=>"ff11a892bc6f7c345a5d74d52b0878f6a7e5011f33df8182b142400000e", "amount"=>{"amount"=>"-0.01000000", "currency"=>"BTC"}, "request"=>false, "status"=>"pending", "sender"=>{"id"=>"5011f33df8182b142400000e", "email"=>"tuser2@example.com", "name"=>"User Two"}, "recipient_address"=>"1EWxf61QGAkQDNUDq6XynH2PdFRyZUm111", "notes"=>""}}
|
158
|
+
fake :get, "/transactions/5011f33df8182b142400000e", response
|
159
|
+
r = @c.transaction "5011f33df8182b142400000e"
|
160
|
+
r.transaction.id.should == "5011f33df8182b142400000e"
|
161
|
+
r.transaction.status.should == "pending"
|
162
|
+
r.transaction.amount.should == "-0.01".to_money("BTC")
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should not fail if there are no transactions" do
|
166
|
+
response = {"current_user"=>{"id"=>"5011f33df8182b142400000e", "email"=>"user2@example.com", "name"=>"user2@example.com"}, "balance"=>{"amount"=>"0.00000000", "currency"=>"BTC"}, "total_count"=>0, "num_pages"=>0, "current_page"=>1}
|
167
|
+
fake :get, '/transactions?page=1', response
|
168
|
+
r = @c.transactions
|
169
|
+
r.transactions.should_not be_nil
|
170
|
+
end
|
171
|
+
|
172
|
+
it "should send money in BTC" do
|
173
|
+
response = {"success"=>true, "transaction"=>{"id"=>"501a1791f8182b2071000087", "created_at"=>"2012-08-01T23:00:49-07:00", "notes"=>"Sample transaction for you!", "amount"=>{"amount"=>"-1.23400000", "currency"=>"BTC"}, "request"=>false, "status"=>"pending", "sender"=>{"id"=>"5011f33df8182b142400000e", "name"=>"User Two", "email"=>"user2@example.com"}, "recipient"=>{"id"=>"5011f33df8182b142400000a", "name"=>"User One", "email"=>"user1@example.com"}}}
|
174
|
+
fake :post, '/transactions/send_money', response
|
175
|
+
r = @c.send_money "user1@example.com", 1.2345, "Sample transaction for you"
|
176
|
+
|
177
|
+
# Ensure BTC is assumed to be the default currency
|
178
|
+
post_params = JSON.parse(FakeWeb.last_request.body)
|
179
|
+
post_params['transaction']['amount_currency_iso'].should == "BTC"
|
180
|
+
post_params['transaction']['amount_string'].should == "1.23450000"
|
181
|
+
|
182
|
+
r.success.should == true
|
183
|
+
r.transaction.id.should == '501a1791f8182b2071000087'
|
184
|
+
end
|
185
|
+
|
186
|
+
it "should send money in USD" do
|
187
|
+
response = {"success"=>true, "transaction"=>{"id"=>"501a1791f8182b2071000087", "created_at"=>"2012-08-01T23:00:49-07:00", "notes"=>"Sample transaction for you!", "amount"=>{"amount"=>"-1.23400000", "currency"=>"BTC"}, "request"=>false, "status"=>"pending", "sender"=>{"id"=>"5011f33df8182b142400000e", "name"=>"User Two", "email"=>"user2@example.com"}, "recipient"=>{"id"=>"5011f33df8182b142400000a", "name"=>"User One", "email"=>"user1@example.com"}}}
|
188
|
+
fake :post, '/transactions/send_money', response
|
189
|
+
r = @c.send_money "user1@example.com", 500.to_money("USD"), "Sample transaction for you"
|
190
|
+
|
191
|
+
post_params = JSON.parse(FakeWeb.last_request.body)
|
192
|
+
post_params['transaction']['amount_currency_iso'].should == "USD"
|
193
|
+
post_params['transaction']['amount_string'].should == "500.00"
|
194
|
+
|
195
|
+
r.success.should == true
|
196
|
+
r.transaction.id.should == '501a1791f8182b2071000087'
|
197
|
+
end
|
198
|
+
|
199
|
+
it "should request money" do
|
200
|
+
response = {"success"=>true, "transaction"=>{"id"=>"501a3554f8182b2754000003", "created_at"=>"2012-08-02T01:07:48-07:00", "notes"=>"Sample request for you!", "amount"=>{"amount"=>"1.23400000", "currency"=>"BTC"}, "request"=>true, "status"=>"pending", "sender"=>{"id"=>"5011f33df8182b142400000a", "name"=>"User One", "email"=>"user1@example.com"}, "recipient"=>{"id"=>"5011f33df8182b142400000e", "name"=>"User Two", "email"=>"user2@example.com"}}}
|
201
|
+
fake :post, '/transactions/request_money', response
|
202
|
+
r = @c.request_money "user1@example.com", 1.2345, "Sample transaction for you"
|
203
|
+
|
204
|
+
# Ensure BTC is assumed to be the default currency
|
205
|
+
post_params = JSON.parse(FakeWeb.last_request.body)
|
206
|
+
post_params['transaction']['amount_currency_iso'].should == "BTC"
|
207
|
+
post_params['transaction']['amount_string'].should == "1.23450000"
|
208
|
+
|
209
|
+
r.success.should == true
|
210
|
+
r.transaction.id.should == '501a3554f8182b2754000003'
|
211
|
+
end
|
212
|
+
|
213
|
+
it "should request money in USD" do
|
214
|
+
response = {"success"=>true, "transaction"=>{"id"=>"501a3554f8182b2754000003", "created_at"=>"2012-08-02T01:07:48-07:00", "notes"=>"Sample request for you!", "amount"=>{"amount"=>"1.23400000", "currency"=>"BTC"}, "request"=>true, "status"=>"pending", "sender"=>{"id"=>"5011f33df8182b142400000a", "name"=>"User One", "email"=>"user1@example.com"}, "recipient"=>{"id"=>"5011f33df8182b142400000e", "name"=>"User Two", "email"=>"user2@example.com"}}}
|
215
|
+
fake :post, '/transactions/request_money', response
|
216
|
+
r = @c.request_money "user1@example.com", 500.to_money("USD"), "Sample transaction for you"
|
217
|
+
|
218
|
+
# Ensure BTC is assumed to be the default currency
|
219
|
+
post_params = JSON.parse(FakeWeb.last_request.body)
|
220
|
+
post_params['transaction']['amount_currency_iso'].should == "USD"
|
221
|
+
post_params['transaction']['amount_string'].should == "500.00"
|
222
|
+
|
223
|
+
r.success.should == true
|
224
|
+
r.transaction.id.should == '501a3554f8182b2754000003'
|
225
|
+
end
|
226
|
+
|
227
|
+
it "should resend requests" do
|
228
|
+
response = {"success"=>true}
|
229
|
+
fake :put, "/transactions/501a3554f8182b2754000003/resend_request", response
|
230
|
+
r = @c.resend_request '501a3554f8182b2754000003'
|
231
|
+
r.success.should == true
|
232
|
+
end
|
233
|
+
|
234
|
+
it "should cancel requests" do
|
235
|
+
response = {"success"=>true}
|
236
|
+
fake :delete, "/transactions/501a3554f8182b2754000003/cancel_request", response
|
237
|
+
r = @c.cancel_request '501a3554f8182b2754000003'
|
238
|
+
r.success.should == true
|
239
|
+
end
|
240
|
+
|
241
|
+
it "should resend requests" do
|
242
|
+
response = {"success"=>true}
|
243
|
+
fake :put, "/transactions/501a3554f8182b2754000003/complete_request", response
|
244
|
+
r = @c.complete_request '501a3554f8182b2754000003'
|
245
|
+
r.success.should == true
|
246
|
+
end
|
247
|
+
|
248
|
+
# Users
|
249
|
+
|
250
|
+
it "should let you create users" do
|
251
|
+
response = {"success"=>true, "user"=>{"id"=>"501a3d22f8182b2754000011", "name"=>"New User", "email"=>"newuser@example.com", "receive_address"=>"mpJKwdmJKYjiyfNo26eRp4j6qGwuUUnw9x"}}
|
252
|
+
fake :post, "/users", response
|
253
|
+
r = @c.create_user "newuser@example.com"
|
254
|
+
r.success.should == true
|
255
|
+
r.user.email.should == "newuser@example.com"
|
256
|
+
r.user.receive_address.should == "mpJKwdmJKYjiyfNo26eRp4j6qGwuUUnw9x"
|
257
|
+
end
|
258
|
+
|
259
|
+
it "should let you create users with OAuth" do
|
260
|
+
response = {
|
261
|
+
"success"=>true,
|
262
|
+
"oauth" => {
|
263
|
+
"access_token" => "the_access_token",
|
264
|
+
"refresh_token" => "the_refresh_token",
|
265
|
+
"scope" => "transactions buy sell",
|
266
|
+
"token_type" => "bearer"
|
267
|
+
},
|
268
|
+
"user" => {
|
269
|
+
"id"=>"501a3d22f8182b2754000011",
|
270
|
+
"name"=>"New User",
|
271
|
+
"email"=>"newuser@example.com",
|
272
|
+
"receive_address"=>"mpJKwdmJKYjiyfNo26eRp4j6qGwuUUnw9x"
|
273
|
+
}
|
274
|
+
}
|
275
|
+
fake :post, "/users", response
|
276
|
+
r = @c.create_user "newuser@example.com", "newpassword", "the_client_id", ['transactions', 'buy', 'sell']
|
277
|
+
r.success.should == true
|
278
|
+
r.oauth.access_token.should == "the_access_token"
|
279
|
+
r.user.email.should == "newuser@example.com"
|
280
|
+
r.user.receive_address.should == "mpJKwdmJKYjiyfNo26eRp4j6qGwuUUnw9x"
|
281
|
+
end
|
282
|
+
|
283
|
+
it "should not let you specify client_id without scopes" do
|
284
|
+
expect{ @c.create_user "newuser@example.com", "newpassword", "the_client_id" }.to raise_error(BetterCoinbase::Client::Error)
|
285
|
+
end
|
286
|
+
|
287
|
+
# Prices
|
288
|
+
|
289
|
+
it "should let you get buy, sell, and spot prices" do
|
290
|
+
fake :get, "/prices/buy?qty=1", {"amount"=>"13.85", "currency"=>"USD"}
|
291
|
+
r = @c.buy_price 1
|
292
|
+
r.to_f.should == 13.85
|
293
|
+
|
294
|
+
fake :get, "/prices/sell?qty=1", {"amount"=>"13.83", "currency"=>"USD"}
|
295
|
+
r = @c.sell_price 1
|
296
|
+
r.to_f.should == 13.83
|
297
|
+
|
298
|
+
fake :get, "/prices/spot_rate?currency=USD", {"amount"=>"13.84", "currency"=>"USD"}
|
299
|
+
r = @c.spot_price
|
300
|
+
r.to_f.should == 13.84
|
301
|
+
end
|
302
|
+
|
303
|
+
# Buys
|
304
|
+
|
305
|
+
it "should let you buy bitcoin" do
|
306
|
+
response = {"success"=>true, "transfer"=>{"_type"=>"AchDebit", "code"=>"6H7GYLXZ", "created_at"=>"2013-01-28T16:08:58-08:00", "fees"=>{"coinbase"=>{"cents"=>14, "currency_iso"=>"USD"}, "bank"=>{"cents"=>15, "currency_iso"=>"USD"}}, "status"=>"created", "payout_date"=>"2013-02-01T18:00:00-08:00", "btc"=>{"amount"=>"1.00000000", "currency"=>"BTC"}, "subtotal"=>{"amount"=>"13.55", "currency"=>"USD"}, "total"=>{"amount"=>"13.84", "currency"=>"USD"}}}
|
307
|
+
fake :post, "/buys", response
|
308
|
+
r = @c.buy! 1
|
309
|
+
r.success?.should == true
|
310
|
+
r.transfer.code.should == '6H7GYLXZ'
|
311
|
+
r.transfer.status.should == 'created'
|
312
|
+
r.transfer.btc.should == 1.to_money("BTC")
|
313
|
+
end
|
314
|
+
|
315
|
+
# Sells
|
316
|
+
|
317
|
+
it "should let you sell bitcoin" do
|
318
|
+
response = {"success"=>true, "transfer"=>{"_type"=>"AchCredit", "code"=>"RD2OC8AL", "created_at"=>"2013-01-28T16:32:35-08:00", "fees"=>{"coinbase"=>{"cents"=>14, "currency_iso"=>"USD"}, "bank"=>{"cents"=>15, "currency_iso"=>"USD"}}, "status"=>"created", "payout_date"=>"2013-02-01T18:00:00-08:00", "btc"=>{"amount"=>"1.00000000", "currency"=>"BTC"}, "subtotal"=>{"amount"=>"13.50", "currency"=>"USD"}, "total"=>{"amount"=>"13.21", "currency"=>"USD"}}}
|
319
|
+
fake :post, "/sells", response
|
320
|
+
r = @c.sell! 1
|
321
|
+
r.success?.should == true
|
322
|
+
r.transfer.code.should == 'RD2OC8AL'
|
323
|
+
r.transfer.status.should == 'created'
|
324
|
+
r.transfer.btc.should == 1.to_money("BTC")
|
325
|
+
end
|
326
|
+
|
327
|
+
# Transfers
|
328
|
+
|
329
|
+
it "should get recent transfers" do
|
330
|
+
response = {"transfers" => [{"transfer" => {"type" => "Buy", "code" => "QPCUCZHR", "created_at" => "2013-02-27T23:28:18-08:00", "fees" => {"coinbase" => {"cents" => 14, "currency_iso" => "USD"}, "bank" => {"cents" => 15, "currency_iso" => "USD"} }, "payout_date" => "2013-03-05T18:00:00-08:00", "transaction_id" => "5011f33df8182b142400000e", "status" => "Pending", "btc" => {"amount" => "1.00000000", "currency" => "BTC"}, "subtotal" => {"amount" => "13.55", "currency" => "USD"}, "total" => {"amount" => "13.84", "currency" => "USD"}, "description" => "Paid for with $13.84 from Test xxxxx3111."} } ], "total_count" => 1, "num_pages" => 1, "current_page" => 1 }
|
331
|
+
fake :get, "/transfers", response
|
332
|
+
r = @c.transfers
|
333
|
+
t = r.transfers.first.transfer
|
334
|
+
t.type.should == "Buy"
|
335
|
+
t.code.should == "QPCUCZHR"
|
336
|
+
t.status.should == "Pending"
|
337
|
+
t.btc.should == 1.to_money("BTC")
|
338
|
+
end
|
339
|
+
|
340
|
+
it "should support pagination" do
|
341
|
+
response = {"transfers" => [{"transfer" => {"type" => "Buy", "code" => "QPCUCZHZ", "created_at" => "2013-02-27T23:28:18-08:00", "fees" => {"coinbase" => {"cents" => 14, "currency_iso" => "USD"}, "bank" => {"cents" => 15, "currency_iso" => "USD"} }, "payout_date" => "2013-03-05T18:00:00-08:00", "transaction_id" => "5011f33df8182b142400000e", "status" => "Pending", "btc" => {"amount" => "1.00000000", "currency" => "BTC"}, "subtotal" => {"amount" => "13.55", "currency" => "USD"}, "total" => {"amount" => "13.84", "currency" => "USD"}, "description" => "Paid for with $13.84 from Test xxxxx3111."} } ], "total_count" => 1, "num_pages" => 1, "current_page" => 1 }
|
342
|
+
fake :get, "/transfers?page=2", response
|
343
|
+
r = @c.transfers :page => 2
|
344
|
+
t = r.transfers.first.transfer
|
345
|
+
t.type.should == "Buy"
|
346
|
+
t.code.should == "QPCUCZHZ"
|
347
|
+
t.status.should == "Pending"
|
348
|
+
t.btc.should == 1.to_money("BTC")
|
349
|
+
FakeWeb.last_request.path.should include("page=2")
|
350
|
+
end
|
351
|
+
|
352
|
+
# Addresses
|
353
|
+
|
354
|
+
it 'should read addresses json' do
|
355
|
+
raw_addresses = <<-eos
|
356
|
+
{
|
357
|
+
"addresses": [
|
358
|
+
{
|
359
|
+
"address": {
|
360
|
+
"address": "moLxGrqWNcnGq4A8Caq8EGP4n9GUGWanj4",
|
361
|
+
"callback_url": null,
|
362
|
+
"label": "My Label",
|
363
|
+
"created_at": "2013-05-09T23:07:08-07:00"
|
364
|
+
}
|
365
|
+
},
|
366
|
+
{
|
367
|
+
"address": {
|
368
|
+
"address": "mwigfecvyG4MZjb6R5jMbmNcs7TkzhUaCj",
|
369
|
+
"callback_url": null,
|
370
|
+
"label": null,
|
371
|
+
"created_at": "2013-05-09T17:50:37-07:00"
|
372
|
+
}
|
373
|
+
}
|
374
|
+
],
|
375
|
+
"total_count": 2,
|
376
|
+
"num_pages": 1,
|
377
|
+
"current_page": 1
|
378
|
+
}
|
379
|
+
eos
|
380
|
+
|
381
|
+
fake :get, '/addresses?page=1', JSON.parse(raw_addresses)
|
382
|
+
|
383
|
+
r = @c.addresses
|
384
|
+
r.total_count.should == 2
|
385
|
+
r.num_pages.should == 1
|
386
|
+
r.current_page.should == 1
|
387
|
+
r.addresses.size.should == 2
|
388
|
+
r.addresses.first.address.address.should == 'moLxGrqWNcnGq4A8Caq8EGP4n9GUGWanj4'
|
389
|
+
r.addresses.first.address.callback_url.should == nil
|
390
|
+
r.addresses.first.address.label.should == 'My Label'
|
391
|
+
r.addresses.first.addresscreated_at == '2013-05-09T23:07:08-07:00'
|
392
|
+
r.addresses[1].address.address.should == 'mwigfecvyG4MZjb6R5jMbmNcs7TkzhUaCj'
|
393
|
+
r.addresses[1].address.callback_url.should == nil
|
394
|
+
r.addresses[1].address.label.should == nil
|
395
|
+
r.addresses[1].address.created_at.should == '2013-05-09T17:50:37-07:00'
|
396
|
+
end
|
397
|
+
|
398
|
+
it 'should get a list of currency exchanges' do
|
399
|
+
response = {'gbp_to_usd'=>'1.633667', 'usd_to_bwp'=>'8.62852', 'usd_to_azn'=>'0.784167', 'eur_to_usd'=>'1.35924', 'usd_to_czk'=>'20.11621', 'czk_to_btc'=>'5.6e-05', 'btc_to_mga'=>'1999686.885067', 'btc_to_djf'=>'158147.411834', 'idr_to_btc'=>'0.0', 'mnt_to_usd'=>'0.00058', 'usd_to_ngn'=>'158.682199', 'usd_to_gbp'=>'0.61212', 'irr_to_btc'=>'0.0', 'ils_to_usd'=>'0.282751', 'ars_to_usd'=>'0.163763', 'usd_to_uyu'=>'21.16168', 'uyu_to_btc'=>'5.3e-05', 'pyg_to_btc'=>'0.0', 'usd_to_yer'=>'215.006099', 'pgk_to_usd'=>'0.387254', 'xcd_to_btc'=>'0.000416', 'usd_to_fjd'=>'1.870015', 'dop_to_btc'=>'2.7e-05', 'mvr_to_usd'=>'0.06503', 'eek_to_usd'=>'0.085636', 'nzd_to_btc'=>'0.000918', 'gnf_to_btc'=>'0.0', 'usd_to_gtq'=>'7.88508', 'bmd_to_usd'=>'1.0', 'btc_to_lbp'=>'1338220.674541', 'usd_to_omr'=>'0.385012', 'usd_to_sos'=>'1207.4067', 'usd_to_thb'=>'32.11708', 'srd_to_btc'=>'0.000343', 'btc_to_all'=>'91888.63729', 'usd_to_vnd'=>'21106.95', 'htg_to_usd'=>'0.025083', 'btc_to_bmd'=>'888.93805', 'kpw_to_usd'=>'0.0', 'lyd_to_usd'=>'0.804161', 'tzs_to_btc'=>'1.0e-06', 'lak_to_usd'=>'0.000125', 'usd_to_idr'=>'11907.583333', 'btc_to_bzd'=>'1770.195675', 'usd_to_gel'=>'1.6904', 'usd_to_kzt'=>'153.658001', 'uah_to_usd'=>'0.121707', 'usd_to_lkr'=>'131.201499', 'btc_to_zwl'=>'286553.630441', 'php_to_btc'=>'2.6e-05', 'ron_to_usd'=>'0.306263', 'btc_to_kyd'=>'734.803304', 'btc_to_cad'=>'940.246665', 'hkd_to_btc'=>'0.000145', 'usd_to_btc'=>'0.001125', 'nok_to_btc'=>'0.000185', 'top_to_usd'=>'0.548145', 'btc_to_xpf'=>'78126.987338', 'usd_to_kgs'=>'48.862875', 'usd_to_bnd'=>'1.25468', 'dzd_to_usd'=>'0.012516', 'vef_to_btc'=>'0.000179', 'usd_to_ars'=>'6.106376', 'syp_to_btc'=>'8.0e-06', 'ngn_to_btc'=>'7.0e-06', 'bgn_to_btc'=>'0.000782', 'lak_to_btc'=>'0.0', 'btc_to_cve'=>'71977.305019', 'mga_to_btc'=>'1.0e-06', 'idr_to_usd'=>'8.4e-05', 'btc_to_htg'=>'35439.725263', 'btc_to_ils'=>'3143.884978', 'mad_to_btc'=>'0.000136', 'usd_to_hnl'=>'20.52386', 'svc_to_btc'=>'0.000129', 'btc_to_ang'=>'1590.274614', 'hkd_to_usd'=>'0.12899', 'usd_to_nad'=>'10.20123', 'szl_to_btc'=>'0.00011', 'etb_to_usd'=>'0.052406', 'pkr_to_btc'=>'1.0e-05', 'usd_to_khr'=>'4003.966833', 'gnf_to_usd'=>'0.000144', 'btc_to_myr'=>'2870.615643', 'btc_to_top'=>'1621.720797', 'nad_to_btc'=>'0.00011', 'huf_to_usd'=>'0.004546', 'mkd_to_btc'=>'2.5e-05', 'lkr_to_btc'=>'9.0e-06', 'svc_to_usd'=>'0.114311', 'btc_to_lyd'=>'1105.422911', 'usd_to_bam'=>'1.440026', 'usd_to_svc'=>'8.74805', 'usd_to_tzs'=>'1609.666667', 'gbp_to_btc'=>'0.001838', 'btc_to_mop'=>'7097.761418', 'btc_to_jod'=>'629.416142', 'clp_to_usd'=>'0.001896', 'cad_to_usd'=>'0.945431', 'cny_to_btc'=>'0.000184', 'jod_to_btc'=>'0.001589', 'syp_to_usd'=>'0.007141', 'lvl_to_btc'=>'0.002175', 'btc_to_cny'=>'5422.419877', 'shp_to_btc'=>'0.001838', 'vef_to_usd'=>'0.158944', 'php_to_usd'=>'0.022869', 'mro_to_usd'=>'0.003427', 'tjs_to_btc'=>'0.000236', 'fkp_to_btc'=>'0.001838', 'bdt_to_usd'=>'0.012869', 'mkd_to_usd'=>'0.021979', 'lrd_to_usd'=>'0.012418', 'usd_to_kes'=>'87.034389', 'btc_to_ars'=>'5428.189974', 'usd_to_chf'=>'0.906341', 'usd_to_lak'=>'7987.781667', 'usd_to_bzd'=>'1.99136', 'usd_to_nzd'=>'1.225977', 'mvr_to_btc'=>'7.3e-05', 'usd_to_wst'=>'2.344837', 'nok_to_usd'=>'0.164135', 'tjs_to_usd'=>'0.209516', 'bob_to_usd'=>'0.144729', 'btc_to_cup'=>'20163.676005', 'afn_to_btc'=>'2.0e-05', 'vnd_to_btc'=>'0.0', 'bnd_to_usd'=>'0.797016', 'byr_to_btc'=>'0.0', 'aed_to_btc'=>'0.000306', 'hnl_to_btc'=>'5.5e-05', 'mmk_to_usd'=>'0.001018', 'zmk_to_btc'=>'0.0', 'usd_to_myr'=>'3.229264', 'usd_to_ils'=>'3.536675', 'usd_to_mdl'=>'13.1323', 'djf_to_usd'=>'0.005621', 'mnt_to_btc'=>'1.0e-06', 'usd_to_sbd'=>'7.143096', 'lbp_to_usd'=>'0.000664', 'aoa_to_btc'=>'1.2e-05', 'btc_to_vnd'=>'18762770.974447', 'btc_to_lak'=>'7100643.058889', 'dkk_to_usd'=>'0.182213', 'inr_to_btc'=>'1.8e-05', 'lrd_to_btc'=>'1.4e-05', 'pab_to_btc'=>'0.001125', 'usd_to_mga'=>'2249.523333', 'btc_to_awg'=>'1591.065769', 'usd_to_try'=>'2.015658', 'usd_to_qar'=>'3.641038', 'usd_to_lvl'=>'0.517161', 'bmd_to_btc'=>'0.001125', 'vuv_to_btc'=>'1.2e-05', 'usd_to_pen'=>'2.80238', 'usd_to_zmk'=>'5253.075255', 'usd_to_ttd'=>'6.41373', 'mwk_to_btc'=>'3.0e-06', 'btc_to_scr'=>'10736.55821', 'egp_to_btc'=>'0.000163', 'bam_to_btc'=>'0.000781', 'usd_to_kmf'=>'362.286958', 'btc_to_aed'=>'3264.928117', 'usd_to_shp'=>'0.61212', 'bbd_to_btc'=>'0.0', 'kes_to_usd'=>'0.01149', 'jpy_to_btc'=>'1.1e-05', 'wst_to_usd'=>'0.426469', 'gyd_to_usd'=>'0.004843', 'kgs_to_btc'=>'2.3e-05', 'btc_to_eek'=>'10380.418515', 'usd_to_php'=>'43.72676', 'sdg_to_usd'=>'0.225802', 'usd_to_isk'=>'120.165', 'scr_to_btc'=>'9.3e-05', 'cup_to_usd'=>'0.044086', 'std_to_btc'=>'0.0', 'usd_to_gip'=>'0.61212', 'usd_to_aud'=>'1.0963', 'usd_to_dzd'=>'79.89655', 'usd_to_xaf'=>'483.051199', 'usd_to_mro'=>'291.7967', 'clp_to_btc'=>'2.0e-06', 'bbd_to_usd'=>'0.0', 'mdl_to_btc'=>'8.6e-05', 'btc_to_pyg'=>'3929049.928111', 'xof_to_btc'=>'2.0e-06', 'kzt_to_btc'=>'7.0e-06', 'usd_to_irr'=>'24785.667967', 'usd_to_vuv'=>'96.5375', 'bif_to_btc'=>'1.0e-06', 'btc_to_gtq'=>'7009.347639', 'usd_to_bif'=>'1551.3184', 'btc_to_xof'=>'429968.666639', 'btc_to_ghs'=>'2020.911763', 'btc_to_kes'=>'77368.180041', 'usd_to_bbd'=>'2', 'usd_to_afn'=>'57.430025', 'usd_to_sdg'=>'4.428657', 'uzs_to_usd'=>'0.00046', 'btc_to_dzd'=>'71023.083359', 'btc_to_uyu'=>'18811.422554', 'usd_to_mnt'=>'1725.083333', 'egp_to_usd'=>'0.145211', 'btc_to_nio'=>'22379.602108', 'usd_to_mur'=>'30.35621', 'usd_to_fkp'=>'0.61212', 'twd_to_usd'=>'0.033739', 'btc_to_bif'=>'1379025.953425', 'nio_to_btc'=>'4.5e-05', 'bhd_to_usd'=>'2.652604', 'aoa_to_usd'=>'0.010273', 'tmm_to_usd'=>'0.350652', 'btc_to_bhd'=>'335.118978', 'kyd_to_btc'=>'0.001361', 'usd_to_mzn'=>'29.89945', 'jmd_to_btc'=>'1.1e-05', 'lbp_to_btc'=>'1.0e-06', 'btc_to_ngn'=>'141058.644549', 'sek_to_btc'=>'0.000171', 'try_to_usd'=>'0.496116', 'btc_to_mkd'=>'40444.556713', 'btc_to_gbp'=>'544.136759', 'aud_to_btc'=>'0.001026', 'xpf_to_usd'=>'0.011378', 'bzd_to_btc'=>'0.000565', 'usd_to_cdf'=>'921.303003', 'btc_to_bdt'=>'69075.748998', 'cup_to_btc'=>'5.0e-05', 'usd_to_lsl'=>'10.19269', 'btc_to_tnd'=>'1481.973513', 'btc_to_pln'=>'2744.550005', 'usd_to_btn'=>'62.405663', 'zar_to_btc'=>'0.00011', 'bob_to_btc'=>'0.000163', 'usd_to_top'=>'1.824335', 'amd_to_btc'=>'3.0e-06', 'btc_to_syp'=>'124475.771907', 'szl_to_usd'=>'0.098101', 'gip_to_usd'=>'1.633667', 'usd_to_mvr'=>'15.37749', 'thb_to_usd'=>'0.031136', 'bgn_to_usd'=>'0.694751', 'btc_to_gnf'=>'6165712.835153', 'rwf_to_btc'=>'2.0e-06', 'cny_to_usd'=>'0.163938', 'btc_to_mzn'=>'26578.758779', 'btc_to_bob'=>'6142.090788', 'btc_to_etb'=>'16962.395852', 'ern_to_usd'=>'0.066235', 'mmk_to_btc'=>'1.0e-06', 'btc_to_uzs'=>'1931941.125176', 'usd_to_kwd'=>'0.282781', 'btc_to_twd'=>'26347.794895', 'usd_to_clp'=>'527.4221', 'ghs_to_usd'=>'0.43987', 'brl_to_btc'=>'0.000485', 'btc_to_try'=>'1791.795092', 'usd_to_dkk'=>'5.488097', 'myr_to_btc'=>'0.000348', 'btc_to_svc'=>'7776.474508', 'kmf_to_btc'=>'3.0e-06', 'mxn_to_btc'=>'8.6e-05', 'nio_to_usd'=>'0.039721', 'uah_to_btc'=>'0.000137', 'ttd_to_btc'=>'0.000175', 'usd_to_sgd'=>'1.254902', 'usd_to_hrk'=>'5.615268', 'btc_to_thb'=>'28550.094467', 'mwk_to_usd'=>'0.002446', 'btc_to_aud'=>'974.542784', 'btc_to_vuv'=>'85815.857002', 'btc_to_php'=>'38870.380767', 'pyg_to_usd'=>'0.000226', 'scr_to_usd'=>'0.082795', 'btc_to_kwd'=>'251.374791', 'ugx_to_usd'=>'0.000396', 'btc_to_gmd'=>'33591.155476', 'zwl_to_btc'=>'3.0e-06', 'btc_to_zar'=>'9069.212668', 'btc_to_hkd'=>'6891.55268', 'btc_to_afn'=>'51051.734435', 'btc_to_fkp'=>'544.136759', 'xaf_to_btc'=>'2.0e-06', 'usd_to_nok'=>'6.092554', 'btc_to_kzt'=>'136592.443776', 'btc_to_btn'=>'55474.768376', 'amd_to_usd'=>'0.002449', 'usd_to_syp'=>'140.027499', 'usd_to_jpy'=>'102.181201', 'usd_to_sek'=>'6.570703', 'btc_to_clp'=>'468845.573101', 'sgd_to_usd'=>'0.796875', 'btc_to_qar'=>'3236.65722', 'czk_to_usd'=>'0.049711', 'usd_to_aoa'=>'97.343626', 'krw_to_usd'=>'0.000942', 'sar_to_usd'=>'0.266627', 'hnl_to_usd'=>'0.048724', 'bwp_to_usd'=>'0.115895', 'usd_to_brl'=>'2.319796', 'btc_to_bbd'=>'1777.8761', 'ngn_to_usd'=>'0.006302', 'azn_to_usd'=>'1.275239', 'btc_to_mnt'=>'1533492.214125', 'usd_to_rub'=>'33.12431', 'btc_to_lvl'=>'459.724091', 'usd_to_ron'=>'3.265171', 'btc_to_azn'=>'697.075884', 'sll_to_usd'=>'0.000232', 'usd_to_dop'=>'42.3681', 'pab_to_usd'=>'1.0', 'pkr_to_usd'=>'0.009223', 'usd_to_scr'=>'12.07796', 'usd_to_huf'=>'219.952799', 'bdt_to_btc'=>'1.4e-05', 'btc_to_crc'=>'439769.207752', 'std_to_usd'=>'5.5e-05', 'mzn_to_usd'=>'0.033445', 'mzn_to_btc'=>'3.8e-05', 'nzd_to_usd'=>'0.815676', 'btc_to_npr'=>'88656.014961', 'btc_to_bwp'=>'7670.219743', 'kwd_to_usd'=>'3.536305', 'omr_to_usd'=>'2.597322', 'btc_to_rwf'=>'600360.508519', 'kgs_to_usd'=>'0.020465', 'afn_to_usd'=>'0.017412', 'btc_to_egp'=>'6121.693216', 'aud_to_usd'=>'0.912159', 'usd_to_mwk'=>'408.8331', 'usd_to_cny'=>'6.099885', 'rwf_to_usd'=>'0.001481', 'usd_to_zwl'=>'322.355006', 'btc_to_cdf'=>'818981.294946', 'usd_to_tjs'=>'4.7729', 'usd_to_all'=>'103.369', 'bhd_to_btc'=>'0.002984', 'kpw_to_btc'=>'0.0', 'bam_to_usd'=>'0.694432', 'btc_to_szl'=>'9061.452238', 'usd_to_pyg'=>'4419.936719', 'gel_to_btc'=>'0.000666', 'xcd_to_usd'=>'0.370165', 'usd_to_lrd'=>'80.528251', 'sos_to_usd'=>'0.000828', 'usd_to_uzs'=>'2173.313568', 'btc_to_fjd'=>'1662.327488', 'btc_to_iqd'=>'1034670.598364', 'usd_to_bsd'=>'1', 'cve_to_btc'=>'1.4e-05', 'rub_to_btc'=>'3.4e-05', 'usd_to_rsd'=>'83.906211', 'sar_to_btc'=>'0.0003', 'eek_to_btc'=>'9.6e-05', 'btc_to_ugx'=>'2244746.378083', 'awg_to_btc'=>'0.000629', 'btc_to_mwk'=>'363427.298689', 'huf_to_btc'=>'5.0e-06', 'ang_to_usd'=>'0.558984', 'usd_to_djf'=>'177.905999', 'usd_to_cad'=>'1.057719', 'btc_to_brl'=>'2062.154933', 'usd_to_ern'=>'15.097825', 'iqd_to_btc'=>'1.0e-06', 'btc_to_pgk'=>'2295.489615', 'usd_to_xcd'=>'2.7015', 'btn_to_btc'=>'1.8e-05', 'myr_to_usd'=>'0.309668', 'lsl_to_usd'=>'0.09811', 'crc_to_usd'=>'0.002021', 'usd_to_egp'=>'6.886524', 'btc_to_rsd'=>'74587.423589', 'gel_to_usd'=>'0.591576', 'jmd_to_usd'=>'0.009719', 'btc_to_ltl'=>'2258.393341', 'lyd_to_btc'=>'0.000905', 'nad_to_usd'=>'0.098027', 'usd_to_kyd'=>'0.826608', 'btc_to_bsd'=>'888.93805', 'ltl_to_btc'=>'0.000443', 'usd_to_srd'=>'3.283333', 'usd_to_awg'=>'1.78985', 'usd_to_szl'=>'10.19357', 'chf_to_btc'=>'0.001241', 'zwl_to_usd'=>'0.003102', 'sll_to_btc'=>'0.0', 'usd_to_cop'=>'1927.433333', 'usd_to_tmm'=>'2.851833', 'btc_to_tjs'=>'4242.812419', 'sbd_to_btc'=>'0.000157', 'ern_to_btc'=>'7.5e-05', 'btc_to_bam'=>'1280.093904', 'btc_to_gip'=>'544.136759', 'sbd_to_usd'=>'0.139995', 'mad_to_usd'=>'0.121088', 'btc_to_ern'=>'13421.031115', 'usd_to_ltl'=>'2.540552', 'qar_to_usd'=>'0.274647', 'usd_to_kpw'=>'900', 'usd_to_crc'=>'494.712998', 'usd_to_xpf'=>'87.888', 'yer_to_btc'=>'5.0e-06', 'chf_to_usd'=>'1.103337', 'jpy_to_usd'=>'0.009787', 'ars_to_btc'=>'0.000184', 'usd_to_pgk'=>'2.582283', 'gyd_to_btc'=>'5.0e-06', 'aed_to_usd'=>'0.272269', 'usd_to_mop'=>'7.98454', 'usd_to_aed'=>'3.672841', 'qar_to_btc'=>'0.000309', 'btc_to_sll'=>'3837842.02269', 'btc_to_dkk'=>'4878.578245', 'gtq_to_usd'=>'0.126822', 'sos_to_btc'=>'1.0e-06', 'dop_to_usd'=>'0.023603', 'awg_to_usd'=>'0.558706', 'btc_to_gel'=>'1502.66088', 'btc_to_lkr'=>'116630.004678', 'btc_to_lrd'=>'71584.626414', 'khr_to_usd'=>'0.00025', 'btc_to_hrk'=>'4991.625386', 'usd_to_etb'=>'19.08164', 'btc_to_sos'=>'1073309.757455', 'btc_to_eur'=>'653.996168', 'usd_to_krw'=>'1061.26498', 'btc_to_dop'=>'37662.616196', 'usd_to_bob'=>'6.90947', 'btc_to_kgs'=>'43436.06882', 'cve_to_usd'=>'0.01235', 'fjd_to_usd'=>'0.534755', 'btc_to_jpy'=>'90832.757564', 'btc_to_omr'=>'342.251817', 'usd_to_gyd'=>'206.501249', 'pen_to_btc'=>'0.000401', 'btc_to_jmd'=>'91465.502779', 'npr_to_usd'=>'0.010027', 'usd_to_tnd'=>'1.667128', 'usd_to_twd'=>'29.63963', 'btc_to_nad'=>'9068.261504', 'azn_to_btc'=>'0.001435', 'btc_to_sgd'=>'1115.530137', 'twd_to_btc'=>'3.8e-05', 'btc_to_sek'=>'5840.947912', 'inr_to_usd'=>'0.016031', 'crc_to_btc'=>'2.0e-06', 'usd_to_mxn'=>'13.10359', 'xaf_to_usd'=>'0.00207', 'btc_to_idr'=>'10585103.90825', 'btc_to_hnl'=>'18244.440087', 'eur_to_btc'=>'0.001529', 'btc_to_sbd'=>'6349.769829', 'hrk_to_usd'=>'0.178086', 'pln_to_btc'=>'0.000364', 'gtq_to_btc'=>'0.000143', 'zmk_to_usd'=>'0.00019', 'thb_to_btc'=>'3.5e-05', 'btc_to_mvr'=>'13669.635974', 'ghs_to_btc'=>'0.000495', 'usd_to_gmd'=>'37.78796', 'usd_to_mkd'=>'45.49761', 'usd_to_eur'=>'0.735705', 'cop_to_btc'=>'1.0e-06', 'btc_to_xcd'=>'2401.466142', 'sdg_to_btc'=>'0.000254', 'btc_to_nzd'=>'1089.817604', 'usd_to_uah'=>'8.21647', 'rsd_to_btc'=>'1.3e-05', 'cdf_to_btc'=>'1.0e-06', 'btn_to_usd'=>'0.016024', 'krw_to_btc'=>'1.0e-06', 'tzs_to_usd'=>'0.000621', 'pgk_to_btc'=>'0.000436', 'btc_to_byr'=>'8303422.168412', 'bsd_to_usd'=>'1.0', 'irr_to_usd'=>'4.0e-05', 'uyu_to_usd'=>'0.047255', 'mop_to_btc'=>'0.000141', 'usd_to_ghs'=>'2.2734', 'btc_to_khr'=>'3559278.468792', 'kyd_to_usd'=>'1.209763', 'btc_to_zmk'=>'4669658.473683', 'cop_to_usd'=>'0.000519', 'btc_to_mad'=>'7341.276218', 'try_to_btc'=>'0.000558', 'xpf_to_btc'=>'1.3e-05', 'kzt_to_usd'=>'0.006508', 'usd_to_bhd'=>'0.376988', 'top_to_btc'=>'0.000617', 'ugx_to_btc'=>'0.0', 'usd_to_mmk'=>'982.69002', 'usd_to_jod'=>'0.708054', 'btc_to_vef'=>'5592.762631', 'gip_to_btc'=>'0.001838', 'btc_to_mmk'=>'873550.550133', 'usd_to_xof'=>'483.687999', 'wst_to_btc'=>'0.00048', 'mdl_to_usd'=>'0.076148', 'ltl_to_usd'=>'0.393615', 'bnd_to_btc'=>'0.000897', 'usd_to_sll'=>'4317.3335', 'usd_to_nio'=>'25.17566', 'btc_to_mro'=>'259389.189494', 'srd_to_usd'=>'0.304569', 'usd_to_lbp'=>'1505.415', 'btc_to_pkr'=>'96380.691049', 'rsd_to_usd'=>'0.011918', 'sgd_to_btc'=>'0.000896', 'yer_to_usd'=>'0.004651', 'lvl_to_usd'=>'1.933634', 'usd_to_ang'=>'1.78896', 'usd_to_sar'=>'3.750561', 'usd_to_iqd'=>'1163.94005', 'btc_to_kmf'=>'322050.661985', 'usd_to_bmd'=>'1', 'kes_to_btc'=>'1.3e-05', 'btc_to_irr'=>'22032923.350532', 'btc_to_aoa'=>'86532.453076', 'btc_to_shp'=>'544.136759', 'btc_to_sdg'=>'3936.801718', 'kmf_to_usd'=>'0.00276', 'btc_to_krw'=>'943398.821854', 'btc_to_srd'=>'2918.679635', 'usd_to_bdt'=>'77.70592', 'usd_to_zar'=>'10.2023', 'bwp_to_btc'=>'0.00013', 'byr_to_usd'=>'0.000107', 'vnd_to_usd'=>'4.7e-05', 'usd_to_cve'=>'80.96999', 'btc_to_btc'=>'1.000055', 'btc_to_pen'=>'2491.142213', 'usd_to_hkd'=>'7.752568', 'isk_to_btc'=>'9.0e-06', 'pen_to_usd'=>'0.35684', 'btc_to_kpw'=>'800044.245', 'btc_to_tmm'=>'0.0', 'bzd_to_usd'=>'0.502169', 'npr_to_btc'=>'1.1e-05', 'btc_to_chf'=>'805.681001', 'btc_to_bgn'=>'1279.506316', 'btc_to_uah'=>'7303.93282', 'pln_to_usd'=>'0.323892', 'btc_to_inr'=>'55450.142125', 'htg_to_btc'=>'2.8e-05', 'btc_to_wst'=>'2084.41483', 'btc_to_ron'=>'2902.534742', 'xof_to_usd'=>'0.002067', 'btc_to_mur'=>'26984.790123', 'usd_to_rwf'=>'675.36822', 'usd_to_pab'=>'1', 'btc_to_mxn'=>'11648.279743', 'all_to_btc'=>'1.1e-05', 'dkk_to_btc'=>'0.000205', 'usd_to_ugx'=>'2525.200016', 'tnd_to_usd'=>'0.599834', 'usd_to_lyd'=>'1.243532', 'usd_to_pkr'=>'108.422281', 'omr_to_btc'=>'0.002922', 'mga_to_usd'=>'0.000445', 'mur_to_btc'=>'3.7e-05', 'usd_to_amd'=>'408.364003', 'jod_to_usd'=>'1.412322', 'tnd_to_btc'=>'0.000675', 'shp_to_usd'=>'1.633667', 'vuv_to_usd'=>'0.010359', 'khr_to_btc'=>'0.0', 'usd_to_htg'=>'39.867486', 'iqd_to_usd'=>'0.000859', 'btc_to_sar'=>'3334.016382', 'mur_to_usd'=>'0.032942', 'lsl_to_btc'=>'0.00011', 'usd_to_jmd'=>'102.893', 'ils_to_btc'=>'0.000318', 'zar_to_usd'=>'0.098017', 'usd_to_pln'=>'3.087448', 'bsd_to_btc'=>'0.001125', 'btc_to_rub'=>'29445.459539', 'usd_to_mad'=>'8.258479', 'usd_to_inr'=>'62.37796', 'btc_to_czk'=>'17882.064491', 'isk_to_usd'=>'0.008322', 'rub_to_usd'=>'0.030189', 'usd_to_usd'=>'1.0', 'fkp_to_usd'=>'1.633667', 'all_to_usd'=>'0.009674', 'mop_to_usd'=>'0.125242', 'usd_to_cup'=>'22.682881', 'mro_to_btc'=>'4.0e-06', 'tmm_to_btc'=>'0.0', 'fjd_to_btc'=>'0.000602', 'usd_to_gnf'=>'6936.043333', 'btc_to_huf'=>'195524.412235', 'usd_to_byr'=>'9340.833333', 'usd_to_bgn'=>'1.439365', 'ang_to_btc'=>'0.000629', 'gmd_to_usd'=>'0.026463', 'bif_to_usd'=>'0.000645', 'etb_to_btc'=>'5.9e-05', 'usd_to_std'=>'18145.400667', 'btc_to_std'=>'16130137.085392', 'btc_to_ttd'=>'5701.408639', 'ron_to_btc'=>'0.000345', 'gmd_to_btc'=>'3.0e-05', 'kwd_to_btc'=>'0.003978', 'btc_to_amd'=>'363010.300517', 'btc_to_gyd'=>'183566.817609', 'btc_to_nok'=>'5415.903072', 'btc_to_yer'=>'191127.102383', 'cdf_to_usd'=>'0.001085', 'btc_to_usd'=>'888.9380499999999', 'hrk_to_btc'=>'0.0002', 'btc_to_xaf'=>'429402.590889', 'btc_to_bnd'=>'1115.332793', 'btc_to_lsl'=>'9060.669973', 'usd_to_eek'=>'11.677325', 'brl_to_usd'=>'0.431072', 'lkr_to_usd'=>'0.007622', 'btc_to_pab'=>'888.93805', 'ttd_to_usd'=>'0.155916', 'btc_to_cop'=>'1713368.828542', 'btc_to_isk'=>'106819.240778', 'uzs_to_btc'=>'1.0e-06', 'mxn_to_usd'=>'0.076315', 'btc_to_mdl'=>'11673.801154', 'djf_to_btc'=>'6.0e-06', 'usd_to_npr'=>'99.732501', 'btc_to_tzs'=>'1430893.948113', 'usd_to_vef'=>'6.29151', 'cad_to_btc'=>'0.001064', 'dzd_to_btc'=>'1.4e-05', 'sek_to_usd'=>'0.152191'}
|
400
|
+
fake :get, '/currencies/exchange_rates', response
|
401
|
+
r = @c.exchange_rates
|
402
|
+
r.usd_to_btc.should == '0.001125'
|
403
|
+
r.btc_to_usd.should == '888.9380499999999'
|
404
|
+
end
|
405
|
+
|
406
|
+
it 'should let you get short list of accepted currencies' do
|
407
|
+
response = "[['Afghan Afghani (AFN)','AFN'],['Albanian Lek (ALL)','ALL'],['Algerian Dinar (DZD)','DZD'],['Angolan Kwanza (AOA)','AOA'],['Argentine Peso (ARS)','ARS'],['Armenian Dram (AMD)','AMD'],['Aruban Florin (AWG)','AWG'],['Australian Dollar (AUD)','AUD'],['Azerbaijani Manat (AZN)','AZN'],['Bahamian Dollar (BSD)','BSD'],['Bahraini Dinar (BHD)','BHD'],['Bangladeshi Taka (BDT)','BDT'],['Barbadian Dollar (BBD)','BBD'],['Belarusian Ruble (BYR)','BYR'],['Belize Dollar (BZD)','BZD'],['Bermudian Dollar (BMD)','BMD'],['Bhutanese Ngultrum (BTN)','BTN'],['Bolivian Boliviano (BOB)','BOB'],['Bosnia and Herzegovina Convertible Mark (BAM)','BAM'],['Botswana Pula (BWP)','BWP'],['Brazilian Real (BRL)','BRL'],['British Pound (GBP)','GBP'],['Brunei Dollar (BND)','BND'],['Bulgarian Lev (BGN)','BGN'],['Burundian Franc (BIF)','BIF'],['Cambodian Riel (KHR)','KHR'],['Canadian Dollar (CAD)','CAD'],['Cape Verdean Escudo (CVE)','CVE'],['Cayman Islands Dollar (KYD)','KYD'],['Central African Cfa Franc (XAF)','XAF'],['Cfp Franc (XPF)','XPF'],['Chilean Peso (CLP)','CLP'],['Chinese Renminbi Yuan (CNY)','CNY'],['Colombian Peso (COP)','COP'],['Comorian Franc (KMF)','KMF'],['Congolese Franc (CDF)','CDF'],['Costa Rican Col\u00f3n (CRC)','CRC'],['Croatian Kuna (HRK)','HRK'],['Cuban Peso (CUP)','CUP'],['Czech Koruna (CZK)','CZK'],['Danish Krone (DKK)','DKK'],['Djiboutian Franc (DJF)','DJF'],['Dominican Peso (DOP)','DOP'],['East Caribbean Dollar (XCD)','XCD'],['Egyptian Pound (EGP)','EGP'],['Eritrean Nakfa (ERN)','ERN'],['Estonian Kroon (EEK)','EEK'],['Ethiopian Birr (ETB)','ETB'],['Euro (EUR)','EUR'],['Falkland Pound (FKP)','FKP'],['Fijian Dollar (FJD)','FJD'],['Gambian Dalasi (GMD)','GMD'],['Georgian Lari (GEL)','GEL'],['Ghanaian Cedi (GHS)','GHS'],['Ghanaian Cedi (GHS)','GHS'],['Gibraltar Pound (GIP)','GIP'],['Guatemalan Quetzal (GTQ)','GTQ'],['Guinean Franc (GNF)','GNF'],['Guyanese Dollar (GYD)','GYD'],['Haitian Gourde (HTG)','HTG'],['Honduran Lempira (HNL)','HNL'],['Hong Kong Dollar (HKD)','HKD'],['Hungarian Forint (HUF)','HUF'],['Icelandic Kr\u00f3na (ISK)','ISK'],['Indian Rupee (INR)','INR'],['Indonesian Rupiah (IDR)','IDR'],['Iranian Rial (IRR)','IRR'],['Iraqi Dinar (IQD)','IQD'],['Israeli New Sheqel (ILS)','ILS'],['Jamaican Dollar (JMD)','JMD'],['Japanese Yen (JPY)','JPY'],['Japanese Yen (JPY)','JPY'],['Jordanian Dinar (JOD)','JOD'],['Kazakhstani Tenge (KZT)','KZT'],['Kenyan Shilling (KES)','KES'],['Kuwaiti Dinar (KWD)','KWD'],['Kyrgyzstani Som (KGS)','KGS'],['Lao Kip (LAK)','LAK'],['Latvian Lats (LVL)','LVL'],['Lebanese Pound (LBP)','LBP'],['Lesotho Loti (LSL)','LSL'],['Liberian Dollar (LRD)','LRD'],['Libyan Dinar (LYD)','LYD'],['Lithuanian Litas (LTL)','LTL'],['Macanese Pataca (MOP)','MOP'],['Macedonian Denar (MKD)','MKD'],['Malagasy Ariary (MGA)','MGA'],['Malawian Kwacha (MWK)','MWK'],['Malaysian Ringgit (MYR)','MYR'],['Maldivian Rufiyaa (MVR)','MVR'],['Mauritanian Ouguiya (MRO)','MRO'],['Mauritian Rupee (MUR)','MUR'],['Mexican Peso (MXN)','MXN'],['Moldovan Leu (MDL)','MDL'],['Mongolian T\u00f6gr\u00f6g (MNT)','MNT'],['Moroccan Dirham (MAD)','MAD'],['Mozambican Metical (MZN)','MZN'],['Myanmar Kyat (MMK)','MMK'],['Namibian Dollar (NAD)','NAD'],['Nepalese Rupee (NPR)','NPR'],['Netherlands Antillean Gulden (ANG)','ANG'],['New Taiwan Dollar (TWD)','TWD'],['New Zealand Dollar (NZD)','NZD'],['Nicaraguan C\u00f3rdoba (NIO)','NIO'],['Nigerian Naira (NGN)','NGN'],['North Korean Won (KPW)','KPW'],['Norwegian Krone (NOK)','NOK'],['Omani Rial (OMR)','OMR'],['Pakistani Rupee (PKR)','PKR'],['Panamanian Balboa (PAB)','PAB'],['Papua New Guinean Kina (PGK)','PGK'],['Paraguayan Guaran\u00ed (PYG)','PYG'],['Peruvian Nuevo Sol (PEN)','PEN'],['Philippine Peso (PHP)','PHP'],['Polish Z\u0142oty (PLN)','PLN'],['Qatari Riyal (QAR)','QAR'],['Romanian Leu (RON)','RON'],['Russian Ruble (RUB)','RUB'],['Rwandan Franc (RWF)','RWF'],['Saint Helenian Pound (SHP)','SHP'],['Salvadoran Col\u00f3n (SVC)','SVC'],['Samoan Tala (WST)','WST'],['Saudi Riyal (SAR)','SAR'],['Serbian Dinar (RSD)','RSD'],['Seychellois Rupee (SCR)','SCR'],['Sierra Leonean Leone (SLL)','SLL'],['Singapore Dollar (SGD)','SGD'],['Solomon Islands Dollar (SBD)','SBD'],['Somali Shilling (SOS)','SOS'],['South African Rand (ZAR)','ZAR'],['South Korean Won (KRW)','KRW'],['Sri Lankan Rupee (LKR)','LKR'],['Sudanese Pound (SDG)','SDG'],['Surinamese Dollar (SRD)','SRD'],['Swazi Lilangeni (SZL)','SZL'],['Swedish Krona (SEK)','SEK'],['Swiss Franc (CHF)','CHF'],['Syrian Pound (SYP)','SYP'],['S\u00e3o Tom\u00e9 and Pr\u00edncipe Dobra (STD)','STD'],['Tajikistani Somoni (TJS)','TJS'],['Tanzanian Shilling (TZS)','TZS'],['Thai Baht (THB)','THB'],['Tongan Pa\u02bbanga (TOP)','TOP'],['Trinidad and Tobago Dollar (TTD)','TTD'],['Tunisian Dinar (TND)','TND'],['Turkish Lira (TRY)','TRY'],['Turkmenistani Manat (TMM)','TMM'],['Turkmenistani Manat (TMM)','TMM'],['Ugandan Shilling (UGX)','UGX'],['Ukrainian Hryvnia (UAH)','UAH'],['United Arab Emirates Dirham (AED)','AED'],['United States Dollar (USD)','USD'],['Uruguayan Peso (UYU)','UYU'],['Uzbekistani Som (UZS)','UZS'],['Vanuatu Vatu (VUV)','VUV'],['Venezuelan Bol\u00edvar (VEF)','VEF'],['Vietnamese \u0110\u1ed3ng (VND)','VND'],['West African Cfa Franc (XOF)','XOF'],['Yemeni Rial (YER)','YER'],['Zambian Kwacha (ZMK)','ZMK'],['Zimbabwean Dollar (ZWL)','ZWL']]"
|
408
|
+
fake :get, '/currencies', response
|
409
|
+
r = @c.currencies_short
|
410
|
+
r.first.should == 'AFN'
|
411
|
+
r[1].should == 'ALL'
|
412
|
+
r.last.should == 'ZWL'
|
413
|
+
end
|
414
|
+
|
415
|
+
it 'should let you get long list of accepted currencies' do
|
416
|
+
response = '[["Afghan Afghani (AFN)","AFN"],["Albanian Lek (ALL)","ALL"],["Algerian Dinar (DZD)","DZD"],["Angolan Kwanza (AOA)","AOA"],["Argentine Peso (ARS)","ARS"],["Armenian Dram (AMD)","AMD"],["Aruban Florin (AWG)","AWG"],["Australian Dollar (AUD)","AUD"],["Azerbaijani Manat (AZN)","AZN"],["Bahamian Dollar (BSD)","BSD"],["Bahraini Dinar (BHD)","BHD"],["Bangladeshi Taka (BDT)","BDT"],["Barbadian Dollar (BBD)","BBD"],["Belarusian Ruble (BYR)","BYR"],["Belize Dollar (BZD)","BZD"],["Bermudian Dollar (BMD)","BMD"],["Bhutanese Ngultrum (BTN)","BTN"],["Bolivian Boliviano (BOB)","BOB"],["Bosnia and Herzegovina Convertible Mark (BAM)","BAM"],["Botswana Pula (BWP)","BWP"],["Brazilian Real (BRL)","BRL"],["British Pound (GBP)","GBP"],["Brunei Dollar (BND)","BND"],["Bulgarian Lev (BGN)","BGN"],["Burundian Franc (BIF)","BIF"],["Cambodian Riel (KHR)","KHR"],["Canadian Dollar (CAD)","CAD"],["Cape Verdean Escudo (CVE)","CVE"],["Cayman Islands Dollar (KYD)","KYD"],["Central African Cfa Franc (XAF)","XAF"],["Cfp Franc (XPF)","XPF"],["Chilean Peso (CLP)","CLP"],["Chinese Renminbi Yuan (CNY)","CNY"],["Colombian Peso (COP)","COP"],["Comorian Franc (KMF)","KMF"],["Congolese Franc (CDF)","CDF"],["Costa Rican Col\u00f3n (CRC)","CRC"],["Croatian Kuna (HRK)","HRK"],["Cuban Peso (CUP)","CUP"],["Czech Koruna (CZK)","CZK"],["Danish Krone (DKK)","DKK"],["Djiboutian Franc (DJF)","DJF"],["Dominican Peso (DOP)","DOP"],["East Caribbean Dollar (XCD)","XCD"],["Egyptian Pound (EGP)","EGP"],["Eritrean Nakfa (ERN)","ERN"],["Estonian Kroon (EEK)","EEK"],["Ethiopian Birr (ETB)","ETB"],["Euro (EUR)","EUR"],["Falkland Pound (FKP)","FKP"],["Fijian Dollar (FJD)","FJD"],["Gambian Dalasi (GMD)","GMD"],["Georgian Lari (GEL)","GEL"],["Ghanaian Cedi (GHS)","GHS"],["Ghanaian Cedi (GHS)","GHS"],["Gibraltar Pound (GIP)","GIP"],["Guatemalan Quetzal (GTQ)","GTQ"],["Guinean Franc (GNF)","GNF"],["Guyanese Dollar (GYD)","GYD"],["Haitian Gourde (HTG)","HTG"],["Honduran Lempira (HNL)","HNL"],["Hong Kong Dollar (HKD)","HKD"],["Hungarian Forint (HUF)","HUF"],["Icelandic Kr\u00f3na (ISK)","ISK"],["Indian Rupee (INR)","INR"],["Indonesian Rupiah (IDR)","IDR"],["Iranian Rial (IRR)","IRR"],["Iraqi Dinar (IQD)","IQD"],["Israeli New Sheqel (ILS)","ILS"],["Jamaican Dollar (JMD)","JMD"],["Japanese Yen (JPY)","JPY"],["Japanese Yen (JPY)","JPY"],["Jordanian Dinar (JOD)","JOD"],["Kazakhstani Tenge (KZT)","KZT"],["Kenyan Shilling (KES)","KES"],["Kuwaiti Dinar (KWD)","KWD"],["Kyrgyzstani Som (KGS)","KGS"],["Lao Kip (LAK)","LAK"],["Latvian Lats (LVL)","LVL"],["Lebanese Pound (LBP)","LBP"],["Lesotho Loti (LSL)","LSL"],["Liberian Dollar (LRD)","LRD"],["Libyan Dinar (LYD)","LYD"],["Lithuanian Litas (LTL)","LTL"],["Macanese Pataca (MOP)","MOP"],["Macedonian Denar (MKD)","MKD"],["Malagasy Ariary (MGA)","MGA"],["Malawian Kwacha (MWK)","MWK"],["Malaysian Ringgit (MYR)","MYR"],["Maldivian Rufiyaa (MVR)","MVR"],["Mauritanian Ouguiya (MRO)","MRO"],["Mauritian Rupee (MUR)","MUR"],["Mexican Peso (MXN)","MXN"],["Moldovan Leu (MDL)","MDL"],["Mongolian T\u00f6gr\u00f6g (MNT)","MNT"],["Moroccan Dirham (MAD)","MAD"],["Mozambican Metical (MZN)","MZN"],["Myanmar Kyat (MMK)","MMK"],["Namibian Dollar (NAD)","NAD"],["Nepalese Rupee (NPR)","NPR"],["Netherlands Antillean Gulden (ANG)","ANG"],["New Taiwan Dollar (TWD)","TWD"],["New Zealand Dollar (NZD)","NZD"],["Nicaraguan C\u00f3rdoba (NIO)","NIO"],["Nigerian Naira (NGN)","NGN"],["North Korean Won (KPW)","KPW"],["Norwegian Krone (NOK)","NOK"],["Omani Rial (OMR)","OMR"],["Pakistani Rupee (PKR)","PKR"],["Panamanian Balboa (PAB)","PAB"],["Papua New Guinean Kina (PGK)","PGK"],["Paraguayan Guaran\u00ed (PYG)","PYG"],["Peruvian Nuevo Sol (PEN)","PEN"],["Philippine Peso (PHP)","PHP"],["Polish Z\u0142oty (PLN)","PLN"],["Qatari Riyal (QAR)","QAR"],["Romanian Leu (RON)","RON"],["Russian Ruble (RUB)","RUB"],["Rwandan Franc (RWF)","RWF"],["Saint Helenian Pound (SHP)","SHP"],["Salvadoran Col\u00f3n (SVC)","SVC"],["Samoan Tala (WST)","WST"],["Saudi Riyal (SAR)","SAR"],["Serbian Dinar (RSD)","RSD"],["Seychellois Rupee (SCR)","SCR"],["Sierra Leonean Leone (SLL)","SLL"],["Singapore Dollar (SGD)","SGD"],["Solomon Islands Dollar (SBD)","SBD"],["Somali Shilling (SOS)","SOS"],["South African Rand (ZAR)","ZAR"],["South Korean Won (KRW)","KRW"],["Sri Lankan Rupee (LKR)","LKR"],["Sudanese Pound (SDG)","SDG"],["Surinamese Dollar (SRD)","SRD"],["Swazi Lilangeni (SZL)","SZL"],["Swedish Krona (SEK)","SEK"],["Swiss Franc (CHF)","CHF"],["Syrian Pound (SYP)","SYP"],["S\u00e3o Tom\u00e9 and Pr\u00edncipe Dobra (STD)","STD"],["Tajikistani Somoni (TJS)","TJS"],["Tanzanian Shilling (TZS)","TZS"],["Thai Baht (THB)","THB"],["Tongan Pa\u02bbanga (TOP)","TOP"],["Trinidad and Tobago Dollar (TTD)","TTD"],["Tunisian Dinar (TND)","TND"],["Turkish Lira (TRY)","TRY"],["Turkmenistani Manat (TMM)","TMM"],["Turkmenistani Manat (TMM)","TMM"],["Ugandan Shilling (UGX)","UGX"],["Ukrainian Hryvnia (UAH)","UAH"],["United Arab Emirates Dirham (AED)","AED"],["United States Dollar (USD)","USD"],["Uruguayan Peso (UYU)","UYU"],["Uzbekistani Som (UZS)","UZS"],["Vanuatu Vatu (VUV)","VUV"],["Venezuelan Bol\u00edvar (VEF)","VEF"],["Vietnamese \u0110\u1ed3ng (VND)","VND"],["West African Cfa Franc (XOF)","XOF"],["Yemeni Rial (YER)","YER"],["Zambian Kwacha (ZMK)","ZMK"],["Zimbabwean Dollar (ZWL)","ZWL"]]'
|
417
|
+
fake :get, '/currencies', response
|
418
|
+
r = @c.currencies_long
|
419
|
+
r.first.should == 'Afghan Afghani (AFN)'
|
420
|
+
r[1].should == 'Albanian Lek (ALL)'
|
421
|
+
r.last.should == 'Zimbabwean Dollar (ZWL)'
|
422
|
+
end
|
423
|
+
|
424
|
+
private
|
425
|
+
def fake method, path, body
|
426
|
+
FakeWeb.register_uri(method, "#{BASE_URI}#{path}", body: body.to_json)
|
427
|
+
end
|
428
|
+
|
429
|
+
end
|