169 lines
4.9 KiB
Ruby
169 lines
4.9 KiB
Ruby
# 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)
|
|
#
|