honeymaker 0.8.0 → 0.9.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/Rakefile +22 -10
- data/lib/honeymaker/exchanges/binance.rb +2 -1
- data/lib/honeymaker/exchanges/bingx.rb +2 -1
- data/lib/honeymaker/exchanges/bitget.rb +2 -1
- data/lib/honeymaker/exchanges/bitmart.rb +2 -1
- data/lib/honeymaker/exchanges/bitrue.rb +2 -1
- data/lib/honeymaker/exchanges/bitvavo.rb +2 -1
- data/lib/honeymaker/exchanges/bybit.rb +2 -1
- data/lib/honeymaker/exchanges/coinbase.rb +11 -1
- data/lib/honeymaker/exchanges/gemini.rb +2 -1
- data/lib/honeymaker/exchanges/hyperliquid.rb +2 -1
- data/lib/honeymaker/exchanges/kraken.rb +2 -1
- data/lib/honeymaker/exchanges/kucoin.rb +2 -1
- data/lib/honeymaker/exchanges/mexc.rb +2 -1
- data/lib/honeymaker/version.rb +1 -1
- data/test/honeymaker/exchanges/binance_test.rb +13 -0
- data/test/honeymaker/exchanges/binance_us_test.rb +2 -0
- data/test/honeymaker/exchanges/bingx_test.rb +1 -0
- data/test/honeymaker/exchanges/bitget_test.rb +4 -2
- data/test/honeymaker/exchanges/bitmart_test.rb +4 -2
- data/test/honeymaker/exchanges/bitrue_test.rb +1 -0
- data/test/honeymaker/exchanges/bitvavo_test.rb +4 -2
- data/test/honeymaker/exchanges/bybit_test.rb +1 -0
- data/test/honeymaker/exchanges/coinbase_test.rb +23 -0
- data/test/honeymaker/exchanges/gemini_test.rb +1 -0
- data/test/honeymaker/exchanges/hyperliquid_test.rb +1 -0
- data/test/honeymaker/exchanges/kraken_test.rb +32 -0
- data/test/honeymaker/exchanges/kucoin_test.rb +1 -0
- data/test/honeymaker/exchanges/mexc_test.rb +4 -2
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 12080b0cbcae6a52a2680efde8f4131b30f4ebcf70647c1c297ac88217c459ba
|
|
4
|
+
data.tar.gz: c475a4e5da6e8f7ac2e0b5f3eaa84e12192eec504876871028935a6b3be05cae
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c6c9bffcfa55f7f096a4128c2b09119e06d11e5be58bc04dde162a693600595e7662334034d38a049b7faaa2f9535976668b22890564bf6ddcf82f8f1c1ade2e
|
|
7
|
+
data.tar.gz: eedbdfab0c9fa12e8b4ae86362eafcd90b4d8319caace49bdb642405ca99a90836af69a6c8a50d9a13e555f6f1be4008175fb7e019927d8198060d7835a3754c
|
data/Rakefile
CHANGED
|
@@ -29,26 +29,38 @@ def bump_version(segment)
|
|
|
29
29
|
puts "Bumped version to #{new_version}"
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
task
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
# Bundler's `release` task is defined when this Rakefile loads — it captures
|
|
33
|
+
# the gemspec version at that moment in `Bundler::GemHelper`. If we bump the
|
|
34
|
+
# version mid-run (as a build prerequisite), the gem is published correctly
|
|
35
|
+
# but the final "Pushed <gem> <ver>" log line still prints the old cached
|
|
36
|
+
# version. Fix: bump first, then invoke bundler's release in a subprocess so
|
|
37
|
+
# it re-reads the gemspec fresh.
|
|
38
|
+
|
|
39
|
+
Rake::Task[:release].clear
|
|
35
40
|
|
|
36
|
-
|
|
41
|
+
def do_release(segment)
|
|
42
|
+
bump_version(segment)
|
|
37
43
|
sh "bundle install"
|
|
38
44
|
Rake::Task[:test].invoke
|
|
39
|
-
sh
|
|
45
|
+
sh %(git add -A && git diff --cached --quiet || git commit -m "v#{current_version}")
|
|
46
|
+
sh "bundle exec rake _bundler_release"
|
|
40
47
|
end
|
|
41
48
|
|
|
42
|
-
|
|
49
|
+
task _bundler_release: %w[build release:guard_clean release:source_control_push release:rubygem_push]
|
|
50
|
+
|
|
51
|
+
desc "Bump patch, run tests, push to rubygems"
|
|
52
|
+
task :release do
|
|
53
|
+
do_release(:patch)
|
|
54
|
+
end
|
|
43
55
|
|
|
44
56
|
namespace :release do
|
|
57
|
+
desc "Bump minor, run tests, push to rubygems"
|
|
45
58
|
task :minor do
|
|
46
|
-
|
|
47
|
-
Rake::Task[:release].invoke
|
|
59
|
+
do_release(:minor)
|
|
48
60
|
end
|
|
49
61
|
|
|
62
|
+
desc "Bump major, run tests, push to rubygems"
|
|
50
63
|
task :major do
|
|
51
|
-
|
|
52
|
-
Rake::Task[:release].invoke
|
|
64
|
+
do_release(:major)
|
|
53
65
|
end
|
|
54
66
|
end
|
|
@@ -25,7 +25,8 @@ module Honeymaker
|
|
|
25
25
|
base_decimals: Utils.decimals(f[:lot_size]["stepSize"]),
|
|
26
26
|
quote_decimals: product["quoteAssetPrecision"],
|
|
27
27
|
price_decimals: Utils.decimals(f[:price]["tickSize"]),
|
|
28
|
-
available:
|
|
28
|
+
available: true,
|
|
29
|
+
trading_enabled: product["status"] == "TRADING"
|
|
29
30
|
}
|
|
30
31
|
end
|
|
31
32
|
end
|
|
@@ -25,7 +25,8 @@ module Honeymaker
|
|
|
25
25
|
base_decimals: Utils.decimals(product["stepSize"]),
|
|
26
26
|
quote_decimals: Utils.decimals(product["tickSize"]),
|
|
27
27
|
price_decimals: Utils.decimals(product["tickSize"]),
|
|
28
|
-
available:
|
|
28
|
+
available: true,
|
|
29
|
+
trading_enabled: product["status"].to_i == 1
|
|
29
30
|
}
|
|
30
31
|
end
|
|
31
32
|
end
|
|
@@ -21,7 +21,8 @@ module Honeymaker
|
|
|
21
21
|
base_decimals: product["quantityPrecision"].to_i,
|
|
22
22
|
quote_decimals: product["quotePrecision"].to_i,
|
|
23
23
|
price_decimals: product["pricePrecision"].to_i,
|
|
24
|
-
available:
|
|
24
|
+
available: true,
|
|
25
|
+
trading_enabled: product["status"] == "online"
|
|
25
26
|
}
|
|
26
27
|
end
|
|
27
28
|
end
|
|
@@ -21,7 +21,8 @@ module Honeymaker
|
|
|
21
21
|
base_decimals: Utils.decimals(product["base_min_size"]),
|
|
22
22
|
quote_decimals: Utils.decimals(product["quote_increment"]),
|
|
23
23
|
price_decimals: product["price_max_precision"].to_i,
|
|
24
|
-
available:
|
|
24
|
+
available: true,
|
|
25
|
+
trading_enabled: product["trade_status"] == "trading"
|
|
25
26
|
}
|
|
26
27
|
end
|
|
27
28
|
end
|
|
@@ -23,7 +23,8 @@ module Honeymaker
|
|
|
23
23
|
base_decimals: f[:lot_size] ? Utils.decimals(f[:lot_size]["stepSize"]) : product["baseAssetPrecision"],
|
|
24
24
|
quote_decimals: product["quotePrecision"],
|
|
25
25
|
price_decimals: f[:price] ? Utils.decimals(f[:price]["tickSize"]) : product["quotePrecision"],
|
|
26
|
-
available:
|
|
26
|
+
available: true,
|
|
27
|
+
trading_enabled: product["status"] == "TRADING"
|
|
27
28
|
}
|
|
28
29
|
end
|
|
29
30
|
end
|
|
@@ -24,7 +24,8 @@ module Honeymaker
|
|
|
24
24
|
base_decimals: product["pricePrecision"] || 8,
|
|
25
25
|
quote_decimals: product["pricePrecision"] || 8,
|
|
26
26
|
price_decimals: product["pricePrecision"] || 8,
|
|
27
|
-
available:
|
|
27
|
+
available: true,
|
|
28
|
+
trading_enabled: product["status"] == "trading"
|
|
28
29
|
}
|
|
29
30
|
end
|
|
30
31
|
end
|
|
@@ -26,7 +26,8 @@ module Honeymaker
|
|
|
26
26
|
base_decimals: Utils.decimals(lot_size_filter["basePrecision"]),
|
|
27
27
|
quote_decimals: Utils.decimals(lot_size_filter["quotePrecision"]),
|
|
28
28
|
price_decimals: Utils.decimals(price_filter["tickSize"]),
|
|
29
|
-
available:
|
|
29
|
+
available: true,
|
|
30
|
+
trading_enabled: product["status"] == "Trading"
|
|
30
31
|
}
|
|
31
32
|
end
|
|
32
33
|
end
|
|
@@ -31,7 +31,8 @@ module Honeymaker
|
|
|
31
31
|
base_decimals: Utils.decimals(product["base_increment"]),
|
|
32
32
|
quote_decimals: Utils.decimals(product["quote_increment"]),
|
|
33
33
|
price_decimals: Utils.decimals(product["price_increment"]),
|
|
34
|
-
available: true
|
|
34
|
+
available: true,
|
|
35
|
+
trading_enabled: trading_enabled?(product)
|
|
35
36
|
}
|
|
36
37
|
end
|
|
37
38
|
end
|
|
@@ -50,6 +51,15 @@ module Honeymaker
|
|
|
50
51
|
|
|
51
52
|
private
|
|
52
53
|
|
|
54
|
+
# Coinbase only signals problems explicitly: a `trading_disabled` flag or a non-"online"
|
|
55
|
+
# `status`. Absent either signal, treat the pair as enabled.
|
|
56
|
+
def trading_enabled?(product)
|
|
57
|
+
return false if product["trading_disabled"] == true
|
|
58
|
+
return false if product.key?("status") && product["status"] != "online"
|
|
59
|
+
|
|
60
|
+
true
|
|
61
|
+
end
|
|
62
|
+
|
|
53
63
|
def connection
|
|
54
64
|
@connection ||= build_connection(BASE_URL)
|
|
55
65
|
end
|
|
@@ -27,7 +27,8 @@ module Honeymaker
|
|
|
27
27
|
base_decimals: Utils.decimals(tick_size),
|
|
28
28
|
quote_decimals: Utils.decimals(quote_increment),
|
|
29
29
|
price_decimals: Utils.decimals(quote_increment),
|
|
30
|
-
available:
|
|
30
|
+
available: true,
|
|
31
|
+
trading_enabled: detail["status"] == "open"
|
|
31
32
|
}
|
|
32
33
|
end
|
|
33
34
|
end
|
|
@@ -59,7 +59,8 @@ module Honeymaker
|
|
|
59
59
|
base_decimals: info["lot_decimals"],
|
|
60
60
|
quote_decimals: info["cost_decimals"],
|
|
61
61
|
price_decimals: info["pair_decimals"],
|
|
62
|
-
available: true
|
|
62
|
+
available: true,
|
|
63
|
+
trading_enabled: info.key?("status") ? info["status"] == "online" : true
|
|
63
64
|
}
|
|
64
65
|
end
|
|
65
66
|
end
|
|
@@ -21,7 +21,8 @@ module Honeymaker
|
|
|
21
21
|
base_decimals: Utils.decimals(product["baseIncrement"]),
|
|
22
22
|
quote_decimals: Utils.decimals(product["quoteIncrement"]),
|
|
23
23
|
price_decimals: Utils.decimals(product["priceIncrement"]),
|
|
24
|
-
available:
|
|
24
|
+
available: true,
|
|
25
|
+
trading_enabled: product["enableTrading"]
|
|
25
26
|
}
|
|
26
27
|
end
|
|
27
28
|
end
|
|
@@ -23,7 +23,8 @@ module Honeymaker
|
|
|
23
23
|
base_decimals: f[:lot_size] ? Utils.decimals(f[:lot_size]["stepSize"]) : product["baseAssetPrecision"],
|
|
24
24
|
quote_decimals: product["quoteAssetPrecision"],
|
|
25
25
|
price_decimals: f[:price] ? Utils.decimals(f[:price]["tickSize"]) : product["quotePrecision"],
|
|
26
|
-
available:
|
|
26
|
+
available: true,
|
|
27
|
+
trading_enabled: product["status"] == "TRADING"
|
|
27
28
|
}
|
|
28
29
|
end
|
|
29
30
|
end
|
data/lib/honeymaker/version.rb
CHANGED
|
@@ -26,6 +26,19 @@ class Honeymaker::Exchanges::BinanceTest < Minitest::Test
|
|
|
26
26
|
assert_equal 8, ticker[:quote_decimals]
|
|
27
27
|
assert_equal 2, ticker[:price_decimals]
|
|
28
28
|
assert ticker[:available]
|
|
29
|
+
assert ticker[:trading_enabled]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def test_get_tickers_info_marks_non_trading_pairs_disabled
|
|
33
|
+
body = load_fixture("binance_exchange_info.json")
|
|
34
|
+
body["symbols"].first["status"] = "BREAK"
|
|
35
|
+
stub_connection(body)
|
|
36
|
+
|
|
37
|
+
result = @exchange.get_tickers_info
|
|
38
|
+
|
|
39
|
+
ticker = result.data.first
|
|
40
|
+
assert ticker[:available] # still listed
|
|
41
|
+
refute ticker[:trading_enabled] # but not trading
|
|
29
42
|
end
|
|
30
43
|
|
|
31
44
|
def test_get_tickers_info_handles_api_error
|
|
@@ -27,6 +27,8 @@ class Honeymaker::Exchanges::BinanceUsTest < Minitest::Test
|
|
|
27
27
|
ticker = result.data.first
|
|
28
28
|
assert_equal "BTCUSDT", ticker[:ticker]
|
|
29
29
|
assert_equal "BTC", ticker[:base]
|
|
30
|
+
assert ticker[:available]
|
|
31
|
+
assert ticker[:trading_enabled]
|
|
30
32
|
end
|
|
31
33
|
|
|
32
34
|
def test_get_bid_ask_parses_response
|
|
@@ -29,16 +29,18 @@ class Honeymaker::Exchanges::BitgetTest < Minitest::Test
|
|
|
29
29
|
assert_equal 8, ticker[:quote_decimals]
|
|
30
30
|
assert_equal 2, ticker[:price_decimals]
|
|
31
31
|
assert ticker[:available]
|
|
32
|
+
assert ticker[:trading_enabled]
|
|
32
33
|
end
|
|
33
34
|
|
|
34
|
-
def
|
|
35
|
+
def test_offline_symbol_listed_but_not_trading_enabled
|
|
35
36
|
body = load_fixture("bitget_symbols.json")
|
|
36
37
|
stub_connection(body)
|
|
37
38
|
|
|
38
39
|
result = @exchange.get_tickers_info
|
|
39
40
|
|
|
40
41
|
eth = result.data.find { |t| t[:ticker] == "ETHUSDT" }
|
|
41
|
-
|
|
42
|
+
assert eth[:available] # still listed
|
|
43
|
+
refute eth[:trading_enabled] # but not trading
|
|
42
44
|
end
|
|
43
45
|
|
|
44
46
|
def test_get_bid_ask_parses_response
|
|
@@ -29,16 +29,18 @@ class Honeymaker::Exchanges::BitMartTest < Minitest::Test
|
|
|
29
29
|
assert_equal 2, ticker[:quote_decimals]
|
|
30
30
|
assert_equal 2, ticker[:price_decimals]
|
|
31
31
|
assert ticker[:available]
|
|
32
|
+
assert ticker[:trading_enabled]
|
|
32
33
|
end
|
|
33
34
|
|
|
34
|
-
def
|
|
35
|
+
def test_pre_trade_listed_but_not_trading_enabled
|
|
35
36
|
body = load_fixture("bitmart_symbols.json")
|
|
36
37
|
stub_connection(body)
|
|
37
38
|
|
|
38
39
|
result = @exchange.get_tickers_info
|
|
39
40
|
|
|
40
41
|
eth = result.data.find { |t| t[:ticker] == "ETH_USDT" }
|
|
41
|
-
|
|
42
|
+
assert eth[:available] # still listed
|
|
43
|
+
refute eth[:trading_enabled] # but not trading
|
|
42
44
|
end
|
|
43
45
|
|
|
44
46
|
def test_get_bid_ask_parses_response
|
|
@@ -29,6 +29,7 @@ class Honeymaker::Exchanges::BitrueTest < Minitest::Test
|
|
|
29
29
|
assert_equal 2, ticker[:quote_decimals]
|
|
30
30
|
assert_equal 2, ticker[:price_decimals]
|
|
31
31
|
assert ticker[:available]
|
|
32
|
+
assert ticker[:trading_enabled]
|
|
32
33
|
end
|
|
33
34
|
|
|
34
35
|
def test_falls_back_to_precision_fields_when_no_filters
|
|
@@ -29,16 +29,18 @@ class Honeymaker::Exchanges::BitvavoTest < Minitest::Test
|
|
|
29
29
|
assert_equal 5, ticker[:quote_decimals]
|
|
30
30
|
assert_equal 5, ticker[:price_decimals]
|
|
31
31
|
assert ticker[:available]
|
|
32
|
+
assert ticker[:trading_enabled]
|
|
32
33
|
end
|
|
33
34
|
|
|
34
|
-
def
|
|
35
|
+
def test_halted_market_listed_but_not_trading_enabled
|
|
35
36
|
body = load_fixture("bitvavo_markets.json")
|
|
36
37
|
stub_connection(body)
|
|
37
38
|
|
|
38
39
|
result = @exchange.get_tickers_info
|
|
39
40
|
|
|
40
41
|
eth = result.data.find { |t| t[:ticker] == "ETH-EUR" }
|
|
41
|
-
|
|
42
|
+
assert eth[:available] # still listed
|
|
43
|
+
refute eth[:trading_enabled] # but not trading
|
|
42
44
|
end
|
|
43
45
|
|
|
44
46
|
def test_get_bid_ask_parses_response
|
|
@@ -29,6 +29,29 @@ class Honeymaker::Exchanges::CoinbaseTest < Minitest::Test
|
|
|
29
29
|
assert_equal 2, ticker[:quote_decimals]
|
|
30
30
|
assert_equal 2, ticker[:price_decimals]
|
|
31
31
|
assert ticker[:available]
|
|
32
|
+
assert ticker[:trading_enabled] # no disabled signal -> defaults to true
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def test_get_tickers_info_disables_when_trading_disabled
|
|
36
|
+
body = load_fixture("coinbase_products.json")
|
|
37
|
+
body["products"].first["trading_disabled"] = true
|
|
38
|
+
stub_connection(body)
|
|
39
|
+
|
|
40
|
+
result = @exchange.get_tickers_info
|
|
41
|
+
|
|
42
|
+
ticker = result.data.first
|
|
43
|
+
assert ticker[:available] # still listed
|
|
44
|
+
refute ticker[:trading_enabled] # but not trading
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def test_get_tickers_info_disables_when_status_not_online
|
|
48
|
+
body = load_fixture("coinbase_products.json")
|
|
49
|
+
body["products"].first["status"] = "delisted"
|
|
50
|
+
stub_connection(body)
|
|
51
|
+
|
|
52
|
+
result = @exchange.get_tickers_info
|
|
53
|
+
|
|
54
|
+
refute result.data.first[:trading_enabled]
|
|
32
55
|
end
|
|
33
56
|
|
|
34
57
|
def test_filters_blacklisted_assets
|
|
@@ -28,6 +28,7 @@ class Honeymaker::Exchanges::HyperliquidTest < Minitest::Test
|
|
|
28
28
|
assert_equal 2, ticker[:quote_decimals]
|
|
29
29
|
assert_equal 5, ticker[:price_decimals]
|
|
30
30
|
assert ticker[:available]
|
|
31
|
+
assert ticker[:trading_enabled] # no native status -> always true
|
|
31
32
|
end
|
|
32
33
|
|
|
33
34
|
def test_skips_pairs_with_missing_tokens
|
|
@@ -26,6 +26,38 @@ class Honeymaker::Exchanges::KrakenTest < Minitest::Test
|
|
|
26
26
|
assert_equal 5, ticker[:quote_decimals]
|
|
27
27
|
assert_equal 1, ticker[:price_decimals]
|
|
28
28
|
assert ticker[:available]
|
|
29
|
+
assert ticker[:trading_enabled] # fixture has no status -> defaults to true
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def test_get_tickers_info_disables_non_online_status
|
|
33
|
+
body = load_fixture("kraken_asset_pairs.json")
|
|
34
|
+
body["result"]["XBTUSDT"]["status"] = "cancel_only"
|
|
35
|
+
stub_request(body)
|
|
36
|
+
|
|
37
|
+
result = @exchange.get_tickers_info
|
|
38
|
+
|
|
39
|
+
ticker = result.data.first
|
|
40
|
+
assert ticker[:available] # still listed
|
|
41
|
+
refute ticker[:trading_enabled] # but not trading
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def test_get_tickers_info_enables_online_status
|
|
45
|
+
body = load_fixture("kraken_asset_pairs.json")
|
|
46
|
+
body["result"]["XBTUSDT"]["status"] = "online"
|
|
47
|
+
stub_request(body)
|
|
48
|
+
|
|
49
|
+
result = @exchange.get_tickers_info
|
|
50
|
+
|
|
51
|
+
assert result.data.first[:trading_enabled]
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def test_get_tickers_info_defaults_trading_enabled_when_status_absent
|
|
55
|
+
body = load_fixture("kraken_asset_pairs.json") # no status key
|
|
56
|
+
stub_request(body)
|
|
57
|
+
|
|
58
|
+
result = @exchange.get_tickers_info
|
|
59
|
+
|
|
60
|
+
assert result.data.first[:trading_enabled]
|
|
29
61
|
end
|
|
30
62
|
|
|
31
63
|
def test_get_tickers_info_skips_pairs_without_wsname
|
|
@@ -29,16 +29,18 @@ class Honeymaker::Exchanges::MexcTest < Minitest::Test
|
|
|
29
29
|
assert_equal 8, ticker[:quote_decimals]
|
|
30
30
|
assert_equal 2, ticker[:price_decimals]
|
|
31
31
|
assert ticker[:available]
|
|
32
|
+
assert ticker[:trading_enabled]
|
|
32
33
|
end
|
|
33
34
|
|
|
34
|
-
def
|
|
35
|
+
def test_halted_symbol_listed_but_not_trading_enabled
|
|
35
36
|
body = load_fixture("mexc_exchange_info.json")
|
|
36
37
|
stub_connection(body)
|
|
37
38
|
|
|
38
39
|
result = @exchange.get_tickers_info
|
|
39
40
|
|
|
40
41
|
halted = result.data.find { |t| t[:ticker] == "ETHUSDT" }
|
|
41
|
-
|
|
42
|
+
assert halted[:available] # still listed
|
|
43
|
+
refute halted[:trading_enabled] # but not trading
|
|
42
44
|
end
|
|
43
45
|
|
|
44
46
|
def test_falls_back_to_precision_fields_when_no_filters
|