Module: MixinBot::Utils::Amount

Included in:
MixinBot::Utils
Defined in:
lib/mixin_bot/utils/amount.rb

Overview

Decimal-safe unit conversion between human-readable amounts and decimal strings, mirroring the Node SDK's utils/amount.ts (BigNumber-based).

Constant Summary collapse

DECIMAL_STRING_PATTERN =
/\A[+-]?\d+(\.\d+)?\z/

Instance Method Summary collapse

Instance Method Details

#format_units(amount, decimals) ⇒ Object

Divide an amount by 10decimals and return the exact decimal string. Accepts Integers and decimal strings ('7.5'); leading zeros are decimal, never octal. Mirrors BigNumber(amount).dividedBy(10unit).

MixinBot.utils.format_units(10**17, 18) # => "0.1"
MixinBot.utils.format_units('010', 18)  # => "0.00000000000000001"
MixinBot.utils.format_units('7.5', 2)   # => "0.075"


23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/mixin_bot/utils/amount.rb', line 23

def format_units(amount, decimals)
  decimals = validated_decimals(decimals)
  value = validated_amount_string(amount)

  sign = value.start_with?('-') ? '-' : ''
  whole, fraction = value.delete_prefix('-').delete_prefix('+').split('.')
  fraction ||= ''
  digits = "#{whole}#{fraction}".sub(/\A0+(?=\d)/, '')
  shift = fraction.length + decimals

  formatted =
    if shift.zero?
      digits
    elsif digits.size > shift
      "#{digits[0...-shift]}.#{digits[-shift..]}"
    else
      "0.#{'0' * (shift - digits.size)}#{digits}"
    end

  "#{sign}#{formatted}".sub(/(\.\d*?)0+\z/, '\1').sub(/\.\z/, '')
end

#parse_units(amount, decimals) ⇒ Object

Multiply a decimal amount string by 10**decimals and return integer minor units. Values with more precision than decimals round down (floor), matching the Node SDK; invalid strings raise ArgumentError.

MixinBot.utils.parse_units('0.1', 18) # => 100000000000000000


52
53
54
55
56
57
# File 'lib/mixin_bot/utils/amount.rb', line 52

def parse_units(amount, decimals)
  decimals = validated_decimals(decimals)
  value = validated_amount_string(amount)

  (value.to_d * (10**decimals)).floor
end