bybit-connector-ruby 0.1.0 → 0.1.3
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/CHANGELOG.md +203 -1
- data/README.md +159 -14
- data/examples/quickstart.rb +36 -7
- data/lib/bybit/client.rb +44 -16
- data/lib/bybit/error.rb +13 -5
- data/lib/bybit/rest_api/account_service.rb +50 -0
- data/lib/bybit/rest_api/alpha_service.rb +545 -0
- data/lib/bybit/rest_api/asset_service.rb +17 -0
- data/lib/bybit/rest_api/broker_service.rb +9 -4
- data/lib/bybit/rest_api/crypto_loan_service.rb +60 -0
- data/lib/bybit/rest_api/earn_service.rb +31 -0
- data/lib/bybit/rest_api/event_service.rb +92 -0
- data/lib/bybit/rest_api/fiat_service.rb +110 -0
- data/lib/bybit/rest_api/institutional_loan_service.rb +128 -0
- data/lib/bybit/rest_api/market_service.rb +17 -4
- data/lib/bybit/rest_api/misc_service.rb +36 -0
- data/lib/bybit/rest_api/position_service.rb +15 -0
- data/lib/bybit/rest_api/pre_upgrade_service.rb +130 -0
- data/lib/bybit/rest_api/referral_service.rb +61 -0
- data/lib/bybit/rest_api/spot_margin_service.rb +258 -0
- data/lib/bybit/rest_api/spot_x_service.rb +142 -0
- data/lib/bybit/rest_api/spread_trade_service.rb +202 -0
- data/lib/bybit/rest_api/strategy_service.rb +105 -0
- data/lib/bybit/rest_api/tax_service.rb +37 -0
- data/lib/bybit/rest_api/user_service.rb +10 -0
- data/lib/bybit/session.rb +18 -7
- data/lib/bybit/version.rb +1 -1
- data/lib/bybit/websocket/client.rb +294 -0
- data/lib/bybit/websocket.rb +9 -0
- metadata +62 -7
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'openssl'
|
|
5
|
+
|
|
6
|
+
module Bybit
|
|
7
|
+
module WebSocket
|
|
8
|
+
# Bybit V5 WebSocket client — public streams (spot / linear / inverse /
|
|
9
|
+
# option) and the private user-data stream.
|
|
10
|
+
#
|
|
11
|
+
# Design goals mirror the REST session:
|
|
12
|
+
# - one class, `channel:` selects endpoint (avoids Public/Private class
|
|
13
|
+
# duplication for ping / subscribe / dispatch logic)
|
|
14
|
+
# - explicit callbacks (`on_message`, `on_open`, `on_close`, `on_error`)
|
|
15
|
+
# passed as procs; no global registry / singleton
|
|
16
|
+
# - HMAC-SHA256 auth for `:private` is identical to REST signing except
|
|
17
|
+
# the payload is `"GET/realtime" + expires` — the docs are explicit
|
|
18
|
+
# - ping every `ping_interval` seconds via a lightweight background
|
|
19
|
+
# thread; server terminates connections after 20s silence
|
|
20
|
+
# - automatic resubscribe on reconnect (topic list is retained across
|
|
21
|
+
# `#connect` calls) so callers don't lose subscriptions on transient
|
|
22
|
+
# network blips
|
|
23
|
+
#
|
|
24
|
+
# This class depends on `websocket-client-simple` (a runtime dep of the
|
|
25
|
+
# gem). If missing, requiring it raises a clear LoadError below.
|
|
26
|
+
class Client
|
|
27
|
+
begin
|
|
28
|
+
require 'websocket-client-simple'
|
|
29
|
+
rescue LoadError => e
|
|
30
|
+
raise LoadError,
|
|
31
|
+
"Bybit::WebSocket::Client requires the 'websocket-client-simple' " \
|
|
32
|
+
"gem. Add `gem 'websocket-client-simple'` to your Gemfile. " \
|
|
33
|
+
"(#{e.message})"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Channel → WS path (public streams are category-scoped; private has one).
|
|
37
|
+
PUBLIC_CHANNELS = %i[spot linear inverse option].freeze
|
|
38
|
+
PRIVATE_CHANNEL = :private
|
|
39
|
+
TRADE_CHANNEL = :trade
|
|
40
|
+
|
|
41
|
+
PATHS = {
|
|
42
|
+
spot: '/v5/public/spot',
|
|
43
|
+
linear: '/v5/public/linear',
|
|
44
|
+
inverse: '/v5/public/inverse',
|
|
45
|
+
option: '/v5/public/option',
|
|
46
|
+
private: '/v5/private',
|
|
47
|
+
trade: '/v5/trade'
|
|
48
|
+
}.freeze
|
|
49
|
+
|
|
50
|
+
HOST_MAINNET = 'stream.bybit.com'
|
|
51
|
+
HOST_TESTNET = 'stream-testnet.bybit.com'
|
|
52
|
+
|
|
53
|
+
DEFAULT_PING_INTERVAL = 20
|
|
54
|
+
# Bybit rejects auth expiry timestamps in the past AND >30s in the future.
|
|
55
|
+
DEFAULT_AUTH_EXPIRY_MS = 10_000
|
|
56
|
+
|
|
57
|
+
attr_reader :channel, :testnet, :url, :subscriptions
|
|
58
|
+
|
|
59
|
+
# @param channel [Symbol] one of `:spot`, `:linear`, `:inverse`,
|
|
60
|
+
# `:option`, `:private`, `:trade`.
|
|
61
|
+
# @param testnet [Boolean] hit stream-testnet.bybit.com instead of mainnet
|
|
62
|
+
# @param api_key [String] required for `:private` / `:trade`
|
|
63
|
+
# @param api_secret [String] required for `:private` / `:trade`
|
|
64
|
+
# @param ping_interval [Integer] seconds between ping frames (default 20)
|
|
65
|
+
# @param url [String] override the entire WS URL (skips host/path build)
|
|
66
|
+
# @param on_open, on_message, on_close, on_error [Proc]
|
|
67
|
+
def initialize(channel:, testnet: false,
|
|
68
|
+
api_key: nil, api_secret: nil,
|
|
69
|
+
ping_interval: DEFAULT_PING_INTERVAL,
|
|
70
|
+
url: nil,
|
|
71
|
+
on_open: nil, on_message: nil, on_close: nil, on_error: nil)
|
|
72
|
+
validate_channel!(channel)
|
|
73
|
+
@channel = channel
|
|
74
|
+
@testnet = testnet
|
|
75
|
+
@api_key = api_key
|
|
76
|
+
@api_secret = api_secret
|
|
77
|
+
@ping_interval = ping_interval
|
|
78
|
+
@url = url || build_url
|
|
79
|
+
@on_open = on_open
|
|
80
|
+
@on_message = on_message
|
|
81
|
+
@on_close = on_close
|
|
82
|
+
@on_error = on_error
|
|
83
|
+
@subscriptions = []
|
|
84
|
+
@ws = nil
|
|
85
|
+
@ping_thread = nil
|
|
86
|
+
@connected = false
|
|
87
|
+
@auth_ok = false
|
|
88
|
+
@closing = false
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Open the WebSocket, authenticate (if private/trade), and start pinging.
|
|
92
|
+
# Calling `connect` a second time closes the prior socket first, then
|
|
93
|
+
# opens a fresh one and replays any topics buffered in `@subscriptions`
|
|
94
|
+
# (call `disconnect` explicitly if you want to drop them). No automatic
|
|
95
|
+
# reconnect on network drop — the caller decides when to re-open.
|
|
96
|
+
def connect
|
|
97
|
+
require_auth! if requires_auth?
|
|
98
|
+
# Idempotent: tear down any prior socket / ping thread so a second
|
|
99
|
+
# `connect` call doesn't leak the previous ws or leave two pingers.
|
|
100
|
+
disconnect if @ws
|
|
101
|
+
@closing = false
|
|
102
|
+
client = self
|
|
103
|
+
@ws = ::WebSocket::Client::Simple.connect(@url)
|
|
104
|
+
|
|
105
|
+
@ws.on(:open) { client.send(:handle_open) }
|
|
106
|
+
@ws.on(:message) { |msg| client.send(:handle_message, msg) }
|
|
107
|
+
@ws.on(:close) { |ev| client.send(:handle_close, ev) }
|
|
108
|
+
@ws.on(:error) { |err| client.send(:handle_error, err) }
|
|
109
|
+
self
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Subscribe to one or more topics. Bybit expects an array under `args`:
|
|
113
|
+
# {"op":"subscribe","args":["orderbook.1.BTCUSDT","tickers.BTCUSDT"]}
|
|
114
|
+
# Callers can call `subscribe` before `connect`; topics are buffered and
|
|
115
|
+
# sent once the socket opens (private streams also wait for auth OK).
|
|
116
|
+
def subscribe(*topics)
|
|
117
|
+
topics = topics.flatten.compact.uniq
|
|
118
|
+
return if topics.empty?
|
|
119
|
+
|
|
120
|
+
@subscriptions |= topics
|
|
121
|
+
flush_subscriptions(topics) if ready?
|
|
122
|
+
self
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def unsubscribe(*topics)
|
|
126
|
+
topics = topics.flatten.compact.uniq
|
|
127
|
+
return if topics.empty?
|
|
128
|
+
|
|
129
|
+
@subscriptions -= topics
|
|
130
|
+
send_frame(op: 'unsubscribe', args: topics) if ready?
|
|
131
|
+
self
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Send a WS message directly (escape hatch for placing orders over the
|
|
135
|
+
# `/v5/trade` stream; the docs specify per-op payloads).
|
|
136
|
+
def send_raw(payload)
|
|
137
|
+
return unless @ws
|
|
138
|
+
|
|
139
|
+
@ws.send(payload.is_a?(String) ? payload : JSON.generate(payload))
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def disconnect
|
|
143
|
+
@closing = true
|
|
144
|
+
stop_pinger
|
|
145
|
+
@connected = false
|
|
146
|
+
@auth_ok = false
|
|
147
|
+
begin
|
|
148
|
+
@ws&.close
|
|
149
|
+
rescue StandardError
|
|
150
|
+
# Socket may already be half-closed by the peer or in a bad state —
|
|
151
|
+
# we only care about detaching, not about clean protocol shutdown.
|
|
152
|
+
end
|
|
153
|
+
@ws = nil
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def connected?
|
|
157
|
+
@connected
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def ready?
|
|
161
|
+
return false unless @connected
|
|
162
|
+
|
|
163
|
+
requires_auth? ? @auth_ok : true
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
private
|
|
167
|
+
|
|
168
|
+
def validate_channel!(channel)
|
|
169
|
+
allowed = PUBLIC_CHANNELS + [PRIVATE_CHANNEL, TRADE_CHANNEL]
|
|
170
|
+
return if allowed.include?(channel)
|
|
171
|
+
|
|
172
|
+
raise Bybit::ConfigurationError,
|
|
173
|
+
"invalid channel: #{channel.inspect} (must be one of #{allowed.inspect})"
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def requires_auth?
|
|
177
|
+
[PRIVATE_CHANNEL, TRADE_CHANNEL].include?(channel)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def require_auth!
|
|
181
|
+
return unless @api_key.nil? || @api_secret.nil?
|
|
182
|
+
|
|
183
|
+
raise Bybit::ConfigurationError,
|
|
184
|
+
":#{channel} WebSocket requires api_key + api_secret"
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def build_url
|
|
188
|
+
host = @testnet ? HOST_TESTNET : HOST_MAINNET
|
|
189
|
+
path = PATHS.fetch(channel)
|
|
190
|
+
"wss://#{host}#{path}"
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def handle_open
|
|
194
|
+
@connected = true
|
|
195
|
+
if requires_auth?
|
|
196
|
+
send_auth_frame
|
|
197
|
+
else
|
|
198
|
+
@auth_ok = true
|
|
199
|
+
flush_subscriptions(@subscriptions)
|
|
200
|
+
end
|
|
201
|
+
start_pinger
|
|
202
|
+
@on_open&.call
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def handle_message(raw)
|
|
206
|
+
data = raw.respond_to?(:data) ? raw.data : raw.to_s
|
|
207
|
+
parsed = safe_parse(data)
|
|
208
|
+
if parsed.is_a?(Hash) && parsed['op'] == 'auth'
|
|
209
|
+
# V5 WS auth reply: {"op":"auth","success":true|false,"ret_msg":...}.
|
|
210
|
+
# `success` is authoritative — do NOT treat missing retCode as OK,
|
|
211
|
+
# else a rejection with only ret_msg would silently pass.
|
|
212
|
+
@auth_ok = parsed['success'] == true
|
|
213
|
+
flush_subscriptions(@subscriptions) if @auth_ok
|
|
214
|
+
end
|
|
215
|
+
@on_message&.call(parsed.nil? ? data : parsed)
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def handle_close(event)
|
|
219
|
+
stop_pinger
|
|
220
|
+
@connected = false
|
|
221
|
+
@auth_ok = false
|
|
222
|
+
@on_close&.call(event)
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def handle_error(err)
|
|
226
|
+
# Suppress the noisy IOError the reader thread emits when we close
|
|
227
|
+
# the socket deliberately (see `disconnect`). Real transport errors
|
|
228
|
+
# still fire — @closing only gates the shutdown window.
|
|
229
|
+
return if @closing
|
|
230
|
+
|
|
231
|
+
@on_error&.call(err)
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
# Ping every `ping_interval` seconds; Bybit closes idle sockets around
|
|
235
|
+
# 20s of silence, so keep this ≤ 20s.
|
|
236
|
+
def start_pinger
|
|
237
|
+
stop_pinger
|
|
238
|
+
ws = @ws
|
|
239
|
+
interval = @ping_interval
|
|
240
|
+
@ping_thread = Thread.new do
|
|
241
|
+
Thread.current.name = "bybit-ws-ping-#{channel}" if Thread.current.respond_to?(:name=)
|
|
242
|
+
loop do
|
|
243
|
+
sleep interval
|
|
244
|
+
break if ws.nil? || ws != @ws
|
|
245
|
+
|
|
246
|
+
begin
|
|
247
|
+
ws.send(JSON.generate(op: 'ping'))
|
|
248
|
+
rescue StandardError
|
|
249
|
+
break
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
def stop_pinger
|
|
256
|
+
return unless @ping_thread
|
|
257
|
+
|
|
258
|
+
begin
|
|
259
|
+
@ping_thread.kill
|
|
260
|
+
rescue StandardError
|
|
261
|
+
nil
|
|
262
|
+
end
|
|
263
|
+
@ping_thread = nil
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def flush_subscriptions(topics)
|
|
267
|
+
return if topics.nil? || topics.empty?
|
|
268
|
+
|
|
269
|
+
send_frame(op: 'subscribe', args: topics)
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def send_frame(payload)
|
|
273
|
+
return unless @ws
|
|
274
|
+
|
|
275
|
+
@ws.send(JSON.generate(payload))
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
# HMAC-SHA256 over "GET/realtime" + expires — the private-stream auth
|
|
279
|
+
# scheme documented at
|
|
280
|
+
# https://bybit-exchange.github.io/docs/v5/ws/connect#authentication
|
|
281
|
+
def send_auth_frame
|
|
282
|
+
expires = (Time.now.to_f * 1000).to_i + DEFAULT_AUTH_EXPIRY_MS
|
|
283
|
+
signature = OpenSSL::HMAC.hexdigest('SHA256', @api_secret, "GET/realtime#{expires}")
|
|
284
|
+
send_frame(op: 'auth', args: [@api_key, expires, signature])
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def safe_parse(str)
|
|
288
|
+
JSON.parse(str)
|
|
289
|
+
rescue JSON::ParserError
|
|
290
|
+
nil
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Optional entry point. `require 'bybit'` loads the REST core only; the
|
|
4
|
+
# WebSocket client lives behind a separate `require 'bybit/websocket'` so
|
|
5
|
+
# REST-only consumers don't take the `websocket-client-simple` dependency
|
|
6
|
+
# at load time.
|
|
7
|
+
|
|
8
|
+
require 'bybit'
|
|
9
|
+
require 'bybit/websocket/client'
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bybit-connector-ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Bybit
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-11-11 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: faraday
|
|
@@ -24,6 +24,34 @@ dependencies:
|
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '2.0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: websocket-client-simple
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0.6'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0.6'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rake
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '13.0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '13.0'
|
|
27
55
|
- !ruby/object:Gem::Dependency
|
|
28
56
|
name: rspec
|
|
29
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -66,6 +94,20 @@ dependencies:
|
|
|
66
94
|
- - "~>"
|
|
67
95
|
- !ruby/object:Gem::Version
|
|
68
96
|
version: '0.22'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: vcr
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - "~>"
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '6.2'
|
|
104
|
+
type: :development
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - "~>"
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '6.2'
|
|
69
111
|
- !ruby/object:Gem::Dependency
|
|
70
112
|
name: webmock
|
|
71
113
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -96,7 +138,7 @@ dependencies:
|
|
|
96
138
|
version: '0.9'
|
|
97
139
|
description: Ruby connector for the Bybit V5 REST API — keyword-arg method signatures,
|
|
98
140
|
HMAC-SHA256 signing, typed error hierarchy, Faraday-based transport.
|
|
99
|
-
email:
|
|
141
|
+
email:
|
|
100
142
|
executables: []
|
|
101
143
|
extensions: []
|
|
102
144
|
extra_rdoc_files: []
|
|
@@ -112,22 +154,35 @@ files:
|
|
|
112
154
|
- lib/bybit/error.rb
|
|
113
155
|
- lib/bybit/rest_api/account_service.rb
|
|
114
156
|
- lib/bybit/rest_api/affiliate_service.rb
|
|
157
|
+
- lib/bybit/rest_api/alpha_service.rb
|
|
115
158
|
- lib/bybit/rest_api/asset_service.rb
|
|
116
159
|
- lib/bybit/rest_api/base_service.rb
|
|
117
160
|
- lib/bybit/rest_api/bot_service.rb
|
|
118
161
|
- lib/bybit/rest_api/broker_service.rb
|
|
119
162
|
- lib/bybit/rest_api/crypto_loan_service.rb
|
|
120
163
|
- lib/bybit/rest_api/earn_service.rb
|
|
164
|
+
- lib/bybit/rest_api/event_service.rb
|
|
165
|
+
- lib/bybit/rest_api/fiat_service.rb
|
|
166
|
+
- lib/bybit/rest_api/institutional_loan_service.rb
|
|
121
167
|
- lib/bybit/rest_api/market_service.rb
|
|
168
|
+
- lib/bybit/rest_api/misc_service.rb
|
|
122
169
|
- lib/bybit/rest_api/p2p_service.rb
|
|
123
170
|
- lib/bybit/rest_api/position_service.rb
|
|
171
|
+
- lib/bybit/rest_api/pre_upgrade_service.rb
|
|
172
|
+
- lib/bybit/rest_api/referral_service.rb
|
|
124
173
|
- lib/bybit/rest_api/rfq_service.rb
|
|
125
174
|
- lib/bybit/rest_api/spot_margin_service.rb
|
|
175
|
+
- lib/bybit/rest_api/spot_x_service.rb
|
|
176
|
+
- lib/bybit/rest_api/spread_trade_service.rb
|
|
177
|
+
- lib/bybit/rest_api/strategy_service.rb
|
|
178
|
+
- lib/bybit/rest_api/tax_service.rb
|
|
126
179
|
- lib/bybit/rest_api/trade_service.rb
|
|
127
180
|
- lib/bybit/rest_api/user_service.rb
|
|
128
181
|
- lib/bybit/session.rb
|
|
129
182
|
- lib/bybit/utils/wire_keys.rb
|
|
130
183
|
- lib/bybit/version.rb
|
|
184
|
+
- lib/bybit/websocket.rb
|
|
185
|
+
- lib/bybit/websocket/client.rb
|
|
131
186
|
homepage: https://github.com/bybit-exchange/bybit.ruby.api
|
|
132
187
|
licenses:
|
|
133
188
|
- MIT
|
|
@@ -136,7 +191,7 @@ metadata:
|
|
|
136
191
|
documentation_uri: https://bybit-exchange.github.io/docs/v5/intro
|
|
137
192
|
changelog_uri: https://github.com/bybit-exchange/bybit.ruby.api/blob/main/CHANGELOG.md
|
|
138
193
|
rubygems_mfa_required: 'true'
|
|
139
|
-
post_install_message:
|
|
194
|
+
post_install_message:
|
|
140
195
|
rdoc_options: []
|
|
141
196
|
require_paths:
|
|
142
197
|
- lib
|
|
@@ -151,8 +206,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
151
206
|
- !ruby/object:Gem::Version
|
|
152
207
|
version: '0'
|
|
153
208
|
requirements: []
|
|
154
|
-
rubygems_version: 3.
|
|
155
|
-
signing_key:
|
|
209
|
+
rubygems_version: 3.5.22
|
|
210
|
+
signing_key:
|
|
156
211
|
specification_version: 4
|
|
157
212
|
summary: Official Bybit V5 REST API connector for Ruby
|
|
158
213
|
test_files: []
|