honeymaker 0.2.0 → 0.4.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 (33) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -0
  3. data/lib/honeymaker/client.rb +22 -0
  4. data/lib/honeymaker/clients/binance.rb +157 -0
  5. data/lib/honeymaker/clients/bingx.rb +31 -0
  6. data/lib/honeymaker/clients/bitget.rb +32 -3
  7. data/lib/honeymaker/clients/bitmart.rb +29 -0
  8. data/lib/honeymaker/clients/bitrue.rb +16 -0
  9. data/lib/honeymaker/clients/bitvavo.rb +24 -0
  10. data/lib/honeymaker/clients/bybit.rb +37 -0
  11. data/lib/honeymaker/clients/coinbase.rb +35 -0
  12. data/lib/honeymaker/clients/gemini.rb +18 -0
  13. data/lib/honeymaker/clients/hyperliquid.rb +23 -0
  14. data/lib/honeymaker/clients/kraken.rb +30 -0
  15. data/lib/honeymaker/clients/kucoin.rb +41 -0
  16. data/lib/honeymaker/clients/mexc.rb +30 -0
  17. data/lib/honeymaker/version.rb +1 -1
  18. data/test/honeymaker/clients/binance_client_test.rb +64 -0
  19. data/test/honeymaker/clients/bingx_client_test.rb +18 -0
  20. data/test/honeymaker/clients/bitget_client_test.rb +25 -1
  21. data/test/honeymaker/clients/bitmart_client_test.rb +18 -0
  22. data/test/honeymaker/clients/bitrue_client_test.rb +6 -0
  23. data/test/honeymaker/clients/bitvavo_client_test.rb +18 -0
  24. data/test/honeymaker/clients/bybit_client_test.rb +24 -0
  25. data/test/honeymaker/clients/coinbase_client_test.rb +14 -0
  26. data/test/honeymaker/clients/gemini_client_test.rb +12 -0
  27. data/test/honeymaker/clients/hyperliquid_client_test.rb +12 -0
  28. data/test/honeymaker/clients/kraken_client_test.rb +14 -0
  29. data/test/honeymaker/clients/kucoin_client_test.rb +24 -0
  30. data/test/honeymaker/clients/mexc_client_test.rb +18 -0
  31. data/test/honeymaker/clients/validation_test.rb +182 -0
  32. metadata +2 -2
  33. data/honeymaker-0.1.0.gem +0 -0
@@ -59,6 +59,37 @@ module Honeymaker
59
59
  get_signed("/api/v1/withdrawals/quotas", { currency: currency, chain: chain })
60
60
  end
61
61
 
62
+ def get_fills(order_id: nil, symbol: nil, side: nil, type: nil, start_at: nil, end_at: nil,
63
+ trade_type: nil, limit: nil, current_page: nil)
64
+ get_signed("/api/v1/fills", {
65
+ orderId: order_id, symbol: symbol, side: side, type: type,
66
+ startAt: start_at, endAt: end_at, tradeType: trade_type,
67
+ pageSize: limit, currentPage: current_page
68
+ })
69
+ end
70
+
71
+ def get_historical_orders(symbol: nil, side: nil, start_at: nil, end_at: nil, current_page: nil, page_size: nil)
72
+ get_signed("/api/v1/hist-orders", {
73
+ symbol: symbol, side: side,
74
+ startAt: start_at, endAt: end_at,
75
+ currentPage: current_page, pageSize: page_size
76
+ })
77
+ end
78
+
79
+ def get_deposits(currency: nil, start_at: nil, end_at: nil, status: nil, current_page: nil, page_size: nil)
80
+ get_signed("/api/v1/deposits", {
81
+ currency: currency, startAt: start_at, endAt: end_at,
82
+ status: status, currentPage: current_page, pageSize: page_size
83
+ })
84
+ end
85
+
86
+ def get_withdrawals(currency: nil, start_at: nil, end_at: nil, status: nil, current_page: nil, page_size: nil)
87
+ get_signed("/api/v1/withdrawals", {
88
+ currency: currency, startAt: start_at, endAt: end_at,
89
+ status: status, currentPage: current_page, pageSize: page_size
90
+ })
91
+ end
92
+
62
93
  def withdraw(currency:, address:, amount:, chain: nil, memo: nil)
