# encoding: UTF-8 # frozen_string_literal: true require_relative '../validations' module API module V2 module Account class Deposits < Grape::API before { deposits_must_be_permitted! } desc 'Get your deposits history.', is_array: true, success: API::V2::Entities::Deposit params do optional :currency, type: String, values: { value: -> { Currency.visible.codes(bothcase: true) }, message: 'account.currency.doesnt_exist' }, desc: 'Currency code' optional :state, values: { value: ->(v) { (Array.wrap(v) - ::Deposit.aasm.states.map(&:name).map(&:to_s)).blank? }, message: 'account.deposit.invalid_state' }, desc: 'Filter deposits by states.' optional :txid, type: String, allow_blank: false, desc: 'Deposit transaction id.' optional :time_from, allow_blank: { value: false, message: 'account.deposit.empty_time_from' }, type: { value: Integer, message: 'account.deposit.non_integer_time_from' }, desc: 'An integer represents the seconds elapsed since Unix epoch.' optional :time_to, type: { value: Integer, message: 'account.deposit.non_integer_time_to' }, allow_blank: { value: false, message: 'account.deposit.empty_time_to' }, desc: 'An integer represents the seconds elapsed since Unix epoch.' optional :limit, type: { value: Integer, message: 'account.deposit.non_integer_limit' }, values: { value: 1..100, message: 'account.deposit.invalid_limit' }, default: 100, desc: "Number of deposits per page (defaults to 100, maximum is 100)." optional :page, type: { value: Integer, message: 'account.deposit.non_integer_page' }, values: { value: -> (p){ p.try(:positive?) }, message: 'account.deposit.non_positive_page'}, default: 1, desc: 'Page number (defaults to 1).' end get "/deposits" do user_authorize! :read, ::Deposit currency = Currency.find(params[:currency]) if params[:currency].present? current_user.deposits.order(id: :desc) .tap { |q| q.where!(currency: currency) if currency } .tap { |q| q.where!(txid: params[:txid]) if params[:txid] } .tap { |q| q.where!(aasm_state: params[:state]) if params[:state] } .tap { |q| q.where!('updated_at >= ?', Time.at(params[:time_from])) if params[:time_from].present? } .tap { |q| q.where!('updated_at <= ?', Time.at(params[:time_to])) if params[:time_to].present? } .tap { |q| present paginate(q), with: API::V2::Entities::Deposit } end desc 'Get details of specific deposit.' do success API::V2::Entities::Deposit end params do requires :txid, type: String, allow_blank: false, desc: "Deposit transaction id" end get "/deposits/:txid" do user_authorize! :read, ::Deposit deposit = current_user.deposits.find_by!(txid: params[:txid]) present deposit, with: API::V2::Entities::Deposit end desc 'Returns deposit address for account you want to deposit to by currency. ' \ 'The address may be blank because address generation process is still in progress. ' \ 'If this case you should try again later.', success: API::V2::Entities::Deposit params do requires :currency, type: String, values: { value: -> { Currency.coins.visible.codes(bothcase: true) }, message: 'account.currency.doesnt_exist'}, desc: 'The account you want to deposit to.' given :currency do optional :address_format, type: String, values: { value: -> { %w[legacy cash] }, message: 'account.deposit_address.invalid_address_format' }, validate_currency_address_format: { value: true, prefix: 'account.deposit_address' }, desc: 'Address format legacy/cash' end end get '/deposit_address/:currency', requirements: { currency: /[\w\.\-]+/ } do user_authorize! :read, ::PaymentAddress currency = Currency.find(params[:currency]) unless currency.deposit_enabled? error!({ errors: ['account.currency.deposit_disabled'] }, 422) end wallet = Wallet.deposit_wallet(currency.id) unless wallet.present? error!({ errors: ['account.wallet.not_found'] }, 422) end payment_address = current_user.payment_address(wallet.id) present payment_address, with: API::V2::Entities::PaymentAddress, address_format: params[:address_format] end ############ desc 'Create fiat deposits' params do requires :amount, type: { value: BigDecimal, message: 'deposit.fiat.non_decimal_amount' }, values: { value: ->(v) { v.try(:positive?) }, message: 'deposit.fiat.non_positive_amount' }, desc: 'The amount to deposit fiat.' requires :callback_url, regexp: { value: URI::regexp, message: 'callback_url.invalid' }, desc: -> { 'callback_url payment url' } requires :currency, type: String, default: 'irt', desc: -> { 'currency' } requires :card, type: String, desc: 'card bank number' optional :factorNumber, type: String, allow_blank: true, desc: 'factor number' optional :description, type: String, allow_blank: true, desc: 'description' end post '/deposits/fiat' do user_authorize! :create, ::Deposit error!({ errors: ['account.deposit.use_valid_card'] }, 403) if current_user.cards.exclude?(params[:card].to_s) deposit_data = { member: current_user, currency: Currency.find(params['currency']), aasm_state: 'canceled', address: params['card'], amount: params['amount'], transfer_type: :fiat } deposit = ::Deposits::Fiat.new(deposit_data) error!({ errors: deposit.errors.full_messages }, 422) if deposit.errors.any? data = { amount: (params[:amount] * 10), callback_url: params[:callback_url], description: params[:description], valid_card_number: params[:card] } response = VandarService::generate_token(data) if response.dig('status').to_i.positive? deposit.tap { |d| d.tid = response.dig('token') }.save! present(response: response.dig('token')) else present(response: response) status 422 end end desc 'Confirm fiat deposits' params do requires :token, type: String, allow_blank: false, desc: 'payment token' end post '/deposits/confirm' do deposit = ::Deposits::Fiat.find_by(tid: params[:token]) error!({ errors: ['corresponding.deposit.record.not.found'] }, 403) unless deposit.present? # because vandar just response one if deposit.txid.present? db_response = { status: 1, amount: deposit.amount, wage: deposit.fee, cardNumber: deposit.address, transId: deposit.txid } return present(response: db_response) end # first step: check everything is ok response = ::VandarService.transaction(params[:token]) if response.dig('status').to_i.positive? && response.dig('trackingCode').present? if response['cardNumber'].last(4).to_i == deposit.address.last(4).to_i response = VandarService.verify(params[:token]) if response.dig('status').to_i.positive? deposit.update(txid: response['transId'], fee: response['wage'].to_f / 10, aasm_state: 'submitted') deposit.charge! end end # TODO we should see the response and check it for rial and toman confirmation present(response: response) else present(response: response) status 422 end # second step: verify payment end end end end end