0
# Network Clients
1
2
Connect to XRPL networks using JSON-RPC or WebSocket protocols with both synchronous and asynchronous interfaces. Clients provide the network communication layer for all XRPL operations.
3
4
## Capabilities
5
6
### Synchronous Clients
7
8
Blocking clients for straightforward request-response communication patterns.
9
10
```python { .api }
11
from xrpl.clients import JsonRpcClient, WebsocketClient
12
13
class JsonRpcClient:
14
"""Synchronous JSON-RPC client for XRPL nodes."""
15
16
def __init__(self, url: str):
17
"""
18
Initialize JSON-RPC client.
19
20
Args:
21
url: URL of the XRPL JSON-RPC endpoint
22
"""
23
24
def request(self, request):
25
"""
26
Send a request to the XRPL node.
27
28
Args:
29
request: Request object (from xrpl.models.requests)
30
31
Returns:
32
Response object with result data
33
34
Raises:
35
XRPLRequestFailureException: If request fails
36
"""
37
38
class WebsocketClient:
39
"""Synchronous WebSocket client for XRPL nodes."""
40
41
def __init__(self, url: str):
42
"""
43
Initialize WebSocket client.
44
45
Args:
46
url: URL of the XRPL WebSocket endpoint
47
"""
48
49
def send(self, request):
50
"""
51
Send a request over WebSocket connection.
52
53
Args:
54
request: Request object
55
56
Returns:
57
Response object
58
"""
59
60
def open(self):
61
"""Open the WebSocket connection."""
62
63
def close(self):
64
"""Close the WebSocket connection."""
65
66
def is_open(self) -> bool:
67
"""Check if WebSocket connection is open."""
68
```
69
70
### Asynchronous Clients
71
72
Non-blocking clients for high-performance concurrent operations.
73
74
```python { .api }
75
from xrpl.asyncio.clients import AsyncJsonRpcClient, AsyncWebsocketClient
76
77
class AsyncJsonRpcClient:
78
"""Asynchronous JSON-RPC client for XRPL nodes."""
79
80
def __init__(self, url: str):
81
"""
82
Initialize async JSON-RPC client.
83
84
Args:
85
url: URL of the XRPL JSON-RPC endpoint
86
"""
87
88
async def request(self, request):
89
"""
90
Send an async request to the XRPL node.
91
92
Args:
93
request: Request object
94
95
Returns:
96
Response object with result data
97
"""
98
99
async def close(self):
100
"""Close the client and clean up resources."""
101
102
class AsyncWebsocketClient:
103
"""Asynchronous WebSocket client for XRPL nodes."""
104
105
def __init__(self, url: str):
106
"""
107
Initialize async WebSocket client.
108
109
Args:
110
url: URL of the XRPL WebSocket endpoint
111
"""
112
113
async def send(self, request):
114
"""
115
Send an async request over WebSocket.
116
117
Args:
118
request: Request object
119
120
Returns:
121
Response object
122
"""
123
124
async def open(self):
125
"""Open the WebSocket connection asynchronously."""
126
127
async def close(self):
128
"""Close the WebSocket connection asynchronously."""
129
130
def is_open(self) -> bool:
131
"""Check if WebSocket connection is open."""
132
```
133
134
### Response Handling
135
136
Utilities for processing client responses and converting between formats.
137
138
```python { .api }
139
from xrpl.clients.utils import (
140
json_to_response, request_to_json_rpc,
141
request_to_websocket, websocket_to_response
142
)
143
144
def json_to_response(json_object: dict):
145
"""
146
Convert JSON response to Response object.
147
148
Args:
149
json_object: Raw JSON response from server
150
151
Returns:
152
Structured Response object
153
"""
154
155
def request_to_json_rpc(request):
156
"""
157
Convert Request object to JSON-RPC format.
158
159
Args:
160
request: Request object to convert
161
162
Returns:
163
JSON-RPC formatted request
164
"""
165
166
def request_to_websocket(request):
167
"""
168
Convert Request object to WebSocket format.
169
170
Args:
171
request: Request object to convert
172
173
Returns:
174
WebSocket formatted request
175
"""
176
177
def websocket_to_response(websocket_response: dict):
178
"""
179
Convert WebSocket response to Response object.
180
181
Args:
182
websocket_response: Raw WebSocket response
183
184
Returns:
185
Structured Response object
186
"""
187
```
188
189
## Network Endpoints
190
191
### Mainnet Endpoints
192
193
```python
194
# JSON-RPC endpoints
195
mainnet_rpc_urls = [
196
"https://s1.ripple.com:51234",
197
"https://s2.ripple.com:51234",
198
"https://xrplcluster.com",
199
"https://xrpl.ws"
200
]
201
202
# WebSocket endpoints
203
mainnet_ws_urls = [
204
"wss://s1.ripple.com:443",
205
"wss://s2.ripple.com:443",
206
"wss://xrplcluster.com",
207
"wss://xrpl.ws"
208
]
209
```
210
211
### Testnet Endpoints
212
213
```python
214
# JSON-RPC endpoints
215
testnet_rpc_urls = [
216
"https://s.altnet.rippletest.net:51234",
217
"https://testnet.xrpl-labs.com"
218
]
219
220
# WebSocket endpoints
221
testnet_ws_urls = [
222
"wss://s.altnet.rippletest.net:443",
223
"wss://testnet.xrpl-labs.com"
224
]
225
```
226
227
### Devnet Endpoints
228
229
```python
230
# JSON-RPC endpoints
231
devnet_rpc_urls = [
232
"https://s.devnet.rippletest.net:51234"
233
]
234
235
# WebSocket endpoints
236
devnet_ws_urls = [
237
"wss://s.devnet.rippletest.net:443"
238
]
239
```
240
241
## Usage Examples
242
243
### Basic JSON-RPC Client Usage
244
245
```python
246
from xrpl.clients import JsonRpcClient
247
from xrpl.models.requests import AccountInfo, Ledger
248
249
# Connect to testnet
250
client = JsonRpcClient("https://s.altnet.rippletest.net:51234")
251
252
# Make account info request
253
account_request = AccountInfo(account="rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH")
254
response = client.request(account_request)
255
256
if response.is_successful():
257
account_data = response.result["account_data"]
258
print(f"Account balance: {account_data['Balance']} drops")
259
print(f"Sequence number: {account_data['Sequence']}")
260
else:
261
print(f"Request failed: {response.result}")
262
263
# Get current ledger info
264
ledger_request = Ledger(ledger_index="current")
265
ledger_response = client.request(ledger_request)
266
print(f"Current ledger: {ledger_response.result['ledger_index']}")
267
```
268
269
### WebSocket Client Usage
270
271
```python
272
from xrpl.clients import WebsocketClient
273
from xrpl.models.requests import Subscribe, AccountInfo
274
import time
275
276
# Connect to testnet WebSocket
277
client = WebsocketClient("wss://s.altnet.rippletest.net:443")
278
279
try:
280
# Open connection
281
client.open()
282
283
# Subscribe to ledger stream
284
subscribe_request = Subscribe(streams=["ledger"])
285
response = client.send(subscribe_request)
286
print(f"Subscription result: {response.result}")
287
288
# Make account query
289
account_request = AccountInfo(account="rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH")
290
account_response = client.send(account_request)
291
print(f"Account info: {account_response.result}")
292
293
# Keep connection open to receive stream updates
294
print("Listening for ledger updates...")
295
time.sleep(10) # Listen for 10 seconds
296
297
finally:
298
client.close()
299
```
300
301
### Asynchronous Client Operations
302
303
```python
304
import asyncio
305
from xrpl.asyncio.clients import AsyncJsonRpcClient
306
from xrpl.models.requests import AccountInfo, ServerInfo, Fee
307
308
async def get_multiple_data(client):
309
"""Fetch multiple pieces of data concurrently."""
310
311
# Create multiple requests
312
account_request = AccountInfo(account="rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH")
313
server_request = ServerInfo()
314
fee_request = Fee()
315
316
# Execute all requests concurrently
317
account_task = client.request(account_request)
318
server_task = client.request(server_request)
319
fee_task = client.request(fee_request)
320
321
# Wait for all to complete
322
account_response, server_response, fee_response = await asyncio.gather(
323
account_task, server_task, fee_task
324
)
325
326
return {
327
"account": account_response.result,
328
"server": server_response.result,
329
"fees": fee_response.result
330
}
331
332
async def main():
333
client = AsyncJsonRpcClient("https://s.altnet.rippletest.net:51234")
334
335
try:
336
# Get data concurrently
337
data = await get_multiple_data(client)
338
339
print("Account data:", data["account"]["account_data"]["Balance"])
340
print("Server version:", data["server"]["info"]["build_version"])
341
print("Current fees:", data["fees"]["drops"])
342
343
finally:
344
await client.close()
345
346
# Run async example
347
asyncio.run(main())
348
```
349
350
### Client Connection Management
351
352
```python
353
from xrpl.clients import JsonRpcClient, WebsocketClient
354
from xrpl.asyncio.clients import AsyncJsonRpcClient
355
import time
356
357
class ManagedClient:
358
"""Wrapper for client connection management."""
359
360
def __init__(self, url: str, client_type: str = "jsonrpc"):
361
self.url = url
362
self.client_type = client_type
363
self.client = None
364
365
def connect(self):
366
"""Establish connection."""
367
if self.client_type == "jsonrpc":
368
self.client = JsonRpcClient(self.url)
369
elif self.client_type == "websocket":
370
self.client = WebsocketClient(self.url)
371
self.client.open()
372
373
print(f"Connected to {self.url}")
374
return self.client
375
376
def disconnect(self):
377
"""Close connection."""
378
if self.client and self.client_type == "websocket":
379
self.client.close()
380
self.client = None
381
print("Disconnected")
382
383
def is_connected(self) -> bool:
384
"""Check connection status."""
385
if self.client_type == "websocket":
386
return self.client and self.client.is_open()
387
else:
388
return self.client is not None
389
390
# Usage
391
manager = ManagedClient("wss://s.altnet.rippletest.net:443", "websocket")
392
393
try:
394
client = manager.connect()
395
396
# Use client
397
from xrpl.models.requests import Ping
398
ping_response = client.send(Ping())
399
print(f"Ping successful: {ping_response.is_successful()}")
400
401
finally:
402
manager.disconnect()
403
```
404
405
### Error Handling and Retry Logic
406
407
```python
408
from xrpl.clients import JsonRpcClient
409
from xrpl.models.requests import AccountInfo
410
import time
411
import random
412
413
def request_with_retry(client, request, max_retries: int = 3, backoff_factor: float = 1.0):
414
"""Make request with exponential backoff retry logic."""
415
416
for attempt in range(max_retries + 1):
417
try:
418
response = client.request(request)
419
420
if response.is_successful():
421
return response
422
else:
423
print(f"Request failed (attempt {attempt + 1}): {response.result}")
424
425
except Exception as e:
426
print(f"Network error (attempt {attempt + 1}): {e}")
427
428
# Don't sleep after the last attempt
429
if attempt < max_retries:
430
sleep_time = backoff_factor * (2 ** attempt) + random.uniform(0, 1)
431
print(f"Retrying in {sleep_time:.2f} seconds...")
432
time.sleep(sleep_time)
433
434
raise Exception(f"Request failed after {max_retries + 1} attempts")
435
436
# Usage with multiple endpoints
437
endpoints = [
438
"https://s.altnet.rippletest.net:51234",
439
"https://testnet.xrpl-labs.com"
440
]
441
442
def request_with_failover(request, endpoints: list):
443
"""Make request with automatic endpoint failover."""
444
445
for i, endpoint in enumerate(endpoints):
446
try:
447
print(f"Trying endpoint {i + 1}: {endpoint}")
448
client = JsonRpcClient(endpoint)
449
return request_with_retry(client, request)
450
451
except Exception as e:
452
print(f"Endpoint {i + 1} failed: {e}")
453
if i == len(endpoints) - 1: # Last endpoint
454
raise Exception("All endpoints failed")
455
456
# Example usage
457
account_request = AccountInfo(account="rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH")
458
response = request_with_failover(account_request, endpoints)
459
print(f"Success: {response.result}")
460
```
461
462
## Exceptions
463
464
```python { .api }
465
class XRPLRequestFailureException(XRPLException):
466
"""Exception raised when XRPL network requests fail."""
467
```