honeymaker 0.12.4-aarch64-linux
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 +7 -0
- data/.github/workflows/native-gems.yml +100 -0
- data/.github/workflows/release.yml +36 -0
- data/.github/workflows/test.yml +33 -0
- data/LICENSE +21 -0
- data/README.md +219 -0
- data/Rakefile +78 -0
- data/crates/honeymaker/tests/vectors/decimal.json +146 -0
- data/crates/honeymaker/tests/vectors/kraken_add_order_wire.json +74 -0
- data/crates/honeymaker/tests/vectors/kraken_signing.json +3314 -0
- data/crates/honeymaker/tests/vectors/kraken_trades_pager.json +1583 -0
- data/lib/honeymaker/3.4/honeymaker_native.so +0 -0
- data/lib/honeymaker/4.0/honeymaker_native.so +0 -0
- data/lib/honeymaker/client.rb +139 -0
- data/lib/honeymaker/clients/binance.rb +687 -0
- data/lib/honeymaker/clients/binance_us.rb +42 -0
- data/lib/honeymaker/clients/bingx.rb +242 -0
- data/lib/honeymaker/clients/bitget.rb +318 -0
- data/lib/honeymaker/clients/bitrue.rb +245 -0
- data/lib/honeymaker/clients/bitvavo.rb +244 -0
- data/lib/honeymaker/clients/bybit.rb +308 -0
- data/lib/honeymaker/clients/coinbase.rb +326 -0
- data/lib/honeymaker/clients/gemini.rb +189 -0
- data/lib/honeymaker/clients/hyperliquid.rb +232 -0
- data/lib/honeymaker/clients/kraken.rb +379 -0
- data/lib/honeymaker/clients/kraken_futures.rb +78 -0
- data/lib/honeymaker/clients/kucoin.rb +310 -0
- data/lib/honeymaker/clients/mexc.rb +249 -0
- data/lib/honeymaker/exchange.rb +129 -0
- data/lib/honeymaker/exchanges/binance.rb +55 -0
- data/lib/honeymaker/exchanges/binance_us.rb +9 -0
- data/lib/honeymaker/exchanges/bingx.rb +56 -0
- data/lib/honeymaker/exchanges/bitget.rb +52 -0
- data/lib/honeymaker/exchanges/bitrue.rb +53 -0
- data/lib/honeymaker/exchanges/bitvavo.rb +65 -0
- data/lib/honeymaker/exchanges/bybit.rb +57 -0
- data/lib/honeymaker/exchanges/coinbase.rb +69 -0
- data/lib/honeymaker/exchanges/gemini.rb +134 -0
- data/lib/honeymaker/exchanges/hyperliquid.rb +67 -0
- data/lib/honeymaker/exchanges/kraken.rb +122 -0
- data/lib/honeymaker/exchanges/kucoin.rb +52 -0
- data/lib/honeymaker/exchanges/mexc.rb +56 -0
- data/lib/honeymaker/native/kraken.rb +263 -0
- data/lib/honeymaker/native.rb +42 -0
- data/lib/honeymaker/result.rb +46 -0
- data/lib/honeymaker/utils.rb +39 -0
- data/lib/honeymaker/version.rb +5 -0
- data/lib/honeymaker.rb +97 -0
- data/script/parity/kraken_client_live.rb +191 -0
- data/script/parity/kraken_live.rb +70 -0
- data/script/parity/kraken_transport.rb +604 -0
- data/script/parity/resolve.c +49 -0
- data/script/release/push_gems.sh +28 -0
- data/script/vectors/kraken.rb +50 -0
- data/script/vectors/kraken_stage2.rb +146 -0
- data/sig/honeymaker.rbs +4 -0
- data/test/fixtures/binance_book_ticker.json +7 -0
- data/test/fixtures/binance_exchange_info.json +30 -0
- data/test/fixtures/bingx_symbols.json +26 -0
- data/test/fixtures/bingx_ticker.json +12 -0
- data/test/fixtures/bitget_symbols.json +28 -0
- data/test/fixtures/bitget_tickers.json +14 -0
- data/test/fixtures/bitmart_symbols.json +26 -0
- data/test/fixtures/bitmart_ticker.json +12 -0
- data/test/fixtures/bitrue_book_ticker.json +7 -0
- data/test/fixtures/bitrue_exchange_info.json +34 -0
- data/test/fixtures/bitvavo_book_ticker.json +7 -0
- data/test/fixtures/bitvavo_markets.json +30 -0
- data/test/fixtures/bybit_instruments.json +23 -0
- data/test/fixtures/bybit_tickers.json +19 -0
- data/test/fixtures/coinbase_product.json +7 -0
- data/test/fixtures/coinbase_products.json +24 -0
- data/test/fixtures/gemini_pubticker.json +10 -0
- data/test/fixtures/gemini_symbol_detail.json +10 -0
- data/test/fixtures/gemini_symbols.json +1 -0
- data/test/fixtures/hyperliquid_all_mids.json +5 -0
- data/test/fixtures/hyperliquid_spot_meta.json +12 -0
- data/test/fixtures/kraken_asset_pairs.json +43 -0
- data/test/fixtures/kraken_ticker.json +16 -0
- data/test/fixtures/kucoin_orderbook_level1.json +10 -0
- data/test/fixtures/kucoin_symbols.json +17 -0
- data/test/fixtures/mexc_book_ticker.json +7 -0
- data/test/fixtures/mexc_exchange_info.json +64 -0
- data/test/honeymaker/client_test.rb +90 -0
- data/test/honeymaker/clients/binance_client_test.rb +151 -0
- data/test/honeymaker/clients/binance_us_client_test.rb +25 -0
- data/test/honeymaker/clients/bingx_client_test.rb +106 -0
- data/test/honeymaker/clients/bitget_client_test.rb +146 -0
- data/test/honeymaker/clients/bitrue_client_test.rb +69 -0
- data/test/honeymaker/clients/bitvavo_client_test.rb +156 -0
- data/test/honeymaker/clients/bybit_client_test.rb +137 -0
- data/test/honeymaker/clients/coinbase_client_test.rb +153 -0
- data/test/honeymaker/clients/gemini_client_test.rb +100 -0
- data/test/honeymaker/clients/honeymaker_client_registry_test.rb +39 -0
- data/test/honeymaker/clients/hyperliquid_client_test.rb +292 -0
- data/test/honeymaker/clients/kraken_client_test.rb +255 -0
- data/test/honeymaker/clients/kraken_futures_client_test.rb +54 -0
- data/test/honeymaker/clients/kucoin_client_test.rb +149 -0
- data/test/honeymaker/clients/mexc_client_test.rb +98 -0
- data/test/honeymaker/clients/validation_test.rb +167 -0
- data/test/honeymaker/error_chain_test.rb +133 -0
- data/test/honeymaker/exchange_test.rb +138 -0
- data/test/honeymaker/exchanges/binance_test.rb +83 -0
- data/test/honeymaker/exchanges/binance_us_test.rb +53 -0
- data/test/honeymaker/exchanges/bingx_test.rb +65 -0
- data/test/honeymaker/exchanges/bitget_test.rb +65 -0
- data/test/honeymaker/exchanges/bitrue_test.rb +65 -0
- data/test/honeymaker/exchanges/bitvavo_test.rb +65 -0
- data/test/honeymaker/exchanges/bybit_test.rb +55 -0
- data/test/honeymaker/exchanges/coinbase_test.rb +106 -0
- data/test/honeymaker/exchanges/gemini_catalogue_test.rb +118 -0
- data/test/honeymaker/exchanges/gemini_test.rb +184 -0
- data/test/honeymaker/exchanges/hyperliquid_test.rb +64 -0
- data/test/honeymaker/exchanges/kraken_test.rb +191 -0
- data/test/honeymaker/exchanges/kucoin_test.rb +55 -0
- data/test/honeymaker/exchanges/mexc_test.rb +97 -0
- data/test/honeymaker/honeymaker_test.rb +27 -0
- data/test/honeymaker/result_test.rb +42 -0
- data/test/honeymaker/utils_test.rb +64 -0
- data/test/native/backend_switch_test.rb +53 -0
- data/test/native/convert_test.rb +137 -0
- data/test/native/gem_isolation_test.rb +17 -0
- data/test/native/loader_test.rb +29 -0
- data/test/native/lockstep_test.rb +23 -0
- data/test/native/signing_smoke_test.rb +28 -0
- data/test/parity/kraken_client_parity_test.rb +398 -0
- data/test/parity/kraken_exchange_parity_test.rb +172 -0
- data/test/release/branch_hardening_test.rb +34 -0
- data/test/release/push_gems_test.rb +79 -0
- data/test/smoke.rb +24 -0
- data/test/support/fixture_helper.rb +13 -0
- data/test/support/kraken_signing_smoke.rb +21 -0
- data/test/support/parity_helper.rb +62 -0
- data/test/support/venue_double.rb +100 -0
- data/test/test_helper.rb +9 -0
- metadata +254 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "test_helper"
|
|
4
|
+
require "tmpdir"
|
|
5
|
+
require "digest"
|
|
6
|
+
require "rubygems/package"
|
|
7
|
+
|
|
8
|
+
class PushGemsTest < Minitest::Test
|
|
9
|
+
SCRIPT = File.expand_path("../../script/release/push_gems.sh", __dir__)
|
|
10
|
+
|
|
11
|
+
PLATFORMS = %w[x86_64-linux aarch64-linux x86_64-darwin arm64-darwin x64-mingw-ucrt].freeze
|
|
12
|
+
|
|
13
|
+
def build_gem(dir, platform)
|
|
14
|
+
spec = Gem::Specification.new do |s|
|
|
15
|
+
s.name = "honeymaker"
|
|
16
|
+
s.version = "9.9.9"
|
|
17
|
+
s.summary = "t"
|
|
18
|
+
s.authors = ["t"]
|
|
19
|
+
s.files = []
|
|
20
|
+
s.platform = platform
|
|
21
|
+
end
|
|
22
|
+
Dir.chdir(dir) { Gem::Package.build(spec) }
|
|
23
|
+
File.join(dir, spec.file_name)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def run_script(gems_dir, published_sha:, push_fails:)
|
|
27
|
+
Dir.mktmpdir do |bin|
|
|
28
|
+
log = File.join(bin, "log")
|
|
29
|
+
File.write(File.join(bin, "gem"), "#!/bin/sh\necho \"push $2\" >> #{log}\n#{push_fails ? 'exit 1' : 'exit 0'}\n")
|
|
30
|
+
File.write(File.join(bin, "curl"), "#!/bin/sh\necho '{\"sha\":\"#{published_sha}\"}'\n")
|
|
31
|
+
File.chmod(0o755, File.join(bin, "gem"), File.join(bin, "curl"))
|
|
32
|
+
out = `PATH=#{bin}:$PATH #{SCRIPT} #{gems_dir} 9.9.9 2>&1`
|
|
33
|
+
[$?.success?, out, File.exist?(log) ? File.read(log).lines.map { |l| File.basename(l.split.last) } : []]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def full_set(dir)
|
|
38
|
+
plats = PLATFORMS.map { |pl| build_gem(dir, pl) }
|
|
39
|
+
[plats, build_gem(dir, "ruby")]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def test_platform_gems_first_then_source_and_idempotent_on_identical_rerun
|
|
43
|
+
Dir.mktmpdir do |dir|
|
|
44
|
+
plats, source = full_set(dir)
|
|
45
|
+
ok, _out, order = run_script(dir, published_sha: "x", push_fails: false)
|
|
46
|
+
assert ok
|
|
47
|
+
assert_equal plats.map { |g| File.basename(g) } + [File.basename(source)], order
|
|
48
|
+
ok, out, = run_script(dir, published_sha: Digest::SHA256.file(plats.first).hexdigest, push_fails: true)
|
|
49
|
+
refute ok, "only the first gem matches the stubbed sha, so the run must stop at the second"
|
|
50
|
+
assert_includes out, "already published with the same checksum"
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def test_mismatched_published_gem_fails
|
|
55
|
+
Dir.mktmpdir do |dir|
|
|
56
|
+
full_set(dir)
|
|
57
|
+
ok, out, = run_script(dir, published_sha: "deadbeef", push_fails: true)
|
|
58
|
+
refute ok
|
|
59
|
+
assert_includes out, "differs from the published gem"
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def test_missing_or_empty_artifacts_push_nothing_and_fail
|
|
64
|
+
Dir.mktmpdir do |dir|
|
|
65
|
+
ok, out, order = run_script(File.join(dir, "nope"), published_sha: "x", push_fails: false)
|
|
66
|
+
refute ok
|
|
67
|
+
assert_empty order
|
|
68
|
+
ok, out, order = run_script(dir, published_sha: "x", push_fails: false)
|
|
69
|
+
refute ok, out
|
|
70
|
+
assert_empty order
|
|
71
|
+
PLATFORMS.first(4).each { |pl| build_gem(dir, pl) }
|
|
72
|
+
build_gem(dir, "ruby")
|
|
73
|
+
ok, out, order = run_script(dir, published_sha: "x", push_fails: false)
|
|
74
|
+
refute ok, "one platform missing must block the whole release"
|
|
75
|
+
assert_includes out, "missing honeymaker-9.9.9-x64-mingw-ucrt.gem"
|
|
76
|
+
assert_empty order
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
data/test/smoke.rb
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Runs against an INSTALLED gem (no bundler, no -Ilib) on native CI runners.
|
|
4
|
+
# EXPECT_PLATFORM=x86_64-linux (platform gem) or EXPECT_PLATFORM=ruby (source gem, compiled on install).
|
|
5
|
+
require "honeymaker"
|
|
6
|
+
|
|
7
|
+
Honeymaker::Native.load!
|
|
8
|
+
abort "native #{Honeymaker::Native::Ext.version} != gem #{Honeymaker::VERSION}" unless Honeymaker::Native::Ext.version == Honeymaker::VERSION
|
|
9
|
+
spec = Gem.loaded_specs.fetch("honeymaker")
|
|
10
|
+
expected = ENV.fetch("EXPECT_PLATFORM")
|
|
11
|
+
abort "installed platform #{spec.platform} != #{expected}" unless spec.platform.to_s == expected
|
|
12
|
+
puts "smoke ok #{RUBY_VERSION} #{RUBY_PLATFORM} #{spec.full_name}"
|
|
13
|
+
|
|
14
|
+
require "uri"
|
|
15
|
+
ext = Honeymaker::Native::Ext::Kraken.new("k", "c2VjcmV0")
|
|
16
|
+
path, pairs = ext.build_post("get_extended_balance", {})
|
|
17
|
+
body = URI.encode_www_form(pairs)
|
|
18
|
+
headers = ext.sign(path, body)
|
|
19
|
+
abort "bad build #{path} #{body} #{headers.keys}" unless path == "/0/private/BalanceEx" && body.start_with?("nonce=") && headers["API-Sign"]
|
|
20
|
+
puts "smoke kraken ok"
|
|
21
|
+
|
|
22
|
+
require_relative "support/kraken_signing_smoke"
|
|
23
|
+
KrakenSigningSmoke.verify!
|
|
24
|
+
puts "smoke kraken signing vector ok"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
|
|
5
|
+
module KrakenSigningSmoke
|
|
6
|
+
VECTORS = File.expand_path("../../crates/honeymaker/tests/vectors/kraken_signing.json", __dir__)
|
|
7
|
+
|
|
8
|
+
def self.verify!
|
|
9
|
+
vector = JSON.parse(File.read(VECTORS)).find do |entry|
|
|
10
|
+
!entry.fetch("api_key").empty? && !entry.fetch("api_secret").empty?
|
|
11
|
+
end
|
|
12
|
+
abort "no authenticated Kraken signing vector" unless vector
|
|
13
|
+
|
|
14
|
+
signer = Honeymaker::Native::Ext::Kraken.new(vector.fetch("api_key"), vector.fetch("api_secret"))
|
|
15
|
+
headers = signer.sign(vector.fetch("path"), vector.fetch("body"))
|
|
16
|
+
%w[API-Key API-Sign].each do |field|
|
|
17
|
+
abort "Kraken signing vector mismatch: #{field}" unless headers[field] == vector.fetch("headers").fetch(field)
|
|
18
|
+
end
|
|
19
|
+
true
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "bigdecimal"
|
|
4
|
+
require_relative "venue_double"
|
|
5
|
+
|
|
6
|
+
# Same-process parity; the legacy client is the oracle. Exact comparison: class, value, String
|
|
7
|
+
# encoding, Float#eql?, BigDecimal sign, Hash key order.
|
|
8
|
+
module ParityHelper
|
|
9
|
+
def self.included(base)
|
|
10
|
+
base.class_eval do
|
|
11
|
+
def setup
|
|
12
|
+
Honeymaker::Native.load!
|
|
13
|
+
require "honeymaker/native/kraken"
|
|
14
|
+
rescue LoadError
|
|
15
|
+
raise if ENV["HONEYMAKER_REQUIRE_NATIVE"]
|
|
16
|
+
|
|
17
|
+
skip "native extension not compiled"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def assert_same_ruby(expected, actual, path = "result")
|
|
23
|
+
return assert_same_exception(expected, actual, path) if expected.is_a?(Exception)
|
|
24
|
+
|
|
25
|
+
assert_equal expected.class, actual.class, "#{path}: class"
|
|
26
|
+
case expected
|
|
27
|
+
when Honeymaker::Result
|
|
28
|
+
assert_same_ruby(expected.errors, actual.errors, "#{path}.errors")
|
|
29
|
+
assert_same_ruby(expected.data, actual.data, "#{path}.data")
|
|
30
|
+
when Hash
|
|
31
|
+
assert_equal expected.keys, actual.keys, "#{path}: keys/order"
|
|
32
|
+
expected.each { |k, v| assert_same_ruby(v, actual[k], "#{path}[#{k.inspect}]") }
|
|
33
|
+
when Array
|
|
34
|
+
assert_equal expected.length, actual.length, "#{path}: length"
|
|
35
|
+
expected.each_with_index { |v, i| assert_same_ruby(v, actual[i], "#{path}[#{i}]") }
|
|
36
|
+
when String
|
|
37
|
+
assert_equal expected.encoding, actual.encoding, "#{path}: encoding"
|
|
38
|
+
assert_equal expected.b, actual.b, "#{path}: bytes"
|
|
39
|
+
when Float
|
|
40
|
+
assert expected.eql?(actual) || (expected.nan? && actual.nan?), "#{path}: #{expected} vs #{actual}"
|
|
41
|
+
when BigDecimal
|
|
42
|
+
assert_equal [expected.to_s, expected.sign], [actual.to_s, actual.sign], "#{path}: BigDecimal"
|
|
43
|
+
else
|
|
44
|
+
if expected.nil?
|
|
45
|
+
assert_nil actual, "#{path}: value"
|
|
46
|
+
else
|
|
47
|
+
assert_equal expected, actual, "#{path}: value"
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# The one documented divergence (spec §5.1): legacy's incidental NoMethodError/TypeError on a
|
|
53
|
+
# nonsensical shape vs ShapeError. Never excuses decimal errors (ArgumentError must match exactly).
|
|
54
|
+
def assert_same_exception(expected, actual, path)
|
|
55
|
+
assert_kind_of Exception, actual, "#{path}: native returned instead of raising"
|
|
56
|
+
if actual.is_a?(Honeymaker::Native::ShapeError)
|
|
57
|
+
assert_includes [NoMethodError, TypeError], expected.class, "#{path}: ShapeError only replaces shape crashes"
|
|
58
|
+
else
|
|
59
|
+
assert_equal [expected.class, expected.message], [actual.class, actual.message], path
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "socket"
|
|
4
|
+
|
|
5
|
+
# Plain-HTTP local venue: scripted replies, recorded requests. Both backends talk to it through
|
|
6
|
+
# the same legacy Faraday connection, one after the other, so URLs in messages are equal.
|
|
7
|
+
class VenueDouble
|
|
8
|
+
Request = Struct.new(:method, :target, :headers, :body, keyword_init: true)
|
|
9
|
+
|
|
10
|
+
attr_reader :port, :requests
|
|
11
|
+
|
|
12
|
+
def initialize(replies)
|
|
13
|
+
reset!(replies)
|
|
14
|
+
@tcp = TCPServer.new("127.0.0.1", 0)
|
|
15
|
+
@port = @tcp.addr[1]
|
|
16
|
+
@thread = Thread.new { loop { serve(@tcp.accept) } }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def reset!(replies)
|
|
20
|
+
@replies = replies.dup
|
|
21
|
+
@requests = []
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def url = "http://127.0.0.1:#{port}"
|
|
25
|
+
|
|
26
|
+
def close
|
|
27
|
+
@thread.kill
|
|
28
|
+
@tcp.close
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def serve(sock)
|
|
34
|
+
Thread.new do
|
|
35
|
+
loop do
|
|
36
|
+
req = read_request(sock) or break
|
|
37
|
+
@requests << req
|
|
38
|
+
status, headers, body = @replies.length > 1 ? @replies.shift : @replies.first
|
|
39
|
+
body = body.to_s.b
|
|
40
|
+
h = { "content-length" => body.bytesize.to_s }.merge(headers)
|
|
41
|
+
sock.write "HTTP/1.1 #{status} X\r\n#{h.map { |k, v| "#{k}: #{v}\r\n" }.join}\r\n#{body}"
|
|
42
|
+
end
|
|
43
|
+
rescue StandardError
|
|
44
|
+
nil
|
|
45
|
+
ensure
|
|
46
|
+
sock.close rescue nil
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def read_request(io)
|
|
51
|
+
head = +""
|
|
52
|
+
head << io.readpartial(4096) until head.include?("\r\n\r\n")
|
|
53
|
+
line, *hdrs = head.split("\r\n\r\n", 2).first.split("\r\n")
|
|
54
|
+
headers = hdrs.to_h { |h| k, v = h.split(": ", 2); [k.downcase, v] }
|
|
55
|
+
body = head.split("\r\n\r\n", 2)[1].to_s.b
|
|
56
|
+
body << io.readpartial(4096) while body.bytesize < headers["content-length"].to_i
|
|
57
|
+
method, target, = line.split(" ")
|
|
58
|
+
Request.new(method: method, target: target, headers: headers, body: body)
|
|
59
|
+
rescue EOFError, IOError
|
|
60
|
+
nil
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# HTTP proxy double: records the first request line of each proxied connection and forwards the
|
|
65
|
+
# bytes to 127.0.0.1:<upstream_port> (absolute-form for http targets, as Net::HTTP sends them).
|
|
66
|
+
class ProxyDouble
|
|
67
|
+
attr_reader :port, :lines
|
|
68
|
+
|
|
69
|
+
def initialize(upstream_port)
|
|
70
|
+
@lines = []
|
|
71
|
+
@tcp = TCPServer.new("127.0.0.1", 0)
|
|
72
|
+
@port = @tcp.addr[1]
|
|
73
|
+
@thread = Thread.new do
|
|
74
|
+
loop do
|
|
75
|
+
s = @tcp.accept
|
|
76
|
+
Thread.new do
|
|
77
|
+
head = +""
|
|
78
|
+
head << s.readpartial(4096) until head.include?("\r\n\r\n")
|
|
79
|
+
@lines << head.lines.first
|
|
80
|
+
up = TCPSocket.new("127.0.0.1", upstream_port)
|
|
81
|
+
up.write(head)
|
|
82
|
+
t = Thread.new { IO.copy_stream(s, up) rescue nil }
|
|
83
|
+
IO.copy_stream(up, s) rescue nil
|
|
84
|
+
t.join(1)
|
|
85
|
+
rescue StandardError
|
|
86
|
+
nil
|
|
87
|
+
ensure
|
|
88
|
+
s.close rescue nil
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def url = "http://127.0.0.1:#{port}"
|
|
95
|
+
|
|
96
|
+
def close
|
|
97
|
+
@thread.kill
|
|
98
|
+
@tcp.close
|
|
99
|
+
end
|
|
100
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: honeymaker
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.12.4
|
|
5
|
+
platform: aarch64-linux
|
|
6
|
+
authors:
|
|
7
|
+
- Deltabadger
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-10-16 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: faraday
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '2.0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '2.0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: faraday-net_http_persistent
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '2.0'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '2.0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: net-http-persistent
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '4.0'
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '4.0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: jwt
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '2.0'
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '2.0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: bigdecimal
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0'
|
|
76
|
+
type: :runtime
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '0'
|
|
83
|
+
description: Unified interface for cryptocurrency exchange APIs — market data, trading,
|
|
84
|
+
balances, and orders. Supports Binance, Kraken, Coinbase, Bybit, KuCoin, Bitget,
|
|
85
|
+
MEXC, and more.
|
|
86
|
+
email:
|
|
87
|
+
- hello@deltabadger.com
|
|
88
|
+
executables: []
|
|
89
|
+
extensions: []
|
|
90
|
+
extra_rdoc_files: []
|
|
91
|
+
files:
|
|
92
|
+
- ".github/workflows/native-gems.yml"
|
|
93
|
+
- ".github/workflows/release.yml"
|
|
94
|
+
- ".github/workflows/test.yml"
|
|
95
|
+
- LICENSE
|
|
96
|
+
- README.md
|
|
97
|
+
- Rakefile
|
|
98
|
+
- crates/honeymaker/tests/vectors/decimal.json
|
|
99
|
+
- crates/honeymaker/tests/vectors/kraken_add_order_wire.json
|
|
100
|
+
- crates/honeymaker/tests/vectors/kraken_signing.json
|
|
101
|
+
- crates/honeymaker/tests/vectors/kraken_trades_pager.json
|
|
102
|
+
- lib/honeymaker.rb
|
|
103
|
+
- lib/honeymaker/3.4/honeymaker_native.so
|
|
104
|
+
- lib/honeymaker/4.0/honeymaker_native.so
|
|
105
|
+
- lib/honeymaker/client.rb
|
|
106
|
+
- lib/honeymaker/clients/binance.rb
|
|
107
|
+
- lib/honeymaker/clients/binance_us.rb
|
|
108
|
+
- lib/honeymaker/clients/bingx.rb
|
|
109
|
+
- lib/honeymaker/clients/bitget.rb
|
|
110
|
+
- lib/honeymaker/clients/bitrue.rb
|
|
111
|
+
- lib/honeymaker/clients/bitvavo.rb
|
|
112
|
+
- lib/honeymaker/clients/bybit.rb
|
|
113
|
+
- lib/honeymaker/clients/coinbase.rb
|
|
114
|
+
- lib/honeymaker/clients/gemini.rb
|
|
115
|
+
- lib/honeymaker/clients/hyperliquid.rb
|
|
116
|
+
- lib/honeymaker/clients/kraken.rb
|
|
117
|
+
- lib/honeymaker/clients/kraken_futures.rb
|
|
118
|
+
- lib/honeymaker/clients/kucoin.rb
|
|
119
|
+
- lib/honeymaker/clients/mexc.rb
|
|
120
|
+
- lib/honeymaker/exchange.rb
|
|
121
|
+
- lib/honeymaker/exchanges/binance.rb
|
|
122
|
+
- lib/honeymaker/exchanges/binance_us.rb
|
|
123
|
+
- lib/honeymaker/exchanges/bingx.rb
|
|
124
|
+
- lib/honeymaker/exchanges/bitget.rb
|
|
125
|
+
- lib/honeymaker/exchanges/bitrue.rb
|
|
126
|
+
- lib/honeymaker/exchanges/bitvavo.rb
|
|
127
|
+
- lib/honeymaker/exchanges/bybit.rb
|
|
128
|
+
- lib/honeymaker/exchanges/coinbase.rb
|
|
129
|
+
- lib/honeymaker/exchanges/gemini.rb
|
|
130
|
+
- lib/honeymaker/exchanges/hyperliquid.rb
|
|
131
|
+
- lib/honeymaker/exchanges/kraken.rb
|
|
132
|
+
- lib/honeymaker/exchanges/kucoin.rb
|
|
133
|
+
- lib/honeymaker/exchanges/mexc.rb
|
|
134
|
+
- lib/honeymaker/native.rb
|
|
135
|
+
- lib/honeymaker/native/kraken.rb
|
|
136
|
+
- lib/honeymaker/result.rb
|
|
137
|
+
- lib/honeymaker/utils.rb
|
|
138
|
+
- lib/honeymaker/version.rb
|
|
139
|
+
- script/parity/kraken_client_live.rb
|
|
140
|
+
- script/parity/kraken_live.rb
|
|
141
|
+
- script/parity/kraken_transport.rb
|
|
142
|
+
- script/parity/resolve.c
|
|
143
|
+
- script/release/push_gems.sh
|
|
144
|
+
- script/vectors/kraken.rb
|
|
145
|
+
- script/vectors/kraken_stage2.rb
|
|
146
|
+
- sig/honeymaker.rbs
|
|
147
|
+
- test/fixtures/binance_book_ticker.json
|
|
148
|
+
- test/fixtures/binance_exchange_info.json
|
|
149
|
+
- test/fixtures/bingx_symbols.json
|
|
150
|
+
- test/fixtures/bingx_ticker.json
|
|
151
|
+
- test/fixtures/bitget_symbols.json
|
|
152
|
+
- test/fixtures/bitget_tickers.json
|
|
153
|
+
- test/fixtures/bitmart_symbols.json
|
|
154
|
+
- test/fixtures/bitmart_ticker.json
|
|
155
|
+
- test/fixtures/bitrue_book_ticker.json
|
|
156
|
+
- test/fixtures/bitrue_exchange_info.json
|
|
157
|
+
- test/fixtures/bitvavo_book_ticker.json
|
|
158
|
+
- test/fixtures/bitvavo_markets.json
|
|
159
|
+
- test/fixtures/bybit_instruments.json
|
|
160
|
+
- test/fixtures/bybit_tickers.json
|
|
161
|
+
- test/fixtures/coinbase_product.json
|
|
162
|
+
- test/fixtures/coinbase_products.json
|
|
163
|
+
- test/fixtures/gemini_pubticker.json
|
|
164
|
+
- test/fixtures/gemini_symbol_detail.json
|
|
165
|
+
- test/fixtures/gemini_symbols.json
|
|
166
|
+
- test/fixtures/hyperliquid_all_mids.json
|
|
167
|
+
- test/fixtures/hyperliquid_spot_meta.json
|
|
168
|
+
- test/fixtures/kraken_asset_pairs.json
|
|
169
|
+
- test/fixtures/kraken_ticker.json
|
|
170
|
+
- test/fixtures/kucoin_orderbook_level1.json
|
|
171
|
+
- test/fixtures/kucoin_symbols.json
|
|
172
|
+
- test/fixtures/mexc_book_ticker.json
|
|
173
|
+
- test/fixtures/mexc_exchange_info.json
|
|
174
|
+
- test/honeymaker/client_test.rb
|
|
175
|
+
- test/honeymaker/clients/binance_client_test.rb
|
|
176
|
+
- test/honeymaker/clients/binance_us_client_test.rb
|
|
177
|
+
- test/honeymaker/clients/bingx_client_test.rb
|
|
178
|
+
- test/honeymaker/clients/bitget_client_test.rb
|
|
179
|
+
- test/honeymaker/clients/bitrue_client_test.rb
|
|
180
|
+
- test/honeymaker/clients/bitvavo_client_test.rb
|
|
181
|
+
- test/honeymaker/clients/bybit_client_test.rb
|
|
182
|
+
- test/honeymaker/clients/coinbase_client_test.rb
|
|
183
|
+
- test/honeymaker/clients/gemini_client_test.rb
|
|
184
|
+
- test/honeymaker/clients/honeymaker_client_registry_test.rb
|
|
185
|
+
- test/honeymaker/clients/hyperliquid_client_test.rb
|
|
186
|
+
- test/honeymaker/clients/kraken_client_test.rb
|
|
187
|
+
- test/honeymaker/clients/kraken_futures_client_test.rb
|
|
188
|
+
- test/honeymaker/clients/kucoin_client_test.rb
|
|
189
|
+
- test/honeymaker/clients/mexc_client_test.rb
|
|
190
|
+
- test/honeymaker/clients/validation_test.rb
|
|
191
|
+
- test/honeymaker/error_chain_test.rb
|
|
192
|
+
- test/honeymaker/exchange_test.rb
|
|
193
|
+
- test/honeymaker/exchanges/binance_test.rb
|
|
194
|
+
- test/honeymaker/exchanges/binance_us_test.rb
|
|
195
|
+
- test/honeymaker/exchanges/bingx_test.rb
|
|
196
|
+
- test/honeymaker/exchanges/bitget_test.rb
|
|
197
|
+
- test/honeymaker/exchanges/bitrue_test.rb
|
|
198
|
+
- test/honeymaker/exchanges/bitvavo_test.rb
|
|
199
|
+
- test/honeymaker/exchanges/bybit_test.rb
|
|
200
|
+
- test/honeymaker/exchanges/coinbase_test.rb
|
|
201
|
+
- test/honeymaker/exchanges/gemini_catalogue_test.rb
|
|
202
|
+
- test/honeymaker/exchanges/gemini_test.rb
|
|
203
|
+
- test/honeymaker/exchanges/hyperliquid_test.rb
|
|
204
|
+
- test/honeymaker/exchanges/kraken_test.rb
|
|
205
|
+
- test/honeymaker/exchanges/kucoin_test.rb
|
|
206
|
+
- test/honeymaker/exchanges/mexc_test.rb
|
|
207
|
+
- test/honeymaker/honeymaker_test.rb
|
|
208
|
+
- test/honeymaker/result_test.rb
|
|
209
|
+
- test/honeymaker/utils_test.rb
|
|
210
|
+
- test/native/backend_switch_test.rb
|
|
211
|
+
- test/native/convert_test.rb
|
|
212
|
+
- test/native/gem_isolation_test.rb
|
|
213
|
+
- test/native/loader_test.rb
|
|
214
|
+
- test/native/lockstep_test.rb
|
|
215
|
+
- test/native/signing_smoke_test.rb
|
|
216
|
+
- test/parity/kraken_client_parity_test.rb
|
|
217
|
+
- test/parity/kraken_exchange_parity_test.rb
|
|
218
|
+
- test/release/branch_hardening_test.rb
|
|
219
|
+
- test/release/push_gems_test.rb
|
|
220
|
+
- test/smoke.rb
|
|
221
|
+
- test/support/fixture_helper.rb
|
|
222
|
+
- test/support/kraken_signing_smoke.rb
|
|
223
|
+
- test/support/parity_helper.rb
|
|
224
|
+
- test/support/venue_double.rb
|
|
225
|
+
- test/test_helper.rb
|
|
226
|
+
homepage: https://github.com/deltabadger/honeymaker
|
|
227
|
+
licenses:
|
|
228
|
+
- MIT
|
|
229
|
+
metadata:
|
|
230
|
+
homepage_uri: https://github.com/deltabadger/honeymaker
|
|
231
|
+
source_code_uri: https://github.com/deltabadger/honeymaker
|
|
232
|
+
post_install_message:
|
|
233
|
+
rdoc_options: []
|
|
234
|
+
require_paths:
|
|
235
|
+
- lib
|
|
236
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
237
|
+
requirements:
|
|
238
|
+
- - ">="
|
|
239
|
+
- !ruby/object:Gem::Version
|
|
240
|
+
version: '3.4'
|
|
241
|
+
- - "<"
|
|
242
|
+
- !ruby/object:Gem::Version
|
|
243
|
+
version: 4.1.dev
|
|
244
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
245
|
+
requirements:
|
|
246
|
+
- - ">="
|
|
247
|
+
- !ruby/object:Gem::Version
|
|
248
|
+
version: '0'
|
|
249
|
+
requirements: []
|
|
250
|
+
rubygems_version: 3.5.23
|
|
251
|
+
signing_key:
|
|
252
|
+
specification_version: 4
|
|
253
|
+
summary: Ruby clients for cryptocurrency exchange APIs
|
|
254
|
+
test_files: []
|