quadrigacx 0.10.1 → 0.12.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +10 -30
  3. data/Gemfile.lock +4 -3
  4. data/LICENSE.txt +22 -0
  5. data/README.md +144 -9
  6. data/Rakefile +2 -1
  7. data/lib/quadrigacx.rb +11 -28
  8. data/lib/quadrigacx/client.rb +6 -6
  9. data/lib/quadrigacx/client/private.rb +18 -9
  10. data/lib/quadrigacx/client/public.rb +2 -2
  11. data/lib/quadrigacx/request.rb +38 -36
  12. data/lib/quadrigacx/version.rb +1 -3
  13. data/quadrigacx.gemspec +27 -24
  14. data/spec/client_spec.rb +125 -114
  15. data/spec/fixtures/vcr_cassettes/QuadrigaCX_Client/private/_balance/returns_all_account_balances.yml +56 -0
  16. data/spec/fixtures/vcr_cassettes/QuadrigaCX_Client/private/_cancel/cancels_an_order.yml +196 -0
  17. data/spec/fixtures/vcr_cassettes/QuadrigaCX_Client/private/_limit_buy/errors/throws_an_error_when_exceeding_available_balance.yml +440 -0
  18. data/spec/fixtures/vcr_cassettes/QuadrigaCX_Client/private/_limit_buy/errors/throws_an_error_when_exceeding_balance.yml +440 -0
  19. data/spec/fixtures/vcr_cassettes/QuadrigaCX_Client/private/_limit_buy/errors/throws_an_error_when_no_price_is_provided.yml +386 -0
  20. data/spec/fixtures/vcr_cassettes/QuadrigaCX_Client/private/_limit_buy/errors/throws_an_error_when_the_amount_is_too_small.yml +440 -0
  21. data/spec/fixtures/vcr_cassettes/QuadrigaCX_Client/private/_limit_buy/places_a_USD_limit_buy_order.yml +385 -0
  22. data/spec/fixtures/vcr_cassettes/QuadrigaCX_Client/private/_limit_buy/places_a_limit_buy_order.yml +338 -0
  23. data/spec/fixtures/vcr_cassettes/QuadrigaCX_Client/private/_limit_buy/places_a_limit_buy_order_cad.yml +384 -0
  24. data/spec/fixtures/vcr_cassettes/QuadrigaCX_Client/private/_limit_sell/errors/throws_an_error_when_no_price_is_provided.yml +387 -0
  25. data/spec/fixtures/vcr_cassettes/QuadrigaCX_Client/private/_limit_sell/places_a_USD_limit_sell_order.yml +385 -0
  26. data/spec/fixtures/vcr_cassettes/QuadrigaCX_Client/private/_limit_sell/places_a_limit_sell_order.yml +385 -0
  27. data/spec/fixtures/vcr_cassettes/QuadrigaCX_Client/private/_market_buy/places_a_USD_market_buy_order.yml +107 -0
  28. data/spec/fixtures/vcr_cassettes/{limit_buy_below_minimum_order_value.yml → QuadrigaCX_Client/private/_market_buy/places_a_market_buy_order.yml} +11 -11
  29. data/spec/fixtures/vcr_cassettes/QuadrigaCX_Client/private/_market_sell/places_a_USD_market_sell_order.yml +107 -0
  30. data/spec/fixtures/vcr_cassettes/{limit_buy_exceeds_available_balance.yml → QuadrigaCX_Client/private/_market_sell/places_a_market_sell_order.yml} +12 -13
  31. data/spec/fixtures/vcr_cassettes/QuadrigaCX_Client/private/_open_orders/lists_USD_open_orders.yml +495 -0
  32. data/spec/fixtures/vcr_cassettes/QuadrigaCX_Client/private/_open_orders/lists_open_orders.yml +690 -0
  33. data/spec/fixtures/vcr_cassettes/QuadrigaCX_Client/private/_user_transactions/returns_a_list_of_USD_transactions.yml +391 -0
  34. data/spec/fixtures/vcr_cassettes/QuadrigaCX_Client/private/_user_transactions/returns_a_list_of_limited_transactions.yml +64 -0
  35. data/spec/fixtures/vcr_cassettes/QuadrigaCX_Client/private/_user_transactions/returns_a_list_of_transactions.yml +197 -0
  36. data/spec/fixtures/vcr_cassettes/{limit_buy_above_maximum_order_value.yml → QuadrigaCX_Client/private/_wallet_address/returns_a_wallet_address.yml} +12 -13
  37. data/spec/fixtures/vcr_cassettes/QuadrigaCX_Client/private/_withdraw/withdraws_bitcoins.yml +54 -0
  38. data/spec/fixtures/vcr_cassettes/QuadrigaCX_Client/public/_order_book/returns_a_USD_order_book.yml +156 -0
  39. data/spec/fixtures/vcr_cassettes/QuadrigaCX_Client/public/_order_book/returns_a_list_of_all_open_orders.yml +91 -0
  40. data/spec/fixtures/vcr_cassettes/QuadrigaCX_Client/public/_order_book/when_using_the_group_option/does_not_group_same_price_orders.yml +286 -0
  41. data/spec/fixtures/vcr_cassettes/QuadrigaCX_Client/public/_order_book/when_using_the_ungrouped_option/does_not_group_same_price_orders.yml +286 -0
  42. data/spec/fixtures/vcr_cassettes/{ticker.yml → QuadrigaCX_Client/public/_ticker/returns_trading_information.yml} +11 -11
  43. data/spec/fixtures/vcr_cassettes/QuadrigaCX_Client/public/_transactions/returns_a_list_of_USD_trades.yml +162 -0
  44. data/spec/fixtures/vcr_cassettes/QuadrigaCX_Client/public/_transactions/returns_a_list_of_recent_trades.yml +57 -0
  45. data/spec/spec_helper.rb +8 -1
  46. metadata +99 -67
  47. data/spec/fixtures/vcr_cassettes/balance.yml +0 -55
  48. data/spec/fixtures/vcr_cassettes/cancel.yml +0 -189
  49. data/spec/fixtures/vcr_cassettes/limit_buy.yml +0 -140
  50. data/spec/fixtures/vcr_cassettes/limit_buy_cancel_order.yml +0 -49
  51. data/spec/fixtures/vcr_cassettes/limit_sell_cancel_order.yml +0 -49
  52. data/spec/fixtures/vcr_cassettes/market_buy.yml +0 -53
  53. data/spec/fixtures/vcr_cassettes/open_orders.yml +0 -55
  54. data/spec/fixtures/vcr_cassettes/order_book.yml +0 -123
  55. data/spec/fixtures/vcr_cassettes/order_book_ungrouped.yml +0 -127
  56. data/spec/fixtures/vcr_cassettes/order_book_ungrouped_cancel_order.yml +0 -49
  57. data/spec/fixtures/vcr_cassettes/safe_limit_buy.yml +0 -176
  58. data/spec/fixtures/vcr_cassettes/safe_limit_sell.yml +0 -176
  59. data/spec/fixtures/vcr_cassettes/transactions.yml +0 -55
  60. data/spec/fixtures/vcr_cassettes/user_transactions.yml +0 -208
  61. data/spec/fixtures/vcr_cassettes/user_transactions_limited.yml +0 -57
  62. data/spec/fixtures/vcr_cassettes/wallet_address.yml +0 -49
  63. data/spec/fixtures/vcr_cassettes/withdraw.yml +0 -49
