quadrigacx 0.10.1 → 0.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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