Class: BinaryCodec::Amount
- Inherits:
-
SerializedType
- Object
- SerializedType
- BinaryCodec::Amount
- Defined in:
- lib/binary-codec/types/amount.rb
Constant Summary collapse
- DEFAULT_AMOUNT_HEX =
"4000000000000000".freeze
- ZERO_CURRENCY_AMOUNT_HEX =
"8000000000000000".freeze
- NATIVE_AMOUNT_BYTE_LENGTH =
8- CURRENCY_AMOUNT_BYTE_LENGTH =
48- MAX_IOU_PRECISION =
16- MIN_IOU_EXPONENT =
-96- MAX_IOU_EXPONENT =
80- MAX_DROPS =
BigDecimal("1e17")
- MIN_XRP =
BigDecimal("1e-6")
Instance Attribute Summary
Attributes inherited from SerializedType
Class Method Summary collapse
-
.from(value) ⇒ Amount
Construct an amount from an IOU, MPT, or string amount.
-
.from_parser(parser) ⇒ Amount
Read an amount from a BinaryParser.
Instance Method Summary collapse
-
#initialize(bytes = nil) ⇒ Amount
constructor
A new instance of Amount.
-
#to_json ⇒ Hash, String
The JSON representation of this Amount.
Methods inherited from SerializedType
from_bytes, from_hex, from_json, get_type_by_name, #to_byte_sink, #to_bytes, #to_hex, #to_s
Constructor Details
#initialize(bytes = nil) ⇒ Amount
22 23 24 25 26 27 28 |
# File 'lib/binary-codec/types/amount.rb', line 22 def initialize(bytes = nil) if bytes.nil? bytes = hex_to_bytes(DEFAULT_AMOUNT_HEX) end @bytes = bytes end |
Class Method Details
.from(value) ⇒ Amount
Construct an amount from an IOU, MPT, or string amount
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/binary-codec/types/amount.rb', line 34 def self.from(value) return value if value.is_a?(Amount) amount = Array.new(8, 0) # Equivalent to a Uint8Array of 8 zeros if value.is_a?(String) Amount.assert_xrp_is_valid(value) number = value.to_i # Use to_i for equivalent BigInt handling int_buf = [Array.new(4, 0), Array.new(4, 0)] BinaryCodec.write_uint32be(int_buf[0], (number >> 32) & 0xFFFFFFFF, 0) BinaryCodec.write_uint32be(int_buf[1], number & 0xFFFFFFFF, 0) amount = int_buf.flatten amount[0] |= 0x40 return Amount.new(amount) end if is_amount_object_iou?(value) number = BigDecimal(value[:value]) self.assert_iou_is_valid(number) if number.zero? amount[0] |= 0x80 else scale = number.frac.to_s('F').split('.').last.size unscaled_value = (number * (10**scale)).to_i int_string = unscaled_value.abs.to_s.ljust(16, '0') num = int_string.to_i int_buf = [Array.new(4, 0), Array.new(4, 0)] BinaryCodec.write_uint32be(int_buf[0], (num >> 32) & 0xFFFFFFFF) BinaryCodec.write_uint32be(int_buf[1], num & 0xFFFFFFFF) amount = int_buf.flatten amount[0] |= 0x80 if number > 0 amount[0] |= 0x40 end exponent = number.exponent - 16 exponent_byte = 97 + exponent amount[0] |= exponent_byte >> 2 amount[1] |= (exponent_byte & 0x03) << 6 end currency = Currency.from(value[:currency]).to_bytes issuer = AccountId.from(value[:issuer]).to_bytes return Amount.new(amount + currency + issuer) end end |
.from_parser(parser) ⇒ Amount
Read an amount from a BinaryParser
97 98 99 100 101 102 103 104 105 |
# File 'lib/binary-codec/types/amount.rb', line 97 def self.from_parser(parser) is_iou = parser.peek & 0x80 != 0 return Amount.new(parser.read(48)) if is_iou # The amount can be either MPT or XRP at this point is_mpt = parser.peek & 0x20 != 0 num_bytes = is_mpt ? 33 : 8 Amount.new(parser.read(num_bytes)) end |
Instance Method Details
#to_json ⇒ Hash, String
The JSON representation of this Amount
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/binary-codec/types/amount.rb', line 110 def to_json if is_native? bytes = @bytes.dup # Duplicate the bytes to avoid mutation is_positive = (bytes[0] & 0x40) != 0 sign = is_positive ? '' : '-' bytes[0] &= 0x3f msb = BinaryCodec.read_uint32be(bytes[0, 4]) lsb = BinaryCodec.read_uint32be(bytes[4, 4]) num = (msb << 32) | lsb return "#{sign}#{num}" end if is_iou? parser = BinaryParser.new(to_s) mantissa = parser.read(8) currency = Currency.from_parser(parser) issuer = AccountId.from_parser(parser) b1 = mantissa[0] b2 = mantissa[1] is_positive = (b1 & 0x40) != 0 sign = is_positive ? '' : '-' exponent = ((b1 & 0x3f) << 2) + ((b2 & 0xff) >> 6) - 97 mantissa[0] = 0 mantissa[1] &= 0x3f value = BigDecimal("#{sign}#{bytes_to_hex(mantissa).to_i(16)}") * BigDecimal("1e#{exponent}") self.class.assert_iou_is_valid(value) return { "value" => value.to_s('F'), "currency" => currency.to_json, "issuer" => issuer.to_json }.to_s end if is_mpt? parser = BinaryParser.new(to_s) leading_byte = parser.read(1) amount = parser.read(8) mpt_id = Hash192.from_parser(parser) is_positive = (leading_byte[0] & 0x40) != 0 sign = is_positive ? '' : '-' msb = read_uint32be(amount[0, 4]) lsb = read_uint32be(amount[4, 4]) num = (msb << 32) | lsb return { value: "#{sign}#{num}", mpt_issuance_id: mpt_id.to_s }.to_s end raise 'Invalid amount to construct JSON' end |