@@ -1,10 +1,11 @@
1
1
  require 'rest-client'
2
2
  require 'json'
3
- require 'hashie'
4
3
  require 'openssl'
5
4
  require 'date'
6
5
  require 'uri'
7
6
  require 'digest'
7
+ require 'ostruct'
8
+ require 'quadrigacx/error'
8
9
 
9
10
  module QuadrigaCX
10
11
  module Request
@@ -13,23 +14,19 @@ module QuadrigaCX
13
14
  protected
14
15
 
15
16
  def request *args
16
- resp = hmac_request(*args)
17
- json = JSON.parse(resp) rescue (return fix_json(resp))
18
- json.kind_of?(Array) ? json.map { |i| to_hashie(i) } : to_hashie(json)
17
+ response = hmac_request(*args)
18
+ response = JSON.parse(response, object_class: OpenStruct) rescue (return fix_json(response))
19
+
20
+ check_error(response)
19
21
  end
20
22
 
21
23
  private
22
24
 
23
25
  def fix_json response
24
- begin
25
- JSON.parse(response)
26
-
27
26
  # The `/cancel_order` route returns `"true"` instead of valid JSON.
28
- rescue JSON::ParserError
29
- return true if response.strip == '"true"'
30
- return false if response.strip == '"false"'
31
- response[/"(.*)"/, 1] || response
32
- end
27
+ return true if response.strip == '"true"'
28
+ return false if response.strip == '"false"'
29
+ response[/"(.*)"/, 1] || response
33
30
  end
