poloniex.rb 0.0.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 +7 -0
- data/Gemfile +12 -0
- data/README.md +118 -0
- data/lib/Poloniex/Client.rb +8 -0
- data/lib/Poloniex/Configuration.rb +48 -0
- data/lib/Poloniex/Error.rb +30 -0
- data/lib/Poloniex/V1/Client.rb +235 -0
- data/lib/Poloniex/VERSION.rb +6 -0
- data/lib/poloniex.rb +9 -0
- data/poloniex.rb.gemspec +28 -0
- data/test/Poloniex/Client_test.rb +26 -0
- data/test/Poloniex/Configuration_test.rb +16 -0
- data/test/Poloniex/V1/Client_test.rb +181 -0
- data/test/helper.rb +32 -0
- data/test/poloniex_test.rb +23 -0
- metadata +67 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 70ca0c1001793f40b8103c611757c292ab05107fad90e09b73c9e5af3c45385a
|
|
4
|
+
data.tar.gz: 5ed27566cee231c459d813b9354cf576c29eec11e75fb374fb9c626339649bda
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: d5207457c2b9c8efc54531e70cc3345e51d61f80e7d7bfe1515bbaef2b74631b5501a041b6cf2df11de5f3b158baad3c20f50533575094dffaa16342164a9420
|
|
7
|
+
data.tar.gz: '092dc1a453c77c1a13d2b6b993054b1d662b9404ce6a95197b6e83ffdec65cfa2fdd26d5c4004e27583e66fcaf0f448607af7c48513afdc970ec663b38401c95'
|
data/Gemfile
ADDED
data/README.md
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# poloniex.rb
|
|
2
|
+
|
|
3
|
+
A Ruby wrapper for the Poloniex cryptocurrency exchange API.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Add this line to your application's Gemfile:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
gem 'poloniex.rb'
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
And then execute:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
$ bundle install
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Or install it yourself as:
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
$ gem install poloniex.rb
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
### Configuration
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
# Configure globally
|
|
31
|
+
Poloniex.configure do |config|
|
|
32
|
+
config.api_key = 'your_api_key'
|
|
33
|
+
config.api_secret = 'your_api_secret'
|
|
34
|
+
config.debug = false # nil by default; set to true for debugging output
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Or configure per client instance
|
|
38
|
+
client = Poloniex::Client.new(
|
|
39
|
+
api_key: 'your_api_key',
|
|
40
|
+
api_secret: 'your_api_secret',
|
|
41
|
+
debug: false # nil by default; set to true for debugging output
|
|
42
|
+
)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Public API Endpoints
|
|
46
|
+
|
|
47
|
+
```ruby
|
|
48
|
+
# Get candles for specific symbol
|
|
49
|
+
client.candles('BTC_USDT', interval: 'DAY_1', start_time: 1648995780000, end_time: 1649082180000, limit: 10)
|
|
50
|
+
|
|
51
|
+
# Get all currencies
|
|
52
|
+
client.currencies
|
|
53
|
+
|
|
54
|
+
# Get specific currency
|
|
55
|
+
client.currencies('BTC')
|
|
56
|
+
|
|
57
|
+
# Get mark prices for all symbols
|
|
58
|
+
client.mark_prices
|
|
59
|
+
|
|
60
|
+
# Get mark price for specific symbol
|
|
61
|
+
client.mark_prices('BTC_USDT')
|
|
62
|
+
|
|
63
|
+
# Get mark price components for specific symbol
|
|
64
|
+
client.mark_price_components('BTC_USDT')
|
|
65
|
+
|
|
66
|
+
# Get all markets/symbols
|
|
67
|
+
client.markets
|
|
68
|
+
|
|
69
|
+
# Get specific market/symbol
|
|
70
|
+
client.markets('BTC_USDT')
|
|
71
|
+
|
|
72
|
+
# Get order book for specific symbol
|
|
73
|
+
client.order_book('BTC_USDT', scale: '1', limit: 10)
|
|
74
|
+
|
|
75
|
+
# Get prices for all symbols
|
|
76
|
+
client.prices
|
|
77
|
+
|
|
78
|
+
# Get price for specific symbol
|
|
79
|
+
client.prices('BTC_USDT')
|
|
80
|
+
|
|
81
|
+
# Get 24h ticker for all symbols
|
|
82
|
+
client.ticker_24h
|
|
83
|
+
|
|
84
|
+
# Get 24h ticker for specific symbol
|
|
85
|
+
client.ticker_24h('BTC_USDT')
|
|
86
|
+
|
|
87
|
+
# Get server timestamp
|
|
88
|
+
client.timestamp
|
|
89
|
+
|
|
90
|
+
# Get trades for specific symbol
|
|
91
|
+
client.trades('BTC_USDT', limit: 10)
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Development
|
|
96
|
+
|
|
97
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
98
|
+
|
|
99
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
100
|
+
|
|
101
|
+
## Contributing
|
|
102
|
+
|
|
103
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/yourusername/poloniex.rb.
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
## Contributing
|
|
107
|
+
|
|
108
|
+
1. Fork it (https://github.com/thoran/bitget.rb/fork)
|
|
109
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
110
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
111
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
112
|
+
5. Create a new pull request
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
## License
|
|
117
|
+
|
|
118
|
+
The gem is available as open source under the terms of the [Ruby License](https://opensource.org/licenses/MIT).
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Poloniex/Configuration.rb
|
|
2
|
+
# Poloniex::Configuration
|
|
3
|
+
|
|
4
|
+
module Poloniex
|
|
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
|
+
:logger
|
|
27
|
+
|
|
28
|
+
def configure
|
|
29
|
+
yield(self)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def reset!
|
|
33
|
+
@api_key = nil
|
|
34
|
+
@api_secret = nil
|
|
35
|
+
@debug = false
|
|
36
|
+
@logger = nil
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
def initialize(api_key: nil, api_secret: nil, debug: nil, logger: nil)
|
|
42
|
+
@api_key = api_key
|
|
43
|
+
@api_secret = api_secret
|
|
44
|
+
@debug = debug
|
|
45
|
+
@logger = logger
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Poloniex/Error.rb
|
|
2
|
+
# Poloniex::Error
|
|
3
|
+
|
|
4
|
+
module Poloniex
|
|
5
|
+
class Error < RuntimeError
|
|
6
|
+
attr_reader\
|
|
7
|
+
:code,
|
|
8
|
+
:message,
|
|
9
|
+
:body
|
|
10
|
+
|
|
11
|
+
def to_s
|
|
12
|
+
"#{self.class} (#{@code}): #{@message}"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def initialize(code:, message:, body:)
|
|
18
|
+
@code = code
|
|
19
|
+
@message = message
|
|
20
|
+
@body = body
|
|
21
|
+
super(message)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
class APIError < Error; end
|
|
26
|
+
class AuthenticationError < Error; end
|
|
27
|
+
class InvalidRequestError < Error; end
|
|
28
|
+
class NetworkError < Error; end
|
|
29
|
+
class RateLimitError < Error; end
|
|
30
|
+
end
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
# Poloniex/V1/Client.rb
|
|
2
|
+
# Poloniex::V1::Client
|
|
3
|
+
|
|
4
|
+
require 'base64'
|
|
5
|
+
require 'fileutils'
|
|
6
|
+
gem 'http.rb'; require 'http.rb'
|
|
7
|
+
require 'json'
|
|
8
|
+
require 'logger'
|
|
9
|
+
require 'openssl'
|
|
10
|
+
|
|
11
|
+
require_relative '../Configuration'
|
|
12
|
+
require_relative '../Error'
|
|
13
|
+
|
|
14
|
+
module Poloniex
|
|
15
|
+
module V1
|
|
16
|
+
class Client
|
|
17
|
+
|
|
18
|
+
API_HOST = 'api.poloniex.com'
|
|
19
|
+
|
|
20
|
+
# Get candles for specific symbol
|
|
21
|
+
def candles(symbol, interval: 'DAY_1', start_time: nil, end_time: nil, limit: nil)
|
|
22
|
+
args = {interval: interval, startTime: start_time, endTime: end_time, limit: limit}
|
|
23
|
+
response = get(path: "/markets/#{symbol}/candles", args: args)
|
|
24
|
+
handle_response(response)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Get all currencies if no currency specified.
|
|
28
|
+
def currencies(currency = nil)
|
|
29
|
+
path = "/currencies"
|
|
30
|
+
path += "/#{currency}" if currency
|
|
31
|
+
response = get(path: path)
|
|
32
|
+
handle_response(response)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Get mark prices for all symbols if no symbol specified.
|
|
36
|
+
def mark_prices(symbol = nil)
|
|
37
|
+
path = '/markets/markPrice'
|
|
38
|
+
path = "/markets/#{symbol}/markPrice" if symbol
|
|
39
|
+
response = get(path: path)
|
|
40
|
+
handle_response(response)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Get mark price components for specific symbol
|
|
44
|
+
def mark_price_components(symbol)
|
|
45
|
+
response = get(path: "/markets/#{symbol}/markPriceComponents")
|
|
46
|
+
handle_response(response)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Get all markets/symbols if no symbol specified.
|
|
50
|
+
def markets(symbol = nil)
|
|
51
|
+
path = "/markets"
|
|
52
|
+
path += "/#{symbol}"if symbol
|
|
53
|
+
response = get(path: path)
|
|
54
|
+
handle_response(response)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Get order book for specific symbol
|
|
58
|
+
def order_book(symbol, scale: nil, limit: nil)
|
|
59
|
+
args = {scale: scale, limit: limit}
|
|
60
|
+
response = get(path: "/markets/#{symbol}/orderBook", args: args)
|
|
61
|
+
handle_response(response)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Get prices for all symbols if no symbol specified.
|
|
65
|
+
def prices(symbol = nil)
|
|
66
|
+
path = '/markets/price'
|
|
67
|
+
path = "/markets/#{symbol}/price" if symbol
|
|
68
|
+
response = get(path: path)
|
|
69
|
+
handle_response(response)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Get 24h ticker for all symbols if no symbol specified.
|
|
73
|
+
def ticker_24h(symbol = nil)
|
|
74
|
+
path = '/markets/ticker24h'
|
|
75
|
+
path = "/markets/#{symbol}/ticker24h" if symbol
|
|
76
|
+
response = get(path: path)
|
|
77
|
+
handle_response(response)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Get server timestamp
|
|
81
|
+
def timestamp
|
|
82
|
+
response = get(path: '/timestamp')
|
|
83
|
+
handle_response(response)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Get trades for specific symbol
|
|
87
|
+
def trades(symbol, limit: nil)
|
|
88
|
+
args = {limit: limit}
|
|
89
|
+
response = get(path: "/markets/#{symbol}/trades", args: args)
|
|
90
|
+
handle_response(response)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
attr_accessor\
|
|
94
|
+
:api_key,
|
|
95
|
+
:api_secret,
|
|
96
|
+
:debug,
|
|
97
|
+
:logger
|
|
98
|
+
|
|
99
|
+
private
|
|
100
|
+
|
|
101
|
+
def initialize(api_key: nil, api_secret: nil, debug: nil, logger: nil, configuration: nil)
|
|
102
|
+
@api_key = api_key || configuration&.api_key || Poloniex.configuration.api_key
|
|
103
|
+
@api_secret = api_secret || configuration&.api_secret || Poloniex.configuration.api_secret
|
|
104
|
+
@debug = debug || configuration&.debug || Poloniex.configuration.debug
|
|
105
|
+
@logger = logger || configuration&.logger || Poloniex.configuration.logger
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def request_timestamp
|
|
109
|
+
@request_timestamp ||= (Time.now.to_i * 1000).to_s
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def message(verb:, path:, args:)
|
|
113
|
+
case verb
|
|
114
|
+
when 'GET'
|
|
115
|
+
if args.empty?
|
|
116
|
+
[request_timestamp, verb, path].join
|
|
117
|
+
else
|
|
118
|
+
query_string = args.x_www_form_urlencode
|
|
119
|
+
[request_timestamp, verb, path, '?', query_string].join
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def signature(message)
|
|
125
|
+
# digest = OpenSSL::Digest.new('SHA256')
|
|
126
|
+
# hmac = OpenSSL::HMAC.digest(digest, @api_secret, message)
|
|
127
|
+
# Base64.strict_encode64(hmac)
|
|
128
|
+
OpenSSL::HMAC.hexdigest(
|
|
129
|
+
'sha256',
|
|
130
|
+
@api_secret,
|
|
131
|
+
message
|
|
132
|
+
)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def request_string(path)
|
|
136
|
+
"https://#{API_HOST}#{path}"
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def headers(signature)
|
|
140
|
+
{
|
|
141
|
+
'Content-Type' => 'application/json',
|
|
142
|
+
'key' => @api_key,
|
|
143
|
+
'signatureMethod' => 'HmacSHA256',
|
|
144
|
+
'signature' => signature,
|
|
145
|
+
'signatureVersion' => '2',
|
|
146
|
+
'timestamp' => request_timestamp
|
|
147
|
+
}
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def use_logging?
|
|
151
|
+
!@logger.nil?
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def log_args?(args)
|
|
155
|
+
!args.values.all?(&:nil?)
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def log_request(verb:, request_string:, args:, headers:)
|
|
159
|
+
log_string = "#{verb} #{request_string}\n"
|
|
160
|
+
if log_args?(args)
|
|
161
|
+
log_string << " Args: #{args}\n"
|
|
162
|
+
end
|
|
163
|
+
log_string << " Headers: #{headers}\n"
|
|
164
|
+
@logger.info(log_string)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def log_response(code:, message:, body:)
|
|
168
|
+
log_string = "Code: #{code}\n"
|
|
169
|
+
log_string << "Message: #{message}\n"
|
|
170
|
+
log_string << "Body: #{body}\n"
|
|
171
|
+
@logger.info(log_string)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def log_error(code:, message:, body:)
|
|
175
|
+
log_string = "Code: #{code}\n"
|
|
176
|
+
log_string << "Message: #{message}\n"
|
|
177
|
+
log_string << "Body: #{body}\n"
|
|
178
|
+
@logger.error(log_string)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def do_request(verb:, path:, args: {})
|
|
182
|
+
sorted_args = args.reject{|_, v| v.nil?}.sort.to_h
|
|
183
|
+
message = message(verb: verb, path: path, args: sorted_args)
|
|
184
|
+
signature = signature(message)
|
|
185
|
+
headers = headers(signature)
|
|
186
|
+
log_request(verb: verb, request_string: request_string(path), args: sorted_args, headers: headers) if use_logging?
|
|
187
|
+
@request_timestamp = nil
|
|
188
|
+
HTTP.send(verb.to_s.downcase, request_string(path), sorted_args, headers)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def get(path:, args: {})
|
|
192
|
+
do_request(verb: 'GET', path: path, args: args)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def handle_response(response)
|
|
196
|
+
if response.success?
|
|
197
|
+
parsed_body = JSON.parse(response.body)
|
|
198
|
+
log_response(code: response.code, message: response.message, body: response.body) if use_logging?
|
|
199
|
+
parsed_body
|
|
200
|
+
else
|
|
201
|
+
case response.code.to_i
|
|
202
|
+
when 400
|
|
203
|
+
log_error(code: response.code, message: response.message, body: response.body) if use_logging?
|
|
204
|
+
raise Poloniex::InvalidRequestError.new(
|
|
205
|
+
code: response.code,
|
|
206
|
+
message: response.message,
|
|
207
|
+
body: body
|
|
208
|
+
)
|
|
209
|
+
when 401
|
|
210
|
+
log_error(code: response.code, message: response.message, body: response.body) if use_logging?
|
|
211
|
+
raise Poloniex::AuthenticationError.new(
|
|
212
|
+
code: response.code,
|
|
213
|
+
message: response.message,
|
|
214
|
+
body: body
|
|
215
|
+
)
|
|
216
|
+
when 429
|
|
217
|
+
log_error(code: response.code, message: response.message, body: response.body) if use_logging?
|
|
218
|
+
raise Poloniex::RateLimitError.new(
|
|
219
|
+
code: response.code,
|
|
220
|
+
message: response.message,
|
|
221
|
+
body: body
|
|
222
|
+
)
|
|
223
|
+
else
|
|
224
|
+
log_error(code: response.code, message: response.message, body: response.body) if use_logging?
|
|
225
|
+
raise Poloniex::APIError.new(
|
|
226
|
+
code: response.code,
|
|
227
|
+
message: response.message,
|
|
228
|
+
body: body
|
|
229
|
+
)
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
end
|
data/lib/poloniex.rb
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# poloniex.rb
|
|
2
|
+
|
|
3
|
+
lib_dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
4
|
+
$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
|
|
5
|
+
|
|
6
|
+
require_relative './Poloniex/Client'
|
|
7
|
+
require_relative './Poloniex/VERSION'
|
|
8
|
+
|
|
9
|
+
module Poloniex; end
|
data/poloniex.rb.gemspec
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require_relative './lib/Poloniex/VERSION'
|
|
2
|
+
|
|
3
|
+
Gem::Specification.new do |spec|
|
|
4
|
+
spec.name = 'poloniex.rb'
|
|
5
|
+
|
|
6
|
+
spec.version = Poloniex::VERSION
|
|
7
|
+
spec.date = '2025-07-02'
|
|
8
|
+
|
|
9
|
+
spec.summary = "Access the Poloniex API with Ruby."
|
|
10
|
+
spec.description = "Access the Poloniex API with Ruby."
|
|
11
|
+
|
|
12
|
+
spec.author = 'thoran'
|
|
13
|
+
spec.email = 'code@thoran.com'
|
|
14
|
+
spec.homepage = 'http://github.com/thoran/poloniex.rb'
|
|
15
|
+
spec.license = 'Ruby'
|
|
16
|
+
|
|
17
|
+
spec.required_ruby_version = '>= 2.7'
|
|
18
|
+
|
|
19
|
+
spec.add_dependency('http.rb')
|
|
20
|
+
spec.files = [
|
|
21
|
+
'poloniex.rb.gemspec',
|
|
22
|
+
'Gemfile',
|
|
23
|
+
Dir['lib/**/*.rb'],
|
|
24
|
+
'README.md',
|
|
25
|
+
Dir['test/**/*.rb']
|
|
26
|
+
].flatten
|
|
27
|
+
spec.require_paths = ['lib']
|
|
28
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require_relative '../helper'
|
|
2
|
+
|
|
3
|
+
describe Poloniex::Client do
|
|
4
|
+
subject do
|
|
5
|
+
Poloniex::Client.new
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
before do
|
|
9
|
+
Poloniex.configure do |config|
|
|
10
|
+
config.api_key = "test_api_key"
|
|
11
|
+
config.api_secret = "test_api_secret"
|
|
12
|
+
config.debug = false
|
|
13
|
+
end
|
|
14
|
+
WebMock.disable_net_connect!(allow_localhost: true)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "inherits from Poloniex::V1::Client" do
|
|
18
|
+
_(subject).must_be_kind_of(Poloniex::V1::Client)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "can make API calls" do
|
|
22
|
+
VCR.use_cassette('v1/markets') do
|
|
23
|
+
_(subject.markets).must_be_kind_of(Array)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require_relative '../helper'
|
|
2
|
+
|
|
3
|
+
describe Poloniex::Configuration do
|
|
4
|
+
subject do
|
|
5
|
+
Poloniex::Configuration.new
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
describe "#new" do
|
|
9
|
+
it "sets default values" do
|
|
10
|
+
assert_nil(subject.api_key)
|
|
11
|
+
assert_nil(subject.api_secret)
|
|
12
|
+
assert_nil(subject.debug)
|
|
13
|
+
assert_nil(subject.logger)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
require_relative '../../helper'
|
|
2
|
+
|
|
3
|
+
describe Poloniex::V1::Client do
|
|
4
|
+
subject do
|
|
5
|
+
Poloniex::V1::Client.new
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
before do
|
|
9
|
+
Poloniex.configure do |config|
|
|
10
|
+
config.api_key = "test_api_key"
|
|
11
|
+
config.api_secret = "test_api_secret"
|
|
12
|
+
config.debug = false
|
|
13
|
+
end
|
|
14
|
+
WebMock.disable_net_connect!(allow_localhost: true)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe ".configuration" do
|
|
18
|
+
context "global configuration" do
|
|
19
|
+
it "uses global configuration by default" do
|
|
20
|
+
client = Poloniex::V1::Client.new
|
|
21
|
+
_(client).must_be_kind_of(Poloniex::V1::Client)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
context "configuration object " do
|
|
26
|
+
it "accepts a configuration object as an argument" do
|
|
27
|
+
configuration = Poloniex::Configuration.new(
|
|
28
|
+
api_key: "test_api_key",
|
|
29
|
+
api_secret: "test_api_secret",
|
|
30
|
+
debug: false
|
|
31
|
+
)
|
|
32
|
+
client = Poloniex::V1::Client.new(configuration: configuration)
|
|
33
|
+
_(client).must_be_kind_of(Poloniex::V1::Client)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
context "" do
|
|
38
|
+
it "allows overriding configuration" do
|
|
39
|
+
client = Poloniex::V1::Client.new(
|
|
40
|
+
api_key: "custom_key",
|
|
41
|
+
api_secret: "custom_secret",
|
|
42
|
+
debug: true
|
|
43
|
+
)
|
|
44
|
+
_(client).must_be_kind_of(Poloniex::V1::Client)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe "#candles" do
|
|
50
|
+
it "fetches candles for a specific symbol" do
|
|
51
|
+
VCR.use_cassette('v1/candles_btcusdt') do
|
|
52
|
+
response = subject.order_book('BTC_USDT')
|
|
53
|
+
_(response).must_be_kind_of(Hash)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
describe "#currencies" do
|
|
59
|
+
it "fetches all currencies" do
|
|
60
|
+
VCR.use_cassette("v1/currencies") do
|
|
61
|
+
response = subject.currencies
|
|
62
|
+
_(response).must_be_kind_of(Array)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "fetches a specific currency" do
|
|
67
|
+
VCR.use_cassette("v1/currencies_btc") do
|
|
68
|
+
response = subject.currencies('BTC')
|
|
69
|
+
_(response).must_be_kind_of(Hash)
|
|
70
|
+
_(response.count).must_equal(1)
|
|
71
|
+
_(response['BTC']).must_be_kind_of(Hash)
|
|
72
|
+
_(response['BTC']['name']).must_equal('Bitcoin')
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
describe "#mark_prices" do
|
|
78
|
+
it "fetches all markets" do
|
|
79
|
+
VCR.use_cassette('v1/mark_prices') do
|
|
80
|
+
response = subject.mark_prices
|
|
81
|
+
_(response).must_be_kind_of(Array)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it "fetches a specific market" do
|
|
86
|
+
VCR.use_cassette('v1/mark_prices_btcusdt') do
|
|
87
|
+
response = subject.mark_prices('BTC_USDT')
|
|
88
|
+
_(response).must_be_kind_of(Hash)
|
|
89
|
+
_(response.count).must_equal(3)
|
|
90
|
+
_(response['symbol']).must_equal('BTC_USDT')
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
describe "#mark_price_components" do
|
|
96
|
+
it "fetches all markets" do
|
|
97
|
+
VCR.use_cassette('v1/mark_price_components') do
|
|
98
|
+
response = subject.mark_price_components('BTC_USDT')
|
|
99
|
+
_(response).must_be_kind_of(Hash)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
describe "#markets" do
|
|
105
|
+
it "fetches all markets" do
|
|
106
|
+
VCR.use_cassette('v1/markets') do
|
|
107
|
+
response = subject.markets
|
|
108
|
+
_(response).must_be_kind_of(Array)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it "fetches a specific market" do
|
|
113
|
+
VCR.use_cassette('v1/markets_btcusdt') do
|
|
114
|
+
response = subject.markets('BTC_USDT')
|
|
115
|
+
_(response).must_be_kind_of(Array)
|
|
116
|
+
_(response.count).must_equal(1)
|
|
117
|
+
_(response.first['symbol']).must_equal('BTC_USDT')
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
describe "#order_book" do
|
|
123
|
+
it "fetches order book for a specific symbol" do
|
|
124
|
+
VCR.use_cassette('v1/order_book_btcusdt') do
|
|
125
|
+
response = subject.order_book('BTC_USDT')
|
|
126
|
+
_(response).must_be_kind_of(Hash)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
describe "#prices" do
|
|
132
|
+
it "fetches prices for all symbols" do
|
|
133
|
+
VCR.use_cassette('v1/prices') do
|
|
134
|
+
response = subject.prices
|
|
135
|
+
_(response).must_be_kind_of(Array)
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
it "fetches price for a specific symbol" do
|
|
140
|
+
VCR.use_cassette('v1/prices_btcusdt') do
|
|
141
|
+
response = subject.prices('BTC_USDT')
|
|
142
|
+
_(response).must_be_kind_of(Hash)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
describe "#ticker_24h" do
|
|
148
|
+
it "fetches 24h ticker for all symbols" do
|
|
149
|
+
VCR.use_cassette('v1/ticker_24h') do
|
|
150
|
+
response = subject.ticker_24h
|
|
151
|
+
_(response).must_be_kind_of(Array)
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
it "fetches 24h ticker for a specific symbol" do
|
|
156
|
+
VCR.use_cassette('v1/ticker_24h_btcusdt') do
|
|
157
|
+
response = subject.ticker_24h('BTC_USDT')
|
|
158
|
+
_(response).must_be_kind_of(Hash)
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
describe "#timestamp" do
|
|
164
|
+
it "fetches server timestamp" do
|
|
165
|
+
VCR.use_cassette("v1/timestamp") do
|
|
166
|
+
response = subject.timestamp
|
|
167
|
+
_(response).must_be_kind_of(Hash)
|
|
168
|
+
_(response["serverTime"]).must_be_kind_of(Integer)
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
describe "#trades" do
|
|
174
|
+
it "fetches trades for a specific symbol" do
|
|
175
|
+
VCR.use_cassette('v1/trades_btcusdt') do
|
|
176
|
+
response = subject.order_book('BTC_USDT')
|
|
177
|
+
_(response).must_be_kind_of(Hash)
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
data/test/helper.rb
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require 'minitest/autorun'
|
|
2
|
+
require 'minitest/spec'
|
|
3
|
+
require 'minitest-spec-context'
|
|
4
|
+
require 'vcr'
|
|
5
|
+
require 'webmock'
|
|
6
|
+
|
|
7
|
+
$LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
|
|
8
|
+
require 'poloniex'
|
|
9
|
+
|
|
10
|
+
VCR.configure do |config|
|
|
11
|
+
config.cassette_library_dir = 'test/fixtures/vcr_cassettes'
|
|
12
|
+
|
|
13
|
+
config.hook_into :webmock
|
|
14
|
+
|
|
15
|
+
config.filter_sensitive_data('<API_KEY>') { 'test_api_key' }
|
|
16
|
+
config.filter_sensitive_data('<API_SECRET>') { 'test_api_secret' }
|
|
17
|
+
|
|
18
|
+
# Allow localhost connections for debugging
|
|
19
|
+
config.ignore_localhost = true
|
|
20
|
+
|
|
21
|
+
config.default_cassette_options = {
|
|
22
|
+
record: :new_episodes,
|
|
23
|
+
match_requests_on: [:method, :uri]
|
|
24
|
+
}
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class Minitest::Test
|
|
28
|
+
def before_setup
|
|
29
|
+
super
|
|
30
|
+
Poloniex.reset_configuration!
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require_relative './helper'
|
|
2
|
+
|
|
3
|
+
describe Poloniex do
|
|
4
|
+
it "has a version number" do
|
|
5
|
+
_(Poloniex::VERSION).must_be_kind_of(String)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
describe ".configure" do
|
|
9
|
+
it "allows setting configuration values" do
|
|
10
|
+
Poloniex.configure do |config|
|
|
11
|
+
config.api_key = "test_key"
|
|
12
|
+
config.api_secret = "test_secret"
|
|
13
|
+
config.debug = true
|
|
14
|
+
config.logger = './log.txt'
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
_(Poloniex.configuration.api_key).must_equal("test_key")
|
|
18
|
+
_(Poloniex.configuration.api_secret).must_equal("test_secret")
|
|
19
|
+
_(Poloniex.configuration.debug).must_equal(true)
|
|
20
|
+
_(Poloniex.configuration.logger).must_equal('./log.txt')
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: poloniex.rb
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- thoran
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 2025-07-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: http.rb
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0'
|
|
26
|
+
description: Access the Poloniex API with Ruby.
|
|
27
|
+
email: code@thoran.com
|
|
28
|
+
executables: []
|
|
29
|
+
extensions: []
|
|
30
|
+
extra_rdoc_files: []
|
|
31
|
+
files:
|
|
32
|
+
- Gemfile
|
|
33
|
+
- README.md
|
|
34
|
+
- lib/Poloniex/Client.rb
|
|
35
|
+
- lib/Poloniex/Configuration.rb
|
|
36
|
+
- lib/Poloniex/Error.rb
|
|
37
|
+
- lib/Poloniex/V1/Client.rb
|
|
38
|
+
- lib/Poloniex/VERSION.rb
|
|
39
|
+
- lib/poloniex.rb
|
|
40
|
+
- poloniex.rb.gemspec
|
|
41
|
+
- test/Poloniex/Client_test.rb
|
|
42
|
+
- test/Poloniex/Configuration_test.rb
|
|
43
|
+
- test/Poloniex/V1/Client_test.rb
|
|
44
|
+
- test/helper.rb
|
|
45
|
+
- test/poloniex_test.rb
|
|
46
|
+
homepage: http://github.com/thoran/poloniex.rb
|
|
47
|
+
licenses:
|
|
48
|
+
- Ruby
|
|
49
|
+
metadata: {}
|
|
50
|
+
rdoc_options: []
|
|
51
|
+
require_paths:
|
|
52
|
+
- lib
|
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
54
|
+
requirements:
|
|
55
|
+
- - ">="
|
|
56
|
+
- !ruby/object:Gem::Version
|
|
57
|
+
version: '2.7'
|
|
58
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
59
|
+
requirements:
|
|
60
|
+
- - ">="
|
|
61
|
+
- !ruby/object:Gem::Version
|
|
62
|
+
version: '0'
|
|
63
|
+
requirements: []
|
|
64
|
+
rubygems_version: 3.6.9
|
|
65
|
+
specification_version: 4
|
|
66
|
+
summary: Access the Poloniex API with Ruby.
|
|
67
|
+
test_files: []
|