honeymaker 0.6.0 → 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/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/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
|
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/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
|