NFT Marketplace 6.1.4

29 July 2026

This release has upgrade notes. Read them before updating — they describe behaviour changes that need your attention.

MONEY FLOWESCROWROYALTIESAUCTIONSSCHEDULINGRELIABILITYSETTINGSUICLEANUPKYCBACKUPSADMINPERFORMANCEMULTI-CHAIN

NFT Marketplace v6.1.4

Release Date: July 29, 2026 Tags: MONEY FLOW, ESCROW, ROYALTIES, AUCTIONS, SCHEDULING, RELIABILITY, SETTINGS, UI, CLEANUP, KYC, BACKUPS, ADMIN, PERFORMANCE, MULTI-CHAIN

Overview

Version 6.1.4 repairs the custodial half of the marketplace. Accepting an NFT offer was impossible — every attempt failed with a server error while the buyer's funds stayed locked in escrow. Rejecting or withdrawing an offer either failed outright or silently stranded the marketplace fee in the buyer's held balance forever. Auctions accepted any bid at all once a single bid stood, and five auction screens failed with a server error on every request. Creator royalties were charged to the buyer, deducted from the seller and paid to nobody. And every marketplace feature toggle did nothing in the "off" direction.

It also makes scheduled blockchain-state backups actually run — a schedule you created did nothing, silently, and reported success — and puts the platform's per-level KYC feature switches in charge of NFT actions for the first time.

Three of the steps below look for money and settings a past defect has already left wrong. Run them.

Requires Core v6.5.8.

Update Instructions

pnpm updator

Then, in this order:

1. Restart the backend

The money-handling and settlement changes load at boot, and the backup cron job is registered there. To confirm scheduling is active, look for "Process NFT Blockchain Backups" in the admin cron monitor.

pm2 restart all

2. Find buyers with funds stranded in escrow

