Staking Rewards Card — Free Live-Accruing Crypto Rewards UI

Staking Rewards Card · Cards · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

APY-derived accrual
The ticking rate is computed from real staked amount and APY, not an arbitrary animation.
Six-decimal precision
Small per-second increments stay visible instead of rounding to zero.
Synced progress + countdown
One counter drives both the payout bar and the mm:ss countdown text.
Guarded claim flow
The button disables on click so a double-click cannot double-claim.
Success confirmation
Shows the exact claimed amount before resetting for the next cycle.
Gradient validator branding
An icon and accent gradient suggest a specific staking pool or validator.
Tabular numerals throughout
Staked amount, rewards, and countdown all use monospaced digit widths.
Framework-portable state
All logic runs off plain counters — trivial to move into React/Vue state.

About this UI Snippet

Staking Rewards Card — Real-Time Accrual, Payout Countdown & Claim Flow

Screenshot of the Staking Rewards Card snippet rendered live

Staking interfaces live or die on one feeling: rewards should look alive, ticking upward in real time rather than sitting static until a page refresh. This snippet builds that staking rewards card — staked amount, APY, a rewards counter that increments every second, a payout-cycle progress bar, a countdown, and a claim button with a genuine success transition — using nothing but setInterval and careful number formatting.

Deriving a per-second rate from APY

Rather than animating an arbitrary number, the accrual is grounded in real inputs: perSecondRate = (stakedAmount * apy) / secondsPerYear. This is the actual per-second yield implied by the displayed APY, so the ticking number represents something real rather than a cosmetic animation — swap in your protocol's actual reward-rate calculation and the rest of the card keeps working unchanged.

Six decimal places, not two

Crypto reward amounts are tiny per second — a two-decimal display would show 0.00 forever. The rewards counter is formatted with toFixed(6), so the increments are visible tick to tick even though the underlying accrual is a fraction of a cent per second. This is the detail that makes the card feel "live" rather than frozen.

A payout cycle, visualized

A progress bar fills over a fixed PAYOUT_PERIOD_SEC window (5 minutes here, representing a compressed simulation of a real payout epoch), paired with a countdown formatted as mm:ss. Both derive from the same secondsIntoPeriod counter, so the bar and the countdown text can never drift out of sync with each other.

Claim: disable, confirm, then reset

Clicking "Claim rewards" freezes further accrual (claimed = true), disables the button so a double-click can't claim twice, and swaps the label to a checkmark confirmation showing the exact claimed amount. After a short delay it resets the counter to zero and re-enables claiming — modeling the real on-chain sequence of a claim transaction settling before the balance can accrue again.

Building a real integration

Replace the simulated accrual with a periodic read of your staking contract or API's actual accrued-rewards value, and wire the claim button to submit a real claim transaction — show the success state only after the transaction confirms, and surface a pending/error state for the in-between. Pair this card with a wallet card for balance context or a crypto price ticker card to convert rewards to a fiat value.

Build with AI

Build, Understand, Optimize, and Extend It With AI

You don't have to work out the accrual math or the claim-guard logic on your own. Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly how perSecondRate is derived from the staked amount and APY, and why six decimal places (rather than the usual two) are necessary for the reward counter to visibly tick rather than appear frozen at small per-second yields. The same assistant can help optimize it — asking whether disabling the claim button synchronously inside the click handler is sufficient protection against a double-claim race, or whether the payout-cycle countdown should instead be computed from a fixed epoch timestamp rather than a client-side counter that resets on refresh. It's also useful for extending the card: ask it to add a pending/error state for a real on-chain claim transaction, show a running fiat-value conversion of the accrued rewards, or add an auto-compound toggle. Treat the code less like a finished artifact and more like a starting point for a conversation.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a "staking rewards card" in plain HTML, CSS, and JavaScript with no library or CDN dependency.

Requirements:
- A card showing an asset/validator icon and name, a staked amount, an APY badge, and a live-accruing rewards counter formatted to six decimal places so tiny per-second increments remain visible instead of rounding to zero.
- Derive the reward accrual rate mathematically from the staked amount and the APY (rate per second = stakedAmount * apy / secondsPerYear), not an arbitrary hardcoded animation increment, and increment the displayed rewards by that rate once per second using setInterval.
- A progress bar and an mm:ss countdown that both represent the same fixed-length "payout cycle" period (e.g. simulate a 5-minute cycle), driven from one shared counter so the bar fill percentage and the countdown text can never drift out of sync with each other, resetting when the cycle completes.
- A "Claim rewards" button that, on click, immediately disables itself (so rapid double-clicks cannot double-claim), stops further accrual, and shows a success state displaying the exact claimed amount with a checkmark — then after a short delay resets the rewards counter to zero, re-enables the button, and resumes accrual.
- Use tabular/monospaced numeral styling on the staked amount, rewards counter, and countdown so digit changes do not cause horizontal layout shift.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSA staking card renders with a staked balance and 0.000000 accrued rewards.
  2. 2
    Watch rewards tick upEvery second, the rewards counter increments based on the derived per-second APY rate.
  3. 3
    Watch the payout cycleThe progress bar fills and the countdown ticks down over a 5-minute simulated payout period.
  4. 4
    Click "Claim rewards"The button disables, shows a checkmark success state with the claimed amount, then resets after a short delay.
  5. 5
    Adjust the inputsChange STAKED_AMOUNT and APY to reflect a real position.
  6. 6
    Wire a real claimReplace the setTimeout reset with an actual claim transaction call, showing pending/error states as needed.

Real-world uses

Common Use Cases

Staking dashboards
Show live rewards next to a wallet card and holdings breakdown.
DeFi yield products
Display accruing yield for a vault or liquidity position.
Validator/pool selection
Compare APY and accrual across pools alongside a pricing toggle-style comparison.
Portfolio overviews
Convert accrued rewards to fiat with a currency converter.
Wallet apps
Pair with a wallet connect button to gate the claim action.
Investor-facing reports
Summarize accrued and claimed rewards alongside an invoice preview-style statement.

Got questions?

Frequently Asked Questions

perSecondRate = (stakedAmount * apy) / secondsPerYear. This derives the actual per-second yield implied by the displayed APY from the staked amount, so the ticking counter represents a real number rather than an arbitrary animated increment. Replace stakedAmount and apy with real position data and the same formula produces a correct rate.

Per-second crypto accrual is extremely small — with typical APYs, two decimal places would show 0.00 indefinitely and the card would look frozen. Formatting with toFixed(6) keeps the increments visible tick to tick, which is what makes the card read as "live" rather than static.

The button is disabled immediately inside the click handler, before the success state or reset timeout runs, so a second click while the confirmation is showing has no effect. This models the real-world guard against double-submitting a claim transaction while the first one is still settling.

Replace the setInterval accrual with a periodic read of your contract's or API's actual accrued-rewards value (poll it, or subscribe to relevant events). In the claim handler, submit the real claim transaction and only show the success state once it confirms on-chain — add a pending spinner state for the interval in between, and an error state if the transaction fails or is rejected.

Hold accrued, secondsIntoPeriod, and claimed in component state, update accrued on a setInterval-equivalent effect using the same per-second rate formula, and derive the progress bar width and countdown text from secondsIntoPeriod in render. The claim handler becomes an async action that awaits your real claim call before setting claimed back to false.