Initial commit

This commit is contained in:
Yaser
2026-08-13 19:50:53 +03:30
commit 38084458fe
879 changed files with 95198 additions and 0 deletions

View File

@@ -0,0 +1,16 @@
# encoding: UTF-8
# frozen_string_literal: true
module API
module V2
module Management
module Entities
class Balance < Base
expose(:uid, documentation: { type: String, desc: 'The shared user ID.' }) { |w| w.member.uid }
expose(:balance, documentation: { type: String, desc: 'The account balance.' }, format_with: :decimal)
expose(:locked, documentation: { type: String, desc: 'The locked account balance.' }, format_with: :decimal)
end
end
end
end
end

View File

@@ -0,0 +1,15 @@
# encoding: UTF-8
# frozen_string_literal: true
module API
module V2
module Management
module Entities
class Base < Grape::Entity
format_with(:iso8601) { |t| t.to_time.in_time_zone(::Rails.configuration.time_zone).iso8601 if t }
format_with(:decimal) { |d| d.to_s('F') if d }
end
end
end
end
end

View File

@@ -0,0 +1,20 @@
# frozen_string_literal: true
module API
module V2
module Management
module Entities
class Beneficiary < API::V2::Entities::Beneficiary
expose(
:data,
documentation: {
desc: 'Bank Account details for fiat Beneficiary in JSON format.'\
'For crypto it\'s blockchain address.',
type: JSON
}
)
end
end
end
end
end

View File

@@ -0,0 +1,80 @@
# encoding: UTF-8
# frozen_string_literal: true
module API
module V2
module Management
module Entities
class Currency < ::API::V2::Entities::Currency
expose(
:code,
documentation: {
desc: 'Unique currency code.',
type: String
}
)
expose(
:min_collection_amount,
documentation: {
desc: 'Minimal deposit amount that will be collected',
example: -> { ::Currency.visible.first.min_collection_amount }
}
)
expose(
:visible,
documentation: {
type: String,
desc: 'Currency display possibility status (true/false).'
}
)
expose(
:subunits,
documentation: {
type: Integer,
desc: 'Fraction of the basic monetary unit.'
}
) { |currency| currency.subunits }
expose(
:options,
documentation: {
type: JSON,
desc: 'Currency options.'
},
if: -> (currency){ currency.coin? }
)
expose(
:position,
documentation: {
type: Integer,
desc: 'Currency position.'
}
)
expose(
:created_at,
format_with: :iso8601,
documentation: {
type: String,
desc: 'Currency created time in iso8601 format.'
}
)
expose(
:updated_at,
format_with: :iso8601,
documentation: {
type: String,
desc: 'Currency updated time in iso8601 format.'
}
)
end
end
end
end
end

View File

@@ -0,0 +1,30 @@
# encoding: UTF-8
# frozen_string_literal: true
module API
module V2
module Management
module Entities
class Deposit < Base
expose :tid, documentation: { type: Integer, desc: 'The shared transaction ID.' }
expose :currency_id, as: :currency, documentation: { type: String, desc: 'The currency code.' }
expose(:uid, documentation: { type: String, desc: 'The shared user ID.' }) { |w| w.member.uid }
expose(:type, documentation: { type: String, desc: 'The deposit type (fiat or coin).' }) { |d| d.class.name.demodulize.underscore }
expose :amount, documentation: { type: String, desc: 'The deposit amount.' }, format_with: :decimal
states = [
'«submitted» initial state.',
'«canceled» deposit has been canceled by outer service.',
'«rejected» deposit has been rejected by outer service..',
'«accepted» deposit has been accepted by outer service, money are loaded.'
]
expose :aasm_state, as: :state, documentation: { type: String, desc: 'The deposit state. ' + states.join(' ') }
expose :created_at, format_with: :iso8601, documentation: { type: String, desc: 'The datetime when deposit was created.' }
expose :completed_at, format_with: :iso8601, documentation: { type: String, desc: 'The datetime when deposit was completed.' }
expose :txid, as: :blockchain_txid, if: -> (d, _) { d.currency.coin? }, documentation: { type: String, desc: 'The transaction ID on the Blockchain (coin only).' }
expose :confirmations, as: :blockchain_confirmations, if: -> (d, _) { d.currency.coin? }, documentation: { type: String, desc: 'The number of transaction confirmations on the Blockchain (coin only).' }
expose :transfer_type, documentation: { type: String, desc: 'deposit transfer_type.' }
end
end
end
end
end

