kraken_ruby 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: af88f54624c729cd704d10d7e489ab9a05c8d9c7
4
+ data.tar.gz: 8f476f022892acf97687f39b6342ce001baf4fb9
5
+ SHA512:
6
+ metadata.gz: 0a9e886717cbdee05f41b87bafc21c4d3e94616ac5195c1d4991672a8343d627876afeb10abd11def56212baed99462cb6a353a53a3f802554e36f43a6fa2b29
7
+ data.tar.gz: 27bb01c561250b27a2c0416192cf4440b2e54e7e9fd6276ba13b9865959fa4f2c52c6aba2a881830f00374059bf266c9576d7506e1a7d24d28e72eeac2929f65
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in kraken_ruby.gemspec
4
+ gemspec
5
+ gem 'httparty'
6
+ gem 'hashie'
7
+ gem 'addressable'
data/Gemfile.lock ADDED
@@ -0,0 +1,40 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ kraken_ruby (0.4.1)
5
+ addressable
6
+ hashie
7
+ httparty
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ addressable (2.3.5)
13
+ diff-lcs (1.2.5)
14
+ hashie (2.0.5)
15
+ httparty (0.12.0)
16
+ json (~> 1.8)
17
+ multi_xml (>= 0.5.2)
18
+ json (1.8.1)
19
+ multi_xml (0.5.5)
20
+ rake (10.1.1)
21
+ rspec (2.14.1)
22
+ rspec-core (~> 2.14.0)
23
+ rspec-expectations (~> 2.14.0)
24
+ rspec-mocks (~> 2.14.0)
25
+ rspec-core (2.14.7)
26
+ rspec-expectations (2.14.5)
27
+ diff-lcs (>= 1.1.3, < 2.0)
28
+ rspec-mocks (2.14.6)
29
+
30
+ PLATFORMS
31
+ ruby
32
+
33
+ DEPENDENCIES
34
+ addressable
35
+ bundler (~> 1.3)
36
+ hashie
37
+ httparty
38
+ kraken_ruby!
39
+ rake
40
+ rspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Alexander Leishman
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,216 @@
1
+ # KrakenRuby
2
+
3
+ ### IMPORTANT
4
+
5
+ This gem is currently built to only query data. There is an experimental ```add_order``` trading method that can be used at **your own risk**. Please thoroughly vet everything in the code for yourself before using this gem to buy, sell, or move any of your assets.
6
+
7
+ PLEASE submit an issue or pull request if you notice any bugs, security holes, or potential improvements.
8
+
9
+ ### Description
10
+
11
+ This gem is a wrapper for the [Kraken Digital Asset Trading Platform](https://www.kraken.com) API. Official documentation from Kraken can be found [here](https://www.kraken.com/help/api).
12
+
13
+ The current version (0.2.0) can be used to query public and private market data. Private data queries require use of your account API keys.
14
+
15
+ ### Pending Future Updates
16
+
17
+ - Solid trade execution functionality
18
+ - More comprehensive test suite for methods requiring authentication (using VCR perhaps)
19
+ - More comprehensive documentation
20
+
21
+ ## Installation
22
+
23
+ Add this line to your application's Gemfile:
24
+
25
+ gem 'kraken_ruby'
26
+
27
+ And then execute:
28
+
29
+ $ bundle
30
+
31
+ Or install it yourself as:
32
+
33
+ $ gem install kraken_ruby
34
+
35
+ ## Usage
36
+
37
+ Create a Kraken client:
38
+
39
+ ```ruby
40
+ API_KEY = '3bH+M/nLp......'
41
+ API_SECRET = 'wQG+7Lr9b.....'
42
+
43
+ kraken = Kraken::Client.new(API_KEY, API_SECRET)
44
+
45
+ time = kraken.server_time
46
+ time.unixtime #=> 1393056191
47
+ ```
48
+
49
+ ### Public Data Methods
50
+
51
+ #### Server Time
52
+
53
+ This functionality is provided by Kraken to to aid in approximating the skew time between the server and client.
54
+
55
+ ```ruby
56
+ time = kraken.server_time
57
+
58
+ time.unixtime #=> 1393056191
59
+ time.rfc1123 #=> "Sat, 22 Feb 2014 08:28:04 GMT"
60
+ ```
61
+
62
+ #### Asset Info
63
+
64
+ 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:
65
+
66
+ ```ruby
67
+ kraken.assets
68
+ ```
69
+
70
+ #### Asset Pairs
71
+
72
+ ```ruby
73
+ pairs = kraken.asset_pairs
74
+ ```
75
+
76
+ #### Ticker Information
77
+
78
+ ```ruby
79
+ ticker_data = kraken.ticker('XLTCXXDG, ZUSDXXVN')
80
+ ```
81
+
82
+ #### Order Book
83
+
84
+ Get market depth information for given asset pairs
85
+
86
+ ```ruby
87
+ depth_data = kraken.order_book('LTCXRP')
88
+ ```
89
+
90
+ #### Trades
91
+
92
+ Get recent trades
93
+
94
+ ```ruby
95
+ trades = kraken.trades('LTCXRP')
96
+ ```
97
+
98
+ #### Spread
99
+
100
+ Get spread data for a given asset pair
101
+
102
+ ```ruby
103
+ spread = kraken.spread('LTCXRP')
104
+ ```
105
+
106
+ ### Private Data Methods
107
+
108
+ #### Balance
109
+
110
+ Get account balance for each asset
111
+ Note: Rates used for the floating valuation is the midpoint of the best bid and ask prices
112
+
113
+ ```ruby
114
+ balance = kraken.balance
115
+ ```
116
+
117
+ #### Trade Balance
118
+
119
+ Get account trade balance
120
+
121
+ ```ruby
122
+ trade_balance = kraken.trade_balance
123
+ ```
124
+
125
+ #### Open Orders
126
+
127
+ ```ruby
128
+ open_orders = kraken.open_orders
129
+ ```
130
+
131
+ #### Query Orders
132
+
133
+ See all orders
134
+
135
+ ```ruby
136
+ orders = kraken.query_orders
137
+ ```
138
+
139
+ #### Trades History
140
+
141
+ Get array of all trades
142
+
143
+ ```ruby
144
+ trades = kraken.trade_history
145
+ ```
146
+
147
+ #### Query Trades
148
+
149
+ **Input:** Comma delimited list of transaction (tx) ids
150
+
151
+ ```ruby
152
+ trades = kraken.query_trades(tx_ids)
153
+ ```
154
+
155
+ #### Open Positions
156
+
157
+ **Input:** Comma delimited list of transaction (tx) ids
158
+
159
+ ```ruby
160
+ positions = kraken.open_positions(tx_ids)
161
+ ```
162
+
163
+ #### Ledgers Info
164
+
165
+ ```ruby
166
+ ledgers = kraken.ledgers_info
167
+ ```
168
+
169
+ #### Ledgers Info
170
+
171
+ **Input:** Comma delimited list of ledger ids
172
+
173
+ ```ruby
174
+ ledgers = kraken.query_ledgers(ledger_ids)
175
+ ```
176
+
177
+ #### Trade Volume
178
+
179
+ **Input:** Comma delimited list of asset pairs
180
+
181
+ ```ruby
182
+ asset_pairs = 'XLTCXXDG, ZEURXXDG'
183
+ volume = kraken.query_ledgers(asset_pairs)
184
+ ```
185
+
186
+ ### Adding and Cancelling Orders
187
+
188
+ #### Add Order
189
+
190
+ 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.
191
+ ```ruby
192
+ # buying 0.01 XBT (bitcoin) for XRP (ripple) at market price
193
+ opts = {
194
+ pair: 'XBTXRP',
195
+ type: 'buy',
196
+ ordertype: 'market',
197
+ volume: 0.01
198
+ }
199
+
200
+ kraken.add_order(opts)
201
+
202
+ ```
203
+
204
+ #### Cancel Order
205
+
206
+ ```ruby
207
+ kraken.cancel_order("UKIYSP-9VN27-AJWWYC")
208
+ ```
209
+
210
+ ## Contributing
211
+
212
+ 1. Fork it
213
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
214
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
215
+ 4. Push to the branch (`git push origin my-new-feature`)
216
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'kraken_ruby/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "kraken_ruby"
8
+ spec.version = KrakenRuby::VERSION
9
+ spec.authors = ["Alexander Leishman"]
10
+ spec.email = ["leishman3@gmail.com"]
11
+ spec.description = %q{"Wrapper for Kraken Exchange API"}
12
+ spec.summary = %q{"Wrapper for Kraken Exchange API"}
13
+ spec.homepage = "https://www.kraken.com/help/api"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
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
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+
25
+ spec.add_dependency "httparty"
26
+ spec.add_dependency "hashie"
27
+ spec.add_dependency "addressable"
28
+ end
@@ -0,0 +1,2 @@
1
+ require "kraken_ruby/version"
2
+ require "kraken_ruby/client"
@@ -0,0 +1,181 @@
1
+ require 'base64'
2
+ require 'securerandom'
3
+ require 'addressable/uri'
4
+ require 'httparty'
5
+ require 'hashie'
6
+
7
+ module Kraken
8
+ class Client
9
+ include HTTParty
10
+
11
+ def initialize(api_key=nil, api_secret=nil, options={})
12
+ @api_key = api_key
13
+ @api_secret = api_secret
14
+ @api_version = options[:version] ||= '0'
15
+ @base_uri = options[:base_uri] ||= 'https://api.kraken.com'
16
+ end
17
+
18
+ ###########################
19
+ ###### Public Data ########
20
+ ###########################
21
+
22
+ def server_time
23
+ get_public 'Time'
24
+ end
25
+
26
+ def assets(opts={})
27
+ get_public 'Assets'
28
+ end
29
+
30
+ def asset_pairs(opts={})
31
+ get_public 'AssetPairs', opts
32
+ end
33
+
34
+ def ticker(pairs) # takes string of comma delimited pairs
35
+ opts = { 'pair' => pairs }
36
+ get_public 'Ticker', opts
37
+ end
38
+
39
+ def order_book(pair, opts={})
40
+ opts['pair'] = pair
41
+ get_public 'Depth', opts
42
+ end
43
+
44
+ def trades(pair, opts={})
45
+ opts['pair'] = pair
46
+ get_public 'Trades', opts
47
+ end
48
+
49
+ def spread(pair, opts={})
50
+ opts['pair'] = pair
51
+ get_public 'Spread', opts
52
+ end
53
+
54
+ def get_public(method, opts={})
55
+ url = @base_uri + '/' + @api_version + '/public/' + method
56
+ r = self.class.get(url, query: opts)
57
+ hash = Hashie::Mash.new(JSON.parse(r.body))
58
+ hash[:result]
59
+ end
60
+
61
+ ######################
62
+ ##### Private Data ###
63
+ ######################
64
+
65
+ def balance(opts={})
66
+ post_private 'Balance', opts
67
+ end
68
+
69
+ def trade_balance(opts={})
70
+ post_private 'TradeBalance', opts
71
+ end
72
+
73
+ def open_orders(opts={})
74
+ post_private 'OpenOrders', opts
75
+ end
76
+
77
+ def query_orders(opts={})
78
+ post_private 'QueryOrders', opts
79
+ end
80
+
81
+ def trade_history(opts={})
82
+ post_private 'TradesHistory', opts
83
+ end
84
+
85
+ def query_trades(tx_ids, opts={})
86
+ opts['txid'] = tx_ids
87
+ post_private 'QueryTrades', opts
88
+ end
89
+
90
+ def open_positions(tx_ids, opts={})
91
+ opts['txid'] = tx_ids
92
+ post_private 'OpenPositions', opts
93
+ end
94
+
95
+ def ledgers_info(opts={})
96
+ post_private 'Ledgers', opts
97
+ end
98
+
99
+ def query_ledgers(ledger_ids, opts={})
100
+ opts['id'] = ledger_ids
101
+ post_private 'QueryLedgers', opts
102
+ end
103
+
104
+ def trade_volume(asset_pairs)
105
+ opts['pair'] = asset_pairs
106
+ post_private 'TradeVolume', opts
107
+ end
108
+
109
+ #### Private User Trading ####
110
+
111
+ def add_order(opts={})
112
+ required_opts = %w{ pair type ordertype volume }
113
+ leftover = required_opts - opts.keys.map(&:to_s)
114
+ if leftover.length > 0
115
+ raise ArgumentError.new("Required options, not given. Input must include #{leftover}")
116
+ end
117
+ post_private 'AddOrder', opts
118
+ end
119
+
120
+ def cancel_order(txid)
121
+ opts = { txid: txid }
122
+ post_private 'CancelOrder', opts
123
+ end
124
+
125
+ #######################
126
+ #### Generate Signed ##
127
+ ##### Post Request ####
128
+ #######################
129
+
130
+ private
131
+
132
+ def post_private(method, opts={})
133
+ opts['nonce'] = nonce
134
+ post_data = encode_options(opts)
135
+
136
+ headers = {
137
+ 'API-Key' => @api_key,
138
+ 'API-Sign' => generate_signature(method, post_data, opts)
139
+ }
140
+
141
+ url = @base_uri + url_path(method)
142
+ r = self.class.post(url, { headers: headers, body: post_data }).parsed_response
143
+ r['error'].empty? ? r['result'] : r['error']
144
+ end
145
+
146
+ # Generate a 64-bit nonce where the 32 high bits come directly from the current
147
+ # timestamp and the low 32 bits are pseudorandom. We can't use a pure [P]RNG here
148
+ # because the Kraken API requires every request within a given session to use a
149
+ # monotonically increasing nonce value. This approach splits the difference.
150
+ def nonce
151
+ high_bits = Time.now.to_i << 32
152
+ low_bits = SecureRandom.random_number(2 ** 32) & 0xffffffff
153
+ (high_bits | low_bits).to_s
154
+ end
155
+
156
+ def encode_options(opts)
157
+ uri = Addressable::URI.new
158
+ uri.query_values = opts
159
+ uri.query
160
+ end
161
+
162
+ def generate_signature(method, post_data, opts={})
163
+ key = Base64.decode64(@api_secret)
164
+ message = generate_message(method, opts, post_data)
165
+ generate_hmac(key, message)
166
+ end
167
+
168
+ def generate_message(method, opts, data)
169
+ digest = OpenSSL::Digest.new('sha256', opts['nonce'] + data).digest
170
+ url_path(method) + digest
171
+ end
172
+
173
+ def generate_hmac(key, message)
174
+ Base64.strict_encode64(OpenSSL::HMAC.digest('sha512', key, message))
175
+ end
176
+
177
+ def url_path(method)
178
+ '/' + @api_version + '/private/' + method
179
+ end
180
+ end
181
+ end
@@ -0,0 +1,3 @@
1
+ module KrakenRuby
2
+ VERSION = "0.4.2"
3
+ end
@@ -0,0 +1,68 @@
1
+ require 'kraken_ruby'
2
+
3
+ describe Kraken::Client do
4
+
5
+ # YOU MUST SET ENVIRONMENT VARIABLES KRAKEN_API_KEY AND
6
+ # KRAKEN_API_SECRET TO TEST PRIVATE DATA QUERIES. PRIVATE
7
+ # TESTS WILL FAIL OTHERWISE.
8
+
9
+ API_KEY = ENV['KRAKEN_API_KEY']
10
+ API_SECRET = ENV['KRAKEN_API_SECRET']
11
+
12
+ before :each do
13
+ sleep 0.3 # to prevent rapidly pinging the Kraken server
14
+ end
15
+
16
+ let(:kraken){Kraken::Client.new(API_KEY, API_SECRET)}
17
+
18
+ context "public data" do
19
+ it "gets the proper server time" do
20
+ kraken_time = DateTime.parse(kraken.server_time.rfc1123)
21
+ utc_time = Time.now.getutc
22
+ expect(kraken_time.day).to eq utc_time.day
23
+ expect(kraken_time.hour).to eq utc_time.hour
24
+ end
25
+
26
+ it "gets list of tradeable assets" do
27
+ expect(kraken.assets).to respond_to :XLTC
28
+ end
29
+
30
+ it "gets list of asset pairs" do
31
+ expect(kraken.asset_pairs).to respond_to :XLTCXXDG
32
+ end
33
+
34
+ it "gets public ticker data for given asset pairs" do
35
+ result = kraken.ticker('XLTCXXDG, ZEURXXDG')
36
+ expect(result).to respond_to :XLTCXXDG
37
+ expect(result).to respond_to :ZEURXXDG
38
+ end
39
+
40
+ it "gets order book data for a given asset pair" do
41
+ order_book = kraken.order_book('XLTCXXDG')
42
+ expect(order_book.XLTCXXDG).to respond_to :asks
43
+ end
44
+
45
+ it "gets an array of trades data for a given asset pair" do
46
+ trades = kraken.trades('XLTCXXDG')
47
+ expect(trades.XLTCXXDG).to be_instance_of(Array)
48
+ end
49
+
50
+ it "gets an array of spread data for a given asset pair" do
51
+ spread = kraken.spread('XLTCXXDG')
52
+ expect(spread.XLTCXXDG).to be_instance_of(Array)
53
+ end
54
+ end
55
+
56
+ context "private data" do # More tests to come
57
+ it "gets the user's balance" do
58
+ expect(kraken.balance).to be_instance_of(Hash)
59
+ end
60
+
61
+ it "uses a 64 bit nonce" do
62
+ nonce = kraken.send :nonce
63
+ expect(nonce.to_i.size).to eq(8)
64
+ expect(nonce.to_i).to be_instance_of(Bignum)
65
+ end
66
+ end
67
+
68
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kraken_ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Leishman