class ExoCrypto::CryptoCalc
Public Class Methods
apply_fun(f, args)
click to toggle source
# File lib/exocrypto/crypto_calc.rb, line 80 def self.apply_fun(f, args) args_prime = args.map { |i| BigDecimal(i) } lambdas = { 'fst' => lambda { |args| args[0] }, '1/fst' => lambda { |args| 1.0 / args[0] }, 'fst,snd' => lambda { |args| [args[0], args[1]] }, 'fst*snd' => lambda { |args| args[0] * args[1] }, 'fst/snd' => lambda { |args| args[0] / args[1] }, 'snd/fst' => lambda { |args| args[1] / args[0] }, '1/(fst*snd)' => lambda { |args| 1.0 / (args[0] * args[1]) }, } lambdas[f].call(args_prime) end
do_partial_payments(request, payments)
click to toggle source
# File lib/exocrypto/crypto_calc.rb, line 37 def self.do_partial_payments(request, payments) epoch = ExoBasic::Timer::EPOCH.to_datetime xs = payments.map do |payment| if payment[:paid] precision = Bip44WalletProvider.precision_of(payment[:currency]) satoshis = BigDecimal(payment[:amount_paid]) * BigDecimal(payment[:exchange_rate]) [satoshis / BigDecimal(10 ** precision), payment[:date]] else [BigDecimal(0), epoch] end end total_paid = xs.map { |x| x[0] }.sum paid_date = xs.map { |x| x[1] }.max if paid_date == epoch paid_date = nil end request_amount = request[:amount] request_precision = request[:precision] total_paid_rounded_s = CryptoCalc.fixed_length_to_s(total_paid.round(request_precision), request_precision) remaining = BigDecimal(request[:amount]) - BigDecimal(total_paid_rounded_s) remaining_rounded_s = CryptoCalc.fixed_length_to_s(remaining.round(request_precision), request_precision) n_paid = payments.select { |payment| payment[:paid] == true }.length n_unpaid = payments.length - n_paid remaining_rounded = BigDecimal(remaining_rounded_s) needs_change = remaining_rounded < BigDecimal(0) is_fully_paid = remaining_rounded.zero? || needs_change is_partially_paid = !is_fully_paid && remaining_rounded < BigDecimal(request_amount) { :n_paid => n_paid, :n_unpaid => n_unpaid, :paid_date => paid_date, :amount_paid => total_paid_rounded_s, :amount_remaining => remaining_rounded_s, :overpaid => needs_change, :is_fully_paid => is_fully_paid, :is_partially_paid => is_partially_paid } end
fixed_length_to_s(amount, precision)
click to toggle source
# File lib/exocrypto/crypto_calc.rb, line 15 def self.fixed_length_to_s(amount, precision) "%.#{precision}f" % amount end
get_satoshis(currency, exchange_rate, remaining)
click to toggle source
see: reinteractive.com/posts/373-diving-into-the-ruby-source-code-bigdecimal-rounding-options
# File lib/exocrypto/crypto_calc.rb, line 25 def self.get_satoshis(currency, exchange_rate, remaining) precision = Bip44WalletProvider.precision_of(currency) amount_to_be_paid = 0 rate = BigDecimal(exchange_rate) if !rate.zero? amount_to_be_paid = BigDecimal(remaining) / rate amount_to_be_paid = (amount_to_be_paid.round(precision) * BigDecimal(10 ** precision)).to_i end amount_to_be_paid end
mul(a, b)
click to toggle source
# File lib/exocrypto/crypto_calc.rb, line 3 def self.mul(a, b) BigDecimal(a) * BigDecimal(b) end
s_from_satoshis(amount, precision)
click to toggle source
# File lib/exocrypto/crypto_calc.rb, line 11 def self.s_from_satoshis(amount, precision) (amount / BigDecimal(10 ** precision)).to_s end
s_to_satoshis(amount, precision)
click to toggle source
# File lib/exocrypto/crypto_calc.rb, line 7 def self.s_to_satoshis(amount, precision) (BigDecimal(amount) * BigDecimal(10 ** precision)).to_i end
to_fixed_length(amount, currency)
click to toggle source
# File lib/exocrypto/crypto_calc.rb, line 19 def self.to_fixed_length(amount, currency) precision = Bip44WalletProvider.precision_of(currency) CryptoCalc.fixed_length_to_s(CryptoCalc.s_from_satoshis(amount, precision), precision) end