198 lines
10 KiB
Ruby
198 lines
10 KiB
Ruby
# encoding: UTF-8
|
|
# frozen_string_literal: true
|
|
|
|
module API
|
|
module V2
|
|
module Public
|
|
class Markets < Grape::API
|
|
helpers ::API::V2::OrderHelpers
|
|
helpers ::API::V2::ParamHelpers
|
|
|
|
class OrderBook < Struct.new(:asks, :bids); end
|
|
|
|
resource :markets do
|
|
desc 'Get all available markets.',
|
|
is_array: true,
|
|
success: API::V2::Entities::Market
|
|
params do
|
|
use :pagination
|
|
optional :ordering,
|
|
values: { value: %w(asc desc), message: 'public.markets.invalid_ordering' },
|
|
default: 'asc',
|
|
desc: 'If set, returned values will be sorted in specific order, defaults to \'asc\'.'
|
|
optional :order_by,
|
|
values: { value: %w(id position), message: 'public.markets.invalid_order_by' },
|
|
default: 'position',
|
|
desc: 'Name of the field, which result will be ordered by.'
|
|
optional :base_unit,
|
|
type: String,
|
|
values: { value: -> (v){ ::Currency.exists?(v) },
|
|
message: 'public.markets.base_unit_doesnt_exist' },
|
|
desc: 'Strict filter for base unit'
|
|
optional :quote_unit,
|
|
type: String,
|
|
values: { value: -> (v){ ::Currency.exists?(v) },
|
|
message: 'public.markets.quote_unit_doesnt_exist' },
|
|
desc: 'Strict filter for quote unit'
|
|
optional :search, type: JSON, default: {} do
|
|
optional :base_code,
|
|
type: String,
|
|
desc: 'Search base currency code using LIKE'
|
|
optional :quote_code,
|
|
type: String,
|
|
desc: 'Search qoute currency code using LIKE'
|
|
optional :base_name,
|
|
type: String,
|
|
desc: 'Search base currency name using LIKE'
|
|
optional :quote_name,
|
|
type: String,
|
|
desc: 'Search quote currency name using LIKE'
|
|
end
|
|
end
|
|
get "/" do
|
|
search_params = params[:search]
|
|
.slice(:base_code, :quote_code, :base_name, :quote_name)
|
|
.transform_keys {|k| "#{k}_cont"}
|
|
.merge(m: 'or')
|
|
|
|
search = ::Market.active
|
|
.where(params.slice(:base_unit, :quote_unit))
|
|
.ransack(search_params)
|
|
|
|
# Add default ordering (position asc) for cases markets where unit position is same.
|
|
search.sorts = ["#{params[:order_by]} #{params[:ordering]}", "position asc"]
|
|
|
|
present paginate(Rails.cache.fetch("markets_#{params}", expires_in: 600) { search.result.load.to_a }),
|
|
with: API::V2::Entities::Market,
|
|
extended: !!params[:extended]
|
|
end
|
|
|
|
desc 'Get the order book of specified market.',
|
|
is_array: true,
|
|
success: API::V2::Entities::OrderBook
|
|
params do
|
|
requires :market,
|
|
type: String,
|
|
values: { value: -> { ::Market.active.ids }, message: 'public.market.doesnt_exist' },
|
|
desc: -> { V2::Entities::Market.documentation[:id] }
|
|
optional :asks_limit,
|
|
type: { value: Integer, message: 'public.order_book.non_integer_ask_limit' },
|
|
values: { value: 1..200, message: 'public.order_book.invalid_ask_limit' },
|
|
default: 20,
|
|
desc: 'Limit the number of returned sell orders. Default to 20.'
|
|
optional :bids_limit,
|
|
type: { value: Integer, message: 'public.order_book.non_integer_bid_limit' },
|
|
values: { value: 1..200, message: 'public.order_book.invalid_bid_limit' },
|
|
default: 20,
|
|
desc: 'Limit the number of returned buy orders. Default to 20.'
|
|
end
|
|
get ":market/order-book", requirements: { market: /[\w\.\-]+/ } do
|
|
asks = OrderAsk.active.with_market(params[:market]).matching_rule.limit(params[:asks_limit])
|
|
bids = OrderBid.active.with_market(params[:market]).matching_rule.limit(params[:bids_limit])
|
|
book = OrderBook.new asks, bids
|
|
present book, with: API::V2::Entities::OrderBook
|
|
end
|
|
|
|
desc 'Get recent trades on market, each trade is included only once. Trades are sorted in reverse creation order.',
|
|
is_array: true,
|
|
success: API::V2::Entities::Trade
|
|
params do
|
|
requires :market,
|
|
type: String,
|
|
values: { value: -> { ::Market.active.ids }, message: 'public.market.doesnt_exist' },
|
|
desc: -> { V2::Entities::Market.documentation[:id] }
|
|
optional :limit,
|
|
type: { value: Integer, message: 'public.trade.non_integer_limit' },
|
|
values: { value: 1..1000, message: 'public.trade.invalid_limit' },
|
|
default: 100,
|
|
desc: 'Limit the number of returned trades. Default to 100.'
|
|
optional :timestamp,
|
|
type: { value: Integer, message: 'public.trade.non_integer_timestamp' },
|
|
desc: "An integer represents the seconds elapsed since Unix epoch."\
|
|
"If set, only trades executed before the time will be returned."
|
|
optional :order_by,
|
|
type: String,
|
|
values: { value: %w(asc desc), message: 'public.trade.invalid_order_by' },
|
|
default: 'desc',
|
|
desc: "If set, returned trades will be sorted in specific order, default to 'desc'."
|
|
end
|
|
get ":market/trades", requirements: { market: /[\w\.\-]+/ } do
|
|
present Trade.public_from_influx(params[:market], params[:limit]), with: API::V2::Entities::PublicTrade
|
|
end
|
|
|
|
desc 'Get depth or specified market. Both asks and bids are sorted from highest price to lowest.'
|
|
params do
|
|
requires :market,
|
|
type: String,
|
|
values: { value: -> { ::Market.active.ids }, message: 'public.market.doesnt_exist' },
|
|
desc: -> { V2::Entities::Market.documentation[:id] }
|
|
optional :limit,
|
|
type: { value: Integer, message: 'public.market_depth.non_integer_limit' },
|
|
values: { value: 1..1000, message: 'public.market_depth.invalid_limit' },
|
|
default: 300,
|
|
desc: 'Limit the number of returned price levels. Default to 300.'
|
|
end
|
|
get ":market/depth", requirements: { market: /[\w\.\-]+/ } do
|
|
asks = OrderAsk.get_depth(params[:market])[0, params[:limit]]
|
|
bids = OrderBid.get_depth(params[:market])[0, params[:limit]]
|
|
{ timestamp: Time.now.to_i, asks: asks, bids: bids }
|
|
end
|
|
|
|
desc 'Get OHLC(k line) of specific market.'
|
|
params do
|
|
requires :market,
|
|
type: String,
|
|
values: { value: -> { ::Market.active.ids }, message: 'public.market.doesnt_exist' },
|
|
desc: -> { V2::Entities::Market.documentation[:id] }
|
|
optional :period,
|
|
type: { value: Integer, message: 'public.k_line.non_integer_period' },
|
|
values: { value: KLineService::AVAILABLE_POINT_PERIODS, message: 'public.k_line.invalid_period' },
|
|
default: 1,
|
|
desc: "Time period of K line, default to 1. You can choose between #{KLineService::AVAILABLE_POINT_PERIODS.join(', ')}"
|
|
optional :time_from,
|
|
type: { value: Integer, message: 'public.k_line.non_integer_time_from' },
|
|
allow_blank: { value: false, c_name: 'k_line' },
|
|
desc: "An integer represents the seconds elapsed since Unix epoch. If set, only k-line data after that time will be returned."
|
|
optional :time_to,
|
|
type: { value: Integer, message: 'public.k_line.non_integer_time_to' },
|
|
allow_blank: { value: false, c_name: 'k_line' },
|
|
desc: "An integer represents the seconds elapsed since Unix epoch. If set, only k-line data till that time will be returned."
|
|
optional :limit,
|
|
type: { value: Integer, message: 'public.k_line.non_integer_limit' },
|
|
values: { value: KLineService::AVAILABLE_POINT_LIMITS, message: 'public.k_line.invalid_limit' },
|
|
default: 30,
|
|
desc: "Limit the number of returned data points default to 30. Ignored if time_from and time_to are given."
|
|
end
|
|
get ":market/k-line", requirements: { market: /[\w\.\-]+/ } do
|
|
KLineService[params[:market], params[:period]]
|
|
.get_ohlc(params.slice(:limit, :time_from, :time_to).merge(offset: true))
|
|
end
|
|
|
|
desc 'Get ticker of all markets (For response doc see /:market/tickers/ response).'
|
|
get "/tickers" do
|
|
Rails.cache.fetch(:markets_tickers, expires_in: 60) do
|
|
::Market.active.ordered.inject({}) do |h, m|
|
|
h[m.id] = format_ticker TickersService[m].ticker
|
|
h
|
|
end
|
|
end
|
|
end
|
|
|
|
desc 'Get ticker of specific market.',
|
|
success: API::V2::Entities::Ticker
|
|
params do
|
|
requires :market,
|
|
type: String,
|
|
values: { value: -> { ::Market.active.ids }, message: 'public.market.doesnt_exist' },
|
|
desc: -> { V2::Entities::Market.documentation[:id] }
|
|
end
|
|
get "/:market/tickers/", requirements: { market: /[\w\.\-]+/ } do
|
|
present format_ticker(TickersService[params[:market]].ticker),
|
|
with: API::V2::Entities::Ticker
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|