View File

@@ -0,0 +1,51 @@
# frozen_string_literal: true
module API
module V2
module Management
module Entities
class Engine < API::V2::Entities::Base
expose(
:id,
documentation: {
type: Integer,
desc: 'Engine uniq id'
}
)
expose(
:name,
documentation: {
type: String,
desc: 'Engine name'
}
)
expose(
:driver,
documentation: {
type: String,
desc: 'Engine driver'
}
)
expose(
:uid,
documentation: {
type: String,
desc: 'Owner of a engine'
}
)
expose(
:state,
documentation: {
type: String,
desc: 'Engine state'
}
)
end
end
end
end
end

View File

@@ -0,0 +1,38 @@
# encoding: UTF-8
# frozen_string_literal: true
module API
module V2
module Management
module Entities
class Market < ::API::V2::Entities::Market
expose(
:position,
documentation: {
type: Integer,
desc: 'Market position.'
}
)
expose(
:created_at,
format_with: :iso8601,
documentation: {
type: String,
desc: 'Market created time in iso8601 format.'
}
)
expose(
:updated_at,
format_with: :iso8601,
documentation: {
type: String,
desc: 'Market updated time in iso8601 format.'
}
)
end
end
end
end
end

View File

@@ -0,0 +1,66 @@
module API
module V2
module Management
module Entities
class Member < Base
expose(
:uid,
documentation: {
type: String,
desc: 'The shared user ID.'
}
)
expose(
:email,
documentation: {
type: String,
desc: 'User email.'
}
)
expose(
:level,
documentation: {
type: Integer,
desc: 'User level.'
}
)
expose(
:role,
documentation: {
type: String,
desc: 'User role.'
}
)
expose(
:group,
documentation: {
type: String,
desc: 'User group (vip-0, vip-1, etc).'
}
)
expose(
:state,
documentation: {
type: String,
desc: 'User state (active/pending/banned).'
}
)
expose(
:created_at,
format_with: :iso8601,
documentation: {
type: String,
desc: 'User create time in iso8601 format.'
}
)
end
end
end
end
end

View File

@@ -0,0 +1,53 @@
# encoding: UTF-8
# frozen_string_literal: true
module API
module V2
module Management
module Entities
class Operation < Base
expose :code,
documentation: {
type: String,
desc: 'The Account code which this operation related to.'
}
expose :currency_id,
as: :currency,
documentation: {
type: String,
desc: 'Operation currency ID.'
}
expose :credit,
if: ->(operation) { !operation.credit.zero? },
documentation: {
type: String,
desc: 'Operation credit amount.'
}
expose :debit,
if: ->(operation) { !operation.debit.zero? },
documentation: {
type: String,
desc: 'Operation debit amount.'
}
expose(:uid,
if: ->(operation) { operation.try(:member).try(:uid) },
documentation: {
type: String,
desc: 'The shared user ID.'
}) { |operation| operation.try(:member).try(:uid) }
expose(:reference_type,
documentation: {
type: String,
desc: 'The type of operations.'
}) { |operation| operation.reference_type.downcase if operation.reference_type.present? }
expose :created_at,
format_with: :iso8601,
documentation: {
type: String,
desc: 'The datetime when operation was created.'
}
end
end
end
end
end

View File

