binance-connector-ruby 1.0.1

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 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