A complete Python library for interacting with the XRP Ledger blockchain, providing transaction creation, account management, and comprehensive XRPL protocol support
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.
Convert between XRP and drops (the smallest unit of XRP).
from xrpl.utils import xrp_to_drops, drops_to_xrp
from decimal import Decimal
from typing import Union
def xrp_to_drops(xrp: Union[str, int, float, Decimal]) -> str:
"""
Convert XRP to drops (1 XRP = 1,000,000 drops).
Args:
xrp: XRP amount as string, int, float, or Decimal
Returns:
String representation of drops amount
Raises:
XRPRangeException: If XRP amount is invalid or out of range
"""
def drops_to_xrp(drops: Union[str, int]) -> Decimal:
"""
Convert drops to XRP (1,000,000 drops = 1 XRP).
Args:
drops: Drops amount as string or int
Returns:
Decimal representation of XRP amount
Raises:
XRPRangeException: If drops amount is invalid
"""Convert between XRPL Ripple time and standard time formats.
from xrpl.utils import (
ripple_time_to_datetime, datetime_to_ripple_time,
ripple_time_to_posix, posix_to_ripple_time
)
from datetime import datetime
def ripple_time_to_datetime(ripple_time: int) -> datetime:
"""
Convert XRPL Ripple time to Python datetime.
Args:
ripple_time: Seconds since Ripple Epoch (Jan 1, 2000 00:00 UTC)
Returns:
Python datetime object
Raises:
XRPLTimeRangeException: If ripple_time is invalid
"""
def datetime_to_ripple_time(dt: datetime) -> int:
"""
Convert Python datetime to XRPL Ripple time.
Args:
dt: Python datetime object
Returns:
Seconds since Ripple Epoch
Raises:
XRPLTimeRangeException: If datetime is before Ripple Epoch
"""
def ripple_time_to_posix(ripple_time: int) -> int:
"""
Convert XRPL Ripple time to POSIX timestamp.
Args:
ripple_time: Seconds since Ripple Epoch
Returns:
POSIX timestamp (seconds since Unix Epoch)
"""
def posix_to_ripple_time(posix_time: int) -> int:
"""
Convert POSIX timestamp to XRPL Ripple time.
Args:
posix_time: POSIX timestamp
Returns:
Seconds since Ripple Epoch
"""Convert between UTF-8 strings and hexadecimal encoding.
from xrpl.utils import str_to_hex, hex_to_str
def str_to_hex(string: str) -> str:
"""
Convert UTF-8 string to hexadecimal encoding.
Args:
string: UTF-8 string to encode
Returns:
Hexadecimal representation of the string
"""
def hex_to_str(hex_string: str) -> str:
"""
Convert hexadecimal encoding to UTF-8 string.
Args:
hex_string: Hexadecimal string to decode
Returns:
Decoded UTF-8 string
Raises:
ValueError: If hex_string is not valid hexadecimal
"""Extract and parse NFToken identifiers and related data.
from xrpl.utils import get_nftoken_id, parse_nftoken_id
def get_nftoken_id(transaction: dict) -> str:
"""
Extract NFToken ID from a transaction.
Args:
transaction: Transaction object or metadata containing NFToken info
Returns:
64-character hex NFToken ID
Raises:
ValueError: If transaction doesn't contain NFToken ID
"""
def parse_nftoken_id(nftoken_id: str) -> dict:
"""
Parse NFToken ID to extract its components.
Args:
nftoken_id: 64-character hex NFToken ID
Returns:
Dictionary containing:
- flags: NFToken flags (16 bits)
- transfer_fee: Transfer fee (16 bits)
- issuer: Issuer account hash (160 bits)
- taxon: NFToken taxon (32 bits)
- sequence: Sequence number (32 bits)
"""Extract cross-chain bridge claim identifiers.
from xrpl.utils import get_xchain_claim_id
def get_xchain_claim_id(transaction: dict) -> str:
"""
Extract cross-chain claim ID from a transaction.
Args:
transaction: Cross-chain transaction containing claim ID
Returns:
Cross-chain claim ID string
Raises:
ValueError: If transaction doesn't contain cross-chain claim ID
"""Analyze transaction effects and balance changes.
from xrpl.utils import get_balance_changes, get_final_balances, get_order_book_changes
def get_balance_changes(transaction: dict) -> dict:
"""
Calculate balance changes from a transaction.
Args:
transaction: Complete transaction with metadata
Returns:
Dictionary mapping addresses to their balance changes:
{
"rAddress1...": [
{"currency": "XRP", "value": "-1.000000"},
{"currency": "USD", "issuer": "rIssuer...", "value": "+100.50"}
],
"rAddress2...": [...]
}
"""
def get_final_balances(transaction: dict) -> dict:
"""
Get final balances after a transaction.
Args:
transaction: Complete transaction with metadata
Returns:
Dictionary mapping addresses to their final balances
"""
def get_order_book_changes(transaction: dict) -> dict:
"""
Extract order book changes from a transaction.
Args:
transaction: Transaction affecting order books (e.g., OfferCreate, Payment)
Returns:
Dictionary describing order book modifications:
{
"offers_created": [...],
"offers_cancelled": [...],
"offers_filled": [...]
}
"""from xrpl.utils import xrp_to_drops, drops_to_xrp
from decimal import Decimal
# Convert XRP to drops
print("=== XRP to Drops ===")
xrp_amounts = [1, 1.5, "2.123456", Decimal("0.000001")]
for xrp in xrp_amounts:
drops = xrp_to_drops(xrp)
print(f"{xrp} XRP = {drops} drops")
# Convert drops to XRP
print("\n=== Drops to XRP ===")
drops_amounts = ["1000000", "1500000", "2123456", "1"]
for drops in drops_amounts:
xrp = drops_to_xrp(drops)
print(f"{drops} drops = {xrp} XRP")
# Practical conversion helper
def format_xrp_amount(drops_str: str) -> str:
"""Format drops as readable XRP amount."""
xrp = drops_to_xrp(drops_str)
return f"{xrp:.6f} XRP ({drops_str} drops)"
# Examples
amounts = ["1000000", "1500000", "123", "999999999999"]
for amount in amounts:
print(format_xrp_amount(amount))from xrpl.utils import (
ripple_time_to_datetime, datetime_to_ripple_time,
ripple_time_to_posix, posix_to_ripple_time
)
from datetime import datetime, timezone
import time
# Current time conversions
print("=== Time Conversions ===")
now = datetime.now(timezone.utc)
current_posix = int(time.time())
print(f"Current datetime: {now}")
print(f"Current POSIX: {current_posix}")
# Convert to Ripple time
ripple_now = datetime_to_ripple_time(now)
ripple_from_posix = posix_to_ripple_time(current_posix)
print(f"Ripple time (from datetime): {ripple_now}")
print(f"Ripple time (from POSIX): {ripple_from_posix}")
# Convert back
dt_from_ripple = ripple_time_to_datetime(ripple_now)
posix_from_ripple = ripple_time_to_posix(ripple_now)
print(f"Datetime from Ripple: {dt_from_ripple}")
print(f"POSIX from Ripple: {posix_from_ripple}")
# Historical dates
print("\n=== Historical Dates ===")
ripple_epoch = 0 # Ripple Epoch: Jan 1, 2000 00:00 UTC
ripple_epoch_dt = ripple_time_to_datetime(ripple_epoch)
print(f"Ripple Epoch: {ripple_epoch_dt}")
# Common transaction time handling
def format_transaction_time(ripple_time: int) -> str:
"""Format Ripple time for display."""
dt = ripple_time_to_datetime(ripple_time)
return dt.strftime("%Y-%m-%d %H:%M:%S UTC")
# Example transaction times
tx_times = [746425740, 746426000, 746430000] # Example Ripple timestamps
for rt in tx_times:
formatted = format_transaction_time(rt)
print(f"Transaction time {rt}: {formatted}")from xrpl.utils import str_to_hex, hex_to_str
# Text to hex conversion
print("=== String to Hex ===")
texts = ["Hello, XRPL!", "🚀 To the moon!", "UTF-8 encoding test: éñüñ"]
for text in texts:
hex_encoded = str_to_hex(text)
print(f"'{text}' → {hex_encoded}")
# Hex to text conversion
print("\n=== Hex to String ===")
hex_strings = [
"48656c6c6f2c2058524050214c21", # "Hello, XRPL!"
"f09f9a80204d6f6f6e212046544621", # "🚀 Moon! FTC!"
"546573742064617461" # "Test data"
]
for hex_str in hex_strings:
try:
decoded = hex_to_str(hex_str)
print(f"{hex_str} → '{decoded}'")
except ValueError as e:
print(f"{hex_str} → Error: {e}")
# Memo encoding/decoding helper
def create_memo_data(text: str) -> dict:
"""Create memo data structure with hex-encoded text."""
return {
"MemoData": str_to_hex(text),
"MemoType": str_to_hex("text/plain"),
"MemoFormat": str_to_hex("text")
}
def decode_memo_data(memo: dict) -> dict:
"""Decode memo data structure."""
decoded = {}
if "MemoData" in memo:
decoded["data"] = hex_to_str(memo["MemoData"])
if "MemoType" in memo:
decoded["type"] = hex_to_str(memo["MemoType"])
if "MemoFormat" in memo:
decoded["format"] = hex_to_str(memo["MemoFormat"])
return decoded
# Example usage
memo = create_memo_data("Hello from Python!")
print(f"\nEncoded memo: {memo}")
decoded = decode_memo_data(memo)
print(f"Decoded memo: {decoded}")from xrpl.utils import get_nftoken_id, parse_nftoken_id
# Example NFToken transaction (simplified)
nft_mint_transaction = {
"meta": {
"CreatedNode": {
"NewFields": {
"NFTokenID": "000B013A95F14B0044F78A264E41713C64B5F89242540EE208C3098E00000D65"
}
}
}
}
# Extract NFToken ID
try:
token_id = get_nftoken_id(nft_mint_transaction)
print(f"NFToken ID: {token_id}")
# Parse the ID components
parsed = parse_nftoken_id(token_id)
print(f"Parsed NFToken ID:")
print(f" Flags: {parsed['flags']}")
print(f" Transfer Fee: {parsed['transfer_fee']}")
print(f" Issuer: {parsed['issuer']}")
print(f" Taxon: {parsed['taxon']}")
print(f" Sequence: {parsed['sequence']}")
except ValueError as e:
print(f"Error extracting NFToken ID: {e}")
# NFToken ID analysis helper
def analyze_nftoken_id(token_id: str):
"""Analyze and display NFToken ID components."""
try:
components = parse_nftoken_id(token_id)
print(f"NFToken Analysis: {token_id}")
print("=" * 50)
print(f"Flags: 0x{components['flags']:04X}")
print(f"Transfer Fee: {components['transfer_fee'] / 100000:.3f}%")
print(f"Issuer Hash: {components['issuer']}")
print(f"Taxon: {components['taxon']}")
print(f"Sequence: {components['sequence']}")
# Decode flags (example interpretations)
flags = components['flags']
print(f"\nFlag Analysis:")
print(f" Burnable: {'Yes' if flags & 0x0001 else 'No'}")
print(f" Only XRP: {'Yes' if flags & 0x0002 else 'No'}")
print(f" Trustline: {'Yes' if flags & 0x0004 else 'No'}")
print(f" Transferable: {'Yes' if flags & 0x0008 else 'No'}")
except Exception as e:
print(f"Error analyzing NFToken ID: {e}")
# Example analysis
example_ids = [
"000B013A95F14B0044F78A264E41713C64B5F89242540EE208C3098E00000D65",
"000800204E494C0000000000000000000000000000000000000000000000234"
]
for token_id in example_ids:
analyze_nftoken_id(token_id)
print()from xrpl.utils import get_balance_changes, get_final_balances
# Example transaction with metadata (simplified)
payment_transaction = {
"transaction": {
"Account": "rSender...",
"Destination": "rReceiver...",
"Amount": "1000000",
"TransactionType": "Payment"
},
"meta": {
"AffectedNodes": [
{
"ModifiedNode": {
"FinalFields": {
"Account": "rSender...",
"Balance": "99000000"
},
"PreviousFields": {
"Balance": "100000000"
},
"LedgerEntryType": "AccountRoot"
}
},
{
"ModifiedNode": {
"FinalFields": {
"Account": "rReceiver...",
"Balance": "1000000"
},
"PreviousFields": {
"Balance": "0"
},
"LedgerEntryType": "AccountRoot"
}
}
]
}
}
# Analyze balance changes
try:
balance_changes = get_balance_changes(payment_transaction)
print("Balance Changes:")
for address, changes in balance_changes.items():
print(f" {address[:12]}...")
for change in changes:
currency = change.get("currency", "XRP")
value = change["value"]
if currency == "XRP":
print(f" {value} XRP")
else:
issuer = change.get("issuer", "")
print(f" {value} {currency} (issuer: {issuer[:12]}...)")
except Exception as e:
print(f"Error analyzing balance changes: {e}")
# Transaction summary helper
def summarize_transaction(tx_with_meta: dict) -> dict:
"""Create transaction summary with key information."""
tx = tx_with_meta.get("transaction", {})
meta = tx_with_meta.get("meta", {})
summary = {
"type": tx.get("TransactionType", "Unknown"),
"account": tx.get("Account", ""),
"fee": tx.get("Fee", "0"),
"sequence": tx.get("Sequence", 0),
"successful": meta.get("TransactionResult") == "tesSUCCESS",
"balance_changes": {},
"ledger_index": meta.get("TransactionIndex", 0)
}
# Add balance changes if available
try:
summary["balance_changes"] = get_balance_changes(tx_with_meta)
except:
pass
# Add type-specific details
if summary["type"] == "Payment":
summary["destination"] = tx.get("Destination", "")
summary["amount"] = tx.get("Amount", "")
elif summary["type"] == "OfferCreate":
summary["taker_gets"] = tx.get("TakerGets", "")
summary["taker_pays"] = tx.get("TakerPays", "")
return summary
# Example usage
summary = summarize_transaction(payment_transaction)
print(f"\nTransaction Summary:")
print(f"Type: {summary['type']}")
print(f"Account: {summary['account']}")
print(f"Successful: {summary['successful']}")
print(f"Fee: {summary['fee']} drops")
if summary['type'] == 'Payment':
print(f"Destination: {summary['destination']}")
print(f"Amount: {summary['amount']} drops")from xrpl.utils import xrp_to_drops, drops_to_xrp, str_to_hex
from decimal import Decimal
def batch_convert_amounts(amounts: list, to_drops: bool = True) -> list:
"""Convert multiple amounts between XRP and drops."""
results = []
for amount in amounts:
try:
if to_drops:
converted = xrp_to_drops(amount)
else:
converted = str(drops_to_xrp(amount))
results.append({"original": amount, "converted": converted, "success": True})
except Exception as e:
results.append({"original": amount, "error": str(e), "success": False})
return results
def batch_encode_strings(strings: list) -> list:
"""Encode multiple strings to hex."""
return [{"original": s, "hex": str_to_hex(s)} for s in strings]
# Example batch operations
xrp_amounts = [1, 2.5, "0.000001", Decimal("10.123456")]
print("Batch XRP to Drops Conversion:")
conversions = batch_convert_amounts(xrp_amounts, to_drops=True)
for result in conversions:
if result["success"]:
print(f" {result['original']} XRP → {result['converted']} drops")
else:
print(f" {result['original']} → Error: {result['error']}")
# Batch string encoding
memo_texts = ["Transaction #1", "Payment memo", "🎉 Success!"]
print("\nBatch String Encoding:")
encoded = batch_encode_strings(memo_texts)
for item in encoded:
print(f" '{item['original']}' → {item['hex']}")class XRPRangeException(XRPLException):
"""Exception for invalid XRP amounts or values outside acceptable ranges."""
class XRPLTimeRangeException(XRPLException):
"""Exception for invalid time values or dates outside XRPL time ranges."""# XRP Conversions
xrp_to_drops(xrp) -> str
drops_to_xrp(drops) -> Decimal
# Time Conversions
ripple_time_to_datetime(ripple_time) -> datetime
datetime_to_ripple_time(datetime) -> int
ripple_time_to_posix(ripple_time) -> int
posix_to_ripple_time(posix_time) -> int
# String Encoding
str_to_hex(string) -> str
hex_to_str(hex_string) -> str
# NFToken Operations
get_nftoken_id(transaction) -> str
parse_nftoken_id(nftoken_id) -> dict
# Cross-Chain Operations
get_xchain_claim_id(transaction) -> str
# Transaction Analysis
get_balance_changes(transaction) -> dict
get_final_balances(transaction) -> dict
get_order_book_changes(transaction) -> dictInstall with Tessl CLI
npx tessl i tessl/pypi-xrpl-py