34
31
 
35
32
  def hmac_request http_method, path, body={}
@@ -39,16 +36,20 @@ module QuadrigaCX
39
36
  if http_method == :get
40
37
  url += '?' + URI.encode_www_form(body)
41
38
  else
42
- raise 'API key, API secret and client ID required!' unless @api_key && @api_secret && @client_id
39
+ client_id = QuadrigaCX.configuration.client_id
40
+ api_key = QuadrigaCX.configuration.api_key
41
+ api_secret = QuadrigaCX.configuration.api_secret
42
+
43
+ raise 'API key, API secret and client ID required!' unless api_key && api_secret && client_id
43
44
 
44
- secret = Digest::MD5.hexdigest(@api_secret)
45
+ secret = Digest::MD5.hexdigest(api_secret)
45
46
  nonce = DateTime.now.strftime('%Q')
46
- data = [nonce + @api_key + @client_id].join
47
+ data = [nonce + api_key + client_id].join
47
48
  digest = OpenSSL::Digest.new('sha256')
48
49
  signature = OpenSSL::HMAC.hexdigest(digest, secret, data)
49
50
 
50
51
  payload = body.merge({
51
- key: @api_key,
52
+ key: api_key,
52
53
  nonce: nonce,
53
54
  signature: signature,
54
55
  })
@@ -66,27 +67,28 @@ module QuadrigaCX
66
67
  )
67
68
  end
68
69
 
69
- def raise_error hash
70
- errorClass =
71
- case hash.error.code
72
- when 21 then ExceedsAvailableBalance
73
- when 22 then BelowMinimumOrderValue
74
- when 23 then AboveMaximumOrderValue
75
- when 106 then NotFound
76
- else Error
77
- end
78
-
79
- message = hash.error.code.to_s + ' '
80
- message += hash.error.to_s if hash.error
81
- message += hash.errors.join(',') if hash.errors
82
-
83
- raise errorClass.new(message)
84
- end
70
+ def check_error responses
71
+ [responses].flatten.each do |response|
72
+
73
+ next unless response.error
74
+
75
+ errorClass =
76
+ case response.error.code
77
+ when 21 then ExceedsAvailableBalance
78
+ when 22 then BelowMinimumOrderValue
79
+ when 23 then AboveMaximumOrderValue
80
+ when 106 then NotFound
81
+ else Error
82
+ end
83
+
84
+ message = response.error.code.to_s + ' '
85
+ message += response.error.to_s if response.error
86
+ message += response.errors.join(',') if response.errors
87
+
88
+ raise errorClass.new(message)
89
+ end
85
90
 
86
- def to_hashie json
87
- hash = Hashie::Mash.new(json)
88
- raise_error(hash) if hash.error
89
- hash
91
+ responses
90
92
  end
91
93
  end
92
94
  end
@@ -1,5 +1,3 @@
1
1
  module QuadrigaCX
2
- unless defined?(QuadrigaCX::VERSION)
3
- VERSION = '0.10.1'
4
- end
2
+ VERSION = '0.12.2'
5
3
  end
data/quadrigacx.gemspec CHANGED
@@ -1,29 +1,32 @@
1
- require File.expand_path('../lib/quadrigacx/version', __FILE__)
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'quadrigacx/version'
2
5
 
3
- Gem::Specification.new do |s|
4
- s.name = "quadrigacx"
5
- s.version = QuadrigaCX::VERSION.dup
6
- s.summary = "QuadrigaCX API wrapper"
7
- s.description = "Ruby wrapper for the QuadrigaCX API"
8
- s.homepage = "https://github.com/mhluska/quadrigacx"
9
- s.authors = ["Maros Hluska"]
10
- s.email = ["mhluska@gmail.com"]
11
- s.homepage = "http://mhluska.com/"
12
- s.license = "MIT"
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'quadrigacx'
8
+ spec.version = QuadrigaCX::VERSION
9
+ spec.author = 'Maros Hluska'
10
+ spec.email = 'mhluska@gmail.com'
11
+ spec.summary = 'QuadrigaCX API wrapper'
12
+ spec.description = 'Ruby wrapper for the QuadrigaCX API'
13
+ spec.homepage = 'https://github.com/mhluska/quadrigacx'
14
+ spec.license = 'MIT'
13
15
 
