26 KiB
Volana — Consumer Frontend Design Brief
1. What is Volana?
Volana is a decentralized, censorship-resistant marketplace — think eBay, but on Solana. The primary inspiration is eBay's consumer UX (browse listings, view a product, buy it), with two fundamental differences:
-
Nobody can censor it. No government, no company, no intermediary can remove a listing or block a transaction. The marketplace is governed entirely by open-source smart contracts on Solana. Anyone can list anything, and no third party can intervene.
-
Payments are final and predictable. Unlike PayPal (which can reverse a payment weeks later) or traditional card payments (chargebacks), payments on Volana go through on-chain escrow contracts. Once the buyer releases the funds, they are final. The entire payment flow is encoded in open smart contracts — anyone can read exactly what will happen before they sign anything. There are no hidden fees, no unexpected reversals, and no intermediary who can freeze your funds.
Target audience for this design: Regular online shoppers who are crypto-curious or already have a Solana wallet (Phantom, Solflare, Backpack, etc.). They are used to eBay or Amazon. They do not need to understand blockchain to use Volana — but they should feel like they are on something more trustworthy and modern.
Scope of this design sprint: Consumer-facing frontend only. This means:
- Homepage / listing browse (like eBay's search results page)
- Listing detail page (like eBay's product page)
- The "place order" / checkout flow (connect wallet → confirm purchase)
- Wallet connect / account state in the nav
- My Orders / Order status
Out of scope for now: seller dashboard, dispute resolution UI, resolver management, technical on-chain explorer views.
2. Why Volana Exists — The Value Propositions (Use in Copy & Tone)
These are the core benefits. The design should make them feel real, not like marketing:
2a. True Freedom of Commerce
No government, no corporation, no payment processor can remove a listing or block a purchase. The marketplace runs on open-source contracts on a public blockchain. Even if the Volana website went offline, someone could spin up a new frontend that reads the same on-chain data and resume trading.
2b. Final, Predictable Payments
- PayPal/credit card problem: A buyer can initiate a chargeback 6 months after a sale. Sellers live in constant fear of payment reversals.
- Volana's solution: Payment flows through a smart contract escrow. The buyer locks funds in the escrow when placing an order. The seller confirms the order. The buyer releases funds when they receive the goods. Once released, the transfer is final — no third party can reverse it.
- Predictability: The exact payment flow (including dispute resolution) is encoded in open contracts. Anyone can audit them before transacting.
2c. Ultra-Low Fees
Solana transactions cost fractions of a cent. Volana charges no percentage fee — the only costs are Solana network fees (< $0.001 per transaction) and, if a dispute arises, the resolver's fee (typically 0.5–2% of the transaction, only charged if the dispute is actually resolved). Compare this to eBay (10–13%) or PayPal (3–4%).
2d. Permissionless Dispute Resolution
If something goes wrong, a neutral third-party resolver (chosen by the buyer at checkout, from a list the seller accepts) adjudicates the dispute. The resolver's ruling is enforced on-chain — neither buyer nor seller can override it. The resolver earns a small fee only when they rule on a case.
3. Brand Identity
Name
Volana — the consumer-facing brand. The underlying protocol is "Solisting/Descro" but regular users never need to know that. The brand is "Volana."
Personality
Modern, clean, trustworthy, slightly edgy (freedom angle), fast. Not "crypto bro" — approachable. Not corporate — honest. Not cheap — premium but accessible.
Tagline options (for reference)
- "Trade freely. Pay finally."
- "The marketplace nobody controls."
- "Buy anything. Pay once. For real."
Visual Mood
The design should feel like a dark-mode-first modern marketplace with a premium, slightly futuristic feel. Reference points: a modern SaaS product, not a financial terminal. Solana's brand identity (purple/green) can be an influence but doesn't have to dominate. The primary CTA ("Buy Now") should feel like the most important thing on screen wherever it appears.
4. Technical Context — What Data Exists On-Chain
The frontend reads two Solana programs:
4a. solisting program — Listings and Orders
ListingAccount (one per product listing):
seller: Pubkey— the seller's wallet address (32-byte Solana public key)name: String— product name (max 64 chars)description: String— product description (max 256 chars)metadata_uri: String— URL to a JSON file with additional metadata (image, more details) (max 256 chars)price: u64— price in the canonical currency's smallest unitcanonical_currency— eitherSol(native SOL, 9 decimals) orSpl { mint, decimals }(an SPL token)alt_currencies: Vec<AltCurrencyConfig>— other currencies the seller accepts (max 3). Price is auto-converted via Pyth oracle at order time.quantity: u32— total units availablequantity_reserved: u32— units currently held by pending orders. Available = quantity − quantity_reserved.is_active: bool— whether the listing accepts new ordersaccepted_resolvers: Vec<Pubkey>— resolvers this seller trusts. Empty = any registered resolver accepted.listing_id: u64— unique identifier per seller
OrderAccount (one per purchase):
listing: Pubkey— which listing this order is forbuyer: Pubkey— the buyer's walletseller: Pubkey— the seller's walletresolver: Option<Pubkey>— the dispute resolver chosen at checkoutpayment_currency— the currency the buyer chose to pay inamount: u64— the actual amount paid (oracle-computed if not canonical currency)escrow_account: Pubkey— the linked escrow on thedescroprogramcreated_at: i64— Unix timestamp
4b. descro program — Escrow State Machine
Each order has a corresponding EscrowAccount with a state machine:
AwaitingSellerConfirm → Active → Complete
↘ ↘ Cancelled
↘ Disputed → Resolved (Complete or Cancelled)
- AwaitingSellerConfirm: Buyer has locked funds. Waiting for the seller to confirm the order. Buyer can cancel for a full refund in this phase.
- Active: Seller confirmed. Funds locked. Buyer should receive the goods. Buyer can confirm receipt (→ Complete) or raise a dispute.
- Complete: Buyer confirmed receipt. Seller receives funds. Final.
- Cancelled: Either the buyer cancelled before the seller confirmed, the seller rejected, or a dispute was resolved in the buyer's favor. Buyer gets refunded.
- Disputed: A dispute was raised. A resolver will adjudicate.
For the consumer frontend, the relevant states are:
- When browsing: show available quantity (quantity − quantity_reserved)
- At checkout: the buyer places an order which goes immediately to
AwaitingSellerConfirm - In "My Orders": show order state + available actions
4c. Resolvers (dispute arbitrators)
ResolverEntry — registered dispute resolvers:
name: String— resolver's display namedescription: String— what they handle / their policyfee_bps: u16— fee in basis points (100 bps = 1%). Charged only if they rule on a dispute.resolver_type— e.g., Automated / Human / DAOacceptance_policy— AutoAccept (takes all cases) or ManualAccept (can decline)ruled_for_buyer: u32— historical rulings for the buyerruled_for_seller: u32— historical rulings for the seller
At checkout, the buyer selects a resolver from the list the seller accepts.
4d. Currency / Price Display Rules
- SOL: price in lamports (divide by 1,000,000,000 to get SOL). Display as "X SOL".
- SPL tokens: price in smallest unit (divide by 10^decimals). Display with token symbol.
- Stablecoins (USDC, USDT, etc.): oracle = None, $1.00 peg assumed.
- Alt currency prices are computed at order time by the on-chain oracle. The buyer passes an
expected_amountandmax_slippage_bpsto protect against price movement.
5. Page Inventory & UX Specification
Priority: Consumer Frontend Only
The design session should focus exclusively on the buyer experience:
- Homepage / Browse Listings (highest priority)
- Listing Detail / Product Page (highest priority)
- Checkout / Place Order flow (highest priority)
- Wallet Connect (integrated into nav)
- My Orders / Order Status (lower priority, can be a simple list)
The following are out of scope for this design sprint:
- Seller dashboard (create/manage listings)
- Dispute resolution UI
- Resolver management
- Technical on-chain explorer views
- Admin/protocol views
Page 1: Homepage / Browse Listings
URL: / or /browse
Purpose: The product catalog. Like eBay's search results or Amazon's browse page. The primary conversion surface.
UX Goals:
- Buyer should immediately see products and understand what Volana is
- Scanning products should feel fast — like a physical store, not a terminal
- Price, image, availability should be instantly readable
- Category/search/filter should be accessible without needing to know how blockchain works
Layout concept:
- Hero / value prop section at the top (first visit only, or collapsible): headline + 2-3 key benefit chips (e.g. "Final payments", "No censorship", "< $0.001 fees")
- Below hero: search + filter bar
- Product grid (primary): card-based layout like eBay. Each card has:
- Product image (from metadata_uri → JSON → image field; fallback: placeholder)
- Product name (from
listing.name) - Price prominently displayed (formatted: "1.5 SOL" or "12.00 USDC")
- Availability indicator: "In Stock" / "Low Stock" (when ≤ 3 available) / "Out of Stock"
- Seller abbreviation (first 4 + last 4 chars of wallet address)
- "Buy" button (opens checkout flow)
Filters / Search:
- Search bar: searches listing names and descriptions
- Filter by currency: All / SOL / USDC / Other
- Filter by price range
- Filter by availability: In Stock only (default on)
- Sort: Newest / Price: Low to High / Price: High to Low
Card states:
- Active + in stock: fully interactive
- Active + out of stock: visible but "Out of Stock" label, buy button disabled
- Inactive: hidden from browse view by default
Technical data per card:
listing.name(display title)listing.description(shown on hover / card subtitle)listing.price+listing.canonical_currency(formatted price)listing.quantity - listing.quantity_reserved(available count)listing.metadata_uri(fetch the JSON at this URL to get the product image)listing.seller(abbreviated wallet address)listing.is_active(show/hide logic)
Page 2: Listing Detail / Product Page
URL: /listing/[address]
Purpose: The product detail page. Like eBay's item page. Where the buyer decides to purchase.
UX Goals:
- The buyer should feel informed and confident
- Price and "Buy Now" should be obvious within 2 seconds of loading
- Trust signals should be visible (on-chain verification, resolver info)
- Blockchain complexity should be completely hidden — it just feels like a trustworthy product page
Layout concept (desktop: 2-column):
Left column (~60%):
- Large product image (from metadata JSON, or placeholder)
- Image gallery thumbnails if multiple images exist in metadata
- Product name (primary heading)
- Description (full text, with "show more" if long)
- Seller info row: abbreviated address + copy button + "Verified on Solana" label
- Technical details expandable section (for advanced users): listing ID, on-chain address
Right column (~40%, sticky while scrolling):
- Price (large, prominent) — show canonical price + note if other currencies accepted
- Availability: "X in stock" with a visual indicator when low
- Currency selector: if the listing accepts multiple currencies, let the buyer pick which to pay with
- Resolver selector: shows accepted resolvers with their fee %. Pre-select a recommended one. Fee is labeled as "only charged if dispute is resolved."
- "Buy Now" button — the primary CTA, most prominent element on the page
- Below CTA: 3 trust signals:
- "Final Payment" — payment cannot be reversed
- "Dispute Protection" — a resolver mediates if something goes wrong
- "On-chain Verified" — all terms are in open smart contracts
- Note: "Funds held in escrow until you confirm receipt"
Seller section (below the grid):
- Abbreviated seller address + copy
- Number of active listings by this seller (optional, if easily fetchable)
Page 3: Checkout / Place Order
Design as a modal or side panel — keep the user on the product page, don't navigate away.
Trigger: Clicking "Buy Now" on the listing detail page.
Pre-condition — wallet not connected:
- "Buy Now" opens a wallet connect modal first
- After connecting, resume the checkout flow automatically
Step 1: Order Review
The user sees a summary before committing:
Buying: [Product Name]
Seller: [abbreviated address]
Payment
Currency: [SOL ▾] ← dropdown if multiple currencies accepted
Amount: 1.5 SOL ≈ $180 USD ← show USD estimate alongside
[ℹ] This amount may vary slightly due to real-time price conversion.
Slippage tolerance: 0.5% ← shown, but pre-set to sensible default
Dispute Protection
[Resolver Name — 0.5% fee if dispute resolved] [▾ Change]
← First/recommended resolver pre-selected
"Resolver fee is only charged if a dispute is actually adjudicated."
[Cancel] [Confirm & Place Order →]
Step 2: Transaction pending
- The wallet extension popup appears (handled by browser)
- The modal shows a loading/pending state: "Confirming on Solana…"
Step 3: Confirmation (after transaction confirmed)
✓ Order placed successfully!
Your payment of 1.5 SOL is now held in secure escrow.
The seller has been notified and will confirm your order.
What happens next:
1. Seller confirms → your order becomes active
2. You receive the goods
3. You confirm receipt → seller gets paid
4. If something goes wrong, [Resolver Name] will mediate
[View My Orders] [Continue Shopping]
Error states:
- Wallet rejected: "Purchase cancelled."
- Out of stock (race condition): "Sorry, this item just sold out."
- Slippage exceeded: "The price changed too much before your transaction went through. Please try again."
- Network error: "Connection issue. Please try again."
What happens under the hood (invisible to the user):
- Frontend calls
solisting::create_orderon-chain - This atomically: validates the listing, computes the oracle-adjusted price if paying in an alt currency, increments
quantity_reserved, and creates adescroescrow (moves funds from buyer's wallet into the escrow vault) - After the transaction confirms, an
OrderAccountexists on-chain linking the listing to the escrow
Page 4: Wallet Connect (in Nav)
Disconnected state:
- Prominent "Connect Wallet" button on the right of the nav
On click: Opens wallet selection modal listing installed wallets (Phantom, Solflare, Backpack, etc.) via @solana/connector.
Connected state:
- Shows an abbreviated wallet address (first 4 + last 4 chars) with a connected indicator dot and a dropdown arrow
On click — dropdown:
- Wallet name + icon
- Full address (copyable)
- [Copy Address] button
- [Disconnect] button
Page 5: My Orders (Order Status)
URL: /orders — visible in nav only when wallet is connected
Content: A list of the connected wallet's OrderAccounts:
- Product name (linked to listing detail)
- Amount paid
- Current status (Awaiting Confirm / Active / Complete / Cancelled / Disputed)
- Date placed
- Link to full order detail
Order Detail page (/order/[address]):
- Order ID and date
- Linked listing (clickable)
- Amount in escrow
- Current escrow state visualized as a linear progress:
Current step highlighted; terminal outcome (Complete / Cancelled) shown separately
[1. Awaiting Confirm] → [2. Active] → [3. Done] - Status-appropriate actions:
AwaitingSellerConfirmstate → [Cancel Order] (full refund)Activestate → [Confirm Receipt] (releases payment to seller)- Terminal states → informational only, no actions
6. Navigation Structure
[Volana Logo] [Search bar] [Browse] [My Orders] [Network ▾] [Connect Wallet]
- Logo → homepage/browse
- Browse →
/browse - My Orders →
/orders(only shown when wallet connected) - Network picker → dropdown to switch between Mainnet-beta, Devnet, Localnet (indicated by a colored dot per network)
- Wallet button → connect/disconnect
Mobile nav: collapsed behind a hamburger; wallet connect accessible from the top of the menu.
7. UI Component Inventory
These are the components that need to exist. Visual design is up to the designer.
Product Card (Browse Grid)
Required information hierarchy:
- Product image (top, full width of card)
- Product name (bold, prominent)
- Seller abbreviation (small, secondary)
- Price (prominent, clear)
- Availability label (In Stock / Low Stock / Out of Stock)
- Buy button (at bottom or on hover)
Status Labels
The following statuses need distinct visual treatment (not just color — also shape/icon/text so they're accessible):
- In Stock — positive/active
- Low Stock — urgency/warning (≤ 3 available)
- Out of Stock — disabled/unavailable
- Awaiting Confirm — pending/waiting
- Active (order) — in progress
- Complete — success/terminal
- Cancelled — neutral/terminal
- Disputed — alert/problem
Trust Badge Strip
Three small badges used on the listing detail page and in the checkout flow:
- "Final Payment"
- "Dispute Protection"
- "On-chain Verified"
Checkout Modal / Sheet
- Overlay/modal on desktop
- Full-screen bottom sheet on mobile
- Contains: order summary, currency picker, resolver picker, CTA button, pending/success states
Toast / Notification
- Transient notification for feedback: "Address copied", "Order placed!", errors
- Should appear without interrupting the user flow
Loading / Skeleton States
- Product grid: skeleton cards while listings load from the blockchain (can take 1–3 seconds)
- Listing detail: skeleton for image and fields
- Button: loading spinner while transaction is pending on-chain
8. Key UX Principles
8a. Hide the Blockchain
- Never show raw 44-character public keys as primary information — abbreviate (first 4 + "…" + last 4 chars), and offer a copy button or "view on explorer" link
- Price is shown in human-readable format: "1.5 SOL", not "1500000000 lamports"
- Escrow states should be explained in plain English (see copy guidance), not contract terminology
- The transaction flow should feel like clicking a "Confirm" button — the wallet popup is the only visible blockchain interaction
8b. Trust Through Transparency (for those who want it)
- Provide optional "see on-chain" links for technically-minded users — don't hide it, just don't foreground it
- The "How it works" section (in footer or dedicated page) explains the escrow flow in plain language with a simple step diagram
- Resolver selection should feel like choosing a "dispute protection plan" — not a cryptographic concept
8c. Conversion Optimization
- The primary "Buy Now" CTA must be above the fold on the listing detail page (sticky in the right column as user scrolls)
- Urgency messaging: "Only 2 left!" when available ≤ 3
- No account creation — connecting a wallet is the account
- Checkout is 1 step (review + confirm) — not a multi-page funnel
- Post-purchase: immediately show order status with clear "what happens next" steps — reduce post-purchase anxiety
8d. Responsive / Mobile
- Browse grid: 1 column on small mobile, 2 on large mobile/tablet, 3–4 on desktop
- Listing detail: single column on mobile (image → price/buy panel → description)
- Checkout: full-screen bottom sheet on mobile (not a floating modal)
8e. Performance Perception
- Product images load lazily with a placeholder shown immediately (blur-up or skeleton)
- Show previously cached listing data while re-fetching — never show a blank screen if stale data exists
- The page should feel fast even when waiting on blockchain RPC responses
9. Content & Copy Guidance
Terminology to Use vs. Avoid
| ❌ Avoid (crypto jargon) | ✅ Use instead |
|---|---|
| "Sign a transaction" | "Confirm your purchase" |
| "Escrow account" | "Secure payment hold" |
| "PDA / program derived address" | (hide entirely from user) |
| "Lamports" | "SOL" (always convert and display) |
| "CPI" / "on-chain instruction" | (hide entirely from user) |
| "Resolver" (without context) | "Dispute mediator" or "Protection" |
| "Canonical currency" | "Primary currency" |
| "Pubkey" | "Wallet address" |
| "Quantity reserved" | "Pending orders" |
| "is_active: false" | "Listing closed" / "Not available" |
Error Messages (User-Facing)
- Wallet declined: "Purchase cancelled."
- Network error: "Connection issue. Please try again."
- Out of stock (race): "Someone else just bought the last one. Sorry!"
- Slippage exceeded: "The price changed too much before your transaction went through. Please try again."
- Wallet not connected: "Connect your wallet to buy."
How It Works (for footer / explainer page)
Plain-language 4-step flow for curious users:
- Browse & pick — find something you want to buy
- Place order — connect your wallet and confirm. Your payment is locked in a secure escrow (a smart contract nobody can tamper with).
- Receive & confirm — when you receive your goods, confirm receipt. The payment is released to the seller automatically.
- Protected — if something goes wrong, your chosen dispute mediator steps in. Their ruling is final and enforced on-chain.
10. Technical Stack Reference
For context on what data is available and how the frontend fetches it:
- Frontend: Next.js 16, React 19, App Router
- Wallet:
@solana/connector— standard Solana wallet adapter; providesuseWallet(),useCluster(), transaction signing - Data fetching: React Query — polls Solana RPC for on-chain account data
- SDK:
@solisting/sdk— typed fetchers forListingAccount,OrderAccount, etc. - Networks: Mainnet-beta, Devnet, Localnet (switchable in the nav)
- Payments currently supported: SOL (native). SPL tokens (USDC etc.) are planned — the contract infrastructure supports them but the frontend doesn't wire them up yet.
- Product images: stored off-chain. The seller provides a
metadata_uri(URL to a JSON file) which contains the image URL. The JSON format follows the standard Solana NFT metadata schema:{ name, description, image, ... }.
11. Flows to Design (Priority Order)
- Browse → Product Detail → Buy Now (connected wallet) — the primary happy path
- Browse → Product Detail → Buy Now (wallet not connected) → connect wallet → complete checkout
- Post-purchase confirmation — order summary + "what happens next"
- My Orders list — status overview of buyer's orders
- Order Detail — current state + available actions (confirm receipt / cancel)
12. What Makes Volana Different from Traditional Marketplaces
Use in hero copy, onboarding tooltips, and "How it works":
| Feature | eBay / Amazon / PayPal | Volana |
|---|---|---|
| Censorship resistance | Any listing can be removed | No one can remove a listing |
| Payment reversal | Chargebacks possible for months | Payments are final once the buyer confirms |
| Fees | 10–13% platform + 3–4% payment processor | < $0.001 network fee only |
| Dispute resolution | Black-box, provider-controlled | On-chain, auditable, mediator of your choice |
| Account required | Email + card + KYC | Solana wallet only |
| Transparency | Terms can change at any time | Rules are open-source smart contracts |
13. Accessibility Requirements
- All interactive elements must have visible focus states
- Status labels must never rely on color alone — pair color with a text label or icon
- Product cards must be fully keyboard-navigable
- Wallet connection modal must be screenreader-compatible (ARIA roles, focus trap)
- Minimum contrast ratio for body text: 4.5:1 (WCAG AA)
14. Screen States to Cover
Browse Page
- Loading: placeholder/skeleton cards while blockchain data is fetched
- Loaded: product grid with filters active
- Empty: no listings on the selected network — suggest switching to Mainnet
- No results: search/filter combination returns nothing
Listing Detail
- Loading: skeleton for image, title, price panel
- Loaded: full detail with all fields
- Out of Stock: detail still visible, "Buy Now" replaced with "Out of Stock" (disabled)
- Wallet not connected: "Buy Now" says "Connect Wallet to Buy" — click opens wallet modal
Checkout Modal
- Review state: order summary, currency/resolver selectors, confirm button
- Pending state: wallet popup has appeared, modal shows loading state
- Success state: confirmation with "what happens next"
- Error state: failed transaction with clear message and retry option
My Orders
- Empty: no orders yet — prompt to browse
- List with orders: orders grouped by status or sorted by date
- Order detail — awaiting confirm: Cancel button available
- Order detail — active: Confirm Receipt button available
- Order detail — terminal: read-only, shows outcome