63
94
  post_signed("/api/v1/withdrawals", {
64
95
  currency: currency, address: address, amount: amount,
@@ -68,6 +99,16 @@ module Honeymaker
68
99
 
69
100
  private
70
101
 
102
+ def validate_trading_credentials
103
+ result = get_accounts(type: "trade")
104
+ return Result::Failure.new("Invalid trading credentials") if result.failure?
105
+ result.data["code"] == "200000" ? Result::Success.new(true) : Result::Failure.new("Invalid trading credentials")
106
+ end
107
+
108
+ def validate_read_credentials
109
+ validate_trading_credentials
110
+ end
111
+
71
112
  def get_public(path, params = {})
72
113
  with_rescue do
73
114
  response = connection.get do |req|
@@ -58,6 +58,27 @@ module Honeymaker
58
58
  })
59
59
  end
60
60
 
61
+ def account_trade_list(symbol:, order_id: nil, start_time: nil, end_time: nil, limit: 500, recv_window: 5000)
62
+ get_signed("/api/v3/myTrades", {
63
+ symbol: symbol, orderId: order_id,
64
+ startTime: start_time, endTime: end_time, limit: limit, recvWindow: recv_window
65
+ })
66
+ end
67
+
68
+ def deposit_history(coin: nil, status: nil, start_time: nil, end_time: nil, limit: 1000, recv_window: 5000)
69
+ get_signed("/api/v3/capital/deposit/hisrec", {
70
+ coin: coin, status: status,
71
+ startTime: start_time, endTime: end_time, limit: limit, recvWindow: recv_window
72
+ })
73
+ end
74
+
75
+ def withdraw_history(coin: nil, status: nil, start_time: nil, end_time: nil, limit: 1000, recv_window: 5000)
76
+ get_signed("/api/v3/capital/withdraw/history", {
77
+ coin: coin, status: status,
78
+ startTime: start_time, endTime: end_time, limit: limit, recvWindow: recv_window
79
+ })
80
+ end
81
+
61
82
  def get_withdraw_addresses(recv_window: 5000)
62
83
  get_signed("/api/v3/capital/withdraw/address", { recvWindow: recv_window })
63
84
  end
@@ -71,6 +92,15 @@ module Honeymaker
71
92
 
72
93
  private
73
94
 
95
+ def validate_trading_credentials
96
+ result = account_information
97
+ result.success? ? Result::Success.new(true) : Result::Failure.new("Invalid trading credentials")
98
+ end
99
+
100
+ def validate_read_credentials
101
+ validate_trading_credentials
102
+ end
103
+
74
104
  def get_public(path, params = {})
75
105
  with_rescue do
76
106
  response = connection.get do |req|
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Honeymaker
4
- VERSION = "0.2.0"
4
+ VERSION = "0.4.0"
5
5
  end
@@ -44,6 +44,70 @@ class Honeymaker::Clients::BinanceTest < Minitest::Test
44
44
  assert result.success?
45
45
  end
46
46
 
