Files
Dena/app/api/v2/account/transactions.rb
2026-08-13 19:50:53 +03:30

110 lines
5.3 KiB
Ruby

# encoding: UTF-8
# frozen_string_literal: true
require_relative '../validations'
module API
module V2
module Account
class Transactions < Grape::API
before { deposits_must_be_permitted! }
before { withdraws_must_be_permitted! }
desc 'Get your transactions history.',
is_array: true
params do
optional :currency,
type: String,
values: { value: -> { Currency.visible.codes(bothcase: true) }, message: 'account.transactions.currency_doesnt_exist' },
desc: 'Currency code'
optional :order_by,
type: String,
values: { value: %w(asc desc), message: 'account.transactions.order_by_invalid' },
default: 'desc',
desc: 'Sorting order'
optional :time_from,
allow_blank: { value: false, message: 'account.transactions.empty_time_from' },
type: { value: Integer, message: 'account.transactions.non_integer_time_from' },
desc: 'An integer represents the seconds elapsed since Unix epoch.'
optional :time_to,
type: { value: Integer, message: 'account.transactions.non_integer_time_to' },
allow_blank: { value: false, message: 'account.transactions.empty_time_to' },
desc: 'An integer represents the seconds elapsed since Unix epoch.'
optional :deposit_state,
values: { value: ->(v) { (Array.wrap(v) - ::Deposit.aasm.states.map(&:name).map(&:to_s)).blank? }, message: 'account.transactions.invalid_deposit_state' },
desc: 'Filter deposits by states.',
default: []
optional :withdraw_state,
values: { value: ->(v) { (Array.wrap(v) - Withdraw::STATES.map(&:to_s)).blank? }, message: 'account.transactions.invalid_withdraw_state' },
desc: 'Filter withdraws by states.',
default: []
optional :txid,
type: String,
allow_blank: false,
desc: 'Transaction id.'
optional :limit,
type: { value: Integer, message: 'account.transactions.non_integer_limit' },
values: { value: 1..1000, message: 'account.transactions.invalid_limit' },
default: 100,
desc: 'Limit the number of returned transactions. Default to 100.'
optional :page,
type: { value: Integer, message: 'account.transactions.non_integer_page' },
values: { value: -> (p){ p.try(:positive?) }, message: 'account.transactions.non_positive_page'},
allow_blank: false,
default: 1,
desc: 'Specify the page of paginated results.'
end
get "/transactions" do
user_authorize! :read, ::Withdraw
user_authorize! :read, ::Deposit
deposit_state = params[:deposit_state]&.split(/\W+/)&.join(',')
withdraw_state = params[:withdraw_state]&.split(/\W+/)&.join(',')
deposit_sql = "(SELECT d.id, currency_id, amount, fee, address, aasm_state, NULL AS note, txid, d.created_at, d.updated_at, d.type, b.height - block_number AS confirmations FROM deposits d " \
"INNER JOIN currencies c ON c.id=d.currency_id LEFT JOIN blockchains b ON b.key=c.blockchain_key WHERE member_id=#{current_user.id} "
if params[:deposit_state].present?
deposit_sql += if Rails.configuration.database_adapter.downcase == 'PostgreSQL'.downcase
"and aasm_state = any(string_to_array('#{deposit_state}',','))"
else
"and FIND_IN_SET(aasm_state, '#{deposit_state}')"
end
end
withdraw_sql = "SELECT w.id, currency_id, amount, fee, rid, aasm_state, note, txid, w.created_at, w.updated_at, w.type, b.height - block_number AS confirmations FROM withdraws w " \
"INNER JOIN currencies c ON c.id=w.currency_id LEFT JOIN blockchains b ON b.key=c.blockchain_key WHERE member_id=#{current_user.id} "
if params[:withdraw_state].present?
withdraw_sql += if Rails.configuration.database_adapter.downcase == 'PostgreSQL'.downcase
"and aasm_state = any(string_to_array('#{withdraw_state}',','))"
else
"and FIND_IN_SET(aasm_state, '#{withdraw_state}')"
end
end
sql = "SELECT * FROM " + deposit_sql + "UNION " + withdraw_sql + ") AS transactions ORDER BY updated_at #{params[:order_by].upcase}"
result = ActiveRecord::Base.connection.exec_query(sql).to_hash
result.select! { |t| t['currency_id'] == params[:currency].downcase } if params[:currency].present?
result.select! { |t| t['txid'] == params[:txid] } if params[:txid].present?
result.select! { |t| t['updated_at'] >= Time.at(params[:time_from]) } if params[:time_from].present?
result.select! { |t| t['updated_at'] <= Time.at(params[:time_to]) } if params[:time_to].present?
present paginate(result.each(&:symbolize_keys!)), with: API::V2::Entities::Transactions
end
end
end
end
end