deribit-api 0.1.3 → 2.0.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.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/.travis.yml +6 -3
- data/CHANGELOG.md +37 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +82 -52
- data/README.md +63 -76
- data/TODOs.org +18 -6
- data/bin/auth.sh +18 -0
- data/bin/trades.py +24 -0
- data/bin/trades.rb +43 -0
- data/bin/whales-watching.rb +25 -0
- data/deribit.gemspec +8 -4
- data/lib/deribit.rb +22 -8
- data/lib/deribit/authentication.rb +10 -14
- data/lib/deribit/client.rb +206 -359
- data/lib/deribit/http.rb +23 -16
- data/lib/deribit/naming.rb +84 -0
- data/lib/deribit/version.rb +1 -1
- data/lib/deribit/websocket.rb +78 -55
- metadata +72 -11
data/lib/deribit/http.rb
CHANGED
@@ -1,32 +1,33 @@
|
|
1
1
|
module Deribit
|
2
|
-
# HTTP API
|
2
|
+
# HTTP API adapter
|
3
|
+
# @author Iulian Costan (deribit-api@iuliancostan.com)
|
3
4
|
# @see https://docs.deribit.com/api-http.html
|
4
5
|
class Http
|
5
|
-
def initialize(host, key: nil, secret: nil, debug: false)
|
6
|
-
|
7
|
-
@connection = Faraday::Connection.new(url: url) do |f|
|
6
|
+
def initialize(host, key: nil, secret: nil, debug: false, raise_error: true)
|
7
|
+
@connection = Faraday::Connection.new(url: http_url(host)) do |f|
|
8
8
|
f.request :json
|
9
|
+
f.use Deribit::Authentication, key, secret
|
9
10
|
f.response :mashify
|
10
11
|
f.response :json
|
11
|
-
f.use
|
12
|
-
f.response :
|
12
|
+
f.use Faraday::Response::RaiseError if raise_error
|
13
|
+
f.response :detailed_logger if debug
|
13
14
|
f.adapter Faraday.default_adapter
|
14
15
|
end
|
15
16
|
end
|
16
17
|
|
17
|
-
def get(
|
18
|
-
response = @connection.get path(
|
18
|
+
def get(uri, params = {})
|
19
|
+
response = @connection.get path(uri), params
|
19
20
|
|
20
21
|
# TODO: move to middleware
|
21
|
-
raise response.
|
22
|
-
raise response.body.message unless response.body.success
|
22
|
+
# raise response.error unless response.error
|
23
|
+
# raise response.body.message unless response.body.success
|
23
24
|
|
24
25
|
body = response.body
|
25
|
-
|
26
|
+
body.result
|
26
27
|
end
|
27
28
|
|
28
|
-
def post(
|
29
|
-
response = @connection.post path(
|
29
|
+
def post(uri, params)
|
30
|
+
response = @connection.post path(uri), params
|
30
31
|
|
31
32
|
# TODO: move to middleware
|
32
33
|
raise response.message unless response.success?
|
@@ -37,9 +38,15 @@ module Deribit
|
|
37
38
|
|
38
39
|
private
|
39
40
|
|
40
|
-
def path(
|
41
|
-
|
42
|
-
|
41
|
+
def path(uri)
|
42
|
+
path = '/api/v2'
|
43
|
+
path += '/' unless uri.start_with? '/'
|
44
|
+
path += uri
|
45
|
+
path
|
46
|
+
end
|
47
|
+
|
48
|
+
def http_url(host)
|
49
|
+
'https://' + host
|
43
50
|
end
|
44
51
|
end
|
45
52
|
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Deribit
|
4
|
+
# @author Iulian Costan (deribit-api@iuliancostan.com)
|
5
|
+
module Naming
|
6
|
+
def trades_channel(options)
|
7
|
+
private = options.delete :private
|
8
|
+
trades = private ? 'user.trades' : 'trades'
|
9
|
+
channel trades, options
|
10
|
+
end
|
11
|
+
|
12
|
+
def trades_uri(options)
|
13
|
+
private = options.delete :private
|
14
|
+
uri = private ? 'private/get_user_trades' : 'public/get_last_trades'
|
15
|
+
uri += by_instrument(options) + by_currency(options)
|
16
|
+
uri += options[:end_timestamp] ? '_and_time' : ''
|
17
|
+
uri
|
18
|
+
end
|
19
|
+
|
20
|
+
def book_channel(options)
|
21
|
+
'book' + for_instrument(options) + with_group_and_depth(options) + with_interval(options)
|
22
|
+
end
|
23
|
+
|
24
|
+
def channel(prefix, options)
|
25
|
+
channel = prefix
|
26
|
+
channel += for_instrument(options) if options[:instrument_name]
|
27
|
+
channel += for_currency(options) if options[:currency]
|
28
|
+
channel += with_interval(options)
|
29
|
+
channel
|
30
|
+
end
|
31
|
+
|
32
|
+
def channel_for_instrument(prefix, options)
|
33
|
+
prefix + for_instrument(options)
|
34
|
+
end
|
35
|
+
|
36
|
+
def instrument_with_interval(prefix, options)
|
37
|
+
prefix + for_instrument(options) + with_interval(options)
|
38
|
+
end
|
39
|
+
|
40
|
+
def cancel_uri(options)
|
41
|
+
'/private/cancel_all' + by_instrument(options) + by_currency(options)
|
42
|
+
end
|
43
|
+
|
44
|
+
def orders_uri(options)
|
45
|
+
'/private/get_open_orders' + by_instrument(options) + by_currency(options)
|
46
|
+
end
|
47
|
+
|
48
|
+
def by_instrument(options)
|
49
|
+
options[:instrument_name] ? '_by_instrument' : ''
|
50
|
+
end
|
51
|
+
|
52
|
+
def by_currency(options)
|
53
|
+
options[:currency] ? '_by_currency' : ''
|
54
|
+
end
|
55
|
+
|
56
|
+
def for_instrument(options)
|
57
|
+
raise 'instrument_name param is required' unless options[:instrument_name]
|
58
|
+
|
59
|
+
".#{options[:instrument_name]}"
|
60
|
+
end
|
61
|
+
|
62
|
+
def for_currency(options)
|
63
|
+
raise 'currency param is required' unless options[:currency]
|
64
|
+
|
65
|
+
kind = options[:kind] || 'any'
|
66
|
+
".#{kind}.#{options[:currency]}"
|
67
|
+
end
|
68
|
+
|
69
|
+
def with_interval(options)
|
70
|
+
interval = options[:interval] || '100ms'
|
71
|
+
".#{interval}"
|
72
|
+
end
|
73
|
+
|
74
|
+
def with_group_and_depth(options)
|
75
|
+
if options[:group] || options[:depth]
|
76
|
+
group = options[:group] || '5'
|
77
|
+
depth = options[:depth] || '10'
|
78
|
+
".#{group}.#{depth}"
|
79
|
+
else
|
80
|
+
''
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/lib/deribit/version.rb
CHANGED
data/lib/deribit/websocket.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Deribit
|
2
|
-
# Websocket API
|
3
|
-
# @
|
4
|
+
# Websocket API adapter
|
5
|
+
# @author Iulian Costan (deribit-api@iuliancostan.com)
|
6
|
+
# @see https://docs.deribit.com/#subscriptions
|
4
7
|
class Websocket
|
5
|
-
attr_reader :host, :key, :secret
|
8
|
+
attr_reader :host, :key, :secret, :access_token, :callbacks
|
6
9
|
|
7
10
|
# Create new websocket instance
|
8
11
|
# @param host [String] the underlying host to connect to
|
@@ -14,6 +17,7 @@ module Deribit
|
|
14
17
|
@key = key
|
15
18
|
@secret = secret
|
16
19
|
@callbacks = {}
|
20
|
+
@ws = nil
|
17
21
|
end
|
18
22
|
|
19
23
|
# Subscribe to a specific topic and optionally filter by symbol
|
@@ -21,85 +25,104 @@ module Deribit
|
|
21
25
|
# @param params [Hash] the arguments for subscription
|
22
26
|
# @yield [Array] data payload
|
23
27
|
def subscribe(topic, params: {}, &callback)
|
24
|
-
raise '
|
25
|
-
|
26
|
-
EM.run do
|
27
|
-
connect
|
28
|
+
raise 'block is required' unless block_given?
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
|
30
|
+
# connect on demand
|
31
|
+
@ws = connect unless connected?
|
32
|
+
raise 'websocket is closed' unless @ws.open?
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
uri = auth ? 'private' : 'public'
|
36
|
-
action = "/api/v1/#{uri}/#{topic}"
|
34
|
+
# save callback handler
|
35
|
+
@callbacks[topic.to_s] = callback
|
37
36
|
|
38
|
-
|
39
|
-
|
37
|
+
# authorize if needed
|
38
|
+
authorize if authorization_required?(topic)
|
40
39
|
|
41
|
-
|
42
|
-
|
40
|
+
# subscription request
|
41
|
+
payload = {
|
42
|
+
jsonrpc: '2.0',
|
43
|
+
method: 'public/subscribe',
|
44
|
+
id: rand(9999),
|
45
|
+
params: { channels: [topic] }
|
46
|
+
}
|
47
|
+
@ws.send payload.to_json.to_s
|
43
48
|
end
|
44
49
|
|
45
|
-
|
46
|
-
|
47
|
-
EM.stop_event_loop
|
50
|
+
def authorized?
|
51
|
+
!access_token.nil?
|
48
52
|
end
|
49
53
|
|
50
54
|
private
|
51
55
|
|
52
|
-
def
|
53
|
-
|
54
|
-
|
55
|
-
_ackey: @key,
|
56
|
-
_acsec: @secret,
|
57
|
-
_action: action
|
58
|
-
}
|
59
|
-
payload.merge! params
|
60
|
-
# query = env['url'].query
|
56
|
+
def connected?
|
57
|
+
!@ws.nil?
|
58
|
+
end
|
61
59
|
|
62
|
-
|
60
|
+
def authorization_required?(topic)
|
61
|
+
topic.include? 'user'
|
63
62
|
end
|
64
63
|
|
65
|
-
def
|
66
|
-
|
64
|
+
def authorize
|
65
|
+
@callbacks['auth'] = lambda do |result|
|
66
|
+
@access_token = result['access_token']
|
67
|
+
end
|
68
|
+
|
69
|
+
@ws.send authorize_payload.to_json.to_s
|
67
70
|
end
|
68
71
|
|
69
|
-
def
|
70
|
-
|
72
|
+
def authorize_payload
|
73
|
+
timestamp = Time.now.utc.to_i * 1000
|
74
|
+
nonce = rand(999_999).to_s
|
75
|
+
signature = Deribit.signature timestamp, nonce, '', @secret
|
76
|
+
{
|
77
|
+
jsonrpc: '2.0',
|
78
|
+
method: 'public/auth',
|
79
|
+
id: 'auth',
|
80
|
+
params: {
|
81
|
+
grant_type: :client_signature,
|
82
|
+
client_id: @key,
|
83
|
+
timestamp: timestamp,
|
84
|
+
nonce: nonce,
|
85
|
+
data: '',
|
86
|
+
signature: signature
|
87
|
+
}
|
88
|
+
}
|
89
|
+
end
|
90
|
+
|
91
|
+
def websocket_url
|
92
|
+
"wss://#{host}/ws/api/v2"
|
71
93
|
end
|
72
94
|
|
73
95
|
def connect
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
# puts [:open, event
|
96
|
+
websocket = self
|
97
|
+
ws = WebSocket::Client::Simple.connect websocket_url
|
98
|
+
ws.on :open do |event|
|
99
|
+
# puts [:open, event]
|
78
100
|
end
|
79
|
-
|
80
|
-
|
101
|
+
ws.on :error do |event|
|
102
|
+
# puts [:error, event.inspect]
|
81
103
|
end
|
82
|
-
|
104
|
+
ws.on :close do |event|
|
83
105
|
# puts [:close, event.reason]
|
84
|
-
|
106
|
+
ws = nil
|
85
107
|
end
|
86
|
-
|
108
|
+
ws.on :message do |event|
|
87
109
|
json = JSON.parse event.data
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
data.each do |payload|
|
96
|
-
payload = Hashie::Mash.new payload if payload.is_a? Hash
|
97
|
-
@result = callback.yield payload, @result
|
110
|
+
if json['method'] == 'subscription'
|
111
|
+
id = json['params']['channel']
|
112
|
+
data = json['params']['data']
|
113
|
+
callback = websocket.callbacks[id]
|
114
|
+
data = [data] if data.is_a? Hash
|
115
|
+
data.each do |datum|
|
116
|
+
@result = callback.yield Hashie::Mash.new(datum)
|
98
117
|
end
|
99
118
|
else
|
100
|
-
|
119
|
+
id = json['id']
|
120
|
+
callback = websocket.callbacks[id]
|
121
|
+
callback&.yield json['result']
|
101
122
|
end
|
102
123
|
end
|
124
|
+
until ws.open? do sleep 1 end # wait for opening
|
125
|
+
ws
|
103
126
|
end
|
104
127
|
end
|
105
128
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deribit-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 2.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Iulian Costan
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-06-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -39,7 +39,7 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: faraday-detailed_logger
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
@@ -53,7 +53,21 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: websocket-client-simple
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: hashie
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
58
72
|
requirements:
|
59
73
|
- - ">="
|
@@ -192,9 +206,51 @@ dependencies:
|
|
192
206
|
- - ">="
|
193
207
|
- !ruby/object:Gem::Version
|
194
208
|
version: '0'
|
195
|
-
|
209
|
+
- !ruby/object:Gem::Dependency
|
210
|
+
name: rubocop
|
211
|
+
requirement: !ruby/object:Gem::Requirement
|
212
|
+
requirements:
|
213
|
+
- - ">="
|
214
|
+
- !ruby/object:Gem::Version
|
215
|
+
version: '0'
|
216
|
+
type: :development
|
217
|
+
prerelease: false
|
218
|
+
version_requirements: !ruby/object:Gem::Requirement
|
219
|
+
requirements:
|
220
|
+
- - ">="
|
221
|
+
- !ruby/object:Gem::Version
|
222
|
+
version: '0'
|
223
|
+
- !ruby/object:Gem::Dependency
|
224
|
+
name: solargraph
|
225
|
+
requirement: !ruby/object:Gem::Requirement
|
226
|
+
requirements:
|
227
|
+
- - ">="
|
228
|
+
- !ruby/object:Gem::Version
|
229
|
+
version: '0'
|
230
|
+
type: :development
|
231
|
+
prerelease: false
|
232
|
+
version_requirements: !ruby/object:Gem::Requirement
|
233
|
+
requirements:
|
234
|
+
- - ">="
|
235
|
+
- !ruby/object:Gem::Version
|
236
|
+
version: '0'
|
237
|
+
- !ruby/object:Gem::Dependency
|
238
|
+
name: irb
|
239
|
+
requirement: !ruby/object:Gem::Requirement
|
240
|
+
requirements:
|
241
|
+
- - ">="
|
242
|
+
- !ruby/object:Gem::Version
|
243
|
+
version: '0'
|
244
|
+
type: :development
|
245
|
+
prerelease: false
|
246
|
+
version_requirements: !ruby/object:Gem::Requirement
|
247
|
+
requirements:
|
248
|
+
- - ">="
|
249
|
+
- !ruby/object:Gem::Version
|
250
|
+
version: '0'
|
251
|
+
description: Idiomatic Ruby library for Deribit API 2.0
|
196
252
|
email:
|
197
|
-
-
|
253
|
+
- deribit-api@iuliancostan.com
|
198
254
|
executables: []
|
199
255
|
extensions: []
|
200
256
|
extra_rdoc_files: []
|
@@ -210,14 +266,19 @@ files:
|
|
210
266
|
- README.md
|
211
267
|
- Rakefile
|
212
268
|
- TODOs.org
|
269
|
+
- bin/auth.sh
|
213
270
|
- bin/console
|
214
271
|
- bin/setup
|
272
|
+
- bin/trades.py
|
273
|
+
- bin/trades.rb
|
274
|
+
- bin/whales-watching.rb
|
215
275
|
- deribit.gemspec
|
216
276
|
- lib/deribit-api.rb
|
217
277
|
- lib/deribit.rb
|
218
278
|
- lib/deribit/authentication.rb
|
219
279
|
- lib/deribit/client.rb
|
220
280
|
- lib/deribit/http.rb
|
281
|
+
- lib/deribit/naming.rb
|
221
282
|
- lib/deribit/version.rb
|
222
283
|
- lib/deribit/websocket.rb
|
223
284
|
homepage: https://github.com/icostan/deribit-api-ruby
|
@@ -227,7 +288,7 @@ metadata:
|
|
227
288
|
homepage_uri: https://github.com/icostan/deribit-api-ruby
|
228
289
|
source_code_uri: https://github.com/icostan/deribit-api-ruby.git
|
229
290
|
changelog_uri: https://github.com/icostan/deribit-api-ruby/blob/master/CHANGELOG.md
|
230
|
-
post_install_message:
|
291
|
+
post_install_message:
|
231
292
|
rdoc_options: []
|
232
293
|
require_paths:
|
233
294
|
- lib
|
@@ -242,8 +303,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
242
303
|
- !ruby/object:Gem::Version
|
243
304
|
version: '0'
|
244
305
|
requirements: []
|
245
|
-
rubygems_version: 3.
|
246
|
-
signing_key:
|
306
|
+
rubygems_version: 3.1.2
|
307
|
+
signing_key:
|
247
308
|
specification_version: 4
|
248
|
-
summary: Ruby library for Deribit API
|
309
|
+
summary: Idiomatic Ruby library for Deribit API 2.0
|
249
310
|
test_files: []
|