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.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -0
  3. data/lib/honeymaker/client.rb +96 -0
  4. data/lib/honeymaker/clients/binance.rb +288 -0
  5. data/lib/honeymaker/clients/binance_us.rb +9 -0
  6. data/lib/honeymaker/clients/bingx.rb +136 -0
  7. data/lib/honeymaker/clients/bitget.rb +157 -0
  8. data/lib/honeymaker/clients/bitmart.rb +146 -0
  9. data/lib/honeymaker/clients/bitrue.rb +130 -0
  10. data/lib/honeymaker/clients/bitvavo.rb +160 -0
  11. data/lib/honeymaker/clients/bybit.rb +166 -0
  12. data/lib/honeymaker/clients/coinbase.rb +219 -0
  13. data/lib/honeymaker/clients/gemini.rb +99 -0
  14. data/lib/honeymaker/clients/hyperliquid.rb +65 -0
  15. data/lib/honeymaker/clients/kraken.rb +162 -0
  16. data/lib/honeymaker/clients/kucoin.rb +180 -0
  17. data/lib/honeymaker/clients/mexc.rb +166 -0
  18. data/lib/honeymaker/exchanges/binance.rb +11 -17
  19. data/lib/honeymaker/exchanges/bitget.rb +2 -2
  20. data/lib/honeymaker/exchanges/bitrue.rb +6 -16
  21. data/lib/honeymaker/exchanges/bitvavo.rb +2 -2
  22. data/lib/honeymaker/exchanges/bybit.rb +2 -2
  23. data/lib/honeymaker/exchanges/coinbase.rb +5 -9
  24. data/lib/honeymaker/exchanges/gemini.rb +4 -6
  25. data/lib/honeymaker/exchanges/kraken.rb +5 -9
  26. data/lib/honeymaker/exchanges/kucoin.rb +2 -2
  27. data/lib/honeymaker/exchanges/mexc.rb +11 -17
  28. data/lib/honeymaker/utils.rb +9 -0
  29. data/lib/honeymaker/version.rb +1 -1
  30. data/lib/honeymaker.rb +38 -0
  31. data/test/fixtures/bingx_symbols.json +26 -0
  32. data/test/fixtures/bitget_symbols.json +28 -0
  33. data/test/fixtures/bitmart_symbols.json +26 -0
  34. data/test/fixtures/bitrue_exchange_info.json +34 -0
  35. data/test/fixtures/bitvavo_markets.json +16 -0
  36. data/test/fixtures/bybit_instruments.json +23 -0
  37. data/test/fixtures/coinbase_products.json +24 -0
  38. data/test/fixtures/gemini_symbol_detail.json +9 -0
  39. data/test/fixtures/gemini_symbols.json +1 -0
  40. data/test/fixtures/hyperliquid_spot_meta.json +12 -0
  41. data/test/fixtures/kucoin_symbols.json +17 -0
  42. data/test/fixtures/mexc_exchange_info.json +40 -0
  43. data/test/honeymaker/client_test.rb +53 -0
  44. data/test/honeymaker/clients/binance_client_test.rb +101 -0
  45. data/test/honeymaker/clients/binance_us_client_test.rb +25 -0
  46. data/test/honeymaker/clients/bingx_client_test.rb +82 -0
  47. data/test/honeymaker/clients/bitget_client_test.rb +109 -0
  48. data/test/honeymaker/clients/bitmart_client_test.rb +96 -0
  49. data/test/honeymaker/clients/bitrue_client_test.rb +69 -0
  50. data/test/honeymaker/clients/bitvavo_client_test.rb +105 -0
  51. data/test/honeymaker/clients/bybit_client_test.rb +102 -0
  52. data/test/honeymaker/clients/coinbase_client_test.rb +132 -0
  53. data/test/honeymaker/clients/gemini_client_test.rb +83 -0
  54. data/test/honeymaker/clients/honeymaker_client_registry_test.rb +44 -0
  55. data/test/honeymaker/clients/hyperliquid_client_test.rb +65 -0
  56. data/test/honeymaker/clients/kraken_client_test.rb +84 -0
  57. data/test/honeymaker/clients/kucoin_client_test.rb +106 -0
  58. data/test/honeymaker/clients/mexc_client_test.rb +93 -0
  59. data/test/honeymaker/clients/validation_test.rb +182 -0
  60. data/test/honeymaker/exchanges/binance_us_test.rb +40 -0
  61. data/test/honeymaker/exchanges/bingx_test.rb +53 -0
  62. data/test/honeymaker/exchanges/bitget_test.rb +52 -0
  63. data/test/honeymaker/exchanges/bitmart_test.rb +52 -0
  64. data/test/honeymaker/exchanges/bitrue_test.rb +53 -0
  65. data/test/honeymaker/exchanges/bitvavo_test.rb +52 -0
  66. data/test/honeymaker/exchanges/bybit_test.rb +43 -0
  67. data/test/honeymaker/exchanges/coinbase_test.rb +52 -0
  68. data/test/honeymaker/exchanges/gemini_test.rb +48 -0
  69. data/test/honeymaker/exchanges/hyperliquid_test.rb +52 -0
  70. data/test/honeymaker/exchanges/kucoin_test.rb +43 -0
  71. data/test/honeymaker/exchanges/mexc_test.rb +64 -0
  72. data/test/honeymaker/utils_test.rb +38 -0
  73. data/test/test_helper.rb +1 -0
  74. 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
data/test/test_helper.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "minitest/autorun"
4
4
  require "mocha/minitest"
5
+ require "ostruct"
5
6
  require "honeymaker"
6
7
 
7
8
  # Load fixture helpers