47
+ def test_account_trade_list
48
+ stub_connection(:get, [{ "symbol" => "BTCUSDT", "id" => 123, "price" => "50000" }])
49
+ result = @client.account_trade_list(symbol: "BTCUSDT")
50
+ assert result.success?
51
+ assert_equal "BTCUSDT", result.data.first["symbol"]
52
+ end
53
+
54
+ def test_deposit_history
55
+ stub_connection(:get, [{ "coin" => "BTC", "amount" => "0.5", "status" => 1 }])
56
+ result = @client.deposit_history
57
+ assert result.success?
58
+ assert_equal "BTC", result.data.first["coin"]
59
+ end
60
+
61
+ def test_withdraw_history
62
+ stub_connection(:get, [{ "coin" => "ETH", "amount" => "1.0", "status" => 6 }])
63
+ result = @client.withdraw_history
64
+ assert result.success?
65
+ assert_equal "ETH", result.data.first["coin"]
66
+ end
67
+
68
+ def test_convert_trade_flow
69
+ stub_connection(:get, { "list" => [{ "quoteId" => "q1", "fromAsset" => "BTC", "toAsset" => "USDT" }] })
70
+ result = @client.convert_trade_flow(start_time: 1710936000000, end_time: 1711022400000)
71
+ assert result.success?
72
+ assert_equal "q1", result.data["list"].first["quoteId"]
73
+ end
74
+
75
+ def test_fiat_payments
76
+ stub_connection(:get, { "data" => [{ "orderNo" => "f1", "cryptoCurrency" => "BTC" }] })
77
+ result = @client.fiat_payments(transaction_type: 0)
78
+ assert result.success?
79
+ end
80
+
81
+ def test_fiat_orders
82
+ stub_connection(:get, { "data" => [{ "orderNo" => "fo1", "fiatCurrency" => "USD" }] })
83
+ result = @client.fiat_orders(transaction_type: 0)
84
+ assert result.success?
85
+ end
86
+
87
+ def test_dust_log
88
+ stub_connection(:get, { "total" => 1, "userAssetDribblets" => [{ "totalTransferedAmount" => "0.001" }] })
89
+ result = @client.dust_log
90
+ assert result.success?
91
+ end
92
+
93
+ def test_asset_dividend
94
+ stub_connection(:get, { "rows" => [{ "asset" => "BNB", "amount" => "0.1" }], "total" => 1 })
95
+ result = @client.asset_dividend
96
+ assert result.success?
97
+ end
98
+
99
+ def test_simple_earn_flexible_rewards
100
+ stub_connection(:get, { "rows" => [{ "asset" => "USDT", "rewards" => "0.5" }], "total" => 1 })
101
+ result = @client.simple_earn_flexible_rewards
102
+ assert result.success?
103
+ end
104
+
105
+ def test_simple_earn_locked_rewards
106
+ stub_connection(:get, { "rows" => [{ "asset" => "ETH", "rewards" => "0.01" }], "total" => 1 })
107
+ result = @client.simple_earn_locked_rewards
108
+ assert result.success?
109
+ end
110
+
47
111
  def test_handles_api_error
48
112
  connection = stub
49
113
  connection.stubs(:get).raises(Faraday::ServerError.new("500", { status: 500, body: "Server Error" }))
@@ -53,6 +53,24 @@ class Honeymaker::Clients::BingXTest < Minitest::Test
53
53
  assert result.success?
54
54
  end
55
55
 
56
+ def test_get_trade_fills
57
+ stub_connection(:get, { "data" => [{ "tradeId" => "t1" }] })
58
+ result = @client.get_trade_fills(symbol: "BTC-USDT")
59
+ assert result.success?
60
+ end
61
+
62
+ def test_deposit_history
63
+ stub_connection(:get, [{ "coin" => "BTC" }])
64
+ result = @client.deposit_history
65
+ assert result.success?
66
+ end
67
+
68
+ def test_withdraw_history
69
+ stub_connection(:get, [{ "coin" => "ETH" }])
70
+ result = @client.withdraw_history
71
+ assert result.success?
72
+ end
73
+
56
74
  private
57
75
 
58
76
  def stub_connection(method, body)
@@ -41,6 +41,12 @@ class Honeymaker::Clients::BitgetTest < Minitest::Test
41
41
  assert result.success?
42
42
  end
43
43
 
44
+ def test_place_order_with_quote_size
45
+ stub_connection(:post, { "data" => { "orderId" => "456" } })
46
+ result = @client.place_order(symbol: "BTCUSDT", side: "buy", order_type: "market", quote_size: "100")
47
+ assert result.success?
48
+ end
49
+
44
50
  def test_get_order
