binance-connector-ruby 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 528658559216256c1f8a39559437b3faf6e4b0e834fbca24f7d4c46a12c6b045
4
+ data.tar.gz: ea13e85275dd64c727b73144c92931b07694c85456beee884d8850cd177d5298
5
+ SHA512:
6
+ metadata.gz: bb20b597d4b9a95248a440a08a57b33765c095c9f529998bc91136ceaaded6ad0074f93980fb46694fa2a0e3aa7a6aa1c158ceffaf921381c645bd4db4fc2c0d
7
+ data.tar.gz: 40f14e2adda863fc0812e45ab56f137ee3f80f7f33565f30be2279a0bb1facec6a8117f68b52904fc7c979d728ed2098871165a987e91b0ddf6ff91391e9d2be
data/CHANGELOG.md ADDED
@@ -0,0 +1,6 @@
1
+ # Changelog
2
+
3
+ ## 1.0.0 - 2021-11-18
4
+
5
+ ### Added
6
+ - First release
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 Binance
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,224 @@
1
+ # Binance Connector Ruby
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/binance-connector.svg)](https://badge.fury.io/rb/binance-connector)
4
+ [![Ruby Style Guide](https://img.shields.io/badge/code_style-rubocop-brightgreen.svg)](https://github.com/rubocop-hq/rubocop)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+
7
+ This is a lightweight library that works as a connector to [Binance public API](https://github.com/binance/binance-spot-api-docs). It’s designed to be simple, clean, and easy to use with minimal dependencies.
8
+
9
+ - Supported APIs:
10
+ - `/api/*`
11
+ - `/sapi/*`
12
+ - Spot Websocket Market Stream
13
+ - Spot User Data Stream
14
+ - Inclusion of test cases and examples
15
+ - Customizable base URL, request timeout
16
+ - Response metadata can be displayed
17
+ - Customizable Logger
18
+
19
+ ## Installation
20
+
21
+ 1. Include the library in Gemfile and then install it when execute the bundler.
22
+
23
+ Add this line in the Gemfile.
24
+
25
+ ```ruby
26
+ gem 'binance-connector'
27
+ ```
28
+
29
+ And then execute the bundler via CLI:
30
+
31
+ ```shell
32
+ bundle
33
+ ```
34
+ 2. Install it with CLI:
35
+ ```shell
36
+ gem install binance-connector
37
+ ```
38
+ ## Documentation
39
+
40
+ [https://www.rubydoc.info/gems/binance-connector](https://www.rubydoc.info/gems/binance-connector)
41
+ ## Restful APIs
42
+
43
+ ```ruby
44
+ require 'binance'
45
+
46
+ # Create a new client instance.
47
+ # If the APIs do not require the keys, (e.g. market data), key and secret can be omitted.
48
+ client = Binance::Spot.new(key: key, secret: secret)
49
+
50
+ # Send a request to query server time
51
+ puts client.time
52
+
53
+ # Send a request to query BTCUSDT ticker
54
+ puts client.ticker_24hr(symbol: 'BTCUSDT')
55
+
56
+ # Send a request to get account information
57
+ puts client.account
58
+
59
+ # Place an order
60
+ response = client.new_order(symbol: 'BNBUSDT', side: 'BUY', price: 20, quantity: 1, type: 'LIMIT', timeInForce: 'GTC')
61
+ ```
62
+
63
+
64
+ Please find `examples` folder to check for more endpoints.
65
+
66
+
67
+ ### Testnet
68
+
69
+ While `/sapi/*` endpoints don't have testnet environment yet, `/api/*` endpoints can be tested in
70
+ [Spot Testnet](https://testnet.binance.vision/). You can use it by changing the base URL:
71
+
72
+ ```ruby
73
+ client = Binance::Spot.new(base_url: 'https://testnet.binance.vision')
74
+ puts client.time
75
+ ```
76
+
77
+ ### Base URL
78
+
79
+ If `base_url` is not provided, it defaults to `api.binance.com`.
80
+
81
+ It's recommended to pass in the `base_url` parameter, even in production as Binance provides alternative URLs in case of performance issues:
82
+
83
+ - `https://api1.binance.com`
84
+ - `https://api2.binance.com`
85
+ - `https://api3.binance.com`
86
+
87
+ ### RecvWindow
88
+
89
+ From Binance API, recvWindow is available for all endpoints require signature. By default, it's 5000ms.
90
+ You are allowed to set this parameter to any value less than 60000, number beyond this limit will receive error from Binance server.
91
+ ```ruby
92
+
93
+ response = client.account(recvWindow: 2_000)
94
+
95
+ ```
96
+
97
+ ### Optional parameters
98
+
99
+ For the optional parameters in the endpoint, pass exactly the field name from API document into method.
100
+ e.g
101
+
102
+ ```ruby
103
+ client = Binance::Spot.new
104
+
105
+ # correct
106
+ response = client.cancel_order(symbol: 'BNBUSDT', orderId: 25)
107
+
108
+ # this is incorrect
109
+ response = client.cancel_order(symbol: 'BNBUSDT', order_id: 25)
110
+ ```
111
+
112
+ ### Timeout
113
+
114
+ Timeout (unit: second) can be specified when initializing a client instance. If `timeout` is not set, the default is **no timeout**.
115
+
116
+ ```ruby
117
+ client = Binance::Spot.new(timeout: 2)
118
+ ```
119
+
120
+ ### Response Metadata
121
+
122
+ The Binance API server provides weight usages in the headers of each response. This information can be fetched from `headers` property. `x-mbx-used-weight` and `x-mbx-used-weight-1m` show the total weight consumed within 1 minute. This is very useful to indentify the current usage.
123
+ To display this value, specify `show_weight_usage: true` when intializing a new client instance.
124
+
125
+ ```ruby
126
+ client = Binance::Spot.new(show_weight_usage: true)
127
+ ```
128
+
129
+ Then, take server time API (`GET /api/v3/time`) as an example, the response data is shown as below:
130
+
131
+ ```ruby
132
+ {:data=>{:serverTime=>1589860878546}, :weight_usage=>{"x-mbx-used-weight"=>"1", "x-mbx-used-weight-1m"=>"1"}}
133
+ ```
134
+
135
+ When `show_header: true`, the library has the ability to print out all response headers, which may be very helpful for debugging the program.
136
+
137
+ ```ruby
138
+ client = Binance::Spot.new(show_header: true)
139
+ ```
140
+
141
+ Then, take the same example as above, the response data becomes:
142
+
143
+ ```ruby
144
+ {:data=>{:serverTime=>1589863539220}, :header=>{"content-type"=>"application/json;charset=utf-8",...}}
145
+ ```
146
+
147
+ ### Custom Logger Integration
148
+
149
+ The client class accepts a [Logger](https://ruby-doc.org/stdlib-2.4.0/libdoc/logger/rdoc/Logger.html) instance as an input parameter.
150
+
151
+ ```ruby
152
+ logger = Logger.new(STDOUT)
153
+ client = Binance::Spot.new(logger: logger)
154
+ logger.info(client.time)
155
+ ```
156
+
157
+ ### Exception
158
+
159
+ There are 3 types of exceptions:
160
+ - `Binance::RequiredParameterError`
161
+ - When missing required param
162
+ - Not sending out the request
163
+ - `Binance::ClientError`
164
+ - This is thrown when API server returns `4XX`, it's an issue from client side.
165
+ - The following properties may be helpful to resolve the issue:
166
+ - Response header - Please refer to `Response Metadata` section for more details.
167
+ - HTTP status code
168
+ - Error code - Server's error code, e.g. `-1102`
169
+ - Error message - Server's error message, e.g. `Unknown order sent.`
170
+ - Request config - Configuration send to the server, which can include URL, request method and headers.
171
+ - `Binance::ServerError`
172
+ - When API server returning 5XX
173
+ - sending out the request
174
+
175
+ They all inherit from `Binance::Error`
176
+
177
+ ```ruby
178
+ begin
179
+ response = client.time
180
+ rescue Binance::ClientError => e
181
+ e.response[:status]
182
+ e.response[:headers]
183
+ e.response[:body]
184
+ end
185
+ ```
186
+
187
+ ## Websocket
188
+
189
+ ```ruby
190
+ require 'binance'
191
+ require 'eventmachine'
192
+
193
+ client = Binance::Spot::WebSocket.new
194
+
195
+ EM.run do
196
+ onopen = proc { logger.info('connected to server') }
197
+ onmessage = proc { |msg, _type| logger.info(msg) }
198
+ onerror = proc { |e| logger.error(e) }
199
+ onclose = proc { logger.info('connection closed') }
200
+
201
+ callbacks = {
202
+ onopen: onopen,
203
+ onmessage: onmessage,
204
+ onerror: onerror,
205
+ onclose: onclose
206
+ }
207
+
208
+ client.kline(symbol: 'btcusdt', interval: '30m', callbacks: callbacks)
209
+ end
210
+ ```
211
+
212
+ More websocket examples are available in the `examples` folder
213
+
214
+ ### Auto response
215
+ Binance requires `pong` for heartbeat, response is sent automatically.
216
+
217
+ ## Limitation
218
+
219
+ Futures and Vanilla Options APIs are not supported:
220
+
221
+ - `/fapi/*`
222
+ - `/dapi/*`
223
+ - `/vapi/*`
224
+ - Associated Websocket Market and User Data Streams
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Binance
4
+ # Authentication response to API key and signature
5
+ class Authentication
6
+ attr_accessor :key, :secret
7
+
8
+ def initialize(key, secret)
9
+ @key = key
10
+ @secret = secret
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Binance
4
+ class Error < StandardError; end
5
+
6
+ # Client error from 400 - 499
7
+ class ClientError < Error
8
+ attr_reader :response
9
+
10
+ def initialize(response = nil)
11
+ @response = response
12
+ super(response)
13
+ end
14
+ end
15
+
16
+ # Server side error for 5xx
17
+ class ServerError < Error
18
+ end
19
+
20
+ # Error when missing required params
21
+ class RequiredParameterError < Error
22
+ def initialize(param_name, param_value)
23
+ super(
24
+ "ValidationFailed: #{param_name} is required, but provided value: #{param_value}"
25
+ )
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'faraday'
4
+ require 'binance/utils/faraday/middleware'
5
+ require 'binance/utils/faraday/custom_params_encoder'
6
+
7
+ module Binance
8
+ # Session has the http request connection
9
+ class Session
10
+ include Binance::Utils::Faraday::Middleware
11
+
12
+ def initialize(options = {})
13
+ @base_url = options[:base_url] || 'https://api.binance.com'
14
+ @auth = Authentication.new(options[:key], options[:secret])
15
+ @logger = options[:logger]
16
+ @show_weight_usage = options[:show_weight_usage] || false
17
+ @show_header = options[:show_header] || false
18
+ @timeout = options[:timeout]
19
+ end
20
+
21
+ def public_request(path: '/', params: {})
22
+ process_request(public_conn, :get, path, params)
23
+ end
24
+
25
+ def limit_request(method: :get, path: '/', params: {})
26
+ process_request(limit_conn, method, path, params)
27
+ end
28
+
29
+ def sign_request(method, path, params: {})
30
+ process_request(signed_conn, method, path, params)
31
+ end
32
+
33
+ private
34
+
35
+ def process_request(conn, method, path, params)
36
+ response = conn.send(method, path_with_query(path, params.compact), nil)
37
+ extract_response(response)
38
+ rescue Faraday::ClientError => e
39
+ raise Binance::ClientError, e.response
40
+ rescue Faraday::ServerError => e
41
+ raise Binance::ServerError, e
42
+ end
43
+
44
+ def extract_response(response)
45
+ begin
46
+ data = JSON.parse(response.body, symbolize_names: true)
47
+ rescue JSON::ParserError
48
+ data = response.body
49
+ end
50
+
51
+ return data if !@show_header && !@show_weight_usage
52
+
53
+ res = { data: data }
54
+ res[:header] = response.headers if @show_header
55
+ res[:weight_usage] = response.headers.select { |k, _| weight_usage?(k) } if @show_weight_usage
56
+ res
57
+ end
58
+
59
+ def weight_usage?(key)
60
+ key.start_with?('x-mbx-used-weight') || key.start_with?('x-sapi-used')
61
+ end
62
+
63
+ def path_with_query(path, params)
64
+ "#{path}?#{Binance::Utils::Url.build_query(params)}"
65
+ end
66
+
67
+ def public_conn
68
+ build_connection
69
+ end
70
+
71
+ def limit_conn
72
+ build_connection do |conn|
73
+ conn.headers['X-MBX-APIKEY'] = @auth.key
74
+ end
75
+ end
76
+
77
+ def signed_conn
78
+ build_connection do |conn|
79
+ conn.headers['X-MBX-APIKEY'] = @auth.key
80
+ conn.use Timestamp
81
+ conn.use Signature, @auth.secret
82
+ end
83
+ end
84
+
85
+ def build_connection
86
+ Faraday.new(url: @base_url) do |client|
87
+ prepare_headers(client)
88
+ client.options.timeout = @timeout
89
+ client.options.params_encoder = Binance::Utils::Faraday::CustomParamsEncoder
90
+ yield client if block_given?
91
+ client.use Faraday::Response::RaiseError
92
+ logger_response(client)
93
+ client.adapter Faraday.default_adapter
94
+ end
95
+ end
96
+
97
+ def logger_response(client)
98
+ client.response :logger, @logger if @logger
99
+ end
100
+
101
+ def prepare_headers(client)
102
+ client.headers['Content-Type'] = 'application/json'
103
+ client.headers['User-Agent'] = "binance-connector-ruby/#{Binance::VERSION}"
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Binance
4
+ class Spot
5
+ # BLVT endpoints
6
+ # @see https://binance-docs.github.io/apidocs/spot/en/#blvt-endpoints
7
+ module Blvt
8
+ # Get BLVT Info (MARKET_DATA)
9
+ #
10
+ # GET /sapi/v1/blvt/tokenInfo
11
+ #
12
+ # @param tokenName [String]
13
+ # @see https://binance-docs.github.io/apidocs/spot/en/#get-blvt-info-market_data
14
+ def token_info(tokenName: nil)
15
+ @session.public_request(
16
+ path: '/sapi/v1/blvt/tokenInfo',
17
+ params: { tokenName: tokenName }
18
+ )
19
+ end
20
+
21
+ # Subscribe BLVT (USER_DATA)
22
+ #
23
+ # POST /sapi/v1/blvt/subscribe
24
+ #
25
+ # @param tokenName [String]
26
+ # @param cost [Float]
27
+ # @param kwargs [Hash]
28
+ # @option kwargs [Integer] :recvWindow The value cannot be greater than 60000
29
+ # @see https://binance-docs.github.io/apidocs/spot/en/#subscribe-blvt-user_data
30
+ def subscribe(tokenName:, cost:, **kwargs)
31
+ Binance::Utils::Validation.require_param('tokenName', tokenName)
32
+ Binance::Utils::Validation.require_param('cost', cost)
33
+
34
+ @session.sign_request(:post, '/sapi/v1/blvt/subscribe', params: kwargs.merge(
35
+ tokenName: tokenName,
36
+ cost: cost
37
+ ))
38
+ end
39
+
40
+ # Query Subscription Record (USER_DATA)
41
+ #
42
+ # GET /sapi/v1/blvt/subscribe/record
43
+ #
44
+ # @param kwargs [Hash]
45
+ # @option kwargs [String] :tokenName
46
+ # @option kwargs [Integer] :id
47
+ # @option kwargs [Integer] :startTime
48
+ # @option kwargs [Integer] :endTime
49
+ # @option kwargs [Integer] :limit
50
+ # @option kwargs [Integer] :recvWindow The value cannot be greater than 60000
51
+ # @see https://binance-docs.github.io/apidocs/spot/en/#query-subscription-record-user_data
52
+ def get_subscribe_record(**kwargs)
53
+ @session.sign_request(:get, '/sapi/v1/blvt/subscribe/record', params: kwargs)
54
+ end
55
+
56
+ # Redeem BLVT (USER_DATA)
57
+ #
58
+ # POST /sapi/v1/blvt/redeem
59
+ #
60
+ # @param tokenName [String]
61
+ # @param amount [Float]
62
+ # @param kwargs [Hash]
63
+ # @option kwargs [Integer] :recvWindow The value cannot be greater than 60000
64
+ # @see https://binance-docs.github.io/apidocs/spot/en/#redeem-blvt-user_data
65
+ def redeem(tokenName:, amount:, **kwargs)
66
+ Binance::Utils::Validation.require_param('tokenName', tokenName)
67
+ Binance::Utils::Validation.require_param('amount', amount)
68
+
69
+ @session.sign_request(:post, '/sapi/v1/blvt/redeem', params: kwargs.merge(
70
+ tokenName: tokenName,
71
+ amount: amount
72
+ ))
73
+ end
74
+
75
+ # Query Redemption Record (USER_DATA)
76
+ #
77
+ # GET /sapi/v1/blvt/redeem/record
78
+ #
79
+ # @param kwargs [Hash]
80
+ # @option kwargs [String] :tokenName
81
+ # @option kwargs [Integer] :id
82
+ # @option kwargs [Integer] :startTime
83
+ # @option kwargs [Integer] :endTime
84
+ # @option kwargs [Integer] :limit
85
+ # @option kwargs [Integer] :recvWindow The value cannot be greater than 60000
86
+ # @see https://binance-docs.github.io/apidocs/spot/en/#query-redemption-record-user_data
87
+ def get_redeem_record(**kwargs)
88
+ @session.sign_request(:get, '/sapi/v1/blvt/redeem/record', params: kwargs)
89
+ end
90
+
91
+ # Get BLVT User Limit Info (USER_DATA)
92
+ #
93
+ # GET /sapi/v1/blvt/userLimit
94
+ #
95
+ # @param kwargs [Hash]
96
+ # @option kwargs [String] :tokenName
97
+ # @option kwargs [Integer] :recvWindow The value cannot be greater than 60000
98
+ # @see https://binance-docs.github.io/apidocs/spot/en/#get-blvt-user-limit-info-user_data
99
+ def user_limit(**kwargs)
100
+ @session.sign_request(:get, '/sapi/v1/blvt/userLimit', params: kwargs)
101
+ end
102
+ end
103
+ end
104
+ end