@@ -0,0 +1,176 @@
# encoding: UTF-8
# frozen_string_literal: true
module API
module V2
module Management
module Entities
class Order < Base
expose(
:id,
documentation:{
type: Integer,
desc: "Unique order id."
}
)
expose(
:member_id,
documentation:{
type: Integer,
desc: "Member id."
}
)
expose(
:uuid,
documentation:{
type: String,
desc: "Unique order UUID."
}
)
expose(
:side,
documentation: {
type: String,
desc: "Either 'sell' or 'buy'."
}
)
expose(
:ord_type,
documentation: {
type: String,
desc: "Type of order, either 'limit' or 'market'."
}
)
expose(
:price,
documentation: {
type: BigDecimal,
desc: "Price for each unit. e.g."\
"If you want to sell/buy 1 btc at 3000 usd, the price is '3000.0'"
}
)
expose(
:avg_price,
documentation: {
type: BigDecimal,
desc: "Average execution price, average of price in trades."
}
)
expose(
:state,
documentation: {
type: String,
desc: "One of 'wait', 'done', or 'cancel'."\
"An order in 'wait' is an active order, waiting fulfillment;"\
"a 'done' order is an order fulfilled;"\
"'cancel' means the order has been canceled."
}
)
expose(
:market_id,
as: :market,
documentation: {
type: String,
desc: "The market in which the order is placed, e.g. 'btcusd'."\
"All available markets can be found at /api/v2/markets."
}
)
expose(
:created_at,
format_with: :iso8601,
documentation: {
type: String,
desc: "Order create time in iso8601 format."
}
)
expose(
:updated_at,
format_with: :iso8601,
documentation: {
type: String,
desc: "Order updated time in iso8601 format."
}
)
expose(
:origin_volume,
documentation: {
type: BigDecimal,
desc: "The amount user want to sell/buy."\
"An order could be partially executed,"\
"e.g. an order sell 5 btc can be matched with a buy 3 btc order,"\
"left 2 btc to be sold; in this case the order's volume would be '5.0',"\
"its remaining_volume would be '2.0', its executed volume is '3.0'."
}
)
expose(
:volume,
as: :remaining_volume,
documentation: {
type: BigDecimal,
desc: "The remaining volume, see 'volume'."
}
)
expose(
:executed_volume,
documentation: {
type: BigDecimal,
desc: "The executed volume, see 'volume'."
}
) do |order, _options|
order.origin_volume - order.volume
end
expose(
:maker_fee,
documentation: {
type: BigDecimal,
desc: "Fee for maker."
}
)
expose(
:taker_fee,
documentation: {
type: BigDecimal,
desc: "Fee for taker."
}
)
expose(
:trades_count,
documentation: {
type: Integer,
desc: "Count of trades."
}
)
expose(
:trades,
documentation: {
type: 'API::V2::Entities::Trade',
is_array: true,
desc: "Trades wiht this order."
},
if: { type: :full }
) do |order, _options|
API::V2::Entities::Trade.represent order.trades, side: order.side
end
end
end
end
end
end

View File

@@ -0,0 +1,27 @@
# frozen_string_literal: true
module API
module V2
module Management
module Entities
class PaymentAddress < ::API::V2::Entities::PaymentAddress
expose(
:uid,
documentation: {
type: String,
desc: 'The shared user ID.'
}
) { |w| w.member.uid }
expose(
:remote,
documentation: {
type: String,
desc: 'Payment address remote creation (true/false).'
}
)
end
end
end
end
end

View File