45
51
  stub_connection(:get, { "data" => [{ "orderId" => "123" }] })
46
52
  result = @client.get_order(order_id: "123")
@@ -61,7 +67,25 @@ class Honeymaker::Clients::BitgetTest < Minitest::Test
61
67
 
62
68
  def test_withdraw
63
69
  stub_connection(:post, { "data" => { "orderId" => "w1" } })
64
- result = @client.withdraw(coin: "BTC", transfer_type: "on_chain", address: "addr", size: "0.1")
70
+ result = @client.withdraw(coin: "BTC", address: "addr", size: "0.1")
71
+ assert result.success?
72
+ end
73
+
74
+ def test_get_fills
75
+ stub_connection(:get, { "data" => [{ "tradeId" => "t1" }] })
76
+ result = @client.get_fills(symbol: "BTCUSDT")
77
+ assert result.success?
78
+ end
79
+
80
+ def test_deposit_list
81
+ stub_connection(:get, { "data" => [{ "coin" => "BTC" }] })
82
+ result = @client.deposit_list
83
+ assert result.success?
84
+ end
85
+
86
+ def test_withdrawal_list
87
+ stub_connection(:get, { "data" => [{ "coin" => "ETH" }] })
88
+ result = @client.withdrawal_list
65
89
  assert result.success?
66
90
  end
67
91
 
@@ -59,6 +59,24 @@ class Honeymaker::Clients::BitMartTest < Minitest::Test
59
59
  assert result.success?
60
60
  end
61
61
 
62
+ def test_get_trades
63
+ stub_connection(:get, { "data" => [{ "tradeId" => "t1" }] })
64
+ result = @client.get_trades(symbol: "BTC_USDT")
65
+ assert result.success?
66
+ end
67
+
68
+ def test_deposit_list
69
+ stub_connection(:get, { "data" => { "records" => [{ "currency" => "BTC" }] } })
70
+ result = @client.deposit_list
71
+ assert result.success?
72
+ end
73
+
74
+ def test_withdraw_list
75
+ stub_connection(:get, { "data" => { "records" => [{ "currency" => "ETH" }] } })
76
+ result = @client.withdraw_list
77
+ assert result.success?
78
+ end
79
+
62
80
  def test_signed_headers_include_memo_in_signature
63
81
  ts = "1234567890"
64
82
  pre_sign = "#{ts}#test_memo#body"
@@ -47,6 +47,12 @@ class Honeymaker::Clients::BitrueTest < Minitest::Test
47
47
  assert result.success?
48
48
  end
49
49
 
50
+ def test_account_trade_list
51
+ stub_connection(:get, [{ "symbol" => "BTCUSDT", "id" => 1 }])
52
+ result = @client.account_trade_list(symbol: "BTCUSDT")
53
+ assert result.success?
54
+ end
55
+
50
56
  def test_headers_include_api_key
51
57
  headers = @client.send(:auth_headers)
52
58
  assert_equal "test_key", headers[:"X-MBX-APIKEY"]
@@ -59,6 +59,24 @@ class Honeymaker::Clients::BitvavoTest < Minitest::Test
59
59
  assert result.success?
60
60
  end
61
61
 
62
+ def test_get_trades
63
+ stub_connection(:get, [{ "id" => "t1", "side" => "buy" }])
64
+ result = @client.get_trades(market: "BTC-EUR")
65
+ assert result.success?
66
+ end
67
+
68
+ def test_get_deposit_history
69
+ stub_connection(:get, [{ "symbol" => "BTC", "amount" => "1.0" }])
70
+ result = @client.get_deposit_history
71
+ assert result.success?
72
+ end
73
+
74
+ def test_get_withdrawal_history
75
+ stub_connection(:get, [{ "symbol" => "ETH", "amount" => "2.0" }])
76
+ result = @client.get_withdrawal_history
77
+ assert result.success?
78
+ end
79
+
62
80
  def test_signed_headers_include_access_window
