class Bitfinex::WSv2
Implements version 2 of the Bitfinex
WebSocket API, taking an evented approach. Incoming packets trigger event broadcasts with names relevant to the individual packets. Provides order manipulation methods that support callback blocks, which are called when the relevant confirmation notifications are received
Constants
- FLAG_CHECKSUM
- FLAG_DEC_S
- FLAG_SEQ_ALL
- FLAG_TIMESTAMP
- FLAG_TIME_S
- INFO_MAINTENANCE_END
- INFO_MAINTENANCE_START
- INFO_SERVER_RESTART
Public Class Methods
Creates a new instance of the class
@param [Hash] params @param [string] params.url - connection URL @param [string] params.aff_code - optional affiliate code to be applied to all orders @param [string] params.api_key @param [string] params.api_secret @param [boolean] params.manage_order_books - if true, order books are persisted internally, allowing for automatic checksum verification @param [boolean] params.transform - if true, full models are returned in place of array data @param [boolean] params.seq_audit - enables automatic seq number verification @param [boolean] params.checksum_audit - enables automatic OB checksum verification (requires manage_order_books)
# File lib/ws/ws2.rb, line 63 def initialize (params = {}) @l = Logger.new(STDOUT) @l.progname = 'ws2' @url = params[:url] || 'wss://api.bitfinex.com/ws/2' @aff_code = params[:aff_code] @api_key = params[:api_key] @api_secret = params[:api_secret] @manage_obs = params[:manage_order_books] @transform = !!params[:transform] @seq_audit = !!params[:seq_audit] @checksum_audit = !!params[:checksum_audit] @enabled_flags = 0 @is_open = false @is_authenticated = false @channel_map = {} @order_books = {} @pending_blocks = {} @last_pub_seq = nil @last_auth_seq = nil end
Public Instance Methods
Authenticates the socket connection
@param [number] calc @param [number] dms - dead man switch, active 4
# File lib/ws/ws2.rb, line 627 def auth! (calc = 0, dms = 0) if @is_authenticated raise Exception, 'already authenticated' end auth_nonce = new_nonce auth_payload = "AUTH#{auth_nonce}#{auth_nonce}" sig = sign(auth_payload) @ws.send(JSON.generate({ :event => 'auth', :apiKey => @api_key, :authSig => sig, :authPayload => auth_payload, :authNonce => auth_nonce, :dms => dms, :calc => calc })) end
Cancel an order by ID
@param [Hash|Array|Order|number] order - must contain or be ID @param [Block] cb - triggered upon receipt of confirmation notification
# File lib/ws/ws2.rb, line 686 def cancel_order (order, &cb) return if !@is_authenticated if order.is_a?(Numeric) id = order elsif order.is_a?(Array) id = order[0] elsif order.instance_of?(Models::Order) id = order.id elsif order.kind_of?(Hash) id = order[:id] || order['id'] else raise Exception, 'tried to cancel order with invalid ID' end @ws.send(JSON.generate([0, 'oc', nil, { :id => id }])) if !cb.nil? @pending_blocks["order-cancel-#{id}"] = cb end end
Closes the websocket client
# File lib/ws/ws2.rb, line 138 def close! @ws.close end
Enable an individual flag (see FLAG_* constants)
@param [number] flag
# File lib/ws/ws2.rb, line 581 def enable_flag (flag) return unless @is_open @ws.send(JSON.generate({ :event => 'conf', :flags => @enabled_flags | flag })) end
Sets the flag to activate order book checksums. Managed order books are required for automatic checksum audits.
@param [boolean] audit - if true (default), incoming checksums will be compared to local checksums
# File lib/ws/ws2.rb, line 616 def enable_ob_checksums (audit = true) @checksum_audit = audit enable_flag(FLAG_CHECKSUM) end
Sets the flag to activate sequence numbers on incoming packets
@param [boolean] audit - if true (default), incoming seq numbers will be checked for consistency
# File lib/ws/ws2.rb, line 605 def enable_sequencing (audit = true) @seq_audit = audit enable_flag(FLAG_SEQ_ALL) end
Checks if an individual flag is enabled (see FLAG_* constants)
@param [number] flag @return [boolean] enabled
# File lib/ws/ws2.rb, line 596 def is_flag_enabled (flag) (@enabled_flags & flag) == flag end
Opens the websocket client inside an eventmachine run block
# File lib/ws/ws2.rb, line 113 def open! if @is_open raise Exception, 'already open' end EM.run { @ws = Faye::WebSocket::Client.new(@url) @ws.on(:open) do |e| on_open(e) end @ws.on(:message) do |e| on_message(e) end @ws.on(:close) do |e| on_close(e) end } end
Requests a calculation to be performed @see docs.bitfinex.com/v2/reference#ws-input-calc
@param [Array] prefixes - i.e. ['margin_base']
# File lib/ws/ws2.rb, line 661 def request_calc (prefixes) @ws.send(JSON.generate([0, 'calc', nil, prefixes.map { |p| [p] }])) end
Submit a new order
@param [Hash|Array|Order] order @param [Block] cb - triggered upon receipt of confirmation notification
# File lib/ws/ws2.rb, line 714 def submit_order (order, &cb) return if !@is_authenticated if order.kind_of?(Array) packet = order elsif order.instance_of?(Models::Order) packet = order.to_new_order_packet elsif order.kind_of?(Hash) packet = Models::Order.new(order).to_new_order_packet else raise Exception, 'tried to submit order of unkown type' end if !@aff_code.nil? unless packet[:meta] packet[:meta] = {} end packet[:meta][:aff_code] = @aff_code end @ws.send(JSON.generate([0, 'on', nil, packet])) if packet.has_key?(:cid) && !cb.nil? @pending_blocks["order-new-#{packet[:cid]}"] = cb end end
Subscribes to the specified channel; params dictate the channel filter
@param [string] channel - i.e. 'trades', 'candles', etc @param [Hash] params @param [string?] params.symbol @param [string?] params.prec - for order book channels @param [string?] params.len - for order book channels @param [string?] params.key - for candle channels
# File lib/ws/ws2.rb, line 442 def subscribe (channel, params = {}) @l.info 'subscribing to channel %s [%s]' % [channel, params] @ws.send(JSON.generate(params.merge({ :event => 'subscribe', :channel => channel, }))) end
Subscribes to a candle channel by key
@param [string] key - i.e. trade:1m:tBTCUSD
# File lib/ws/ws2.rb, line 473 def subscribe_candles (key) subscribe('candles', { :key => key }) end
Subscribes to an order book channel
@param [string] sym - i.e. tBTCUSD @param [string] prec - i.e. R0, P0, etc @param [string] len - i.e. 25, 100, etc
# File lib/ws/ws2.rb, line 484 def subscribe_order_book (sym, prec, len) subscribe('book', { :symbol => sym, :prec => prec, :len => len }) end
Subscribes to a ticker channel by symbol
@param [string] sym - i.e. tBTCUSD
# File lib/ws/ws2.rb, line 455 def subscribe_ticker (sym) subscribe('ticker', { :symbol => sym }) end
Subscribes to a trades channel by symbol
@param [string] sym - i.e. tBTCUSD
# File lib/ws/ws2.rb, line 464 def subscribe_trades (sym) subscribe('trades', { :symbol => sym }) end
Update an order with a changeset by ID
@param [Hash] changes - must contain ID @param [Block] cb - triggered upon receipt of confirmation notification
# File lib/ws/ws2.rb, line 671 def update_order (changes, &cb) id = changes[:id] || changes['id'] @ws.send(JSON.generate([0, 'ou', nil, changes])) if !cb.nil? @pending_blocks["order-update-#{id}"] = cb end end