honeymaker 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +4 -0
- data/lib/honeymaker/client.rb +22 -0
- data/lib/honeymaker/clients/binance.rb +48 -0
- data/lib/honeymaker/clients/bingx.rb +31 -0
- data/lib/honeymaker/clients/bitget.rb +32 -3
- data/lib/honeymaker/clients/bitmart.rb +29 -0
- data/lib/honeymaker/clients/bitrue.rb +16 -0
- data/lib/honeymaker/clients/bitvavo.rb +24 -0
- data/lib/honeymaker/clients/bybit.rb +30 -0
- data/lib/honeymaker/clients/coinbase.rb +35 -0
- data/lib/honeymaker/clients/gemini.rb +18 -0
- data/lib/honeymaker/clients/hyperliquid.rb +23 -0
- data/lib/honeymaker/clients/kraken.rb +30 -0
- data/lib/honeymaker/clients/kucoin.rb +33 -0
- data/lib/honeymaker/clients/mexc.rb +30 -0
- data/lib/honeymaker/version.rb +1 -1
- data/test/honeymaker/clients/binance_client_test.rb +21 -0
- data/test/honeymaker/clients/bingx_client_test.rb +18 -0
- data/test/honeymaker/clients/bitget_client_test.rb +25 -1
- data/test/honeymaker/clients/bitmart_client_test.rb +18 -0
- data/test/honeymaker/clients/bitrue_client_test.rb +6 -0
- data/test/honeymaker/clients/bitvavo_client_test.rb +18 -0
- data/test/honeymaker/clients/bybit_client_test.rb +18 -0
- data/test/honeymaker/clients/coinbase_client_test.rb +14 -0
- data/test/honeymaker/clients/gemini_client_test.rb +12 -0
- data/test/honeymaker/clients/hyperliquid_client_test.rb +12 -0
- data/test/honeymaker/clients/kraken_client_test.rb +14 -0
- data/test/honeymaker/clients/kucoin_client_test.rb +18 -0
- data/test/honeymaker/clients/mexc_client_test.rb +18 -0
- data/test/honeymaker/clients/validation_test.rb +182 -0
- metadata +2 -2
- data/honeymaker-0.1.0.gem +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ff95afc5916845501bc9cbb7c625979f9f06662608d0e47bfbf9ec4bb7be686b
|
|
4
|
+
data.tar.gz: 978d54c3f108c0a037c627250bd277d6c1e5159d940c10a1579e54d0f96523d3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: aec9b76d37ca978445002ba6243c73c857b6a3e9bfc4b7fd43f8c73091a7606503df1076da8af93856a4a6a74fb9e72c32af20237b74b3e339339cc5b168d3d3
|
|
7
|
+
data.tar.gz: 630b79116ad0d74be37993f412aa4b81f371cdc58fae756fd5c08fe7496a887c458aee0b9e6439575d89268a6f8f0c8b78bc7734d35ac8debe0c16185d7280a1
|
data/README.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Honeymaker
|
|
2
2
|
|
|
3
|
+
[](https://rubygems.org/gems/honeymaker)
|
|
4
|
+
[](https://github.com/deltabadger/honeymaker/actions)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
|
|
3
7
|
Ruby clients for cryptocurrency exchange APIs. Originally extracted from [Deltabadger](https://github.com/deltabadger/deltabadger).
|
|
4
8
|
|
|
5
9
|
## Supported Exchanges
|
data/lib/honeymaker/client.rb
CHANGED
|
@@ -23,8 +23,30 @@ module Honeymaker
|
|
|
23
23
|
@logger = logger
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
+
def validate(type = :trading)
|
|
27
|
+
return Result::Failure.new("No credentials provided") unless authenticated?
|
|
28
|
+
|
|
29
|
+
case type
|
|
30
|
+
when :trading then validate_trading_credentials
|
|
31
|
+
when :read then validate_read_credentials
|
|
32
|
+
else raise Error, "Unknown validation type: #{type}. Use :trading or :read"
|
|
33
|
+
end
|
|
34
|
+
rescue Error
|
|
35
|
+
raise
|
|
36
|
+
rescue StandardError => e
|
|
37
|
+
Result::Failure.new(e.message)
|
|
38
|
+
end
|
|
39
|
+
|
|
26
40
|
private
|
|
27
41
|
|
|
42
|
+
def validate_trading_credentials
|
|
43
|
+
raise NotImplementedError, "#{self.class} must implement #validate_trading_credentials"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def validate_read_credentials
|
|
47
|
+
raise NotImplementedError, "#{self.class} must implement #validate_read_credentials"
|
|
48
|
+
end
|
|
49
|
+
|
|
28
50
|
def with_rescue
|
|
29
51
|
Result::Success.new(yield)
|
|
30
52
|
rescue Faraday::Error => e
|
|
@@ -168,6 +168,40 @@ module Honeymaker
|
|
|
168
168
|
end
|
|
169
169
|
end
|
|
170
170
|
|
|
171
|
+
def deposit_history(coin: nil, status: nil, start_time: nil, end_time: nil, offset: nil, limit: 1000, recv_window: 5000)
|
|
172
|
+
with_rescue do
|
|
173
|
+
response = connection.get do |req|
|
|
174
|
+
req.url "/sapi/v1/capital/deposit/hisrec"
|
|
175
|
+
req.headers = headers
|
|
176
|
+
req.params = {
|
|
177
|
+
coin: coin, status: status,
|
|
178
|
+
startTime: start_time, endTime: end_time,
|
|
179
|
+
offset: offset, limit: limit,
|
|
180
|
+
recvWindow: recv_window, timestamp: timestamp_ms
|
|
181
|
+
}.compact
|
|
182
|
+
req.params[:signature] = sign_params(req.params)
|
|
183
|
+
end
|
|
184
|
+
response.body
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def withdraw_history(coin: nil, status: nil, start_time: nil, end_time: nil, offset: nil, limit: 1000, recv_window: 5000)
|
|
189
|
+
with_rescue do
|
|
190
|
+
response = connection.get do |req|
|
|
191
|
+
req.url "/sapi/v1/capital/withdraw/history"
|
|
192
|
+
req.headers = headers
|
|
193
|
+
req.params = {
|
|
194
|
+
coin: coin, status: status,
|
|
195
|
+
startTime: start_time, endTime: end_time,
|
|
196
|
+
offset: offset, limit: limit,
|
|
197
|
+
recvWindow: recv_window, timestamp: timestamp_ms
|
|
198
|
+
}.compact
|
|
199
|
+
req.params[:signature] = sign_params(req.params)
|
|
200
|
+
end
|
|
201
|
+
response.body
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
171
205
|
def get_all_coins_information(recv_window: 5000)
|
|
172
206
|
with_rescue do
|
|
173
207
|
response = connection.get do |req|
|
|
@@ -222,6 +256,20 @@ module Honeymaker
|
|
|
222
256
|
|
|
223
257
|
private
|
|
224
258
|
|
|
259
|
+
def validate_trading_credentials
|
|
260
|
+
# Try cancelling a non-existent order — error -2011 (ORDER_DOES_NOT_EXIST) means key is valid with trade permission
|
|
261
|
+
result = cancel_order(symbol: "ETHBTC", order_id: "9999999999")
|
|
262
|
+
return Result::Failure.new("Invalid trading credentials") if result.failure?
|
|
263
|
+
|
|
264
|
+
code = result.data.is_a?(Hash) ? result.data["code"] : nil
|
|
265
|
+
code == -2011 ? Result::Success.new(true) : Result::Failure.new("Invalid trading credentials")
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def validate_read_credentials
|
|
269
|
+
result = api_description
|
|
270
|
+
Result.new(data: result.success?, errors: result.success? ? [] : ["Invalid read credentials"])
|
|
271
|
+
end
|
|
272
|
+
|
|
225
273
|
def headers
|
|
226
274
|
if authenticated?
|
|
227
275
|
{ "X-MBX-APIKEY": @api_key, Accept: "application/json", "Content-Type": "application/json" }
|
|
@@ -50,6 +50,27 @@ module Honeymaker
|
|
|
50
50
|
})
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
+
def get_trade_fills(symbol: nil, order_id: nil, start_time: nil, end_time: nil, from_id: nil, limit: nil)
|
|
54
|
+
get_signed("/openApi/spot/v1/trade/fills", {
|
|
55
|
+
symbol: symbol, orderId: order_id,
|
|
56
|
+
startTime: start_time, endTime: end_time, fromId: from_id, limit: limit
|
|
57
|
+
})
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def deposit_history(coin: nil, status: nil, start_time: nil, end_time: nil, offset: nil, limit: nil)
|
|
61
|
+
get_signed("/openApi/wallets/v1/capital/deposit/hisrec", {
|
|
62
|
+
coin: coin, status: status,
|
|
63
|
+
startTime: start_time, endTime: end_time, offset: offset, limit: limit
|
|
64
|
+
})
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def withdraw_history(coin: nil, status: nil, start_time: nil, end_time: nil, offset: nil, limit: nil, id: nil)
|
|
68
|
+
get_signed("/openApi/wallets/v1/capital/withdraw/history", {
|
|
69
|
+
coin: coin, status: status,
|
|
70
|
+
startTime: start_time, endTime: end_time, offset: offset, limit: limit, id: id
|
|
71
|
+
})
|
|
72
|
+
end
|
|
73
|
+
|
|
53
74
|
def withdraw(coin:, address:, amount:, network: nil, wallet_type: nil, tag: nil)
|
|
54
75
|
post_signed("/openApi/wallets/v1/capital/withdraw/apply", {
|
|
55
76
|
coin: coin, address: address, amount: amount,
|
|
@@ -59,6 +80,16 @@ module Honeymaker
|
|
|
59
80
|
|
|
60
81
|
private
|
|
61
82
|
|
|
83
|
+
def validate_trading_credentials
|
|
84
|
+
result = get_balances
|
|
85
|
+
return Result::Failure.new("Invalid trading credentials") if result.failure?
|
|
86
|
+
result.data["code"]&.to_i&.zero? ? Result::Success.new(true) : Result::Failure.new("Invalid trading credentials")
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def validate_read_credentials
|
|
90
|
+
validate_trading_credentials
|
|
91
|
+
end
|
|
92
|
+
|
|
62
93
|
def get_public(path, params = {})
|
|
63
94
|
with_rescue do
|
|
64
95
|
response = connection.get do |req|
|
|
@@ -39,10 +39,10 @@ module Honeymaker
|
|
|
39
39
|
get_signed("/api/v2/spot/account/assets", { coin: coin })
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
-
def place_order(symbol:, side:, order_type:, size
|
|
42
|
+
def place_order(symbol:, side:, order_type:, size: nil, quote_size: nil, price: nil, force: nil, client_oid: nil)
|
|
43
43
|
post_signed("/api/v2/spot/trade/place-order", {
|
|
44
44
|
symbol: symbol, side: side, orderType: order_type,
|
|
45
|
-
size: size, price: price, force: force, clientOid: client_oid
|
|
45
|
+
size: size, quoteSize: quote_size, price: price, force: force, clientOid: client_oid
|
|
46
46
|
})
|
|
47
47
|
end
|
|
48
48
|
|
|
@@ -56,7 +56,26 @@ module Honeymaker
|
|
|
56
56
|
})
|
|
57
57
|
end
|
|
58
58
|
|
|
59
|
-
def
|
|
59
|
+
def get_fills(symbol: nil, order_id: nil, start_time: nil, end_time: nil, limit: nil, id_less_than: nil)
|
|
60
|
+
get_signed("/api/v2/spot/trade/fills", {
|
|
61
|
+
symbol: symbol, orderId: order_id,
|
|
62
|
+
startTime: start_time, endTime: end_time, limit: limit, idLessThan: id_less_than
|
|
63
|
+
})
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def deposit_list(coin: nil, start_time: nil, end_time: nil, limit: nil, id_less_than: nil)
|
|
67
|
+
get_signed("/api/v2/spot/wallet/deposit-records", {
|
|
68
|
+
coin: coin, startTime: start_time, endTime: end_time, limit: limit, idLessThan: id_less_than
|
|
69
|
+
})
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def withdrawal_list(coin: nil, start_time: nil, end_time: nil, limit: nil, id_less_than: nil)
|
|
73
|
+
get_signed("/api/v2/spot/wallet/withdrawal-records", {
|
|
74
|
+
coin: coin, startTime: start_time, endTime: end_time, limit: limit, idLessThan: id_less_than
|
|
75
|
+
})
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def withdraw(coin:, address:, size:, transfer_type: nil, chain: nil, tag: nil, client_oid: nil)
|
|
60
79
|
post_signed("/api/v2/spot/wallet/withdrawal", {
|
|
61
80
|
coin: coin, transferType: transfer_type, address: address,
|
|
62
81
|
size: size, chain: chain, tag: tag, clientOid: client_oid
|
|
@@ -65,6 +84,16 @@ module Honeymaker
|
|
|
65
84
|
|
|
66
85
|
private
|
|
67
86
|
|
|
87
|
+
def validate_trading_credentials
|
|
88
|
+
result = get_account_assets
|
|
89
|
+
return Result::Failure.new("Invalid trading credentials") if result.failure?
|
|
90
|
+
result.data["code"] == "00000" ? Result::Success.new(true) : Result::Failure.new("Invalid trading credentials")
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def validate_read_credentials
|
|
94
|
+
validate_trading_credentials
|
|
95
|
+
end
|
|
96
|
+
|
|
68
97
|
def get_public(path, params = {})
|
|
69
98
|
with_rescue do
|
|
70
99
|
response = connection.get do |req|
|
|
@@ -52,6 +52,25 @@ module Honeymaker
|
|
|
52
52
|
})
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
+
def get_trades(symbol:, order_mode: nil, start_time: nil, end_time: nil, limit: nil, recv_window: nil)
|
|
56
|
+
get_signed("/spot/v2/trades", {
|
|
57
|
+
symbol: symbol, orderMode: order_mode,
|
|
58
|
+
startTime: start_time, endTime: end_time, N: limit, recvWindow: recv_window
|
|
59
|
+
})
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def deposit_list(currency: nil, n: nil, status: nil)
|
|
63
|
+
get_signed("/account/v1/deposit-withdraw/detail", {
|
|
64
|
+
currency: currency, N: n, type: "deposit", operation_type: "deposit", status: status
|
|
65
|
+
})
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def withdraw_list(currency: nil, n: nil, status: nil)
|
|
69
|
+
get_signed("/account/v1/deposit-withdraw/detail", {
|
|
70
|
+
currency: currency, N: n, type: "withdraw", operation_type: "withdraw", status: status
|
|
71
|
+
})
|
|
72
|
+
end
|
|
73
|
+
|
|
55
74
|
def withdraw(currency:, amount:, address:, address_memo: nil, destination: nil)
|
|
56
75
|
post_signed("/account/v1/withdraw/apply", {
|
|
57
76
|
currency: currency, amount: amount,
|
|
@@ -62,6 +81,16 @@ module Honeymaker
|
|
|
62
81
|
|
|
63
82
|
private
|
|
64
83
|
|
|
84
|
+
def validate_trading_credentials
|
|
85
|
+
result = get_wallet
|
|
86
|
+
return Result::Failure.new("Invalid trading credentials") if result.failure?
|
|
87
|
+
result.data["code"] == 1000 ? Result::Success.new(true) : Result::Failure.new("Invalid trading credentials")
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def validate_read_credentials
|
|
91
|
+
validate_trading_credentials
|
|
92
|
+
end
|
|
93
|
+
|
|
65
94
|
def get_public(path, params = {})
|
|
66
95
|
with_rescue do
|
|
67
96
|
response = connection.get do |req|
|
|
@@ -52,8 +52,24 @@ module Honeymaker
|
|
|
52
52
|
})
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
+
def account_trade_list(symbol:, start_time: nil, end_time: nil, from_id: nil, limit: 500, recv_window: 5000)
|
|
56
|
+
get_signed("/api/v1/myTrades", {
|
|
57
|
+
symbol: symbol, startTime: start_time, endTime: end_time,
|
|
58
|
+
fromId: from_id, limit: limit, recvWindow: recv_window
|
|
59
|
+
})
|
|
60
|
+
end
|
|
61
|
+
|
|
55
62
|
private
|
|
56
63
|
|
|
64
|
+
def validate_trading_credentials
|
|
65
|
+
result = account_information
|
|
66
|
+
result.success? ? Result::Success.new(true) : Result::Failure.new("Invalid trading credentials")
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def validate_read_credentials
|
|
70
|
+
validate_trading_credentials
|
|
71
|
+
end
|
|
72
|
+
|
|
57
73
|
def get_public(path, params = {})
|
|
58
74
|
with_rescue do
|
|
59
75
|
response = connection.get do |req|
|
|
@@ -49,6 +49,21 @@ module Honeymaker
|
|
|
49
49
|
delete_signed("/v2/order", { market: market, orderId: order_id })
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
+
def get_trades(market:, limit: nil, start_time: nil, end_time: nil, trade_id_from: nil, trade_id_to: nil)
|
|
53
|
+
get_signed("/v2/trades", {
|
|
54
|
+
market: market, limit: limit, start: start_time, end: end_time,
|
|
55
|
+
tradeIdFrom: trade_id_from, tradeIdTo: trade_id_to
|
|
56
|
+
})
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def get_deposit_history(symbol: nil, limit: nil, start_time: nil, end_time: nil)
|
|
60
|
+
get_signed("/v2/deposit", { symbol: symbol, limit: limit, start: start_time, end: end_time })
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def get_withdrawal_history(symbol: nil, limit: nil, start_time: nil, end_time: nil)
|
|
64
|
+
get_signed("/v2/withdrawal", { symbol: symbol, limit: limit, start: start_time, end: end_time })
|
|
65
|
+
end
|
|
66
|
+
|
|
52
67
|
def withdraw(symbol:, amount:, address:, payment_id: nil)
|
|
53
68
|
post_signed("/v2/withdrawal", {
|
|
54
69
|
symbol: symbol, amount: amount, address: address, paymentId: payment_id
|
|
@@ -57,6 +72,15 @@ module Honeymaker
|
|
|
57
72
|
|
|
58
73
|
private
|
|
59
74
|
|
|
75
|
+
def validate_trading_credentials
|
|
76
|
+
result = get_balance
|
|
77
|
+
result.success? ? Result::Success.new(true) : Result::Failure.new("Invalid trading credentials")
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def validate_read_credentials
|
|
81
|
+
validate_trading_credentials
|
|
82
|
+
end
|
|
83
|
+
|
|
60
84
|
def get_public(path, params = {})
|
|
61
85
|
with_rescue do
|
|
62
86
|
response = connection.get do |req|
|
|
@@ -61,6 +61,26 @@ module Honeymaker
|
|
|
61
61
|
})
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
+
def execution_list(category:, symbol: nil, order_id: nil, start_time: nil, end_time: nil, limit: nil, cursor: nil)
|
|
65
|
+
get_authenticated("/v5/execution/list", {
|
|
66
|
+
category: category, symbol: symbol, orderId: order_id,
|
|
67
|
+
startTime: start_time, endTime: end_time, limit: limit, cursor: cursor
|
|
68
|
+
})
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def deposit_records(coin: nil, start_time: nil, end_time: nil, limit: nil, cursor: nil)
|
|
72
|
+
get_authenticated("/v5/asset/deposit/query-record", {
|
|
73
|
+
coin: coin, startTime: start_time, endTime: end_time, limit: limit, cursor: cursor
|
|
74
|
+
})
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def withdraw_records(coin: nil, start_time: nil, end_time: nil, limit: nil, cursor: nil, withdraw_type: nil)
|
|
78
|
+
get_authenticated("/v5/asset/withdraw/query-record", {
|
|
79
|
+
coin: coin, startTime: start_time, endTime: end_time,
|
|
80
|
+
limit: limit, cursor: cursor, withdrawType: withdraw_type
|
|
81
|
+
})
|
|
82
|
+
end
|
|
83
|
+
|
|
64
84
|
def withdraw(coin:, chain:, address:, amount:, tag: nil, force_chain: nil)
|
|
65
85
|
post_authenticated("/v5/asset/withdraw/create", {
|
|
66
86
|
coin: coin, chain: chain, address: address, amount: amount,
|
|
@@ -70,6 +90,16 @@ module Honeymaker
|
|
|
70
90
|
|
|
71
91
|
private
|
|
72
92
|
|
|
93
|
+
def validate_trading_credentials
|
|
94
|
+
result = wallet_balance(account_type: "UNIFIED")
|
|
95
|
+
return Result::Failure.new("Invalid trading credentials") if result.failure?
|
|
96
|
+
result.data["retCode"]&.zero? ? Result::Success.new(true) : Result::Failure.new("Invalid trading credentials")
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def validate_read_credentials
|
|
100
|
+
validate_trading_credentials
|
|
101
|
+
end
|
|
102
|
+
|
|
73
103
|
def get_public(path, params = {})
|
|
74
104
|
with_rescue do
|
|
75
105
|
response = connection.get do |req|
|
|
@@ -108,6 +108,28 @@ module Honeymaker
|
|
|
108
108
|
})
|
|
109
109
|
end
|
|
110
110
|
|
|
111
|
+
def list_fills(product_id: nil, order_id: nil, start_sequence_timestamp: nil,
|
|
112
|
+
end_sequence_timestamp: nil, limit: nil, cursor: nil)
|
|
113
|
+
with_rescue do
|
|
114
|
+
response = connection.get do |req|
|
|
115
|
+
req.url "/api/v3/brokerage/orders/historical/fills"
|
|
116
|
+
req.headers = auth_headers(req)
|
|
117
|
+
req.params = {
|
|
118
|
+
product_id: product_id, order_id: order_id,
|
|
119
|
+
start_sequence_timestamp: start_sequence_timestamp,
|
|
120
|
+
end_sequence_timestamp: end_sequence_timestamp,
|
|
121
|
+
limit: limit, cursor: cursor
|
|
122
|
+
}.compact
|
|
123
|
+
req.options.params_encoder = Faraday::FlatParamsEncoder
|
|
124
|
+
end
|
|
125
|
+
response.body
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def list_transactions(account_id:, limit: nil, starting_after: nil)
|
|
130
|
+
get("/v2/accounts/#{account_id}/transactions", { limit: limit, starting_after: starting_after })
|
|
131
|
+
end
|
|
132
|
+
|
|
111
133
|
private
|
|
112
134
|
|
|
113
135
|
def get(path, params = {})
|
|
@@ -132,6 +154,19 @@ module Honeymaker
|
|
|
132
154
|
end
|
|
133
155
|
end
|
|
134
156
|
|
|
157
|
+
def validate_trading_credentials
|
|
158
|
+
# List accounts — if it works, the key has trading access
|
|
159
|
+
result = list_accounts
|
|
160
|
+
return Result::Failure.new("Invalid trading credentials") if result.failure?
|
|
161
|
+
Result::Success.new(true)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def validate_read_credentials
|
|
165
|
+
result = get_api_key_permissions
|
|
166
|
+
return Result::Failure.new("Invalid read credentials") if result.failure?
|
|
167
|
+
Result::Success.new(true)
|
|
168
|
+
end
|
|
169
|
+
|
|
135
170
|
def auth_headers(req)
|
|
136
171
|
return unauthenticated_headers unless authenticated?
|
|
137
172
|
|
|
@@ -41,12 +41,30 @@ module Honeymaker
|
|
|
41
41
|
post_signed("/v1/order/cancel", { order_id: order_id })
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
+
def get_my_trades(symbol: nil, limit_trades: nil, timestamp: nil)
|
|
45
|
+
post_signed("/v1/mytrades", { symbol: symbol, limit_trades: limit_trades, timestamp: timestamp })
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def get_transfers(timestamp: nil, limit_transfers: nil)
|
|
49
|
+
post_signed("/v1/transfers", { timestamp: timestamp, limit_transfers: limit_transfers })
|
|
50
|
+
end
|
|
51
|
+
|
|
44
52
|
def withdraw(currency:, address:, amount:)
|
|
45
53
|
post_signed("/v1/withdraw/#{currency}", { address: address, amount: amount })
|
|
46
54
|
end
|
|
47
55
|
|
|
48
56
|
private
|
|
49
57
|
|
|
58
|
+
def validate_trading_credentials
|
|
59
|
+
result = get_balances
|
|
60
|
+
return Result::Failure.new("Invalid trading credentials") if result.failure?
|
|
61
|
+
result.data.is_a?(Array) ? Result::Success.new(true) : Result::Failure.new("Invalid trading credentials")
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def validate_read_credentials
|
|
65
|
+
validate_trading_credentials
|
|
66
|
+
end
|
|
67
|
+
|
|
50
68
|
def get_public(path, params = {})
|
|
51
69
|
with_rescue do
|
|
52
70
|
response = connection.get do |req|
|
|
@@ -25,8 +25,31 @@ module Honeymaker
|
|
|
25
25
|
post_info({ type: "openOrders", user: user })
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
+
def user_fills(user:, start_time: nil, end_time: nil)
|
|
29
|
+
body = { type: "userFills", user: user }
|
|
30
|
+
body[:startTime] = start_time if start_time
|
|
31
|
+
body[:endTime] = end_time if end_time
|
|
32
|
+
post_info(body)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def user_fills_by_time(user:, start_time:, end_time: nil)
|
|
36
|
+
body = { type: "userFillsByTime", user: user, startTime: start_time }
|
|
37
|
+
body[:endTime] = end_time if end_time
|
|
38
|
+
post_info(body)
|
|
39
|
+
end
|
|
40
|
+
|
|
28
41
|
private
|
|
29
42
|
|
|
43
|
+
def validate_trading_credentials
|
|
44
|
+
return Result::Failure.new("No wallet address provided") unless @api_key
|
|
45
|
+
result = open_orders(user: @api_key)
|
|
46
|
+
result.success? ? Result::Success.new(true) : Result::Failure.new("Invalid credentials")
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def validate_read_credentials
|
|
50
|
+
validate_trading_credentials
|
|
51
|
+
end
|
|
52
|
+
|
|
30
53
|
def post_info(body)
|
|
31
54
|
with_rescue do
|
|
32
55
|
response = connection.post do |req|
|
|
@@ -61,6 +61,20 @@ module Honeymaker
|
|
|
61
61
|
get_public("/0/public/OHLC", { pair: pair, interval: interval, since: since })
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
+
def get_trades_history(type: nil, trades: nil, start: nil, end_time: nil, ofs: nil)
|
|
65
|
+
post_private("/0/private/TradesHistory", {
|
|
66
|
+
nonce: nonce, type: type, trades: trades,
|
|
67
|
+
start: start, end: end_time, ofs: ofs
|
|
68
|
+
})
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def get_ledgers(asset: nil, type: nil, start: nil, end_time: nil, ofs: nil)
|
|
72
|
+
post_private("/0/private/Ledgers", {
|
|
73
|
+
nonce: nonce, asset: asset, type: type,
|
|
74
|
+
start: start, end: end_time, ofs: ofs
|
|
75
|
+
})
|
|
76
|
+
end
|
|
77
|
+
|
|
64
78
|
def get_withdraw_addresses(asset: nil, method: nil)
|
|
65
79
|
post_private("/0/private/WithdrawAddresses", { nonce: nonce, asset: asset, method: method })
|
|
66
80
|
end
|
|
@@ -75,6 +89,22 @@ module Honeymaker
|
|
|
75
89
|
|
|
76
90
|
private
|
|
77
91
|
|
|
92
|
+
def validate_trading_credentials
|
|
93
|
+
result = get_extended_balance
|
|
94
|
+
return Result::Failure.new("Invalid trading credentials") if result.failure?
|
|
95
|
+
|
|
96
|
+
errors = result.data["error"]
|
|
97
|
+
if errors.is_a?(Array) && errors.none?
|
|
98
|
+
Result::Success.new(true)
|
|
99
|
+
else
|
|
100
|
+
Result::Failure.new("Invalid trading credentials")
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def validate_read_credentials
|
|
105
|
+
validate_trading_credentials
|
|
106
|
+
end
|
|
107
|
+
|
|
78
108
|
def get_public(path, params = {})
|
|
79
109
|
with_rescue do
|
|
80
110
|
response = connection.get do |req|
|
|
@@ -59,6 +59,29 @@ 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_deposits(currency: nil, start_at: nil, end_at: nil, status: nil, current_page: nil, page_size: nil)
|
|
72
|
+
get_signed("/api/v1/deposits", {
|
|
73
|
+
currency: currency, startAt: start_at, endAt: end_at,
|
|
74
|
+
status: status, currentPage: current_page, pageSize: page_size
|
|
75
|
+
})
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def get_withdrawals(currency: nil, start_at: nil, end_at: nil, status: nil, current_page: nil, page_size: nil)
|
|
79
|
+
get_signed("/api/v1/withdrawals", {
|
|
80
|
+
currency: currency, startAt: start_at, endAt: end_at,
|
|
81
|
+
status: status, currentPage: current_page, pageSize: page_size
|
|
82
|
+
})
|
|
83
|
+
end
|
|
84
|
+
|
|
62
85
|
def withdraw(currency:, address:, amount:, chain: nil, memo: nil)
|
|
63
86
|
post_signed("/api/v1/withdrawals", {
|
|
64
87
|
currency: currency, address: address, amount: amount,
|
|
@@ -68,6 +91,16 @@ module Honeymaker
|
|
|
68
91
|
|
|
69
92
|
private
|
|
70
93
|
|
|
94
|
+
def validate_trading_credentials
|
|
95
|
+
result = get_accounts(type: "trade")
|
|
96
|
+
return Result::Failure.new("Invalid trading credentials") if result.failure?
|
|
97
|
+
result.data["code"] == "200000" ? 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
|
+
|
|
71
104
|
def get_public(path, params = {})
|
|
72
105
|
with_rescue do
|
|
73
106
|
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|
|
data/lib/honeymaker/version.rb
CHANGED
|
@@ -44,6 +44,27 @@ 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
|
+
|
|
47
68
|
def test_handles_api_error
|
|
48
69
|
connection = stub
|
|
49
70
|
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",
|
|
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,24 @@ class Honeymaker::Clients::BybitTest < Minitest::Test
|
|
|
60
60
|
assert result.success?
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
+
def test_execution_list
|
|
64
|
+
stub_connection(:get, { "result" => { "list" => [{ "execId" => "e1" }] } })
|
|
65
|
+
result = @client.execution_list(category: "spot")
|
|
66
|
+
assert result.success?
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def test_deposit_records
|
|
70
|
+
stub_connection(:get, { "result" => { "rows" => [{ "coin" => "BTC" }] } })
|
|
71
|
+
result = @client.deposit_records
|
|
72
|
+
assert result.success?
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def test_withdraw_records
|
|
76
|
+
stub_connection(:get, { "result" => { "rows" => [{ "coin" => "ETH" }] } })
|
|
77
|
+
result = @client.withdraw_records
|
|
78
|
+
assert result.success?
|
|
79
|
+
end
|
|
80
|
+
|
|
63
81
|
def test_signed_headers_include_api_key
|
|
64
82
|
headers = @client.send(:signed_headers, "GET", { foo: "bar" })
|
|
65
83
|
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,24 @@ class Honeymaker::Clients::KucoinTest < Minitest::Test
|
|
|
59
59
|
assert result.success?
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
+
def test_get_fills
|
|
63
|
+
stub_connection(:get, { "data" => { "items" => [{ "tradeId" => "t1" }] } })
|
|
64
|
+
result = @client.get_fills(symbol: "BTC-USDT")
|
|
65
|
+
assert result.success?
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def test_get_deposits
|
|
69
|
+
stub_connection(:get, { "data" => { "items" => [{ "currency" => "BTC" }] } })
|
|
70
|
+
result = @client.get_deposits
|
|
71
|
+
assert result.success?
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def test_get_withdrawals
|
|
75
|
+
stub_connection(:get, { "data" => { "items" => [{ "currency" => "ETH" }] } })
|
|
76
|
+
result = @client.get_withdrawals
|
|
77
|
+
assert result.success?
|
|
78
|
+
end
|
|
79
|
+
|
|
62
80
|
def test_signed_headers_include_passphrase_and_version
|
|
63
81
|
ts = "1234567890"
|
|
64
82
|
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
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: honeymaker
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Deltabadger
|
|
@@ -78,7 +78,6 @@ files:
|
|
|
78
78
|
- LICENSE
|
|
79
79
|
- README.md
|
|
80
80
|
- Rakefile
|
|
81
|
-
- honeymaker-0.1.0.gem
|
|
82
81
|
- lib/honeymaker.rb
|
|
83
82
|
- lib/honeymaker/client.rb
|
|
84
83
|
- lib/honeymaker/clients/binance.rb
|
|
@@ -144,6 +143,7 @@ files:
|
|
|
144
143
|
- test/honeymaker/clients/kraken_client_test.rb
|
|
145
144
|
- test/honeymaker/clients/kucoin_client_test.rb
|
|
146
145
|
- test/honeymaker/clients/mexc_client_test.rb
|
|
146
|
+
- test/honeymaker/clients/validation_test.rb
|
|
147
147
|
- test/honeymaker/exchange_test.rb
|
|
148
148
|
- test/honeymaker/exchanges/binance_test.rb
|
|
149
149
|
- test/honeymaker/exchanges/binance_us_test.rb
|
data/honeymaker-0.1.0.gem
DELETED
|
Binary file
|