honeymaker 0.5.1 → 0.7.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 +4 -4
- data/lib/honeymaker/clients/binance.rb +26 -0
- data/lib/honeymaker/clients/bingx.rb +4 -0
- data/lib/honeymaker/clients/bitmart.rb +8 -0
- data/lib/honeymaker/clients/bitrue.rb +11 -0
- data/lib/honeymaker/clients/gemini.rb +8 -0
- data/lib/honeymaker/clients/hyperliquid.rb +46 -0
- data/lib/honeymaker/clients/kucoin.rb +4 -0
- data/lib/honeymaker/exchange.rb +43 -0
- data/lib/honeymaker/exchanges/binance.rb +13 -0
- data/lib/honeymaker/exchanges/bingx.rb +14 -0
- data/lib/honeymaker/exchanges/bitget.rb +14 -0
- data/lib/honeymaker/exchanges/bitmart.rb +14 -0
- data/lib/honeymaker/exchanges/bitrue.rb +13 -0
- data/lib/honeymaker/exchanges/bitvavo.rb +13 -0
- data/lib/honeymaker/exchanges/bybit.rb +14 -0
- data/lib/honeymaker/exchanges/coinbase.rb +11 -0
- data/lib/honeymaker/exchanges/gemini.rb +11 -0
- data/lib/honeymaker/exchanges/hyperliquid.rb +14 -0
- data/lib/honeymaker/exchanges/kraken.rb +17 -0
- data/lib/honeymaker/exchanges/kucoin.rb +14 -0
- data/lib/honeymaker/exchanges/mexc.rb +13 -0
- data/lib/honeymaker/result.rb +12 -0
- data/lib/honeymaker/version.rb +1 -1
- data/test/fixtures/binance_book_ticker.json +7 -0
- data/test/fixtures/bingx_ticker.json +12 -0
- data/test/fixtures/bitget_tickers.json +14 -0
- data/test/fixtures/bitmart_ticker.json +12 -0
- data/test/fixtures/bitrue_book_ticker.json +7 -0
- data/test/fixtures/bitvavo_book_ticker.json +7 -0
- data/test/fixtures/bybit_tickers.json +19 -0
- data/test/fixtures/coinbase_product.json +7 -0
- data/test/fixtures/gemini_pubticker.json +10 -0
- data/test/fixtures/hyperliquid_all_mids.json +5 -0
- data/test/fixtures/kraken_ticker.json +16 -0
- data/test/fixtures/kucoin_orderbook_level1.json +10 -0
- data/test/fixtures/mexc_book_ticker.json +7 -0
- data/test/honeymaker/exchange_test.rb +97 -0
- data/test/honeymaker/exchanges/binance_test.rb +21 -0
- data/test/honeymaker/exchanges/binance_us_test.rb +11 -0
- data/test/honeymaker/exchanges/bingx_test.rb +11 -0
- data/test/honeymaker/exchanges/bitget_test.rb +11 -0
- data/test/honeymaker/exchanges/bitmart_test.rb +11 -0
- data/test/honeymaker/exchanges/bitrue_test.rb +11 -0
- data/test/honeymaker/exchanges/bitvavo_test.rb +11 -0
- data/test/honeymaker/exchanges/bybit_test.rb +11 -0
- data/test/honeymaker/exchanges/coinbase_test.rb +11 -0
- data/test/honeymaker/exchanges/gemini_test.rb +11 -0
- data/test/honeymaker/exchanges/hyperliquid_test.rb +11 -0
- data/test/honeymaker/exchanges/kraken_test.rb +20 -0
- data/test/honeymaker/exchanges/kucoin_test.rb +11 -0
- data/test/honeymaker/exchanges/mexc_test.rb +11 -0
- metadata +14 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b5111180bb98ceb8eae9aad595851e28a45a10d908f780f2e69325df702b29aa
|
|
4
|
+
data.tar.gz: e1aea0e0de8989a11f19a7a3fb5cab7d64a9b4944efb86bac69d7ecafb0e6096
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c0df0bf1c364389aac57e683a6ff74aa1b5282c9ad95b63379901d291d0a5c5f22e11878a87c9f231047d858062fce1038326be2c5c4472296f146fef111122f
|
|
7
|
+
data.tar.gz: d7f22d0e9f0d7af33eaa0d5e82633b6a01caf01d83246558af40befa365df99d59db9d33fd9cd4c8ddccc56ba70b6ec54a1188507bd6c75171873b726c464ac3
|
|
@@ -168,6 +168,32 @@ module Honeymaker
|
|
|
168
168
|
end
|
|
169
169
|
end
|
|
170
170
|
|
|
171
|
+
def test_new_order(symbol:, side:, type:, time_in_force: nil, quantity: nil, quote_order_qty: nil,
|
|
172
|
+
price: nil, new_client_order_id: nil, strategy_id: nil, strategy_type: nil,
|
|
173
|
+
stop_price: nil, trailing_delta: nil, iceberg_qty: nil, new_order_resp_type: nil,
|
|
174
|
+
self_trade_prevention_mode: nil, recv_window: 5000, compute_commission_rates: false)
|
|
175
|
+
with_rescue do
|
|
176
|
+
response = connection.post do |req|
|
|
177
|
+
req.url "/api/v3/order/test"
|
|
178
|
+
req.headers = headers
|
|
179
|
+
req.params = {
|
|
180
|
+
symbol: symbol, side: side, type: type,
|
|
181
|
+
timeInForce: time_in_force, quantity: quantity,
|
|
182
|
+
quoteOrderQty: quote_order_qty, price: price,
|
|
183
|
+
newClientOrderId: new_client_order_id,
|
|
184
|
+
strategyId: strategy_id, strategyType: strategy_type,
|
|
185
|
+
stopPrice: stop_price, trailingDelta: trailing_delta,
|
|
186
|
+
icebergQty: iceberg_qty, newOrderRespType: new_order_resp_type,
|
|
187
|
+
selfTradePreventionMode: self_trade_prevention_mode,
|
|
188
|
+
computeCommissionRates: compute_commission_rates,
|
|
189
|
+
recvWindow: recv_window, timestamp: timestamp_ms
|
|
190
|
+
}.compact
|
|
191
|
+
req.params[:signature] = sign_params(req.params)
|
|
192
|
+
end
|
|
193
|
+
response.body
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
171
197
|
def cancel_order(symbol:, order_id: nil, orig_client_order_id: nil, new_client_order_id: nil,
|
|
172
198
|
cancel_restrictions: nil, recv_window: 5000)
|
|
173
199
|
with_rescue do
|
|
@@ -77,6 +77,10 @@ module Honeymaker
|
|
|
77
77
|
})
|
|
78
78
|
end
|
|
79
79
|
|
|
80
|
+
def get_all_coins_info
|
|
81
|
+
get_signed("/openApi/wallets/v1/capital/config/getall")
|
|
82
|
+
end
|
|
83
|
+
|
|
80
84
|
def get_trade_fills(symbol: nil, order_id: nil, start_time: nil, end_time: nil, from_id: nil, limit: nil)
|
|
81
85
|
get_signed("/openApi/spot/v1/trade/fills", {
|
|
82
86
|
symbol: symbol, orderId: order_id,
|
|
@@ -17,6 +17,10 @@ module Honeymaker
|
|
|
17
17
|
get_public("/spot/v1/symbols/details")
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
+
def get_currencies
|
|
21
|
+
get_public("/account/v1/currencies")
|
|
22
|
+
end
|
|
23
|
+
|
|
20
24
|
def get_ticker(symbol: nil)
|
|
21
25
|
get_public("/spot/quotation/v3/ticker", { symbol: symbol })
|
|
22
26
|
end
|
|
@@ -102,6 +106,10 @@ module Honeymaker
|
|
|
102
106
|
})
|
|
103
107
|
end
|
|
104
108
|
|
|
109
|
+
def get_withdraw_addresses
|
|
110
|
+
get_signed("/account/v1/withdraw/address/list")
|
|
111
|
+
end
|
|
112
|
+
|
|
105
113
|
def withdraw(currency:, amount:, address:, address_memo: nil, destination: nil)
|
|
106
114
|
post_signed("/account/v1/withdraw/apply", {
|
|
107
115
|
currency: currency, amount: amount,
|
|
@@ -77,6 +77,17 @@ module Honeymaker
|
|
|
77
77
|
})
|
|
78
78
|
end
|
|
79
79
|
|
|
80
|
+
def get_all_coins_information(recv_window: 5000)
|
|
81
|
+
get_signed("/api/v1/capital/config/getall", { recvWindow: recv_window })
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def withdraw(coin:, address:, amount:, network: nil, address_tag: nil, recv_window: 5000)
|
|
85
|
+
post_signed("/api/v1/capital/withdraw/apply", {
|
|
86
|
+
coin: coin, address: address, amount: amount,
|
|
87
|
+
network: network, addressTag: address_tag, recvWindow: recv_window
|
|
88
|
+
})
|
|
89
|
+
end
|
|
90
|
+
|
|
80
91
|
def account_trade_list(symbol:, start_time: nil, end_time: nil, from_id: nil, limit: 500, recv_window: 5000)
|
|
81
92
|
get_signed("/api/v1/myTrades", {
|
|
82
93
|
symbol: symbol, startTime: start_time, endTime: end_time,
|
|
@@ -22,6 +22,14 @@ module Honeymaker
|
|
|
22
22
|
get_public("/v2/candles/#{symbol}/#{time_frame}")
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
def get_price_feed
|
|
26
|
+
get_public("/v1/pricefeed")
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def get_approved_addresses(network:)
|
|
30
|
+
post_signed("/v1/approvedAddresses/account/#{network}")
|
|
31
|
+
end
|
|
32
|
+
|
|
25
33
|
def get_raw_balances
|
|
26
34
|
post_signed("/v1/balances")
|
|
27
35
|
end
|
|
@@ -6,6 +6,10 @@ module Honeymaker
|
|
|
6
6
|
URL = "https://api.hyperliquid.xyz"
|
|
7
7
|
RATE_LIMITS = { default: 200, orders: 200 }.freeze
|
|
8
8
|
|
|
9
|
+
def initialize(api_key: nil, api_secret: nil, proxy: nil, logger: nil)
|
|
10
|
+
super
|
|
11
|
+
end
|
|
12
|
+
|
|
9
13
|
def spot_meta
|
|
10
14
|
post_info({ type: "spotMeta" })
|
|
11
15
|
end
|
|
@@ -18,6 +22,23 @@ module Honeymaker
|
|
|
18
22
|
post_info({ type: "spotClearinghouseState", user: user })
|
|
19
23
|
end
|
|
20
24
|
|
|
25
|
+
def all_mids
|
|
26
|
+
post_info({ type: "allMids" })
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def spot_balances(user: nil)
|
|
30
|
+
user ||= @api_key
|
|
31
|
+
spot_clearinghouse_state(user: user)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def l2_book(coin:)
|
|
35
|
+
post_info({ type: "l2Book", coin: coin })
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def candles_snapshot(coin:, interval:, start_time:, end_time:)
|
|
39
|
+
post_info({ type: "candleSnapshot", req: { coin: coin, interval: interval, startTime: start_time, endTime: end_time } })
|
|
40
|
+
end
|
|
41
|
+
|
|
21
42
|
def get_balances(user: nil)
|
|
22
43
|
user ||= @api_key
|
|
23
44
|
result = spot_clearinghouse_state(user: user)
|
|
@@ -82,6 +103,20 @@ module Honeymaker
|
|
|
82
103
|
post_info(body)
|
|
83
104
|
end
|
|
84
105
|
|
|
106
|
+
# --- Trading (requires hyperliquid gem) ---
|
|
107
|
+
|
|
108
|
+
def order(coin:, is_buy:, size:, limit_px:, order_type: { limit: { tif: "Gtc" } })
|
|
109
|
+
with_rescue do
|
|
110
|
+
exchange_client.order(coin: coin, is_buy: is_buy, size: size, limit_px: limit_px, order_type: order_type)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def cancel(coin:, oid:)
|
|
115
|
+
with_rescue do
|
|
116
|
+
exchange_client.cancel(coin: coin, oid: oid)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
85
120
|
# --- Futures ---
|
|
86
121
|
|
|
87
122
|
def user_funding(user:, start_time:, end_time: nil)
|
|
@@ -118,6 +153,17 @@ module Honeymaker
|
|
|
118
153
|
validate_trading_credentials
|
|
119
154
|
end
|
|
120
155
|
|
|
156
|
+
def exchange_client
|
|
157
|
+
raise Error, "Trading requires api_secret (agent key)" unless @api_secret && !@api_secret.empty?
|
|
158
|
+
@exchange ||= begin
|
|
159
|
+
require "hyperliquid"
|
|
160
|
+
sdk = ::Hyperliquid.new(private_key: @api_secret)
|
|
161
|
+
sdk.exchange
|
|
162
|
+
rescue LoadError
|
|
163
|
+
raise Error, "Add 'hyperliquid' to your Gemfile to use Hyperliquid trading"
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
121
167
|
def post_info(body)
|
|
122
168
|
with_rescue do
|
|
123
169
|
response = connection.post do |req|
|
|
@@ -82,6 +82,10 @@ module Honeymaker
|
|
|
82
82
|
delete_signed("/api/v1/orders/#{order_id}")
|
|
83
83
|
end
|
|
84
84
|
|
|
85
|
+
def get_orderbook(symbol:, limit: 20)
|
|
86
|
+
get_public("/api/v1/market/orderbook/level2_#{limit}", { symbol: symbol })
|
|
87
|
+
end
|
|
88
|
+
|
|
85
89
|
def get_currencies
|
|
86
90
|
get_public("/api/v3/currencies")
|
|
87
91
|
end
|
data/lib/honeymaker/exchange.rb
CHANGED
|
@@ -14,6 +14,49 @@ module Honeymaker
|
|
|
14
14
|
raise NotImplementedError, "#{self.class} must implement #get_tickers_info"
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
+
def get_bid_ask(symbol)
|
|
18
|
+
raise NotImplementedError, "#{self.class} must implement #get_bid_ask"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def get_price(symbol)
|
|
22
|
+
result = get_bid_ask(symbol)
|
|
23
|
+
return result if result.failure?
|
|
24
|
+
|
|
25
|
+
Result::Success.new((result.data[:bid] + result.data[:ask]) / 2)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def tickers_info
|
|
29
|
+
if @tickers_info_cache && @tickers_info_expires_at && @tickers_info_expires_at > Time.now
|
|
30
|
+
return Result::Success.new(@tickers_info_cache)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
result = get_tickers_info
|
|
34
|
+
if result.success?
|
|
35
|
+
@tickers_info_cache = result.data
|
|
36
|
+
@tickers_info_expires_at = Time.now + cache_ttl
|
|
37
|
+
end
|
|
38
|
+
result
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def find_ticker(symbol)
|
|
42
|
+
result = tickers_info
|
|
43
|
+
return result if result.failure?
|
|
44
|
+
|
|
45
|
+
ticker = result.data.find { |t| t[:ticker] == symbol }
|
|
46
|
+
ticker ? Result::Success.new(ticker) : Result::Failure.new("Unknown symbol: #{symbol}")
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def symbols
|
|
50
|
+
result = tickers_info
|
|
51
|
+
return result if result.failure?
|
|
52
|
+
|
|
53
|
+
Result::Success.new(result.data.map { |t| { base: t[:base], quote: t[:quote] } })
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def cache_ttl
|
|
57
|
+
3600
|
|
58
|
+
end
|
|
59
|
+
|
|
17
60
|
private
|
|
18
61
|
|
|
19
62
|
def with_rescue
|
|
@@ -31,6 +31,19 @@ module Honeymaker
|
|
|
31
31
|
end
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
+
def get_bid_ask(symbol)
|
|
35
|
+
with_rescue do
|
|
36
|
+
response = connection.get("/api/v3/ticker/bookTicker") do |req|
|
|
37
|
+
req.params = { symbol: symbol }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
{
|
|
41
|
+
bid: BigDecimal(response.body["bidPrice"]),
|
|
42
|
+
ask: BigDecimal(response.body["askPrice"])
|
|
43
|
+
}
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
34
47
|
private
|
|
35
48
|
|
|
36
49
|
def connection
|
|
@@ -31,6 +31,20 @@ module Honeymaker
|
|
|
31
31
|
end
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
+
def get_bid_ask(symbol)
|
|
35
|
+
with_rescue do
|
|
36
|
+
response = connection.get("/openApi/spot/v2/market/ticker") do |req|
|
|
37
|
+
req.params = { symbol: symbol }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
data = response.body["data"].first
|
|
41
|
+
{
|
|
42
|
+
bid: BigDecimal(data["bestBidPrice"]),
|
|
43
|
+
ask: BigDecimal(data["bestAskPrice"])
|
|
44
|
+
}
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
34
48
|
private
|
|
35
49
|
|
|
36
50
|
def connection
|
|
@@ -27,6 +27,20 @@ module Honeymaker
|
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
+
def get_bid_ask(symbol)
|
|
31
|
+
with_rescue do
|
|
32
|
+
response = connection.get("/api/v2/spot/market/tickers") do |req|
|
|
33
|
+
req.params = { symbol: symbol }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
ticker = response.body["data"].first
|
|
37
|
+
{
|
|
38
|
+
bid: BigDecimal(ticker["bestBid"]),
|
|
39
|
+
ask: BigDecimal(ticker["bestAsk"])
|
|
40
|
+
}
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
30
44
|
private
|
|
31
45
|
|
|
32
46
|
def connection
|
|
@@ -27,6 +27,20 @@ module Honeymaker
|
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
+
def get_bid_ask(symbol)
|
|
31
|
+
with_rescue do
|
|
32
|
+
response = connection.get("/spot/quotation/v3/ticker") do |req|
|
|
33
|
+
req.params = { symbol: symbol }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
data = response.body["data"]
|
|
37
|
+
{
|
|
38
|
+
bid: BigDecimal(data["best_bid"]),
|
|
39
|
+
ask: BigDecimal(data["best_ask"])
|
|
40
|
+
}
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
30
44
|
private
|
|
31
45
|
|
|
32
46
|
def connection
|
|
@@ -29,6 +29,19 @@ module Honeymaker
|
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
+
def get_bid_ask(symbol)
|
|
33
|
+
with_rescue do
|
|
34
|
+
response = connection.get("/api/v1/ticker/bookTicker") do |req|
|
|
35
|
+
req.params = { symbol: symbol }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
{
|
|
39
|
+
bid: BigDecimal(response.body["bidPrice"]),
|
|
40
|
+
ask: BigDecimal(response.body["askPrice"])
|
|
41
|
+
}
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
32
45
|
private
|
|
33
46
|
|
|
34
47
|
def connection
|
|
@@ -30,6 +30,19 @@ module Honeymaker
|
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
+
def get_bid_ask(symbol)
|
|
34
|
+
with_rescue do
|
|
35
|
+
response = connection.get("/v2/ticker/book") do |req|
|
|
36
|
+
req.params = { market: symbol }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
{
|
|
40
|
+
bid: BigDecimal(response.body["bid"]),
|
|
41
|
+
ask: BigDecimal(response.body["ask"])
|
|
42
|
+
}
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
33
46
|
private
|
|
34
47
|
|
|
35
48
|
def connection
|
|
@@ -32,6 +32,20 @@ module Honeymaker
|
|
|
32
32
|
end
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
+
def get_bid_ask(symbol)
|
|
36
|
+
with_rescue do
|
|
37
|
+
response = connection.get("/v5/market/tickers") do |req|
|
|
38
|
+
req.params = { category: "spot", symbol: symbol }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
ticker = response.body["result"]["list"].first
|
|
42
|
+
{
|
|
43
|
+
bid: BigDecimal(ticker["bid1Price"]),
|
|
44
|
+
ask: BigDecimal(ticker["ask1Price"])
|
|
45
|
+
}
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
35
49
|
private
|
|
36
50
|
|
|
37
51
|
def connection
|
|
@@ -37,6 +37,17 @@ module Honeymaker
|
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
+
def get_bid_ask(symbol)
|
|
41
|
+
with_rescue do
|
|
42
|
+
response = connection.get("/api/v3/brokerage/market/products/#{symbol}")
|
|
43
|
+
|
|
44
|
+
{
|
|
45
|
+
bid: BigDecimal(response.body["bid"]),
|
|
46
|
+
ask: BigDecimal(response.body["ask"])
|
|
47
|
+
}
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
40
51
|
private
|
|
41
52
|
|
|
42
53
|
def connection
|
|
@@ -33,6 +33,17 @@ module Honeymaker
|
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
+
def get_bid_ask(symbol)
|
|
37
|
+
with_rescue do
|
|
38
|
+
response = connection.get("/v1/pubticker/#{symbol.downcase}")
|
|
39
|
+
|
|
40
|
+
{
|
|
41
|
+
bid: BigDecimal(response.body["bid"]),
|
|
42
|
+
ask: BigDecimal(response.body["ask"])
|
|
43
|
+
}
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
36
47
|
private
|
|
37
48
|
|
|
38
49
|
def connection
|
|
@@ -37,6 +37,20 @@ module Honeymaker
|
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
+
def get_bid_ask(symbol)
|
|
41
|
+
with_rescue do
|
|
42
|
+
response = connection.post("/info") do |req|
|
|
43
|
+
req.body = { type: "allMids" }.to_json
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
price = BigDecimal(response.body[symbol])
|
|
47
|
+
{
|
|
48
|
+
bid: price,
|
|
49
|
+
ask: price
|
|
50
|
+
}
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
40
54
|
private
|
|
41
55
|
|
|
42
56
|
def connection
|
|
@@ -58,6 +58,23 @@ module Honeymaker
|
|
|
58
58
|
end
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
+
def get_bid_ask(symbol)
|
|
62
|
+
with_rescue do
|
|
63
|
+
response = connection.get("/0/public/Ticker") do |req|
|
|
64
|
+
req.params = { pair: symbol }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
error = response.body["error"]
|
|
68
|
+
raise StandardError, error.first if error.is_a?(Array) && error.any?
|
|
69
|
+
|
|
70
|
+
_key, data = response.body["result"].first
|
|
71
|
+
{
|
|
72
|
+
bid: BigDecimal(data["b"][0]),
|
|
73
|
+
ask: BigDecimal(data["a"][0])
|
|
74
|
+
}
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
61
78
|
private
|
|
62
79
|
|
|
63
80
|
def connection
|
|
@@ -27,6 +27,20 @@ module Honeymaker
|
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
+
def get_bid_ask(symbol)
|
|
31
|
+
with_rescue do
|
|
32
|
+
response = connection.get("/api/v1/market/orderbook/level1") do |req|
|
|
33
|
+
req.params = { symbol: symbol }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
data = response.body["data"]
|
|
37
|
+
{
|
|
38
|
+
bid: BigDecimal(data["bestBid"]),
|
|
39
|
+
ask: BigDecimal(data["bestAsk"])
|
|
40
|
+
}
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
30
44
|
private
|
|
31
45
|
|
|
32
46
|
def connection
|
|
@@ -29,6 +29,19 @@ module Honeymaker
|
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
+
def get_bid_ask(symbol)
|
|
33
|
+
with_rescue do
|
|
34
|
+
response = connection.get("/api/v3/ticker/bookTicker") do |req|
|
|
35
|
+
req.params = { symbol: symbol }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
{
|
|
39
|
+
bid: BigDecimal(response.body["bidPrice"]),
|
|
40
|
+
ask: BigDecimal(response.body["askPrice"])
|
|
41
|
+
}
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
32
45
|
private
|
|
33
46
|
|
|
34
47
|
def connection
|
data/lib/honeymaker/result.rb
CHANGED
|
@@ -17,6 +17,18 @@ module Honeymaker
|
|
|
17
17
|
!success?
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
+
def or(other)
|
|
21
|
+
return data if success?
|
|
22
|
+
|
|
23
|
+
other
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def ==(other)
|
|
27
|
+
return false unless other.is_a?(Result)
|
|
28
|
+
|
|
29
|
+
data == other.data && errors == other.errors
|
|
30
|
+
end
|
|
31
|
+
|
|
20
32
|
class Success < Result
|
|
21
33
|
def initialize(data = nil)
|
|
22
34
|
@data = data
|
data/lib/honeymaker/version.rb
CHANGED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"retCode": 0,
|
|
3
|
+
"retMsg": "OK",
|
|
4
|
+
"result": {
|
|
5
|
+
"category": "spot",
|
|
6
|
+
"list": [
|
|
7
|
+
{
|
|
8
|
+
"symbol": "BTCUSDT",
|
|
9
|
+
"bid1Price": "67123.45",
|
|
10
|
+
"bid1Size": "1.234567",
|
|
11
|
+
"ask1Price": "67125.67",
|
|
12
|
+
"ask1Size": "0.987654",
|
|
13
|
+
"lastPrice": "67124.56",
|
|
14
|
+
"highPrice24h": "67500.00",
|
|
15
|
+
"lowPrice24h": "66800.00"
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"error": [],
|
|
3
|
+
"result": {
|
|
4
|
+
"XBTUSDT": {
|
|
5
|
+
"a": ["67125.67000", "1", "1.000"],
|
|
6
|
+
"b": ["67123.45000", "2", "2.000"],
|
|
7
|
+
"c": ["67124.50000", "0.00100000"],
|
|
8
|
+
"v": ["1234.56789012", "5678.90123456"],
|
|
9
|
+
"p": ["67100.00000", "67050.00000"],
|
|
10
|
+
"t": [12345, 67890],
|
|
11
|
+
"l": ["66800.00000", "66500.00000"],
|
|
12
|
+
"h": ["67500.00000", "67800.00000"],
|
|
13
|
+
"o": "67000.00000"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -28,4 +28,101 @@ class Honeymaker::ExchangeTest < Minitest::Test
|
|
|
28
28
|
assert result.success?
|
|
29
29
|
assert_equal [1, 2, 3], result.data
|
|
30
30
|
end
|
|
31
|
+
|
|
32
|
+
def test_get_bid_ask_raises_not_implemented
|
|
33
|
+
exchange = Honeymaker::Exchange.new
|
|
34
|
+
assert_raises(NotImplementedError) { exchange.get_bid_ask("BTCUSDT") }
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def test_get_price_returns_midpoint
|
|
38
|
+
exchange = Honeymaker::Exchange.new
|
|
39
|
+
bid_ask = { bid: BigDecimal("100"), ask: BigDecimal("102") }
|
|
40
|
+
exchange.define_singleton_method(:get_bid_ask) { |_| Honeymaker::Result::Success.new(bid_ask) }
|
|
41
|
+
|
|
42
|
+
result = exchange.get_price("BTCUSDT")
|
|
43
|
+
assert result.success?
|
|
44
|
+
assert_equal BigDecimal("101"), result.data
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def test_get_price_propagates_failure
|
|
48
|
+
exchange = Honeymaker::Exchange.new
|
|
49
|
+
exchange.define_singleton_method(:get_bid_ask) { |_| Honeymaker::Result::Failure.new("error") }
|
|
50
|
+
|
|
51
|
+
result = exchange.get_price("BTCUSDT")
|
|
52
|
+
assert result.failure?
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def test_tickers_info_caches_result
|
|
56
|
+
exchange = Honeymaker::Exchange.new
|
|
57
|
+
tickers = [{ ticker: "BTCUSDT", base: "BTC", quote: "USDT" }]
|
|
58
|
+
call_count = 0
|
|
59
|
+
exchange.define_singleton_method(:get_tickers_info) do
|
|
60
|
+
call_count += 1
|
|
61
|
+
Honeymaker::Result::Success.new(tickers)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
result1 = exchange.tickers_info
|
|
65
|
+
result2 = exchange.tickers_info
|
|
66
|
+
assert result1.success?
|
|
67
|
+
assert result2.success?
|
|
68
|
+
assert_equal 1, call_count
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def test_tickers_info_does_not_cache_failure
|
|
72
|
+
exchange = Honeymaker::Exchange.new
|
|
73
|
+
call_count = 0
|
|
74
|
+
exchange.define_singleton_method(:get_tickers_info) do
|
|
75
|
+
call_count += 1
|
|
76
|
+
Honeymaker::Result::Failure.new("error")
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
exchange.tickers_info
|
|
80
|
+
exchange.tickers_info
|
|
81
|
+
assert_equal 2, call_count
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def test_find_ticker_returns_matching_ticker
|
|
85
|
+
exchange = Honeymaker::Exchange.new
|
|
86
|
+
tickers = [
|
|
87
|
+
{ ticker: "BTCUSDT", base: "BTC", quote: "USDT" },
|
|
88
|
+
{ ticker: "ETHUSDT", base: "ETH", quote: "USDT" }
|
|
89
|
+
]
|
|
90
|
+
exchange.define_singleton_method(:get_tickers_info) do
|
|
91
|
+
Honeymaker::Result::Success.new(tickers)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
result = exchange.find_ticker("ETHUSDT")
|
|
95
|
+
assert result.success?
|
|
96
|
+
assert_equal "ETH", result.data[:base]
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def test_find_ticker_returns_failure_for_unknown_symbol
|
|
100
|
+
exchange = Honeymaker::Exchange.new
|
|
101
|
+
exchange.define_singleton_method(:get_tickers_info) do
|
|
102
|
+
Honeymaker::Result::Success.new([{ ticker: "BTCUSDT" }])
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
result = exchange.find_ticker("NOPE")
|
|
106
|
+
assert result.failure?
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def test_symbols_returns_base_quote_pairs
|
|
110
|
+
exchange = Honeymaker::Exchange.new
|
|
111
|
+
tickers = [
|
|
112
|
+
{ ticker: "BTCUSDT", base: "BTC", quote: "USDT" },
|
|
113
|
+
{ ticker: "ETHUSDT", base: "ETH", quote: "USDT" }
|
|
114
|
+
]
|
|
115
|
+
exchange.define_singleton_method(:get_tickers_info) do
|
|
116
|
+
Honeymaker::Result::Success.new(tickers)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
result = exchange.symbols
|
|
120
|
+
assert result.success?
|
|
121
|
+
assert_equal [{ base: "BTC", quote: "USDT" }, { base: "ETH", quote: "USDT" }], result.data
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def test_cache_ttl_defaults_to_3600
|
|
125
|
+
exchange = Honeymaker::Exchange.new
|
|
126
|
+
assert_equal 3600, exchange.cache_ttl
|
|
127
|
+
end
|
|
31
128
|
end
|
|
@@ -38,6 +38,27 @@ class Honeymaker::Exchanges::BinanceTest < Minitest::Test
|
|
|
38
38
|
assert result.failure?
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
+
def test_get_bid_ask_parses_response
|
|
42
|
+
body = load_fixture("binance_book_ticker.json")
|
|
43
|
+
stub_connection(body)
|
|
44
|
+
|
|
45
|
+
result = @exchange.get_bid_ask("BTCUSDT")
|
|
46
|
+
|
|
47
|
+
assert result.success?
|
|
48
|
+
assert_equal BigDecimal("67123.45"), result.data[:bid]
|
|
49
|
+
assert_equal BigDecimal("67125.67"), result.data[:ask]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def test_get_bid_ask_handles_api_error
|
|
53
|
+
connection = stub
|
|
54
|
+
connection.stubs(:get).raises(Faraday::ServerError.new("500", { status: 500, body: "Internal Server Error" }))
|
|
55
|
+
@exchange.instance_variable_set(:@connection, connection)
|
|
56
|
+
|
|
57
|
+
result = @exchange.get_bid_ask("BTCUSDT")
|
|
58
|
+
|
|
59
|
+
assert result.failure?
|
|
60
|
+
end
|
|
61
|
+
|
|
41
62
|
private
|
|
42
63
|
|
|
43
64
|
def stub_connection(body)
|
|
@@ -29,6 +29,17 @@ class Honeymaker::Exchanges::BinanceUsTest < Minitest::Test
|
|
|
29
29
|
assert_equal "BTC", ticker[:base]
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
+
def test_get_bid_ask_parses_response
|
|
33
|
+
body = load_fixture("binance_book_ticker.json")
|
|
34
|
+
stub_connection(body)
|
|
35
|
+
|
|
36
|
+
result = @exchange.get_bid_ask("BTCUSDT")
|
|
37
|
+
|
|
38
|
+
assert result.success?
|
|
39
|
+
assert_equal BigDecimal("67123.45"), result.data[:bid]
|
|
40
|
+
assert_equal BigDecimal("67125.67"), result.data[:ask]
|
|
41
|
+
end
|
|
42
|
+
|
|
32
43
|
private
|
|
33
44
|
|
|
34
45
|
def stub_connection(body)
|
|
@@ -42,6 +42,17 @@ class Honeymaker::Exchanges::BingXTest < Minitest::Test
|
|
|
42
42
|
refute_includes tickers, "INVALID"
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
+
def test_get_bid_ask_parses_response
|
|
46
|
+
body = load_fixture("bingx_ticker.json")
|
|
47
|
+
stub_connection(body)
|
|
48
|
+
|
|
49
|
+
result = @exchange.get_bid_ask("BTC-USDT")
|
|
50
|
+
|
|
51
|
+
assert result.success?
|
|
52
|
+
assert_equal BigDecimal("67123.45"), result.data[:bid]
|
|
53
|
+
assert_equal BigDecimal("67125.67"), result.data[:ask]
|
|
54
|
+
end
|
|
55
|
+
|
|
45
56
|
private
|
|
46
57
|
|
|
47
58
|
def stub_connection(body)
|
|
@@ -41,6 +41,17 @@ class Honeymaker::Exchanges::BitgetTest < Minitest::Test
|
|
|
41
41
|
refute eth[:available]
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
+
def test_get_bid_ask_parses_response
|
|
45
|
+
body = load_fixture("bitget_tickers.json")
|
|
46
|
+
stub_connection(body)
|
|
47
|
+
|
|
48
|
+
result = @exchange.get_bid_ask("BTCUSDT")
|
|
49
|
+
|
|
50
|
+
assert result.success?
|
|
51
|
+
assert_equal BigDecimal("67123.45"), result.data[:bid]
|
|
52
|
+
assert_equal BigDecimal("67125.67"), result.data[:ask]
|
|
53
|
+
end
|
|
54
|
+
|
|
44
55
|
private
|
|
45
56
|
|
|
46
57
|
def stub_connection(body)
|
|
@@ -41,6 +41,17 @@ class Honeymaker::Exchanges::BitMartTest < Minitest::Test
|
|
|
41
41
|
refute eth[:available]
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
+
def test_get_bid_ask_parses_response
|
|
45
|
+
body = load_fixture("bitmart_ticker.json")
|
|
46
|
+
stub_connection(body)
|
|
47
|
+
|
|
48
|
+
result = @exchange.get_bid_ask("BTC_USDT")
|
|
49
|
+
|
|
50
|
+
assert result.success?
|
|
51
|
+
assert_equal BigDecimal("67123.45"), result.data[:bid]
|
|
52
|
+
assert_equal BigDecimal("67125.67"), result.data[:ask]
|
|
53
|
+
end
|
|
54
|
+
|
|
44
55
|
private
|
|
45
56
|
|
|
46
57
|
def stub_connection(body)
|
|
@@ -42,6 +42,17 @@ class Honeymaker::Exchanges::BitrueTest < Minitest::Test
|
|
|
42
42
|
assert_equal 2, eth[:price_decimals]
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
+
def test_get_bid_ask_parses_response
|
|
46
|
+
body = load_fixture("bitrue_book_ticker.json")
|
|
47
|
+
stub_connection(body)
|
|
48
|
+
|
|
49
|
+
result = @exchange.get_bid_ask("BTCUSDT")
|
|
50
|
+
|
|
51
|
+
assert result.success?
|
|
52
|
+
assert_equal BigDecimal("67123.45"), result.data[:bid]
|
|
53
|
+
assert_equal BigDecimal("67125.67"), result.data[:ask]
|
|
54
|
+
end
|
|
55
|
+
|
|
45
56
|
private
|
|
46
57
|
|
|
47
58
|
def stub_connection(body)
|
|
@@ -41,6 +41,17 @@ class Honeymaker::Exchanges::BitvavoTest < Minitest::Test
|
|
|
41
41
|
refute eth[:available]
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
+
def test_get_bid_ask_parses_response
|
|
45
|
+
body = load_fixture("bitvavo_book_ticker.json")
|
|
46
|
+
stub_connection(body)
|
|
47
|
+
|
|
48
|
+
result = @exchange.get_bid_ask("BTC-EUR")
|
|
49
|
+
|
|
50
|
+
assert result.success?
|
|
51
|
+
assert_equal BigDecimal("67123.45"), result.data[:bid]
|
|
52
|
+
assert_equal BigDecimal("67125.67"), result.data[:ask]
|
|
53
|
+
end
|
|
54
|
+
|
|
44
55
|
private
|
|
45
56
|
|
|
46
57
|
def stub_connection(body)
|
|
@@ -32,6 +32,17 @@ class Honeymaker::Exchanges::BybitTest < Minitest::Test
|
|
|
32
32
|
assert ticker[:available]
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
+
def test_get_bid_ask_parses_response
|
|
36
|
+
body = load_fixture("bybit_tickers.json")
|
|
37
|
+
stub_connection(body)
|
|
38
|
+
|
|
39
|
+
result = @exchange.get_bid_ask("BTCUSDT")
|
|
40
|
+
|
|
41
|
+
assert result.success?
|
|
42
|
+
assert_equal BigDecimal("67123.45"), result.data[:bid]
|
|
43
|
+
assert_equal BigDecimal("67125.67"), result.data[:ask]
|
|
44
|
+
end
|
|
45
|
+
|
|
35
46
|
private
|
|
36
47
|
|
|
37
48
|
def stub_connection(body)
|
|
@@ -41,6 +41,17 @@ class Honeymaker::Exchanges::CoinbaseTest < Minitest::Test
|
|
|
41
41
|
refute_includes bases, "RENDER"
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
+
def test_get_bid_ask_parses_response
|
|
45
|
+
body = load_fixture("coinbase_product.json")
|
|
46
|
+
stub_connection(body)
|
|
47
|
+
|
|
48
|
+
result = @exchange.get_bid_ask("BTC-USD")
|
|
49
|
+
|
|
50
|
+
assert result.success?
|
|
51
|
+
assert_equal BigDecimal("67123.45"), result.data[:bid]
|
|
52
|
+
assert_equal BigDecimal("67125.67"), result.data[:ask]
|
|
53
|
+
end
|
|
54
|
+
|
|
44
55
|
private
|
|
45
56
|
|
|
46
57
|
def stub_connection(body)
|
|
@@ -37,6 +37,17 @@ class Honeymaker::Exchanges::GeminiTest < Minitest::Test
|
|
|
37
37
|
assert ticker[:available]
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
+
def test_get_bid_ask_parses_response
|
|
41
|
+
body = load_fixture("gemini_pubticker.json")
|
|
42
|
+
stub_connection(body)
|
|
43
|
+
|
|
44
|
+
result = @exchange.get_bid_ask("BTCUSD")
|
|
45
|
+
|
|
46
|
+
assert result.success?
|
|
47
|
+
assert_equal BigDecimal("67123.45"), result.data[:bid]
|
|
48
|
+
assert_equal BigDecimal("67125.67"), result.data[:ask]
|
|
49
|
+
end
|
|
50
|
+
|
|
40
51
|
private
|
|
41
52
|
|
|
42
53
|
def stub_connection(body)
|
|
@@ -41,6 +41,17 @@ class Honeymaker::Exchanges::HyperliquidTest < Minitest::Test
|
|
|
41
41
|
assert_equal 1, result.data.size
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
+
def test_get_bid_ask_parses_response
|
|
45
|
+
body = load_fixture("hyperliquid_all_mids.json")
|
|
46
|
+
stub_connection(body)
|
|
47
|
+
|
|
48
|
+
result = @exchange.get_bid_ask("BTC/USDC")
|
|
49
|
+
|
|
50
|
+
assert result.success?
|
|
51
|
+
assert_equal BigDecimal("67124.56"), result.data[:bid]
|
|
52
|
+
assert_equal BigDecimal("67124.56"), result.data[:ask]
|
|
53
|
+
end
|
|
54
|
+
|
|
44
55
|
private
|
|
45
56
|
|
|
46
57
|
def stub_connection(body)
|
|
@@ -60,6 +60,26 @@ class Honeymaker::Exchanges::KrakenTest < Minitest::Test
|
|
|
60
60
|
assert_includes result.errors, "EGeneral:Internal error"
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
+
def test_get_bid_ask_parses_response
|
|
64
|
+
body = load_fixture("kraken_ticker.json")
|
|
65
|
+
stub_request(body)
|
|
66
|
+
|
|
67
|
+
result = @exchange.get_bid_ask("XBTUSDT")
|
|
68
|
+
|
|
69
|
+
assert result.success?
|
|
70
|
+
assert_equal BigDecimal("67123.45"), result.data[:bid]
|
|
71
|
+
assert_equal BigDecimal("67125.67"), result.data[:ask]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def test_get_bid_ask_handles_api_error
|
|
75
|
+
body = { "error" => ["EGeneral:Internal error"], "result" => {} }
|
|
76
|
+
stub_request(body)
|
|
77
|
+
|
|
78
|
+
result = @exchange.get_bid_ask("XBTUSDT")
|
|
79
|
+
|
|
80
|
+
assert result.failure?
|
|
81
|
+
end
|
|
82
|
+
|
|
63
83
|
private
|
|
64
84
|
|
|
65
85
|
def stub_request(body)
|
|
@@ -32,6 +32,17 @@ class Honeymaker::Exchanges::KucoinTest < Minitest::Test
|
|
|
32
32
|
assert ticker[:available]
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
+
def test_get_bid_ask_parses_response
|
|
36
|
+
body = load_fixture("kucoin_orderbook_level1.json")
|
|
37
|
+
stub_connection(body)
|
|
38
|
+
|
|
39
|
+
result = @exchange.get_bid_ask("BTC-USDT")
|
|
40
|
+
|
|
41
|
+
assert result.success?
|
|
42
|
+
assert_equal BigDecimal("67123.45"), result.data[:bid]
|
|
43
|
+
assert_equal BigDecimal("67125.67"), result.data[:ask]
|
|
44
|
+
end
|
|
45
|
+
|
|
35
46
|
private
|
|
36
47
|
|
|
37
48
|
def stub_connection(body)
|
|
@@ -53,6 +53,17 @@ class Honeymaker::Exchanges::MexcTest < Minitest::Test
|
|
|
53
53
|
assert_equal 2, eth[:price_decimals]
|
|
54
54
|
end
|
|
55
55
|
|
|
56
|
+
def test_get_bid_ask_parses_response
|
|
57
|
+
body = load_fixture("mexc_book_ticker.json")
|
|
58
|
+
stub_connection(body)
|
|
59
|
+
|
|
60
|
+
result = @exchange.get_bid_ask("BTCUSDT")
|
|
61
|
+
|
|
62
|
+
assert result.success?
|
|
63
|
+
assert_equal BigDecimal("67123.45"), result.data[:bid]
|
|
64
|
+
assert_equal BigDecimal("67125.67"), result.data[:ask]
|
|
65
|
+
end
|
|
66
|
+
|
|
56
67
|
private
|
|
57
68
|
|
|
58
69
|
def stub_connection(body)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: honeymaker
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Deltabadger
|
|
@@ -128,19 +128,32 @@ files:
|
|
|
128
128
|
- lib/honeymaker/utils.rb
|
|
129
129
|
- lib/honeymaker/version.rb
|
|
130
130
|
- sig/honeymaker.rbs
|
|
131
|
+
- test/fixtures/binance_book_ticker.json
|
|
131
132
|
- test/fixtures/binance_exchange_info.json
|
|
132
133
|
- test/fixtures/bingx_symbols.json
|
|
134
|
+
- test/fixtures/bingx_ticker.json
|
|
133
135
|
- test/fixtures/bitget_symbols.json
|
|
136
|
+
- test/fixtures/bitget_tickers.json
|
|
134
137
|
- test/fixtures/bitmart_symbols.json
|
|
138
|
+
- test/fixtures/bitmart_ticker.json
|
|
139
|
+
- test/fixtures/bitrue_book_ticker.json
|
|
135
140
|
- test/fixtures/bitrue_exchange_info.json
|
|
141
|
+
- test/fixtures/bitvavo_book_ticker.json
|
|
136
142
|
- test/fixtures/bitvavo_markets.json
|
|
137
143
|
- test/fixtures/bybit_instruments.json
|
|
144
|
+
- test/fixtures/bybit_tickers.json
|
|
145
|
+
- test/fixtures/coinbase_product.json
|
|
138
146
|
- test/fixtures/coinbase_products.json
|
|
147
|
+
- test/fixtures/gemini_pubticker.json
|
|
139
148
|
- test/fixtures/gemini_symbol_detail.json
|
|
140
149
|
- test/fixtures/gemini_symbols.json
|
|
150
|
+
- test/fixtures/hyperliquid_all_mids.json
|
|
141
151
|
- test/fixtures/hyperliquid_spot_meta.json
|
|
142
152
|
- test/fixtures/kraken_asset_pairs.json
|
|
153
|
+
- test/fixtures/kraken_ticker.json
|
|
154
|
+
- test/fixtures/kucoin_orderbook_level1.json
|
|
143
155
|
- test/fixtures/kucoin_symbols.json
|
|
156
|
+
- test/fixtures/mexc_book_ticker.json
|
|
144
157
|
- test/fixtures/mexc_exchange_info.json
|
|
145
158
|
- test/honeymaker/client_test.rb
|
|
146
159
|
- test/honeymaker/clients/binance_client_test.rb
|