Initial commit
This commit is contained in:
140
spec/api/v2/public/currencies_spec.rb
Normal file
140
spec/api/v2/public/currencies_spec.rb
Normal file
@@ -0,0 +1,140 @@
|
||||
# encoding: UTF-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
describe API::V2::Public::Currencies, type: :request do
|
||||
|
||||
before(:each) { clear_redis }
|
||||
describe 'GET /api/v2/public/currencies/:id' do
|
||||
let(:fiat) { Currency.find(:usd) }
|
||||
let(:coin) { Currency.find(:btc) }
|
||||
|
||||
let(:expected_for_fiat) do
|
||||
%w[id type deposit_enabled withdrawal_enabled deposit_fee withdraw_fee withdraw_limit_24h withdraw_limit_72h base_factor precision]
|
||||
end
|
||||
let(:expected_for_coin) do
|
||||
expected_for_fiat.concat(%w[explorer_transaction explorer_address])
|
||||
end
|
||||
|
||||
it 'returns information about specified currency' do
|
||||
get "/api/v2/public/currencies/#{coin.id}"
|
||||
expect(response).to be_successful
|
||||
|
||||
result = JSON.parse(response.body)
|
||||
expect(result.fetch('id')).to eq coin.id
|
||||
end
|
||||
|
||||
context 'currency code with dot' do
|
||||
let!(:currency) { create(:currency, :xagm_cx) }
|
||||
|
||||
it 'returns information about specified currency' do
|
||||
get "/api/v2/public/currencies/#{currency.id}"
|
||||
|
||||
result = JSON.parse(response.body)
|
||||
expect(result.fetch('id')).to eq currency.id
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns correct keys for fiat' do
|
||||
get "/api/v2/public/currencies/#{fiat.id}"
|
||||
expect(response).to be_successful
|
||||
|
||||
result = JSON.parse(response.body)
|
||||
|
||||
expected_for_fiat.each { |key| expect(result).to have_key key }
|
||||
|
||||
(expected_for_coin - expected_for_fiat).each do |key|
|
||||
expect(result).not_to have_key key
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns correct keys for coin' do
|
||||
get "/api/v2/public/currencies/#{coin.id}"
|
||||
expect(response).to be_successful
|
||||
|
||||
result = JSON.parse(response.body)
|
||||
expected_for_coin.each { |key| expect(result).to have_key key }
|
||||
end
|
||||
|
||||
it 'returns error in case of invalid id' do
|
||||
get '/api/v2/public/currencies/invalid'
|
||||
|
||||
expect(response).to have_http_status 422
|
||||
expect(response).to include_api_error('public.currency.doesnt_exist')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /api/v2/public/currencies' do
|
||||
it 'lists visible currencies' do
|
||||
get '/api/v2/public/currencies'
|
||||
expect(response).to be_successful
|
||||
|
||||
result = JSON.parse(response.body)
|
||||
expect(result.size).to eq Currency.visible.size
|
||||
end
|
||||
|
||||
it 'lists visible coins' do
|
||||
get '/api/v2/public/currencies', params: { type: 'coin' }
|
||||
expect(response).to be_successful
|
||||
|
||||
result = JSON.parse(response.body)
|
||||
expect(result.size).to eq Currency.coins.visible.size
|
||||
end
|
||||
|
||||
it 'lists visible fiats' do
|
||||
get '/api/v2/public/currencies', params: { type: 'fiat' }
|
||||
expect(response).to be_successful
|
||||
|
||||
result = JSON.parse(response.body, symbolize_names: true)
|
||||
expect(result.size).to eq Currency.fiats.visible.size
|
||||
expect(result.dig(0, :id)).to eq 'usd'
|
||||
end
|
||||
|
||||
it 'returns error in case of invalid type' do
|
||||
get '/api/v2/public/currencies', params: { type: 'invalid' }
|
||||
expect(response).to have_http_status 422
|
||||
end
|
||||
|
||||
context 'pagination' do
|
||||
it 'returns paginated currencies' do
|
||||
get '/api/v2/public/currencies', params: { limit: 2 }
|
||||
|
||||
result = JSON.parse(response.body)
|
||||
|
||||
expect(response).to be_successful
|
||||
|
||||
expect(response.headers.fetch('Total').to_i).to eq Currency.visible.count
|
||||
expect(result.size).to eq(2)
|
||||
end
|
||||
end
|
||||
|
||||
context 'search' do
|
||||
it 'searches by code' do
|
||||
get '/api/v2/public/currencies', params: { search: { code: 't' } }
|
||||
|
||||
expect(response).to be_successful
|
||||
result = JSON.parse(response.body)
|
||||
|
||||
expect(result.pluck('id')).to contain_exactly('eth', 'btc', 'trst')
|
||||
end
|
||||
|
||||
it 'searches by name' do
|
||||
get '/api/v2/public/currencies', params: { search: { name: 'e' } }
|
||||
|
||||
expect(response).to be_successful
|
||||
result = JSON.parse(response.body)
|
||||
|
||||
expect(result.pluck('name')).to contain_exactly('Ethereum', 'Evolution Land Global Token', 'WeTrust')
|
||||
end
|
||||
|
||||
it 'searches by code or name' do
|
||||
get '/api/v2/public/currencies', params: { search: { name: 'us', code: 'us' } }
|
||||
|
||||
expect(response).to be_successful
|
||||
result = JSON.parse(response.body)
|
||||
|
||||
expect(result.pluck('id')).to contain_exactly('usd', 'trst')
|
||||
expect(result.pluck('name')).to contain_exactly('US Dollar', 'WeTrust')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
760
spec/api/v2/public/markets_spec.rb
Normal file
760
spec/api/v2/public/markets_spec.rb
Normal file
@@ -0,0 +1,760 @@
|
||||
# encoding: UTF-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
describe API::V2::Public::Markets, type: :request do
|
||||
|
||||
before(:each) { clear_redis }
|
||||
describe 'GET /api/v2/markets' do
|
||||
before { create(:market, :ethusd) }
|
||||
|
||||
let(:expected_keys) do
|
||||
%w[id name base_unit quote_unit min_price max_price
|
||||
min_amount amount_precision price_precision state]
|
||||
end
|
||||
|
||||
it 'lists enabled markets' do
|
||||
get '/api/v2/public/markets'
|
||||
expect(response).to be_successful
|
||||
result = JSON.parse(response.body)
|
||||
|
||||
expect(result.size).to eq Market.enabled.size
|
||||
|
||||
result.each do |market|
|
||||
expect(market.keys).to contain_exactly(*expected_keys)
|
||||
end
|
||||
end
|
||||
|
||||
context 'api will return hidden markets' do
|
||||
before { create(:market, :btceur, state: :hidden) }
|
||||
it 'returns hidden market' do
|
||||
get '/api/v2/public/markets'
|
||||
expect(response).to be_successful
|
||||
result = JSON.parse(response.body)
|
||||
|
||||
expect(result.find { |currency| currency['id'] == 'btceur' }['state']).to eq('hidden')
|
||||
end
|
||||
end
|
||||
|
||||
context 'pagination' do
|
||||
it 'returns paginated markets' do
|
||||
get '/api/v2/public/markets', params: { limit: 2 }
|
||||
|
||||
result = JSON.parse(response.body)
|
||||
|
||||
expect(response).to be_successful
|
||||
|
||||
expect(response.headers.fetch('Total').to_i).to eq Market.enabled.size
|
||||
expect(result.size).to eq(2)
|
||||
end
|
||||
end
|
||||
|
||||
context 'filters' do
|
||||
context 'base_unit & quote_unit' do
|
||||
it 'filters by base_unit' do
|
||||
get '/api/v2/public/markets', params: { base_unit: :btc }
|
||||
expect(response).to be_successful
|
||||
result = JSON.parse(response.body)
|
||||
|
||||
expect(result.size).to eq Market.enabled.where(base_unit: :btc).size
|
||||
result.each do |market|
|
||||
expect(market['base_unit']).to eq 'btc'
|
||||
end
|
||||
end
|
||||
|
||||
it 'filters by quote_unit' do
|
||||
get '/api/v2/public/markets', params: { quote_unit: :usd }
|
||||
expect(response).to be_successful
|
||||
result = JSON.parse(response.body)
|
||||
|
||||
expect(result.size).to eq Market.enabled.where(quote_unit: :usd).size
|
||||
result.each do |market|
|
||||
expect(market['quote_unit']).to eq 'usd'
|
||||
end
|
||||
end
|
||||
|
||||
it 'does not filter' do
|
||||
get '/api/v2/public/markets'
|
||||
expect(response).to be_successful
|
||||
result = JSON.parse(response.body)
|
||||
|
||||
expect(result.size).to eq Market.enabled.size
|
||||
end
|
||||
end
|
||||
|
||||
context 'base_code & quote_code' do
|
||||
it 'filters by base_code' do
|
||||
get '/api/v2/public/markets', params: { search: { base_code: "bt" } }
|
||||
# Since we have next markets list:
|
||||
# btcusd, btceth, ethusd
|
||||
# Since 2 of them has 'bt' in base_unit (btc).
|
||||
# We expect them to be returned in API response.
|
||||
expect(response).to be_successful
|
||||
result = JSON.parse(response.body)
|
||||
|
||||
expect(result.pluck('id')).to contain_exactly('btceth', 'btcusd')
|
||||
end
|
||||
|
||||
it 'filters by quote_code' do
|
||||
Currency.find(:eur).update(visible: true)
|
||||
create(:market, :btceur)
|
||||
# Since we have next markets list:
|
||||
# btceur, btcusd, btceth, ethusd
|
||||
# Since 2 of them has 'e' in quote_unit (eur, eth).
|
||||
# We expect them to be returned in API response.
|
||||
get '/api/v2/public/markets', params: { search: { quote_code: "e" } }
|
||||
expect(response).to be_successful
|
||||
result = JSON.parse(response.body)
|
||||
|
||||
expect(result.pluck('id')).to contain_exactly('btceth', 'btceur')
|
||||
end
|
||||
end
|
||||
|
||||
context 'quote_name' do
|
||||
before do
|
||||
Currency.find(:eur).update(visible: true)
|
||||
create(:market, :btceur)
|
||||
create(:market, :btctrst)
|
||||
end
|
||||
|
||||
it 'filters by name 1' do
|
||||
# Since we have next markets list:
|
||||
# btceur, btcusd, btceth, btctrst, ethusd
|
||||
# Since 3 of them has 'E' in quote name (Euro, Ethereum, We Trust).
|
||||
# We expect them to be returned in API response.
|
||||
get '/api/v2/public/markets', params: { search: { quote_name: 'E' } }
|
||||
expect(response).to be_successful
|
||||
result = JSON.parse(response.body)
|
||||
expect(result.pluck('id')).to contain_exactly('btceth', 'btceur', 'btctrst')
|
||||
end
|
||||
|
||||
it 'filters by name 2' do
|
||||
# Since we have next markets list:
|
||||
# btceur, btcusd, btceth, btctrst, ethusd
|
||||
# Since 3 of them has 'uS' in quote name (US Dollar, We Trust).
|
||||
# We expect them to be returned in API response.
|
||||
get '/api/v2/public/markets', params: { search: { quote_name: 'uS' } }
|
||||
expect(response).to be_successful
|
||||
result = JSON.parse(response.body)
|
||||
expect(result.pluck('id')).to contain_exactly('btcusd', 'btctrst', 'ethusd')
|
||||
end
|
||||
end
|
||||
|
||||
context 'complex filter' do
|
||||
before do
|
||||
Currency.find(:eur).update(visible: true)
|
||||
create(:market, :btceur)
|
||||
create(:market, :btctrst)
|
||||
end
|
||||
|
||||
it 'filters by base_unit & quote_name or quote_code' do
|
||||
# Since we have next markets list:
|
||||
# btceur, btcusd, btceth, btctrst, ethusd
|
||||
# 1. Filter by base_unit btc: btceur, btcusd, btceth, btctrst
|
||||
# 2. Filter by quote_code or quote_name 'et': btceth, btctrst (Ethereum, WeTrust)
|
||||
# We expect them to be returned in API response.
|
||||
get '/api/v2/public/markets', params: { base_unit: :btc, search: { quote_name: 'et', quote_code: 'et' } }
|
||||
expect(response).to be_successful
|
||||
result = JSON.parse(response.body)
|
||||
expect(result.pluck('id')).to contain_exactly('btceth', 'btctrst')
|
||||
end
|
||||
|
||||
it 'filters by base_unit & quote_code' do
|
||||
# Since we have next markets list:
|
||||
# btceur, btcusd, btceth, btctrst, ethusd
|
||||
# 1. Filter by base_unit btc: btceur, btcusd, btceth, btctrst
|
||||
# 2. Filter by quote_code 'et': btceth (eth)
|
||||
# We expect them to be returned in API response.
|
||||
get '/api/v2/public/markets', params: { base_unit: :btc, search: { quote_code: 'et' } }
|
||||
expect(response).to be_successful
|
||||
result = JSON.parse(response.body)
|
||||
expect(result.pluck('id')).to contain_exactly('btceth')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /api/v2/public/markets/:market/order_book' do
|
||||
before do
|
||||
create_list(:order_bid, 5, :btcusd)
|
||||
create_list(:order_ask, 5, :btcusd)
|
||||
end
|
||||
|
||||
let(:market) { :btcusd }
|
||||
|
||||
it 'returns ask and bid orders on specified market' do
|
||||
get "/api/v2/public/markets/#{market}/order-book"
|
||||
expect(response).to be_successful
|
||||
|
||||
result = JSON.parse(response.body)
|
||||
expect(result['asks'].size).to eq 5
|
||||
expect(result['bids'].size).to eq 5
|
||||
end
|
||||
|
||||
context 'market name with dot' do
|
||||
let!(:currency) { create(:currency, :xagm_cx) }
|
||||
let!(:market) { create(:market, :xagm_cxusd) }
|
||||
|
||||
it 'returns information about specified market' do
|
||||
get "/api/v2/public/markets/#{market.id}/order-book"
|
||||
expect(response).to be_successful
|
||||
|
||||
result = JSON.parse(response.body)
|
||||
expect(result['asks'].size).to eq 0
|
||||
expect(result['bids'].size).to eq 0
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns limited asks and bids' do
|
||||
get "/api/v2/public/markets/#{market}/order-book", params: { asks_limit: 1, bids_limit: 1 }
|
||||
expect(response).to be_successful
|
||||
|
||||
result = JSON.parse(response.body)
|
||||
expect(result['asks'].size).to eq 1
|
||||
expect(result['bids'].size).to eq 1
|
||||
end
|
||||
|
||||
it 'validates market param' do
|
||||
get "/api/v2/public/markets/somecoin/order-book", params: { asks_limit: 1, bids_limit: 1 }
|
||||
expect(response).to have_http_status 422
|
||||
expect(response).to include_api_error('public.market.doesnt_exist')
|
||||
end
|
||||
|
||||
it 'validates asks limit' do
|
||||
get "/api/v2/public/markets/somecoin/order-book", params: { asks_limit: 201, bids_limit: 1 }
|
||||
expect(response).to have_http_status 422
|
||||
expect(response).to include_api_error('public.order_book.invalid_ask_limit')
|
||||
end
|
||||
|
||||
it 'validates bids limit' do
|
||||
get "/api/v2/public/markets/somecoin/order-book", params: { asks_limit: 1, bids_limit: 201 }
|
||||
expect(response).to have_http_status 422
|
||||
expect(response).to include_api_error('public.order_book.invalid_bid_limit')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /api/v2/markets/:market/depth' do
|
||||
before do
|
||||
create_list(:order_bid, 5, :btcusd)
|
||||
create_list(:order_bid, 5, :btcusd, price: 2)
|
||||
create_list(:order_ask, 5, :btcusd)
|
||||
create_list(:order_ask, 5, :btcusd, price: 3)
|
||||
end
|
||||
|
||||
let(:asks) { [["1.0", "5.0"], ["3.0", "5.0"]] }
|
||||
let(:bids) { [["2.0", "5.0"], ["1.0", "5.0"]] }
|
||||
|
||||
let(:market) { :btcusd }
|
||||
|
||||
context 'valid market param' do
|
||||
it 'sorts asks and bids from highest to lowest' do
|
||||
get "/api/v2/public/markets/#{market}/depth"
|
||||
expect(response).to be_successful
|
||||
|
||||
result = JSON.parse(response.body)
|
||||
expect(result['asks']).to eq asks
|
||||
expect(result['bids']).to eq bids
|
||||
end
|
||||
end
|
||||
|
||||
context 'market name with dot' do
|
||||
let!(:currency) { create(:currency, :xagm_cx) }
|
||||
let!(:market) { create(:market, :xagm_cxusd) }
|
||||
|
||||
it 'returns information about specified market' do
|
||||
get "/api/v2/public/markets/#{market.id}/depth"
|
||||
expect(response).to be_successful
|
||||
|
||||
result = JSON.parse(response.body)
|
||||
expect(result['asks'].size).to eq 0
|
||||
expect(result['bids'].size).to eq 0
|
||||
end
|
||||
end
|
||||
|
||||
context 'invalid market param' do
|
||||
it 'validates market param' do
|
||||
api_get "/api/v2/public/markets/usdusd/depth"
|
||||
expect(response).to have_http_status 422
|
||||
expect(response).to include_api_error('public.market.doesnt_exist')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /api/v2/public/markets/market/k-line' do
|
||||
let(:points) do
|
||||
# [timestamp, open_price, max_price, min_price, last_price, period_volume]
|
||||
[[1537370460, 0.7079, 0.2204, 0.9794, 0.5273, 0.0747],
|
||||
[1537370520, 0.6293, 0.5054, 0.2253, 0.1969, 0.7276],
|
||||
[1537370580, 0.0939, 0.1949, 0.0032, 0.8328, 0.5895],
|
||||
[1537370640, 0.6416, 0.0772, 0.7045, 0.7794, 0.6151],
|
||||
[1537370700, 0.0566, 0.6377, 0.3007, 0.6855, 0.6976],
|
||||
[1537370760, 0.7868, 0.6465, 0.3207, 0.6428, 0.1771],
|
||||
[1537370820, 0.3318, 0.2124, 0.3773, 0.4274, 0.3473],
|
||||
[1537370880, 0.0704, 0.4902, 0.5957, 0.5214, 0.3687],
|
||||
[1537370940, 0.6629, 0.6585, 0.0756, 0.4559, 0.8554],
|
||||
[1537371000, 0.6627, 0.6627, 0.2128, 0.0788, 0.2013],
|
||||
[1537371060, 0.5165, 0.0435, 0.5228, 0.6447, 0.9237],
|
||||
[1537371120, 0.9311, 0.8886, 0.1605, 0.3223, 0.0211],
|
||||
[1537371180, 0.0704, 0.0103, 0.0325, 0.3846, 0.8957],
|
||||
[1537371240, 0.1445, 0.6031, 0.9533, 0.0866, 0.4871],
|
||||
[1537371300, 0.0974, 0.1344, 0.1533, 0.9029, 0.2009],
|
||||
[1537371360, 0.2609, 0.9687, 0.0287, 0.4465, 0.7088],
|
||||
[1537371420, 0.5671, 0.0576, 0.6617, 0.1041, 0.4942],
|
||||
[1537371480, 0.8355, 0.5336, 0.7419, 0.7062, 0.9562],
|
||||
[1537371540, 0.1805, 0.3577, 0.2768, 0.3162, 0.0209],
|
||||
[1537371600, 0.7971, 0.1799, 0.8307, 0.5074, 0.0122],
|
||||
[1537371660, 0.9491, 0.7448, 0.2019, 0.4662, 0.7035],
|
||||
[1537371720, 0.8126, 0.3899, 0.8823, 0.8115, 0.6067],
|
||||
[1537371780, 0.2632, 0.6558, 0.7411, 0.3894, 0.1509],
|
||||
[1537371840, 0.4274, 0.8187, 0.6661, 0.4331, 0.6335],
|
||||
[1537371900, 0.1356, 0.1787, 0.3081, 0.9549, 0.0723],
|
||||
[1537371960, 0.1931, 0.9486, 0.2469, 0.2295, 0.9366],
|
||||
[1537372020, 0.8323, 0.8168, 0.8453, 0.1278, 0.7975],
|
||||
[1537372080, 0.5663, 0.1374, 0.0025, 0.0358, 0.6063],
|
||||
[1537372140, 0.9296, 0.5443, 0.2732, 0.6434, 0.9173],
|
||||
[1537372200, 0.7292, 0.0367, 0.3569, 0.7876, 0.6626],
|
||||
[1537372260, 0.9979, 0.2182, 0.5141, 0.8984, 0.4512],
|
||||
[1537372320, 0.4363, 0.4416, 0.2354, 0.6053, 0.7398],
|
||||
[1537372380, 0.1815, 0.4969, 0.4091, 0.0798, 0.8797]]
|
||||
end
|
||||
let(:point_period) { KLineService::POINT_PERIOD_IN_SECONDS }
|
||||
let(:points_default_limit) { 30 }
|
||||
let(:last_point) { points.last }
|
||||
let(:first_point) { points.first }
|
||||
|
||||
before { write_to_influx(points) }
|
||||
after { delete_measurments("candles_1m") }
|
||||
|
||||
def influx_data(point)
|
||||
{
|
||||
values:
|
||||
{
|
||||
open: point[1],
|
||||
high: point[2],
|
||||
low: point[3],
|
||||
close: point[4],
|
||||
volume: point[5],
|
||||
},
|
||||
tags:
|
||||
{
|
||||
market: 'btcusd'
|
||||
},
|
||||
timestamp: point[0]
|
||||
}
|
||||
end
|
||||
|
||||
def write_to_influx(points)
|
||||
points.each do |point|
|
||||
Peatio::InfluxDB.client(epoch: 's').write_point('candles_1m', influx_data(point), 's')
|
||||
end
|
||||
end
|
||||
|
||||
def load_k_line(query = {})
|
||||
api_get '/api/v2/public/markets/btcusd/k-line?' + query.to_query
|
||||
expect(response).to have_http_status 200
|
||||
end
|
||||
|
||||
def response_body
|
||||
JSON.parse(response.body)
|
||||
end
|
||||
|
||||
context 'data exists' do
|
||||
it 'without time limits' do
|
||||
load_k_line
|
||||
expect(JSON.parse(response.body)).to eq points[-points_default_limit..-1]
|
||||
end
|
||||
|
||||
context 'with time_from' do
|
||||
it 'smaller than first point timestamp' do
|
||||
load_k_line(time_from: first_point.first - 2 * point_period)
|
||||
expect(response_body).to eq points[0...points_default_limit]
|
||||
end
|
||||
|
||||
it 'bigger than last point timestamp' do
|
||||
load_k_line(time_from: last_point.first + 2 * point_period)
|
||||
expect(response_body).to eq []
|
||||
end
|
||||
|
||||
it 'in range of first and last timestamp' do
|
||||
time_from = first_point.first + 10 * point_period
|
||||
load_k_line(time_from: time_from)
|
||||
expect(response_body).to eq points[10..-1]
|
||||
# First point timestamp should be eq to time_from.
|
||||
expect(response_body.first.first).to eq time_from
|
||||
|
||||
time_from = first_point.first + 22 * point_period
|
||||
load_k_line(time_from: time_from)
|
||||
expect(response_body).to eq points[22..-1]
|
||||
# First point timestamp should be eq to time_from.
|
||||
expect(response_body.first.first).to eq time_from
|
||||
end
|
||||
end
|
||||
|
||||
context 'with time_to' do
|
||||
it 'smaller than first point timestamp' do
|
||||
load_k_line(time_to: first_point.first - 2 * point_period)
|
||||
expect(response_body).to eq []
|
||||
end
|
||||
|
||||
it 'bigger than last point timestamp' do
|
||||
load_k_line(time_to: last_point.first + 2 * point_period)
|
||||
# Returns (limit - 2) left points.
|
||||
expect(response_body).to eq points[-points_default_limit..]
|
||||
end
|
||||
|
||||
it 'in range of first and last timestamp' do
|
||||
load_k_line(time_to: first_point.first + 1 * point_period)
|
||||
expect(response_body).to eq points[0..1]
|
||||
|
||||
load_k_line(time_to: first_point.first + 20 * point_period)
|
||||
expect(response_body).to eq points[0..20]
|
||||
end
|
||||
end
|
||||
|
||||
context 'with time_from and time_to' do
|
||||
|
||||
it 'time_to less than time_from' do
|
||||
time_from = first_point.first + 2 * point_period
|
||||
time_to = first_point.first - 2 * point_period
|
||||
|
||||
load_k_line(time_from: time_from, time_to: time_to)
|
||||
expect(response_body).to eq []
|
||||
end
|
||||
|
||||
it 'both less than first point timestamp' do
|
||||
time_from = first_point.first - 10 * point_period
|
||||
time_to = first_point.first - 4 * point_period
|
||||
|
||||
load_k_line(time_from: time_from, time_to: time_to)
|
||||
expect(response_body).to eq []
|
||||
end
|
||||
|
||||
it 'both bigger than last point timestamp' do
|
||||
time_from = last_point.first + 2 * point_period
|
||||
time_to = last_point.first + 12 * point_period
|
||||
|
||||
load_k_line(time_from: time_from, time_to: time_to)
|
||||
expect(response_body).to eq []
|
||||
end
|
||||
|
||||
it 'both in range of first and last timestamp' do
|
||||
time_from = first_point.first + 10 * point_period
|
||||
time_to = last_point.first - 10 * point_period
|
||||
|
||||
load_k_line(time_from: time_from, time_to: time_to)
|
||||
# Points timestamps should be in range time_from..time_to (limit is bigger).
|
||||
expect(response_body).to eq\
|
||||
points.select { |p| p.first >= time_from && p.first <= time_to }
|
||||
expect(response_body.first.first).to eq time_from
|
||||
expect(response_body.last.first).to eq time_to
|
||||
end
|
||||
end
|
||||
|
||||
context 'with limit' do
|
||||
it 'returns n last points' do
|
||||
limit = 5
|
||||
load_k_line(limit: limit)
|
||||
expect(response_body).to eq points[-limit..-1]
|
||||
|
||||
limit = 10
|
||||
load_k_line(limit: limit)
|
||||
expect(response_body).to eq points[-limit..-1]
|
||||
end
|
||||
|
||||
it 'returns all points if limit greater than points number' do
|
||||
limit = points.length + 1
|
||||
load_k_line(limit: limit)
|
||||
expect(response_body).to eq points
|
||||
end
|
||||
end
|
||||
|
||||
context 'with limits, time_from and time_to' do
|
||||
it 'ignores limit' do
|
||||
time_from = first_point.first + 1 * point_period
|
||||
time_to = last_point.first - 1 * point_period
|
||||
limit = 5
|
||||
load_k_line(time_from: time_from, time_to: time_to, limit: limit)
|
||||
|
||||
# All point in time_from..time_to including time_to (time_to - time_from) / 60 + 1.
|
||||
expect(response_body.count).to eq (time_to - time_from) / 60 + 1
|
||||
# Points timestamps should be in range time_from..time_to.
|
||||
expect(response_body).to eq\
|
||||
points.select { |p| p.first >= time_from && p.first <= time_to }
|
||||
expect(response_body.first.first).to eq time_from
|
||||
expect(response_body.last.first).to eq time_to
|
||||
end
|
||||
end
|
||||
|
||||
context 'with limits and time_from' do
|
||||
it 'returns n right points from time_from (adds limit to time_from)' do
|
||||
time_from = first_point.first + 5 * point_period
|
||||
limit = 10
|
||||
load_k_line(time_from: time_from, limit: limit)
|
||||
|
||||
expect(response_body.count).to eq limit
|
||||
# Points timestamps should be bigger than time_from and we select first 10.
|
||||
expect(response_body).to eq\
|
||||
points.select { |p| p.first >= time_from }[0...limit]
|
||||
expect(response_body.first.first).to eq time_from
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'data is missing' do
|
||||
before { delete_measurments("candles_1m") }
|
||||
|
||||
it 'without time_from' do
|
||||
load_k_line
|
||||
expect(JSON.parse(response.body)).to eq []
|
||||
end
|
||||
|
||||
it 'with time_from' do
|
||||
load_k_line(time_from: first_point.first)
|
||||
expect(JSON.parse(response.body)).to eq []
|
||||
end
|
||||
|
||||
it 'with time_from and time_to' do
|
||||
load_k_line(time_from: first_point.first, time_to: last_point.first)
|
||||
expect(JSON.parse(response.body)).to eq []
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /api/v2/markets/tickers' do
|
||||
after { delete_measurments("trades") }
|
||||
|
||||
context 'no trades executed yet' do
|
||||
let(:expected_ticker) do
|
||||
{ 'low' => '0.0', 'high' => '0.0',
|
||||
'open' => '0.0', 'last' => '0.0',
|
||||
'volume' => '0.0', 'vol' => '0.0', 'amount' => '0.0',
|
||||
'avg_price' => '0.0', 'price_change_percent' => '+0.00%' }
|
||||
end
|
||||
|
||||
it 'returns ticker of all markets' do
|
||||
get '/api/v2/public/markets/tickers'
|
||||
expect(response).to be_successful
|
||||
expect(JSON.parse(response.body)['btcusd']['at']).not_to be_nil
|
||||
expect(JSON.parse(response.body)['btcusd']['ticker']).to include(expected_ticker)
|
||||
end
|
||||
end
|
||||
|
||||
context 'single trade was executed' do
|
||||
let!(:trade) { create(:trade, :btcusd, price: '5.0'.to_d, amount: '1.1'.to_d, total: '5.5'.to_d)}
|
||||
let(:expected_ticker) do
|
||||
{ 'low' => '5.0', 'high' => '5.0',
|
||||
'open' => '5.0', 'last' => '5.0',
|
||||
'volume' => '5.5', 'vol' => '5.5', 'amount' => '1.1',
|
||||
'avg_price' => '5.0', 'price_change_percent' => '+0.00%' }
|
||||
end
|
||||
before do
|
||||
trade.write_to_influx
|
||||
end
|
||||
|
||||
it 'returns market tickers' do
|
||||
get '/api/v2/public/markets/tickers'
|
||||
expect(response).to be_successful
|
||||
expect(JSON.parse(response.body)['btcusd']['at']).not_to be_nil
|
||||
expect(JSON.parse(response.body)['btcusd']['ticker']).to include(expected_ticker)
|
||||
end
|
||||
end
|
||||
|
||||
context 'multiple trades were executed' do
|
||||
let!(:trade1) { create(:trade, :btcusd, price: '5.0'.to_d, amount: '1.1'.to_d, total: '5.5'.to_d)}
|
||||
let!(:trade2) { create(:trade, :btcusd, price: '6.0'.to_d, amount: '0.9'.to_d, total: '5.4'.to_d)}
|
||||
|
||||
let(:expected_ticker) do
|
||||
{ 'low' => '5.0', 'high' => '6.0',
|
||||
'open' => '5.0', 'last' => '6.0',
|
||||
'vol' => '10.9', 'volume' => '10.9', 'amount' => '2.0',
|
||||
'avg_price' => '5.45', 'price_change_percent' => '+20.00%' }
|
||||
end
|
||||
before do
|
||||
trade1.write_to_influx
|
||||
trade2.write_to_influx
|
||||
end
|
||||
|
||||
it 'returns market tickers' do
|
||||
get '/api/v2/public/markets/tickers'
|
||||
expect(response).to be_successful
|
||||
expect(JSON.parse(response.body)['btcusd']['at']).not_to be_nil
|
||||
expect(JSON.parse(response.body)['btcusd']['ticker']).to include(expected_ticker)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /api/v2/public/markets/:market/tickers' do
|
||||
after { delete_measurments("trades") }
|
||||
context 'no trades executed yet' do
|
||||
let(:expected_ticker) do
|
||||
{ 'low' => '0.0', 'high' => '0.0',
|
||||
'open' => '0.0', 'last' => '0.0',
|
||||
'volume' => '0.0', 'vol' => '0.0', 'amount' => '0.0',
|
||||
'avg_price' => '0.0', 'price_change_percent' => '+0.00%' }
|
||||
end
|
||||
|
||||
it 'returns market tickers' do
|
||||
get '/api/v2/public/markets/btcusd/tickers'
|
||||
expect(response).to be_successful
|
||||
expect(JSON.parse(response.body)['ticker']).to include(expected_ticker)
|
||||
end
|
||||
|
||||
context 'market name with dot' do
|
||||
let!(:currency) { create(:currency, :xagm_cx) }
|
||||
let!(:market) { create(:market, :xagm_cxusd) }
|
||||
|
||||
it 'returns information about specified market' do
|
||||
get "/api/v2/public/markets/#{market.id}/tickers"
|
||||
expect(response).to be_successful
|
||||
expect(JSON.parse(response.body)['ticker']).to include(expected_ticker)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'single trade was executed' do
|
||||
let!(:trade) { create(:trade, :btcusd, price: '5.0'.to_d, amount: '1.1'.to_d, total: '5.5'.to_d)}
|
||||
let(:expected_ticker) do
|
||||
{ 'low' => '5.0', 'high' => '5.0',
|
||||
'open' => '5.0', 'last' => '5.0',
|
||||
'volume' => '5.5', 'vol' => '5.5', 'amount' => '1.1',
|
||||
'avg_price' => '5.0', 'price_change_percent' => '+0.00%' }
|
||||
end
|
||||
before do
|
||||
trade.write_to_influx
|
||||
end
|
||||
|
||||
it 'returns market tickers' do
|
||||
get '/api/v2/public/markets/btcusd/tickers'
|
||||
expect(response).to be_successful
|
||||
expect(JSON.parse(response.body)['ticker']).to include(expected_ticker)
|
||||
end
|
||||
end
|
||||
|
||||
context 'multiple trades were executed' do
|
||||
let!(:trade1) { create(:trade, :btcusd, price: '5.0'.to_d, amount: '1.1'.to_d, total: '5.5'.to_d)}
|
||||
let!(:trade2) { create(:trade, :btcusd, price: '6.0'.to_d, amount: '0.9'.to_d, total: '5.4'.to_d)}
|
||||
|
||||
# open = 6.0 because it takes last by default.
|
||||
# to make it work correctly need to run k-line daemon.
|
||||
let(:expected_ticker) do
|
||||
{ 'low' => '5.0', 'high' => '6.0',
|
||||
'open' => '5.0', 'last' => '6.0',
|
||||
'vol' => '10.9', 'volume' => '10.9', 'amount' => '2.0',
|
||||
'avg_price' => '5.45', 'price_change_percent' => '+20.00%' }
|
||||
end
|
||||
before do
|
||||
trade1.write_to_influx
|
||||
trade2.write_to_influx
|
||||
end
|
||||
|
||||
it 'returns market tickers' do
|
||||
get '/api/v2/public/markets/btcusd/tickers'
|
||||
expect(response).to be_successful
|
||||
expect(JSON.parse(response.body)['ticker']).to include(expected_ticker)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /api/v2/public/markets/#{market}/trades' do
|
||||
|
||||
let(:member) do
|
||||
create(:member, :level_3).tap do |m|
|
||||
m.get_account(:btc).update_attributes(balance: 12.13, locked: 3.14)
|
||||
m.get_account(:usd).update_attributes(balance: 2014.47, locked: 0)
|
||||
end
|
||||
end
|
||||
|
||||
let(:ask) do
|
||||
create(
|
||||
:order_ask,
|
||||
:btcusd,
|
||||
price: '12.32'.to_d,
|
||||
volume: '123.12345678',
|
||||
member: member
|
||||
)
|
||||
end
|
||||
|
||||
let(:bid) do
|
||||
create(
|
||||
:order_bid,
|
||||
:btcusd,
|
||||
price: '12.32'.to_d,
|
||||
volume: '123.12345678',
|
||||
member: member
|
||||
)
|
||||
end
|
||||
|
||||
let(:market) { :btcusd }
|
||||
|
||||
let!(:ask_trade) { create(:trade, :btcusd, maker_order: ask, created_at: 2.days.ago) }
|
||||
let!(:bid_trade) { create(:trade, :btcusd, taker_order: bid, created_at: 1.day.ago) }
|
||||
|
||||
|
||||
after do
|
||||
delete_measurments('trades')
|
||||
end
|
||||
|
||||
before do
|
||||
ask_trade.write_to_influx
|
||||
bid_trade.write_to_influx
|
||||
end
|
||||
|
||||
it 'returns all recent trades' do
|
||||
get "/api/v2/public/markets/#{market}/trades"
|
||||
|
||||
expect(response).to be_successful
|
||||
expect(JSON.parse(response.body).size).to eq 2
|
||||
end
|
||||
|
||||
context 'market name with dot' do
|
||||
let!(:currency) { create(:currency, :xagm_cx) }
|
||||
let!(:market) { create(:market, :xagm_cxusd) }
|
||||
|
||||
it 'returns information about specified market' do
|
||||
get "/api/v2/public/markets/#{market.id}/trades"
|
||||
expect(response).to be_successful
|
||||
expect(JSON.parse(response.body).size).to eq 0
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns 1 trade' do
|
||||
get "/api/v2/public/markets/#{market}/trades", params: {limit: 1}
|
||||
|
||||
expect(response).to be_successful
|
||||
expect(JSON.parse(response.body).size).to eq 1
|
||||
end
|
||||
|
||||
it 'sorts trades in reverse creation order' do
|
||||
get "/api/v2/public/markets/#{market}/trades"
|
||||
|
||||
expect(response).to be_successful
|
||||
expect(JSON.parse(response.body).first['id']).to eq bid_trade.id
|
||||
end
|
||||
|
||||
it 'gets trades by limit' do
|
||||
trade = create(:trade, :btcusd, taker_order: bid, created_at: 6.hours.ago)
|
||||
trade.write_to_influx
|
||||
|
||||
get "/api/v2/public/markets/#{market}/trades", params: { limit: 2, order_by: 'asc'}
|
||||
|
||||
expect(response).to be_successful
|
||||
expect(JSON.parse(response.body).count).to eq 2
|
||||
|
||||
get "/api/v2/public/markets/#{market}/trades", params: { market: 'btcusd', limit: 3, order_by: 'asc' }
|
||||
|
||||
expect(response).to be_successful
|
||||
expect(JSON.parse(response.body).count).to eq 3
|
||||
end
|
||||
|
||||
it 'validates market param' do
|
||||
api_get "/api/v2/public/markets/usdusd/trades"
|
||||
expect(response).to have_http_status 422
|
||||
expect(response).to include_api_error('public.market.doesnt_exist')
|
||||
end
|
||||
|
||||
it 'validates limit param' do
|
||||
get "/api/v2/public/markets/#{market}/trades", params: { limit: 1001 }
|
||||
expect(response).to have_http_status 422
|
||||
expect(response).to include_api_error('public.trade.invalid_limit')
|
||||
end
|
||||
end
|
||||
end
|
||||
12
spec/api/v2/public/member_levels_spec.rb
Normal file
12
spec/api/v2/public/member_levels_spec.rb
Normal file
@@ -0,0 +1,12 @@
|
||||
# encoding: UTF-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
describe API::V2::Public::MemberLevels, type: :request do
|
||||
describe 'GET /member_levels' do
|
||||
it 'responds with 200 and returns correct data' do
|
||||
api_get '/api/v2/public/member-levels'
|
||||
expect(response).to be_successful
|
||||
expect(response.body).to eq '{"deposit":{"minimum_level":3},"withdraw":{"minimum_level":3},"trading":{"minimum_level":3}}'
|
||||
end
|
||||
end
|
||||
end
|
||||
39
spec/api/v2/public/tools_spec.rb
Normal file
39
spec/api/v2/public/tools_spec.rb
Normal file
@@ -0,0 +1,39 @@
|
||||
# encoding: UTF-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
describe API::V2::Public::Tools, type: :request do
|
||||
describe '/timestamp' do
|
||||
it 'returns current time in seconds' do
|
||||
now = Time.now
|
||||
get '/api/v2/public/timestamp'
|
||||
expect(response).to be_successful
|
||||
expect(JSON.parse(response.body)).to be_between(now.iso8601, (now + 1).iso8601)
|
||||
end
|
||||
end
|
||||
|
||||
describe '/health' do
|
||||
it 'returns successful liveness probe' do
|
||||
get '/api/v2/public/health/alive'
|
||||
expect(response).to be_successful
|
||||
end
|
||||
|
||||
it 'returns failed liveness probe' do
|
||||
Market.stubs(:connected?).returns(false)
|
||||
|
||||
get '/api/v2/public/health/alive'
|
||||
expect(response).to have_http_status(503)
|
||||
end
|
||||
|
||||
it 'returns successful readiness probe' do
|
||||
get '/api/v2/public/health/ready'
|
||||
expect(response).to be_successful
|
||||
end
|
||||
|
||||
it 'returns failed readiness probe' do
|
||||
Bunny.stubs(:run).returns(false)
|
||||
|
||||
get '/api/v2/public/health/alive'
|
||||
expect(response).to have_http_status(503)
|
||||
end
|
||||
end
|
||||
end
|
||||
50
spec/api/v2/public/trading_fees_spec.rb
Normal file
50
spec/api/v2/public/trading_fees_spec.rb
Normal file
@@ -0,0 +1,50 @@
|
||||
# encoding: UTF-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
describe API::V2::Public::TradingFees, type: :request do
|
||||
|
||||
before(:each) { clear_redis }
|
||||
describe 'GET /trading_fees' do
|
||||
before do
|
||||
create(:trading_fee, maker: 0.0005, taker: 0.001, market_id: :btcusd, group: 'vip-0')
|
||||
create(:trading_fee, maker: 0.0008, taker: 0.001, market_id: :any, group: 'vip-0')
|
||||
create(:trading_fee, maker: 0.001, taker: 0.0012, market_id: :btcusd, group: :any)
|
||||
end
|
||||
|
||||
it 'returns all trading fees' do
|
||||
api_get '/api/v2/public/trading_fees'
|
||||
|
||||
expect(response.status).to eq 200
|
||||
expect(JSON.parse(response.body).length).to eq TradingFee.count
|
||||
end
|
||||
|
||||
it 'pagination' do
|
||||
api_get '/api/v2/public/trading_fees', params: { limit: 1 }
|
||||
expect(JSON.parse(response.body).length).to eq 1
|
||||
end
|
||||
|
||||
it 'filters by market_id' do
|
||||
api_get '/api/v2/public/trading_fees', params: { market_id: 'btcusd' }
|
||||
|
||||
result = JSON.parse(response.body)
|
||||
expect(result.map { |r| r['market_id'] }).to all eq 'btcusd'
|
||||
expect(result.length).to eq TradingFee.where(market_id: 'btcusd').count
|
||||
end
|
||||
|
||||
it 'filters by group' do
|
||||
api_get '/api/v2/public/trading_fees', params: { group: 'vip-0' }
|
||||
|
||||
result = JSON.parse(response.body)
|
||||
expect(result.map { |r| r['group'] }).to all eq 'vip-0'
|
||||
expect(result.length).to eq TradingFee.where(group: 'vip-0').count
|
||||
end
|
||||
|
||||
it 'capitalized fee group' do
|
||||
api_get '/api/v2/public/trading_fees', params: { group: 'Vip-0' }
|
||||
|
||||
result = JSON.parse(response.body)
|
||||
expect(result.map { |r| r['group'] }).to all eq 'vip-0'
|
||||
expect(result.length).to eq TradingFee.where(group: 'vip-0').count
|
||||
end
|
||||
end
|
||||
end
|
||||
193
spec/api/v2/public/webhooks.rb
Normal file
193
spec/api/v2/public/webhooks.rb
Normal file
@@ -0,0 +1,193 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
describe API::V2::Public::Webhooks, type: :request do
|
||||
describe 'GET /webhooks/:event' do
|
||||
|
||||
let(:member) { create(:member) }
|
||||
|
||||
let(:transaction) do
|
||||
Peatio::Transaction.new(
|
||||
currency_id: :eth,
|
||||
hash: '0xa049b0202ba078caa723c6b59594247b0c9f33e24878950f8537cedff9ea20ac',
|
||||
amount: 0.5,
|
||||
to_address: '0x1ef338196bd0207ba4852ba7a6847eed59331b84',
|
||||
block_number: 16880960,
|
||||
txout: 0,
|
||||
status: :success
|
||||
)
|
||||
end
|
||||
|
||||
let(:invlaid_transaction) do
|
||||
Peatio::Transaction.new(
|
||||
currency_id: :eth,
|
||||
hash: '0xa049b0202ba078caa723c6b59594247b0c9f33e24878950f8537cedff9ea20ac',
|
||||
amount: 0.5,
|
||||
to_address: '0x1ef338196bd0207ba4852ba7a6847eed59331b85',
|
||||
block_number: 16880960,
|
||||
txout: 0
|
||||
)
|
||||
end
|
||||
|
||||
let!(:wallet) { create(:wallet, :eth_deposit, name: 'Bitgo Deposit',
|
||||
gateway: :bitgo, settings:
|
||||
{ uri: 'http://localhost',
|
||||
secret: 'changeme',
|
||||
wallet_id: '5e4d43680f39a6710435b74edba4e2c2',
|
||||
access_token: 'changeme',
|
||||
testnet: false }) }
|
||||
|
||||
let(:request_body) {
|
||||
{ 'event' => 'deposit',
|
||||
'id' => '5e539be5e6715b2006c7bfa6278aa3f4',
|
||||
'type' => 'transfer',
|
||||
'wallet' => '5e4d43680f39a6710435b74edba4e2c2',
|
||||
'url' => 'http://localhost.com',
|
||||
'hash' => '0xa049b0202ba078caa723c6b59594247b0c9f33e24878950f8537cedff9ea20ac',
|
||||
'coin' => 'eth',
|
||||
'transfer' => '5e4e824894d4902c060f20c28b161fa8',
|
||||
'state' => 'new',
|
||||
'simulation' => 'true',
|
||||
'retries' => '0',
|
||||
'webhook' => '5e5399ddda65833f06cd53429bcbca83',
|
||||
'updatedAt' => '2020-02-24T09:48:21.795Z',
|
||||
'version' => '2' }
|
||||
}
|
||||
|
||||
|
||||
context 'nonexistent wallet' do
|
||||
let(:request_body) {
|
||||
{ 'event' => 'deposit',
|
||||
'id' => '5e539be5e6715b2006c7bfa6278aa3f4',
|
||||
'type' => 'transfer',
|
||||
'wallet' => 'changeme',
|
||||
'url' => 'http://localhost.com',
|
||||
'hash' => '0xa049b0202ba078caa723c6b59594247b0c9f33e24878950f8537cedff9ea20ac',
|
||||
'coin' => 'eth',
|
||||
'transfer' => '5e4e824894d4902c060f20c28b161fa8',
|
||||
'state' => 'new',
|
||||
'simulation' => 'true',
|
||||
'retries' => '0',
|
||||
'webhook' => '5e5399ddda65833f06cd53429bcbca83',
|
||||
'updatedAt' => '2020-02-24T09:48:21.795Z',
|
||||
'version' => '2' }
|
||||
}
|
||||
|
||||
it 'doesnt create deposit and return 200' do
|
||||
expect do
|
||||
api_post '/api/v2/public/webhooks/deposit', params: request_body
|
||||
|
||||
expect(response.status).to eq 200
|
||||
end.not_to change { Deposit.count }
|
||||
end
|
||||
end
|
||||
|
||||
context 'valid webhook callback' do
|
||||
|
||||
before do
|
||||
member.get_account(:eth).payment_addresses.create(currency_id: :eth, address: '0x1ef338196bd0207ba4852ba7a6847eed59331b84')
|
||||
WalletService.any_instance.stubs(:trigger_webhook_event).with(request_body).returns({ transfers: [transaction] })
|
||||
end
|
||||
|
||||
it 'creates new deposit' do
|
||||
api_post '/api/v2/public/webhooks/deposit', params: request_body
|
||||
|
||||
expect(response.status).to eq 200
|
||||
expect(Deposit.last.txid).to eq('0xa049b0202ba078caa723c6b59594247b0c9f33e24878950f8537cedff9ea20ac')
|
||||
end
|
||||
|
||||
context 'process second time' do
|
||||
|
||||
it 'doesnt create deposit for same transfer' do
|
||||
api_post '/api/v2/public/webhooks/deposit', params: request_body
|
||||
expect do
|
||||
api_post '/api/v2/public/webhooks/deposit', params: request_body
|
||||
|
||||
expect(response.status).to eq 200
|
||||
expect(Deposit.last.txid).to eq('0xa049b0202ba078caa723c6b59594247b0c9f33e24878950f8537cedff9ea20ac')
|
||||
end.not_to change { Deposit.count }
|
||||
end
|
||||
end
|
||||
|
||||
context 'process undefined transfer' do
|
||||
|
||||
before do
|
||||
WalletService.any_instance.stubs(:trigger_webhook_event).with(request_body).returns({ transfers: [invlaid_transaction] })
|
||||
end
|
||||
|
||||
it 'doesnt create deposit and return 200' do
|
||||
expect do
|
||||
api_post '/api/v2/public/webhooks/deposit', params: request_body
|
||||
|
||||
expect(response.status).to eq 200
|
||||
end.not_to change { Deposit.count }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'adapter raises error invalid' do
|
||||
|
||||
before do
|
||||
member.get_account(:eth).payment_addresses.create(currency_id: :eth, address: '0x1ef338196bd0207ba4852ba7a6847eed59331b84')
|
||||
WalletService.any_instance.stubs(:trigger_webhook_event).with(request_body).raises(Peatio::Wallet::ClientError.new('something went wrong'))
|
||||
end
|
||||
|
||||
it 'returns error' do
|
||||
api_post '/api/v2/public/webhooks/deposit', params: request_body
|
||||
expect(response.status).to eq 422
|
||||
expect(response).to include_api_error('public.webhook.cannot_perfom_transfer')
|
||||
end
|
||||
end
|
||||
|
||||
context 'address confirmation event' do
|
||||
let(:request_body) {
|
||||
{ 'event' => 'deposit',
|
||||
'address' => '0xa049b0202ba078caa723c6b59594247b0c9f33e24878950f8537cedff9ea20ac',
|
||||
'type' => 'address_confirmation',
|
||||
'walletId' => '5e4e824894d4902c060f20c28b161fa8',
|
||||
'hash' => '0xa049b0202ba078caa723c6b59594247b0c9f33e24878950f8537cedff9ea20ac',
|
||||
}
|
||||
}
|
||||
|
||||
context 'valid webhook callback' do
|
||||
context 'update payment address' do
|
||||
before do
|
||||
member.get_account(:eth).payment_addresses.create(currency_id: :eth, address: nil, details: { address_id: 'address_id' })
|
||||
WalletService.any_instance.stubs(:trigger_webhook_event).with(request_body).returns({ address_id: 'address_id', currency_id: 'eth' })
|
||||
end
|
||||
|
||||
it 'should create address for member' do
|
||||
api_post '/api/v2/public/webhooks/deposit', params: request_body
|
||||
expect(response.status).to eq 200
|
||||
expect(member.get_account(:eth).payment_addresses[0].address).to eq request_body['address']
|
||||
end
|
||||
end
|
||||
|
||||
context 'skip payment address' do
|
||||
before do
|
||||
member.get_account(:eth).payment_addresses.create(currency_id: :eth, address: request_body['address'], details: { address_id: 'address_id' })
|
||||
WalletService.any_instance.stubs(:trigger_webhook_event).with(request_body).returns({ address_id: 'address_id', currency_id: 'eth' })
|
||||
end
|
||||
|
||||
it 'should not update address if address already exists' do
|
||||
api_post '/api/v2/public/webhooks/deposit', params: request_body
|
||||
expect(response.status).to eq 200
|
||||
expect(member.get_account(:eth).payment_addresses[0].created_at).to eq member.get_account(:eth).payment_addresses[0].updated_at
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'adapter raises error invalid' do
|
||||
before do
|
||||
member.get_account(:eth).payment_addresses.create(currency_id: :eth, address: nil, details: { address_id: 'address_id' })
|
||||
WalletService.any_instance.stubs(:trigger_webhook_event).with(request_body).raises(Peatio::Wallet::ClientError.new('something went wrong'))
|
||||
end
|
||||
|
||||
it 'returns error' do
|
||||
api_post '/api/v2/public/webhooks/deposit', params: request_body
|
||||
expect(response.status).to eq 422
|
||||
expect(response).to include_api_error('public.webhook.cannot_perfom_address_confirmation')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user