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

168
app/models/wallet.rb Normal file
View 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)
#