kraken_client 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +61 -0
- data/LICENSE.md +24 -0
- data/Rakefile +1 -0
- data/fixtures/vcr_cassettes/add_order.yml +41 -0
- data/fixtures/vcr_cassettes/assets.yml +45 -0
- data/fixtures/vcr_cassettes/assets_pairs.yml +45 -0
- data/fixtures/vcr_cassettes/balance.yml +41 -0
- data/fixtures/vcr_cassettes/cancel_order.yml +41 -0
- data/fixtures/vcr_cassettes/closed_orders.yml +134 -0
- data/fixtures/vcr_cassettes/ledgers.yml +41 -0
- data/fixtures/vcr_cassettes/open_orders.yml +43 -0
- data/fixtures/vcr_cassettes/order_book.yml +43 -0
- data/fixtures/vcr_cassettes/query_ledgers.yml +41 -0
- data/fixtures/vcr_cassettes/query_orders.yml +43 -0
- data/fixtures/vcr_cassettes/query_trades.yml +41 -0
- data/fixtures/vcr_cassettes/server_time.yml +44 -0
- data/fixtures/vcr_cassettes/spread.yml +43 -0
- data/fixtures/vcr_cassettes/ticker.yml +43 -0
- data/fixtures/vcr_cassettes/trade_balance.yml +41 -0
- data/fixtures/vcr_cassettes/trade_volume.yml +41 -0
- data/fixtures/vcr_cassettes/trades.yml +43 -0
- data/fixtures/vcr_cassettes/trades_history.yml +41 -0
- data/kraken_rb.gemspec +33 -0
- data/lib/configurable.rb +13 -0
- data/lib/configuration.rb +19 -0
- data/lib/exceptions.rb +6 -0
- data/lib/kraken_client/application.rb +45 -0
- data/lib/kraken_client/endpoints/base.rb +43 -0
- data/lib/kraken_client/endpoints/private.rb +45 -0
- data/lib/kraken_client/endpoints/public.rb +33 -0
- data/lib/kraken_client/requests/base.rb +35 -0
- data/lib/kraken_client/requests/content/body.rb +18 -0
- data/lib/kraken_client/requests/content/header.rb +61 -0
- data/lib/kraken_client/requests/get.rb +13 -0
- data/lib/kraken_client/requests/limiter.rb +78 -0
- data/lib/kraken_client/requests/post.rb +38 -0
- data/lib/kraken_client.rb +15 -0
- data/lib/version.rb +3 -0
- data/readme.md +280 -0
- data/spec/requests/private_spec.rb +104 -0
- data/spec/requests/public_spec.rb +57 -0
- metadata +229 -0
@@ -0,0 +1,61 @@
|
|
1
|
+
module KrakenClient
|
2
|
+
module Requests
|
3
|
+
module Content
|
4
|
+
class Header
|
5
|
+
|
6
|
+
attr_accessor :config, :endpoint_name, :options, :url
|
7
|
+
|
8
|
+
def initialize(config, endpoint_name, options, url)
|
9
|
+
@config = config
|
10
|
+
@endpoint_name = endpoint_name
|
11
|
+
@url = url
|
12
|
+
|
13
|
+
@options = options
|
14
|
+
@options[:nonce] = nonce
|
15
|
+
end
|
16
|
+
|
17
|
+
def call
|
18
|
+
{
|
19
|
+
'API-Key' => config.api_key,
|
20
|
+
'API-Sign' => generate_signature,
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
## Security
|
27
|
+
|
28
|
+
# Generate a 64-bit nonce where the 48 high bits come directly from the current
|
29
|
+
# timestamp and the low 16 bits are pseudorandom. We can't use a pure [P]RNG here
|
30
|
+
# because the Kraken API requires every request within a given session to use a
|
31
|
+
# monotonically increasing nonce value. This approach splits the difference.
|
32
|
+
def nonce
|
33
|
+
high_bits = (Time.now.to_f * 10000).to_i << 16
|
34
|
+
low_bits = SecureRandom.random_number(2 ** 16) & 0xffff
|
35
|
+
(high_bits | low_bits).to_s
|
36
|
+
end
|
37
|
+
|
38
|
+
def encoded_options
|
39
|
+
uri = Addressable::URI.new
|
40
|
+
uri.query_values = options
|
41
|
+
uri.query
|
42
|
+
end
|
43
|
+
|
44
|
+
def generate_signature
|
45
|
+
key = Base64.decode64(config.api_secret)
|
46
|
+
message = generate_message
|
47
|
+
generate_hmac(key, message)
|
48
|
+
end
|
49
|
+
|
50
|
+
def generate_message
|
51
|
+
digest = OpenSSL::Digest.new('sha256', options[:nonce] + encoded_options).digest
|
52
|
+
url.split('.com').last + digest
|
53
|
+
end
|
54
|
+
|
55
|
+
def generate_hmac(key, message)
|
56
|
+
Base64.strict_encode64(OpenSSL::HMAC.digest('sha512', key, message))
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module KrakenClient
|
2
|
+
module Requests
|
3
|
+
class Limiter
|
4
|
+
|
5
|
+
attr_reader :config, :previous_timestamps, :endpoint_name, :current_count
|
6
|
+
|
7
|
+
def initialize(config)
|
8
|
+
@config = config
|
9
|
+
@previous_timestamps = Time.now
|
10
|
+
@current_count = counter_total
|
11
|
+
end
|
12
|
+
|
13
|
+
def update(endpoint_name)
|
14
|
+
return unless config.limiter
|
15
|
+
@endpoint_name = endpoint_name
|
16
|
+
|
17
|
+
decrement_current_count
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
# Adds the number of seconds depending of the current tier value
|
23
|
+
def refresh_current_count
|
24
|
+
@current_count += ((Time.now - previous_timestamps) / seconds_to_decrement).to_int
|
25
|
+
@current_count = counter_total if current_count > counter_total
|
26
|
+
|
27
|
+
current_count
|
28
|
+
end
|
29
|
+
|
30
|
+
def decrement_current_count
|
31
|
+
@current_count -= value_to_decrement
|
32
|
+
|
33
|
+
if current_count < 0
|
34
|
+
sleep value_to_decrement
|
35
|
+
|
36
|
+
@current_count = value_to_decrement
|
37
|
+
|
38
|
+
update(endpoint_name)
|
39
|
+
else
|
40
|
+
refresh_current_count
|
41
|
+
|
42
|
+
@previous_timestamps = Time.now
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def value_to_decrement
|
47
|
+
|
48
|
+
case endpoint_name
|
49
|
+
when 'Ledger' then 2
|
50
|
+
when 'TradeHistory' then 2
|
51
|
+
when 'AddOrder' then 0
|
52
|
+
when 'CancelOrder' then 0
|
53
|
+
else 1
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def counter_total
|
58
|
+
@counter ||= case config.tier
|
59
|
+
when 0 then 10
|
60
|
+
when 1 then 10
|
61
|
+
when 2 then 10
|
62
|
+
when 3 then 20
|
63
|
+
when 4 then 20
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def seconds_to_decrement
|
68
|
+
@decrement ||= case config.tier
|
69
|
+
when 0 then 5
|
70
|
+
when 1 then 5
|
71
|
+
when 2 then 5
|
72
|
+
when 3 then 2
|
73
|
+
when 4 then 1
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module KrakenClient
|
2
|
+
module Requests
|
3
|
+
class Post < Base
|
4
|
+
|
5
|
+
def call(url, endpoint_name, options)
|
6
|
+
super
|
7
|
+
|
8
|
+
@url = url
|
9
|
+
@endpoint_name = endpoint_name
|
10
|
+
|
11
|
+
response = HTTParty.post(url, params(options)).parsed_response
|
12
|
+
response['error'].empty? ? response['result'] : response['error']
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def params(options = {})
|
18
|
+
params = {}
|
19
|
+
|
20
|
+
header_content = content_manager::Header.new(config, endpoint_name, options, url)
|
21
|
+
|
22
|
+
params[:headers] = header_content.call
|
23
|
+
params[:body] = body_content(header_content).call
|
24
|
+
|
25
|
+
params
|
26
|
+
end
|
27
|
+
|
28
|
+
def content_manager
|
29
|
+
KrakenClient::Requests::Content
|
30
|
+
end
|
31
|
+
|
32
|
+
def body_content(header_content)
|
33
|
+
content_manager::Body.new(header_content.send(:encoded_options))
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'find'
|
2
|
+
require 'active_support/inflector'
|
3
|
+
|
4
|
+
Find.find('./lib').select { |p| /.*\.rb$/ =~ p }.each do |path|
|
5
|
+
require_relative("../" + path)
|
6
|
+
end
|
7
|
+
|
8
|
+
module KrakenClient
|
9
|
+
extend KrakenClient::Configurable
|
10
|
+
|
11
|
+
def self.load(params = {})
|
12
|
+
KrakenClient::Application.new(params)
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
data/lib/version.rb
ADDED
data/readme.md
ADDED
@@ -0,0 +1,280 @@
|
|
1
|
+
|
2
|
+
# **KrakenClient**
|
3
|
+
|
4
|
+
`KrakenClient` is a **Ruby** wrapper of the Kraken API. Kraken is a market exchange site serving those trading with Crypto-Currencies, such as **Bitcoin**.
|
5
|
+
|
6
|
+
This gem tends to be a replacement for [kraken_ruby](https://github.com/leishman/kraken_ruby), another wrapper, from which it is originally forked from.
|
7
|
+
|
8
|
+
It has every features of the latter gem, with improved readability, usability, maintenability, and speced using the Awesome [Spectus gem](https://github.com/fixrb/spectus).
|
9
|
+
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Add this line to your application's Gemfile:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
gem 'kraken_client'
|
17
|
+
```
|
18
|
+
|
19
|
+
And then execute:
|
20
|
+
|
21
|
+
$ bundle
|
22
|
+
|
23
|
+
Or install it yourself as:
|
24
|
+
|
25
|
+
$ gem install kraken_ruby
|
26
|
+
|
27
|
+
And require it in your application:
|
28
|
+
|
29
|
+
irb(main):001:0> require 'kraken_client'
|
30
|
+
=> true
|
31
|
+
|
32
|
+
|
33
|
+
## Usage
|
34
|
+
|
35
|
+
### Configuration ###
|
36
|
+
You can pass multiple variables that will be used in the gem.
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
KrakenClient.configure do |config|
|
40
|
+
config.api_key = ENV['KRAKEN_API_KEY']
|
41
|
+
config.api_secret = ENV['KRAKEN_API_SECRET']
|
42
|
+
config.base_uri = 'https://api.kraken.com'
|
43
|
+
config.api_version = 0
|
44
|
+
config.limiter = true
|
45
|
+
config.tier = 2
|
46
|
+
end
|
47
|
+
```
|
48
|
+
|
49
|
+
By default, the default values are the ones described in the above example.
|
50
|
+
|
51
|
+
You can also pass any of those options inline when loading an instance of KrakenClient.
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
KrakenClient.load({base_uri: 'https://api.kraken.com', tier: 3}).config.tier
|
55
|
+
```
|
56
|
+
|
57
|
+
|
58
|
+
**/!\\ Important Note /!\\** If you wish to use the Private Endpoints, you need to specify an API Key, or an exception will be raised.
|
59
|
+
|
60
|
+
### Call Rate Limiter ###
|
61
|
+
|
62
|
+
Kraken has implemented a security which limit API users to make too much requests to the server. Each user has a counter (which is bigger depending on your tier). Each call increments your counter, and if your counter reaches its limit, you are blocked for 15 minutes.
|
63
|
+
|
64
|
+
To prevent this, `KrakenClient` has a safeguard, which queue the request which should in theory be blocked and is executed two second later.
|
65
|
+
|
66
|
+
If you want to disable this option, pass the `limiter` variable in the configuration to false.
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
KrakenClient.load({limiter: false}).config.tier
|
70
|
+
```
|
71
|
+
|
72
|
+
Also, this limiter is activated by default. You would like to specify your tier, and `KrakenClient` will automatically make the required adjustments. The default `tier` is 2.
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
KrakenClient.load({tier: 3}).config.tier
|
76
|
+
```
|
77
|
+
|
78
|
+
For more information, please consult the [Kraken official documentation](https://support.kraken.com/hc/en-us/articles/206548367-What-is-the-API-call-rate-limit-).
|
79
|
+
|
80
|
+
### Requests ###
|
81
|
+
|
82
|
+
In all our examples henceforward, we consider this variable to be a loaded instance of `KrakenClient`
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
client = KrakenClient.load
|
86
|
+
```
|
87
|
+
|
88
|
+
If you ever need to see the full documentation for the possible parameters, please take a look at the official [Kraken API docs](https://www.kraken.com/help/api).
|
89
|
+
|
90
|
+
A `KrakenClient::MissingParameter` exception will be raised along with the missing parameters if a required parameter is not passed.
|
91
|
+
|
92
|
+
### *Public Endpoints* ###
|
93
|
+
|
94
|
+
|
95
|
+
##### Server Time
|
96
|
+
|
97
|
+
This functionality is provided by Kraken to to aid in approximating the skew time between the server and client.
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
time = client.public.server_time
|
101
|
+
|
102
|
+
time.unixtime #=> 1393056191
|
103
|
+
time.rfc1123 #=> "Sat, 22 Feb 2014 08:28:04 GMT"
|
104
|
+
```
|
105
|
+
|
106
|
+
##### Asset Info
|
107
|
+
|
108
|
+
Returns the assets that can be traded on the exchange. This method can be passed ```info```, ```aclass``` (asset class), and ```asset``` options. An example below is given for each:
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
assets = client.public.assets
|
112
|
+
```
|
113
|
+
|
114
|
+
##### Asset Pairs
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
pairs = client.public.asset_pairs
|
118
|
+
```
|
119
|
+
|
120
|
+
##### Ticker Information
|
121
|
+
|
122
|
+
```ruby
|
123
|
+
ticker_data = client.public.ticker('XLTCXXDG, ZUSDXXVN')
|
124
|
+
```
|
125
|
+
|
126
|
+
##### Order Book
|
127
|
+
|
128
|
+
Get market depth information for given asset pairs
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
depth_data = client.public.order_book('LTCXRP')
|
132
|
+
```
|
133
|
+
|
134
|
+
##### Trades
|
135
|
+
|
136
|
+
Get recent trades
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
trades = client.public.trades('LTCXRP')
|
140
|
+
```
|
141
|
+
|
142
|
+
##### Spread
|
143
|
+
|
144
|
+
Get spread data for a given asset pair
|
145
|
+
|
146
|
+
```ruby
|
147
|
+
spread = client.public.spread('LTCXRP')
|
148
|
+
```
|
149
|
+
|
150
|
+
|
151
|
+
#### Private Endpoints ####
|
152
|
+
|
153
|
+
##### Balance
|
154
|
+
|
155
|
+
Get account balance for each asset
|
156
|
+
Note: Rates used for the floating valuation is the midpoint of the best bid and ask prices
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
balance = client.private.balance
|
160
|
+
```
|
161
|
+
|
162
|
+
##### Trade Balance
|
163
|
+
|
164
|
+
Get account trade balance
|
165
|
+
|
166
|
+
```ruby
|
167
|
+
trade_balance = client.private.trade_balance
|
168
|
+
```
|
169
|
+
|
170
|
+
##### Open Orders
|
171
|
+
|
172
|
+
```ruby
|
173
|
+
open_orders = client.private.open_orders
|
174
|
+
```
|
175
|
+
|
176
|
+
##### Closed Orders
|
177
|
+
|
178
|
+
```ruby
|
179
|
+
closed_orders = client.private.closed_orders
|
180
|
+
```
|
181
|
+
|
182
|
+
##### Query Orders
|
183
|
+
|
184
|
+
**Input:** Comma delimited list of transaction ids (txid)
|
185
|
+
|
186
|
+
See all orders
|
187
|
+
|
188
|
+
```ruby
|
189
|
+
orders = client.private.query_orders(txid: ids)
|
190
|
+
```
|
191
|
+
|
192
|
+
##### Trades History
|
193
|
+
|
194
|
+
Get array of all trades
|
195
|
+
|
196
|
+
```ruby
|
197
|
+
trades = client.private.trade_history
|
198
|
+
```
|
199
|
+
|
200
|
+
##### Query Trades
|
201
|
+
|
202
|
+
**Input:** Comma delimited list of transaction ids (txid)
|
203
|
+
|
204
|
+
See all orders
|
205
|
+
|
206
|
+
```ruby
|
207
|
+
orders = client.private.query_orders(txid: ids)
|
208
|
+
```
|
209
|
+
|
210
|
+
##### Open Positions
|
211
|
+
|
212
|
+
**Input:** Comma delimited list of transaction (txid) ids
|
213
|
+
|
214
|
+
```ruby
|
215
|
+
positions = client.private.open_positions(txid)
|
216
|
+
```
|
217
|
+
|
218
|
+
##### Ledgers Info
|
219
|
+
|
220
|
+
```ruby
|
221
|
+
ledgers = client.private.ledgers
|
222
|
+
```
|
223
|
+
|
224
|
+
##### Query Ledgers
|
225
|
+
|
226
|
+
**Input:** Comma delimited list of ledger ids
|
227
|
+
|
228
|
+
```ruby
|
229
|
+
ledgers = client.private.query_ledgers(id: ledger_ids)
|
230
|
+
```
|
231
|
+
|
232
|
+
##### Trade Volume
|
233
|
+
|
234
|
+
```ruby
|
235
|
+
ledgers = client.private.trade_volume
|
236
|
+
```
|
237
|
+
|
238
|
+
##### Add Order
|
239
|
+
|
240
|
+
There are 4 required parameters for buying an order. The example below illustrates the most basic order. Please see the [Kraken documentation](https://www.kraken.com/help/api#add-standard-order) for the parameters required for more advanced order types.
|
241
|
+
|
242
|
+
```ruby
|
243
|
+
# buying 0.01 XBT (bitcoin) for XRP (ripple) at market price
|
244
|
+
opts = {
|
245
|
+
pair: 'XBTXRP',
|
246
|
+
type: 'buy',
|
247
|
+
ordertype: 'market',
|
248
|
+
volume: 0.01
|
249
|
+
}
|
250
|
+
|
251
|
+
client.private.add_order(opts)
|
252
|
+
```
|
253
|
+
|
254
|
+
##### Cancel Order
|
255
|
+
|
256
|
+
```ruby
|
257
|
+
client.private.cancel_order("UKIYSP-9VN27-AJWWYC")
|
258
|
+
```
|
259
|
+
|
260
|
+
|
261
|
+
## Credits
|
262
|
+
|
263
|
+
This gem has been made by [Sidney SISSAOUI (shideneyu)](https://github.com/shideneyu).
|
264
|
+
|
265
|
+
Special credits goes to [Alexander LEISHMAN](http://alexleishman.com/) and other [kraken_ruby](https://github.com/leishman/kraken_ruby) contributors for their gem, which helped me to have a nice base to begin **KrakenClient**. It would have been difficult for me to sign the requests if it wasn't thanks to their work.
|
266
|
+
If you want to be part of those credits, do not hesitate to contribute by doing some pull requests ;) !
|
267
|
+
|
268
|
+
|
269
|
+
## Contributing
|
270
|
+
|
271
|
+
1. Fork it ( https://github.com/[my-github-username]/swiffer/fork )
|
272
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
273
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
274
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
275
|
+
5. Create a new Pull Request
|
276
|
+
|
277
|
+
|
278
|
+
## License
|
279
|
+
|
280
|
+
See `LICENSE.md` file.
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require_relative File.join '..', '..', 'lib', 'kraken_client'
|
2
|
+
require 'spectus'
|
3
|
+
require 'vcr'
|
4
|
+
require 'webmock'
|
5
|
+
|
6
|
+
include WebMock::API
|
7
|
+
|
8
|
+
VCR.configure do |config|
|
9
|
+
config.cassette_library_dir = "fixtures/vcr_cassettes"
|
10
|
+
config.hook_into :webmock # or :fakeweb
|
11
|
+
end
|
12
|
+
|
13
|
+
# Testing Private Endpoints
|
14
|
+
KrakenClient.configure do |config|
|
15
|
+
config.api_key = ENV['KRAKEN_API_KEY'] || 'COMPUTED'
|
16
|
+
config.api_secret = ENV['KRAKEN_API_SECRET'] ||'COMPUTED'
|
17
|
+
end
|
18
|
+
|
19
|
+
kraken = KrakenClient.load
|
20
|
+
client = kraken.private
|
21
|
+
|
22
|
+
# User Balance
|
23
|
+
VCR.use_cassette("balance") do
|
24
|
+
Spectus.this { client.balance.class }.MUST Equal: Hashie::Mash
|
25
|
+
end
|
26
|
+
|
27
|
+
# Trade Balance
|
28
|
+
VCR.use_cassette("trade_balance") do
|
29
|
+
Spectus.this { client.trade_balance.c }.MUST Eql: '0.0000'
|
30
|
+
end
|
31
|
+
|
32
|
+
# Open Orders
|
33
|
+
VCR.use_cassette("open_orders") do
|
34
|
+
Spectus.this { client.open_orders.open.class }.MUST Equal: Hashie::Mash
|
35
|
+
end
|
36
|
+
|
37
|
+
# Closed Orders
|
38
|
+
VCR.use_cassette("closed_orders") do
|
39
|
+
Spectus.this { client.closed_orders.closed.class }.MUST Equal: Hashie::Mash
|
40
|
+
end
|
41
|
+
|
42
|
+
# Query Orders
|
43
|
+
VCR.use_cassette("query_orders") do
|
44
|
+
Spectus.this do
|
45
|
+
order = client.query_orders({txid: 'OKRRJ6-MH3UH-DV6IKT'})
|
46
|
+
order['OKRRJ6-MH3UH-DV6IKT'].status
|
47
|
+
end.MUST Eql: 'canceled'
|
48
|
+
end
|
49
|
+
|
50
|
+
# Trades History
|
51
|
+
VCR.use_cassette("trades_history") do
|
52
|
+
Spectus.this { client.trades_history.trades.class }.MUST Equal: Hashie::Mash
|
53
|
+
end
|
54
|
+
|
55
|
+
# Query Trades
|
56
|
+
VCR.use_cassette("query_trades") do
|
57
|
+
Spectus.this do
|
58
|
+
order = client.query_trades({txid: 'THZPTW-BMF6X-VWMN5P'})
|
59
|
+
order['THZPTW-BMF6X-VWMN5P'].pair
|
60
|
+
end.MUST Eql: 'XETHZEUR'
|
61
|
+
end
|
62
|
+
|
63
|
+
# Open Positions
|
64
|
+
#CANT TEST, PARAMS DO NOT WORK
|
65
|
+
|
66
|
+
# Ledgers Info
|
67
|
+
VCR.use_cassette("ledgers") do
|
68
|
+
Spectus.this { client.ledgers.ledger.class }.MUST Equal: Hashie::Mash
|
69
|
+
end
|
70
|
+
|
71
|
+
# Query Ledgers
|
72
|
+
VCR.use_cassette("query_ledgers") do
|
73
|
+
Spectus.this do
|
74
|
+
ledger = client.query_ledgers(id: 'LRSNYS-DICDD-3QM34P')
|
75
|
+
ledger['LRSNYS-DICDD-3QM34P'].class
|
76
|
+
end.MUST Equal: Hashie::Mash
|
77
|
+
end
|
78
|
+
|
79
|
+
# Trade Volume
|
80
|
+
VCR.use_cassette("trade_volume") do
|
81
|
+
Spectus.this { client.trade_volume(pair: 'XETHZEUR').count }.MUST Equal: 4
|
82
|
+
end
|
83
|
+
|
84
|
+
# Add Order
|
85
|
+
VCR.use_cassette("add_order") do
|
86
|
+
Spectus.this do
|
87
|
+
|
88
|
+
opts = {
|
89
|
+
pair: 'ETHEUR',
|
90
|
+
type: 'buy',
|
91
|
+
ordertype: 'market',
|
92
|
+
volume: 0.01
|
93
|
+
}
|
94
|
+
|
95
|
+
client.add_order(opts).txid
|
96
|
+
end.MUST Eql: ['OEDIZV-VDAW3-RHLJVB']
|
97
|
+
end
|
98
|
+
|
99
|
+
# Cancel Order
|
100
|
+
VCR.use_cassette("cancel_order") do
|
101
|
+
Spectus.this do
|
102
|
+
client.cancel_order(txid: 'ODEC3J-QAMVD-NSF7XD').count
|
103
|
+
end.MUST Eql: 1
|
104
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require_relative File.join '..', '..', 'lib', 'kraken_client'
|
2
|
+
require 'spectus'
|
3
|
+
require 'vcr'
|
4
|
+
require 'webmock'
|
5
|
+
|
6
|
+
include WebMock::API
|
7
|
+
|
8
|
+
VCR.configure do |config|
|
9
|
+
config.cassette_library_dir = "fixtures/vcr_cassettes"
|
10
|
+
config.hook_into :webmock # or :fakeweb
|
11
|
+
end
|
12
|
+
|
13
|
+
# Testing Public Endpoints
|
14
|
+
kraken = KrakenClient.load
|
15
|
+
client = kraken.public
|
16
|
+
|
17
|
+
# Server Time
|
18
|
+
VCR.use_cassette("server_time") do
|
19
|
+
kraken_time = DateTime.parse(client.server_time.rfc1123)
|
20
|
+
utc_time = Time.now.getutc
|
21
|
+
Spectus.this { kraken_time.day.class }.MUST Equal: Fixnum
|
22
|
+
Spectus.this { kraken_time.hour.class }.MUST Equal: Fixnum
|
23
|
+
end
|
24
|
+
|
25
|
+
# Assets
|
26
|
+
VCR.use_cassette("assets") do
|
27
|
+
Spectus.this { client.assets.XETH.aclass }.MUST Eql: 'currency'
|
28
|
+
end
|
29
|
+
|
30
|
+
# Assets Pairs
|
31
|
+
VCR.use_cassette("assets_pairs") do
|
32
|
+
Spectus.this { client.asset_pairs.XETHXXBT.altname }.MUST Eql: 'ETHXBT'
|
33
|
+
end
|
34
|
+
|
35
|
+
# Ticker
|
36
|
+
VCR.use_cassette("ticker") do
|
37
|
+
result = client.ticker(pair: 'XXBTZEUR, XXBTZGBP')
|
38
|
+
Spectus.this { result.XXBTZGBP.a.class }.MUST Equal: Array
|
39
|
+
end
|
40
|
+
|
41
|
+
# Order Book
|
42
|
+
VCR.use_cassette("order_book") do
|
43
|
+
order_book = client.order_book(pair: 'XXBTZEUR')
|
44
|
+
Spectus.this { order_book.XXBTZEUR.asks.class }.MUST Equal: Array
|
45
|
+
end
|
46
|
+
|
47
|
+
# Trades
|
48
|
+
VCR.use_cassette("trades") do
|
49
|
+
trades = client.trades(pair: 'XXBTZEUR')
|
50
|
+
Spectus.this { trades.XXBTZEUR.class }.MUST Equal: Array
|
51
|
+
end
|
52
|
+
|
53
|
+
# Spread
|
54
|
+
VCR.use_cassette("spread") do
|
55
|
+
spread = client.spread(pair: 'XXBTZEUR')
|
56
|
+
Spectus.this { spread.XXBTZEUR.class }.MUST Equal: Array
|
57
|
+
end
|