{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["tabs","tab"]},"redocly_category":"Documentation","type":"markdown"},"seo":{"title":"Getting Started with XRPL DEX Trading","siteUrl":"https://xrpl.org/","llmstxt":{"hide":false,"title":"XRPL Developer Portal & Documentation","description":"Explore XRP Ledger documentation, blogs, and other blockchain developer resources needed to start building and integrating with the ledger.","details":{"content":"XRP Ledger concepts, use cases, tutorials, references, and other blockchain developer resources. Also, stay up to date with release announcements and more through the XRPL Blog."},"sections":[{"title":"Introduction","description":"A high-level introduction to the XRP Ledger.","includeFiles":["docs/introduction/**/*.*","about/faq.md"],"excludeFiles":["docs/introduction/index.md"]},{"title":"Use Cases","description":"Real-world applications and business scenarios for the XRP Ledger.","includeFiles":["docs/use-cases/**/*.*"],"excludeFiles":["docs/use-cases/index.md","docs/use-cases/defi/index.md"]},{"title":"Agentic Transactions","description":"XRPL AI Starter Kit to help autonomous agents discover, set up, and execute agentic transactions on the XRP Ledger.","includeFiles":["docs/agents/**/*.*"]},{"title":"Concepts","description":"Core concepts including accounts, tokens, transactions, consensus, and more.","includeFiles":["docs/concepts/**/*.*"],"excludeFiles":["docs/concepts/index.md","docs/concepts/decentralized-storage/index.md","docs/concepts/payment-types/index.md"]},{"title":"Tutorials","description":"Step-by-step guides for building on the XRP Ledger in JavaScript, Python, Go, and more.","includeFiles":["docs/tutorials/**/*.*"]},{"title":"References","description":"Protocol specification, transaction types, ledger entries, and API methods.","includeFiles":["docs/references/**/*.*"],"excludeFiles":["docs/references/xrp-api.md","docs/references/data-api.md","docs/references/protocol/index.md","docs/references/protocol/ledger-data/ledger-entry-types/index.md","docs/references/protocol/transactions/index.md","docs/references/protocol/transactions/types/index.md","docs/references/http-websocket-apis/api-conventions/index.md","docs/references/http-websocket-apis/public-api-methods/*/index.md","docs/references/http-websocket-apis/admin-api-methods/*/index.md"]},{"title":"Infrastructure","description":"Install, configure, and troubleshoot xrpld and Clio servers.","includeFiles":["docs/infrastructure/**/*.*"],"excludeFiles":["docs/infrastructure/index.md","docs/infrastructure/*/index.md","docs/infrastructure/installation/build-run-xrpld-in-reporting-mode.md","docs/infrastructure/configuration/data-retention/index.md","docs/infrastructure/configuration/server-modes/index.md"]},{"title":"Blog (2023+)","description":"Recent XRPL Blog posts (showing 2023 and newer).","includeFiles":["blog/2023/**/*.*","blog/2024/**/*.*","blog/2025/**/*.*","blog/2026/**/*.*"]},{"title":"Resources","description":"Developer resources and contribution guidelines.","includeFiles":["resources/**/*.*"]}]},"description":"Install the XRPL Trading and Agent Wallet skills for Claude, read a live order book, and place your first autonomous limit order on the XRP Ledger decentralised exchange — in under 30 minutes.\n"},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"getting-started-with-xrpl-dex-trading","__idx":0},"children":["Getting Started with XRPL DEX Trading"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This tutorial walks you through your first autonomous DEX trading session on the"," ","XRP Ledger using Claude. You will install two XRPL skills, read a live order book,"," ","and place a limit order on the permissionless XRPL DEX — all driven by"," ","natural-language prompts."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["What you will build:"]}," a live order book read, a limit order placement, and an"," ","offer cancellation."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Time to complete:"]}," approximately 30 minutes."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Prerequisite:"]}," A funded XRPL testnet wallet. If you don't have one yet, follow"," ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/agents/getting-started-with-agentic-transactions/"},"children":["Getting Started with Agentic Transactions"]}," ","first — it takes about 15 minutes and you will reuse the wallet here."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"the-two-skills","__idx":1},"children":["The two skills"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["XRPL agent skills are layered: one shared foundation, one domain skill per use"," ","case. This tutorial uses the trading combination."]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"align":"left","data-label":"Skill"},"children":["Skill"]},{"$$mdtype":"Tag","name":"th","attributes":{"align":"left","data-label":"Role"},"children":["Role"]},{"$$mdtype":"Tag","name":"th","attributes":{"align":"left","data-label":"When it applies"},"children":["When it applies"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["XRPL Agent Wallet"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["Shared foundation"]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["From the start — owns wallet creation, key loading, and the full signing ceremony (autofill → preview → confirm → sign → submit)."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["XRPL Trading"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["Domain skill"]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["At transaction time — gives Claude accurate knowledge of XRPL DEX operations: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["OfferCreate"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["OfferCancel"]},", order book reads, AMM interaction, fill classification, and agentic best practices."]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The Wallet skill owns the signing ceremony. The Trading skill constructs the right"," ","transaction object for any DEX operation. Claude coordinates the handoff — you do not"," ","need to manage it manually."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"prerequisites","__idx":2},"children":["Prerequisites"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"align":"left","data-label":"Requirement"},"children":["Requirement"]},{"$$mdtype":"Tag","name":"th","attributes":{"align":"left","data-label":"Notes"},"children":["Notes"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Node.js 18+"]}," or ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Python 3.9+"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["Code samples are provided in both languages."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Claude Code"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["Recommended for development — runs Claude in your terminal alongside your project files."]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["A funded testnet wallet"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["Follow ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/agents/getting-started-with-agentic-transactions/"},"children":["Getting Started with Agentic Transactions"]}," if you don't have one."]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Install the XRP Ledger SDK for your language:"]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"TypeScript","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"sh","header":{"controls":{"copy":{}}},"source":"npm install xrpl\n","lang":"sh"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Python","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"sh","header":{"controls":{"copy":{}}},"source":"pip install xrpl-py\n","lang":"sh"},"children":[]}]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"step-1-install-the-skills","__idx":3},"children":["Step 1: Install the skills"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If you completed the payments getting-started guide, the Wallet skill is already"," ","installed. Skip to installing the Trading skill."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"sh","header":{"controls":{"copy":{}}},"source":"# Wallet skill (skip if already installed)\nnpx skills add https://github.com/XRPLF/xrpl-dev-portal/tree/master/.claude/skills/xrpl-skills/xrpl-agent-wallet --agent claude-code\n\n# Trading skill\nnpx skills add https://github.com/XRPLF/xrpl-dev-portal/tree/master/.claude/skills/xrpl-skills/xrpl-trading --agent claude-code\n","lang":"sh"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Verify both skills are loaded:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"/skills\n"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You should see:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"Project skills (.claude/skills)\n  xrpl-agent-wallet\n  xrpl-trading\n"},"children":[]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"step-2-get-a-tradeable-testnet-pair","__idx":4},"children":["Step 2: Get a tradeable Testnet pair"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Testnet has almost no real liquidity."]}," The well-known Mainnet issuers (Bitstamp,"," ","GateHub, and so on) either do not exist on Testnet or have no usable order book there, so"," ","you cannot simply point at ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["USD.Bitstamp"]}," and expect a market. Before you can place a"," ","meaningful trade you need a pair that actually has an offer on the other side."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You have two options."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Option A — trade against a one-sided book (fastest)."]}," Place a limit order that does not"," ","cross, let it rest, then cancel it. This exercises the full ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["OfferCreate"]}," → verify →"," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["OfferCancel"]}," → verify loop and needs no counterparty. Skip to Step 3; just expect"," ","\"one-sided book\" when you read prices, and expect your order to rest rather than fill."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Option B — create your own pair (needed to see a real fill)."]}," Issue a test token from a"," ","second wallet and place a maker offer against it. Four transactions:"]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"TypeScript","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"import { Client, Wallet, xrpToDrops, AccountSetAsfFlags } from \"xrpl\";\n\nconst client = new Client(\"wss://s.altnet.rippletest.net:51233\");\nawait client.connect();\n\n// Two throwaway Testnet wallets: an issuer and a market maker.\nconst { wallet: issuer } = await client.fundWallet();\nconst { wallet: maker  } = await client.fundWallet();\n\nconst submit = async (w: Wallet, tx: any) =>\n  client.submitAndWait((w.sign(await client.autofill(tx))).tx_blob);\n\n// 1. The issuer must allow its token to move between holders.\nawait submit(issuer, { TransactionType: \"AccountSet\", Account: issuer.classicAddress,\n                       SetFlag: AccountSetAsfFlags.asfDefaultRipple });\n\n// 2. The maker trusts the issuer for TST.\nawait submit(maker, { TransactionType: \"TrustSet\", Account: maker.classicAddress,\n                      LimitAmount: { currency: \"TST\", issuer: issuer.classicAddress, value: \"1000\" } });\n\n// 3. The issuer sends the maker 100 TST.\nawait submit(issuer, { TransactionType: \"Payment\", Account: issuer.classicAddress,\n                       Destination: maker.classicAddress,\n                       Amount: { currency: \"TST\", issuer: issuer.classicAddress, value: \"100\" } });\n\n// 4. The maker posts liquidity: sell 20 TST for 4 XRP (0.2 XRP/TST).\nawait submit(maker, { TransactionType: \"OfferCreate\", Account: maker.classicAddress,\n                      TakerPays: xrpToDrops(4),\n                      TakerGets: { currency: \"TST\", issuer: issuer.classicAddress, value: \"20\" } });\n\nconsole.log(\"Tradeable pair ready. Issuer:\", issuer.classicAddress);\nawait client.disconnect();\n","lang":"typescript"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Python","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"python","header":{"controls":{"copy":{}}},"source":"from xrpl.clients import JsonRpcClient\nfrom xrpl.wallet import generate_faucet_wallet\nfrom xrpl.transaction import submit_and_wait\nfrom xrpl.utils import xrp_to_drops\nfrom xrpl.models.transactions import AccountSet, TrustSet, Payment, OfferCreate\nfrom xrpl.models.transactions.account_set import AccountSetAsfFlag\n\nclient = JsonRpcClient(\"https://s.altnet.rippletest.net:51234\")\nissuer = generate_faucet_wallet(client)\nmaker  = generate_faucet_wallet(client)\n\n# 1. Allow the token to move between holders.\nsubmit_and_wait(AccountSet(account=issuer.classic_address,\n                           set_flag=AccountSetAsfFlag.ASF_DEFAULT_RIPPLE), client, issuer)\n\n# 2. The maker trusts the issuer for TST.\nsubmit_and_wait(TrustSet(account=maker.classic_address,\n    limit_amount={\"currency\": \"TST\", \"issuer\": issuer.classic_address, \"value\": \"1000\"}),\n    client, maker)\n\n# 3. The issuer sends the maker 100 TST.\nsubmit_and_wait(Payment(account=issuer.classic_address, destination=maker.classic_address,\n    amount={\"currency\": \"TST\", \"issuer\": issuer.classic_address, \"value\": \"100\"}),\n    client, issuer)\n\n# 4. The maker posts liquidity: sell 20 TST for 4 XRP (0.2 XRP/TST).\nsubmit_and_wait(OfferCreate(account=maker.classic_address, taker_pays=xrp_to_drops(4),\n    taker_gets={\"currency\": \"TST\", \"issuer\": issuer.classic_address, \"value\": \"20\"}),\n    client, maker)\n\nprint(\"Tradeable pair ready. Issuer:\", issuer.classic_address)\n","lang":"python"},"children":[]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Note the issuer address that gets printed — the rest of this tutorial uses it wherever"," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["TEST_ISSUER"]}," appears. Your trading wallet needs ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["no"]}," trust line to it: the ledger creates"," ","one automatically the first time you receive TST. Budget 0.2 XRP of owner reserve for it."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"step-3-read-the-order-book","__idx":5},"children":["Step 3: Read the order book"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Order book reads are read-only — no signature or confirmation required. Ask Claude:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"Show me the current XRP/USD order book on testnet — best bid, best ask,\nmid price, and spread.\n"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Claude calls ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["book_offers"]}," on both sides of the pair and returns a summary:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"Order book: XRP / USD.Bitstamp (testnet)\n  Best ask : 0.512400 USD/XRP\n  Best bid : 0.511200 USD/XRP\n  Mid price: 0.511800 USD/XRP\n  Spread   : 0.235 %\n  Ask depth: 12 offers, 8,420 XRP available at mid ± 1%\n"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The code behind this request:"]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"TypeScript","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"import { Client, dropsToXrp } from \"xrpl\";\n\n// NOTE: rvYAfWj5... is Bitstamp's MAINNET issuer. It has no meaningful book on\n// Testnet. Substitute an issuer that is actually active on Testnet, or issue your\n// own test token and trade against it.\nconst USD_ISSUER = process.env.TEST_ISSUER!;   // a Testnet issuer you control\nconst client    = new Client(\"wss://s.altnet.rippletest.net:51233\");\nawait client.connect();\n\nconst [asks, bids] = await Promise.all([\n  client.request({\n    command:    \"book_offers\",\n    taker_pays: { currency: \"USD\", issuer: USD_ISSUER },\n    taker_gets: { currency: \"XRP\" },\n    limit: 20,\n  }),\n  client.request({\n    command:    \"book_offers\",\n    taker_pays: { currency: \"XRP\" },\n    taker_gets: { currency: \"USD\", issuer: USD_ISSUER },\n    limit: 20,\n  }),\n]);\n\n// `quality` is TakerPays/TakerGets in PROTOCOL units — XRP is in drops, so an\n// XRP-denominated quality is 1,000,000x off and the two book sides are inverted.\n// Always derive the price from the amounts instead.\nconst amt = (a: any) => typeof a === \"string\" ? Number(dropsToXrp(a)) : Number(a.value);\nconst price = (o: any, getsBase: boolean) =>\n  getsBase ? amt(o.TakerPays) / amt(o.TakerGets) : amt(o.TakerGets) / amt(o.TakerPays);\n\n// `book_offers` also returns offers their owner cannot currently fund — including\n// completely unfunded ones, which carry a real-looking price and size. Tradeable\n// size is `taker_gets_funded` when present; drop anything that resolves to 0.\nconst fundedGets  = (o: any) => o.taker_gets_funded ?? o.TakerGets;\nconst liveOffers  = (os: any[]) => os.filter(o => amt(fundedGets(o)) > 0);\n\nconst askOffers = liveOffers(asks.result.offers);   // taker_gets = XRP -> getsBase = true\nconst bidOffers = liveOffers(bids.result.offers);   // taker_pays = XRP -> getsBase = false\nconst bestAsk   = askOffers.length ? price(askOffers[0], true)  : null;\nconst bestBid   = bidOffers.length ? price(bidOffers[0], false) : null;\n\n// A one-sided book has no mid price and no spread. Report that honestly.\nif (bestAsk === null || bestBid === null) {\n  console.log(\"One-sided book — mid price and spread are undefined.\");\n} else {\n  const midPrice  = (bestAsk + bestBid) / 2;\n  const spreadPct = ((bestAsk - bestBid) / midPrice) * 100;\n  console.log(`Mid price: ${midPrice.toFixed(6)} USD/XRP`);\n  console.log(`Spread   : ${spreadPct.toFixed(3)} %`);\n}\n\nawait client.disconnect();\n","lang":"typescript"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Python","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"python","header":{"controls":{"copy":{}}},"source":"from xrpl.clients import JsonRpcClient\nfrom xrpl.models.requests import BookOffers\nfrom xrpl.utils import drops_to_xrp\n\nUSD_ISSUER = \"rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B\"\nclient     = JsonRpcClient(\"https://s.altnet.rippletest.net:51234\")\n\nasks = client.request(BookOffers(\n    taker_pays={\"currency\": \"USD\", \"issuer\": USD_ISSUER},\n    taker_gets={\"currency\": \"XRP\"},\n    limit=20,\n)).result.get(\"offers\", [])\n\nbids = client.request(BookOffers(\n    taker_pays={\"currency\": \"XRP\"},\n    taker_gets={\"currency\": \"USD\", \"issuer\": USD_ISSUER},\n    limit=20,\n)).result.get(\"offers\", [])\n\n# `quality` is in PROTOCOL units (XRP as drops) and the two book sides are\n# inverted — derive the price from the amounts instead.\ndef _amt(a):\n    return float(drops_to_xrp(a)) if isinstance(a, str) else float(a[\"value\"])\n\ndef _price(o, gets_base):\n    return (_amt(o[\"TakerPays\"]) / _amt(o[\"TakerGets\"])) if gets_base \\\n        else (_amt(o[\"TakerGets\"]) / _amt(o[\"TakerPays\"]))\n\n# `book_offers` also returns offers their owner cannot currently fund - including\n# completely unfunded ones, which carry a real-looking price and size. Tradeable\n# size is `taker_gets_funded` when present; drop anything that resolves to 0.\ndef _live(offers):\n    return [o for o in offers\n            if _amt(o.get(\"taker_gets_funded\", o[\"TakerGets\"])) > 0]\n\nasks, bids = _live(asks), _live(bids)\n\nbest_ask = _price(asks[0], True)  if asks else None\nbest_bid = _price(bids[0], False) if bids else None\n\nif best_ask is None or best_bid is None:\n    print(\"One-sided book - mid price and spread are undefined.\")\nelse:\n    mid_price = (best_ask + best_bid) / 2\n    print(f\"Mid price: {mid_price:.6f} USD/XRP\")\n    print(f\"Spread   : {(best_ask - best_bid) / mid_price * 100:.3f} %\")\n","lang":"python"},"children":[]}]}]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"step-4-place-a-limit-order","__idx":6},"children":["Step 4: Place a limit order"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Ask Claude to place a limit order. The Trading skill builds the transaction object"," ","and the Wallet skill runs the signing ceremony — you will see a preview before"," ","anything is submitted."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"Place a limit order to sell 10 XRP and buy 5 USD at 0.5 USD/XRP,\nexpiring in 1 hour. Show me the order book first.\n"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Claude will show you a pre-trade summary before requesting your signature:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"Pre-trade summary\n──────────────────────────────────────────────────────\nOffering:     10 XRP (10,000,000 drops)\nTo receive:   5 USD (Bitstamp issuer)\nLimit price:  0.500000 USD/XRP  (minimum you will accept)\nMid price:    0.511800 USD/XRP  (from order book)\nEst. fill:    100% — your limit is below the best bid, so the whole order crosses\nExec. price:  0.511200 USD/XRP  (you receive the better book price, not your limit)\nSlippage:     0.00% vs best bid — depth exceeds order size\nExpiry:       2026-08-21T14:30:00Z (1 hour from now)\n──────────────────────────────────────────────────────\nProceed to sign? (yes / no)\n"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["After acknowledgement, the Wallet skill displays its transaction preview:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"─── XRPL Transaction Preview ────────────────────────────────────────\nNetwork           : testnet\nType              : OfferCreate\nFrom              : rYourFullAddressShownInFullNoTruncation\nTo                : —\nAmount            : —\nFee               : 0.000012 XRP\nSequence          : 48291010\nLastLedgerSequence: 48291030  (expires in ~20 ledgers, ~80 seconds)\nFlags             : 0\nMemos             : —\nTakerGets         : 10 XRP (10,000,000 drops)\nTakerPays         : 5 USD  issuer rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B\nOther fields      : Expiration 2026-08-21T14:30:00Z\n─────────────────────────────────────────────────────────────────────\nSign and submit? (yes / no)\n"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The code Claude generates for the transaction object:"]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"TypeScript","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"import { OfferCreate, xrpToDrops } from \"xrpl\";\n\nconst XRPL_EPOCH_OFFSET = 946_684_800;\nconst expiryXRPL = Math.floor(Date.now() / 1000) + 3600 - XRPL_EPOCH_OFFSET;\n\nconst offer: Omit<OfferCreate, \"Fee\" | \"Sequence\" | \"LastLedgerSequence\"> = {\n  TransactionType: \"OfferCreate\",\n  Account:    \"rYourAddress\",\n  TakerPays:  { currency: \"USD\", issuer: \"rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B\", value: \"5\" },\n  TakerGets:  xrpToDrops(10),      // \"10000000\" drops\n  Expiration: expiryXRPL,\n  // Fee, Sequence, LastLedgerSequence: set by Wallet skill autofill\n  // SourceTag: applied by Wallet skill (20260530) automatically\n};\n// → hand to XRPL Agent Wallet skill\n","lang":"typescript"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Python","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"python","header":{"controls":{"copy":{}}},"source":"import time\nfrom xrpl.models.transactions import OfferCreate\nfrom xrpl.utils import xrp_to_drops\n\nXRPL_EPOCH_OFFSET = 946_684_800\nexpiry_xrpl = int(time.time()) + 3600 - XRPL_EPOCH_OFFSET\n\noffer = OfferCreate(\n    account=\"rYourAddress\",\n    taker_pays={\"currency\": \"USD\", \"issuer\": \"rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B\", \"value\": \"5\"},\n    taker_gets=xrp_to_drops(10),   # \"10000000\" drops\n    expiration=expiry_xrpl,\n    # Fee, Sequence, LastLedgerSequence: set by Wallet skill autofill\n    # source_tag: applied by Wallet skill (20260530) automatically\n)\n# → hand to XRPL Agent Wallet skill\n","lang":"python"},"children":[]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["After signing, Claude classifies the result:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"Fill status:    partial (remainder resting)\nAmount filled:  6 of 10 XRP sold (60%), 3.07 USD received\nRemaining:      4 XRP / 2 USD resting on the book\nOffer sequence: 48291010  ← save this to cancel later\nFee paid:       12 drops (0.000012 XRP)\nTx hash:        A3F9B2...\n"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Save the offer sequence."]}," You will need it to cancel the resting portion."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"step-5-cancel-the-resting-offer","__idx":7},"children":["Step 5: Cancel the resting offer"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If the offer doesn't fill completely, cancel it with:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"Cancel my resting offer at sequence 48291010.\n"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Claude verifies the offer exists, shows a cancellation summary, and presents the"," ","Wallet skill's preview before submitting:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"Cancelling offer sequence: 48291010\nYou are giving up:         4 XRP (remaining TakerGets)\nYou would have received:   2 USD (remaining TakerPays)\nNetwork fee:               12 drops\n"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["OfferCancel"]}," transaction:"]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"TypeScript","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"import { OfferCancel } from \"xrpl\";\n\nconst cancel: Omit<OfferCancel, \"Fee\" | \"Sequence\" | \"LastLedgerSequence\"> = {\n  TransactionType: \"OfferCancel\",\n  Account:        \"rYourAddress\",\n  OfferSequence:  48291010,   // Sequence of the original OfferCreate\n};\n// → hand to XRPL Agent Wallet skill\n","lang":"typescript"},"children":[]}]},{"$$mdtype":"Tag","name":"TabItemFragment","attributes":{"label":"Python","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"python","header":{"controls":{"copy":{}}},"source":"from xrpl.models.transactions import OfferCancel\n\ncancel = OfferCancel(\n    account=\"rYourAddress\",\n    offer_sequence=48291010,   # Sequence of the original OfferCreate\n)\n# → hand to XRPL Agent Wallet skill\n","lang":"python"},"children":[]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A successful cancellation returns ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tesSUCCESS"]}," with the offer in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["meta.AffectedNodes"]}," ","as a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["DeletedNode"]},". If the offer was already filled, the cancel still succeeds but"," ","does nothing — and the fee is still charged. Always verify offer existence before"," ","cancelling."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"common-flag-combinations","__idx":8},"children":["Common flag combinations"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"align":"left","data-label":"Goal"},"children":["Goal"]},{"$$mdtype":"Tag","name":"th","attributes":{"align":"left","data-label":"Flag to set"},"children":["Flag to set"]},{"$$mdtype":"Tag","name":"th","attributes":{"align":"left","data-label":"Notes"},"children":["Notes"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["Standard limit order (rests if unfilled)"]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["None"]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["Default"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["Market order (fill what you can, cancel rest)"]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tfImmediateOrCancel"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["Draws on AMM + order book"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["Must fill completely or cancel"]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tfFillOrKill"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tecKILLED"]}," on failure — fee charged"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["Post-only (never cross, always rest)"]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tfPassive"]}]},{"$$mdtype":"Tag","name":"td","attributes":{"align":"left"},"children":["Use for maker strategies"]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Never combine ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tfImmediateOrCancel"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tfFillOrKill"]},"."]}," The Trading skill rejects"," ","this combination at construction."]},{"$$mdtype":"Tag","name":"hr","attributes":{},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"where-to-go-next","__idx":9},"children":["Where to go next"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Skill reference"]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/agents/xrpl-trading-skill/"},"children":["The XRPL Trading Skill"]}," —"," ","Full reference for offer semantics, flag behaviour, AMM interaction, fill classification, and error codes."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/agents/xrpl-agent-wallet-skill/"},"children":["The XRPL Agent Wallet Skill"]}," —"," ","Security model, signing ceremony, key handling patterns, and production setup including OWS."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Use case guides"]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/agents/agentic-payments-x402/"},"children":["Agentic Payments with X402"]}," — Pay for HTTP services autonomously using XRPL payments."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/agents/track-agent-behavior/"},"children":["Track and Measure Agent Behavior"]}," — Use SourceTag, Memos, and WebSocket monitoring to attribute and audit every agent transaction."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Go deeper on XRPL features"]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/concepts/tokens/decentralized-exchange/"},"children":["Decentralized Exchange"]}," — XRPL DEX concepts: offer matching, quality, and the order book."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/concepts/tokens/decentralized-exchange/automated-market-makers/"},"children":["Automated Market Maker"]}," — AMM pools and how they interact with the DEX order book."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["SDK references"]}]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://js.xrpl.org/"},"children":["xrpl.js documentation"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://xrpl-py.readthedocs.io/"},"children":["xrpl-py documentation"]}]}]}]},"headings":[{"value":"Getting Started with XRPL DEX Trading","id":"getting-started-with-xrpl-dex-trading","depth":1},{"value":"The two skills","id":"the-two-skills","depth":2},{"value":"Prerequisites","id":"prerequisites","depth":2},{"value":"Step 1: Install the skills","id":"step-1-install-the-skills","depth":2},{"value":"Step 2: Get a tradeable Testnet pair","id":"step-2-get-a-tradeable-testnet-pair","depth":2},{"value":"Step 3: Read the order book","id":"step-3-read-the-order-book","depth":2},{"value":"Step 4: Place a limit order","id":"step-4-place-a-limit-order","depth":2},{"value":"Step 5: Cancel the resting offer","id":"step-5-cancel-the-resting-offer","depth":2},{"value":"Common flag combinations","id":"common-flag-combinations","depth":2},{"value":"Where to go next","id":"where-to-go-next","depth":2}],"frontmatter":{"seo":{"title":"Getting Started with XRPL DEX Trading","description":"Install the XRPL Trading and Agent Wallet skills for Claude, read a live order book, and place your first autonomous limit order on the XRP Ledger decentralised exchange — in under 30 minutes.\n"},"labels":["AI","Agents","Tutorial","DEX","Trading"]},"editPage":{"to":"https://github.com/XRPLF/xrpl-dev-portal/tree/master/docs/agents/getting-started-with-xrpl-trading.md"},"lastModified":"2026-09-15T08:09:10.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/docs/agents/getting-started-with-xrpl-trading","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}