63
81
  ts = "1234567890"
64
82
  headers = @client.send(:signed_headers, ts, "payload")
@@ -60,6 +60,30 @@ class Honeymaker::Clients::BybitTest < Minitest::Test
60
60
  assert result.success?
61
61
  end
62
62
 
63
+ def test_transaction_log
64
+ stub_connection(:get, { "result" => { "list" => [{ "transactionTime" => "1710936000000" }] } })
65
+ result = @client.transaction_log
66
+ assert result.success?
67
+ end
68
+
69
+ def test_execution_list
70
+ stub_connection(:get, { "result" => { "list" => [{ "execId" => "e1" }] } })
71
+ result = @client.execution_list(category: "spot")
72
+ assert result.success?
73
+ end
74
+
75
+ def test_deposit_records
76
+ stub_connection(:get, { "result" => { "rows" => [{ "coin" => "BTC" }] } })
77
+ result = @client.deposit_records
78
+ assert result.success?
79
+ end
80
+
81
+ def test_withdraw_records
82
+ stub_connection(:get, { "result" => { "rows" => [{ "coin" => "ETH" }] } })
83
+ result = @client.withdraw_records
84
+ assert result.success?
85
+ end
86
+
63
87
  def test_signed_headers_include_api_key
64
88
  headers = @client.send(:signed_headers, "GET", { foo: "bar" })
65
89
  assert_equal "test_key", headers[:"X-BAPI-API-KEY"]
@@ -68,6 +68,20 @@ class Honeymaker::Clients::CoinbaseTest < Minitest::Test
68
68
  assert result.success?
69
69
  end
70
70
 
71
+ def test_list_fills
72
+ stub_connection(:get, { "fills" => [{ "trade_id" => "f1", "product_id" => "BTC-USD" }] })
73
+ result = @client.list_fills(product_id: "BTC-USD")
74
+ assert result.success?
75
+ assert_equal "f1", result.data["fills"].first["trade_id"]
76
+ end
77
+
78
+ def test_list_transactions
79
+ stub_connection(:get, { "data" => [{ "id" => "tx1", "type" => "send" }] })
80
+ result = @client.list_transactions(account_id: "acc1")
81
+ assert result.success?
82
+ assert_equal "tx1", result.data["data"].first["id"]
83
+ end
84
+
71
85
  def test_handles_api_error
72
86
  connection = stub
73
87
  connection.stubs(:get).raises(Faraday::ClientError.new("401", { status: 401, body: "Unauthorized" }))
@@ -60,6 +60,18 @@ class Honeymaker::Clients::GeminiTest < Minitest::Test
60
60
  assert result.success?
61
61
  end
62
62
 
63
+ def test_get_my_trades
64
+ stub_connection(:post, [{ "tid" => 123, "price" => "50000" }])
65
+ result = @client.get_my_trades(symbol: "btcusd")
66
+ assert result.success?
67
+ end
68
+
69
+ def test_get_transfers
70
+ stub_connection(:post, [{ "type" => "Deposit", "currency" => "BTC" }])
71
+ result = @client.get_transfers
72
+ assert result.success?
73
+ end
74
+
63
75
  private
64
76
 
65
77
  def stub_connection(method, body)
@@ -42,6 +42,18 @@ class Honeymaker::Clients::HyperliquidTest < Minitest::Test
42
42
  assert result.success?
43
43
  end
44
44
 
45
+ def test_user_fills
46
+ stub_connection(:post, [{ "oid" => 1, "side" => "B" }])
47
+ result = @client.user_fills(user: "0xabc")
48
+ assert result.success?
49
+ end
50
+
51
+ def test_user_fills_by_time
52
+ stub_connection(:post, [{ "oid" => 1, "side" => "B" }])
53
+ result = @client.user_fills_by_time(user: "0xabc", start_time: 1710936000000)
54
+ assert result.success?
55
+ end
56
+
45
57
  private
