<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[DeFiTap]]></title><description><![CDATA[DeFiTap]]></description><link>https://defitap.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Thu, 12 Nov 2026 09:15:37 GMT</lastBuildDate><atom:link href="https://defitap.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Your Cardano Swap Is Two Transactions. Read DEX Data Like It.]]></title><description><![CDATA[How eUTXO forces batchers on Cardano DEXs, and what that changes when you parse swaps, pools and volume on chain.]]></description><link>https://defitap.hashnode.dev/your-cardano-swap-is-two-transactions-read-dex-data-like-it</link><guid isPermaLink="true">https://defitap.hashnode.dev/your-cardano-swap-is-two-transactions-read-dex-data-like-it</guid><category><![CDATA[#cardano]]></category><category><![CDATA[defi]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[Smart Contracts]]></category><category><![CDATA[data]]></category><dc:creator><![CDATA[DeFiTap]]></dc:creator><pubDate>Tue, 10 Nov 2026 18:23:13 GMT</pubDate><content:encoded><![CDATA[<p>You click swap. Your wallet signs. The DEX shows "order placed". Then you wait.</p>
<p>If you came from an EVM chain, that wait feels like a bug. It is not. It is the ledger model talking, and once you see why, every chart and table of Cardano DEX data starts to read differently.</p>
<p>This post is for developers and data people who want to understand what is actually happening between "order placed" and "swap done", and how to avoid the classic mistakes when you index or analyze Cardano DEX activity.</p>
<h2>Start with the coin, not the account</h2>
<p>On an account based chain, a pool contract is one object with mutable storage. A thousand users can hit it in the same block, and the chain just orders their calls one after another.</p>
<p>Cardano does not work like that. It uses the <a href="https://docs.cardano.org/about-cardano/learn/eutxo-explainer">Extended UTXO model</a>. Value lives in discrete outputs. Each output has an address, a value, and optionally a datum. A transaction consumes existing outputs whole and creates new ones. Each output can be spent exactly once.</p>
<p>The "extended" part adds two things. Addresses can be scripts, so spending can depend on arbitrary validation logic. And outputs can carry data, so a script can keep state in the datum.</p>
<p>Validators do not compute new state. They check it. Off chain code builds the transaction, and the on chain script returns yes or no. The <a href="https://docs.cardano.org/developer-resources/smart-contracts/plutus">Plutus docs</a> put the upside plainly: validity depends only on the transaction and its inputs, so you can check it off chain before you submit. The catch is in the same paragraph. A transaction can still fail if someone else spends an input it expected.</p>
<p>Hold that thought. It is the whole story.</p>
<h2>One pool, one UTXO, one winner</h2>
<p>A constant product pool needs a single shared view of its reserves. On Cardano the natural place for that is one UTXO at the pool script address, holding the reserves and a datum with pool parameters.</p>
<p>Now picture three users building a direct swap against that pool in the same block. All three transactions reference the same pool UTXO as an input. The first one included wins. The other two fail because their input no longer exists. The <a href="https://developers.cardano.org/docs/developers/curriculum/dapps/defi/">Cardano Developer Portal</a> describes exactly this and calls it what it is: a fundamental property of the model, not a bug.</p>
<p>If you build a DEX the account way on eUTXO, you get a race on every block. Users rebuild, resubmit, and lose again. Sundae Labs wrote a good <a href="https://sundae.fi/blog/concurrency-state-cardano">deep dive on this contention problem</a> if you want the long version.</p>
<h2>Enter the batcher</h2>
<p>The most common fix splits a swap into two steps by two different parties.</p>
<p><strong>Step one, the user.</strong> Your wallet does not touch the pool. It sends your funds to an order script address with a datum that encodes intent: what you sell, what you want, the minimum you accept, and where to pay out. This transaction cannot conflict with anyone else, because it only spends your own UTXOs.</p>
<p><strong>Step two, the batcher.</strong> An off chain service watches the order address, collects pending orders, and builds one transaction that spends the pool UTXO plus many order UTXOs together. It outputs a new pool UTXO with updated reserves and pays each user per their datum. The validator enforces that every order got what its datum allows.</p>
<p>Different DEXs name this role differently. Scooper, agent, executor. Same job.</p>
<p>The batcher absorbs the contention users would have felt. It keeps its own view of pending orders, rechecks that queued orders still exist before building a batch, and rebuilds from fresh chain state when it loses a race. It also picks which orders go in and in what sequence. That ordering policy is where fairness lives, so it is worth reading for any DEX you analyze.</p>
<p><a href="https://iohk.io/en/blog/posts/2021/11/16/architecting-dapps-on-the-eutxo-ledger/">IOG notes another cost</a>: when N orders are consumed in one transaction, the order script runs N times and the execution budget adds up. That is why batch sizes have practical ceilings and why some designs move work around to keep scripts cheap.</p>
<p>There are other patterns too. Some designs split liquidity across several UTXOs so more than one transaction can touch the pool per block. Others chain transactions within a block. But batching is the one you will meet most when you read raw data.</p>
<h2>What this means when you read DEX data</h2>
<p>Here is where people get burned. Most mistakes in Cardano DEX analytics come from treating a swap as one event.</p>
<h3>1. An order is not a trade</h3>
<p>The user transaction that locks funds at the order address is intent, not execution. Some orders get filled. Some get cancelled. Some sit until the user reclaims them. If you count order transactions as volume, you are counting wishes.</p>
<p>Real volume comes from the batch transaction, where pool reserves actually change. Measure the delta between the pool UTXO consumed and the pool UTXO produced. That delta is the trade.</p>
<h3>2. Price lives in reserves, not in orders</h3>
<p>The minimum receive amount in an order datum is a slippage guard, not a price. The executed price is set by pool reserves at batch time, in the order the batcher processed things. Two orders in one batch can get different prices because the first one moved the reserves before the second one hit.</p>
<p>If you want a clean price series, read reserves from successive pool UTXOs. Do not average minimums from order datums.</p>
<h3>3. Timestamps have two meanings</h3>
<p>There is the time the user placed the order and the time it executed. In a busy period those can be different blocks. Decide which one your metric uses. "Time to fill" is a useful metric in its own right and tells you a lot about batcher health.</p>
<h3>4. One batch, many wallets</h3>
<p>A single batch transaction pays out to many addresses. If your indexer attributes the whole transaction to whoever signed it, you will make the batcher look like the biggest whale on the chain. Attribute each payout to the address in the corresponding order datum.</p>
<h3>5. Fees come in layers</h3>
<p>The user pays the normal network fee to place the order. The batcher earns a flat fee per order for execution. The pool charges its swap fee, which usually stays in reserves and accrues to liquidity providers. These are three different numbers with three different recipients. Mixing them up makes fee revenue charts wrong in confusing ways.</p>
<h3>6. Each DEX encodes datums its own way</h3>
<p>There is no universal order datum. Every protocol defines its own schema for orders and pool state, and versions change. A robust indexer keeps a parser per protocol and version, keyed by script hash, and fails loudly on an unknown shape instead of guessing.</p>
<h3>7. Your own wallet has contention too</h3>
<p>A wallet is also a set of UTXOs. Fire two orders back to back from the same wallet before the first confirms, and the second may try to spend inputs the first already used. That shows up in data as a burst of failed or delayed submissions that have nothing to do with the DEX itself.</p>
<h2>A quick mental model for your pipeline</h2>
<p>When you design a Cardano DEX indexer, think in three streams:</p>
<ul>
<li><strong>Intent stream.</strong> Order UTXOs created at order script addresses, decoded per protocol.</li>
<li><strong>Execution stream.</strong> Pool UTXO transitions, with reserve deltas and the set of orders consumed in each batch.</li>
<li><strong>Settlement stream.</strong> Payouts to user addresses, linked back to the order that caused them.</li>
</ul>
<p>Join them on order output references. Now you can answer real questions. Fill rate. Time to fill. Effective price versus quoted minimum. Batcher share of executions. Volume that actually moved reserves.</p>
<p>If you would rather explore those numbers than build the pipeline yourself, <a href="https://defitap.io">DeFiTap</a> tracks Cardano pools, tokens and DEX volume in one dashboard.</p>
<h2>The takeaway</h2>
<p>On Cardano, a swap is a conversation between your wallet, an order script, a batcher, and a pool UTXO. Read the data as that conversation, not as a single call, and your numbers stop lying to you.</p>
<p>Not financial advice. Do your own research.</p>
<p>Track Cardano DeFi in one tap at <a href="https://defitap.io">https://defitap.io</a></p>
]]></content:encoded></item></channel></rss>