14
- s.add_development_dependency 'byebug', '~> 5.0'
15
- s.add_development_dependency 'rspec', '~> 3.1'
16
- s.add_development_dependency 'webmock', '~> 1.20'
17
- s.add_development_dependency 'vcr', '~> 2.9'
18
- s.add_development_dependency 'dotenv', '~> 1.0'
19
- s.add_development_dependency 'gem-release', '~> 0.7'
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
20
 
21
- s.add_runtime_dependency 'json', '~> 1.8'
22
- s.add_runtime_dependency 'rest-client', '~> 1.7'
23
- s.add_runtime_dependency 'hashie', '~> 3.3'
21
+ spec.add_runtime_dependency 'json', '~> 1.8'
22
+ spec.add_runtime_dependency 'rest-client', '~> 1.7'
24
23
 
25
- s.files = `git ls-files`.split("\n")
26
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
27
- s.executables = `git ls-files -- bin/*`.split("\n").map{|f| File.basename(f)}
28
- s.require_paths = ["lib"]
24
+ spec.add_development_dependency 'byebug', '~> 5.0'
25
+ spec.add_development_dependency 'rspec', '~> 3.1'
26
+ spec.add_development_dependency 'webmock', '~> 1.20'
27
+ spec.add_development_dependency 'vcr', '~> 2.9'
28
+ spec.add_development_dependency 'dotenv', '~> 1.0'
29
+ spec.add_development_dependency 'gem-release', '~> 0.7'
30
+ spec.add_development_dependency 'bundler', '~> 1.7'
31
+ spec.add_development_dependency 'rake', '~> 10.0'
29
32
  end
data/spec/client_spec.rb CHANGED
@@ -1,71 +1,62 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe QuadrigaCX::Client do
4
- subject(:client) { QuadrigaCX::Client.new(
5
- client_id: ENV['QUADRIGACX_CLIENT_ID'],
6
- api_key: ENV['QUADRIGACX_API_KEY'],
7
- api_secret: ENV['QUADRIGACX_API_SECRET'],
8
- )}
9
-
10
- def safe_limit_buy
11
- VCR.use_cassette('safe_limit_buy') do
12
- worst_price = client.order_book.bids.last[0]
13
- client.limit_buy(price: worst_price, amount: 1)
14
- end
3
+ describe QuadrigaCX::Client, :vcr do
4
+ def safe_limit_buy book: :btc_cad
5
+ worst_price = subject.order_book.bids.last[0]
6
+ subject.limit_buy(price: worst_price, amount: 1, book: book)
15
7
  end
16
8
 
17
- def safe_limit_sell
18
- VCR.use_cassette('safe_limit_sell') do
19
- worst_price = client.order_book.asks.last[0]
20
- client.limit_sell(price: worst_price, amount: 0.01)
21
- end
9
+ def safe_limit_sell book: :btc_cad
10
+ worst_price = subject.order_book.asks.last[0]
11
+ subject.limit_sell(price: worst_price, amount: 0.01, book: book)
22
12
  end
23
13
 
24
14
  describe 'public' do
25
15
  describe '#ticker' do
26
16
  it 'returns trading information' do
27
- VCR.use_cassette('ticker') do
28
- ticker = client.ticker
17
+ ticker = subject.ticker
29
18
 
30
- expect(ticker.high).not_to be_nil
31
- expect(ticker.low).not_to be_nil
32
- end
19
+ expect(ticker.high).not_to be_nil
20
+ expect(ticker.low).not_to be_nil
33
21
  end
34
22
  end
35
23
 
36
24
  describe '#order_book' do
25
+ let(:order_book_cad) { subject.order_book }
26
+ let(:order_book_usd) { subject.order_book(book: :btc_usd) }
27
+
37
28
  it 'returns a list of all open orders' do