46
58
 
47
59
  def stub_connection(method, body)
@@ -46,6 +46,20 @@ class Honeymaker::Clients::KrakenTest < Minitest::Test
46
46
  assert result.success?
47
47
  end
48
48
 
49
+ def test_get_trades_history
50
+ stub_connection(:post, { "error" => [], "result" => { "trades" => { "T1" => { "pair" => "XBTUSDT" } }, "count" => 1 } })
51
+ result = @client.get_trades_history
52
+ assert result.success?
53
+ assert result.data["result"]["trades"].key?("T1")
54
+ end
55
+
56
+ def test_get_ledgers
57
+ stub_connection(:post, { "error" => [], "result" => { "ledger" => { "L1" => { "type" => "trade" } }, "count" => 1 } })
58
+ result = @client.get_ledgers
59
+ assert result.success?
60
+ assert result.data["result"]["ledger"].key?("L1")
61
+ end
62
+
49
63
  def test_private_headers_produce_signature
50
64
  headers = @client.send(:private_headers, "/0/private/Balance", "nonce=12345")
51
65
  assert headers.key?(:"API-Key")
@@ -59,6 +59,30 @@ class Honeymaker::Clients::KucoinTest < Minitest::Test
59
59
  assert result.success?
60
60
  end
61
61
 
62
+ def test_get_historical_orders
63
+ stub_connection(:get, { "data" => { "items" => [{ "id" => "ho1", "symbol" => "BTC-USDT" }] } })
64
+ result = @client.get_historical_orders
65
+ assert result.success?
66
+ end
67
+
68
+ def test_get_fills
69
+ stub_connection(:get, { "data" => { "items" => [{ "tradeId" => "t1" }] } })
70
+ result = @client.get_fills(symbol: "BTC-USDT")
71
+ assert result.success?
72
+ end
73
+
74
+ def test_get_deposits
75
+ stub_connection(:get, { "data" => { "items" => [{ "currency" => "BTC" }] } })
76
+ result = @client.get_deposits
77
+ assert result.success?
78
+ end
79
+
80
+ def test_get_withdrawals
81
+ stub_connection(:get, { "data" => { "items" => [{ "currency" => "ETH" }] } })
82
+ result = @client.get_withdrawals
83
+ assert result.success?
84
+ end
85
+
62
86
  def test_signed_headers_include_passphrase_and_version
63
87
  ts = "1234567890"
64
88
  headers = @client.send(:signed_headers, ts, "payload")
@@ -53,6 +53,24 @@ class Honeymaker::Clients::MexcTest < Minitest::Test
53
53
  assert result.success?
54
54
  end
55
55
 
56
+ def test_account_trade_list
57
+ stub_connection(:get, [{ "symbol" => "BTCUSDT", "id" => 1 }])
58
+ result = @client.account_trade_list(symbol: "BTCUSDT")
59
+ assert result.success?
60
+ end
61
+
62
+ def test_deposit_history
63
+ stub_connection(:get, [{ "coin" => "BTC" }])
64
+ result = @client.deposit_history
65
+ assert result.success?
66
+ end
67
+
68
+ def test_withdraw_history
69
+ stub_connection(:get, [{ "coin" => "ETH" }])
70
+ result = @client.withdraw_history
71
+ assert result.success?
72
+ end
73
+
56
74
  def test_headers_include_api_key
57
75
  headers = @client.send(:headers)
58
76
  assert_equal "test_key", headers[:"X-MEXC-APIKEY"]
