kraken_client 0.2.0
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.
- 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
|