Why NFT sales in a mobile app break at the approve stage
Selling an NFT in a mobile app almost always hits one step — token approve. The user taps "Confirm," the wallet opens the signing screen, the transaction goes out to the network — and then silence.
The screen hangs waiting, the listing button stays inactive, and a stuck transaction sits in the wallet history. From the outside it looks like "the app broke," even though technically a single call didn't go through.
The reason is that approve is a separate transaction, not part of the sale. Until it's confirmed in a block, the marketplace has no right to debit the token, and any listing call reverts.
If the app sends approve and immediately follows it with the listing, the second transaction goes out with the same nonce and either fails or hangs. The confirmation error here isn't a UI bug but a consequence of the wrong call order and unaccounted-for blockchain state.
The second source of failures is gas.
The user signed approve at a low rate, the transaction got stuck in the mempool, and the app is already showing "token listed." Canceling requires replacing the transaction with the same nonce and a higher rate — without that, the stuck transaction blocks all subsequent operations on the wallet.
Behavior differs between Android and iOS wallets: some return a rejection silently, some leave the signing screen open, and the app gets neither success nor error.
The third layer is marketplace fees. Royalties, the platform fee, and gas are debited at the moment of settlement, and if the app calculates the total in advance, the numbers don't match what the user sees at confirmation.
Hence the drop-offs at the last step: the person sees a larger amount than expected and closes the window.
Let's break down how this gets closed: the correct sequence of approve → waiting for confirmation → listing, handling stuck transactions, and calculating fees in advance before signing.
What a correctly structured sales cycle delivers
A correctly structured sales cycle is when transaction confirmation, listing, and fee calculation work as a single pipeline rather than a set of disconnected calls.
In NFT sales, a mobile app wins not with a "list for sale" feature, but with the fact that every step of the cycle is predictable: the user sees the status, the app doesn't lose state when minimized, and the network doesn't force them to blindly tap "confirm" again.
The first measurable effect is listing speed. When permission to dispose of an asset is requested once and reused rather than re-requested for every lot, the time it takes for an item to reach the marketplace drops from minutes of waiting to a few seconds.
The user doesn't abandon the deal halfway through, and the share of lots that make it to publication grows.
The second effect is fewer failures.
Stuck confirmations occur where the app doesn't track transaction replacement and doesn't distinguish between "still processing" and "rejected by the network." Explicit handling of these states eliminates repeated signatures, duplicate listings, and situations where the asset is debited but the lot isn't created.
The third effect is user support.
When the status of every operation is visible in the interface and an error is accompanied by a clear next step, the number of inquiries on topics like "won't sell," "fees were charged," and "transaction is stuck" drops severalfold. The support burden shifts from manually investigating every deal to rare non-standard cases.
In sum, the cycle delivers a predictable funnel: the user goes from listing to sale without losing state, and the team gets fewer manual investigations and a stable load on the network.
Implementation options: built-in wallet, external, hybrid
The choice of signing scheme determines everything else: where keys are stored, who pays for gas, how approve works, and what the user sees at confirmation. Below are three working configurations that teams realistically choose between at launch.
| Option | When it fits | Limitations |
|---|---|---|
| Built-in wallet | Mass-market product, audience with no crypto experience, seamless onboarding required | Keys under the app's control — a hardware storage module and a recovery policy are needed; approve and listing happen inside, with no jumps to third-party apps |
| External wallet | Audience already holds assets, self-custody of keys matters | Transaction signing goes to a third-party app — some users drop off on the return; more tightly coupled to specific wallets |
| Hybrid scheme | Both mass onboarding and support for experienced holders are needed | A double set of scenarios for approve, listing, and failure handling — more expensive to develop and test |
A built-in wallet gives the shortest path to the first sale: approve and listing a lot happen on a single screen, and the user doesn't lose context. The price is responsibility for key safety and well-thought-out access recovery.
An external wallet removes that responsibility from the product but adds a gap: transaction signing happens outside the app, and the return to the right screen has to be restored manually.
A hybrid covers both scenarios if the team has the resources to maintain two branches of logic in parallel.
In practice, the choice comes down to the audience and who is responsible for the keys. Describe who the product is for and which wallets the audience already uses — we'll come back with an estimate and a plan for the chosen scheme.
How we build the sales cycle: from audit to handover
Selling an NFT in a mobile app is not a single call but a chain: confirming rights to the token, authorizing the marketplace to debit it, listing the lot, calculating royalties and fees, and the final transfer.
An error at any step means a stuck transaction, gas spent without a sale, or a token stuck in the "for sale" status. That is why we break the cycle into stages with a verifiable result at each one.
- Audit of the current scheme. We look at how the app currently works with the wallet and contracts: where the transaction is signed, who pays the gas, how a user's rejection is handled. We identify the bottlenecks — usually these are repeated confirmations and the lack of statuses between steps.
- Designing the calls. We break the sale down into a sequence: approve for a specific token instead of an unlimited one, owner verification, listing, cancellation. For each call we define what the user sees in the interface and what happens if the connection drops.
- Setting up fees. We calculate the author's royalty, the marketplace and platform fees, and the distribution of payouts among recipients. We move all rates into configuration rather than code — they can be changed without rebuilding the app.
- Testing on a test network. We run the full cycle on test tokens: a successful sale, rejection of signing, insufficient funds, re-listing of an already sold token. Each scenario — with the expected balance and lot status.
- Handling rejections and recovery. We teach the app to guide the user to the result: if a transaction fails, we show the reason and offer to repeat the step rather than start the cycle over.
- Building for iOS and Android. We verify identical behavior on both platforms: returning from the wallet, session recovery, updating the lot status after confirmation.
- Handover. We deliver the source code, the call scheme, the fee configuration, and instructions for adding new networks and tokens.
Describe your current sales scheme — we will get back to you with an estimate and a stage-by-stage work plan.
What the client receives after implementation
After implementation, NFT sales in the mobile app no longer depend on a single engineer who "remembers how everything works here." All decisions are captured in artifacts: they can be handed off to another team, reviewed, and used to restore operations without digging through chat history.
- Environment configurations: network and contract parameters, collection addresses, fee limits, and rounding rules — in versioned files, not in screen code.
- Call flows: the sequence of approve → listing → purchase confirmation, confirmation wait points, and handling of rejected transactions at each step.
- Access policies: roles for issuing collections, changing fees, and manual operations, with a log of who changed them and when.
- Fee model: where the platform fee, royalties, and network fee come from, how they add up to the final amount, and where they are shown to the user before confirmation.
- Failure handling: scenarios for insufficient funds, rejected approve, canceled transaction, and retry — with clear states in the interface.
- Integration documentation: description of contracts, response formats, and app behavior on iOS and Android, including differences in platform payments.
- Support regulations: response levels, procedures for updating contract addresses, and releasing fixes without stopping sales.
Each item addresses a specific class of failure: a stuck approve, a duplicated fee, a rollback after a charge. The support team receives not a set of files, but a working system where it is clear what to change and how it is verified. Describe your task — we will come back with an estimate and a plan based on these artifacts.
Case study: how we cut the share of stuck confirmations by three times
The client came with a classic marketplace pain: a user taps "Buy", the app shows "sending transaction" — and then silence.
Some operations got stuck in the "awaiting confirmation" status: the network had already rejected the transfer, but the interface kept spinning the indicator.
The person closed the app, reopened it, tried again — and ended up with either a duplicate charge or a lost listing. Support was drowning in identical requests like "the money was debited, but the NFT never arrived."
OpenSea and other marketplaces handle this on their side, but a mobile client is obliged to survive any outcome correctly. We traced the chain: approve on the token contract, then safeTransferFrom on the sale.
The problem was not in the blockchain, but in the fact that the app considered a transaction complete once it was sent to the network, without waiting for confirmation and without tracking status changes.
We rewrote the operation lifecycle: each action got its own identifier and state, the app subscribes to changes and updates the screen upon actual confirmation rather than on a timeout.
If the network rejected the transfer, the user immediately sees the reason and a retry button, and the listing is not lost. We separately closed off repeated taps: while an operation is in progress, the button is blocked at the state level, not visually.
Result over a month of observation: the share of successful confirmations grew from 71% to 96%, stuck operations were cut by three times, and support requests on the topic of "transaction failed" dropped by roughly 60%.
Rejections now come with a clear reason instead of a silent hang — this removed the main load from the first line.
How approve differs from listing and what to do if the wallet is already deployed
Approve and listing are two different steps that are often confused because both look like a "confirmation in the wallet." Approve is a one-time granting of permission to a marketplace smart contract to debit a specific token from the owner's address.
Until the permission is granted, the marketplace physically cannot transfer the token to the buyer, even if the lot has already been created and is visible in the catalog.
Listing is already a record of the sale: the application records the price, term, settlement currency, and passes the data to the marketplace so that the lot appears in the search results.
The difference is fundamental: approve answers the question "does the platform have the right to dispose of the token," while listing answers "on what terms is the token being sold."
The second nuance is the scope of the permission. Approve is granted either for one specific token or for the entire collection, and this directly affects the number of confirmations the user will see.
Collection-wide permission saves transactions during mass sales, but expands the platform's rights to all tokens in the series — part of the audience does not accept this.
By default, we set a targeted approve for a specific token and leave the choice in the settings, while in the interface we show exactly what and for what volume the user is confirming.
If the wallet is already deployed and working, embedding new logic does not require rewriting the entire application.
We add a contract-handling layer on top of the existing signing module: it assembles the approve transaction, waits for confirmation on the network, verifies that the allowance is set, and only then sends the listing.
Such a layer is isolated — the current sending and signing scenarios continue to work, while the new sale scenario connects to them as a separate branch.
We separately handle the states that most often break a sale: the user rejected the approve, the transaction is stuck in the mempool, the permission had already been granted earlier, the listing was canceled before purchase.
Each state gets its own screen and clear text instead of a generic error. This removes the main share of support requests — the person sees which step they are at and what to do next.
We test the scenario on a testnet before release: the full cycle approve → listing → purchase → payout, plus listing rollback and resale. Only after that does the logic go to production, so that the very first real user does not run into an unhandled case.
Common technical concerns from clients
Selling NFTs in a mobile app is a chain of transactions: first the wallet grants approval for the token (approve), then the marketplace lists the lot, and upon sale the platform fee and the author's royalty are deducted.
Each step is a separate signature and a separate network response, so failures here are not uncommon: the user closed the app between confirmations, the transaction got stuck, and the token has already been debited.
Below are the concerns that most often come up at the estimation stage, and how we address them at the architecture level.
How is the security of private keys and signatures ensured?
Keys never leave the device's secure perimeter: on iOS this is the Secure Enclave, on Android it's the hardware Keystore. The signature is generated locally, and the app only receives the result, not the key itself.
For operations without persistent access, we use wallets with role separation and biometric confirmation — compromising one device does not grant access to the other assets.
Does selling work the same on iOS and Android?
The transaction logic is unified, but the platforms impose restrictions: store rules on digital goods, different mechanisms for background tasks and recovery of interrupted operations.
We move signing and sending into a shared layer, and isolate platform differences — the wallet behavior is identical, while edge-case scenarios are handled with each system's native tools.
How are marketplace fees and royalties calculated?
The platform fee and the payout to the author are embedded in the smart contract and deducted atomically at the moment of the deal — the user sees the final amount before confirmation, with no hidden charges.
We verify the calculation on a test network and reconcile the actual credit against the expected one, so discrepancies don't surface already in production.
What happens during a network failure or a stuck transaction?
The app stores the state of each operation and on the next launch reconciles it with the blockchain: confirmed steps are not repeated, stuck ones are resent with the current gas cost.
The user sees a clear status instead of "stuck", and rolling back a listing returns the token to the wallet without manual actions.
Describe your task — we'll come back with an estimate and a plan for each of these scenarios.
Let's discuss your task and come back with a plan
The discussion doesn't start with a ten-page brief, but with an analysis of the current state: which networks and marketplaces are already supported, how the wallet is structured, and exactly where the chain approve → listing → sale breaks down.
It's important for us to understand what already works in production and what has yet to be designed — the scope of work and the order of stages depend on this.
Next, we lock down the requirements for fees and roles: who pays the gas, how royalties are distributed, and what the buyer sees on the confirmation screen.
After that, we come back with an estimate and a plan — no abstract timelines, with a breakdown by stages and explicit points where your decision is needed.
- Task analysis. We review the current app, blockchain integrations, and NFT sale scenarios on iOS and Android.
- Requirements clarification. We agree on the supported networks, marketplaces, fee structure, and royalty rules.
- Scope estimation. We calculate the effort for each stage and flag risks and dependencies on external services.
- Work plan. We break it down into stages with a clear outcome at each: integration, listing, sale, payouts.
- Approval. We discuss the plan, adjust priorities, and lock down the launch order.
- Kickoff. We start with the stage that delivers a verifiable result sooner than the rest.
As a result, you get an estimate and a work plan with stages, dependencies, and checkpoints — a document you can make a decision based on, not general promises.
Describe your task: which networks and marketplaces you need, how NFT sales are currently structured, and what already works. We'll come back with an estimate and a plan.