@@ -0,0 +1,182 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+
5
+ class ValidationTest < Minitest::Test
6
+ def test_validate_without_credentials
7
+ client = Honeymaker::Client.new
8
+ result = client.validate(:trading)
9
+ assert result.failure?
10
+ assert_includes result.errors, "No credentials provided"
11
+ end
12
+
13
+ def test_validate_unknown_type
14
+ client = Honeymaker::Client.new(api_key: "k", api_secret: "s")
15
+ assert_raises(Honeymaker::Error) { client.validate(:unknown) }
16
+ end
17
+
18
+ def test_validate_rescues_errors
19
+ client = Honeymaker::Client.new(api_key: "k", api_secret: "s")
20
+ client.define_singleton_method(:validate_trading_credentials) { raise "boom" }
21
+ result = client.validate(:trading)
22
+ assert result.failure?
23
+ assert_includes result.errors, "boom"
24
+ end
25
+
26
+ # Binance
27
+ def test_binance_validate_trading_success
28
+ client = Honeymaker::Clients::Binance.new(api_key: "k", api_secret: "s")
29
+ # cancel_order returns error code -2011 = valid key
30
+ stub_connection(client, :delete, { "code" => -2011, "msg" => "Unknown order" })
31
+ result = client.validate(:trading)
32
+ assert result.success?
33
+ end
34
+
35
+ def test_binance_validate_trading_failure
36
+ client = Honeymaker::Clients::Binance.new(api_key: "k", api_secret: "s")
37
+ stub_connection(client, :delete, { "code" => -2015, "msg" => "Invalid API-key" })
38
+ result = client.validate(:trading)
39
+ assert result.failure?
40
+ end
41
+
42
+ def test_binance_validate_read
43
+ client = Honeymaker::Clients::Binance.new(api_key: "k", api_secret: "s")
44
+ stub_connection(client, :get, { "ipRestrict" => true })
45
+ result = client.validate(:read)
46
+ assert result.success?
47
+ end
48
+
49
+ # Kraken
50
+ def test_kraken_validate_trading_success
51
+ client = Honeymaker::Clients::Kraken.new(api_key: "k", api_secret: Base64.strict_encode64("s" * 32))
52
+ stub_connection(client, :post, { "error" => [], "result" => { "XXBT" => "0.5" } })
53
+ result = client.validate(:trading)
54
+ assert result.success?
55
+ end
56
+
57
+ def test_kraken_validate_trading_failure
58
+ client = Honeymaker::Clients::Kraken.new(api_key: "k", api_secret: Base64.strict_encode64("s" * 32))
59
+ stub_connection(client, :post, { "error" => ["EAPI:Invalid key"], "result" => {} })
60
+ result = client.validate(:trading)
61
+ assert result.failure?
62
+ end
63
+
64
+ # Coinbase
65
+ def test_coinbase_validate_trading_success
66
+ key = OpenSSL::PKey::EC.generate("prime256v1")
67
+ client = Honeymaker::Clients::Coinbase.new(api_key: "k", api_secret: key.to_pem)
68
+ stub_connection(client, :get, { "accounts" => [] })
69
+ result = client.validate(:trading)
70
+ assert result.success?
71
+ end
72
+
73
+ # Bybit
74
+ def test_bybit_validate_trading_success
75
+ client = Honeymaker::Clients::Bybit.new(api_key: "k", api_secret: "s")
76
+ stub_connection(client, :get, { "retCode" => 0, "result" => {} })
77
+ result = client.validate(:trading)
78
+ assert result.success?
79
+ end
80
+
81
+ def test_bybit_validate_trading_failure
82
+ client = Honeymaker::Clients::Bybit.new(api_key: "k", api_secret: "s")
83
+ stub_connection(client, :get, { "retCode" => 10003, "retMsg" => "Invalid apikey" })
84
+ result = client.validate(:trading)
85
+ assert result.failure?
86
+ end
87
+
88
+ # MEXC
89
+ def test_mexc_validate_trading_success
90
+ client = Honeymaker::Clients::Mexc.new(api_key: "k", api_secret: "s")
91
+ stub_connection(client, :get, { "balances" => [] })
92
+ result = client.validate(:trading)
93
+ assert result.success?
94
+ end
95
+
96
+ # Bitget
97
+ def test_bitget_validate_trading_success
98
+ client = Honeymaker::Clients::Bitget.new(api_key: "k", api_secret: "s", passphrase: "p")
99
+ stub_connection(client, :get, { "code" => "00000", "data" => [] })
100
+ result = client.validate(:trading)
101
+ assert result.success?
102
+ end
103
+
104
+ def test_bitget_validate_trading_failure
105
+ client = Honeymaker::Clients::Bitget.new(api_key: "k", api_secret: "s", passphrase: "p")
106
+ stub_connection(client, :get, { "code" => "40014", "msg" => "Invalid ApiKey" })
107
+ result = client.validate(:trading)
108
+ assert result.failure?
109
+ end
110
+
111
+ # KuCoin
112
+ def test_kucoin_validate_trading_success
113
+ client = Honeymaker::Clients::Kucoin.new(api_key: "k", api_secret: "s", passphrase: "p")
114
+ stub_connection(client, :get, { "code" => "200000", "data" => [] })
115
+ result = client.validate(:trading)
116
+ assert result.success?
117
+ end
118
+
119
+ # Bitvavo
120
+ def test_bitvavo_validate_trading_success
121
+ client = Honeymaker::Clients::Bitvavo.new(api_key: "k", api_secret: "s")
122
+ stub_connection(client, :get, [{ "symbol" => "BTC", "available" => "0.5" }])
123
+ result = client.validate(:trading)
124
+ assert result.success?
125
+ end
126
+
127
+ # Gemini
128
+ def test_gemini_validate_trading_success
129
+ client = Honeymaker::Clients::Gemini.new(api_key: "k", api_secret: "s")
130
+ stub_connection(client, :post, [{ "currency" => "BTC", "amount" => "0.5" }])
131
+ result = client.validate(:trading)
132
+ assert result.success?
133
+ end
134
+
135
+ # BingX
136
+ def test_bingx_validate_trading_success
137
+ client = Honeymaker::Clients::BingX.new(api_key: "k", api_secret: "s")
138
+ stub_connection(client, :get, { "code" => 0, "data" => {} })
139
+ result = client.validate(:trading)
140
+ assert result.success?
141
+ end
142
+
143
+ # Bitrue
144
+ def test_bitrue_validate_trading_success
145
+ client = Honeymaker::Clients::Bitrue.new(api_key: "k", api_secret: "s")
146
+ stub_connection(client, :get, { "balances" => [] })
147
+ result = client.validate(:trading)
148
+ assert result.success?
149
+ end
150
+
151
+ # BitMart
152
+ def test_bitmart_validate_trading_success
153
+ client = Honeymaker::Clients::BitMart.new(api_key: "k", api_secret: "s", memo: "m")
154
+ stub_connection(client, :get, { "code" => 1000, "data" => {} })
155
+ result = client.validate(:trading)
156
+ assert result.success?
157
+ end
158
+
159
+ def test_bitmart_validate_trading_failure
160
+ client = Honeymaker::Clients::BitMart.new(api_key: "k", api_secret: "s", memo: "m")
161
+ stub_connection(client, :get, { "code" => 30004, "message" => "Unauthorized" })
162
+ result = client.validate(:trading)
163
+ assert result.failure?
164
+ end
165
+
166
+ # Hyperliquid
167
+ def test_hyperliquid_validate_trading_success
168
+ client = Honeymaker::Clients::Hyperliquid.new(api_key: "0xabc", api_secret: "s")
169
+ stub_connection(client, :post, [])
170
+ result = client.validate(:trading)
171
+ assert result.success?
172
+ end
173
+
174
+ private
175
+
176
+ def stub_connection(client, method, body)
177
+ response = stub(body: body)
178
+ connection = stub
179
+ connection.stubs(method).returns(response)
180
+ client.instance_variable_set(:@connection, connection)
181
+ end
182
+ end