def to_json(self: Amount) -> Union[str, Dict[Any, Any]]: """Construct a JSON object representing this Amount. Returns: The JSON representation of this amount. """ if self.is_native(): sign = "" if self.is_positive() else "-" masked_bytes = (int.from_bytes(self.buffer, byteorder="big") & 0x3FFFFFFFFFFFFFFF) return f"{sign}{masked_bytes}" parser = BinaryParser(str(self)) value_bytes = parser.read(8) currency = Currency.from_parser(parser) issuer = AccountID.from_parser(parser) b1 = value_bytes[0] b2 = value_bytes[1] is_positive = b1 & 0x40 sign = "" if is_positive else "-" exponent = ((b1 & 0x3F) << 2) + ((b2 & 0xFF) >> 6) - 97 hex_mantissa = hex(b2 & 0x3F) + value_bytes[2:].hex() int_mantissa = int(hex_mantissa[2:], 16) value = Decimal(f"{sign}{int_mantissa}") * Decimal(f"1e{exponent}") if value.is_zero(): value_str = "0" else: value_str = str(value).rstrip("0").rstrip(".") verify_iou_value(value_str) return { "value": value_str, "currency": currency.to_json(), "issuer": issuer.to_json(), }
def test_int_read_methods(self): test_hex = "01000200000003" binary_parser = BinaryParser(test_hex) int8 = binary_parser.read_uint8() int16 = binary_parser.read_uint16() int32 = binary_parser.read_uint32() self.assertEqual(int8, 1) self.assertEqual(int16, 2) self.assertEqual(int32, 3)
def test_read_variable_length_length(self): for case in [100, 1000, 20_000]: binary_serializer = BinarySerializer() bytestring = "A2" * case blob = Blob.from_value(bytestring) binary_serializer.write_length_encoded(blob) # hex string representation of encoded length prefix encoded_length = binary_serializer.bytesink.hex() binary_parser = BinaryParser(encoded_length) decoded_length = binary_parser._read_length_prefix() self.assertEqual(case, decoded_length)
def from_parser(cls: Type[Amount], parser: BinaryParser, length_hint: Optional[int] = None) -> Amount: """Construct an Amount from an existing BinaryParser. Args: parser: The parser to construct the Amount object from. length_hint: Unused. Returns: An Amount object. """ parser_first_byte = parser.peek() not_xrp = (int(parser_first_byte) if parser_first_byte is not None else 0x00) & 0x80 if not_xrp: num_bytes = _CURRENCY_AMOUNT_BYTE_LENGTH else: num_bytes = _NATIVE_AMOUNT_BYTE_LENGTH return cls(parser.read(num_bytes))
def test_peek_skip_read_methods(self): test_hex = "00112233445566" test_bytes = bytes.fromhex(test_hex) binary_parser = BinaryParser(test_hex) first_byte = binary_parser.peek() self.assertEqual(first_byte, test_bytes[0]) binary_parser.skip(3) self.assertEqual(test_bytes[3:], binary_parser.bytes) next_n_bytes = binary_parser.read(2) self.assertEqual(test_bytes[3:5], next_n_bytes)
def setUp(self): # 32 bytes, 64 nibbles self.hex_256_bits = ( "1000000000200000000030000000004000000000500000000060000000001234") self.parser = BinaryParser(self.hex_256_bits) self.expected_width = 32
def setUp(self): # 20 bytes, 40 nibbles self.hex_160_bits = "1000000000200000000030000000004000000000" self.parser = BinaryParser(self.hex_160_bits) self.expected_width = 20
def setUp(self): # 16 bytes, 32 nibbles self.hex_128_bits = "10000000002000000000300000000012" self.parser = BinaryParser(self.hex_128_bits) self.expected_width = 16
def test_to_json_xrp(self): for json, serialized in XRP_CASES: parser = BinaryParser(serialized) amount_object = amount.Amount.from_parser(parser) self.assertEqual(amount_object.to_json(), json)
def test_to_json_issued_currency(self): for json, serialized in IOU_CASES: parser = BinaryParser(serialized) amount_object = amount.Amount.from_parser(parser) self.assertEqual(amount_object.to_json(), json)
def test_from_parser(self): parser = BinaryParser(SERIALIZED) vector256_object = Vector256.from_parser(parser) self.assertEqual(vector256_object.to_hex(), SERIALIZED)