def serialize_step(step: t.Mapping) -> bytes: blob = bytearray([0]) if 'account' in step: blob[0] |= 0x01 blob.extend(DEFAULT_CODEC.decode_address(step['account'])) if 'currency' in step: blob[0] |= 0x10 blob.extend(serialize_currency(step['currency'])) if 'issuer' in step: blob[0] |= 0x20 blob.extend(DEFAULT_CODEC.decode_address(step['issuer'])) return bytes(blob)
def deserialize_step(scanner: Scanner) -> Step: type_byte = scanner.take1() step = t.cast(Step, {}) if type_byte & 0x01: step['account'] = DEFAULT_CODEC.encode_address( t.cast(AccountId, scanner.take(20))) if type_byte & 0x10: step['currency'] = deserialize_currency(scanner) if type_byte & 0x20: step['issuer'] = DEFAULT_CODEC.encode_address( t.cast(AccountId, scanner.take(20))) step['type'] = type_byte step['type_hex'] = to_bytes(type_byte, 8).hex().upper() return step
def serialize_amount(amount: Amount) -> bytes: """ Serialize an Amount. An XRP Amount comes as a string. It must be serialized to 64 bits: 1 zero bit, 1 sign bit (zero for negative, one for positive), 62 bits of absolute value. A non-XRP Amount comes as a dictionary. It must be serialized thus: 64 bits of unsigned value; 160 bit currency code; 160 bit issuer AccountID. """ if isinstance(amount, str): value = int(amount) sign = int(value > 0) magnitude = abs(value) assert magnitude <= 10**17 return to_bytes(sign << 62 | magnitude, 8) if isinstance(amount, dict): value_bytes = serialize_amount_non_xrp(amount['value']) currency_bytes = serialize_currency(amount['currency']) address_bytes = DEFAULT_CODEC.decode_address( t.cast(Address, amount['issuer'])) return value_bytes + currency_bytes + address_bytes raise ValueError('Amount must be `str` or `{value, currency, issuer}`')
def test_derive_address2(): # From example in section "Address Encoding": # https://xrpl.org/accounts.html#address-encoding public_key = bytes.fromhex( 'ED9434799226374926EDA3B54B1B461B4ABF7237962EAE18528FEA67595397FA32') address = 'rDTXLQ7ZKZVKz33zJbHjgVShjsBnqMBhmN' account_id = derive_account_id(public_key) assert codec.encode_address(account_id) == address
def test_derive_address1(): # From example request and response: # https://xrpl.org/wallet_propose.html public_key = bytes.fromhex( '0330E7FC9D56BB25D6893BA3F317AE5BCF33B3291BD63DB32654A313222F7FD020') address = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh' account_id = derive_account_id(public_key) assert codec.encode_address(account_id) == address
def deserialize_amount(scanner: Scanner) -> Amount: byte1 = scanner.bite() # Most-significant bit is the format bit. 1 means "is not XRP". if not byte1 & (1 << 7): # Second most-significant bit is the sign bit. 1 means "is positive". sign = 1 if byte1 & (1 << 6) else -1 # Format bit is already cleared, but clear both top bits regardless. magnitude = from_bytes(scanner.take(8)) & ~(0b11 << 62) return str(sign * magnitude) value = deserialize_amount_non_xrp(scanner) currency = deserialize_currency(scanner) issuer = DEFAULT_CODEC.encode_address(t.cast(AccountId, scanner.take(20))) return {'value': value, 'currency': currency, 'issuer': issuer}
def test_encode_address(account_id_hex, address): account_id = bytes.fromhex(account_id_hex) assert codec.encode_address(account_id) == address
def serialize_account_id(address: str) -> bytes: return vl_encode(DEFAULT_CODEC.decode_address(t.cast(Address, address)))
def test_encode_with_checksum(bites, encoded_bites): assert codec.encode_with_checksum(bites) == encoded_bites
def deserialize_account_id(scanner: Scanner) -> Address: account_id = t.cast(AccountId, vl_decode(scanner)) return DEFAULT_CODEC.encode_address(account_id)
def test_decode_with_checksum(bites, encoded_bites): assert codec.decode_with_checksum(encoded_bites) == bites
def test_decode_address(account_id_hex, address): account_id = bytes.fromhex(account_id_hex) assert codec.decode_address(address) == account_id
def test_encode(bites, encoded_bites): assert codec.encode(bites) == encoded_bites
def test_decode_secp256k1_seed(seed_hex, encoded_seed): seed, algorithm = codec.decode_seed(encoded_seed) assert algorithm == secp256k1 assert seed.hex().upper() == seed_hex
def test_encode_secp256k1_seed(seed_hex, encoded_seed): seed = bytes.fromhex(seed_hex) assert codec.encode_seed(seed, secp256k1) == encoded_seed
def test_decode_ed25519_seed(seed_hex, encoded_seed): seed, algorithm = codec.decode_seed(encoded_seed) assert algorithm == ed25519 assert seed.hex().upper() == seed_hex
def test_encode_ed25519_seed(seed_hex, encoded_seed): seed = bytes.fromhex(seed_hex) assert codec.encode_seed(seed, ed25519) == encoded_seed