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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 29c7f3e3612cc7bc336a83b1eaf26480ec881b491e7e3c66d042b9a6a23efb71
|
|
4
|
+
data.tar.gz: 7d64066ef1795efbdfc0f13c11bda3f8ea5e99e6f0d627fb4a1baf28bd6de99c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e767a4025a6b105dad09bd0abb87ad04127183505981a35445e9d699c512ea9c699e769a77bd6b8a899fe7f2a91a073c70d823f822b08383f63ec9d3ef20a728
|
|
7
|
+
data.tar.gz: 312fd1a206d9513423767aa47d1a1009bbd28883d14367928df5799698c31205f72c661b9efcbfc36f1795b97434147c02a6ff3ba0235a744f616072f4e9213b
|
data/CHANGELOG.md
CHANGED
|
@@ -5,7 +5,136 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## 0.1.
|
|
8
|
+
## [0.1.3] - 2026-11-06
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- `AlphaService#get_lp_order_list(...)`
|
|
12
|
+
- `AlphaService#get_lp_pay_token_list(...)`
|
|
13
|
+
- `AlphaService#get_lp_pay_token_price(...)`
|
|
14
|
+
- `AlphaService#get_lp_pool_info(...)`
|
|
15
|
+
- `AlphaService#get_lp_pool_list(...)`
|
|
16
|
+
- `AlphaService#get_lp_position_list(...)`
|
|
17
|
+
- `AlphaService#execute_lp_redeem(...)`
|
|
18
|
+
- `AlphaService#execute_lp_stake(...)`
|
|
19
|
+
- `AlphaService#execute_prediction_buy(...)`
|
|
20
|
+
- `AlphaService#get_prediction_engine_status(...)`
|
|
21
|
+
- `AlphaService#get_prediction_event_detail(...)`
|
|
22
|
+
- `AlphaService#get_prediction_order_book(...)`
|
|
23
|
+
- `AlphaService#get_prediction_order_estimate(...)`
|
|
24
|
+
- `AlphaService#get_prediction_order_list(...)`
|
|
25
|
+
- `AlphaService#get_prediction_pay_token_list(...)`
|
|
26
|
+
- `AlphaService#get_prediction_portfolio_summary(...)`
|
|
27
|
+
- `AlphaService#get_prediction_position_history(...)`
|
|
28
|
+
- `AlphaService#get_prediction_position_list(...)`
|
|
29
|
+
- `AlphaService#get_prediction_price_history(...)`
|
|
30
|
+
- `AlphaService#execute_prediction_sell(...)`
|
|
31
|
+
- `AlphaService#get_prediction_side_market_list(...)`
|
|
32
|
+
- `AlphaService#get_prediction_group_stage_detail(...)`
|
|
33
|
+
- `AlphaService#get_prediction_match_list(...)`
|
|
34
|
+
- `AlphaService#get_prediction_timeline_stages(...)`
|
|
35
|
+
- `AlphaService#get_prediction_token_price(...)`
|
|
36
|
+
- `AlphaService#get_asset_detail(...)`
|
|
37
|
+
- `AlphaService#get_asset_list(...)`
|
|
38
|
+
- `AlphaService#get_biz_token_details(...)`
|
|
39
|
+
- `AlphaService#get_biz_token_list(...)`
|
|
40
|
+
- `AlphaService#get_biz_token_price_list(...)`
|
|
41
|
+
- `AlphaService#get_order_list(...)`
|
|
42
|
+
- `AlphaService#get_pay_token_list(...)`
|
|
43
|
+
- `AlphaService#execute_purchase(...)`
|
|
44
|
+
- `AlphaService#get_trade_quote(...)`
|
|
45
|
+
- `AlphaService#execute_redeem(...)`
|
|
46
|
+
- `EventService#get_ec_order_history(...)`
|
|
47
|
+
- `EventService#get_ec_active_orders(...)`
|
|
48
|
+
- `EventService#get_ec_position_info(...)`
|
|
49
|
+
- `EventService#get_ec_settlements(...)`
|
|
50
|
+
- `EventService#get_ec_trade_history(...)`
|
|
51
|
+
- `TaxService#batch_create_tax_reports(...)`
|
|
52
|
+
- `TaxService#batch_query_tax_reports(...)`
|
|
53
|
+
- `FiatService#query_balance(...)`
|
|
54
|
+
- `FiatService#query_coin_list(...)`
|
|
55
|
+
- `FiatService#query_trade_history(...)`
|
|
56
|
+
- `FiatService#apply_quote(...)`
|
|
57
|
+
- `FiatService#get_reference_price(...)`
|
|
58
|
+
- `FiatService#confirm_quote(...)`
|
|
59
|
+
- `FiatService#query_trade(...)`
|
|
60
|
+
- `InstitutionalLoanService#ins_loan_coin_delta_amount(...)`
|
|
61
|
+
- `InstitutionalLoanService#ins_loan_delay_liq_status(...)`
|
|
62
|
+
- `ReferralService#get_campaign_rewards(...)`
|
|
63
|
+
- `ReferralService#get_commission_records(...)`
|
|
64
|
+
- `ReferralService#get_user_identity_profile(...)`
|
|
65
|
+
- `ReferralService#get_user_invitations(...)`
|
|
66
|
+
- `SpotMarginService#query_fixed_borrow_penalty_interest(...)`
|
|
67
|
+
- `SpotMarginService#cancel_fixed_borrow_order(...)`
|
|
68
|
+
- `SpotXService#get_launchpool_project_list(...)`
|
|
69
|
+
- `SpotXService#get_launchpool_user_activity_log(...)`
|
|
70
|
+
- `SpotXService#get_launchpool_user_current_staking(...)`
|
|
71
|
+
- `SpotXService#get_launchpool_user_history(...)`
|
|
72
|
+
- `SpotXService#get_puzzle_project_list(...)`
|
|
73
|
+
- `SpotXService#get_token_splash_project_list(...)`
|
|
74
|
+
- `SpotXService#get_token_splash_user_activity_params(...)`
|
|
75
|
+
- `SpreadTradeService#get_history(...)`
|
|
76
|
+
- `SpreadTradeService#get_spread_instruments_info(...)`
|
|
77
|
+
- `SpreadTradeService#get_spread_max_qty(...)`
|
|
78
|
+
- `SpreadTradeService#amend_spread_order(...)`
|
|
79
|
+
- `SpreadTradeService#cancel_spread_order(...)`
|
|
80
|
+
- `SpreadTradeService#cancel_all_spread_orders(...)`
|
|
81
|
+
- `SpreadTradeService#create_spread_order(...)`
|
|
82
|
+
- `SpreadTradeService#get_spread_order_history(...)`
|
|
83
|
+
- `SpreadTradeService#get_spread_open_orders(...)`
|
|
84
|
+
- `SpreadTradeService#get_spread_orderbook(...)`
|
|
85
|
+
- `SpreadTradeService#get_spread_recent_trades(...)`
|
|
86
|
+
- `SpreadTradeService#get_spread_tickers(...)`
|
|
87
|
+
- `StrategyService#create_strategy(...)`
|
|
88
|
+
- `StrategyService#query_list(...)`
|
|
89
|
+
- `StrategyService#query_order_list(...)`
|
|
90
|
+
- `StrategyService#stop_strategy(...)`
|
|
91
|
+
|
|
92
|
+
### Fixed
|
|
93
|
+
- `AlphaService#get_prediction_side_market_list(...)` now requires `event_id` and accepts the documented filters and pagination options.
|
|
94
|
+
|
|
95
|
+
### Sources
|
|
96
|
+
- OpenAPI: `705f49bf6dba27ecc5b9b402f46ab2423cfb5dd9`
|
|
97
|
+
- Docs: `9cde0843c270dd1e6009fb4593272f43f60cccf0`
|
|
98
|
+
|
|
99
|
+
## [0.1.2] - 2026-10-13
|
|
100
|
+
|
|
101
|
+
### Added
|
|
102
|
+
- `AccountService#demo_apply_money(...)`
|
|
103
|
+
- `AccountService#get_option_asset_info(...)`
|
|
104
|
+
- `AccountService#get_pay_info(...)`
|
|
105
|
+
- `AccountService#get_trade_info_for_analysis(...)`
|
|
106
|
+
- `AssetService#limit_order_callback(...)`
|
|
107
|
+
- `CryptoLoanService#get_fixed_available_inventory(...)`
|
|
108
|
+
- `CryptoLoanService#get_fixed_repayment_history(...)`
|
|
109
|
+
- `CryptoLoanService#supply_fixed(...)`
|
|
110
|
+
- `CryptoLoanService#get_flexible_available_inventory(...)`
|
|
111
|
+
- `EarnService#list_auto_savings(...)`
|
|
112
|
+
- `EarnService#edit_earn_auto_savings(...)`
|
|
113
|
+
- `MarketService#get_option_base_coins(...)`
|
|
114
|
+
- `PositionService#get_symbol_info(...)`
|
|
115
|
+
- `SpotMarginService#get_trade_coin_state(...)`
|
|
116
|
+
- `SpotMarginService#query_fixed_available_inventory(...)`
|
|
117
|
+
- `SpotMarginService#account_fixed_borrow(...)`
|
|
118
|
+
- `SpotMarginService#query_fixed_borrow_contracts(...)`
|
|
119
|
+
- `SpotMarginService#query_fixed_borrow_orders(...)`
|
|
120
|
+
- `SpotMarginService#query_fixed_borrow_market(...)`
|
|
121
|
+
- `SpotMarginService#renew_fixed_borrow(...)`
|
|
122
|
+
- `SpotMarginService#get_trade_flexible_available_inventory(...)`
|
|
123
|
+
- `SpotMarginService#get_trade_auto_repay_mode(...)`
|
|
124
|
+
- `SpotMarginService#query_borrow_liability(...)`
|
|
125
|
+
- `SpotMarginService#get_trade_max_borrowable(...)`
|
|
126
|
+
- `SpotMarginService#get_trade_repayment_available_amount(...)`
|
|
127
|
+
- `SpotMarginService#set_auto_repay_mode(...)`
|
|
128
|
+
- `SpotMarginService#spot_margin_set_leverage(...)`
|
|
129
|
+
- `SpotMarginService#get_trade_state(...)`
|
|
130
|
+
- `SpotMarginService#spot_margin_switch_mode(...)`
|
|
131
|
+
- `UserService#query_referral_code(...)`
|
|
132
|
+
|
|
133
|
+
### Sources
|
|
134
|
+
- OpenAPI: `08130d57323d390dea58f15418758e2667c74ce6`
|
|
135
|
+
- Docs: `59e3d457dea6b419a14987c19a3aabf4ffb38238`
|
|
136
|
+
|
|
137
|
+
## [0.1.1] - 2026-07-22
|
|
9
138
|
|
|
10
139
|
### Added
|
|
11
140
|
- `AccountService#batch_set_collateral(...)`
|
|
@@ -34,9 +163,48 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
34
163
|
- `AccountService#upgrade_to_uta_pro(...)`
|
|
35
164
|
- `AffiliateService#get_sub_list(...)`
|
|
36
165
|
- `AffiliateService#get_user_list(...)`
|
|
166
|
+
- `AssetService#account_coin_balance_query(...)`
|
|
167
|
+
- `AssetService#asset_info_query(...)`
|
|
168
|
+
- `AssetService#cancel_withdraw(...)`
|
|
169
|
+
- `AssetService#coin_convert_limit_query(...)`
|
|
170
|
+
- `AssetService#coin_list_query(...)`
|
|
171
|
+
- `AssetService#convert_execute(...)`
|
|
172
|
+
- `AssetService#convert_history_query(...)`
|
|
173
|
+
- `AssetService#get_asset_overview(...)`
|
|
37
174
|
- `AssetService#get_coin_balance(...)`
|
|
38
175
|
- `AssetService#get_coin_greeks(...)`
|
|
176
|
+
- `AssetService#get_coin_info(...)`
|
|
177
|
+
- `AssetService#get_convert_result(...)`
|
|
178
|
+
- `AssetService#get_delivery_record(...)`
|
|
179
|
+
- `AssetService#get_deposit_address(...)`
|
|
180
|
+
- `AssetService#get_portfolio_margin(...)`
|
|
181
|
+
- `AssetService#get_settlement_record(...)`
|
|
182
|
+
- `AssetService#get_sub_member_deposit_address(...)`
|
|
183
|
+
- `AssetService#get_total_members_assets(...)`
|
|
184
|
+
- `AssetService#get_vasp_list(...)`
|
|
185
|
+
- `AssetService#get_withdrawable_amount_by_coin(...)`
|
|
186
|
+
- `AssetService#inter_transfer(...)`
|
|
187
|
+
- `AssetService#inter_transfer_list_query(...)`
|
|
188
|
+
- `AssetService#list_convert_orders(...)`
|
|
189
|
+
- `AssetService#list_convert_orders_by_page(...)`
|
|
190
|
+
- `AssetService#list_deposit_records(...)`
|
|
39
191
|
- `AssetService#list_funding_history(...)`
|
|
192
|
+
- `AssetService#list_internal_deposit_records(...)`
|
|
193
|
+
- `AssetService#list_small_balance_coins(...)`
|
|
194
|
+
- `AssetService#list_small_balance_history(...)`
|
|
195
|
+
- `AssetService#list_sub_member_deposit_records(...)`
|
|
196
|
+
- `AssetService#list_withdraw_addresses(...)`
|
|
197
|
+
- `AssetService#list_withdraw_records(...)`
|
|
198
|
+
- `AssetService#quote_apply(...)`
|
|
199
|
+
- `AssetService#send_withdraw(...)`
|
|
200
|
+
- `AssetService#set_default_deposit_to_account(...)`
|
|
201
|
+
- `AssetService#small_asset_convert(...)`
|
|
202
|
+
- `AssetService#small_asset_quote(...)`
|
|
203
|
+
- `AssetService#sub_member_list_query(...)`
|
|
204
|
+
- `AssetService#transfer_coin_list_query(...)`
|
|
205
|
+
- `AssetService#transfer_sub_member_save(...)`
|
|
206
|
+
- `AssetService#universal_transfer(...)`
|
|
207
|
+
- `AssetService#universal_transfer_list_query(...)`
|
|
40
208
|
- `BrokerService#distribute_award(...)`
|
|
41
209
|
- `BrokerService#get_award_info(...)`
|
|
42
210
|
- `BrokerService#get_distribution_record(...)`
|
|
@@ -257,3 +425,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
257
425
|
- `UserService#sign_agreement(...)`
|
|
258
426
|
- `UserService#update_api_key(...)`
|
|
259
427
|
- `UserService#update_sub_api_key(...)`
|
|
428
|
+
- `InstitutionalLoanService#get_product_info(...)`
|
|
429
|
+
- `InstitutionalLoanService#get_margin_coin_info(...)`
|
|
430
|
+
- `InstitutionalLoanService#get_loan_orders(...)`
|
|
431
|
+
- `InstitutionalLoanService#get_repayment_orders(...)`
|
|
432
|
+
- `InstitutionalLoanService#get_ltv(...)`
|
|
433
|
+
- `InstitutionalLoanService#bind_or_unbind_uid(...)`
|
|
434
|
+
- `InstitutionalLoanService#repay_loan(...)`
|
|
435
|
+
- `MiscService#get_announcements(...)`
|
|
436
|
+
- `MiscService#get_system_status(...)`
|
|
437
|
+
- `PreUpgradeService#get_order_history(...)`
|
|
438
|
+
- `PreUpgradeService#get_trade_history(...)`
|
|
439
|
+
- `PreUpgradeService#get_closed_pnl(...)`
|
|
440
|
+
- `PreUpgradeService#get_transaction_log(...)`
|
|
441
|
+
- `PreUpgradeService#get_option_delivery_record(...)`
|
|
442
|
+
- `PreUpgradeService#get_usdc_session_settlement(...)`
|
|
443
|
+
- `Bybit::WebSocket::Client` — public (spot/linear/inverse/option), private,
|
|
444
|
+
and trade streams; HMAC-SHA256 auth, ping/pong, deferred subscribe (topics
|
|
445
|
+
buffered until socket opens; private streams wait for auth OK), idempotent
|
|
446
|
+
`#connect` (second call replays buffered subscriptions), testnet host
|
|
447
|
+
support. Load via `require 'bybit/websocket'` (opt-in dep on
|
|
448
|
+
`websocket-client-simple`).
|
|
449
|
+
- VCR-driven end-to-end specs asserting the exact wire bytes and X-BAPI-SIGN
|
|
450
|
+
header for signed GET (query) and signed POST (body) routing.
|
|
451
|
+
- SimpleCov floor coverage gate for `lib/bybit/rest_api/*_service.rb` — new
|
|
452
|
+
services without matching specs now drop CI.
|
|
453
|
+
- README: WebSocket usage section.
|
|
454
|
+
|
|
455
|
+
### Fixed
|
|
456
|
+
- `Session#parse_response` now maps HTTP 401/403 → `Bybit::AuthError` and 429
|
|
457
|
+
→ `Bybit::RateLimitError` even when the response body is non-JSON
|
|
458
|
+
(CDN/WAF path), matching the contract in README.md#Error-Handling.
|
|
459
|
+
- `BrokerService#list_broker_earnings` — caller-facing kwargs renamed from
|
|
460
|
+
`:begin_` / `:end_` to `:start_date` / `:end_date`; internal rewrite now
|
|
461
|
+
goes through `WireKeys::RESERVED_ALIASES` instead of hand-rolled shim.
|
data/README.md
CHANGED
|
@@ -1,8 +1,26 @@
|
|
|
1
1
|
# bybit-connector-ruby
|
|
2
2
|
|
|
3
|
+
[](https://rubygems.org/gems/bybit-connector-ruby) [](https://github.com/bybit-exchange/bybit.ruby.api/blob/main/LICENSE)
|
|
4
|
+
|
|
3
5
|
Official lightweight Ruby connector for the [Bybit V5 REST API](https://bybit-exchange.github.io/docs/v5/intro).
|
|
4
6
|
|
|
5
|
-
`bybit-connector-ruby` wraps the Bybit V5 HTTP endpoints as a set of typed Ruby methods with keyword-arg signatures.
|
|
7
|
+
`bybit-connector-ruby` wraps the Bybit V5 HTTP endpoints as a set of typed Ruby methods with keyword-arg signatures.
|
|
8
|
+
## Prerequisites
|
|
9
|
+
|
|
10
|
+
Before you write any code you need a Bybit API key. Two accounts to know
|
|
11
|
+
about:
|
|
12
|
+
|
|
13
|
+
- **Testnet** — [testnet.bybit.com](https://testnet.bybit.com) → sign up →
|
|
14
|
+
API Management → *Create New Key*. This is where you should point every
|
|
15
|
+
new integration until you're confident about behavior. Testnet balances
|
|
16
|
+
are virtual; nothing you do here touches real funds.
|
|
17
|
+
- **Mainnet** — [bybit.com](https://www.bybit.com) → API Management. Real
|
|
18
|
+
money. Enable only the permissions you actually need (spot / derivatives /
|
|
19
|
+
withdrawals) and prefer IP-restricted keys.
|
|
20
|
+
|
|
21
|
+
Testnet and mainnet keys are **separate** — an API key issued on one won't
|
|
22
|
+
work against the other. The SDK selects the environment via
|
|
23
|
+
`testnet: true|false` (or an explicit `base_url:` override).
|
|
6
24
|
|
|
7
25
|
## Installation
|
|
8
26
|
|
|
@@ -23,30 +41,43 @@ gem 'bybit-connector-ruby'
|
|
|
23
41
|
```ruby
|
|
24
42
|
require 'bybit'
|
|
25
43
|
|
|
44
|
+
# All calls below run against testnet — swap testnet: false for mainnet
|
|
45
|
+
# once you're happy with the behavior.
|
|
26
46
|
Bybit.configure do |c|
|
|
27
|
-
c.api_key = ENV['
|
|
28
|
-
c.api_secret = ENV['
|
|
29
|
-
c.testnet = true
|
|
47
|
+
c.api_key = ENV['BYBIT_TESTNET_KEY']
|
|
48
|
+
c.api_secret = ENV['BYBIT_TESTNET_SECRET']
|
|
49
|
+
c.testnet = true
|
|
30
50
|
end
|
|
31
51
|
|
|
32
52
|
client = Bybit::Client.new
|
|
33
53
|
|
|
34
|
-
# Public endpoint — no auth needed
|
|
54
|
+
# 1. Public endpoint — no auth needed.
|
|
35
55
|
puts client.market.get_server_time
|
|
36
56
|
|
|
37
|
-
# Signed endpoint —
|
|
57
|
+
# 2. Signed endpoint — api_key + api_secret required.
|
|
38
58
|
wallet = client.account.get_wallet_balance(account_type: 'UNIFIED')
|
|
39
59
|
puts wallet['result']['list']
|
|
40
60
|
|
|
41
|
-
# Place
|
|
61
|
+
# 3. Place a LIMIT order well below market so it sits on the book and does
|
|
62
|
+
# NOT fill (safe to run repeatedly). Adjust `price:` if BTC ever trades
|
|
63
|
+
# at $10k again — otherwise this stays a resting order you can cancel.
|
|
42
64
|
order = client.trade.create_order(
|
|
43
65
|
category: 'linear', symbol: 'BTCUSDT',
|
|
44
66
|
side: 'Buy', order_type: 'Limit', qty: '0.01',
|
|
45
|
-
price: '
|
|
67
|
+
price: '10000', time_in_force: 'GTC'
|
|
46
68
|
)
|
|
47
|
-
|
|
69
|
+
order_id = order['result']['orderId']
|
|
70
|
+
puts "orderId: #{order_id}"
|
|
71
|
+
|
|
72
|
+
# 4. Cancel it before moving on.
|
|
73
|
+
client.trade.cancel_order(category: 'linear', symbol: 'BTCUSDT', order_id: order_id)
|
|
48
74
|
```
|
|
49
75
|
|
|
76
|
+
> ⚠️ **Before switching `testnet: false`**: verify the price / qty in
|
|
77
|
+
> `create_order` won't cross the top of the book — a Limit Buy at $10k on
|
|
78
|
+
> mainnet becomes a market fill instantly (if BTC ever drops that low),
|
|
79
|
+
> and a Limit Sell at $1M does the reverse.
|
|
80
|
+
|
|
50
81
|
See `examples/quickstart.rb` for a runnable script.
|
|
51
82
|
|
|
52
83
|
## Configuration
|
|
@@ -58,12 +89,17 @@ Bybit.configure do |c|
|
|
|
58
89
|
c.api_key = ENV['BYBIT_KEY']
|
|
59
90
|
c.api_secret = ENV['BYBIT_SECRET']
|
|
60
91
|
c.testnet = false # default false
|
|
61
|
-
c.recv_window = '5000' #
|
|
92
|
+
c.recv_window = '5000' # milliseconds — Bybit rejects requests
|
|
93
|
+
# whose signed timestamp is older than
|
|
94
|
+
# this window. Bump to 10000+ if your
|
|
95
|
+
# clock drifts or the network is noisy.
|
|
62
96
|
c.timeout = 10 # Faraday timeout, seconds
|
|
63
97
|
end
|
|
64
98
|
```
|
|
65
99
|
|
|
66
|
-
Or pass overrides to `Client.new
|
|
100
|
+
Or pass overrides to `Client.new` — **per-client overrides win over
|
|
101
|
+
`Bybit.configure`**, so you can share defaults globally and still spin up a
|
|
102
|
+
dedicated client with a different key or environment:
|
|
67
103
|
|
|
68
104
|
```ruby
|
|
69
105
|
client = Bybit::Client.new(api_key: '...', api_secret: '...', testnet: true)
|
|
@@ -92,16 +128,27 @@ Each API group is a property on `Bybit::Client`:
|
|
|
92
128
|
- `client.trade` — orders (create / amend / cancel / batch / history)
|
|
93
129
|
- `client.position` — positions, leverage, TP/SL, move-position
|
|
94
130
|
- `client.account` — wallet, margin, collateral, fee-rate, transaction log
|
|
131
|
+
- `client.alpha` — Alpha liquidity pools, prediction markets, and on-chain token trading
|
|
95
132
|
- `client.asset` — coin balance, coin greeks, funding history
|
|
96
133
|
- `client.user` — sub-accounts, API-key management
|
|
97
134
|
- `client.affiliate` — sub-affiliate lists
|
|
98
135
|
- `client.broker` — broker earnings, distributions
|
|
99
136
|
- `client.crypto_loan` — flexible / fixed crypto loans
|
|
137
|
+
- `client.event` — event contracts, positions, settlements, and executions
|
|
138
|
+
- `client.fiat` — fiat convert balances, quotes, trades, and history
|
|
139
|
+
- `client.institutional_loan` — /v5/ins-loan/* (OTC institutional loans)
|
|
100
140
|
- `client.rfq` — request-for-quote (block trades)
|
|
101
141
|
- `client.spot_margin` — UTA spot margin
|
|
142
|
+
- `client.spot_x` — Launchpool, Puzzle Hunt, and Token Splash
|
|
143
|
+
- `client.spread_trade` — spread instruments, orders, orderbook, and executions
|
|
144
|
+
- `client.strategy` — strategy creation, queries, and lifecycle operations
|
|
145
|
+
- `client.tax` — private tax report generation and status queries
|
|
102
146
|
- `client.earn` — earn, liquidity mining, RWA, PWM, hold-to-earn
|
|
103
147
|
- `client.p2p` — P2P advertise / order / chat
|
|
104
148
|
- `client.bot` — DCA / grid / futures-combo / futures-grid / martingale
|
|
149
|
+
- `client.pre_upgrade` — /v5/pre-upgrade/* historical queries for Classic → UTA upgrades
|
|
150
|
+
- `client.referral` — campaign rewards, commissions, profiles, and invitations
|
|
151
|
+
- `client.misc` — /v5/announcements/index, /v5/system/status
|
|
105
152
|
|
|
106
153
|
## Error Handling
|
|
107
154
|
|
|
@@ -139,6 +186,12 @@ Full hierarchy:
|
|
|
139
186
|
|
|
140
187
|
Every `ApiError` exposes `#ret_code`, `#ret_msg`, `#result`, `#time`, `#http_status`. See the [Bybit V5 error-code list](https://bybit-exchange.github.io/docs/v5/error) for meanings.
|
|
141
188
|
|
|
189
|
+
> The `sleep 1 && retry` shown above is fine for exploration, **not** for
|
|
190
|
+
> production — Bybit will escalate throttling on tight retry loops. For
|
|
191
|
+
> real workloads, wire a `Faraday::Retry` middleware with exponential
|
|
192
|
+
> backoff via the "bring your own Faraday connection" hook in
|
|
193
|
+
> [Configuration](#configuration) above.
|
|
194
|
+
|
|
142
195
|
## Return Value
|
|
143
196
|
|
|
144
197
|
Every service method returns the raw parsed JSON as a `Hash`:
|
|
@@ -151,14 +204,106 @@ response['result'] # => { 'category' => 'spot', 'symbol' => 'BTCUSDT', 'list
|
|
|
151
204
|
response['time'] # => 1234567890000
|
|
152
205
|
```
|
|
153
206
|
|
|
154
|
-
|
|
207
|
+
> Keys are **strings, not symbols** — `response[:result]` is `nil`. This is
|
|
208
|
+
> a common first-hour gotcha; pass through `JSON.parse` semantics rather
|
|
209
|
+
> than converting.
|
|
210
|
+
|
|
211
|
+
## Method Reference
|
|
212
|
+
|
|
213
|
+
Method names follow the Bybit V5 endpoint slug in snake_case, grouped by
|
|
214
|
+
domain. A few illustrative mappings:
|
|
215
|
+
|
|
216
|
+
| Bybit V5 path | SDK method |
|
|
217
|
+
| ------------------------------------- | ----------------------------------------- |
|
|
218
|
+
| `GET /v5/market/kline` | `client.market.get_kline` |
|
|
219
|
+
| `GET /v5/market/tickers` | `client.market.get_tickers` |
|
|
220
|
+
| `POST /v5/order/create` | `client.trade.create_order` |
|
|
221
|
+
| `POST /v5/order/cancel` | `client.trade.cancel_order` |
|
|
222
|
+
| `GET /v5/position/list` | `client.position.get_positions` |
|
|
223
|
+
| `GET /v5/account/wallet-balance` | `client.account.get_wallet_balance` |
|
|
224
|
+
|
|
225
|
+
For the full list, generate YARD docs locally:
|
|
226
|
+
|
|
227
|
+
```
|
|
228
|
+
bundle exec yard doc
|
|
229
|
+
open doc/index.html
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
or browse the published copy on
|
|
233
|
+
[rubydoc.info/gems/bybit-connector-ruby](https://rubydoc.info/gems/bybit-connector-ruby).
|
|
234
|
+
|
|
235
|
+
## Pagination
|
|
236
|
+
|
|
237
|
+
Bybit V5 uses **opaque cursor pagination** — the response's
|
|
238
|
+
`result['nextPageCursor']` (empty string when the page is the last one)
|
|
239
|
+
feeds back in as the `cursor:` argument on the next call:
|
|
240
|
+
|
|
241
|
+
```ruby
|
|
242
|
+
cursor = nil
|
|
243
|
+
loop do
|
|
244
|
+
resp = client.trade.get_order_history(category: 'linear', limit: 50, cursor: cursor)
|
|
245
|
+
resp['result']['list'].each { |order| process(order) }
|
|
246
|
+
cursor = resp['result']['nextPageCursor']
|
|
247
|
+
break if cursor.nil? || cursor.empty?
|
|
248
|
+
end
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
The same pattern works for `get_positions`, `get_execution_history`,
|
|
252
|
+
`get_transaction_log`, and every other paginated endpoint.
|
|
253
|
+
|
|
254
|
+
## WebSockets
|
|
155
255
|
|
|
156
|
-
|
|
256
|
+
Hosts (mirror the REST split):
|
|
257
|
+
|
|
258
|
+
- Mainnet — `wss://stream.bybit.com/v5/{public/<category>|private|trade}`
|
|
259
|
+
- Testnet — `wss://stream-testnet.bybit.com/v5/{public/<category>|private|trade}`
|
|
260
|
+
|
|
261
|
+
WebSocket support ships behind an opt-in require so REST-only consumers don't
|
|
262
|
+
load the underlying `websocket-client-simple` dependency at boot. Four
|
|
263
|
+
callbacks are available; all are optional but you'll almost always want at
|
|
264
|
+
least `on_message`.
|
|
157
265
|
|
|
158
266
|
```ruby
|
|
159
|
-
|
|
267
|
+
require 'bybit/websocket'
|
|
268
|
+
|
|
269
|
+
# Public stream — no auth needed.
|
|
270
|
+
public_ws = Bybit::WebSocket::Client.new(
|
|
271
|
+
channel: :linear, # :spot / :linear / :inverse / :option
|
|
272
|
+
testnet: true,
|
|
273
|
+
on_open: -> { puts 'connected' },
|
|
274
|
+
on_message: ->(msg) { puts msg.inspect }, # your handler
|
|
275
|
+
on_close: ->(_ev) { puts 'closed' },
|
|
276
|
+
on_error: ->(err) { warn "ws error: #{err}" }
|
|
277
|
+
).connect
|
|
278
|
+
|
|
279
|
+
public_ws.subscribe('tickers.BTCUSDT', 'orderbook.1.BTCUSDT')
|
|
280
|
+
|
|
281
|
+
# Private stream — HMAC-SHA256 auth over "GET/realtime" + expiry.
|
|
282
|
+
private_ws = Bybit::WebSocket::Client.new(
|
|
283
|
+
channel: :private,
|
|
284
|
+
testnet: true,
|
|
285
|
+
api_key: ENV['BYBIT_TESTNET_KEY'],
|
|
286
|
+
api_secret: ENV['BYBIT_TESTNET_SECRET'],
|
|
287
|
+
on_message: ->(msg) { puts msg.inspect } # your handler
|
|
288
|
+
).connect
|
|
289
|
+
|
|
290
|
+
# Subscribe returns immediately; the actual `op:subscribe` frame is deferred
|
|
291
|
+
# until the private-stream auth reply lands, so you can call subscribe
|
|
292
|
+
# anytime — before or after `#connect`.
|
|
293
|
+
private_ws.subscribe('position', 'order', 'wallet')
|
|
294
|
+
|
|
295
|
+
# Later:
|
|
296
|
+
private_ws.unsubscribe('wallet')
|
|
297
|
+
private_ws.disconnect
|
|
160
298
|
```
|
|
161
299
|
|
|
300
|
+
Supported channels: `:spot`, `:linear`, `:inverse`, `:option`, `:private`,
|
|
301
|
+
`:trade`. `testnet: true` swaps in the `stream-testnet.bybit.com` host.
|
|
302
|
+
Pings ship every 20 seconds — Bybit closes idle sockets after ~20s of
|
|
303
|
+
silence. There is no automatic reconnect on network drop: callers listening
|
|
304
|
+
on `on_close` can invoke `#connect` again to reopen the socket and replay
|
|
305
|
+
the buffered `#subscriptions`.
|
|
306
|
+
|
|
162
307
|
## Development
|
|
163
308
|
|
|
164
309
|
```
|
data/examples/quickstart.rb
CHANGED
|
@@ -1,29 +1,35 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# End-to-end quickstart —
|
|
4
|
-
#
|
|
3
|
+
# End-to-end quickstart — mirrors README's Quick Start:
|
|
4
|
+
# 1. public unsigned call
|
|
5
|
+
# 2. signed GET (wallet balance)
|
|
6
|
+
# 3. safe LIMIT order well below market (does not fill)
|
|
7
|
+
# 4. cancel that order
|
|
8
|
+
# Run with:
|
|
9
|
+
# BYBIT_TESTNET_KEY=... BYBIT_TESTNET_SECRET=... ruby examples/quickstart.rb
|
|
5
10
|
|
|
6
11
|
require 'bybit'
|
|
7
12
|
|
|
8
13
|
Bybit.configure do |c|
|
|
9
|
-
c.api_key = ENV
|
|
10
|
-
c.api_secret = ENV
|
|
11
|
-
c.testnet = true # flip to false for mainnet
|
|
14
|
+
c.api_key = ENV.fetch('BYBIT_TESTNET_KEY')
|
|
15
|
+
c.api_secret = ENV.fetch('BYBIT_TESTNET_SECRET')
|
|
16
|
+
c.testnet = true # flip to false for mainnet — see README warning
|
|
12
17
|
end
|
|
13
18
|
|
|
14
19
|
client = Bybit::Client.new
|
|
15
20
|
|
|
16
|
-
# 1. Public endpoint — server time (no auth needed)
|
|
21
|
+
# 1. Public endpoint — server time (no auth needed).
|
|
17
22
|
puts '--- server time ---'
|
|
18
23
|
puts client.market.get_server_time.inspect
|
|
19
24
|
|
|
20
|
-
# 2. Signed endpoint — wallet balance
|
|
25
|
+
# 2. Signed endpoint — wallet balance.
|
|
21
26
|
puts '--- wallet balance ---'
|
|
22
27
|
begin
|
|
23
28
|
wallet = client.account.get_wallet_balance(account_type: 'UNIFIED')
|
|
24
29
|
puts wallet['result']['list'].inspect
|
|
25
30
|
rescue Bybit::AuthError => e
|
|
26
31
|
warn "auth failed: [#{e.ret_code}] #{e.ret_msg}"
|
|
32
|
+
exit 1
|
|
27
33
|
rescue Bybit::RateLimitError => e
|
|
28
34
|
warn "rate-limited: #{e.ret_msg}"
|
|
29
35
|
rescue Bybit::TimeoutError => e
|
|
@@ -33,3 +39,26 @@ rescue Bybit::NetworkError => e
|
|
|
33
39
|
rescue Bybit::ApiError => e
|
|
34
40
|
warn "api error [#{e.ret_code}]: #{e.ret_msg}"
|
|
35
41
|
end
|
|
42
|
+
|
|
43
|
+
# 3. Place a LIMIT order well below market so it sits on the book and does
|
|
44
|
+
# NOT fill (safe to run repeatedly). Adjust price if BTC ever trades that
|
|
45
|
+
# low; otherwise this stays a resting order you can cancel below.
|
|
46
|
+
puts '--- place limit order ---'
|
|
47
|
+
begin
|
|
48
|
+
order = client.trade.create_order(
|
|
49
|
+
category: 'linear', symbol: 'BTCUSDT',
|
|
50
|
+
side: 'Buy', order_type: 'Limit', qty: '0.01',
|
|
51
|
+
price: '10000', time_in_force: 'GTC'
|
|
52
|
+
)
|
|
53
|
+
order_id = order['result']['orderId']
|
|
54
|
+
puts "orderId: #{order_id}"
|
|
55
|
+
|
|
56
|
+
# 4. Cancel it before exiting so we don't leave test orders on the book.
|
|
57
|
+
puts '--- cancel order ---'
|
|
58
|
+
cancel = client.trade.cancel_order(
|
|
59
|
+
category: 'linear', symbol: 'BTCUSDT', order_id: order_id
|
|
60
|
+
)
|
|
61
|
+
puts cancel['result'].inspect
|
|
62
|
+
rescue Bybit::ApiError => e
|
|
63
|
+
warn "api error [#{e.ret_code}]: #{e.ret_msg}"
|
|
64
|
+
end
|
data/lib/bybit/client.rb
CHANGED
|
@@ -8,13 +8,24 @@ require 'bybit/rest_api/bot_service'
|
|
|
8
8
|
require 'bybit/rest_api/broker_service'
|
|
9
9
|
require 'bybit/rest_api/crypto_loan_service'
|
|
10
10
|
require 'bybit/rest_api/earn_service'
|
|
11
|
+
require 'bybit/rest_api/institutional_loan_service'
|
|
11
12
|
require 'bybit/rest_api/market_service'
|
|
13
|
+
require 'bybit/rest_api/misc_service'
|
|
12
14
|
require 'bybit/rest_api/p2p_service'
|
|
13
15
|
require 'bybit/rest_api/position_service'
|
|
16
|
+
require 'bybit/rest_api/pre_upgrade_service'
|
|
14
17
|
require 'bybit/rest_api/rfq_service'
|
|
15
18
|
require 'bybit/rest_api/spot_margin_service'
|
|
16
19
|
require 'bybit/rest_api/trade_service'
|
|
17
20
|
require 'bybit/rest_api/user_service'
|
|
21
|
+
require 'bybit/rest_api/alpha_service'
|
|
22
|
+
require 'bybit/rest_api/event_service'
|
|
23
|
+
require 'bybit/rest_api/fiat_service'
|
|
24
|
+
require 'bybit/rest_api/referral_service'
|
|
25
|
+
require 'bybit/rest_api/spot_x_service'
|
|
26
|
+
require 'bybit/rest_api/spread_trade_service'
|
|
27
|
+
require 'bybit/rest_api/strategy_service'
|
|
28
|
+
require 'bybit/rest_api/tax_service'
|
|
18
29
|
# gen-sdk-ruby:service-requires:end
|
|
19
30
|
|
|
20
31
|
module Bybit
|
|
@@ -33,8 +44,10 @@ module Bybit
|
|
|
33
44
|
|
|
34
45
|
class Client
|
|
35
46
|
# gen-sdk-ruby:client-readers:start
|
|
36
|
-
attr_reader :account, :affiliate, :asset, :bot, :broker, :crypto_loan, :earn,
|
|
37
|
-
:
|
|
47
|
+
attr_reader :account, :affiliate, :alpha, :asset, :bot, :broker, :crypto_loan, :earn,
|
|
48
|
+
:event, :fiat, :institutional_loan, :market, :misc, :p2p, :position,
|
|
49
|
+
:pre_upgrade, :referral, :rfq, :spot_margin, :spot_x, :spread_trade,
|
|
50
|
+
:strategy, :tax, :trade, :user
|
|
38
51
|
|
|
39
52
|
# gen-sdk-ruby:client-readers:end
|
|
40
53
|
|
|
@@ -45,20 +58,35 @@ module Bybit
|
|
|
45
58
|
@config = cfg
|
|
46
59
|
|
|
47
60
|
# gen-sdk-ruby:client-inits:start
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
{
|
|
62
|
+
account: RestApi::AccountService,
|
|
63
|
+
affiliate: RestApi::AffiliateService,
|
|
64
|
+
alpha: RestApi::AlphaService,
|
|
65
|
+
asset: RestApi::AssetService,
|
|
66
|
+
bot: RestApi::BotService,
|
|
67
|
+
broker: RestApi::BrokerService,
|
|
68
|
+
crypto_loan: RestApi::CryptoLoanService,
|
|
69
|
+
earn: RestApi::EarnService,
|
|
70
|
+
event: RestApi::EventService,
|
|
71
|
+
fiat: RestApi::FiatService,
|
|
72
|
+
institutional_loan: RestApi::InstitutionalLoanService,
|
|
73
|
+
market: RestApi::MarketService,
|
|
74
|
+
misc: RestApi::MiscService,
|
|
75
|
+
p2p: RestApi::P2pService,
|
|
76
|
+
position: RestApi::PositionService,
|
|
77
|
+
pre_upgrade: RestApi::PreUpgradeService,
|
|
78
|
+
referral: RestApi::ReferralService,
|
|
79
|
+
rfq: RestApi::RfqService,
|
|
80
|
+
spot_margin: RestApi::SpotMarginService,
|
|
81
|
+
spot_x: RestApi::SpotXService,
|
|
82
|
+
spread_trade: RestApi::SpreadTradeService,
|
|
83
|
+
strategy: RestApi::StrategyService,
|
|
84
|
+
tax: RestApi::TaxService,
|
|
85
|
+
trade: RestApi::TradeService,
|
|
86
|
+
user: RestApi::UserService
|
|
87
|
+
}.each do |name, service_class|
|
|
88
|
+
instance_variable_set("@#{name}", service_class.new(session))
|
|
89
|
+
end
|
|
62
90
|
# gen-sdk-ruby:client-inits:end
|
|
63
91
|
end
|
|
64
92
|
|
data/lib/bybit/error.rb
CHANGED
|
@@ -22,16 +22,24 @@ module Bybit
|
|
|
22
22
|
|
|
23
23
|
# Raised when the server returns HTTP 200 + retCode != 0 (the V5 norm),
|
|
24
24
|
# or when a transport-level error is enriched with a Bybit body payload.
|
|
25
|
+
# Accepts either a V5 response Hash (extracts retCode/retMsg/result/time)
|
|
26
|
+
# or a plain String message (used for HTTP-status mapping when the CDN/WAF
|
|
27
|
+
# returns a non-JSON body — e.g. 401/403/429 → AuthError/RateLimitError
|
|
28
|
+
# without a decodable retCode).
|
|
25
29
|
class ApiError < Error
|
|
26
30
|
attr_reader :ret_code, :ret_msg, :result, :time, :http_status
|
|
27
31
|
|
|
28
32
|
def initialize(response, http_status: nil)
|
|
29
|
-
@ret_code = response['retCode']
|
|
30
|
-
@ret_msg = response['retMsg']
|
|
31
|
-
@result = response['result']
|
|
32
|
-
@time = response['time']
|
|
33
33
|
@http_status = http_status
|
|
34
|
-
|
|
34
|
+
if response.is_a?(Hash)
|
|
35
|
+
@ret_code = response['retCode']
|
|
36
|
+
@ret_msg = response['retMsg']
|
|
37
|
+
@result = response['result']
|
|
38
|
+
@time = response['time']
|
|
39
|
+
super("[#{@ret_code}] #{@ret_msg}")
|
|
40
|
+
else
|
|
41
|
+
super(response.to_s)
|
|
42
|
+
end
|
|
35
43
|
end
|
|
36
44
|
end
|
|
37
45
|
|