Initial commit
This commit is contained in:
155
app/api/v2/management/withdraws.rb
Normal file
155
app/api/v2/management/withdraws.rb
Normal file
@@ -0,0 +1,155 @@
|
||||
# encoding: UTF-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
module API
|
||||
module V2
|
||||
module Management
|
||||
class Withdraws < Grape::API
|
||||
|
||||
helpers do
|
||||
def perform_action(withdraw, action)
|
||||
withdraw.with_lock do
|
||||
case action
|
||||
when 'process'
|
||||
withdraw.accept!
|
||||
# Process fiat withdraw immediately. Crypto withdraws will be processed by workers.
|
||||
if withdraw.currency.fiat?
|
||||
withdraw.process!
|
||||
withdraw.dispatch!
|
||||
withdraw.success!
|
||||
end
|
||||
when 'cancel'
|
||||
withdraw.cancel!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Returns withdraws as paginated collection.' do
|
||||
@settings[:scope] = :read_withdraws
|
||||
success API::V2::Management::Entities::Withdraw
|
||||
end
|
||||
params do
|
||||
optional :uid, type: String, desc: 'The shared user ID.'
|
||||
optional :currency, type: String, values: -> { Currency.codes(bothcase: true) }, desc: 'The currency code.'
|
||||
optional :page, type: Integer, default: 1, integer_gt_zero: true, desc: 'The page number (defaults to 1).'
|
||||
optional :limit, type: Integer, default: 100, range: 1..1000, desc: 'The number of objects per page (defaults to 100, maximum is 1000).'
|
||||
optional :state, type: String, values: -> { Withdraw::STATES.map(&:to_s) }, desc: 'The state to filter by.'
|
||||
end
|
||||
post '/withdraws' do
|
||||
currency = Currency.find(params[:currency]) if params[:currency].present?
|
||||
member = Member.find_by!(uid: params[:uid]) if params[:uid].present?
|
||||
|
||||
Withdraw
|
||||
.order(id: :desc)
|
||||
.includes(:member, :currency)
|
||||
.tap { |q| q.where!(currency: currency) if currency }
|
||||
.tap { |q| q.where!(member: member) if member }
|
||||
.tap { |q| q.where!(aasm_state: params[:state]) if params[:state] }
|
||||
.page(params[:page])
|
||||
.per(params[:limit])
|
||||
.tap { |q| present q, with: API::V2::Management::Entities::Withdraw }
|
||||
status 200
|
||||
end
|
||||
|
||||
desc 'Returns withdraw by ID.' do
|
||||
@settings[:scope] = :read_withdraws
|
||||
success API::V2::Management::Entities::Withdraw
|
||||
end
|
||||
params do
|
||||
requires :tid, type: String, desc: 'The shared transaction ID.'
|
||||
end
|
||||
post '/withdraws/get' do
|
||||
present Withdraw.find_by!(params.slice(:tid)), with: API::V2::Management::Entities::Withdraw
|
||||
end
|
||||
|
||||
desc 'Creates new withdraw.' do
|
||||
@settings[:scope] = :write_withdraws
|
||||
detail 'Creates new withdraw. The behaviours for fiat and crypto withdraws are different. ' \
|
||||
'Fiat: money are immediately locked, withdraw state is set to «submitted», system workers ' \
|
||||
'will validate withdraw later against suspected activity, and assign state to «rejected» or «accepted». ' \
|
||||
'The processing will not begin automatically. The processing may be initiated manually from admin panel or by PUT /management_api/v1/withdraws/action. ' \
|
||||
'Coin: money are immediately locked, withdraw state is set to «submitted», system workers ' \
|
||||
'will validate withdraw later against suspected activity, validate withdraw address and ' \
|
||||
'set state to «rejected» or «accepted». ' \
|
||||
'Then in case state is «accepted» withdraw workers will perform interactions with blockchain. ' \
|
||||
'The withdraw receives new state «processing». Then withdraw receives state either «confirming» or «failed».' \
|
||||
'Then in case state is «confirming» withdraw confirmations workers will perform interactions with blockchain.' \
|
||||
'Withdraw receives state «succeed» when it receives minimum necessary amount of confirmations.'
|
||||
success API::V2::Management::Entities::Withdraw
|
||||
end
|
||||
params do
|
||||
requires :uid, type: String, desc: 'The shared user ID.'
|
||||
optional :tid, type: String, desc: 'The shared transaction ID. Must not exceed 64 characters. Peatio will generate one automatically unless supplied.'
|
||||
optional :rid, type: String, desc: 'The beneficiary ID or wallet address on the Blockchain.'
|
||||
optional :beneficiary_id, type: String, desc: 'ID of Active Beneficiary belonging to user.'
|
||||
requires :currency, type: String, values: -> { Currency.codes(bothcase: true) }, desc: 'The currency code.'
|
||||
requires :amount, type: BigDecimal, desc: 'The amount to withdraw.'
|
||||
optional :note, type: String, desc: 'The note for withdraw.'
|
||||
optional :action, type: String, values: %w[process], desc: 'The action to perform.'
|
||||
optional :transfer_type, type: String,
|
||||
values: { value: -> { Withdraw::TRANSFER_TYPES.keys }, message: 'account.withdraw.transfer_type_not_in_list' },
|
||||
desc: -> { API::V2::Admin::Entities::Withdraw.documentation[:transfer_type][:desc] }
|
||||
|
||||
exactly_one_of :rid, :beneficiary_id
|
||||
end
|
||||
post '/withdraws/new' do
|
||||
member = Member.find_by(uid: params[:uid])
|
||||
|
||||
currency = Currency.find(params[:currency])
|
||||
unless currency.withdrawal_enabled?
|
||||
error!({ errors: ['management.currency.withdrawal_disabled'] }, 422)
|
||||
end
|
||||
|
||||
beneficiary = Beneficiary.find_by(id: params[:beneficiary_id]) if params[:beneficiary_id].present?
|
||||
if params[:rid].blank? && beneficiary.blank?
|
||||
error!({ errors: ['management.beneficiary.doesnt_exist'] }, 422)
|
||||
elsif params[:rid].blank? && !beneficiary&.active?
|
||||
error!({ errors: ['management.beneficiary.invalid_state_for_withdrawal'] }, 422)
|
||||
end
|
||||
|
||||
if params[:tid].present?
|
||||
error!({ errors: ['TID already exist'] }, 422) if Withdraw.where(tid: params[:tid]).present?
|
||||
end
|
||||
|
||||
declared_params = declared(params, include_missing: false).slice(:tid, :rid, :note, :transfer_type).merge(
|
||||
sum: params[:amount],
|
||||
member: member,
|
||||
currency: currency,
|
||||
tid: params[:tid]
|
||||
)
|
||||
|
||||
declared_params.merge!(beneficiary: beneficiary) if params[:beneficiary_id].present?
|
||||
withdraw = "withdraws/#{currency.type}".camelize.constantize.new(declared_params)
|
||||
|
||||
withdraw.save!
|
||||
withdraw.with_lock { withdraw.accept! }
|
||||
perform_action(withdraw, params[:action]) if params[:action]
|
||||
present withdraw, with: API::V2::Management::Entities::Withdraw
|
||||
rescue ::Account::AccountError => e
|
||||
report_api_error(e, request)
|
||||
error!({ errors: [e.to_s] }, 422)
|
||||
rescue => e
|
||||
report_exception(e)
|
||||
error!({ errors: ['Failed to create withdraw!'] }, 422)
|
||||
end
|
||||
|
||||
desc 'Performs action on withdraw.' do
|
||||
@settings[:scope] = :write_withdraws
|
||||
detail '«process» – system will lock the money, check for suspected activity, validate recipient address, and initiate the processing of the withdraw. ' \
|
||||
'«cancel» – system will mark withdraw as «canceled», and unlock the money.'
|
||||
success API::V2::Management::Entities::Withdraw
|
||||
end
|
||||
params do
|
||||
requires :tid, type: String, desc: 'The shared transaction ID.'
|
||||
requires :action, type: String, values: %w[process cancel], desc: 'The action to perform.'
|
||||
end
|
||||
put '/withdraws/action' do
|
||||
record = Withdraw.find_by!(params.slice(:tid))
|
||||
perform_action(record, params[:action])
|
||||
present record, with: API::V2::Management::Entities::Withdraw
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user