What an intent-based swaps frontend has to stop promising

July 18, 20266 min readBy Harman Kamboj
IntentsSolversWeb3DeFi

For most of the years I spent building swap and bridge interfaces, the shape of the job never really moved. The user picks a token pair, you quote a price off a pool or a router, they sign one transaction, and you sit there watching for the receipt. Intent-based swaps take that loop apart. The user no longer signs a transaction that says how to move state. They sign a wish that says what outcome they want, and a network of off-chain solvers competes to deliver it. If you are building an intent-based swaps frontend, the hard part is not the signing. It is being honest about a result you no longer own.

I have watched teams bolt an intent flow onto a UI that still thinks it is quoting a Uniswap pool, and the seams show up fast. So here is what actually changes once a solver stands between your user and the chain, written from the parts that bit me.

The quote is now a hope, not a price

In a classic router swap, the number you show is close to the number the user gets, minus slippage and gas. You are reading the same pool the transaction will hit. With intents, the amount you display is an estimate of what some solver might fill, and the real fill happens later in an auction you cannot see from the browser. CoW Protocol batches orders and matches them against each other before it ever touches a pool. UniswapX runs a Dutch auction where the price the user accepts is a floor, not a target. So the friendly "you will receive 1,204.6 USDC" is doing more work than it looks like.

The fix is not a better estimate. It is a UI that says what the number actually is. I show a minimum received as the real promise, because that is the value the signed order enforces, and I treat the mid estimate as a maybe. This is the same discipline I argued for in my notes on building a gas-aware frontend. If a number can be worse than what you print, print the worse number as the commitment and let the upside be a pleasant surprise.

You are waiting on a solver you do not control

A router swap resolves on its own timeline. You submit, it lands or it reverts, and either way the chain tells you within a block or two. An intent sits in a mempool of orders waiting for a solver to decide it is worth filling. Most of the time that is fast. Sometimes it is not, because the pair is thin, the size is awkward, or the market moved and no solver can fill inside the limit the user signed. Your UI has to hold a state that the old flow never had, which is "signed, accepted, and still waiting."

I have seen frontends treat that gap as a spinner and nothing else, and users read a long spinner as a hang. So I give the pending window its own honest state. Order received, solvers looking, and a plain note that it can take a bit longer for larger or less liquid trades. When I have a deadline from the order itself, I show it counting down, because a visible deadline feels different from a spinner that might never end.

Failure looks different, so it has to read different

The old failure was a revert. Gas spent, transaction on chain, red toast, done. Intents fail in quieter ways. The order can expire because no solver filled it before the deadline. It can be filled at the floor when the user was eyeing the estimate, which is not a failure at all but reads like one if you only advertised the rosy number. On chains where signing the order costs nothing, an expiry can leave the user with no on-chain trace, which is great for their wallet and confusing for their trust if the UI does not explain it.

Every one of these needs its own copy. Expired is not reverted. Filled below your estimate is not a bug. I learned the hard way with ordinary swaps that vague failure states generate support tickets faster than almost anything else, which is half of what my writeup on token swap frontend pitfalls is really about. Intents add three new endings, and each one deserves a sentence a normal person can read.

Approvals and signatures moved around too

Intents change the signing story in a way that helps you if you plan for it. Most intent systems take a gasless off-chain signature rather than an on-chain approve and swap, so the wallet prompt is one signature over typed data, not a transaction. That pairs well with smart accounts. Once EIP-7702 lets a plain wallet carry code, you can bundle the token permit and the order into a single signed object instead of dragging the user through two prompts. The catch is that a typed-data signature is harder for a user to read than a transaction, and a signed order that points at the wrong settlement contract is exactly the kind of thing phishing loves. So I surface what the order authorizes in plain language before the prompt, not after.

Where this is genuinely better

I am not down on intents. When the wiring is right they fix real pain. Batching orders means one user's sell can be another's buy without either touching a pool, which trims cost. Solvers route across venues so a thin pair on your home chain can still fill from liquidity somewhere else, which is the cross-chain UX people actually wanted when I was stitching bridges together by hand. And handing execution to a competitive auction takes a class of MEV off the user, since the solver eats the routing risk instead of the trader. I spent a good while on venue design in my writeup on DeFi DEX architecture, and intents solve some of the exact edges that were painful to handle inside a single AMM.

What I would build first

If I were adding intents to a swap product tomorrow, I would start with the states, not the happy path. Wire the pending window as a first-class screen with a real deadline. Show minimum received as the promise and the estimate as a maybe. Write distinct copy for filled, filled at floor, and expired. Only then would I polish the quote. The demo of an intent swap is one clean click, and that click is the easy 20 percent. The other 80 percent is telling the truth about an outcome a solver decides after the user has already let go. If you want more of how I think about the wallet-facing layer, it is collected in my Web3 and on-chain notes, and the rest of the work is on the homepage.

Building something where this matters?

I am open to senior full-stack, Web3, or AI engineering roles, fully remote and any timezone. If your product's hard part is the swap layer, the on-chain data, or the parts that quietly break under real users, that is the work I like.

Get in touch →