38
- VCR.use_cassette('order_book') do
39
- order_book = client.order_book
29
+ expect(order_book_cad.timestamp).not_to be_nil
30
+ expect(order_book_cad.bids.first.length).to equal 2
31
+ expect(order_book_cad.asks.first.length).to equal 2
32
+ end
40
33
 
41
- expect(order_book.timestamp).not_to be_nil
42
- expect(order_book.bids.first.length).to equal 2
43
- expect(order_book.asks.first.length).to equal 2
44
- end
34
+ it 'returns a USD order book' do
35
+ expect(order_book_usd.bids.first).to_not equal(order_book_cad.bids.first)
45
36
  end
46
37
 
47
- context 'when using the ungrouped option' do
48
- order = nil
49
- after { VCR.use_cassette('order_book_ungrouped_cancel_order') { client.cancel(id: order.id) if order }}
38
+ context 'when using the group option' do
39
+ let!(:order) { safe_limit_buy }
40
+ after { subject.cancel(id: order.id) }
50
41
 
51
42
  it 'does not group same price orders' do
52
- VCR.use_cassette('order_book_ungrouped') do
53
- order = safe_limit_buy
54
- ungrouped_bids = client.order_book(group: 0).bids
55
- expect(ungrouped_bids[-2][0]).to eq(ungrouped_bids.last[0])
56
- end
43
+ ungrouped_bids = subject.order_book(group: 0).bids
44
+ expect(ungrouped_bids[-2][0]).to eq(ungrouped_bids.last[0])
57
45
  end
58
46
  end
59
47
  end
60
48
 
61
49
  describe '#transactions' do
50
+ let(:transactions_cad) { subject.transactions }
51
+ let(:transactions_usd) { subject.transactions(book: :btc_usd) }
52
+
62
53
  it 'returns a list of recent trades' do
63
- VCR.use_cassette('transactions') do
64
- transactions = client.transactions
54
+ expect(transactions_cad.first.date).not_to be_nil
55
+ expect(transactions_cad.first.price).not_to be_nil
56
+ end
65
57
 
66
- expect(transactions.first.date).not_to be_nil
67
- expect(transactions.first.price).not_to be_nil
68
- end
58
+ it 'returns a list of USD trades' do
59
+ expect(transactions_usd.first.price).not_to equal(transactions_cad.first.price)
69
60
  end
70
61
  end
71
62
  end
@@ -73,77 +64,96 @@ describe QuadrigaCX::Client do
73
64
  describe 'private' do
74
65
  describe '#balance' do
75
66
  it 'returns all account balances' do
76
- VCR.use_cassette('balance') do
77
- balance = client.balance
67
+ balance = subject.balance
78
68
 
79
- expect(balance.cad_balance).not_to be_nil
80
- expect(balance.btc_balance).not_to be_nil
81
- end
69
+ expect(balance.cad_balance).not_to be_nil
70
+ expect(balance.btc_balance).not_to be_nil
82
71
  end
83
72
  end
84
73
 
85
74
  describe '#limit_buy' do
86
- order = nil
87
- after { VCR.use_cassette('limit_buy_cancel_order') { client.cancel(id: order.id) if order }}
88
-
89
- it 'throws an error when no price is provided' do
90
- expect { client.limit_buy }.to raise_error(QuadrigaCX::ConfigurationError)
91
- end
75
+ describe 'errors' do
76
+ it 'throws an error when no price is provided' do
77
+ expect { subject.limit_buy }.to raise_error(QuadrigaCX::ConfigurationError)
78
+ end
92
79
 
93
- it 'places a limit buy order' do
94
- VCR.use_cassette('limit_buy') do
95
- order = safe_limit_buy
80
+ it 'throws an error when exceeding balance' do
81
+ expect { subject.limit_buy(price: 1_000_000, amount: 1) }.to raise_error(QuadrigaCX::AboveMaximumOrderValue)
82
+ end
96
83
 
97
- expect(order.datetime).not_to be_nil
98
- expect(order.id).not_to be_nil
84
+ it 'throws an error when the amount is too small' do
85
+ expect { subject.limit_buy(price: 100, amount: 0.00000001) }.to raise_error(QuadrigaCX::BelowMinimumOrderValue)
99
86
  end
100
- end
101
87
 
