Skip to content
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions xrpl/asyncio/clients/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from __future__ import annotations

from abc import ABC, abstractmethod
from typing import Optional
from typing import Optional, Dict

from typing_extensions import Final, Self

Expand All @@ -24,14 +24,24 @@ class Client(ABC):
:meta private:
"""

def __init__(self: Self, url: str) -> None:
def __init__(
self: Self,
url: str,
*,
headers: Optional[Dict[str, str]] = None,
) -> None:
"""
Initializes a client.

Arguments:
url: The url to which this client will connect
url: The URL to which this client will connect.
headers: Optional dictionary of default headers to include with each request.
These can be used to authenticate with private XRPL nodes or pass
custom metadata, such as:
- {"Authorization": "Bearer <token>"}
"""
self.url = url
self.headers = headers or {}
self.network_id: Optional[int] = None
self.build_version: Optional[str] = None

Expand Down Expand Up @@ -66,7 +76,6 @@ async def get_network_id_and_build_version(client: Client) -> None:
Raises:
XRPLRequestFailureException: if the rippled API call fails.
"""
# the required values are already present, no need for further processing
if client.network_id and client.build_version:
return

Expand Down
36 changes: 33 additions & 3 deletions xrpl/asyncio/clients/json_rpc_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from __future__ import annotations

from json import JSONDecodeError
from typing import Optional, Dict

from httpx import AsyncClient
from typing_extensions import Self
Expand All @@ -21,16 +22,37 @@ class JsonRpcBase(Client):
:meta private:
"""

def __init__(
self: Self,
url: str,
*,
headers: Optional[Dict[str, str]] = None,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a similar update to the WebSocket class's constructor?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would updating Client supersede this?

) -> None:
"""
Initializes a new JsonRpcBase client.

Arguments:
url: The URL of the XRPL node to connect to.
headers: Optional default headers for all requests (e.g. API key or Dhali payment-claim).
"""
super().__init__(url)
self.headers = headers or {}

async def _request_impl(
self: Self, request: Request, *, timeout: float = REQUEST_TIMEOUT
self: Self,
request: Request,
*,
timeout: float = REQUEST_TIMEOUT,
headers: Optional[Dict[str, str]] = None,
) -> Response:
"""
Base ``_request_impl`` implementation for JSON RPC.

Arguments:
request: An object representing information about a rippled request.
timeout: The duration within which we expect to hear a response from the
rippled validator.
rippled server.
headers: Optional additional headers to include for this request.

Returns:
The response from the server, as a Response object.
Expand All @@ -40,10 +62,18 @@ async def _request_impl(

:meta private:
"""
# Merge global and per-request headers
merged_headers = {
"Content-Type": "application/json",
**self.headers,
**(headers or {}),
}

async with AsyncClient(timeout=timeout) as http_client:
response = await http_client.post(
self.url,
json=request_to_json_rpc(request),
headers=merged_headers,
)
try:
return json_to_response(response.json())
Expand All @@ -53,4 +83,4 @@ async def _request_impl(
"error": response.status_code,
"error_message": response.text,
}
)
) from None