@@ -0,0 +1,130 @@
# encoding: UTF-8
# frozen_string_literal: true
module API
module V2
module Management
module Entities
class Trade < Base
expose(
:id,
documentation: {
type: String,
desc: 'Trade ID.'
}
)
expose(
:price,
documentation: {
type: BigDecimal,
desc: 'Trade price.'
}
)
expose(
:amount,
documentation: {
type: BigDecimal,
desc: 'Trade amount.'
}
)
expose(
:total,
documentation: {
type: BigDecimal,
desc: 'Trade total.'
}
)
expose(
:market_id,
as: :market,
documentation: {
type: String,
desc: 'Trade market id.'
}
)
expose(
:created_at,
format_with: :iso8601,
documentation: {
type: String,
desc: 'Trade create time in iso8601 format.'
}
)
expose(
:maker_order_id,
documentation: {
type: String,
desc: 'Trade maker order id.'
}
)
expose(
:taker_order_id,
documentation: {
type: String,
desc: 'Trade taker order id.'
}
)
expose(
:maker_member_uid,
documentation: {
type: String,
desc: 'Trade ask member uid.'
}
) do |trade|
trade.maker.uid
end
expose(
:taker_member_uid,
documentation: {
type: String,
desc: 'Trade bid member uid.'
}
) do |trade|
trade.taker.uid
end
expose(
:taker_type,
documentation: {
type: String,
desc: 'Trade maker order type (sell or buy).'
}
) do |trade, _options|
trade.taker_order.side
end
expose(
:side,
if: ->(trade, options) { options[:side] || options[:current_user] },
documentation: {
type: String,
desc: 'Trade side.'
}
) do |trade, options|
options[:side] || trade.order_for_member(options[:current_user]).side
end
expose(
:order_id,
documentation: {
type: Integer,
desc: 'Order id.'
},
if: ->(_, options) { options[:current_user] }
) do |trade, options|
trade.order_for_member(options[:current_user]).id
end
end
end
end
end
end

View File

@@ -0,0 +1,40 @@
# encoding: UTF-8
# frozen_string_literal: true
module API
module V2
module Management
module Entities
class Transfer < Base
expose :key,
documentation: {
type: String,
desc: 'Unique Transfer Key.'
}
expose :category,
documentation: {
type: String,
desc: 'Transfer Category.'
}
expose :description,
documentation: {
type: String,
desc: 'Transfer Description'
}
# Expose assets, expenses, liabilities, revenues if present.
::Operations::Account::TYPES.map(&:pluralize).each do |op_t|
expose op_t,
using: Operation,
if: ->(transfer) { transfer.public_send(op_t).present? },
documentation: {
desc: "Transfer #{op_t}"
}
end
end
end
end
end
end

View File

@@ -0,0 +1,36 @@
# encoding: UTF-8
# frozen_string_literal: true
module API
module V2
module Management
module Entities
class Withdraw < Base
expose :tid, documentation: { type: Integer, desc: 'The shared transaction ID.' }
expose(:uid, documentation: { type: String, desc: 'The shared user ID.' }) { |w| w.member.uid }
expose :currency_id, as: :currency, documentation: { type: String, desc: 'The currency code.' }
expose :note, documentation: { type: String, desc: 'The note for withdraw.' }
expose(:type, documentation: { type: String, desc: 'The withdraw type (fiat or coin).' }) { |w| w.class.name.demodulize.underscore }
expose :amount, documentation: { type: String, desc: 'The withdraw amount excluding fee.' }, format_with: :decimal
expose :fee, documentation: { type: String, desc: 'The exchange fee.' }, format_with: :decimal
expose :rid, documentation: { type: String, desc: 'The beneficiary ID or wallet address on the Blockchain.' }
states = [
'«prepared» initial state, money are not locked.',
'«submitted» withdraw has been allowed by outer service for further validation, money are locked.',
'«canceled» withdraw has been canceled by outer service, money are unlocked.',
'«accepted» system has validated withdraw and queued it for processing by worker, money are locked.',
'«rejected» system has validated withdraw and found errors, money are unlocked.',
'«processing» worker is processing withdraw as the current moment, money are locked.',
'«skipped» worker skipped withdrawal in case of insufficient balance of hot wallet or it absence.',
'«succeed» worker has successfully processed withdraw, money are subtracted from the account.',
'«failed» worker has encountered an unhandled error while processing withdraw, money are unlocked.'
]
expose :aasm_state, as: :state, documentation: { type: String, desc: 'The withdraw state. ' + states.join(' ') }
expose :created_at, format_with: :iso8601, documentation: { type: String, desc: 'The datetime when withdraw was created.' }
expose :txid, as: :blockchain_txid, documentation: { type: String, desc: 'The transaction ID on the Blockchain (coin only).' }, if: -> (w, _) { w.currency.coin? }
expose :transfer_type, documentation: { type: String, desc: 'withdraw transfer_type.' }
end
end
end
end
end