Exemplo n.º 1
0
def _convert_to_classic_address(json: Dict[str, Any], field: str) -> None:
    """
    Mutates JSON-like dictionary to convert the given field from an X-address (if
    applicable) to a classic address.
    """
    if field in json and is_valid_xaddress(json[field]):
        json[field] = xaddress_to_classic_address(json[field])
Exemplo n.º 2
0
async def get_account_info(address: str, client: Client) -> Response:
    """
    Query the ledger for account info of given address.

    Args:
        address: the account to query.
        client: the network client used to make network calls.

    Returns:
        The account info for the address.

    Raises:
        XRPLRequestFailureException: if the rippled API call fails.
    """
    if is_valid_xaddress(address):
        address, _, _ = xaddress_to_classic_address(address)
    response = await client.request_impl(
        AccountInfo(
            account=address,
            ledger_index="validated",
        ))
    if response.is_successful():
        return response

    result = cast(Dict[str, Any], response.result)
    raise XRPLRequestFailureException(result)
Exemplo n.º 3
0
def _validate_account_xaddress(
    json: Dict[str, Any], account_field: str, tag_field: str
) -> None:
    """
    Mutates JSON-like dictionary so the X-Address in the account field is the classic
    address, and the tag is in the tag field.
    """
    if is_valid_xaddress(json[account_field]):
        account, tag, _ = xaddress_to_classic_address(json[account_field])
        json[account_field] = account
        if json[tag_field] and json[tag_field] != tag:
            raise XRPLException(f"{tag_field} value does not match X-Address tag")
        json[tag_field] = tag
Exemplo n.º 4
0
async def get_latest_transaction(account: str, client: Client) -> Response:
    """
    Fetches the most recent transaction on the ledger associated with an account.

    Args:
        account: the account to query.
        client: the network client used to communicate with a rippled node.

    Returns:
        The Response object containing the transaction info.

    Raises:
        XRPLRequestFailureException: if the transaction fails.
    """
    # max == -1 means that it's the most recent validated ledger version
    if is_valid_xaddress(account):
        account, _, _ = xaddress_to_classic_address(account)
    response = await client.request_impl(
        AccountTx(account=account, ledger_index_max=-1, limit=1))
    if not response.is_successful():
        result = cast(Dict[str, Any], response.result)
        raise XRPLRequestFailureException(result)
    return response
Exemplo n.º 5
0
async def get_account_transactions(address: str,
                                   client: Client) -> List[Dict[str, Any]]:
    """
    Query the ledger for a list of transactions that involved a given account.

    Args:
        address: the account to query.
        client: the network client used to make network calls.

    Returns:
        The transaction history for the address.

    Raises:
        XRPLRequestFailureException: if the transaction fails.
    """
    if is_valid_xaddress(address):
        address, _, _ = xaddress_to_classic_address(address)
    request = AccountTx(account=address)
    response = await client.request_impl(request)
    result = cast(Dict[str, Any], response.result)
    if not response.is_successful():
        raise XRPLRequestFailureException(result)
    return cast(List[Dict[str, Any]], result["transactions"])
Exemplo n.º 6
0
    def from_value(cls: Type[AccountID], value: str) -> AccountID:
        """
        Construct an AccountID from a hex string or a base58 r-Address.

        Args:
            value: The string to construct an AccountID from.

        Returns:
            The AccountID constructed from value.

        Raises:
            XRPLBinaryCodecException: If the supplied value is of the wrong type.
        """
        if not isinstance(value, str):
            raise XRPLBinaryCodecException(
                "Invalid type to construct an AccountID: expected str,"
                f" received {value.__class__.__name__}."
            )

        if value == "":
            return cls()

        # hex-encoded case
        if _HEX_REGEX.fullmatch(value):
            return cls(bytes.fromhex(value))
        # base58 case
        if is_valid_classic_address(value):
            return cls(decode_classic_address(value))
        if is_valid_xaddress(value):
            classic_address, _, _ = xaddress_to_classic_address(value)
            return cls(decode_classic_address(classic_address))

        raise XRPLBinaryCodecException(
            "Invalid value to construct an AccountID: expected valid classic address "
            f"or X-Address, received {value.__class__.__name__}."
        )
Exemplo n.º 7
0
    def test_is_valid_xaddress_empty(self):
        xaddress = ""

        result = addresscodec.is_valid_xaddress(xaddress)
        self.assertFalse(result)
Exemplo n.º 8
0
    def test_is_valid_xaddress_invalid(self):
        xaddress = "XVLhHMPHU98es4dbozjVtdWzVrDjtV18pX8zeUygYrCgrPh"

        result = addresscodec.is_valid_xaddress(xaddress)
        self.assertFalse(result)
Exemplo n.º 9
0
    def test_is_valid_xaddress_valid(self):
        xaddress = "X7AcgcsBL6XDcUb289X4mJ8djcdyKaB5hJDWMArnXr61cqZ"

        result = addresscodec.is_valid_xaddress(xaddress)
        self.assertTrue(result)
Exemplo n.º 10
0
    def from_value(
        cls: Type[SerializedDict], value: Dict[str, Any], only_signing: bool = False
    ) -> SerializedDict:
        """
        Create a SerializedDict object from a dictionary.

        Args:
            value: The dictionary to construct a SerializedDict from.
            only_signing: whether only the signing fields should be included.

        Returns:
            The SerializedDict object constructed from value.

        Raises:
            XRPLBinaryCodecException: If the SerializedDict can't be constructed
                from value.
        """
        from xrpl.core.binarycodec.binary_wrappers.binary_serializer import (
            BinarySerializer,
        )

        serializer = BinarySerializer()

        xaddress_decoded = {}
        for (k, v) in value.items():
            if isinstance(v, str) and is_valid_xaddress(v):
                handled = _handle_xaddress(k, v)
                if (
                    _SOURCE_TAG in handled
                    and handled[_SOURCE_TAG] is not None
                    and _SOURCE_TAG in value
                    and value[_SOURCE_TAG] is not None
                ):
                    raise XRPLBinaryCodecException(
                        "Cannot have Account X-Address and SourceTag"
                    )
                if (
                    _DEST_TAG in handled
                    and handled[_DEST_TAG] is not None
                    and _DEST_TAG in value
                    and value[_DEST_TAG] is not None
                ):
                    raise XRPLBinaryCodecException(
                        "Cannot have Destination X-Address and DestinationTag"
                    )
                xaddress_decoded.update(handled)
            else:
                xaddress_decoded[k] = _str_to_enum(k, v)

        sorted_keys: List[FieldInstance] = []
        for field_name in xaddress_decoded:
            field_instance = get_field_instance(field_name)
            if (
                field_instance is not None
                and xaddress_decoded[field_instance.name] is not None
                and field_instance.is_serialized
            ):
                sorted_keys.append(field_instance)
        sorted_keys.sort(key=lambda x: x.ordinal)

        if only_signing:
            sorted_keys = list(filter(lambda x: x.is_signing, sorted_keys))

        for field in sorted_keys:
            try:
                associated_value = field.associated_type.from_value(
                    xaddress_decoded[field.name]
                )
            except XRPLBinaryCodecException as e:
                # mildly hacky way to get more context in the error
                # provides the field name and not just the type it's expecting
                # keeps the original stack trace
                e.args = (f"Error processing {field.name}: {e.args[0]}",) + e.args[1:]
                raise
            serializer.write_field_and_value(field, associated_value)
            if field.type == _SERIALIZED_DICT:
                serializer.append(_OBJECT_END_MARKER_BYTE)

        return SerializedDict(bytes(serializer))