Offers made before this release either could not be settled (acceptance 500'd) or were released short by the marketplace fee. Both leave money held against an order that the buyer cannot spend. To find it:

SELECT o.id AS offerId, o.userId, o.amount, o.currency, o.status,
       (SELECT t.amount FROM transaction t
        WHERE t.idempotencyKey = CONCAT('nft_offer_hold_', o.id)) AS held
FROM nft_offer o
WHERE o.status IN ('CANCELLED', 'REJECTED', 'EXPIRED')
ORDER BY o.createdAt DESC;

Any row where held is set and the offer is in a terminal state was supposed to be fully released. Re-running the expiry cron does not re-release an already-released hold, so residues have to be corrected against the wallet's held balance. Contact support before adjusting balances by hand.

3. Re-check your marketplace fee

The offer path read a settings key that does not exist (nftMarketplaceFee) and always fell through to a hardcoded 2.5%, while direct purchases honoured the real key. Both now read nftMarketplaceFeePercentage. If your configured fee is not 2.5%, offers will now charge what you configured — confirm it is what you intend.

4. Re-check your feature toggles

Every NFT toggle was inert when switched off. Anything you believed was disabled — auctions, offers, fixed-price sales, anti-snipe, metadata validation — has in fact been running. Open the NFT settings screen and confirm the current state is what you want before traffic hits it.


Upgrade Notes

No breaking changes in setup. Three behaviour changes worth knowing:

  • Offer settlement amounts changed. The seller now receives the amount minus the royalty rather than the amount minus the fee and the royalty, and the creator is actually paid the royalty. Any report that reconstructed seller proceeds with the old formula will disagree with the ledger.
  • Feature toggles now take effect. Anything currently switched off in the NFT settings screen will start being enforced after the restart.
  • Verification requirements now apply to NFT actions. The per-level KYC feature switches govern creating, minting, listing, transferring and deploying for the first time, and the high-value purchase check now recognises fiat-priced sales it previously converted to nothing. Confirm both your per-level switches and your high-value threshold before traffic hits them.

A backend restart is required so the backup schedule is registered. No database migration and no configuration change.


Added

Chain and coin logos across the marketplace

Real chain and coin artwork now appears everywhere the marketplace shows a network or a price — the landing page, the marketplace grid, token and collection pages, creator profiles, create and batch mint, the offer and deploy dialogs, and the gas estimator. A collection with no logo of its own now shows its initials instead of a broken-image glyph.

The same pass corrects four labels that were simply wrong:

  • Trending collections: floor price and volume were labelled BNB on every card, whatever chain the collection actually lived on. Each card now shows its own chain's currency, sent along with the card rather than guessed at.
  • 24h Volume on the landing page: suffixed BNB, although the figure is one total across every completed sale with no separation by currency — wrong on any multi-chain install. The ticker is gone; the figure itself is unchanged.
  • Gas estimator: printed the chain's name where the coin's name belongs — "0.0012 BSC". It now names the coin.
  • Multi-chain grid: drew a coloured square with two letters in it in place of each coin's logo.

Enable Public Mint on the collection edit screen

A creator can now open public minting on their deployed contract straight from the collection edit screen. Before sending, it checks that the connected wallet actually owns the contract, so a non-owner gets a clear message instead of paying gas for a send that reverts.


Changed

The NFT landing page and the marketplace and admin screens were redesigned

The landing hero was rebuilt on the platform's shared landing design, and the blue, purple, pink, green and amber colour values written directly into roughly fifty screens were replaced with the platform's theme colours — so the NFT pages follow light and dark mode the way the rest of the product does. A decorative grid overlay that was invisible in light mode is gone, along with the animated background blobs behind the hero.

  • Fixed: several admin status colours that rendered two different states identically. Dispute priority High was indistinguishable from Medium, and dispute status Investigating was indistinguishable from Escalated. Each pair now reads apart at a glance.
  • Fixed: the category and blockchain distribution charts on the admin NFT analytics dashboard picked a random colour per slice every time the page drew, so a category changed hue whenever anything on the screen updated and the legend could not be trusted between two glances. Both now use a fixed palette that follows your theme, assigned by position.

Performance

Backups no longer stall the server, and their checksum verifies

Creating and restoring a backup compressed and wrote its file synchronously, which blocks the same process that serves the marketplace, the live market feed and every other scheduled job for as long as the backup takes. A large chain froze everything.

  • Changed: compression and file access no longer block, and records are read in pages of 1,000 instead of loading the lot at once.
  • Fixed: backup files were written indented for human reading while their checksum was calculated on the compact form — so every stored checksum failed verification. Files are now written compact, which both verifies and roughly halves the file size.

Offer expiry and auction settlement work in bounded batches

Both scheduled jobs walked their entire result set in one run, doing a wallet-locking money movement or an on-chain settlement for each row. After an outage, or with any real backlog, a single run loaded everything at once and held wallet locks for its whole duration.

  • Changed: a run takes at most 500 expired offers and 100 ended auctions, oldest first, and resumes where it left off on the next run. On a marketplace that is keeping up, nothing changes.

Fixed

Security

NFT actions now honour the per-level KYC feature switches

The platform's KYC screens let an administrator enable or disable Create NFT, Sell NFT, Transfer NFT and Deploy NFT Contract for each level. The NFT marketplace never consulted any of them. A level with every NFT feature switched off could mint, list, transfer and deploy exactly like a fully verified one.

  • Changed: creating a collection, minting, batch minting, listing a single NFT or a batch, starting an auction, transferring a token and deploying a contract are all checked on the server. The matching screens — create, collection create, batch mint, the token page, the listing form and the deploy dialog — now show a verification notice in place of the action, rather than a button the server will refuse.

The high-value purchase threshold could not read a fiat-priced sale

Converting a sale price to USD looked the currency up by its display symbol rather than its code, and in the cases where it would have matched it multiplied by the stored rate instead of dividing by it. A sale priced in a fiat currency therefore converted to nothing, never reached your high-value threshold, and skipped the extra verification check entirely. Sales priced in USD, USDT, USDC, DAI or BUSD, or in a listed ecosystem token, did convert.

  • Changed: fiat prices convert correctly.

Accepting an offer was impossible

Every attempt to accept an offer failed with a server error. The buyer's funds had already been escrowed when the offer was made, and there was no path that could settle them. The message shown — "An unexpected error occurred while accepting the offer" — told nobody anything.

  • Changed: offers can be accepted, and genuine failures now say what actually went wrong.

Auctions, bidding, the live market feed and the admin marketplace overview all returned a server error

Five separate screens tried to load a bid's bidder under a name that does not exist, so every one of them failed outright. Browsing auctions, opening an auction, placing a bid, the live market feed on the marketplace and the admin NFT marketplace overview each returned a server error on every request. Auctions were unusable end to end — you could not see them, open them, or bid on them.

  • Changed: all five load. Opening an auction also stopped trying to attach a creator that is stored separately, which was a second failure sitting on the same screen.

Rejecting or withdrawing an offer stranded the marketplace fee — or failed outright

Releasing an escrowed offer recalculated the amount incorrectly. Depending on the fee, the offer amount was released and the fee left in the buyer's held funds permanently — or the calculation produced nonsense and the offer could not be rejected at all.

  • Changed: every release returns exactly what was reserved. That also fixes a second problem: recalculating from the current fee diverged whenever an admin changed the fee in between, either over-releasing (draining other operations' held funds) or under-releasing (stranding the remainder).

An offer escrowed 2.5% no matter what your marketplace fee was

Making an offer read a fee setting the platform does not store and fell through to a hardcoded 2.5%, so the buyer's held funds were always the offer amount plus 2.5% — while acceptance settled the hold and collected the platform's cut at the fee you actually configured. On a marketplace charging 5%, the difference was created out of nothing on every accepted offer. On one charging 0%, the buyer was overcharged 2.5% and never given it back.

  • Changed: the hold is sized at your configured marketplace fee, so what is escrowed when an offer is made is exactly what settlement consumes. This is the change update step 3 asks you to re-check your fee for.

Creator royalties were charged and then destroyed

The buyer paid the amount plus the fee, the seller received the amount minus the fee and the royalty, and the platform collected the fee. The royalty was deducted from the seller and paid to nobody, and the marketplace fee was charged twice. On a 200 sale with a 2.5% fee and a 5% royalty, 12.50 vanished on every trade.

  • Changed: the buyer pays the amount plus the fee; the seller receives the amount minus the royalty; the creator is paid the royalty; the platform takes the fee. What leaves the buyer now equals exactly what reaches the seller, the creator and the platform.

A collection could charge more royalty than the platform allows

Creating a collection allowed royalties up to 50% while the platform maximum is 10%. Direct purchases capped at the maximum; offer acceptance did not. The same NFT therefore paid a different royalty depending on how it was bought, and a creator who set 40% was shown earnings they would never receive.

  • Changed: creation refuses a royalty above your configured maximum, and acceptance caps to it as purchases always did.

An auction accepted any bid once a single bid stood

The minimum-increment check never worked. With a standing bid of 120 and a 10 increment, a bid of 15 was accepted and became the new highest bid. The minimum increment did not exist in practice.

  • Changed: a bid below the standing bid, or one that does not clear the increment, is refused.
  • Fixed: a second bidding path calculated the minimum bid on a 100 auction as "1000.01" and refused every reasonable bid with a nonsensical figure.

One stuck auction settlement froze every auction behind it

The settlement job waited indefinitely for the on-chain end-auction transaction to confirm, and it only releases its single-run lock once that wait finishes. A single transaction that never mined stopped every later auction from settling until the backend was restarted.

  • Changed: the wait is capped at two minutes. On a timeout the transaction hash is written to the log so an operator can verify it on chain before retrying, and settlement moves on to the next auction.

Scheduled blockchain-state backups never ran

Creating a schedule returned success and the backup never happened. Three separate schedulers had been written for this feature and none of them was running — one was complete but never registered, one was never called, and one only lived inside whichever process happened to serve the admin request and was lost on every restart.

  • Changed: backups are now run by a proper scheduled job under the nft category, checking every 15 minutes. The finest schedule the admin screen offers is hourly, so a due backup fires close to its time instead of drifting. The in-process timers have been removed rather than wired — they could not run alongside the scheduled job without backing up twice, and they could never survive a restart.
  • Nothing about the admin screen or your saved schedules changed. Existing schedules are picked up on the next check with no migration.

Incremental blockchain backups contained no records and reported success

An incremental backup wrote a file with nothing in it, and the screen reported the run as successful. Two further failures followed from the same cause: an incremental run saved no record of itself, so the next run had no window to measure changes from, and old files were never pruned on a schedule that only ran incrementals, so they accumulated without limit.

  • Changed: an incremental backup now contains the collections, tokens and listings that changed since the previous run, records itself, prunes old files, and falls back to a full backup when the previous run's record cannot be read.
  • The admin backup screen and your saved schedules are unaffected and need no further action.

Backup retention deleted the newest full backups first

Once a chain passed 30 stored backup files, retention deleted the wrong ones. It ordered files by name, which ranks every incremental ahead of every full snapshot, and "block 9" ahead of "block 12345" — the date in the name was never reached. Operators lost the full snapshot the deltas restore against, and kept deltas with nothing left to apply them to.

  • Changed: retention orders by each file's own modification time, and never deletes the newest full backup no matter what else is due for removal.

Every marketplace feature toggle did nothing when switched off

Auctions, offers, fixed-price sales, anti-snipe, metadata validation and the high-value KYC requirement could all be switched off in the admin screen with no effect whatsoever.

  • Changed: toggles now take effect. Disabling auctions genuinely stops auctions being created.

Three user-facing pages returned an error page

/nft/collection, /nft/token and /nft/user returned an error instead of redirecting, so any visitor who trimmed an id off a URL hit an error page.

  • Changed: they redirect properly, keeping the language the visitor was browsing in.

The Follow button never worked

Every press on a creator's profile came back with "User Id is required.; Action is required." It could not have unfollowed either.

  • Changed: following and unfollowing both work from the profile page.

The onboarding checklist was refused for every user

The creator onboarding progress required an admin permission that no customer holds, so the checklist failed for everyone while the rest of the marketplace worked.

  • Changed: it works for signed-in users, like every other user-facing NFT screen.

The Batch Mint page led nowhere

The Batch Mint screen posted to something that did not exist, and creator onboarding linked users straight there — so every batch ended in "Batch mint failed" with nothing created.

  • Changed: batch creation now works, and does what this platform can honestly do: it creates the tokens as drafts in one pass, so a creator can prepare a whole drop at once, checking that the collection is theirs and capping royalties at the platform maximum. It explicitly refuses to batch mint on chain: minting here is confirmed after the creator's own wallet signs it, and there is no server-side wallet to sign with. Asking for one now returns that explanation instead of silently creating tokens the caller believes are minted.

A sale whose transfer never happened was left that way forever

Accepting an offer settles the money — the buyer's escrow is consumed, the seller is paid, the creator gets their royalty, the platform takes its fee — while ownership only moves when the buyer confirms the on-chain transfer. If that confirmation never arrived, nothing happened at all. The seller kept both the payment and the NFT, the buyer had neither, and no screen anywhere said so.

  • Changed: accepted sales whose transfer never completed are now swept up (default grace 24 hours, adjustable). The sale is reversed in full — seller, creator royalty and platform fee all give back exactly what they received, the buyer is refunded everything they paid including the marketplace fee, and the listing goes back on sale. A repeat sweep pays nobody twice.
  • When it cannot be reversed: if a recipient has already spent the money, nothing moves at all. A partial reversal would leave the books in a state nobody can reason about, so the sale is instead flagged to admins with the exact shortfall — who holds what, and how much the buyer is out.

Admin NFT screens rendered as empty instead of reporting a failure

When a request failed, the screen was indistinguishable from "there is nothing here" — an analytics dashboard with no figures, a dispute board showing zero disputes, an onboarding checklist with nothing ticked. An administrator had no way to tell an outage from a quiet marketplace.

  • Changed: analytics shows its error state, the dispute board raises a message, admin onboarding falls back to the progress stored in the browser, and the gas estimator explains why an estimate failed instead of failing silently.

The admin CRM could not show a user's NFT sales

Opening a user in the admin CRM and looking at their NFT sales failed outright rather than listing anything — the lookup filtered on a user reference that is not part of a sale record at all.

  • Changed: it returns the sales where that user was the buyer or the seller.

Money values compared and added as text

The root cause behind the offer and bid defects above. Money values were being handled as text, so multiplication looked correct while addition and comparison silently produced nonsense.

  • Changed: all 27 money fields across the NFT feature are now handled as numbers, so the same mistake cannot be made again.

Smaller corrections

  • A backup run in which every schedule failed reported success. If every due schedule in a run failed, the run still finished as completed in the admin scheduled-job monitor, and nothing anywhere surfaced the failure. A run in which nothing succeeded is now reported as failed, while a run where only some schedules fail still isolates the bad one and continues with the rest. Status and log lines now carry the job's registered name, so they land on the Process NFT Blockchain Backups row the update instructions point you at.
  • The dispute board was narrower than every other admin screen. It drew its own page frame inside the page's frame, so it sat visibly inset next to the rest of the admin area. It now uses the standard admin page width.
  • The Active toggle heading showed as raw text on six admin screens. On the admin auction, collection, creator, listing, offer and token screens the heading above the Active toggle was read from somewhere that does not define it. It now reads the shared Active label, in the visitor's language.

Removed

Four support modules had no reachable caller and were removed:

  • The IPFS service — non-functional by construction, not merely unused. Its client always returned nothing and every upload would have sent an empty file. Platform-hosted pinning was deliberately abandoned in v6.1.3; the supported path is your own IPFS provider (Pinata / NFT.Storage / Web3.Storage) with gateway fallback at mint time.
  • The metadata backup service — superseded by the blockchain backup service, which does strictly more and is live behind the admin backup screen. It also depended on the broken IPFS service above.
  • The blockchain recovery service — incompatible with the wallet-signed mint flow; transactions are confirmed at mint time instead.
  • The gas estimation service — superseded by the live gas estimate feature.

The blockchain backup service is retained — it is the engine behind the admin backup screen and the newly-scheduled backups, and it was repaired in this release rather than removed.