102
- it 'throws an error when exceeding balance' do
103
- VCR.use_cassette('limit_buy_above_maximum_order_value') do
104
- expect { client.limit_buy(price: 1_000_000, amount: 1) }.to raise_error(QuadrigaCX::AboveMaximumOrderValue)
88
+ it 'throws an error when exceeding available balance' do
89
+ expect { subject.limit_buy(price: 4999, amount: 1) }.to raise_error(QuadrigaCX::ExceedsAvailableBalance)
105
90
  end
106
91
  end
107
92
 
108
- it 'throws an error when the amount is too small' do
109
- VCR.use_cassette('limit_buy_below_minimum_order_value') do
110
- expect { client.limit_buy(price: 100, amount: 0.00000001) }.to raise_error(QuadrigaCX::BelowMinimumOrderValue)
111
- end
93
+ let(:order_cad) { safe_limit_buy }
94
+ let(:order_usd) { safe_limit_buy(book: :btc_usd) }
95
+
96
+ after { subject.cancel(id: order_cad.id) && subject.cancel(id: order_usd.id) }
97
+
98
+ it 'places a limit buy order_cad' do
99
+ expect(order_cad.datetime).not_to be_nil
100
+ expect(order_cad.id).not_to be_nil
101
+ expect(order_cad.price).not_to be_nil
112
102
  end
113
103
 
114
- it 'throws an error when exceeding available balance' do
115
- VCR.use_cassette('limit_buy_exceeds_available_balance') do
116
- expect { client.limit_buy(price: 4999, amount: 1) }.to raise_error(QuadrigaCX::ExceedsAvailableBalance)
117
- end
104
+ it 'places a USD limit buy order' do
105
+ expect(order_cad.price).not_to equal(order_usd.price)
118
106
  end
119
107
  end
120
108
 
121
109
  describe '#limit_sell' do
122
- order = nil
123
- after { VCR.use_cassette('limit_sell_cancel_order') { client.cancel(id: order.id) if order }}
124
-
125
- it 'throws an error when no price is provided' do
126
- expect { client.limit_sell }.to raise_error(QuadrigaCX::ConfigurationError)
110
+ describe 'errors' do
111
+ it 'throws an error when no price is provided' do
112
+ expect { subject.limit_sell }.to raise_error(QuadrigaCX::ConfigurationError)
113
+ end
127
114
  end
128
115
 
116
+ let(:order_cad) { safe_limit_sell }
117
+ let(:order_usd) { safe_limit_sell(book: :btc_usd) }
118
+
119
+ after { subject.cancel(id: order_cad.id) && subject.cancel(id: order_usd.id) }
120
+
129
121
  it 'places a limit sell order' do
130
- VCR.use_cassette('limit_sell') do
131
- order = safe_limit_sell
122
+ expect(order_cad.datetime).not_to be_nil
123
+ expect(order_cad.id).not_to be_nil
124
+ expect(order_cad.price).not_to be_nil
125
+ end
132
126
 
133
- expect(order.datetime).not_to be_nil
134
- expect(order.id).not_to be_nil
135
- end
127
+ it 'places a USD limit sell order' do
128
+ expect(order_cad.price).not_to equal(order_usd.price)
136
129
  end
137
130
  end
138
131
 
139
132
  describe '#market_buy' do
133
+ let(:market_buy_cad) { subject.market_buy(amount: 5.00) }
134
+ let(:market_buy_usd) { subject.market_buy(amount: 5.00, book: :btc_usd) }
135
+
140
136
  it 'places a market buy order' do
141
- VCR.use_cassette('market_buy') do
142
- response = client.market_buy(amount: 5.00) # 5 CAD
137
+ expect(market_buy_cad.amount).not_to be_nil
138
+ expect(market_buy_cad.orders_matched.first.price).not_to be_nil
139
+ end
143
140
 
144
- expect(response.amount).not_to be_nil
145
- expect(response.orders_matched.first.price).not_to be_nil
146
- end
141
+ it 'places a USD market buy order' do
142
+ expect(market_buy_cad.orders_matched.first.price).not_to equal(market_buy_usd.orders_matched.first.price)
143
+ end
144
+ end
145
+
146
+ describe '#market_sell' do
147
+ let(:market_sell_cad) { subject.market_sell(amount: 0.01) }
148
+ let(:market_sell_usd) { subject.market_sell(amount: 0.01, book: :btc_usd) }
149
+
150
+ it 'places a market sell order' do
151
+ expect(market_sell_cad.amount).not_to be_nil
152
+ expect(market_sell_cad.orders_matched.first.price).not_to be_nil
153
+ end
154
+
155
+ it 'places a USD market sell order' do
156
+ expect(market_sell_cad.orders_matched.first.price).not_to equal(market_sell_usd.orders_matched.first.price)
147
157
  end
