Initial commit
This commit is contained in:
168
app/models/wallet.rb
Normal file
168
app/models/wallet.rb
Normal file
@@ -0,0 +1,168 @@
|
||||
# encoding: UTF-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Wallet < ApplicationRecord
|
||||
extend Enumerize
|
||||
|
||||
serialize :balance, JSON unless Rails.configuration.database_support_json
|
||||
|
||||
include Vault::EncryptedModel
|
||||
|
||||
vault_lazy_decrypt!
|
||||
|
||||
# We use this attribute values rules for wallet kinds:
|
||||
# 1** - for deposit wallets.
|
||||
# 2** - for fee wallets.
|
||||
# 3** - for withdraw wallets (sorted by security hot < warm < cold).
|
||||
ENUMERIZED_KINDS = { deposit: 100, fee: 200, hot: 310, warm: 320, cold: 330 }.freeze
|
||||
enumerize :kind, in: ENUMERIZED_KINDS, scope: true
|
||||
|
||||
SETTING_ATTRIBUTES = %i[ uri secret ].freeze
|
||||
|
||||
SETTING_ATTRIBUTES.each do |attribute|
|
||||
define_method attribute do
|
||||
self.settings[attribute.to_s]
|
||||
end
|
||||
|
||||
define_method "#{attribute}=".to_sym do |value|
|
||||
self.settings = self.settings.merge(attribute.to_s => value)
|
||||
end
|
||||
end
|
||||
|
||||
NOT_AVAILABLE = 'N/A'.freeze
|
||||
|
||||
vault_attribute :settings, serialize: :json, default: {}
|
||||
|
||||
belongs_to :blockchain, foreign_key: :blockchain_key, primary_key: :key
|
||||
has_and_belongs_to_many :currencies
|
||||
|
||||
validates :name, presence: true, uniqueness: true
|
||||
validates :address, presence: true
|
||||
|
||||
validates :status, inclusion: { in: %w[active disabled] }
|
||||
|
||||
validates :gateway, inclusion: { in: ->(_){ Wallet.gateways.map(&:to_s) } }
|
||||
|
||||
validates :max_balance, numericality: { greater_than_or_equal_to: 0 }
|
||||
|
||||
scope :active, -> { where(status: :active) }
|
||||
scope :deposit, -> { where(kind: kinds(deposit: true, values: true)) }
|
||||
scope :fee, -> { where(kind: kinds(fee: true, values: true)) }
|
||||
scope :withdraw, -> { where(kind: kinds(withdraw: true, values: true)) }
|
||||
scope :with_currency, ->(currency) { joins(:currencies).where(currencies: { id: currency }) }
|
||||
scope :ordered, -> { order(kind: :asc) }
|
||||
|
||||
before_validation(on: :create) do
|
||||
if address.blank? && settings[:uri].present? && currencies.present?
|
||||
begin
|
||||
result = generate_settings
|
||||
rescue StandardError => e
|
||||
Rails.logger.info { "Cannot generate wallet address and secret error: #{e.message}" }
|
||||
result = { address: 'changeme', secret: 'changeme' }
|
||||
ensure
|
||||
if result.present?
|
||||
self.address = result[:address]
|
||||
self.secret = result[:secret]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
before_validation do
|
||||
next unless address? && blockchain.blockchain_api.supports_cash_addr_format?
|
||||
self.address = CashAddr::Converter.to_cash_address(address)
|
||||
end
|
||||
|
||||
class << self
|
||||
def gateways
|
||||
Peatio::Wallet.registry.adapters.keys
|
||||
end
|
||||
|
||||
def kinds(options={})
|
||||
ENUMERIZED_KINDS
|
||||
.yield_self do |kinds|
|
||||
case
|
||||
when options.fetch(:deposit, false)
|
||||
kinds.select { |_k, v| v / 100 == 1 }
|
||||
when options.fetch(:fee, false)
|
||||
kinds.select { |_k, v| v / 100 == 2 }
|
||||
when options.fetch(:withdraw, false)
|
||||
kinds.select { |_k, v| v / 100 == 3 }
|
||||
else
|
||||
kinds
|
||||
end
|
||||
end
|
||||
.yield_self do |kinds|
|
||||
case
|
||||
when options.fetch(:keys, false)
|
||||
kinds.keys
|
||||
when options.fetch(:values, false)
|
||||
kinds.values
|
||||
else
|
||||
kinds
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def deposit_wallet(currency_id)
|
||||
Wallet.active.deposit.joins(:currencies).find_by(currencies: { id: currency_id })
|
||||
end
|
||||
end
|
||||
|
||||
def current_balance(currency = nil)
|
||||
if currency.present?
|
||||
WalletService.new(self).load_balance!(currency)
|
||||
else
|
||||
currencies.each_with_object({}) do |c, balances|
|
||||
balances[c.id] = WalletService.new(self).load_balance!(c)
|
||||
rescue StandardError => e
|
||||
report_exception(e)
|
||||
balances[c.id] = NOT_AVAILABLE
|
||||
end
|
||||
end
|
||||
rescue StandardError => e
|
||||
report_exception(e)
|
||||
NOT_AVAILABLE
|
||||
end
|
||||
|
||||
def to_wallet_api_settings
|
||||
settings.compact.deep_symbolize_keys.merge(address: address)
|
||||
end
|
||||
|
||||
def wallet_url
|
||||
blockchain.explorer_address.gsub('#{address}', address) if blockchain
|
||||
end
|
||||
|
||||
def service
|
||||
::WalletService.new(self)
|
||||
end
|
||||
|
||||
def generate_settings
|
||||
service.create_address!('peatio', {})
|
||||
end
|
||||
end
|
||||
|
||||
# == Schema Information
|
||||
# Schema version: 20201125134745
|
||||
#
|
||||
# Table name: wallets
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# blockchain_key :string(32)
|
||||
# name :string(64)
|
||||
# address :string(255) not null
|
||||
# kind :integer not null
|
||||
# gateway :string(20) default(""), not null
|
||||
# settings_encrypted :string(1024)
|
||||
# balance :json
|
||||
# max_balance :decimal(32, 16) default(0.0), not null
|
||||
# status :string(32)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_wallets_on_kind (kind)
|
||||
# index_wallets_on_kind_and_currency_id_and_status (kind,status)
|
||||
# index_wallets_on_status (status)
|
||||
#
|
||||
Reference in New Issue
Block a user