Automate XRPL with Python

A short loop is the whole trick: wait for the next validated ledger, then do one clean thing. No mempool, no gas oracle, no retry theatre.

Updated 21 Aug 2026 · Follows the xrpl-py getting started guide

Keep the job small

XRPL was comfortable for automation long before most chains were. Settlement in seconds. Fees that stay tiny. JSON you can print. A script that checks a balance or sends a drop of Testnet XRP can stay under forty lines and still be honest.

Do not start on Mainnet. Do not put a seed in the repo. One process, one purpose.

Watch new ledgers

Poll validated every few seconds. When the index changes, a ledger closed. That is your cron.

import time
from xrpl.clients import JsonRpcClient
from xrpl.models.requests import Ledger

client = JsonRpcClient("https://s.altnet.rippletest.net:51234/")
last = None

while True:
    result = client.request(Ledger(ledger_index="validated")).result
    idx = result["ledger_index"]
    if idx != last:
        print("closed", idx)
        last = idx
    time.sleep(4)

Four seconds is slightly slower than a typical close. You will not miss a ledger for a balance job; you might skip one index if you sleep too long, so store last and catch up if you care about every sequence.

Watch one account

Same idea: read the account on each new ledger. Useful for “did my mint / payment land?” without sitting in an explorer.

from xrpl.account import get_balance
from xrpl.utils import drops_to_xrp

ADDRESS = "rYourTestnetAddress"

while True:
    result = client.request(Ledger(ledger_index="validated")).result
    idx = result["ledger_index"]
    if idx != last:
        drops = get_balance(ADDRESS, client)
        print(idx, drops_to_xrp(drops), "XRP")
        last = idx
    time.sleep(4)

Send 1 XRP on Testnet

Two faucet wallets, one payment, wait until it is validated. submit_and_wait fills sequence and fee, signs locally, submits, and blocks until the result is final.

from xrpl.models.transactions import Payment
from xrpl.transaction import submit_and_wait
from xrpl.utils import xrp_to_drops
from xrpl.wallet import generate_faucet_wallet

sender = generate_faucet_wallet(client, debug=True)
receiver = generate_faucet_wallet(client, debug=True)

payment = Payment(
    account=sender.address,
    destination=receiver.address,
    amount=xrp_to_drops(1),
)
response = submit_and_wait(payment, client, sender)
print(response.result.get("hash"))
print("validated", response.result.get("validated"))

Look up the hash on testnet.xrpl.org. If you see tesSUCCESS and validated: true, it happened.

Mainnet habits

  • Load the seed from the environment, never from a file you commit: Wallet.from_seed(os.environ["XRPL_SEED"]).
  • Start with a tiny amount. Confirm the destination address on an explorer first.
  • Exchanges need a destination tag. A normal r-address in Xaman does not.
  • Same code path as Testnet — only the URL and the money change.
import os
from xrpl.wallet import Wallet

# Mainnet read/write only after Testnet is boring
client = JsonRpcClient("https://s2.ripple.com:51234/")
wallet = Wallet.from_seed(os.environ["XRPL_SEED"])
print(wallet.address)

When to use WebSockets

If you outgrow polling, subscribe to the ledger stream with WebsocketClient. Most Pixelverse-style jobs never need it. JSON-RPC stays easier to log, retry, and run under Windows Task Scheduler or cron.

Holders who want a quieter node can swap the URL for the Pixelverse rippled endpoint after login.

Automation is how XRPL stays calm. A wallet is how you hold what you made.

xrpl-py setup Sign in with Xaman