honeymaker 0.1.0 → 0.3.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/README.md +4 -0
- data/lib/honeymaker/client.rb +96 -0
- data/lib/honeymaker/clients/binance.rb +288 -0
- data/lib/honeymaker/clients/binance_us.rb +9 -0
- data/lib/honeymaker/clients/bingx.rb +136 -0
- data/lib/honeymaker/clients/bitget.rb +157 -0
- data/lib/honeymaker/clients/bitmart.rb +146 -0
- data/lib/honeymaker/clients/bitrue.rb +130 -0
- data/lib/honeymaker/clients/bitvavo.rb +160 -0
- data/lib/honeymaker/clients/bybit.rb +166 -0
- data/lib/honeymaker/clients/coinbase.rb +219 -0
- data/lib/honeymaker/clients/gemini.rb +99 -0
- data/lib/honeymaker/clients/hyperliquid.rb +65 -0
- data/lib/honeymaker/clients/kraken.rb +162 -0
- data/lib/honeymaker/clients/kucoin.rb +180 -0
- data/lib/honeymaker/clients/mexc.rb +166 -0
- data/lib/honeymaker/exchanges/binance.rb +11 -17
- data/lib/honeymaker/exchanges/bitget.rb +2 -2
- data/lib/honeymaker/exchanges/bitrue.rb +6 -16
- data/lib/honeymaker/exchanges/bitvavo.rb +2 -2
- data/lib/honeymaker/exchanges/bybit.rb +2 -2
- data/lib/honeymaker/exchanges/coinbase.rb +5 -9
- data/lib/honeymaker/exchanges/gemini.rb +4 -6
- data/lib/honeymaker/exchanges/kraken.rb +5 -9
- data/lib/honeymaker/exchanges/kucoin.rb +2 -2
- data/lib/honeymaker/exchanges/mexc.rb +11 -17
- data/lib/honeymaker/utils.rb +9 -0
- data/lib/honeymaker/version.rb +1 -1
- data/lib/honeymaker.rb +38 -0
- data/test/fixtures/bingx_symbols.json +26 -0
- data/test/fixtures/bitget_symbols.json +28 -0
- data/test/fixtures/bitmart_symbols.json +26 -0
- data/test/fixtures/bitrue_exchange_info.json +34 -0
- data/test/fixtures/bitvavo_markets.json +16 -0
- data/test/fixtures/bybit_instruments.json +23 -0
- data/test/fixtures/coinbase_products.json +24 -0
- data/test/fixtures/gemini_symbol_detail.json +9 -0
- data/test/fixtures/gemini_symbols.json +1 -0
- data/test/fixtures/hyperliquid_spot_meta.json +12 -0
- data/test/fixtures/kucoin_symbols.json +17 -0
- data/test/fixtures/mexc_exchange_info.json +40 -0
- data/test/honeymaker/client_test.rb +53 -0
- data/test/honeymaker/clients/binance_client_test.rb +101 -0
- data/test/honeymaker/clients/binance_us_client_test.rb +25 -0
- data/test/honeymaker/clients/bingx_client_test.rb +82 -0
- data/test/honeymaker/clients/bitget_client_test.rb +109 -0
- data/test/honeymaker/clients/bitmart_client_test.rb +96 -0
- data/test/honeymaker/clients/bitrue_client_test.rb +69 -0
- data/test/honeymaker/clients/bitvavo_client_test.rb +105 -0
- data/test/honeymaker/clients/bybit_client_test.rb +102 -0
- data/test/honeymaker/clients/coinbase_client_test.rb +132 -0
- data/test/honeymaker/clients/gemini_client_test.rb +83 -0
- data/test/honeymaker/clients/honeymaker_client_registry_test.rb +44 -0
- data/test/honeymaker/clients/hyperliquid_client_test.rb +65 -0
- data/test/honeymaker/clients/kraken_client_test.rb +84 -0
- data/test/honeymaker/clients/kucoin_client_test.rb +106 -0
- data/test/honeymaker/clients/mexc_client_test.rb +93 -0
- data/test/honeymaker/clients/validation_test.rb +182 -0
- data/test/honeymaker/exchanges/binance_us_test.rb +40 -0
- data/test/honeymaker/exchanges/bingx_test.rb +53 -0
- data/test/honeymaker/exchanges/bitget_test.rb +52 -0
- data/test/honeymaker/exchanges/bitmart_test.rb +52 -0
- data/test/honeymaker/exchanges/bitrue_test.rb +53 -0
- data/test/honeymaker/exchanges/bitvavo_test.rb +52 -0
- data/test/honeymaker/exchanges/bybit_test.rb +43 -0
- data/test/honeymaker/exchanges/coinbase_test.rb +52 -0
- data/test/honeymaker/exchanges/gemini_test.rb +48 -0
- data/test/honeymaker/exchanges/hyperliquid_test.rb +52 -0
- data/test/honeymaker/exchanges/kucoin_test.rb +43 -0
- data/test/honeymaker/exchanges/mexc_test.rb +64 -0
- data/test/honeymaker/utils_test.rb +38 -0
- data/test/test_helper.rb +1 -0
- metadata +74 -3
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
class Honeymaker::Exchanges::BinanceUsTest < Minitest::Test
|
|
6
|
+
include FixtureHelper
|
|
7
|
+
|
|
8
|
+
def setup
|
|
9
|
+
@exchange = Honeymaker::Exchanges::BinanceUs.new
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def test_inherits_from_binance
|
|
13
|
+
assert_kind_of Honeymaker::Exchanges::Binance, @exchange
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def test_uses_binance_us_url
|
|
17
|
+
assert_equal "https://api.binance.us", Honeymaker::Exchanges::BinanceUs::BASE_URL
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def test_get_tickers_info_parses_response
|
|
21
|
+
body = load_fixture("binance_exchange_info.json")
|
|
22
|
+
stub_connection(body)
|
|
23
|
+
|
|
24
|
+
result = @exchange.get_tickers_info
|
|
25
|
+
|
|
26
|
+
assert result.success?
|
|
27
|
+
ticker = result.data.first
|
|
28
|
+
assert_equal "BTCUSDT", ticker[:ticker]
|
|
29
|
+
assert_equal "BTC", ticker[:base]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def stub_connection(body)
|
|
35
|
+
response = stub(body: body)
|
|
36
|
+
connection = stub
|
|
37
|
+
connection.stubs(:get).with { |_, &block| block&.call(OpenStruct.new(params: {})); true }.returns(response)
|
|
38
|
+
@exchange.instance_variable_set(:@connection, connection)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
class Honeymaker::Exchanges::BingXTest < Minitest::Test
|
|
6
|
+
include FixtureHelper
|
|
7
|
+
|
|
8
|
+
def setup
|
|
9
|
+
@exchange = Honeymaker::Exchanges::BingX.new
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def test_get_tickers_info_parses_response
|
|
13
|
+
body = load_fixture("bingx_symbols.json")
|
|
14
|
+
stub_connection(body)
|
|
15
|
+
|
|
16
|
+
result = @exchange.get_tickers_info
|
|
17
|
+
|
|
18
|
+
assert result.success?
|
|
19
|
+
# "INVALID" has no dash so it's skipped
|
|
20
|
+
assert_equal 1, result.data.size
|
|
21
|
+
|
|
22
|
+
ticker = result.data.first
|
|
23
|
+
assert_equal "BTC-USDT", ticker[:ticker]
|
|
24
|
+
assert_equal "BTC", ticker[:base]
|
|
25
|
+
assert_equal "USDT", ticker[:quote]
|
|
26
|
+
assert_equal "0.00001", ticker[:minimum_base_size]
|
|
27
|
+
assert_equal "1", ticker[:minimum_quote_size]
|
|
28
|
+
assert_equal "500", ticker[:maximum_base_size]
|
|
29
|
+
assert_equal 5, ticker[:base_decimals]
|
|
30
|
+
assert_equal 2, ticker[:quote_decimals]
|
|
31
|
+
assert_equal 2, ticker[:price_decimals]
|
|
32
|
+
assert ticker[:available]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def test_skips_symbols_without_dash
|
|
36
|
+
body = load_fixture("bingx_symbols.json")
|
|
37
|
+
stub_connection(body)
|
|
38
|
+
|
|
39
|
+
result = @exchange.get_tickers_info
|
|
40
|
+
|
|
41
|
+
tickers = result.data.map { |t| t[:ticker] }
|
|
42
|
+
refute_includes tickers, "INVALID"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def stub_connection(body)
|
|
48
|
+
response = stub(body: body)
|
|
49
|
+
connection = stub
|
|
50
|
+
connection.stubs(:get).returns(response)
|
|
51
|
+
@exchange.instance_variable_set(:@connection, connection)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
class Honeymaker::Exchanges::BitgetTest < Minitest::Test
|
|
6
|
+
include FixtureHelper
|
|
7
|
+
|
|
8
|
+
def setup
|
|
9
|
+
@exchange = Honeymaker::Exchanges::Bitget.new
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def test_get_tickers_info_parses_response
|
|
13
|
+
body = load_fixture("bitget_symbols.json")
|
|
14
|
+
stub_connection(body)
|
|
15
|
+
|
|
16
|
+
result = @exchange.get_tickers_info
|
|
17
|
+
|
|
18
|
+
assert result.success?
|
|
19
|
+
assert_equal 2, result.data.size
|
|
20
|
+
|
|
21
|
+
ticker = result.data.first
|
|
22
|
+
assert_equal "BTCUSDT", ticker[:ticker]
|
|
23
|
+
assert_equal "BTC", ticker[:base]
|
|
24
|
+
assert_equal "USDT", ticker[:quote]
|
|
25
|
+
assert_equal "0.00001", ticker[:minimum_base_size]
|
|
26
|
+
assert_equal "5", ticker[:minimum_quote_size]
|
|
27
|
+
assert_equal "9000", ticker[:maximum_base_size]
|
|
28
|
+
assert_equal 6, ticker[:base_decimals]
|
|
29
|
+
assert_equal 8, ticker[:quote_decimals]
|
|
30
|
+
assert_equal 2, ticker[:price_decimals]
|
|
31
|
+
assert ticker[:available]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def test_offline_symbol_not_available
|
|
35
|
+
body = load_fixture("bitget_symbols.json")
|
|
36
|
+
stub_connection(body)
|
|
37
|
+
|
|
38
|
+
result = @exchange.get_tickers_info
|
|
39
|
+
|
|
40
|
+
eth = result.data.find { |t| t[:ticker] == "ETHUSDT" }
|
|
41
|
+
refute eth[:available]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def stub_connection(body)
|
|
47
|
+
response = stub(body: body)
|
|
48
|
+
connection = stub
|
|
49
|
+
connection.stubs(:get).returns(response)
|
|
50
|
+
@exchange.instance_variable_set(:@connection, connection)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
class Honeymaker::Exchanges::BitMartTest < Minitest::Test
|
|
6
|
+
include FixtureHelper
|
|
7
|
+
|
|
8
|
+
def setup
|
|
9
|
+
@exchange = Honeymaker::Exchanges::BitMart.new
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def test_get_tickers_info_parses_response
|
|
13
|
+
body = load_fixture("bitmart_symbols.json")
|
|
14
|
+
stub_connection(body)
|
|
15
|
+
|
|
16
|
+
result = @exchange.get_tickers_info
|
|
17
|
+
|
|
18
|
+
assert result.success?
|
|
19
|
+
assert_equal 2, result.data.size
|
|
20
|
+
|
|
21
|
+
ticker = result.data.first
|
|
22
|
+
assert_equal "BTC_USDT", ticker[:ticker]
|
|
23
|
+
assert_equal "BTC", ticker[:base]
|
|
24
|
+
assert_equal "USDT", ticker[:quote]
|
|
25
|
+
assert_equal "0.00001", ticker[:minimum_base_size]
|
|
26
|
+
assert_equal "5", ticker[:minimum_quote_size]
|
|
27
|
+
assert_nil ticker[:maximum_base_size]
|
|
28
|
+
assert_equal 5, ticker[:base_decimals]
|
|
29
|
+
assert_equal 2, ticker[:quote_decimals]
|
|
30
|
+
assert_equal 2, ticker[:price_decimals]
|
|
31
|
+
assert ticker[:available]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def test_pre_trade_not_available
|
|
35
|
+
body = load_fixture("bitmart_symbols.json")
|
|
36
|
+
stub_connection(body)
|
|
37
|
+
|
|
38
|
+
result = @exchange.get_tickers_info
|
|
39
|
+
|
|
40
|
+
eth = result.data.find { |t| t[:ticker] == "ETH_USDT" }
|
|
41
|
+
refute eth[:available]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def stub_connection(body)
|
|
47
|
+
response = stub(body: body)
|
|
48
|
+
connection = stub
|
|
49
|
+
connection.stubs(:get).returns(response)
|
|
50
|
+
@exchange.instance_variable_set(:@connection, connection)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
class Honeymaker::Exchanges::BitrueTest < Minitest::Test
|
|
6
|
+
include FixtureHelper
|
|
7
|
+
|
|
8
|
+
def setup
|
|
9
|
+
@exchange = Honeymaker::Exchanges::Bitrue.new
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def test_get_tickers_info_parses_response
|
|
13
|
+
body = load_fixture("bitrue_exchange_info.json")
|
|
14
|
+
stub_connection(body)
|
|
15
|
+
|
|
16
|
+
result = @exchange.get_tickers_info
|
|
17
|
+
|
|
18
|
+
assert result.success?
|
|
19
|
+
assert_equal 2, result.data.size
|
|
20
|
+
|
|
21
|
+
ticker = result.data.first
|
|
22
|
+
assert_equal "BTCUSDT", ticker[:ticker]
|
|
23
|
+
assert_equal "BTC", ticker[:base]
|
|
24
|
+
assert_equal "USDT", ticker[:quote]
|
|
25
|
+
assert_equal "0.00001", ticker[:minimum_base_size]
|
|
26
|
+
assert_equal "5", ticker[:minimum_quote_size]
|
|
27
|
+
assert_equal "9000", ticker[:maximum_base_size]
|
|
28
|
+
assert_equal 5, ticker[:base_decimals]
|
|
29
|
+
assert_equal 2, ticker[:quote_decimals]
|
|
30
|
+
assert_equal 2, ticker[:price_decimals]
|
|
31
|
+
assert ticker[:available]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def test_falls_back_to_precision_fields_when_no_filters
|
|
35
|
+
body = load_fixture("bitrue_exchange_info.json")
|
|
36
|
+
stub_connection(body)
|
|
37
|
+
|
|
38
|
+
result = @exchange.get_tickers_info
|
|
39
|
+
|
|
40
|
+
eth = result.data.find { |t| t[:ticker] == "ETHUSDT" }
|
|
41
|
+
assert_equal 6, eth[:base_decimals]
|
|
42
|
+
assert_equal 2, eth[:price_decimals]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def stub_connection(body)
|
|
48
|
+
response = stub(body: body)
|
|
49
|
+
connection = stub
|
|
50
|
+
connection.stubs(:get).returns(response)
|
|
51
|
+
@exchange.instance_variable_set(:@connection, connection)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
class Honeymaker::Exchanges::BitvavoTest < Minitest::Test
|
|
6
|
+
include FixtureHelper
|
|
7
|
+
|
|
8
|
+
def setup
|
|
9
|
+
@exchange = Honeymaker::Exchanges::Bitvavo.new
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def test_get_tickers_info_parses_response
|
|
13
|
+
body = load_fixture("bitvavo_markets.json")
|
|
14
|
+
stub_connection(body)
|
|
15
|
+
|
|
16
|
+
result = @exchange.get_tickers_info
|
|
17
|
+
|
|
18
|
+
assert result.success?
|
|
19
|
+
assert_equal 2, result.data.size
|
|
20
|
+
|
|
21
|
+
ticker = result.data.first
|
|
22
|
+
assert_equal "BTC-EUR", ticker[:ticker]
|
|
23
|
+
assert_equal "BTC", ticker[:base]
|
|
24
|
+
assert_equal "EUR", ticker[:quote]
|
|
25
|
+
assert_equal "0.00001", ticker[:minimum_base_size]
|
|
26
|
+
assert_equal "5", ticker[:minimum_quote_size]
|
|
27
|
+
assert_nil ticker[:maximum_base_size]
|
|
28
|
+
assert_equal 5, ticker[:base_decimals]
|
|
29
|
+
assert_equal 5, ticker[:quote_decimals]
|
|
30
|
+
assert_equal 5, ticker[:price_decimals]
|
|
31
|
+
assert ticker[:available]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def test_halted_market_not_available
|
|
35
|
+
body = load_fixture("bitvavo_markets.json")
|
|
36
|
+
stub_connection(body)
|
|
37
|
+
|
|
38
|
+
result = @exchange.get_tickers_info
|
|
39
|
+
|
|
40
|
+
eth = result.data.find { |t| t[:ticker] == "ETH-EUR" }
|
|
41
|
+
refute eth[:available]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def stub_connection(body)
|
|
47
|
+
response = stub(body: body)
|
|
48
|
+
connection = stub
|
|
49
|
+
connection.stubs(:get).returns(response)
|
|
50
|
+
@exchange.instance_variable_set(:@connection, connection)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
class Honeymaker::Exchanges::BybitTest < Minitest::Test
|
|
6
|
+
include FixtureHelper
|
|
7
|
+
|
|
8
|
+
def setup
|
|
9
|
+
@exchange = Honeymaker::Exchanges::Bybit.new
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def test_get_tickers_info_parses_response
|
|
13
|
+
body = load_fixture("bybit_instruments.json")
|
|
14
|
+
stub_connection(body)
|
|
15
|
+
|
|
16
|
+
result = @exchange.get_tickers_info
|
|
17
|
+
|
|
18
|
+
assert result.success?
|
|
19
|
+
assert_equal 1, result.data.size
|
|
20
|
+
|
|
21
|
+
ticker = result.data.first
|
|
22
|
+
assert_equal "BTCUSDT", ticker[:ticker]
|
|
23
|
+
assert_equal "BTC", ticker[:base]
|
|
24
|
+
assert_equal "USDT", ticker[:quote]
|
|
25
|
+
assert_equal "0.000048", ticker[:minimum_base_size]
|
|
26
|
+
assert_equal "1", ticker[:minimum_quote_size]
|
|
27
|
+
assert_equal "71.73956243", ticker[:maximum_base_size]
|
|
28
|
+
assert_equal "4000000", ticker[:maximum_quote_size]
|
|
29
|
+
assert_equal 6, ticker[:base_decimals]
|
|
30
|
+
assert_equal 8, ticker[:quote_decimals]
|
|
31
|
+
assert_equal 2, ticker[:price_decimals]
|
|
32
|
+
assert ticker[:available]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def stub_connection(body)
|
|
38
|
+
response = stub(body: body)
|
|
39
|
+
connection = stub
|
|
40
|
+
connection.stubs(:get).with { |_, &block| block&.call(OpenStruct.new(params: {})); true }.returns(response)
|
|
41
|
+
@exchange.instance_variable_set(:@connection, connection)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
class Honeymaker::Exchanges::CoinbaseTest < Minitest::Test
|
|
6
|
+
include FixtureHelper
|
|
7
|
+
|
|
8
|
+
def setup
|
|
9
|
+
@exchange = Honeymaker::Exchanges::Coinbase.new
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def test_get_tickers_info_parses_response
|
|
13
|
+
body = load_fixture("coinbase_products.json")
|
|
14
|
+
stub_connection(body)
|
|
15
|
+
|
|
16
|
+
result = @exchange.get_tickers_info
|
|
17
|
+
|
|
18
|
+
assert result.success?
|
|
19
|
+
# RENDER is blacklisted, so only BTC-USD should remain
|
|
20
|
+
assert_equal 1, result.data.size
|
|
21
|
+
ticker = result.data.first
|
|
22
|
+
assert_equal "BTC-USD", ticker[:ticker]
|
|
23
|
+
assert_equal "BTC", ticker[:base]
|
|
24
|
+
assert_equal "USD", ticker[:quote]
|
|
25
|
+
assert_equal "0.00000001", ticker[:minimum_base_size]
|
|
26
|
+
assert_equal "1", ticker[:minimum_quote_size]
|
|
27
|
+
assert_equal "3400", ticker[:maximum_base_size]
|
|
28
|
+
assert_equal 8, ticker[:base_decimals]
|
|
29
|
+
assert_equal 2, ticker[:quote_decimals]
|
|
30
|
+
assert_equal 2, ticker[:price_decimals]
|
|
31
|
+
assert ticker[:available]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def test_filters_blacklisted_assets
|
|
35
|
+
body = load_fixture("coinbase_products.json")
|
|
36
|
+
stub_connection(body)
|
|
37
|
+
|
|
38
|
+
result = @exchange.get_tickers_info
|
|
39
|
+
|
|
40
|
+
bases = result.data.map { |t| t[:base] }
|
|
41
|
+
refute_includes bases, "RENDER"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def stub_connection(body)
|
|
47
|
+
response = stub(body: body)
|
|
48
|
+
connection = stub
|
|
49
|
+
connection.stubs(:get).returns(response)
|
|
50
|
+
@exchange.instance_variable_set(:@connection, connection)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
class Honeymaker::Exchanges::GeminiTest < Minitest::Test
|
|
6
|
+
include FixtureHelper
|
|
7
|
+
|
|
8
|
+
def setup
|
|
9
|
+
@exchange = Honeymaker::Exchanges::Gemini.new
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def test_get_tickers_info_parses_response
|
|
13
|
+
symbols_body = load_fixture("gemini_symbols.json")
|
|
14
|
+
detail_body = load_fixture("gemini_symbol_detail.json")
|
|
15
|
+
|
|
16
|
+
symbols_response = stub(body: symbols_body)
|
|
17
|
+
detail_response = stub(body: detail_body)
|
|
18
|
+
connection = stub
|
|
19
|
+
connection.stubs(:get).with("/v1/symbols").returns(symbols_response)
|
|
20
|
+
connection.stubs(:get).with { |path| path.start_with?("/v1/symbols/details/") }.returns(detail_response)
|
|
21
|
+
@exchange.instance_variable_set(:@connection, connection)
|
|
22
|
+
|
|
23
|
+
result = @exchange.get_tickers_info
|
|
24
|
+
|
|
25
|
+
assert result.success?
|
|
26
|
+
assert_equal 2, result.data.size
|
|
27
|
+
|
|
28
|
+
ticker = result.data.first
|
|
29
|
+
assert_equal "BTCUSD", ticker[:ticker]
|
|
30
|
+
assert_equal "BTC", ticker[:base]
|
|
31
|
+
assert_equal "USD", ticker[:quote]
|
|
32
|
+
assert_equal "0.00001", ticker[:minimum_base_size]
|
|
33
|
+
assert_equal "0", ticker[:minimum_quote_size]
|
|
34
|
+
assert_equal 8, ticker[:base_decimals]
|
|
35
|
+
assert_equal 2, ticker[:quote_decimals]
|
|
36
|
+
assert_equal 2, ticker[:price_decimals]
|
|
37
|
+
assert ticker[:available]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def stub_connection(body)
|
|
43
|
+
response = stub(body: body)
|
|
44
|
+
connection = stub
|
|
45
|
+
connection.stubs(:get).returns(response)
|
|
46
|
+
@exchange.instance_variable_set(:@connection, connection)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
class Honeymaker::Exchanges::HyperliquidTest < Minitest::Test
|
|
6
|
+
include FixtureHelper
|
|
7
|
+
|
|
8
|
+
def setup
|
|
9
|
+
@exchange = Honeymaker::Exchanges::Hyperliquid.new
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def test_get_tickers_info_parses_response
|
|
13
|
+
body = load_fixture("hyperliquid_spot_meta.json")
|
|
14
|
+
stub_connection(body)
|
|
15
|
+
|
|
16
|
+
result = @exchange.get_tickers_info
|
|
17
|
+
|
|
18
|
+
assert result.success?
|
|
19
|
+
assert_equal 1, result.data.size
|
|
20
|
+
|
|
21
|
+
ticker = result.data.first
|
|
22
|
+
assert_equal "PURR/USDC", ticker[:ticker]
|
|
23
|
+
assert_equal "PURR", ticker[:base]
|
|
24
|
+
assert_equal "USDC", ticker[:quote]
|
|
25
|
+
assert_nil ticker[:minimum_base_size]
|
|
26
|
+
assert_nil ticker[:minimum_quote_size]
|
|
27
|
+
assert_equal 2, ticker[:base_decimals]
|
|
28
|
+
assert_equal 2, ticker[:quote_decimals]
|
|
29
|
+
assert_equal 5, ticker[:price_decimals]
|
|
30
|
+
assert ticker[:available]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def test_skips_pairs_with_missing_tokens
|
|
34
|
+
body = load_fixture("hyperliquid_spot_meta.json")
|
|
35
|
+
body["universe"] << { "name" => "MISSING/PAIR", "tokens" => [99, 100] }
|
|
36
|
+
stub_connection(body)
|
|
37
|
+
|
|
38
|
+
result = @exchange.get_tickers_info
|
|
39
|
+
|
|
40
|
+
assert result.success?
|
|
41
|
+
assert_equal 1, result.data.size
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def stub_connection(body)
|
|
47
|
+
response = stub(body: body)
|
|
48
|
+
connection = stub
|
|
49
|
+
connection.stubs(:post).with { |_, &block| block&.call(OpenStruct.new(body: nil)); true }.returns(response)
|
|
50
|
+
@exchange.instance_variable_set(:@connection, connection)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
class Honeymaker::Exchanges::KucoinTest < Minitest::Test
|
|
6
|
+
include FixtureHelper
|
|
7
|
+
|
|
8
|
+
def setup
|
|
9
|
+
@exchange = Honeymaker::Exchanges::Kucoin.new
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def test_get_tickers_info_parses_response
|
|
13
|
+
body = load_fixture("kucoin_symbols.json")
|
|
14
|
+
stub_connection(body)
|
|
15
|
+
|
|
16
|
+
result = @exchange.get_tickers_info
|
|
17
|
+
|
|
18
|
+
assert result.success?
|
|
19
|
+
assert_equal 1, result.data.size
|
|
20
|
+
|
|
21
|
+
ticker = result.data.first
|
|
22
|
+
assert_equal "BTC-USDT", ticker[:ticker]
|
|
23
|
+
assert_equal "BTC", ticker[:base]
|
|
24
|
+
assert_equal "USDT", ticker[:quote]
|
|
25
|
+
assert_equal "0.00001", ticker[:minimum_base_size]
|
|
26
|
+
assert_equal "0.1", ticker[:minimum_quote_size]
|
|
27
|
+
assert_equal "10000000000", ticker[:maximum_base_size]
|
|
28
|
+
assert_equal "99999999", ticker[:maximum_quote_size]
|
|
29
|
+
assert_equal 8, ticker[:base_decimals]
|
|
30
|
+
assert_equal 6, ticker[:quote_decimals]
|
|
31
|
+
assert_equal 1, ticker[:price_decimals]
|
|
32
|
+
assert ticker[:available]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def stub_connection(body)
|
|
38
|
+
response = stub(body: body)
|
|
39
|
+
connection = stub
|
|
40
|
+
connection.stubs(:get).returns(response)
|
|
41
|
+
@exchange.instance_variable_set(:@connection, connection)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
class Honeymaker::Exchanges::MexcTest < Minitest::Test
|
|
6
|
+
include FixtureHelper
|
|
7
|
+
|
|
8
|
+
def setup
|
|
9
|
+
@exchange = Honeymaker::Exchanges::Mexc.new
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def test_get_tickers_info_parses_response
|
|
13
|
+
body = load_fixture("mexc_exchange_info.json")
|
|
14
|
+
stub_connection(body)
|
|
15
|
+
|
|
16
|
+
result = @exchange.get_tickers_info
|
|
17
|
+
|
|
18
|
+
assert result.success?
|
|
19
|
+
assert_equal 2, result.data.size
|
|
20
|
+
|
|
21
|
+
ticker = result.data.first
|
|
22
|
+
assert_equal "BTCUSDT", ticker[:ticker]
|
|
23
|
+
assert_equal "BTC", ticker[:base]
|
|
24
|
+
assert_equal "USDT", ticker[:quote]
|
|
25
|
+
assert_equal "0.00001", ticker[:minimum_base_size]
|
|
26
|
+
assert_equal "5", ticker[:minimum_quote_size]
|
|
27
|
+
assert_equal "9000", ticker[:maximum_base_size]
|
|
28
|
+
assert_equal 5, ticker[:base_decimals]
|
|
29
|
+
assert_equal 8, ticker[:quote_decimals]
|
|
30
|
+
assert_equal 2, ticker[:price_decimals]
|
|
31
|
+
assert ticker[:available]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def test_halted_symbol_not_available
|
|
35
|
+
body = load_fixture("mexc_exchange_info.json")
|
|
36
|
+
stub_connection(body)
|
|
37
|
+
|
|
38
|
+
result = @exchange.get_tickers_info
|
|
39
|
+
|
|
40
|
+
halted = result.data.find { |t| t[:ticker] == "ETHUSDT" }
|
|
41
|
+
refute halted[:available]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def test_falls_back_to_precision_fields_when_no_filters
|
|
45
|
+
body = load_fixture("mexc_exchange_info.json")
|
|
46
|
+
stub_connection(body)
|
|
47
|
+
|
|
48
|
+
result = @exchange.get_tickers_info
|
|
49
|
+
|
|
50
|
+
# ETHUSDT has empty filters, should use baseAssetPrecision/quotePrecision
|
|
51
|
+
eth = result.data.find { |t| t[:ticker] == "ETHUSDT" }
|
|
52
|
+
assert_equal 6, eth[:base_decimals]
|
|
53
|
+
assert_equal 2, eth[:price_decimals]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
def stub_connection(body)
|
|
59
|
+
response = stub(body: body)
|
|
60
|
+
connection = stub
|
|
61
|
+
connection.stubs(:get).returns(response)
|
|
62
|
+
@exchange.instance_variable_set(:@connection, connection)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -23,4 +23,42 @@ class Honeymaker::UtilsTest < Minitest::Test
|
|
|
23
23
|
assert_equal 0, Honeymaker::Utils.decimals("1")
|
|
24
24
|
assert_equal 0, Honeymaker::Utils.decimals("10")
|
|
25
25
|
end
|
|
26
|
+
|
|
27
|
+
def test_decimals_with_nil
|
|
28
|
+
assert_equal 0, Honeymaker::Utils.decimals(nil)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def test_parse_filters
|
|
32
|
+
filters = [
|
|
33
|
+
{ "filterType" => "PRICE_FILTER", "tickSize" => "0.01" },
|
|
34
|
+
{ "filterType" => "LOT_SIZE", "stepSize" => "0.001" },
|
|
35
|
+
{ "filterType" => "NOTIONAL", "minNotional" => "5" }
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
result = Honeymaker::Utils.parse_filters(filters)
|
|
39
|
+
|
|
40
|
+
assert_equal "0.01", result[:price]["tickSize"]
|
|
41
|
+
assert_equal "0.001", result[:lot_size]["stepSize"]
|
|
42
|
+
assert_equal "5", result[:notional]["minNotional"]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def test_parse_filters_with_min_notional
|
|
46
|
+
filters = [
|
|
47
|
+
{ "filterType" => "MIN_NOTIONAL", "minNotional" => "10" }
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
result = Honeymaker::Utils.parse_filters(filters)
|
|
51
|
+
|
|
52
|
+
assert_nil result[:price]
|
|
53
|
+
assert_nil result[:lot_size]
|
|
54
|
+
assert_equal "10", result[:notional]["minNotional"]
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def test_parse_filters_empty
|
|
58
|
+
result = Honeymaker::Utils.parse_filters([])
|
|
59
|
+
|
|
60
|
+
assert_nil result[:price]
|
|
61
|
+
assert_nil result[:lot_size]
|
|
62
|
+
assert_nil result[:notional]
|
|
63
|
+
end
|
|
26
64
|
end
|