Trade NFTs on the XRP Ledger without trusting the counterparty. Payment locks in escrow when the buyer commits — it releases automatically only once the NFT is confirmed in the buyer's wallet. Neither party can take the money and run.
Standard NFT trades on any chain carry counterparty risk: the buyer pays first and hopes the NFT arrives, or the seller transfers first and hopes payment follows. Off-chain agreements, trusted escrow services, and multi-sig setups all require some form of trust.
XRPL's native escrow operates at the protocol layer — not a smart contract, the base ledger itself. Combined with the AgentTrust referee, you get a two-sided atomic trade:
Buyer funds are held in XRPL crypto-condition escrow at the moment of commitment — not held by any platform, not in a hot wallet, locked in the ledger itself.
The seller submits proof of NFT transfer (the on-chain token ID in the buyer's wallet). The AI referee verifies the chain state and releases payment automatically.
Buyer can't receive the NFT and claim non-delivery. Seller can't receive payment and not transfer. The escrow enforces the deal atomically.
XRPL transactions cost ~0.00001 XRP — not $5–50 in gas. The AgentTrust protocol fee is $0.10 per escrow, payable in XRP, RLUSD, or USDC.
Platforms like Coinbase NFT or OpenSea let you buy and sell NFTs — but they rely on centralised custody and infrastructure you can't call from a script. AgentTrust is a REST API that any agent or developer can use directly.
Centralised marketplaces hold your funds during a trade. AgentTrust escrow is XRPL native — the ledger holds the payment, not a company. No counterparty default, no platform insolvency risk.
Marketplaces require OAuth, browser sessions, and user accounts. AgentTrust is three API calls. Any AI agent with an XRPL wallet can create an escrow, transfer an NFT, and collect payment — fully autonomously, no login flow.
Require the NFT from a specific verified issuer (using the XRPL Issuer Registry), enforce metadata constraints, or combine with other trust layers — domain verification, Verifiable Credentials, wallet trust score. No marketplace offers programmable release conditions.
Works with any XRPL NFT — not just ones listed on a marketplace. Two parties can agree a deal anywhere (an agent marketplace, a chat, an API) and settle it through AgentTrust. No listing fee, no platform cut.
Layer 1 settlement. Payment and NFT transfer both settle on the XRPL ledger itself — not a database record, not a smart contract on top. Final, irreversible, and auditable by anyone. This is what makes it safe for agents to transact without a human in the loop.
What the AI referee checks: The task description you write into the escrow becomes the verification spec. Write it as: "NFT [token ID] issued by [issuer address] must be owned by [buyer address] at the time of evaluation." The referee queries the XRPL ledger directly and checks the current owner of that token ID.
Buyer and seller agree on the XRPL NFT token ID (a 64-character hex string, e.g. 000800006B6B…), the price in XRP or RLUSD, and a cancellation window (e.g. 72 hours if the NFT never arrives). The token ID uniquely identifies the specific NFT on the ledger.
The buyer pays the $0.10 protocol fee and calls POST /escrow/generate with the task description encoding the expected NFT ownership. The resulting EscrowCreate transaction is submitted on-chain, locking the funds.
Seller uses XRPL's NFTokenCreateOffer / NFTokenAcceptOffer flow to transfer the NFT to the buyer's wallet, then calls POST /evaluate with the token ID as proof. On PASS, payment releases automatically.
Security: Never put a wallet seed in browser JavaScript. Run this server-side or in your agent's trusted environment.
# pip install xrpl-py httpx
import httpx, secrets
from xrpl.clients import JsonRpcClient
from xrpl.models.transactions import Payment, EscrowCreate
from xrpl.wallet import Wallet
from xrpl.utils import xrp_to_drops
from xrpl.transaction import submit_and_wait
REFEREE = "https://mcp.cryptovault.co.uk"
PROTOCOL_FEE = "rmcSrkpZ2i2kuvtCPeTVetee9SixP4djR"
XRPL_NODE = "https://s1.ripple.com:51234/"
buyer_wallet = Wallet.from_seed("sBUYER_SEED_HERE")
seller_address = "rSELLER_ADDRESS_HERE"
client = JsonRpcClient(XRPL_NODE)
# Agree these off-chain with the seller:
NFT_TOKEN_ID = "000800006B6B..." # 64-char hex NFT token ID
PRICE_XRP = 50.0
CANCEL_HRS = 72
# Build the task description — this is what the referee will verify
task_desc = (
f"NFT Delivery-vs-Payment escrow.\n"
f"NFT token ID: {NFT_TOKEN_ID}\n"
f"Must be owned by buyer wallet: {buyer_wallet.address}\n"
f"Payment releases when the NFT is confirmed in the buyer's wallet."
)
# Step 1: Pay the $0.10 protocol fee
fee_tx = Payment(
account = buyer_wallet.address,
amount = xrp_to_drops(0.1),
destination = PROTOCOL_FEE,
)
fee_hash = submit_and_wait(fee_tx, client, buyer_wallet).result["hash"]
print(f"Protocol fee tx: {fee_hash}")
# Step 2: Generate escrow parameters from AgentTrust
escrow_id = f"NFT-{secrets.token_hex(4).upper()}"
params = httpx.post(f"{REFEREE}/escrow/generate", json={
"escrow_id": escrow_id,
"fee_hash": fee_hash,
"buyer_name": "Alice",
"buyer_address": buyer_wallet.address,
"worker_address": seller_address,
"task_description": task_desc,
"amount_xrp": PRICE_XRP,
"cancel_after_hrs": CANCEL_HRS,
}, timeout=30).json()
# Step 3: Submit the EscrowCreate on-chain
escrow_tx = EscrowCreate(
account = buyer_wallet.address,
destination = seller_address,
amount = xrp_to_drops(PRICE_XRP),
condition = params["condition"],
finish_after = params["finish_after_ripple"],
cancel_after = params["cancel_after_ripple"],
)
tx_hash = submit_and_wait(escrow_tx, client, buyer_wallet).result["hash"]
print(f"Escrow created: {tx_hash}")
# Step 4: Confirm the escrow with AgentTrust (starts the clock)
httpx.post(f"{REFEREE}/escrow/{escrow_id}/confirm",
json={"tx_hash": tx_hash}).raise_for_status()
print(f"Escrow ID: {escrow_id} — share this with the seller")
Flow: Transfer the NFT to the buyer's XRPL wallet first, then call /evaluate with the token ID as your proof. The referee checks on-chain that the NFT is now owned by the buyer before releasing payment.
# pip install xrpl-py httpx
import httpx
from xrpl.clients import JsonRpcClient
from xrpl.models.transactions import NFTokenCreateOffer, NFTokenAcceptOffer
from xrpl.models.requests import AccountNFTs
from xrpl.wallet import Wallet
from xrpl.transaction import submit_and_wait
from xrpl.utils import xrp_to_drops
REFEREE = "https://mcp.cryptovault.co.uk"
XRPL_NODE = "https://s1.ripple.com:51234/"
seller_wallet = Wallet.from_seed("sSELLER_SEED_HERE")
buyer_address = "rBUYER_ADDRESS_HERE"
client = JsonRpcClient(XRPL_NODE)
ESCROW_ID = "NFT-XXXX" # escrow_id shared by the buyer
NFT_TOKEN_ID = "000800006B6B..."
# Step 1: Create a sell offer for 0 XRP (free transfer to specific buyer)
offer_tx = NFTokenCreateOffer(
account = seller_wallet.address,
nftoken_id = NFT_TOKEN_ID,
amount = "0", # buyer already paid via escrow
destination = buyer_address, # restricted to the buyer only
flags = 1, # tfSellNFToken
)
offer_result = submit_and_wait(offer_tx, client, seller_wallet).result
offer_id = next(
n["CreatedNode"]["LedgerIndex"]
for n in offer_result["meta"]["AffectedNodes"]
if n.get("CreatedNode", {}).get("LedgerEntryType") == "NFTokenOffer"
)
print(f"Sell offer created: {offer_id}")
# Step 2: Buyer accepts the offer — run this as the buyer
buyer_wallet = Wallet.from_seed("sBUYER_SEED") # buyer's XRPL wallet seed
accept_tx = NFTokenAcceptOffer(
account=buyer_wallet.address, nftoken_sell_offer=offer_id)
submit_and_wait(accept_tx, client, buyer_wallet)
print("NFT transferred to buyer wallet")
# -- (once buyer has accepted and NFT is in their wallet) --
# Step 3: Verify the NFT is now in the buyer's wallet
nfts = client.request(AccountNFTs(account=buyer_address)).result["account_nfts"]
owned = any(n["NFTokenID"] == NFT_TOKEN_ID for n in nfts)
assert owned, "NFT not yet in buyer wallet — wait for acceptance"
print("NFT confirmed in buyer wallet. Submitting proof...")
# Step 4: Submit proof to AgentTrust — payment releases automatically on PASS
result = httpx.post(f"{REFEREE}/evaluate", json={
"escrow_id": ESCROW_ID,
"work": (
f"NFT transfer complete.\n"
f"Token ID: {NFT_TOKEN_ID}\n"
f"Current owner (buyer): {buyer_address}\n"
f"Sell offer accepted: {offer_id}\n"
f"NFT is confirmed in the buyer's wallet on the XRP Ledger."
),
}, timeout=120).json()
print(f"Verdict: {result['verdict']} | Score: {result['score']}/100")
# PASS → EscrowFinish submitted on-chain automatically → seller receives XRP
Two-sided acceptance: On XRPL, both parties need to act: the seller creates a sell offer, the buyer accepts it. In a fully automated flow, both sides run their respective code. In a manual flow, share the offer_id with the buyer so they can accept it with Xaman or any XRPL wallet.
The task description is the verification spec the AI referee scores against. For NFT DvP trades, be explicit about exactly what constitutes proof of delivery:
NFT Delivery-vs-Payment escrow.
NFT token ID: 000800006B6B4C70EDB8EBC90F2A5EDB45FDBA
Issuer address: rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh
Buyer wallet: rBuyer123...
Seller wallet: rSeller456...
Agreed price: 50 XRP (held in escrow, released on verification)
PAYMENT RELEASES when the submission confirms that:
- The NFT with the above token ID is owned by the buyer wallet
- The transfer has been accepted and finalized on the XRP Ledger mainnet
Seller should include: the sell offer ID, confirmation that the
buyer accepted it, and a statement that the NFT is in the buyer's wallet.
Cancel window matters: Set cancel_after_hrs to give the seller enough time to list, transfer, and have the buyer accept the NFT. 72 hours is reasonable for a manually coordinated trade. If the deadline passes without a PASS verdict, the buyer can reclaim the escrowed funds. The NFT offer will remain open unless explicitly cancelled.
AgentTrust lets you add a trust condition requiring the seller wallet to hold an NFT from a specific issuer before the escrow can be created. This is useful for gating trades to verified platforms, credentialed creators, or whitelisted collections.
{
"escrow_id": "NFT-TRADE-001",
"fee_hash": "...",
"buyer_address": "rBuyer...",
"worker_address": "rSeller...",
"task_description": "...",
"amount_xrp": 50,
"cancel_after_hrs": 72,
// Require seller to hold a verified-creator NFT from this issuer
"required_nft_issuer": "rISSUER_ADDRESS",
"required_nft_taxon": 12 // optional: restrict to a specific collection
}
If the seller's wallet doesn't hold a matching NFT, escrow creation is blocked and a clear error is returned. Combine this with domain verification and OFAC screening for a fully trust-gated trade.
Native RLUSD escrow is in the codebase and ready, but requires Ripple to enable the lsfAllowTrustLineLocking flag on their issuer account — this is pending. In the meantime, escrows run in XRP; workers who want RLUSD can swap via the XRPL DEX after release using the /dex/quote endpoint. The currency: "RLUSD" field is accepted by the API and will activate automatically once the issuer flag is live.
{
"escrow_id": "NFT-USD-001",
"fee_hash": "...",
"buyer_address": "rBuyer...",
"worker_address": "rSeller...",
"task_description": "...",
"currency": "RLUSD",
"amount_rlusd": 500.00, // $500 USD
"cancel_after_hrs": 72
}
Creator sells a 1-of-1 or edition NFT. Buyer's payment locks before the transfer — neither side can ghost after committing.
Event tickets issued as XRPL NFTs. Resale market with atomic settlement — buyer gets the ticket, seller gets paid, simultaneously.
Tokenised real-world assets (property fractions, carbon credits, trade finance instruments) settling with cryptographic finality.
AI agents trading NFT-represented licences, data access tokens, or compute credits autonomously — payment and delivery without human approval.