gate.rb 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/gate.rb.gemspec +1 -1
- data/lib/Gate/Configuration.rb +45 -0
- data/lib/Gate/Error.rb +1 -0
- data/lib/Gate/V4/Client.rb +69 -17
- data/lib/Gate/VERSION.rb +1 -1
- data/lib/gate.rb +1 -0
- data/test/Gate/Configuration_test.rb +13 -0
- data/test/Gate/V4/Client/test_private_endpoints.rb +99 -1
- data/test/helper.rb +2 -3
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: af5b0afadf1a2aba9eba70064c5fc2503477d45569d27a5cfacfe0798d1ea3f0
|
4
|
+
data.tar.gz: 4c9cd963ac62156e5e0ae6c1b73c50c82c13cbeaacd15ed8c6ab657bcd5dfe50
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ced56131ac508a3cbb25b6cdb14f1e0382b7d91bf57bcecd452169158daee8f595dddabeb3ef820aaedb47362348a4613c69c76f2d5f9c4d69b47ac8a30488ca
|
7
|
+
data.tar.gz: 3aab85b7ba081c0de10770cf8123e22358bd84d66524f1dc3a7f156dd1589e1219ae2a296484710ac0df59ad60da0c94e32f64b0e232d4a3a243b5c180201289
|
data/gate.rb.gemspec
CHANGED
@@ -0,0 +1,45 @@
|
|
1
|
+
# Gate/Configuration.rb
|
2
|
+
# Gate::Configuration
|
3
|
+
|
4
|
+
module Gate
|
5
|
+
class << self
|
6
|
+
attr_writer :configuration
|
7
|
+
|
8
|
+
def configuration
|
9
|
+
@configuration ||= Configuration.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def configure
|
13
|
+
yield(configuration)
|
14
|
+
end
|
15
|
+
|
16
|
+
def reset_configuration!
|
17
|
+
@configuration = Configuration.new
|
18
|
+
end
|
19
|
+
end # class << self
|
20
|
+
|
21
|
+
class Configuration
|
22
|
+
attr_accessor\
|
23
|
+
:api_key,
|
24
|
+
:api_secret,
|
25
|
+
:debug,
|
26
|
+
|
27
|
+
def configure
|
28
|
+
yield(self)
|
29
|
+
end
|
30
|
+
|
31
|
+
def reset!
|
32
|
+
@api_key = nil
|
33
|
+
@api_secret = nil
|
34
|
+
@debug = false
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def initialize(api_key: nil, api_secret: nil, debug: nil)
|
40
|
+
@api_key = api_key
|
41
|
+
@api_secret = api_secret
|
42
|
+
@debug = debug
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/Gate/Error.rb
CHANGED
data/lib/Gate/V4/Client.rb
CHANGED
@@ -120,6 +120,13 @@ module Gate
|
|
120
120
|
handle_response(response)
|
121
121
|
end
|
122
122
|
|
123
|
+
# Private endpoints
|
124
|
+
|
125
|
+
def wallet_total_balance(currency: nil)
|
126
|
+
response = get(path: '/wallet/total_balance', args: {currency: currency})
|
127
|
+
handle_response(response)
|
128
|
+
end
|
129
|
+
|
123
130
|
def spot_orders(
|
124
131
|
text: nil,
|
125
132
|
currency_pair:,
|
@@ -149,20 +156,63 @@ module Gate
|
|
149
156
|
handle_response(response)
|
150
157
|
end
|
151
158
|
|
159
|
+
def spot_my_trades(
|
160
|
+
currency_pair: nil,
|
161
|
+
limit: nil,
|
162
|
+
page: nil,
|
163
|
+
order_id: nil,
|
164
|
+
account: nil,
|
165
|
+
from: nil,
|
166
|
+
to: nil
|
167
|
+
)
|
168
|
+
args = {
|
169
|
+
currency_pair: currency_pair,
|
170
|
+
limit: limit,
|
171
|
+
page: page,
|
172
|
+
order_id: order_id,
|
173
|
+
account: account,
|
174
|
+
from: from,
|
175
|
+
to: to
|
176
|
+
}.reject{|k,v| v.nil?}.stringify_values
|
177
|
+
response = get(
|
178
|
+
path: '/spot/my_trades',
|
179
|
+
args: args
|
180
|
+
)
|
181
|
+
handle_response(response)
|
182
|
+
end
|
183
|
+
|
152
184
|
private
|
153
185
|
|
154
|
-
def initialize(api_key
|
155
|
-
@api_key = api_key.encode('UTF-8')
|
156
|
-
@api_secret = api_secret.encode('UTF-8')
|
186
|
+
def initialize(api_key: nil, api_secret: nil, configuration: nil)
|
187
|
+
@api_key = (api_key || configuration&.api_key || Gate.configuration.api_key).encode('UTF-8')
|
188
|
+
@api_secret = (api_secret || configuration&.api_secret || Gate.configuration.api_secret).encode('UTF-8')
|
157
189
|
end
|
158
190
|
|
159
191
|
def full_path(path)
|
160
192
|
self.class.path_prefix + path
|
161
193
|
end
|
162
194
|
|
163
|
-
def
|
164
|
-
|
165
|
-
|
195
|
+
def query_string(verb:, args:)
|
196
|
+
case verb
|
197
|
+
when 'GET'
|
198
|
+
args.x_www_form_urlencode
|
199
|
+
when 'POST'
|
200
|
+
nil
|
201
|
+
else
|
202
|
+
raise "The verb, #{verb}, is not acceptable."
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def encoded_payload(verb:, args:)
|
207
|
+
case verb
|
208
|
+
when 'GET'
|
209
|
+
OpenSSL::Digest::SHA512.hexdigest('')
|
210
|
+
when 'POST'
|
211
|
+
args.reject!{|k,v| v.nil?}
|
212
|
+
OpenSSL::Digest::SHA512.hexdigest(JSON.dump(args))
|
213
|
+
else
|
214
|
+
raise "The verb, #{verb}, is not acceptable."
|
215
|
+
end
|
166
216
|
end
|
167
217
|
|
168
218
|
def timestamp
|
@@ -170,17 +220,13 @@ module Gate
|
|
170
220
|
end
|
171
221
|
|
172
222
|
def message(verb:, path:, args:)
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
raise "The verb, #{verb}, is not acceptable."
|
181
|
-
end
|
182
|
-
)
|
183
|
-
[verb, full_path(path), query_string, encoded_payload(args), timestamp].join("\n")
|
223
|
+
[
|
224
|
+
verb,
|
225
|
+
full_path(path),
|
226
|
+
query_string(verb: verb, args: args),
|
227
|
+
encoded_payload(verb: verb, args: args),
|
228
|
+
timestamp
|
229
|
+
].join("\n")
|
184
230
|
end
|
185
231
|
|
186
232
|
def signature(message)
|
@@ -234,6 +280,12 @@ module Gate
|
|
234
280
|
message: response.message,
|
235
281
|
body: response.body
|
236
282
|
)
|
283
|
+
when 403
|
284
|
+
raise Gate::InsufficientPermissionError.new(
|
285
|
+
code: response.code,
|
286
|
+
message: response.message,
|
287
|
+
body: response.body
|
288
|
+
)
|
237
289
|
when 429
|
238
290
|
raise Gate::RateLimitError.new(
|
239
291
|
code: response.code,
|
data/lib/Gate/VERSION.rb
CHANGED
data/lib/gate.rb
CHANGED
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
|
3
|
+
describe Gate::Configuration do
|
4
|
+
describe "#initialize" do
|
5
|
+
it "sets default values" do
|
6
|
+
config = Gate::Configuration.new
|
7
|
+
_(config.api_base_url).to eq('https://api.gateio.ws')
|
8
|
+
_(config.debug).to eq(false)
|
9
|
+
_(config.api_key).must_equal(nil)
|
10
|
+
_(config.api_secret).must_equal(nil)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -11,6 +11,57 @@ describe Gate::V4::Client do
|
|
11
11
|
)
|
12
12
|
end
|
13
13
|
|
14
|
+
describe "#wallet_total_balance" do
|
15
|
+
let(:amount){0.0001}
|
16
|
+
let(:price){100_000}
|
17
|
+
let(:side){'buy'}
|
18
|
+
|
19
|
+
context "success" do
|
20
|
+
it "fetches my wallet balance for a specific market" do
|
21
|
+
VCR.use_cassette('v4/wallet/total_balance') do
|
22
|
+
response = subject.wallet_total_balance(currency: 'BTC')
|
23
|
+
_(response).must_be_kind_of(Hash)
|
24
|
+
assert(response['details'])
|
25
|
+
assert(response['details']['delivery'])
|
26
|
+
_(response['details']['delivery']['currency']).must_equal('BTC')
|
27
|
+
_(response['details']['delivery']['amount']).must_equal('0')
|
28
|
+
assert(response['details']['finance'])
|
29
|
+
_(response['details']['finance']['currency']).must_equal('BTC')
|
30
|
+
_(response['details']['finance']['amount']).must_equal('0')
|
31
|
+
assert(response['details']['futures'])
|
32
|
+
_(response['details']['futures']['currency']).must_equal('BTC')
|
33
|
+
_(response['details']['futures']['amount']).must_equal('0')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "invalid key" do
|
39
|
+
let(:api_key){'invalid_key'}
|
40
|
+
let(:api_secret){'invalid_secret'}
|
41
|
+
|
42
|
+
it "raises an error" do
|
43
|
+
VCR.use_cassette('v4/wallet/total_balance_with_an_invalid_key') do
|
44
|
+
assert_raises do
|
45
|
+
subject.wallet_total_balance(currency: 'BTC')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context "insufficient permission" do
|
52
|
+
let(:api_key){'key_with_insufficient_permission'}
|
53
|
+
let(:api_secret){'secret_with_insufficient_permission'}
|
54
|
+
|
55
|
+
it "raises an error" do
|
56
|
+
VCR.use_cassette('v4/wallet/total_balance_with_insufficient_permission') do
|
57
|
+
assert_raises do
|
58
|
+
subject.spot_orders(currency: 'BTC')
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
14
65
|
describe "#spot_orders" do
|
15
66
|
let(:amount){0.0001}
|
16
67
|
let(:price){100_000}
|
@@ -31,7 +82,10 @@ describe Gate::V4::Client do
|
|
31
82
|
end
|
32
83
|
|
33
84
|
context "invalid key" do
|
34
|
-
|
85
|
+
let(:api_key){'invalid_key'}
|
86
|
+
let(:api_secret){'invalid_secret'}
|
87
|
+
|
88
|
+
it "raises an error" do
|
35
89
|
VCR.use_cassette('v4/spot/orders_with_an_invalid_key') do
|
36
90
|
assert_raises do
|
37
91
|
subject.spot_orders(currency_pair: 'BTC_USDT', side: side, amount: amount, time_in_force: 'gtc', price: price)
|
@@ -39,5 +93,49 @@ describe Gate::V4::Client do
|
|
39
93
|
end
|
40
94
|
end
|
41
95
|
end
|
96
|
+
|
97
|
+
context "insufficient permission" do
|
98
|
+
let(:api_key){'key_with_insufficient_permission'}
|
99
|
+
let(:api_secret){'secret_with_insufficient_permission'}
|
100
|
+
|
101
|
+
it "raises an error" do
|
102
|
+
VCR.use_cassette('v4/spot/orders_with_insufficient_permission') do
|
103
|
+
assert_raises do
|
104
|
+
subject.spot_orders(currency_pair: 'BTC_USDT', side: side, amount: amount, time_in_force: 'gtc', price: price)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe "#spot_my_trades" do
|
112
|
+
context "success" do
|
113
|
+
it "fetches my trading history" do
|
114
|
+
VCR.use_cassette('v4/spot/my_trades') do
|
115
|
+
response = subject.spot_my_trades(currency_pair: 'BTC5S_USDT')
|
116
|
+
_(response).must_be_kind_of(Array)
|
117
|
+
_(response.first).must_be_kind_of(Hash)
|
118
|
+
assert(response.first['id'])
|
119
|
+
assert(response.first['create_time'])
|
120
|
+
assert(response.first['currency_pair'])
|
121
|
+
assert(response.first['amount'])
|
122
|
+
assert(response.first['price'])
|
123
|
+
assert(['buy', 'sell'].include?(response.first['side']))
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
context "invalid key" do
|
129
|
+
let(:api_key){'invalid_key'}
|
130
|
+
let(:api_secret){'invalid_secret'}
|
131
|
+
|
132
|
+
it "raises an error" do
|
133
|
+
VCR.use_cassette('v4/spot/my_trades_with_an_invalid_key') do
|
134
|
+
assert_raises do
|
135
|
+
subject.spot_my_trades(currency_pair: 'BTC_USDT')
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
42
140
|
end
|
43
141
|
end
|
data/test/helper.rb
CHANGED
@@ -9,18 +9,17 @@ require 'gate'
|
|
9
9
|
|
10
10
|
VCR.configure do |config|
|
11
11
|
config.cassette_library_dir = 'test/fixtures/vcr_cassettes'
|
12
|
-
|
13
12
|
config.hook_into :webmock
|
14
13
|
|
15
14
|
config.filter_sensitive_data('<API_KEY>'){ENV['GATE_API_KEY']}
|
16
|
-
config.filter_sensitive_data('<API_SECRET>'){ENV['GATE_API_SECRET']
|
15
|
+
config.filter_sensitive_data('<API_SECRET>'){ENV['GATE_API_SECRET']}
|
17
16
|
|
18
17
|
# Allow localhost connections for debugging
|
19
18
|
config.ignore_localhost = true
|
20
19
|
|
21
20
|
config.default_cassette_options = {
|
22
21
|
record: :new_episodes,
|
23
|
-
match_requests_on: [:method, :uri]
|
22
|
+
match_requests_on: [:method, :uri, :body]
|
24
23
|
}
|
25
24
|
end
|
26
25
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gate.rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- thoran
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-07-
|
10
|
+
date: 2025-07-17 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: http.rb
|
@@ -33,6 +33,7 @@ files:
|
|
33
33
|
- README.md
|
34
34
|
- gate.rb.gemspec
|
35
35
|
- lib/Gate/Client.rb
|
36
|
+
- lib/Gate/Configuration.rb
|
36
37
|
- lib/Gate/Error.rb
|
37
38
|
- lib/Gate/V4/Client.rb
|
38
39
|
- lib/Gate/VERSION.rb
|
@@ -41,6 +42,7 @@ files:
|
|
41
42
|
- lib/Thoran/Hash/XWwwFormUrlencode/x_www_form_urlencode.rb
|
42
43
|
- lib/Thoran/String/UrlEncode/url_encode.rb
|
43
44
|
- lib/gate.rb
|
45
|
+
- test/Gate/Configuration_test.rb
|
44
46
|
- test/Gate/V4/Client/test_private_endpoints.rb
|
45
47
|
- test/Gate/V4/Client/test_public_endpoints.rb
|
46
48
|
- test/helper.rb
|