0
# Utility Functions
1
2
Helper functions for unit conversions, time formatting, string encoding, NFT operations, and transaction analysis. The utils module provides essential utility functions that simplify common XRPL operations.
3
4
## Capabilities
5
6
### XRP Unit Conversion
7
8
Convert between XRP and drops (the smallest unit of XRP).
9
10
```python { .api }
11
from xrpl.utils import xrp_to_drops, drops_to_xrp
12
from decimal import Decimal
13
from typing import Union
14
15
def xrp_to_drops(xrp: Union[str, int, float, Decimal]) -> str:
16
"""
17
Convert XRP to drops (1 XRP = 1,000,000 drops).
18
19
Args:
20
xrp: XRP amount as string, int, float, or Decimal
21
22
Returns:
23
String representation of drops amount
24
25
Raises:
26
XRPRangeException: If XRP amount is invalid or out of range
27
"""
28
29
def drops_to_xrp(drops: Union[str, int]) -> Decimal:
30
"""
31
Convert drops to XRP (1,000,000 drops = 1 XRP).
32
33
Args:
34
drops: Drops amount as string or int
35
36
Returns:
37
Decimal representation of XRP amount
38
39
Raises:
40
XRPRangeException: If drops amount is invalid
41
"""
42
```
43
44
### Time Conversion
45
46
Convert between XRPL Ripple time and standard time formats.
47
48
```python { .api }
49
from xrpl.utils import (
50
ripple_time_to_datetime, datetime_to_ripple_time,
51
ripple_time_to_posix, posix_to_ripple_time
52
)
53
from datetime import datetime
54
55
def ripple_time_to_datetime(ripple_time: int) -> datetime:
56
"""
57
Convert XRPL Ripple time to Python datetime.
58
59
Args:
60
ripple_time: Seconds since Ripple Epoch (Jan 1, 2000 00:00 UTC)
61
62
Returns:
63
Python datetime object
64
65
Raises:
66
XRPLTimeRangeException: If ripple_time is invalid
67
"""
68
69
def datetime_to_ripple_time(dt: datetime) -> int:
70
"""
71
Convert Python datetime to XRPL Ripple time.
72
73
Args:
74
dt: Python datetime object
75
76
Returns:
77
Seconds since Ripple Epoch
78
79
Raises:
80
XRPLTimeRangeException: If datetime is before Ripple Epoch
81
"""
82
83
def ripple_time_to_posix(ripple_time: int) -> int:
84
"""
85
Convert XRPL Ripple time to POSIX timestamp.
86
87
Args:
88
ripple_time: Seconds since Ripple Epoch
89
90
Returns:
91
POSIX timestamp (seconds since Unix Epoch)
92
"""
93
94
def posix_to_ripple_time(posix_time: int) -> int:
95
"""
96
Convert POSIX timestamp to XRPL Ripple time.
97
98
Args:
99
posix_time: POSIX timestamp
100
101
Returns:
102
Seconds since Ripple Epoch
103
"""
104
```
105
106
### String Encoding
107
108
Convert between UTF-8 strings and hexadecimal encoding.
109
110
```python { .api }
111
from xrpl.utils import str_to_hex, hex_to_str
112
113
def str_to_hex(string: str) -> str:
114
"""
115
Convert UTF-8 string to hexadecimal encoding.
116
117
Args:
118
string: UTF-8 string to encode
119
120
Returns:
121
Hexadecimal representation of the string
122
"""
123
124
def hex_to_str(hex_string: str) -> str:
125
"""
126
Convert hexadecimal encoding to UTF-8 string.
127
128
Args:
129
hex_string: Hexadecimal string to decode
130
131
Returns:
132
Decoded UTF-8 string
133
134
Raises:
135
ValueError: If hex_string is not valid hexadecimal
136
"""
137
```
138
139
### NFToken Utilities
140
141
Extract and parse NFToken identifiers and related data.
142
143
```python { .api }
144
from xrpl.utils import get_nftoken_id, parse_nftoken_id
145
146
def get_nftoken_id(transaction: dict) -> str:
147
"""
148
Extract NFToken ID from a transaction.
149
150
Args:
151
transaction: Transaction object or metadata containing NFToken info
152
153
Returns:
154
64-character hex NFToken ID
155
156
Raises:
157
ValueError: If transaction doesn't contain NFToken ID
158
"""
159
160
def parse_nftoken_id(nftoken_id: str) -> dict:
161
"""
162
Parse NFToken ID to extract its components.
163
164
Args:
165
nftoken_id: 64-character hex NFToken ID
166
167
Returns:
168
Dictionary containing:
169
- flags: NFToken flags (16 bits)
170
- transfer_fee: Transfer fee (16 bits)
171
- issuer: Issuer account hash (160 bits)
172
- taxon: NFToken taxon (32 bits)
173
- sequence: Sequence number (32 bits)
174
"""
175
```
176
177
### Cross-Chain Utilities
178
179
Extract cross-chain bridge claim identifiers.
180
181
```python { .api }
182
from xrpl.utils import get_xchain_claim_id
183
184
def get_xchain_claim_id(transaction: dict) -> str:
185
"""
186
Extract cross-chain claim ID from a transaction.
187
188
Args:
189
transaction: Cross-chain transaction containing claim ID
190
191
Returns:
192
Cross-chain claim ID string
193
194
Raises:
195
ValueError: If transaction doesn't contain cross-chain claim ID
196
"""
197
```
198
199
### Transaction Analysis
200
201
Analyze transaction effects and balance changes.
202
203
```python { .api }
204
from xrpl.utils import get_balance_changes, get_final_balances, get_order_book_changes
205
206
def get_balance_changes(transaction: dict) -> dict:
207
"""
208
Calculate balance changes from a transaction.
209
210
Args:
211
transaction: Complete transaction with metadata
212
213
Returns:
214
Dictionary mapping addresses to their balance changes:
215
{
216
"rAddress1...": [
217
{"currency": "XRP", "value": "-1.000000"},
218
{"currency": "USD", "issuer": "rIssuer...", "value": "+100.50"}
219
],
220
"rAddress2...": [...]
221
}
222
"""
223
224
def get_final_balances(transaction: dict) -> dict:
225
"""
226
Get final balances after a transaction.
227
228
Args:
229
transaction: Complete transaction with metadata
230
231
Returns:
232
Dictionary mapping addresses to their final balances
233
"""
234
235
def get_order_book_changes(transaction: dict) -> dict:
236
"""
237
Extract order book changes from a transaction.
238
239
Args:
240
transaction: Transaction affecting order books (e.g., OfferCreate, Payment)
241
242
Returns:
243
Dictionary describing order book modifications:
244
{
245
"offers_created": [...],
246
"offers_cancelled": [...],
247
"offers_filled": [...]
248
}
249
"""
250
```
251
252
## Usage Examples
253
254
### XRP Unit Conversions
255
256
```python
257
from xrpl.utils import xrp_to_drops, drops_to_xrp
258
from decimal import Decimal
259
260
# Convert XRP to drops
261
print("=== XRP to Drops ===")
262
xrp_amounts = [1, 1.5, "2.123456", Decimal("0.000001")]
263
264
for xrp in xrp_amounts:
265
drops = xrp_to_drops(xrp)
266
print(f"{xrp} XRP = {drops} drops")
267
268
# Convert drops to XRP
269
print("\n=== Drops to XRP ===")
270
drops_amounts = ["1000000", "1500000", "2123456", "1"]
271
272
for drops in drops_amounts:
273
xrp = drops_to_xrp(drops)
274
print(f"{drops} drops = {xrp} XRP")
275
276
# Practical conversion helper
277
def format_xrp_amount(drops_str: str) -> str:
278
"""Format drops as readable XRP amount."""
279
xrp = drops_to_xrp(drops_str)
280
return f"{xrp:.6f} XRP ({drops_str} drops)"
281
282
# Examples
283
amounts = ["1000000", "1500000", "123", "999999999999"]
284
for amount in amounts:
285
print(format_xrp_amount(amount))
286
```
287
288
### Time Conversions
289
290
```python
291
from xrpl.utils import (
292
ripple_time_to_datetime, datetime_to_ripple_time,
293
ripple_time_to_posix, posix_to_ripple_time
294
)
295
from datetime import datetime, timezone
296
import time
297
298
# Current time conversions
299
print("=== Time Conversions ===")
300
now = datetime.now(timezone.utc)
301
current_posix = int(time.time())
302
303
print(f"Current datetime: {now}")
304
print(f"Current POSIX: {current_posix}")
305
306
# Convert to Ripple time
307
ripple_now = datetime_to_ripple_time(now)
308
ripple_from_posix = posix_to_ripple_time(current_posix)
309
310
print(f"Ripple time (from datetime): {ripple_now}")
311
print(f"Ripple time (from POSIX): {ripple_from_posix}")
312
313
# Convert back
314
dt_from_ripple = ripple_time_to_datetime(ripple_now)
315
posix_from_ripple = ripple_time_to_posix(ripple_now)
316
317
print(f"Datetime from Ripple: {dt_from_ripple}")
318
print(f"POSIX from Ripple: {posix_from_ripple}")
319
320
# Historical dates
321
print("\n=== Historical Dates ===")
322
ripple_epoch = 0 # Ripple Epoch: Jan 1, 2000 00:00 UTC
323
ripple_epoch_dt = ripple_time_to_datetime(ripple_epoch)
324
print(f"Ripple Epoch: {ripple_epoch_dt}")
325
326
# Common transaction time handling
327
def format_transaction_time(ripple_time: int) -> str:
328
"""Format Ripple time for display."""
329
dt = ripple_time_to_datetime(ripple_time)
330
return dt.strftime("%Y-%m-%d %H:%M:%S UTC")
331
332
# Example transaction times
333
tx_times = [746425740, 746426000, 746430000] # Example Ripple timestamps
334
for rt in tx_times:
335
formatted = format_transaction_time(rt)
336
print(f"Transaction time {rt}: {formatted}")
337
```
338
339
### String Encoding
340
341
```python
342
from xrpl.utils import str_to_hex, hex_to_str
343
344
# Text to hex conversion
345
print("=== String to Hex ===")
346
texts = ["Hello, XRPL!", "π To the moon!", "UTF-8 encoding test: éñüñ"]
347
348
for text in texts:
349
hex_encoded = str_to_hex(text)
350
print(f"'{text}' β {hex_encoded}")
351
352
# Hex to text conversion
353
print("\n=== Hex to String ===")
354
hex_strings = [
355
"48656c6c6f2c2058524050214c21", # "Hello, XRPL!"
356
"f09f9a80204d6f6f6e212046544621", # "π Moon! FTC!"
357
"546573742064617461" # "Test data"
358
]
359
360
for hex_str in hex_strings:
361
try:
362
decoded = hex_to_str(hex_str)
363
print(f"{hex_str} β '{decoded}'")
364
except ValueError as e:
365
print(f"{hex_str} β Error: {e}")
366
367
# Memo encoding/decoding helper
368
def create_memo_data(text: str) -> dict:
369
"""Create memo data structure with hex-encoded text."""
370
return {
371
"MemoData": str_to_hex(text),
372
"MemoType": str_to_hex("text/plain"),
373
"MemoFormat": str_to_hex("text")
374
}
375
376
def decode_memo_data(memo: dict) -> dict:
377
"""Decode memo data structure."""
378
decoded = {}
379
if "MemoData" in memo:
380
decoded["data"] = hex_to_str(memo["MemoData"])
381
if "MemoType" in memo:
382
decoded["type"] = hex_to_str(memo["MemoType"])
383
if "MemoFormat" in memo:
384
decoded["format"] = hex_to_str(memo["MemoFormat"])
385
return decoded
386
387
# Example usage
388
memo = create_memo_data("Hello from Python!")
389
print(f"\nEncoded memo: {memo}")
390
391
decoded = decode_memo_data(memo)
392
print(f"Decoded memo: {decoded}")
393
```
394
395
### NFToken Operations
396
397
```python
398
from xrpl.utils import get_nftoken_id, parse_nftoken_id
399
400
# Example NFToken transaction (simplified)
401
nft_mint_transaction = {
402
"meta": {
403
"CreatedNode": {
404
"NewFields": {
405
"NFTokenID": "000B013A95F14B0044F78A264E41713C64B5F89242540EE208C3098E00000D65"
406
}
407
}
408
}
409
}
410
411
# Extract NFToken ID
412
try:
413
token_id = get_nftoken_id(nft_mint_transaction)
414
print(f"NFToken ID: {token_id}")
415
416
# Parse the ID components
417
parsed = parse_nftoken_id(token_id)
418
print(f"Parsed NFToken ID:")
419
print(f" Flags: {parsed['flags']}")
420
print(f" Transfer Fee: {parsed['transfer_fee']}")
421
print(f" Issuer: {parsed['issuer']}")
422
print(f" Taxon: {parsed['taxon']}")
423
print(f" Sequence: {parsed['sequence']}")
424
425
except ValueError as e:
426
print(f"Error extracting NFToken ID: {e}")
427
428
# NFToken ID analysis helper
429
def analyze_nftoken_id(token_id: str):
430
"""Analyze and display NFToken ID components."""
431
try:
432
components = parse_nftoken_id(token_id)
433
434
print(f"NFToken Analysis: {token_id}")
435
print("=" * 50)
436
print(f"Flags: 0x{components['flags']:04X}")
437
print(f"Transfer Fee: {components['transfer_fee'] / 100000:.3f}%")
438
print(f"Issuer Hash: {components['issuer']}")
439
print(f"Taxon: {components['taxon']}")
440
print(f"Sequence: {components['sequence']}")
441
442
# Decode flags (example interpretations)
443
flags = components['flags']
444
print(f"\nFlag Analysis:")
445
print(f" Burnable: {'Yes' if flags & 0x0001 else 'No'}")
446
print(f" Only XRP: {'Yes' if flags & 0x0002 else 'No'}")
447
print(f" Trustline: {'Yes' if flags & 0x0004 else 'No'}")
448
print(f" Transferable: {'Yes' if flags & 0x0008 else 'No'}")
449
450
except Exception as e:
451
print(f"Error analyzing NFToken ID: {e}")
452
453
# Example analysis
454
example_ids = [
455
"000B013A95F14B0044F78A264E41713C64B5F89242540EE208C3098E00000D65",
456
"000800204E494C0000000000000000000000000000000000000000000000234"
457
]
458
459
for token_id in example_ids:
460
analyze_nftoken_id(token_id)
461
print()
462
```
463
464
### Transaction Analysis
465
466
```python
467
from xrpl.utils import get_balance_changes, get_final_balances
468
469
# Example transaction with metadata (simplified)
470
payment_transaction = {
471
"transaction": {
472
"Account": "rSender...",
473
"Destination": "rReceiver...",
474
"Amount": "1000000",
475
"TransactionType": "Payment"
476
},
477
"meta": {
478
"AffectedNodes": [
479
{
480
"ModifiedNode": {
481
"FinalFields": {
482
"Account": "rSender...",
483
"Balance": "99000000"
484
},
485
"PreviousFields": {
486
"Balance": "100000000"
487
},
488
"LedgerEntryType": "AccountRoot"
489
}
490
},
491
{
492
"ModifiedNode": {
493
"FinalFields": {
494
"Account": "rReceiver...",
495
"Balance": "1000000"
496
},
497
"PreviousFields": {
498
"Balance": "0"
499
},
500
"LedgerEntryType": "AccountRoot"
501
}
502
}
503
]
504
}
505
}
506
507
# Analyze balance changes
508
try:
509
balance_changes = get_balance_changes(payment_transaction)
510
print("Balance Changes:")
511
for address, changes in balance_changes.items():
512
print(f" {address[:12]}...")
513
for change in changes:
514
currency = change.get("currency", "XRP")
515
value = change["value"]
516
if currency == "XRP":
517
print(f" {value} XRP")
518
else:
519
issuer = change.get("issuer", "")
520
print(f" {value} {currency} (issuer: {issuer[:12]}...)")
521
522
except Exception as e:
523
print(f"Error analyzing balance changes: {e}")
524
525
# Transaction summary helper
526
def summarize_transaction(tx_with_meta: dict) -> dict:
527
"""Create transaction summary with key information."""
528
tx = tx_with_meta.get("transaction", {})
529
meta = tx_with_meta.get("meta", {})
530
531
summary = {
532
"type": tx.get("TransactionType", "Unknown"),
533
"account": tx.get("Account", ""),
534
"fee": tx.get("Fee", "0"),
535
"sequence": tx.get("Sequence", 0),
536
"successful": meta.get("TransactionResult") == "tesSUCCESS",
537
"balance_changes": {},
538
"ledger_index": meta.get("TransactionIndex", 0)
539
}
540
541
# Add balance changes if available
542
try:
543
summary["balance_changes"] = get_balance_changes(tx_with_meta)
544
except:
545
pass
546
547
# Add type-specific details
548
if summary["type"] == "Payment":
549
summary["destination"] = tx.get("Destination", "")
550
summary["amount"] = tx.get("Amount", "")
551
elif summary["type"] == "OfferCreate":
552
summary["taker_gets"] = tx.get("TakerGets", "")
553
summary["taker_pays"] = tx.get("TakerPays", "")
554
555
return summary
556
557
# Example usage
558
summary = summarize_transaction(payment_transaction)
559
print(f"\nTransaction Summary:")
560
print(f"Type: {summary['type']}")
561
print(f"Account: {summary['account']}")
562
print(f"Successful: {summary['successful']}")
563
print(f"Fee: {summary['fee']} drops")
564
565
if summary['type'] == 'Payment':
566
print(f"Destination: {summary['destination']}")
567
print(f"Amount: {summary['amount']} drops")
568
```
569
570
### Batch Utility Operations
571
572
```python
573
from xrpl.utils import xrp_to_drops, drops_to_xrp, str_to_hex
574
from decimal import Decimal
575
576
def batch_convert_amounts(amounts: list, to_drops: bool = True) -> list:
577
"""Convert multiple amounts between XRP and drops."""
578
results = []
579
for amount in amounts:
580
try:
581
if to_drops:
582
converted = xrp_to_drops(amount)
583
else:
584
converted = str(drops_to_xrp(amount))
585
results.append({"original": amount, "converted": converted, "success": True})
586
except Exception as e:
587
results.append({"original": amount, "error": str(e), "success": False})
588
return results
589
590
def batch_encode_strings(strings: list) -> list:
591
"""Encode multiple strings to hex."""
592
return [{"original": s, "hex": str_to_hex(s)} for s in strings]
593
594
# Example batch operations
595
xrp_amounts = [1, 2.5, "0.000001", Decimal("10.123456")]
596
print("Batch XRP to Drops Conversion:")
597
conversions = batch_convert_amounts(xrp_amounts, to_drops=True)
598
for result in conversions:
599
if result["success"]:
600
print(f" {result['original']} XRP β {result['converted']} drops")
601
else:
602
print(f" {result['original']} β Error: {result['error']}")
603
604
# Batch string encoding
605
memo_texts = ["Transaction #1", "Payment memo", "π Success!"]
606
print("\nBatch String Encoding:")
607
encoded = batch_encode_strings(memo_texts)
608
for item in encoded:
609
print(f" '{item['original']}' β {item['hex']}")
610
```
611
612
## Exceptions
613
614
```python { .api }
615
class XRPRangeException(XRPLException):
616
"""Exception for invalid XRP amounts or values outside acceptable ranges."""
617
618
class XRPLTimeRangeException(XRPLException):
619
"""Exception for invalid time values or dates outside XRPL time ranges."""
620
```
621
622
## Utility Function Categories
623
624
```python { .api }
625
# XRP Conversions
626
xrp_to_drops(xrp) -> str
627
drops_to_xrp(drops) -> Decimal
628
629
# Time Conversions
630
ripple_time_to_datetime(ripple_time) -> datetime
631
datetime_to_ripple_time(datetime) -> int
632
ripple_time_to_posix(ripple_time) -> int
633
posix_to_ripple_time(posix_time) -> int
634
635
# String Encoding
636
str_to_hex(string) -> str
637
hex_to_str(hex_string) -> str
638
639
# NFToken Operations
640
get_nftoken_id(transaction) -> str
641
parse_nftoken_id(nftoken_id) -> dict
642
643
# Cross-Chain Operations
644
get_xchain_claim_id(transaction) -> str
645
646
# Transaction Analysis
647
get_balance_changes(transaction) -> dict
648
get_final_balances(transaction) -> dict
649
get_order_book_changes(transaction) -> dict
650
```