148
158
  end
149
159
 
@@ -151,60 +161,61 @@ describe QuadrigaCX::Client do
151
161
  let(:order) { safe_limit_buy }
152
162
 
153
163
  it 'cancels an order' do
154
- VCR.use_cassette('cancel') do
155
- response = client.cancel(id: order.id)
156
- expect(response).to be true
157
- end
164
+ response = subject.cancel(id: order.id)
165
+ expect(response).to be true
158
166
  end
159
167
  end
160
168
 
161
169
  describe '#withdraw' do
162
170
  it 'withdraws bitcoins' do
163
- VCR.use_cassette('withdraw') do
164
- response = client.withdraw(amount: 0.01, address: '1FAs1ywa3pqS6S5mvypXjCtHAzwCkymNUX')
165
- expect(response).to eq('ok')
166
- end
171
+ response = subject.withdraw(amount: 0.01, address: '1DVLFma28jEgTCUjQ32FUYe12bRzvywAfr')
172
+ expect(response).to eq('ok')
167
173
  end
168
174
  end
169
175
 
170
176
  describe '#open_orders' do
177
+ let(:open_orders_cad) { subject.open_orders }
178
+ let(:open_orders_usd) { subject.open_orders(book: :btc_usd) }
179
+ let!(:orders) { [safe_limit_buy, safe_limit_buy(book: :btc_usd)] }
180
+
181
+ after { orders.each { |order| subject.cancel(id: order.id) }}
182
+
171
183
  it 'lists open orders' do
172
- VCR.use_cassette('open_orders') do
173
- response = client.open_orders
184
+ expect(open_orders_cad.first.datetime).not_to be_nil
185
+ expect(open_orders_cad.first.type).not_to be_nil
186
+ expect(open_orders_cad.first.price).not_to be_nil
187
+ end
174
188
 
175
- expect(response.first.datetime).not_to be_nil
176
- expect(response.first.price).not_to be_nil
177
- expect(response.first.type).not_to be_nil
178
- end
189
+ it 'lists USD open orders' do
190
+ expect(open_orders_cad.first.price).not_to equal open_orders_usd.first.price
179
191
  end
180
192
  end
181
193
 
182
194
  describe '#wallet_address' do
183
195
  it 'returns a wallet address' do
184
- VCR.use_cassette('wallet_address') do
185
- response = client.wallet_address
186
- expect(response.length).to be_between(26, 35)
187
- end
196
+ response = subject.wallet_address
197
+ expect(response.length).to be_between(26, 35)
188
198
  end
189
199
  end
190
200
 
191
201
  describe '#user_transactions' do
202
+ let(:user_transactions_cad) { subject.user_transactions }
203
+ let(:user_transactions_usd) { subject.user_transactions(order_book: :btc_usd) }
204
+
192
205
  it 'returns a list of transactions' do
193
- VCR.use_cassette('user_transactions') do
194
- response = client.user_transactions
195
- expect(response.first.id).to be_kind_of(String)
196
- expect(response.first.datetime).not_to be_nil
197
- end
206
+ expect(user_transactions_cad.first.id).to be_kind_of(String)
207
+ expect(user_transactions_cad.first.datetime).not_to be_nil
208
+ expect(user_transactions_cad.first.rate).not_to be_nil
198
209
  end
199
210
 
200
- it 'returns a list of limited transactions' do
201
- VCR.use_cassette('user_transactions_limited') do
202
- limit = 1
203
- response = client.user_transactions(limit: limit)
211
+ it 'returns a list of USD transactions' do
212
+ expect(user_transactions_cad.first.rate).not_to equal(user_transactions_usd.first.rate)
213
+ end
204
214
 
205
- # For some reason the API is off by one.
206
- expect(response.length).to be (limit + 1)
207
- end
215
+ it 'returns a list of limited transactions' do
216
+ limit = 5
217
+ response = subject.user_transactions(limit: limit)
218
+ expect(response.length).to equal limit
208
219
  end
209
220
  end
210
221
  end