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.
- checksums.yaml +4 -4
- data/honeymaker-0.1.0.gem +0 -0
- data/lib/honeymaker/client.rb +74 -0
- data/lib/honeymaker/clients/binance.rb +240 -0
- data/lib/honeymaker/clients/binance_us.rb +9 -0
- data/lib/honeymaker/clients/bingx.rb +105 -0
- data/lib/honeymaker/clients/bitget.rb +128 -0
- data/lib/honeymaker/clients/bitmart.rb +117 -0
- data/lib/honeymaker/clients/bitrue.rb +114 -0
- data/lib/honeymaker/clients/bitvavo.rb +136 -0
- data/lib/honeymaker/clients/bybit.rb +136 -0
- data/lib/honeymaker/clients/coinbase.rb +184 -0
- data/lib/honeymaker/clients/gemini.rb +81 -0
- data/lib/honeymaker/clients/hyperliquid.rb +42 -0
- data/lib/honeymaker/clients/kraken.rb +132 -0
- data/lib/honeymaker/clients/kucoin.rb +147 -0
- data/lib/honeymaker/clients/mexc.rb +136 -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 +80 -0
- data/test/honeymaker/clients/binance_us_client_test.rb +25 -0
- data/test/honeymaker/clients/bingx_client_test.rb +64 -0
- data/test/honeymaker/clients/bitget_client_test.rb +85 -0
- data/test/honeymaker/clients/bitmart_client_test.rb +78 -0
- data/test/honeymaker/clients/bitrue_client_test.rb +63 -0
- data/test/honeymaker/clients/bitvavo_client_test.rb +87 -0
- data/test/honeymaker/clients/bybit_client_test.rb +84 -0
- data/test/honeymaker/clients/coinbase_client_test.rb +118 -0
- data/test/honeymaker/clients/gemini_client_test.rb +71 -0
- data/test/honeymaker/clients/honeymaker_client_registry_test.rb +44 -0
- data/test/honeymaker/clients/hyperliquid_client_test.rb +53 -0
- data/test/honeymaker/clients/kraken_client_test.rb +70 -0
- data/test/honeymaker/clients/kucoin_client_test.rb +88 -0
- data/test/honeymaker/clients/mexc_client_test.rb +75 -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,70 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
class Honeymaker::Clients::KrakenTest < Minitest::Test
|
|
6
|
+
def setup
|
|
7
|
+
@client = Honeymaker::Clients::Kraken.new(
|
|
8
|
+
api_key: "test_key",
|
|
9
|
+
api_secret: Base64.strict_encode64("test_secret_key_1234567890123456")
|
|
10
|
+
)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def test_url
|
|
14
|
+
assert_equal "https://api.kraken.com", Honeymaker::Clients::Kraken::URL
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def test_get_tradable_asset_pairs
|
|
18
|
+
stub_connection(:get, { "error" => [], "result" => { "XBTUSDT" => { "altname" => "XBTUSDT" } } })
|
|
19
|
+
result = @client.get_tradable_asset_pairs
|
|
20
|
+
assert result.success?
|
|
21
|
+
assert result.data["result"].key?("XBTUSDT")
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def test_get_ticker_information
|
|
25
|
+
stub_connection(:get, { "error" => [], "result" => { "XBTUSDT" => { "a" => ["50000"] } } })
|
|
26
|
+
result = @client.get_ticker_information(pair: "XBTUSDT")
|
|
27
|
+
assert result.success?
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def test_add_order
|
|
31
|
+
stub_connection(:post, { "error" => [], "result" => { "txid" => ["ORDER-123"] } })
|
|
32
|
+
result = @client.add_order(ordertype: "market", type: "buy", volume: "0.001", pair: "XBTUSDT")
|
|
33
|
+
assert result.success?
|
|
34
|
+
assert_equal ["ORDER-123"], result.data["result"]["txid"]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def test_cancel_order
|
|
38
|
+
stub_connection(:post, { "error" => [], "result" => { "count" => 1 } })
|
|
39
|
+
result = @client.cancel_order(txid: "ORDER-123")
|
|
40
|
+
assert result.success?
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def test_get_extended_balance
|
|
44
|
+
stub_connection(:post, { "error" => [], "result" => { "XXBT" => { "balance" => "0.5" } } })
|
|
45
|
+
result = @client.get_extended_balance
|
|
46
|
+
assert result.success?
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def test_private_headers_produce_signature
|
|
50
|
+
headers = @client.send(:private_headers, "/0/private/Balance", "nonce=12345")
|
|
51
|
+
assert headers.key?(:"API-Key")
|
|
52
|
+
assert headers.key?(:"API-Sign")
|
|
53
|
+
assert_equal "test_key", headers[:"API-Key"]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def test_public_headers_no_auth
|
|
57
|
+
client = Honeymaker::Clients::Kraken.new
|
|
58
|
+
headers = client.send(:public_headers)
|
|
59
|
+
refute headers.key?(:"API-Key")
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def stub_connection(method, body)
|
|
65
|
+
response = stub(body: body)
|
|
66
|
+
connection = stub
|
|
67
|
+
connection.stubs(method).returns(response)
|
|
68
|
+
@client.instance_variable_set(:@connection, connection)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
class Honeymaker::Clients::KucoinTest < Minitest::Test
|
|
6
|
+
def setup
|
|
7
|
+
@client = Honeymaker::Clients::Kucoin.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.kucoin.com", Honeymaker::Clients::Kucoin::URL
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def test_accepts_passphrase
|
|
17
|
+
assert_equal "test_pass", @client.passphrase
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def test_get_symbols
|
|
21
|
+
stub_connection(:get, { "data" => [{ "symbol" => "BTC-USDT" }] })
|
|
22
|
+
result = @client.get_symbols
|
|
23
|
+
assert result.success?
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def test_get_all_tickers
|
|
27
|
+
stub_connection(:get, { "data" => { "ticker" => [] } })
|
|
28
|
+
result = @client.get_all_tickers
|
|
29
|
+
assert result.success?
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def test_get_accounts
|
|
33
|
+
stub_connection(:get, { "data" => [{ "currency" => "BTC" }] })
|
|
34
|
+
result = @client.get_accounts
|
|
35
|
+
assert result.success?
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def test_place_order
|
|
39
|
+
stub_connection(:post, { "data" => { "orderId" => "123" } })
|
|
40
|
+
result = @client.place_order(client_oid: "c1", side: "buy", symbol: "BTC-USDT", type: "market", funds: "100")
|
|
41
|
+
assert result.success?
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def test_get_order
|
|
45
|
+
stub_connection(:get, { "data" => { "id" => "123", "isActive" => false } })
|
|
46
|
+
result = @client.get_order(order_id: "123")
|
|
47
|
+
assert result.success?
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def test_cancel_order
|
|
51
|
+
stub_connection(:delete, { "data" => { "cancelledOrderIds" => ["123"] } })
|
|
52
|
+
result = @client.cancel_order(order_id: "123")
|
|
53
|
+
assert result.success?
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def test_withdraw
|
|
57
|
+
stub_connection(:post, { "data" => { "withdrawalId" => "w1" } })
|
|
58
|
+
result = @client.withdraw(currency: "BTC", address: "addr", amount: "0.1")
|
|
59
|
+
assert result.success?
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def test_signed_headers_include_passphrase_and_version
|
|
63
|
+
ts = "1234567890"
|
|
64
|
+
headers = @client.send(:signed_headers, ts, "payload")
|
|
65
|
+
assert_equal "test_key", headers[:"KC-API-KEY"]
|
|
66
|
+
assert_equal "2", headers[:"KC-API-KEY-VERSION"]
|
|
67
|
+
assert headers.key?(:"KC-API-SIGN")
|
|
68
|
+
assert headers.key?(:"KC-API-PASSPHRASE")
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def test_passphrase_is_signed
|
|
72
|
+
ts = "1234567890"
|
|
73
|
+
headers = @client.send(:signed_headers, ts, "payload")
|
|
74
|
+
# KuCoin v2 signs the passphrase with the secret
|
|
75
|
+
raw_passphrase = "test_pass"
|
|
76
|
+
expected = Base64.strict_encode64(OpenSSL::HMAC.digest("sha256", "test_secret", raw_passphrase))
|
|
77
|
+
assert_equal expected, headers[:"KC-API-PASSPHRASE"]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
private
|
|
81
|
+
|
|
82
|
+
def stub_connection(method, body)
|
|
83
|
+
response = stub(body: body)
|
|
84
|
+
connection = stub
|
|
85
|
+
connection.stubs(method).returns(response)
|
|
86
|
+
@client.instance_variable_set(:@connection, connection)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
|
|
5
|
+
class Honeymaker::Clients::MexcTest < Minitest::Test
|
|
6
|
+
def setup
|
|
7
|
+
@client = Honeymaker::Clients::Mexc.new(api_key: "test_key", api_secret: "test_secret")
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def test_url
|
|
11
|
+
assert_equal "https://api.mexc.com", Honeymaker::Clients::Mexc::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_withdraw
|
|
51
|
+
stub_connection(:post, { "id" => "w1" })
|
|
52
|
+
result = @client.withdraw(coin: "BTC", address: "addr", amount: "0.1")
|
|
53
|
+
assert result.success?
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def test_headers_include_api_key
|
|
57
|
+
headers = @client.send(:headers)
|
|
58
|
+
assert_equal "test_key", headers[:"X-MEXC-APIKEY"]
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def test_sign_params
|
|
62
|
+
sig = @client.send(:sign_params, { symbol: "BTCUSDT", timestamp: 1234567890 })
|
|
63
|
+
assert sig.is_a?(String)
|
|
64
|
+
assert_equal 64, sig.length
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
def stub_connection(method, body)
|
|
70
|
+
response = stub(body: body)
|
|
71
|
+
connection = stub
|
|
72
|
+
connection.stubs(method).returns(response)
|
|
73
|
+
@client.instance_variable_set(:@connection, connection)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -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
|