bitfinex-rb 0.0.11 → 0.1.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/lib/bitfinex-rb.rb +1 -0
- data/lib/bitfinex.rb +25 -14
- data/lib/bitfinex/api_versions.rb +7 -0
- data/lib/bitfinex/authenticated_rest.rb +26 -6
- data/lib/bitfinex/client.rb +30 -14
- data/lib/bitfinex/configurable.rb +9 -0
- data/lib/bitfinex/connection.rb +4 -2
- data/lib/bitfinex/errors.rb +5 -4
- data/lib/bitfinex/{account_info.rb → v1/account_info.rb} +11 -2
- data/lib/bitfinex/{deposit.rb → v1/deposit.rb} +2 -1
- data/lib/bitfinex/{funding_book.rb → v1/funding_book.rb} +1 -1
- data/lib/bitfinex/{historical_data.rb → v1/historical_data.rb} +1 -1
- data/lib/bitfinex/{lends.rb → v1/lends.rb} +1 -1
- data/lib/bitfinex/{margin_funding.rb → v1/margin_funding.rb} +7 -4
- data/lib/bitfinex/{orderbook.rb → v1/orderbook.rb} +4 -4
- data/lib/bitfinex/{orders.rb → v1/orders.rb} +3 -4
- data/lib/bitfinex/{positions.rb → v1/positions.rb} +1 -1
- data/lib/bitfinex/{stats.rb → v1/stats.rb} +1 -1
- data/lib/bitfinex/{symbols.rb → v1/symbols.rb} +3 -3
- data/lib/bitfinex/{ticker.rb → v1/ticker.rb} +2 -2
- data/lib/bitfinex/{trades.rb → v1/trades.rb} +3 -3
- data/lib/bitfinex/{wallet.rb → v1/wallet.rb} +1 -1
- data/lib/bitfinex/v2/margin.rb +34 -0
- data/lib/bitfinex/v2/personal.rb +94 -0
- data/lib/bitfinex/v2/stats.rb +27 -0
- data/lib/bitfinex/v2/ticker.rb +58 -0
- data/lib/bitfinex/v2/trading.rb +146 -0
- data/lib/bitfinex/v2/utils.rb +27 -0
- data/lib/bitfinex/version.rb +1 -1
- data/lib/bitfinex/websocket_connection.rb +49 -28
- metadata +25 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b1b2e7fdeb41e8d0de71ff3ab3a8c8f65b438f74
|
4
|
+
data.tar.gz: 5ee463c95bed54185d0ad7b0bd99c75c2ad461ee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a393e8688103054bd93c9b73799c96a8ff6a921155ad1064f12de83332d82c32c7e244153b0ffea1390232b9454761c323aebc35523715f02fd6318ae5f28932
|
7
|
+
data.tar.gz: d33751ff047447639cf5f2e7034e14e96b7dcf414984a1e72dde42a40e07c05aa2156ac0287653651f4b33c7452e8e27c485d30a8a5d5e2f590566fb17a75568
|
data/lib/bitfinex-rb.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require_relative "./bitfinex.rb"
|
data/lib/bitfinex.rb
CHANGED
@@ -9,19 +9,30 @@ require 'bitfinex/errors'
|
|
9
9
|
require 'bitfinex/connection'
|
10
10
|
require 'bitfinex/websocket_connection'
|
11
11
|
require 'bitfinex/authenticated_rest'
|
12
|
-
require 'bitfinex/
|
13
|
-
require 'bitfinex/trades'
|
14
|
-
require 'bitfinex/funding_book'
|
15
|
-
require 'bitfinex/orderbook'
|
16
|
-
require 'bitfinex/lends'
|
17
|
-
require 'bitfinex/symbols'
|
18
|
-
require 'bitfinex/stats'
|
19
|
-
require 'bitfinex/account_info'
|
20
|
-
require 'bitfinex/deposit'
|
21
|
-
require 'bitfinex/orders'
|
22
|
-
require 'bitfinex/wallet'
|
23
|
-
require 'bitfinex/positions'
|
24
|
-
require 'bitfinex/historical_data'
|
25
|
-
require 'bitfinex/margin_funding'
|
12
|
+
require 'bitfinex/api_versions'
|
26
13
|
require 'bitfinex/client'
|
27
14
|
|
15
|
+
# API Version 1
|
16
|
+
require 'bitfinex/v1/ticker'
|
17
|
+
require 'bitfinex/v1/trades'
|
18
|
+
require 'bitfinex/v1/funding_book'
|
19
|
+
require 'bitfinex/v1/orderbook'
|
20
|
+
require 'bitfinex/v1/lends'
|
21
|
+
require 'bitfinex/v1/symbols'
|
22
|
+
require 'bitfinex/v1/stats'
|
23
|
+
require 'bitfinex/v1/account_info'
|
24
|
+
require 'bitfinex/v1/deposit'
|
25
|
+
require 'bitfinex/v1/orders'
|
26
|
+
require 'bitfinex/v1/wallet'
|
27
|
+
require 'bitfinex/v1/positions'
|
28
|
+
require 'bitfinex/v1/historical_data'
|
29
|
+
require 'bitfinex/v1/margin_funding'
|
30
|
+
|
31
|
+
# API Version 2
|
32
|
+
require 'bitfinex/v2/stats'
|
33
|
+
require 'bitfinex/v2/ticker'
|
34
|
+
require 'bitfinex/v2/utils'
|
35
|
+
require 'bitfinex/v2/personal'
|
36
|
+
require 'bitfinex/v2/trading'
|
37
|
+
require 'bitfinex/v2/margin'
|
38
|
+
|
@@ -5,27 +5,47 @@ module Bitfinex
|
|
5
5
|
def authenticated_post(url, options = {})
|
6
6
|
raise Bitfinex::InvalidAuthKeyError unless valid_key?
|
7
7
|
complete_url = build_url(url)
|
8
|
-
|
8
|
+
body = options[:params] || {}
|
9
|
+
nonce = new_nonce
|
10
|
+
|
11
|
+
payload = if config.api_version == 1
|
12
|
+
build_payload("/v1/#{url}", options[:params], nonce)
|
13
|
+
else
|
14
|
+
"/api#{complete_url}#{nonce}#{body.to_json}"
|
15
|
+
end
|
16
|
+
|
9
17
|
response = rest_connection.post do |req|
|
10
18
|
req.url complete_url
|
19
|
+
req.body = body.to_json
|
11
20
|
req.options.timeout = config.rest_timeout
|
12
21
|
req.options.open_timeout = config.rest_open_timeout
|
13
22
|
req.headers['Content-Type'] = 'application/json'
|
14
23
|
req.headers['Accept'] = 'application/json'
|
15
|
-
|
16
|
-
|
17
|
-
|
24
|
+
|
25
|
+
if config.api_version == 1
|
26
|
+
req.headers['X-BFX-PAYLOAD'] = payload
|
27
|
+
req.headers['X-BFX-SIGNATURE'] = sign(payload)
|
28
|
+
req.headers['X-BFX-APIKEY'] = config.api_key
|
29
|
+
else
|
30
|
+
req.headers['bfx-nonce'] = nonce
|
31
|
+
req.headers['bfx-signature'] = sign(payload)
|
32
|
+
req.headers['bfx-apikey'] = config.api_key
|
33
|
+
end
|
18
34
|
end
|
19
35
|
end
|
20
36
|
|
21
|
-
def build_payload(url, params = {})
|
37
|
+
def build_payload(url, params = {}, nonce)
|
22
38
|
payload = {}
|
23
|
-
payload['nonce'] =
|
39
|
+
payload['nonce'] = nonce
|
24
40
|
payload['request'] = url
|
25
41
|
payload.merge!(params) if params
|
26
42
|
Base64.strict_encode64(payload.to_json)
|
27
43
|
end
|
28
44
|
|
45
|
+
def new_nonce
|
46
|
+
(Time.now.to_f * 10_000).to_i.to_s
|
47
|
+
end
|
48
|
+
|
29
49
|
def sign(payload)
|
30
50
|
OpenSSL::HMAC.hexdigest('sha384', config.secret, payload)
|
31
51
|
end
|
data/lib/bitfinex/client.rb
CHANGED
@@ -3,20 +3,36 @@ module Bitfinex
|
|
3
3
|
include Bitfinex::RestConnection
|
4
4
|
include Bitfinex::WebsocketConnection
|
5
5
|
include Bitfinex::AuthenticatedConnection
|
6
|
-
include Bitfinex::TickerClient
|
7
|
-
include Bitfinex::TradesClient
|
8
|
-
include Bitfinex::FundingBookClient
|
9
|
-
include Bitfinex::OrderbookClient
|
10
|
-
include Bitfinex::StatsClient
|
11
|
-
include Bitfinex::LendsClient
|
12
|
-
include Bitfinex::SymbolsClient
|
13
|
-
include Bitfinex::AccountInfoClient
|
14
|
-
include Bitfinex::DepositClient
|
15
|
-
include Bitfinex::OrdersClient
|
16
|
-
include Bitfinex::PositionsClient
|
17
|
-
include Bitfinex::HistoricalDataClient
|
18
|
-
include Bitfinex::MarginFundingClient
|
19
|
-
include Bitfinex::WalletClient
|
20
6
|
include Bitfinex::Configurable
|
7
|
+
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
if config.api_version == 1
|
11
|
+
extend Bitfinex::V1::TickerClient
|
12
|
+
extend Bitfinex::V1::TradesClient
|
13
|
+
extend Bitfinex::V1::FundingBookClient
|
14
|
+
extend Bitfinex::V1::OrderbookClient
|
15
|
+
extend Bitfinex::V1::StatsClient
|
16
|
+
extend Bitfinex::V1::LendsClient
|
17
|
+
extend Bitfinex::V1::SymbolsClient
|
18
|
+
extend Bitfinex::V1::AccountInfoClient
|
19
|
+
extend Bitfinex::V1::DepositClient
|
20
|
+
extend Bitfinex::V1::OrdersClient
|
21
|
+
extend Bitfinex::V1::PositionsClient
|
22
|
+
extend Bitfinex::V1::HistoricalDataClient
|
23
|
+
extend Bitfinex::V1::MarginFundingClient
|
24
|
+
extend Bitfinex::V1::WalletClient
|
25
|
+
else
|
26
|
+
extend Bitfinex::V2::TickerClient
|
27
|
+
extend Bitfinex::V2::StatsClient
|
28
|
+
extend Bitfinex::V2::UtilsClient
|
29
|
+
extend Bitfinex::V2::PersonalClient
|
30
|
+
extend Bitfinex::V2::TradingClient
|
31
|
+
extend Bitfinex::V2::MarginClient
|
32
|
+
end
|
33
|
+
|
34
|
+
@mutex = Mutex.new
|
35
|
+
@c_counter = 1
|
36
|
+
end
|
21
37
|
end
|
22
38
|
end
|
@@ -23,6 +23,7 @@ module Bitfinex
|
|
23
23
|
attr_accessor :api_endpoint, :debug, :debug_connection, :secret
|
24
24
|
attr_accessor :api_key, :websocket_api_endpoint, :rest_timeout
|
25
25
|
attr_accessor :reconnect, :reconnect_after, :rest_open_timeout
|
26
|
+
attr_accessor :api_version
|
26
27
|
|
27
28
|
def initialize
|
28
29
|
self.api_endpoint = "https://api.bitfinex.com/v1/"
|
@@ -33,6 +34,14 @@ module Bitfinex
|
|
33
34
|
self.rest_timeout = 30
|
34
35
|
self.rest_open_timeout = 30
|
35
36
|
self.debug_connection = false
|
37
|
+
self.api_version = 1
|
38
|
+
end
|
39
|
+
|
40
|
+
# Helper that configure to version 2
|
41
|
+
def use_api_v2
|
42
|
+
self.api_version = 2
|
43
|
+
self.api_endpoint = "https://api.bitfinex.com/v2/"
|
44
|
+
self.websocket_api_endpoint = "wss://api.bitfinex.com/ws/2/"
|
36
45
|
end
|
37
46
|
end
|
38
47
|
|
data/lib/bitfinex/connection.rb
CHANGED
@@ -4,12 +4,14 @@ module Bitfinex
|
|
4
4
|
module RestConnection
|
5
5
|
private
|
6
6
|
# Make an HTTP GET request
|
7
|
-
def get(url,
|
7
|
+
def get(url, params={})
|
8
8
|
rest_connection.get do |req|
|
9
9
|
req.url build_url(url)
|
10
10
|
req.headers['Content-Type'] = 'application/json'
|
11
11
|
req.headers['Accept'] = 'application/json'
|
12
|
-
|
12
|
+
params.each do |k,v|
|
13
|
+
req.params[k] = v
|
14
|
+
end
|
13
15
|
req.options.timeout = config.rest_timeout
|
14
16
|
req.options.open_timeout = config.rest_open_timeout
|
15
17
|
end
|
data/lib/bitfinex/errors.rb
CHANGED
@@ -12,6 +12,7 @@ module Bitfinex
|
|
12
12
|
class ForbiddenError < ServerError; end
|
13
13
|
class UnauthorizedError < ServerError; end
|
14
14
|
class InternalServerError < ServerError; end
|
15
|
+
class WebsocketError < ServerError; end
|
15
16
|
|
16
17
|
class CustomErrors < Faraday::Response::Middleware
|
17
18
|
def on_complete(env)
|
@@ -19,13 +20,13 @@ module Bitfinex
|
|
19
20
|
when 400
|
20
21
|
raise BadRequestError, env.body['message']
|
21
22
|
when 401
|
22
|
-
raise UnauthorizedError
|
23
|
+
raise UnauthorizedError, env.body['message']
|
23
24
|
when 403
|
24
|
-
raise ForbiddenError
|
25
|
+
raise ForbiddenError, env.body['message']
|
25
26
|
when 404
|
26
|
-
raise NotFoundError
|
27
|
+
raise NotFoundError, env.body['message']
|
27
28
|
when 500
|
28
|
-
raise InternalServerError
|
29
|
+
raise InternalServerError, env.body['message']
|
29
30
|
else
|
30
31
|
super
|
31
32
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module Bitfinex
|
2
|
-
|
3
|
-
module AccountInfoClient
|
2
|
+
module V1::AccountInfoClient
|
4
3
|
|
5
4
|
# Get account information
|
6
5
|
#
|
@@ -24,6 +23,16 @@ module Bitfinex
|
|
24
23
|
raise BlockMissingError unless block_given?
|
25
24
|
ws_auth(&block)
|
26
25
|
end
|
26
|
+
|
27
|
+
# See the fees applied to your withdrawals
|
28
|
+
#
|
29
|
+
# @return [Hash]
|
30
|
+
# @example:
|
31
|
+
# client.fees
|
32
|
+
def fees
|
33
|
+
resp = authenticated_post("fees")
|
34
|
+
resp.body
|
35
|
+
end
|
27
36
|
end
|
28
37
|
|
29
38
|
end
|
@@ -1,23 +1,26 @@
|
|
1
1
|
module Bitfinex
|
2
|
-
module MarginFundingClient
|
2
|
+
module V1::MarginFundingClient
|
3
3
|
|
4
4
|
# Submit a new offer
|
5
5
|
#
|
6
6
|
# @param currency [string] The name of the currency, es: 'USD'
|
7
7
|
# @param amount [decimal] Offer size: how much to lend or borrow
|
8
|
-
# @param rate [decimal] Rate to lend or borrow at. In percentage per 365 days.
|
8
|
+
# @param rate [decimal] Rate to lend or borrow at. In percentage per 365 days.
|
9
|
+
# Set to 0 for FRR, ±delta for FRR±delta.
|
9
10
|
# @param period [integer] Number of days of the funding contract (in days)
|
10
11
|
# @param direction [string] Either “lend” or “loan”
|
12
|
+
# @param frrdelta [bool] If true, the rate represents ±delta to FRR.
|
11
13
|
# @return [Hash]
|
12
14
|
# @example:
|
13
15
|
# client.new_offer("btc", 10.0, 20, 365, "lend")
|
14
|
-
def new_offer(currency, amount, rate, period, direction)
|
16
|
+
def new_offer(currency, amount, rate, period, direction, frrdelta=false)
|
15
17
|
params = {
|
16
18
|
currency: currency,
|
17
19
|
amount: amount.to_s,
|
18
20
|
rate: rate.to_s,
|
19
21
|
period: period.to_i,
|
20
|
-
direction: direction
|
22
|
+
direction: direction,
|
23
|
+
frrdelta: !!frrdelta
|
21
24
|
}
|
22
25
|
authenticated_post("offer/new", params: params).body
|
23
26
|
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
module Bitfinex
|
3
|
-
module OrderbookClient
|
3
|
+
module V1::OrderbookClient
|
4
4
|
|
5
5
|
# Get the full order book
|
6
6
|
#
|
7
|
-
# @param symbol [string]
|
7
|
+
# @param symbol [string]
|
8
8
|
# @param params :limit_bids [int] (optional) Limit the number of bids returned. May be 0 in which case the array of bids is empty. Default 50.
|
9
9
|
# @param params :limit_asks [int] (optional) Limit the number of asks returned. May be 0 in which case the array of asks is empty. Default 50.
|
10
10
|
# @param params :group [0/1] (optional) If 1, orders are grouped by price in the orderbook. If 0, orders are not grouped and sorted individually. Default 1
|
@@ -18,8 +18,8 @@ module Bitfinex
|
|
18
18
|
|
19
19
|
|
20
20
|
# Get the order book changes using websocket
|
21
|
-
#
|
22
|
-
# @param pair [string]
|
21
|
+
#
|
22
|
+
# @param pair [string]
|
23
23
|
# @param prec [string] Level of price aggregation (P0, P1, P2, P3). The default is P0.
|
24
24
|
# @param freq [string] Frequency of updates (F0, F1, F2, F3). F0=realtime / F1=2sec / F2=5sec / F3=10sec
|
25
25
|
# @param len [int] Number of price points (“25”, “100”) [default=“25”]
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module Bitfinex
|
2
|
-
|
3
|
-
module OrdersClient
|
2
|
+
module V1::OrdersClient
|
4
3
|
|
5
4
|
# Submit a new order
|
6
5
|
# @param symbol [string] The name of the symbol (see `#symbols`)
|
@@ -27,7 +26,7 @@ module Bitfinex
|
|
27
26
|
type: type,
|
28
27
|
side: side,
|
29
28
|
exchange: 'bitfinex',
|
30
|
-
price: price.
|
29
|
+
price: "%.10f" % price.to_f.round(10) # Decimalize float price (necessary for small numbers)
|
31
30
|
})
|
32
31
|
authenticated_post("order/new", params: params).body
|
33
32
|
end
|
@@ -45,7 +44,7 @@ module Bitfinex
|
|
45
44
|
# @example:
|
46
45
|
# client.multiple_orders([{symbol: "usdbtc", amount: 10, price: 0, exchange: "bitfinex", side: "buy", type: "market"}])
|
47
46
|
def multiple_orders(orders)
|
48
|
-
authenticated_post("order/new/multi", params: orders).body
|
47
|
+
authenticated_post("order/new/multi", params: {orders: orders}).body
|
49
48
|
end
|
50
49
|
|
51
50
|
# Cancel an order
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Bitfinex
|
2
|
-
module SymbolsClient
|
3
|
-
|
2
|
+
module V1::SymbolsClient
|
3
|
+
|
4
4
|
# Get a list of valid symbol IDs.
|
5
5
|
#
|
6
6
|
# @return [Array]
|
@@ -17,6 +17,6 @@ module Bitfinex
|
|
17
17
|
# client.symbols_details
|
18
18
|
def symbols_details
|
19
19
|
get("symbols_details").body
|
20
|
-
end
|
20
|
+
end
|
21
21
|
end
|
22
22
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Bitfinex
|
2
|
-
module TickerClient
|
2
|
+
module V1::TickerClient
|
3
3
|
|
4
4
|
# Gives innermost bid and asks and information on the most recent trade, as well as high, low and volume of the last 24 hours.
|
5
5
|
#
|
@@ -14,7 +14,7 @@ module Bitfinex
|
|
14
14
|
# Call the specified block passing tickers, it uses websocket
|
15
15
|
#
|
16
16
|
# @param pair [string]
|
17
|
-
# @param block [Block] The code to be executed when a new ticker is sent by the server
|
17
|
+
# @param block [Block] The code to be executed when a new ticker is sent by the server
|
18
18
|
# @example:
|
19
19
|
# client.listen_ticker do |tick|
|
20
20
|
# puts tick.inspect
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Bitfinex
|
2
|
-
module TradesClient
|
2
|
+
module V1::TradesClient
|
3
3
|
|
4
4
|
# Get a list of the most recent trades for the given symbol.
|
5
5
|
#
|
@@ -7,11 +7,11 @@ module Bitfinex
|
|
7
7
|
# @param params :timestamp [time] Only show trades at or after this timestamp.
|
8
8
|
# @param params :limit_trades [int] Limit the number of trades returned. Must be >= 1.
|
9
9
|
# @return [Array]
|
10
|
-
# @example:
|
10
|
+
# @example:
|
11
11
|
# client.trades
|
12
12
|
def trades(symbol="btcusd", params={})
|
13
13
|
check_params(params, %i{timestamp limit_trades})
|
14
|
-
get("trades/#{symbol}", params
|
14
|
+
get("trades/#{symbol}", params).body
|
15
15
|
end
|
16
16
|
|
17
17
|
# Listen to the trades using websocket.
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Bitfinex
|
2
|
+
module V2::MarginClient
|
3
|
+
|
4
|
+
# Get active offers
|
5
|
+
#
|
6
|
+
# @example:
|
7
|
+
# client.offers
|
8
|
+
def offers
|
9
|
+
authenticated_post("auth/r/offers").body
|
10
|
+
end
|
11
|
+
|
12
|
+
# Get account margin info
|
13
|
+
# - if symbol is not specified return everything
|
14
|
+
#
|
15
|
+
# @param symbol [string] (optional)
|
16
|
+
#
|
17
|
+
# @example:
|
18
|
+
# client.margin_info("tBTCUSD")
|
19
|
+
def margin_info(symbol = "base")
|
20
|
+
authenticated_post("auth/r/margin/#{symbol}").body
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
# Get account funding info
|
25
|
+
#
|
26
|
+
# @param symbol [string] default fUSD
|
27
|
+
#
|
28
|
+
# @example:
|
29
|
+
# client.funding_info
|
30
|
+
def funding_info(symbol = "fUSD")
|
31
|
+
authenticated_post("auth/r/funding/#{symbol}").body
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Bitfinex
|
2
|
+
module V2::PersonalClient
|
3
|
+
|
4
|
+
# Get account wallets
|
5
|
+
#
|
6
|
+
# @example:
|
7
|
+
# client.wallets
|
8
|
+
def wallets
|
9
|
+
authenticated_post("auth/r/wallets").body
|
10
|
+
end
|
11
|
+
|
12
|
+
# Get account historical daily performance
|
13
|
+
#
|
14
|
+
# @example:
|
15
|
+
# client.performance
|
16
|
+
def performance
|
17
|
+
authenticated_post("auth/r/stats/perf:1D/hist")
|
18
|
+
end
|
19
|
+
|
20
|
+
# Get the list of alerts
|
21
|
+
#
|
22
|
+
# @example:
|
23
|
+
# client.alerts
|
24
|
+
def alerts(type = 'price')
|
25
|
+
authenticated_post("auth/r/alerts", params: {type: type}).body
|
26
|
+
end
|
27
|
+
|
28
|
+
# Set a new alert
|
29
|
+
#
|
30
|
+
# @param price
|
31
|
+
# @param symbol
|
32
|
+
# @param type
|
33
|
+
#
|
34
|
+
# @example:
|
35
|
+
# client.alert(3000, "tBTCUSD")
|
36
|
+
def alert(price, symbol = "tBTCUSD", type = "price")
|
37
|
+
params = {
|
38
|
+
type: type,
|
39
|
+
price: price,
|
40
|
+
symbol: symbol
|
41
|
+
}
|
42
|
+
authenticated_post("auth/w/alert/set", params: params).body
|
43
|
+
end
|
44
|
+
|
45
|
+
# Delete an existing alert
|
46
|
+
#
|
47
|
+
# @param price
|
48
|
+
# @param symbol
|
49
|
+
#
|
50
|
+
# @example:
|
51
|
+
# client.delete_alert(3000, "tBTCUSD")
|
52
|
+
def delete_alert(price, symbol = "tBTCUSD")
|
53
|
+
authenticated_post("auth/w/alert/price:#{symbol}:#{price}/del").body
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
# Calculate available balance for order/offer
|
58
|
+
#
|
59
|
+
# @param rate [int] Rate of the order/offer
|
60
|
+
# @param dir [int] direction of the order/offer
|
61
|
+
# (orders: > 0 buy, < 0 sell | offers:
|
62
|
+
# > 0 sell, < 0 buy)
|
63
|
+
# @param type [string] Type of the order/offer
|
64
|
+
# EXCHANGE or MARGIN
|
65
|
+
# @param symbol [string]
|
66
|
+
|
67
|
+
# @example:
|
68
|
+
# client.available_balance(800, 1, 'EXCHANGE', 'tBTCUSD')
|
69
|
+
def available_balance(rate, dir, type, symbol)
|
70
|
+
params = {
|
71
|
+
symbol: symbol,
|
72
|
+
dir: dir,
|
73
|
+
type: type,
|
74
|
+
rate: rate
|
75
|
+
}
|
76
|
+
authenticated_post("auth/calc/order/avail", params: params).body
|
77
|
+
end
|
78
|
+
|
79
|
+
# Listen to authenticated channel
|
80
|
+
#
|
81
|
+
# Documentation:
|
82
|
+
# https://docs.bitfinex.com/v2/reference#account-info
|
83
|
+
#
|
84
|
+
# example:
|
85
|
+
# client.listen_account do |account|
|
86
|
+
# puts account
|
87
|
+
# end
|
88
|
+
def listen_account(&block)
|
89
|
+
raise BlockMissingError unless block_given?
|
90
|
+
ws_auth(&block)
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Bitfinex
|
4
|
+
module V2::StatsClient
|
5
|
+
|
6
|
+
# Various statistics about the requested pair.
|
7
|
+
#
|
8
|
+
# @param symbol [string] The symbol you want information about.
|
9
|
+
# @param key [string] Allowed values: "funding.size",
|
10
|
+
# "credits.size", "credits.size.sym", "pos.size"
|
11
|
+
# @param side [string] Available values: "long", "short"
|
12
|
+
# @param section [string] Available values: "last", "hist"
|
13
|
+
# @param size [string] Available values: '1m'
|
14
|
+
# @param params :sort [int32] if = 1 it sorts results
|
15
|
+
# returned with old > new
|
16
|
+
#
|
17
|
+
# @return [Array]
|
18
|
+
#
|
19
|
+
# @example:
|
20
|
+
# client.stats('fUSD', 'pos.size')
|
21
|
+
def stats(symbol = 'fUSD', key = 'funding.size', side = "long", section = "last", size = '1m', params = {})
|
22
|
+
check_params(params, %i{sort})
|
23
|
+
get("stats1/#{key}:#{size}:#{symbol}:#{side}/#{section}").body
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Bitfinex
|
4
|
+
module V2::TickerClient
|
5
|
+
|
6
|
+
# Gives innermost bid and asks and information on
|
7
|
+
# the most recent trade, as well as high, low and
|
8
|
+
# volume of the last 24 hours.
|
9
|
+
#
|
10
|
+
# @param symbols a list of symbols
|
11
|
+
# @return [Hash]
|
12
|
+
# @example:
|
13
|
+
# client.ticker("tBTCUSD","tLTCUSD","fUSD")
|
14
|
+
def ticker(*symbols)
|
15
|
+
if symbols.size == 1
|
16
|
+
get("ticker/#{symbols.first}").body
|
17
|
+
else
|
18
|
+
get("tickers", symbols: "#{symbols.flatten.join(",")}").body
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Call the specified block passing tickers, it uses websocket
|
23
|
+
#
|
24
|
+
# @param pair [string]
|
25
|
+
# @param block [Block] The code to be executed when a new ticker is sent by the server
|
26
|
+
#
|
27
|
+
# Documentation:
|
28
|
+
# https://docs.bitfinex.com/v2/reference#ws-public-ticker
|
29
|
+
#
|
30
|
+
# @example:
|
31
|
+
# client.listen_ticker do |tick|
|
32
|
+
# puts tick.inspect
|
33
|
+
# end
|
34
|
+
def listen_ticker(pair="tBTCUSD", &block)
|
35
|
+
raise BlockMissingError unless block_given?
|
36
|
+
register_channel pair: pair, channel: "ticker", &block
|
37
|
+
end
|
38
|
+
|
39
|
+
# Provides a way to access charting candle info
|
40
|
+
#
|
41
|
+
# @param symbol [string]
|
42
|
+
# @param time_frame [string] default '1m' - see doc for list of options
|
43
|
+
#
|
44
|
+
# Documentation:
|
45
|
+
# https://docs.bitfinex.com/v2/reference#ws-public-candle
|
46
|
+
#
|
47
|
+
# @example:
|
48
|
+
# client.listen_candles("tBTCUSD","1m") do |candle|
|
49
|
+
# puts "high #{candle[1][8]} | low #{candle[1][9]}"
|
50
|
+
# end
|
51
|
+
def listen_candles(symbol="tBTCUSD", time_frame="1m", &block)
|
52
|
+
raise BlockMissingError unless block_given?
|
53
|
+
key = "trade:#{time_frame}:#{symbol}"
|
54
|
+
register_channel key: key, channel: 'candles', &block
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
module Bitfinex
|
2
|
+
module V2::TradingClient
|
3
|
+
|
4
|
+
# Provides a way to access charting candle info
|
5
|
+
#
|
6
|
+
# @param symbol [string] The symbol you want information about.
|
7
|
+
# @param timeframe [string] Available values: '1m', '5m', '15m',
|
8
|
+
# '30m', '1h', '3h', '6h', '12h', '1D', '7D', '14D', '1M'
|
9
|
+
# @param section [string] Available values: "last", "hist"
|
10
|
+
# @param params :limit [int32] Number of candles requested
|
11
|
+
# @param params :start [int32] Filter start (ms)
|
12
|
+
# @param params :end [int32] Filter end (ms)
|
13
|
+
# @param params :sort [int32] if = 1 it sorts
|
14
|
+
# results returned with old > new
|
15
|
+
#
|
16
|
+
# @return [Array]
|
17
|
+
#
|
18
|
+
# @example:
|
19
|
+
# client.candles('tBTCUSD')
|
20
|
+
def candles(symbol = 'tBTCUSD', timeframe = '1m', section = "last", params = {})
|
21
|
+
check_params(params, %i{limit start end sort})
|
22
|
+
get("candles/trade:#{timeframe}:#{symbol}/#{section}", params).body
|
23
|
+
end
|
24
|
+
|
25
|
+
# The Order Books channel allow you to keep track
|
26
|
+
# of the state of the Bitfinex order book.
|
27
|
+
# It is provided on a price aggregated basis,
|
28
|
+
# with customizable precision.
|
29
|
+
#
|
30
|
+
#
|
31
|
+
# @param symbol [string] The symbol you want
|
32
|
+
# information about. You can find the list of
|
33
|
+
# valid symbols by calling the /symbols
|
34
|
+
# endpoint.
|
35
|
+
# @param precision [string] Level of price
|
36
|
+
# aggregation (P0, P1, P2, P3, R0)
|
37
|
+
# @param params :len [int32] Number of price
|
38
|
+
# points ("25", "100")
|
39
|
+
#
|
40
|
+
# @return [Hash] :bids [Array], :asks [Array]
|
41
|
+
#
|
42
|
+
# @example:
|
43
|
+
# client.orderbook("btcusd")
|
44
|
+
def books(symbol="btcusd", precision="P0", params = {})
|
45
|
+
check_params(params, %i{len})
|
46
|
+
get("book/#{symbol}/#{precision}", params: params).body
|
47
|
+
end
|
48
|
+
|
49
|
+
# Trades endpoint includes all the pertinent details
|
50
|
+
# of the trade, such as price, size and time.
|
51
|
+
#
|
52
|
+
# @param symbol [string] the name of the symbol
|
53
|
+
# @param params :limit [int32] Number of records
|
54
|
+
# @param params :start [int32] Millisecond start time
|
55
|
+
# @param params :end [int32] Millisecond end time
|
56
|
+
# @param params :sort [int32] if = 1 it sorts
|
57
|
+
# results returned with old > new
|
58
|
+
#
|
59
|
+
# @return [Array]
|
60
|
+
#
|
61
|
+
# @example:
|
62
|
+
# client.trades("tETHUSD")
|
63
|
+
def trades(symbol="tBTCUSD", params={})
|
64
|
+
check_params(params, %i{limit start end sort})
|
65
|
+
get("trades/#{symbol}", params).body
|
66
|
+
end
|
67
|
+
|
68
|
+
# Get active orders
|
69
|
+
#
|
70
|
+
# example:
|
71
|
+
# client.orders
|
72
|
+
def orders
|
73
|
+
authenticated_post("auth/r/orders").body
|
74
|
+
end
|
75
|
+
|
76
|
+
# Get Trades generated by an Order
|
77
|
+
#
|
78
|
+
# @param order_id [int32] Id of the order
|
79
|
+
# @param symbol [string] symbol used for the order
|
80
|
+
#
|
81
|
+
# @return [Array]
|
82
|
+
#
|
83
|
+
# @example:
|
84
|
+
# client.order_trades 10010, "tBTCUSD"
|
85
|
+
#
|
86
|
+
def order_trades(order_id, symbol="tBTCUSD")
|
87
|
+
authenticated_post("auth/r/order/#{symbol}:#{order_id}/trades").body
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
# Get active positions
|
92
|
+
#
|
93
|
+
# return [Array]
|
94
|
+
#
|
95
|
+
# @example:
|
96
|
+
# client.active_positions
|
97
|
+
def active_positions
|
98
|
+
authenticated_post("auth/positions").body
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
# This channel sends a trade message whenever a trade occurs at Bitfinex.
|
103
|
+
# It includes all the pertinent details of the trade, such as price, size and time.
|
104
|
+
#
|
105
|
+
# @param symbol [string]
|
106
|
+
# @param block [Block] The code to be executed when a new ticker is sent by the server
|
107
|
+
#
|
108
|
+
# Documentation:
|
109
|
+
# https://docs.bitfinex.com/v2/reference#ws-public-trades
|
110
|
+
#
|
111
|
+
# @example:
|
112
|
+
# client.listen_trades("tBTCUSD") do |trade|
|
113
|
+
# puts "traded #{trade[2][2]} BTC for #{trade[2][3]} USD"
|
114
|
+
# end
|
115
|
+
def listen_trades(symbol="tBTCUSD", &block)
|
116
|
+
raise BlockMissingError unless block_given?
|
117
|
+
register_channel symbol: symbol, channel: "trades", &block
|
118
|
+
end
|
119
|
+
|
120
|
+
# The Order Books channel allow you to keep track of the state of the Bitfinex order book.
|
121
|
+
# It is provided on a price aggregated basis, with customizable precision.
|
122
|
+
# After receiving the response, you will receive a snapshot of the book,
|
123
|
+
# followed by updates upon any changes to the book.
|
124
|
+
#
|
125
|
+
# @param symbol [string]
|
126
|
+
# @param precision [string] Level of price aggregation (P0, P1, P2, P3, R0).
|
127
|
+
# (default P0) R0 is raw books - These are the most granular books.
|
128
|
+
# @param frequency [string] Frequency of updates (F0, F1, F2, F3).
|
129
|
+
# F0=realtime / F1=2sec / F2=5sec / F3=10sec (default F0)
|
130
|
+
# @param length [int] Number of price points ("25", "100") [default="25"]
|
131
|
+
#
|
132
|
+
# Documentation:
|
133
|
+
# https://docs.bitfinex.com/v2/reference#ws-public-order-books
|
134
|
+
# https://docs.bitfinex.com/v2/reference#ws-public-raw-order-books
|
135
|
+
#
|
136
|
+
# @example:
|
137
|
+
# client.listen_book("tBTCUSD") do |trade|
|
138
|
+
# puts "traded #{trade[2][2]} BTC for #{trade[2][3]} USD"
|
139
|
+
# end
|
140
|
+
def listen_book(symbol="tBTCUSD", frequency="F0", length=25, precision="P0", &block)
|
141
|
+
raise BlockMissingError unless block_given?
|
142
|
+
register_channel symbol: symbol, channel: "book", prec: precision, freq: frequency, len: length, &block
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Bitfinex
|
4
|
+
module V2::UtilsClient
|
5
|
+
|
6
|
+
# Calculate the average execution rate for Trading or Margin funding.
|
7
|
+
#
|
8
|
+
# @param symbol [string] The symbol you want information about.
|
9
|
+
# @param amount [string] Amount. Positive for buy, negative for sell (ex. "1.123")
|
10
|
+
# @param period [string] (optional) Maximum period for Margin Funding
|
11
|
+
# @param rate_limit [string] Limit rate/price (ex. "1000.5")
|
12
|
+
#
|
13
|
+
# @return [Array]
|
14
|
+
#
|
15
|
+
# @example:
|
16
|
+
# client.calc_avg_price('tBTCUSD', 1000, 1000)
|
17
|
+
def calc_avg_price(symbol = 'tBTCUSD', amount = 0, period = 0, rate_limit = nil)
|
18
|
+
params = {
|
19
|
+
symbol: symbol,
|
20
|
+
amount: amount.to_s,
|
21
|
+
period: period.to_s
|
22
|
+
}
|
23
|
+
params[:rateLimit] = rate_limit.to_s unless rate_limit.nil?
|
24
|
+
get("calc/trade/avg",params)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/bitfinex/version.rb
CHANGED
@@ -16,23 +16,38 @@ module Bitfinex
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def ws_close_all
|
19
|
-
ws_client.
|
19
|
+
ws_client.stop!
|
20
20
|
@ws_open = false
|
21
21
|
ws_reset_channels
|
22
22
|
end
|
23
23
|
|
24
24
|
def ws_auth(&block)
|
25
25
|
unless @ws_auth
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
26
|
+
nonce = (Time.now.to_f * 10_000).to_i.to_s
|
27
|
+
sub_id = add_callback(&block)
|
28
|
+
save_channel_id(sub_id,0)
|
29
|
+
if config.api_version == 1
|
30
|
+
payload = 'AUTH' + nonce
|
31
|
+
signature = sign(payload)
|
32
|
+
ws_safe_send({
|
33
|
+
apiKey: config.api_key,
|
34
|
+
authSig: sign(payload),
|
35
|
+
authPayload: payload,
|
36
|
+
subId: sub_id.to_s,
|
37
|
+
event: 'auth'
|
38
|
+
})
|
39
|
+
else
|
40
|
+
payload = 'AUTH' + nonce + nonce
|
41
|
+
signature = sign(payload)
|
42
|
+
ws_safe_send({
|
43
|
+
apiKey: config.api_key,
|
44
|
+
authSig: sign(payload),
|
45
|
+
authPayload: payload,
|
46
|
+
authNonce: nonce,
|
47
|
+
subId: sub_id.to_s,
|
48
|
+
event: 'auth'
|
49
|
+
})
|
50
|
+
end
|
36
51
|
@ws_auth = true
|
37
52
|
end
|
38
53
|
end
|
@@ -71,15 +86,22 @@ module Bitfinex
|
|
71
86
|
end
|
72
87
|
|
73
88
|
def callbacks
|
74
|
-
@callbacks ||=
|
89
|
+
@callbacks ||= []
|
75
90
|
end
|
76
91
|
|
77
|
-
def add_callback(
|
78
|
-
|
92
|
+
def add_callback(&block)
|
93
|
+
id = 0
|
94
|
+
@mutex.synchronize do
|
95
|
+
callbacks[@c_counter] = { block: block, chan_id: nil }
|
96
|
+
id = @c_counter
|
97
|
+
@c_counter += 1
|
98
|
+
end
|
99
|
+
id
|
79
100
|
end
|
80
101
|
|
81
102
|
def register_authenticated_channel(msg, &block)
|
82
|
-
add_callback(
|
103
|
+
sub_id = add_callback(&block)
|
104
|
+
msg.merge!(subId: sub_id.to_s)
|
83
105
|
ws_safe_send(msg.merge(event:'subscribe'))
|
84
106
|
end
|
85
107
|
|
@@ -92,7 +114,8 @@ module Bitfinex
|
|
92
114
|
end
|
93
115
|
|
94
116
|
def register_channel(msg, &block)
|
95
|
-
add_callback(
|
117
|
+
sub_id = add_callback(&block)
|
118
|
+
msg.merge!(subId: sub_id.to_s)
|
96
119
|
if ws_open
|
97
120
|
ws_client.send msg.merge(event: 'subscribe')
|
98
121
|
else
|
@@ -100,25 +123,20 @@ module Bitfinex
|
|
100
123
|
end
|
101
124
|
end
|
102
125
|
|
103
|
-
def fingerprint(msg)
|
104
|
-
msg.reject{|k,v| [:event,'chanId','event'].include?(k) }.
|
105
|
-
inject({}){|h, (k,v)| h[k.to_sym]=v.to_s; h}
|
106
|
-
end
|
107
|
-
|
108
126
|
def listen
|
109
127
|
ws_client.on(:message) do |rmsg|
|
110
128
|
msg = JSON.parse(rmsg)
|
111
129
|
if msg.kind_of?(Hash) && msg["event"] == "subscribed"
|
112
|
-
save_channel_id(
|
130
|
+
save_channel_id(msg["subId"],msg["chanId"])
|
113
131
|
elsif msg.kind_of?(Array)
|
114
132
|
exec_callback_for(msg)
|
115
133
|
end
|
116
134
|
end
|
117
135
|
end
|
118
136
|
|
119
|
-
def save_channel_id(
|
120
|
-
callbacks[
|
121
|
-
chan_ids[
|
137
|
+
def save_channel_id(sub_id,chan_id)
|
138
|
+
callbacks[sub_id.to_i][:chan_id] = chan_id
|
139
|
+
chan_ids[chan_id] = sub_id.to_i
|
122
140
|
end
|
123
141
|
|
124
142
|
def exec_callback_for(msg)
|
@@ -198,12 +216,15 @@ module Bitfinex
|
|
198
216
|
end
|
199
217
|
|
200
218
|
def ws_closed(event)
|
201
|
-
|
202
|
-
|
219
|
+
if @stop
|
220
|
+
EM.stop
|
221
|
+
elsif @reconnect
|
222
|
+
EM.add_timer(@reconnect_after){ connect! }
|
223
|
+
end
|
203
224
|
end
|
204
225
|
|
205
226
|
def ws_error(event)
|
206
|
-
|
227
|
+
raise WebsocketError, event.message
|
207
228
|
end
|
208
229
|
end
|
209
230
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bitfinex-rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bitfinex
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-09-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -132,27 +132,35 @@ extensions: []
|
|
132
132
|
extra_rdoc_files: []
|
133
133
|
files:
|
134
134
|
- lib/bitfinex-api-rb.rb
|
135
|
+
- lib/bitfinex-rb.rb
|
135
136
|
- lib/bitfinex.rb
|
136
|
-
- lib/bitfinex/
|
137
|
+
- lib/bitfinex/api_versions.rb
|
137
138
|
- lib/bitfinex/authenticated_rest.rb
|
138
139
|
- lib/bitfinex/client.rb
|
139
140
|
- lib/bitfinex/configurable.rb
|
140
141
|
- lib/bitfinex/connection.rb
|
141
|
-
- lib/bitfinex/deposit.rb
|
142
142
|
- lib/bitfinex/errors.rb
|
143
|
-
- lib/bitfinex/
|
144
|
-
- lib/bitfinex/
|
145
|
-
- lib/bitfinex/
|
146
|
-
- lib/bitfinex/
|
147
|
-
- lib/bitfinex/
|
148
|
-
- lib/bitfinex/
|
149
|
-
- lib/bitfinex/
|
150
|
-
- lib/bitfinex/
|
151
|
-
- lib/bitfinex/
|
152
|
-
- lib/bitfinex/
|
153
|
-
- lib/bitfinex/
|
143
|
+
- lib/bitfinex/v1/account_info.rb
|
144
|
+
- lib/bitfinex/v1/deposit.rb
|
145
|
+
- lib/bitfinex/v1/funding_book.rb
|
146
|
+
- lib/bitfinex/v1/historical_data.rb
|
147
|
+
- lib/bitfinex/v1/lends.rb
|
148
|
+
- lib/bitfinex/v1/margin_funding.rb
|
149
|
+
- lib/bitfinex/v1/orderbook.rb
|
150
|
+
- lib/bitfinex/v1/orders.rb
|
151
|
+
- lib/bitfinex/v1/positions.rb
|
152
|
+
- lib/bitfinex/v1/stats.rb
|
153
|
+
- lib/bitfinex/v1/symbols.rb
|
154
|
+
- lib/bitfinex/v1/ticker.rb
|
155
|
+
- lib/bitfinex/v1/trades.rb
|
156
|
+
- lib/bitfinex/v1/wallet.rb
|
157
|
+
- lib/bitfinex/v2/margin.rb
|
158
|
+
- lib/bitfinex/v2/personal.rb
|
159
|
+
- lib/bitfinex/v2/stats.rb
|
160
|
+
- lib/bitfinex/v2/ticker.rb
|
161
|
+
- lib/bitfinex/v2/trading.rb
|
162
|
+
- lib/bitfinex/v2/utils.rb
|
154
163
|
- lib/bitfinex/version.rb
|
155
|
-
- lib/bitfinex/wallet.rb
|
156
164
|
- lib/bitfinex/websocket_connection.rb
|
157
165
|
homepage: https://www.bitfinex.com/
|
158
166
|
licenses:
|
@@ -174,7 +182,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
174
182
|
version: '0'
|
175
183
|
requirements: []
|
176
184
|
rubyforge_project:
|
177
|
-
rubygems_version: 2.
|
185
|
+
rubygems_version: 2.4.5.1
|
178
186
|
signing_key:
|
179
187
|
specification_version: 4
|
180
188
|
summary: Bitfinex API Wrapper
|