honeymaker 0.1.0 → 0.2.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 (73) hide show
  1. checksums.yaml +4 -4
  2. data/honeymaker-0.1.0.gem +0 -0
  3. data/lib/honeymaker/client.rb +74 -0
  4. data/lib/honeymaker/clients/binance.rb +240 -0
  5. data/lib/honeymaker/clients/binance_us.rb +9 -0
  6. data/lib/honeymaker/clients/bingx.rb +105 -0
  7. data/lib/honeymaker/clients/bitget.rb +128 -0
  8. data/lib/honeymaker/clients/bitmart.rb +117 -0
  9. data/lib/honeymaker/clients/bitrue.rb +114 -0
  10. data/lib/honeymaker/clients/bitvavo.rb +136 -0
  11. data/lib/honeymaker/clients/bybit.rb +136 -0
  12. data/lib/honeymaker/clients/coinbase.rb +184 -0
  13. data/lib/honeymaker/clients/gemini.rb +81 -0
  14. data/lib/honeymaker/clients/hyperliquid.rb +42 -0
  15. data/lib/honeymaker/clients/kraken.rb +132 -0
  16. data/lib/honeymaker/clients/kucoin.rb +147 -0
  17. data/lib/honeymaker/clients/mexc.rb +136 -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 +80 -0
  45. data/test/honeymaker/clients/binance_us_client_test.rb +25 -0
  46. data/test/honeymaker/clients/bingx_client_test.rb +64 -0
  47. data/test/honeymaker/clients/bitget_client_test.rb +85 -0
  48. data/test/honeymaker/clients/bitmart_client_test.rb +78 -0
  49. data/test/honeymaker/clients/bitrue_client_test.rb +63 -0
  50. data/test/honeymaker/clients/bitvavo_client_test.rb +87 -0
  51. data/test/honeymaker/clients/bybit_client_test.rb +84 -0
  52. data/test/honeymaker/clients/coinbase_client_test.rb +118 -0
  53. data/test/honeymaker/clients/gemini_client_test.rb +71 -0
  54. data/test/honeymaker/clients/honeymaker_client_registry_test.rb +44 -0
  55. data/test/honeymaker/clients/hyperliquid_client_test.rb +53 -0
  56. data/test/honeymaker/clients/kraken_client_test.rb +70 -0
  57. data/test/honeymaker/clients/kucoin_client_test.rb +88 -0
  58. data/test/honeymaker/clients/mexc_client_test.rb +75 -0
  59. data/test/honeymaker/exchanges/binance_us_test.rb +40 -0
  60. data/test/honeymaker/exchanges/bingx_test.rb +53 -0
  61. data/test/honeymaker/exchanges/bitget_test.rb +52 -0
  62. data/test/honeymaker/exchanges/bitmart_test.rb +52 -0
  63. data/test/honeymaker/exchanges/bitrue_test.rb +53 -0
  64. data/test/honeymaker/exchanges/bitvavo_test.rb +52 -0
  65. data/test/honeymaker/exchanges/bybit_test.rb +43 -0
  66. data/test/honeymaker/exchanges/coinbase_test.rb +52 -0
  67. data/test/honeymaker/exchanges/gemini_test.rb +48 -0
  68. data/test/honeymaker/exchanges/hyperliquid_test.rb +52 -0
  69. data/test/honeymaker/exchanges/kucoin_test.rb +43 -0
  70. data/test/honeymaker/exchanges/mexc_test.rb +64 -0
  71. data/test/honeymaker/utils_test.rb +38 -0
  72. data/test/test_helper.rb +1 -0
  73. metadata +74 -3
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ class Honeymaker::Clients::BitgetTest < Minitest::Test
6
+ def setup
7
+ @client = Honeymaker::Clients::Bitget.new(
8
+ api_key: "test_key", api_secret: "test_secret", passphrase: "test_pass"
9
+ )
10
+ end
11
+
12
+ def test_url
13
+ assert_equal "https://api.bitget.com", Honeymaker::Clients::Bitget::URL
14
+ end
15
+
16
+ def test_accepts_passphrase
17
+ assert_equal "test_pass", @client.passphrase
18
+ end
19
+
20
+ def test_get_coins
21
+ stub_connection(:get, { "data" => [{ "coin" => "BTC" }] })
22
+ result = @client.get_coins
23
+ assert result.success?
24
+ end
25
+
26
+ def test_get_symbols
27
+ stub_connection(:get, { "data" => [{ "symbol" => "BTCUSDT" }] })
28
+ result = @client.get_symbols
29
+ assert result.success?
30
+ end
31
+
32
+ def test_get_account_assets
33
+ stub_connection(:get, { "data" => [{ "coin" => "BTC", "available" => "0.5" }] })
34
+ result = @client.get_account_assets
35
+ assert result.success?
36
+ end
37
+
38
+ def test_place_order
39
+ stub_connection(:post, { "data" => { "orderId" => "123" } })
40
+ result = @client.place_order(symbol: "BTCUSDT", side: "buy", order_type: "market", size: "0.001")
41
+ assert result.success?
42
+ end
43
+
44
+ def test_get_order
45
+ stub_connection(:get, { "data" => [{ "orderId" => "123" }] })
46
+ result = @client.get_order(order_id: "123")
47
+ assert result.success?
48
+ end
49
+
50
+ def test_cancel_order
51
+ stub_connection(:post, { "data" => { "orderId" => "123" } })
52
+ result = @client.cancel_order(symbol: "BTCUSDT", order_id: "123")
53
+ assert result.success?
54
+ end
55
+
56
+ def test_get_candles
57
+ stub_connection(:get, { "data" => [] })
58
+ result = @client.get_candles(symbol: "BTCUSDT", granularity: "1min")
59
+ assert result.success?
60
+ end
61
+
62
+ def test_withdraw
63
+ stub_connection(:post, { "data" => { "orderId" => "w1" } })
64
+ result = @client.withdraw(coin: "BTC", transfer_type: "on_chain", address: "addr", size: "0.1")
65
+ assert result.success?
66
+ end
67
+
68
+ def test_signed_headers_include_passphrase
69
+ ts = "1234567890"
70
+ headers = @client.send(:signed_headers, ts, "payload")
71
+ assert_equal "test_key", headers[:"ACCESS-KEY"]
72
+ assert_equal "test_pass", headers[:"ACCESS-PASSPHRASE"]
73
+ assert_equal ts, headers[:"ACCESS-TIMESTAMP"]
74
+ assert headers.key?(:"ACCESS-SIGN")
75
+ end
76
+
77
+ private
78
+
79
+ def stub_connection(method, body)
80
+ response = stub(body: body)
81
+ connection = stub
82
+ connection.stubs(method).returns(response)
83
+ @client.instance_variable_set(:@connection, connection)
84
+ end
85
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ class Honeymaker::Clients::BitMartTest < Minitest::Test
6
+ def setup
7
+ @client = Honeymaker::Clients::BitMart.new(
8
+ api_key: "test_key", api_secret: "test_secret", memo: "test_memo"
9
+ )
10
+ end
11
+
12
+ def test_url
13
+ assert_equal "https://api-cloud.bitmart.com", Honeymaker::Clients::BitMart::URL
14
+ end
15
+
16
+ def test_accepts_memo
17
+ assert_equal "test_memo", @client.memo
18
+ end
19
+
20
+ def test_get_symbols_details
21
+ stub_connection(:get, { "data" => { "symbols" => [{ "symbol" => "BTC_USDT" }] } })
22
+ result = @client.get_symbols_details
23
+ assert result.success?
24
+ end
25
+
26
+ def test_get_ticker
27
+ stub_connection(:get, { "data" => [{ "symbol" => "BTC_USDT" }] })
28
+ result = @client.get_ticker(symbol: "BTC_USDT")
29
+ assert result.success?
30
+ end
31
+
32
+ def test_get_wallet
33
+ stub_connection(:get, { "data" => { "wallet" => [{ "id" => "BTC" }] } })
34
+ result = @client.get_wallet
35
+ assert result.success?
36
+ end
37
+
38
+ def test_submit_order
39
+ stub_connection(:post, { "data" => { "order_id" => 123 } })
40
+ result = @client.submit_order(symbol: "BTC_USDT", side: "buy", type: "market", notional: "100")
41
+ assert result.success?
42
+ end
43
+
44
+ def test_get_order
45
+ stub_connection(:post, { "data" => { "order_id" => 123 } })
46
+ result = @client.get_order(order_id: "123")
47
+ assert result.success?
48
+ end
49
+
50
+ def test_cancel_order
51
+ stub_connection(:post, { "data" => true })
52
+ result = @client.cancel_order(symbol: "BTC_USDT", order_id: "123")
53
+ assert result.success?
54
+ end
55
+
56
+ def test_withdraw
57
+ stub_connection(:post, { "data" => { "withdraw_id" => "w1" } })
58
+ result = @client.withdraw(currency: "BTC", amount: "0.1", address: "addr")
59
+ assert result.success?
60
+ end
61
+
62
+ def test_signed_headers_include_memo_in_signature
63
+ ts = "1234567890"
64
+ pre_sign = "#{ts}#test_memo#body"
65
+ headers = @client.send(:signed_headers, ts, pre_sign)
66
+ assert_equal "test_key", headers[:"X-BM-KEY"]
67
+ assert headers.key?(:"X-BM-SIGN")
68
+ end
69
+
70
+ private
71
+
72
+ def stub_connection(method, body)
73
+ response = stub(body: body)
74
+ connection = stub
75
+ connection.stubs(method).returns(response)
76
+ @client.instance_variable_set(:@connection, connection)
77
+ end
78
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ class Honeymaker::Clients::BitrueTest < Minitest::Test
6
+ def setup
7
+ @client = Honeymaker::Clients::Bitrue.new(api_key: "test_key", api_secret: "test_secret")
8
+ end
9
+
10
+ def test_url
11
+ assert_equal "https://openapi.bitrue.com", Honeymaker::Clients::Bitrue::URL
12
+ end
13
+
14
+ def test_exchange_information
15
+ stub_connection(:get, { "symbols" => [{ "symbol" => "BTCUSDT" }] })
16
+ result = @client.exchange_information
17
+ assert result.success?
18
+ end
19
+
20
+ def test_symbol_price_ticker
21
+ stub_connection(:get, { "symbol" => "BTCUSDT", "price" => "50000" })
22
+ result = @client.symbol_price_ticker(symbol: "BTCUSDT")
23
+ assert result.success?
24
+ end
25
+
26
+ def test_account_information
27
+ stub_connection(:get, { "balances" => [{ "asset" => "BTC" }] })
28
+ result = @client.account_information
29
+ assert result.success?
30
+ end
31
+
32
+ def test_new_order
33
+ stub_connection(:post, { "orderId" => "123" })
34
+ result = @client.new_order(symbol: "BTCUSDT", side: "BUY", type: "MARKET", quantity: "0.001")
35
+ assert result.success?
36
+ end
37
+
38
+ def test_query_order
39
+ stub_connection(:get, { "orderId" => "123", "status" => "FILLED" })
40
+ result = @client.query_order(symbol: "BTCUSDT", order_id: "123")
41
+ assert result.success?
42
+ end
43
+
44
+ def test_cancel_order
45
+ stub_connection(:delete, { "orderId" => "123" })
46
+ result = @client.cancel_order(symbol: "BTCUSDT", order_id: "123")
47
+ assert result.success?
48
+ end
49
+
50
+ def test_headers_include_api_key
51
+ headers = @client.send(:auth_headers)
52
+ assert_equal "test_key", headers[:"X-MBX-APIKEY"]
53
+ end
54
+
55
+ private
56
+
57
+ def stub_connection(method, body)
58
+ response = stub(body: body)
59
+ connection = stub
60
+ connection.stubs(method).returns(response)
61
+ @client.instance_variable_set(:@connection, connection)
62
+ end
63
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ class Honeymaker::Clients::BitvavoTest < Minitest::Test
6
+ def setup
7
+ @client = Honeymaker::Clients::Bitvavo.new(api_key: "test_key", api_secret: "test_secret")
8
+ end
9
+
10
+ def test_url
11
+ assert_equal "https://api.bitvavo.com", Honeymaker::Clients::Bitvavo::URL
12
+ end
13
+
14
+ def test_get_markets
15
+ stub_connection(:get, [{ "market" => "BTC-EUR" }])
16
+ result = @client.get_markets
17
+ assert result.success?
18
+ end
19
+
20
+ def test_get_ticker_price
21
+ stub_connection(:get, [{ "market" => "BTC-EUR", "price" => "50000" }])
22
+ result = @client.get_ticker_price
23
+ assert result.success?
24
+ end
25
+
26
+ def test_get_balance
27
+ stub_connection(:get, [{ "symbol" => "BTC", "available" => "0.5" }])
28
+ result = @client.get_balance
29
+ assert result.success?
30
+ end
31
+
32
+ def test_place_order
33
+ stub_connection(:post, { "orderId" => "123" })
34
+ result = @client.place_order(market: "BTC-EUR", side: "buy", order_type: "market", amount_quote: "100")
35
+ assert result.success?
36
+ end
37
+
38
+ def test_get_order
39
+ stub_connection(:get, { "orderId" => "123", "status" => "filled" })
40
+ result = @client.get_order(market: "BTC-EUR", order_id: "123")
41
+ assert result.success?
42
+ end
43
+
44
+ def test_cancel_order
45
+ stub_connection(:delete, { "orderId" => "123" })
46
+ result = @client.cancel_order(market: "BTC-EUR", order_id: "123")
47
+ assert result.success?
48
+ end
49
+
50
+ def test_withdraw
51
+ stub_connection(:post, { "success" => true })
52
+ result = @client.withdraw(symbol: "BTC", amount: "0.1", address: "addr")
53
+ assert result.success?
54
+ end
55
+
56
+ def test_get_assets
57
+ stub_connection(:get, [{ "symbol" => "BTC" }])
58
+ result = @client.get_assets
59
+ assert result.success?
60
+ end
61
+
62
+ def test_signed_headers_include_access_window
63
+ ts = "1234567890"
64
+ headers = @client.send(:signed_headers, ts, "payload")
65
+ assert_equal "test_key", headers[:"BITVAVO-ACCESS-KEY"]
66
+ assert_equal "10000", headers[:"BITVAVO-ACCESS-WINDOW"]
67
+ assert headers.key?(:"BITVAVO-ACCESS-SIGNATURE")
68
+ end
69
+
70
+ def test_signing_payload_format
71
+ # Verify the signing payload matches Bitvavo's expected format
72
+ sig1 = @client.send(:hmac_sha256, "test_secret", "1234567890GET/v2/balance")
73
+ sig2 = @client.send(:hmac_sha256, "test_secret", "1234567890POST/v2/order{\"market\":\"BTC-EUR\"}")
74
+ assert sig1.is_a?(String)
75
+ assert sig2.is_a?(String)
76
+ refute_equal sig1, sig2
77
+ end
78
+
79
+ private
80
+
81
+ def stub_connection(method, body)
82
+ response = stub(body: body)
83
+ connection = stub
84
+ connection.stubs(method).returns(response)
85
+ @client.instance_variable_set(:@connection, connection)
86
+ end
87
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ class Honeymaker::Clients::BybitTest < Minitest::Test
6
+ def setup
7
+ @client = Honeymaker::Clients::Bybit.new(api_key: "test_key", api_secret: "test_secret")
8
+ end
9
+
10
+ def test_url
11
+ assert_equal "https://api.bybit.com", Honeymaker::Clients::Bybit::URL
12
+ end
13
+
14
+ def test_instruments_info
15
+ stub_connection(:get, { "result" => { "list" => [{ "symbol" => "BTCUSDT" }] } })
16
+ result = @client.instruments_info(category: "spot")
17
+ assert result.success?
18
+ end
19
+
20
+ def test_tickers
21
+ stub_connection(:get, { "result" => { "list" => [{ "lastPrice" => "50000" }] } })
22
+ result = @client.tickers(category: "spot", symbol: "BTCUSDT")
23
+ assert result.success?
24
+ end
25
+
26
+ def test_wallet_balance
27
+ stub_connection(:get, { "result" => { "list" => [{ "coin" => [{ "coin" => "BTC" }] }] } })
28
+ result = @client.wallet_balance(account_type: "UNIFIED")
29
+ assert result.success?
30
+ end
31
+
32
+ def test_create_order
33
+ stub_connection(:post, { "result" => { "orderId" => "123" } })
34
+ result = @client.create_order(category: "spot", symbol: "BTCUSDT", side: "Buy", order_type: "Market", qty: "0.001")
35
+ assert result.success?
36
+ assert_equal "123", result.data["result"]["orderId"]
37
+ end
38
+
39
+ def test_get_order
40
+ stub_connection(:get, { "result" => { "list" => [{ "orderId" => "123" }] } })
41
+ result = @client.get_order(category: "spot", order_id: "123")
42
+ assert result.success?
43
+ end
44
+
45
+ def test_cancel_order
46
+ stub_connection(:post, { "result" => { "orderId" => "123" } })
47
+ result = @client.cancel_order(category: "spot", symbol: "BTCUSDT", order_id: "123")
48
+ assert result.success?
49
+ end
50
+
51
+ def test_kline
52
+ stub_connection(:get, { "result" => { "list" => [] } })
53
+ result = @client.kline(category: "spot", symbol: "BTCUSDT", interval: "60")
54
+ assert result.success?
55
+ end
56
+
57
+ def test_withdraw
58
+ stub_connection(:post, { "result" => { "id" => "w1" } })
59
+ result = @client.withdraw(coin: "BTC", chain: "BTC", address: "addr", amount: "0.1")
60
+ assert result.success?
61
+ end
62
+
63
+ def test_signed_headers_include_api_key
64
+ headers = @client.send(:signed_headers, "GET", { foo: "bar" })
65
+ assert_equal "test_key", headers[:"X-BAPI-API-KEY"]
66
+ assert headers.key?(:"X-BAPI-SIGN")
67
+ assert headers.key?(:"X-BAPI-TIMESTAMP")
68
+ end
69
+
70
+ def test_unauthenticated_client
71
+ client = Honeymaker::Clients::Bybit.new
72
+ headers = client.send(:signed_headers, "GET", {})
73
+ refute headers.key?(:"X-BAPI-SIGN")
74
+ end
75
+
76
+ private
77
+
78
+ def stub_connection(method, body)
79
+ response = stub(body: body)
80
+ connection = stub
81
+ connection.stubs(method).returns(response)
82
+ @client.instance_variable_set(:@connection, connection)
83
+ end
84
+ end
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ class Honeymaker::Clients::CoinbaseTest < Minitest::Test
6
+ def setup
7
+ # Use ECDSA key for testing
8
+ @key = OpenSSL::PKey::EC.generate("prime256v1")
9
+ @client = Honeymaker::Clients::Coinbase.new(
10
+ api_key: "test_key",
11
+ api_secret: @key.to_pem
12
+ )
13
+ end
14
+
15
+ def test_url
16
+ assert_equal "https://api.coinbase.com", Honeymaker::Clients::Coinbase::URL
17
+ end
18
+
19
+ def test_get_order
20
+ stub_connection(:get, { "order" => { "order_id" => "abc", "status" => "FILLED" } })
21
+ result = @client.get_order(order_id: "abc")
22
+ assert result.success?
23
+ assert_equal "abc", result.data["order"]["order_id"]
24
+ end
25
+
26
+ def test_create_order
27
+ stub_connection(:post, { "success" => true, "order_id" => "xyz" })
28
+ result = @client.create_order(
29
+ client_order_id: "c1", product_id: "BTC-USD",
30
+ side: "BUY", order_configuration: { market_market_ioc: { quote_size: "100" } }
31
+ )
32
+ assert result.success?
33
+ end
34
+
35
+ def test_cancel_orders
36
+ stub_connection(:post, { "results" => [{ "success" => true }] })
37
+ result = @client.cancel_orders(order_ids: ["abc"])
38
+ assert result.success?
39
+ end
40
+
41
+ def test_list_public_products
42
+ stub_connection(:get, { "products" => [{ "product_id" => "BTC-USD" }] })
43
+ result = @client.list_public_products
44
+ assert result.success?
45
+ end
46
+
47
+ def test_get_public_product
48
+ stub_connection(:get, { "product_id" => "BTC-USD" })
49
+ result = @client.get_public_product(product_id: "BTC-USD")
50
+ assert result.success?
51
+ end
52
+
53
+ def test_get_api_key_permissions
54
+ stub_connection(:get, { "can_trade" => true })
55
+ result = @client.get_api_key_permissions
56
+ assert result.success?
57
+ end
58
+
59
+ def test_list_accounts
60
+ stub_connection(:get, { "accounts" => [] })
61
+ result = @client.list_accounts
62
+ assert result.success?
63
+ end
64
+
65
+ def test_send_money
66
+ stub_connection(:post, { "data" => { "id" => "tx1" } })
67
+ result = @client.send_money(account_id: "acc1", to: "addr", amount: "0.1", currency: "BTC")
68
+ assert result.success?
69
+ end
70
+
71
+ def test_handles_api_error
72
+ connection = stub
73
+ connection.stubs(:get).raises(Faraday::ClientError.new("401", { status: 401, body: "Unauthorized" }))
74
+ @client.instance_variable_set(:@connection, connection)
75
+ result = @client.list_accounts
76
+ assert result.failure?
77
+ end
78
+
79
+ def test_ecdsa_key_detected
80
+ assert @client.send(:ecdsa_key?)
81
+ end
82
+
83
+ def test_non_ecdsa_key_not_detected
84
+ client = Honeymaker::Clients::Coinbase.new(api_key: "k", api_secret: "not-a-pem-key")
85
+ refute client.send(:ecdsa_key?)
86
+ end
87
+
88
+ def test_ed25519_returns_nil_without_rbnacl
89
+ client = Honeymaker::Clients::Coinbase.new(api_key: "k", api_secret: Base64.encode64("short"))
90
+ # rbnacl may or may not be installed; either way should not raise
91
+ result = client.send(:ed25519_signing_key)
92
+ # Returns nil if rbnacl not installed or key is invalid
93
+ assert_nil result
94
+ end
95
+
96
+ def test_unauthenticated_headers
97
+ client = Honeymaker::Clients::Coinbase.new
98
+ stub_connection_on(client, :get, { "products" => [] })
99
+ result = client.list_public_products
100
+ assert result.success?
101
+ end
102
+
103
+ private
104
+
105
+ def stub_connection(method, body)
106
+ response = stub(body: body)
107
+ connection = stub
108
+ connection.stubs(method).returns(response)
109
+ @client.instance_variable_set(:@connection, connection)
110
+ end
111
+
112
+ def stub_connection_on(client, method, body)
113
+ response = stub(body: body)
114
+ connection = stub
115
+ connection.stubs(method).returns(response)
116
+ client.instance_variable_set(:@connection, connection)
117
+ end
118
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ class Honeymaker::Clients::GeminiTest < Minitest::Test
6
+ def setup
7
+ @client = Honeymaker::Clients::Gemini.new(api_key: "test_key", api_secret: "test_secret")
8
+ end
9
+
10
+ def test_url
11
+ assert_equal "https://api.gemini.com", Honeymaker::Clients::Gemini::URL
12
+ end
13
+
14
+ def test_get_symbols
15
+ stub_connection(:get, ["btcusd", "ethusd"])
16
+ result = @client.get_symbols
17
+ assert result.success?
18
+ assert_includes result.data, "btcusd"
19
+ end
20
+
21
+ def test_get_symbol_details
22
+ stub_connection(:get, { "symbol" => "BTCUSD", "base_currency" => "BTC" })
23
+ result = @client.get_symbol_details(symbol: "btcusd")
24
+ assert result.success?
25
+ end
26
+
27
+ def test_get_ticker
28
+ stub_connection(:get, { "last" => "50000" })
29
+ result = @client.get_ticker(symbol: "btcusd")
30
+ assert result.success?
31
+ end
32
+
33
+ def test_get_balances
34
+ stub_connection(:post, [{ "currency" => "BTC", "amount" => "0.5" }])
35
+ result = @client.get_balances
36
+ assert result.success?
37
+ end
38
+
39
+ def test_new_order
40
+ stub_connection(:post, { "order_id" => "123" })
41
+ result = @client.new_order(symbol: "btcusd", amount: "0.001", price: "50000", side: "buy", type: "exchange limit")
42
+ assert result.success?
43
+ end
44
+
45
+ def test_order_status
46
+ stub_connection(:post, { "order_id" => "123", "is_live" => false })
47
+ result = @client.order_status(order_id: "123")
48
+ assert result.success?
49
+ end
50
+
51
+ def test_cancel_order
52
+ stub_connection(:post, { "order_id" => "123", "is_cancelled" => true })
53
+ result = @client.cancel_order(order_id: "123")
54
+ assert result.success?
55
+ end
56
+
57
+ def test_withdraw
58
+ stub_connection(:post, { "destination" => "addr", "amount" => "0.1" })
59
+ result = @client.withdraw(currency: "btc", address: "addr", amount: "0.1")
60
+ assert result.success?
61
+ end
62
+
63
+ private
64
+
65
+ def stub_connection(method, body)
66
+ response = stub(body: body)
67
+ connection = stub
68
+ connection.stubs(method).returns(response)
69
+ @client.instance_variable_set(:@connection, connection)
70
+ end
71
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ class HoneymakerClientRegistryTest < Minitest::Test
6
+ def test_client_returns_correct_class
7
+ client = Honeymaker.client("binance", api_key: "k", api_secret: "s")
8
+ assert_instance_of Honeymaker::Clients::Binance, client
9
+ end
10
+
11
+ def test_client_with_symbol
12
+ client = Honeymaker.client(:kraken, api_key: "k", api_secret: "s")
13
+ assert_instance_of Honeymaker::Clients::Kraken, client
14
+ end
15
+
16
+ def test_client_raises_for_unknown
17
+ assert_raises(Honeymaker::Error) { Honeymaker.client("unknown") }
18
+ end
19
+
20
+ def test_all_clients_registered
21
+ assert_equal 14, Honeymaker::CLIENTS.size
22
+ end
23
+
24
+ def test_client_passes_credentials
25
+ client = Honeymaker.client("binance", api_key: "my_key", api_secret: "my_secret")
26
+ assert_equal "my_key", client.api_key
27
+ assert_equal "my_secret", client.api_secret
28
+ end
29
+
30
+ def test_bitget_accepts_passphrase
31
+ client = Honeymaker.client("bitget", api_key: "k", api_secret: "s", passphrase: "p")
32
+ assert_equal "p", client.passphrase
33
+ end
34
+
35
+ def test_kucoin_accepts_passphrase
36
+ client = Honeymaker.client("kucoin", api_key: "k", api_secret: "s", passphrase: "p")
37
+ assert_equal "p", client.passphrase
38
+ end
39
+
40
+ def test_bitmart_accepts_memo
41
+ client = Honeymaker.client("bitmart", api_key: "k", api_secret: "s", memo: "m")
42
+ assert_equal "m", client.memo
43
+ end
44
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ class Honeymaker::Clients::HyperliquidTest < Minitest::Test
6
+ def setup
7
+ @client = Honeymaker::Clients::Hyperliquid.new
8
+ end
9
+
10
+ def test_url
11
+ assert_equal "https://api.hyperliquid.xyz", Honeymaker::Clients::Hyperliquid::URL
12
+ end
13
+
14
+ def test_spot_meta
15
+ stub_connection(:post, { "tokens" => [], "universe" => [] })
16
+ result = @client.spot_meta
17
+ assert result.success?
18
+ assert_equal [], result.data["tokens"]
19
+ end
20
+
21
+ def test_spot_meta_and_asset_ctxs
22
+ stub_connection(:post, [{ "tokens" => [] }, []])
23
+ result = @client.spot_meta_and_asset_ctxs
24
+ assert result.success?
25
+ end
26
+
27
+ def test_spot_clearinghouse_state
28
+ stub_connection(:post, { "balances" => [] })
29
+ result = @client.spot_clearinghouse_state(user: "0xabc")
30
+ assert result.success?
31
+ end
32
+
33
+ def test_order_status
34
+ stub_connection(:post, { "status" => "filled" })
35
+ result = @client.order_status(user: "0xabc", oid: 123)
36
+ assert result.success?
37
+ end
38
+
39
+ def test_open_orders
40
+ stub_connection(:post, [])
41
+ result = @client.open_orders(user: "0xabc")
42
+ assert result.success?
43
+ end
44
+
45
+ private
46
+
47
+ def stub_connection(method, body)
48
+ response = stub(body: body)
49
+ connection = stub
50
+ connection.stubs(method).returns(response)
51
+ @client.instance_variable_set(:@connection, connection)
52
+ end
53
+ end