Production-inspired NFT staking dApp built with React, TypeScript, Solidity, wagmi, viem, RainbowKit, TailwindCSS, and The Graph.
Live Demo: Tanaka Stake
Repository: NftCollection-UI
- Public mint
- Whitelist mint using Merkle proofs
- Dynamic mint mode selection
- Quantity-based total cost calculation
- Admin-controlled mint phases
- Stake owned TNFTs
- Unstake staked TNFTs
- Claim GOV rewards
- Total staked metric
- Reward-per-second accounting
- Toggle public mint
- Toggle whitelist mint
- Pause / unpause collection
- Set treasury recipient
- Generate Merkle root
- Export whitelist proofs JSON
- Update staking reward rate
- Grant / revoke
REWARD_MANAGER_ROLE
- Wallet connection with RainbowKit
- Sepolia network guard
- Toast-based transaction feedback
- Dark / light mode
- Responsive UI
- The Graph powered NFT ownership sync
- React
- TypeScript
- Vite
- TailwindCSS v4
- RainbowKit
- wagmi v2
- viem
- TanStack Query
- Solidity
- Foundry
- The Graph Studio
ERC721A NFT collection with:
- Public + whitelist minting
- ERC2981 royalties
- Pause functionality
- Merkle whitelist verification
NFT staking contract with:
- Reward-per-second accounting
- Accumulated reward-per-share model
- Multi-user staking support
- AccessControl roles
ERC20 reward token with minting permissions controlled via roles.
Rewards are distributed using an accumulated reward-per-share accounting model:
accRewardPerSharerewardDebtpendingRewards
This allows scalable reward distribution across multiple stakers without iterating over users.
NFTCollection: 0x6CA691947f144b33135889b7855e47D30a56c90F
GovernanceToken: 0x380E2C6613d99461f47e522f3DE17914d46e2546
NFTStaking: 0x8D2a23889f0A677Ee13C2E66f16aA931AeaE25A5
NFT ownership is indexed with The Graph using Transfer events.
Current subgraph:
type Account @entity {
id: Bytes!
tokens: [Token!]! @derivedFrom(field: "owner")
}
type Token @entity {
id: String!
tokenId: BigInt!
owner: Account!
}Frontend query:
tokens(where: { owner: $owner }) {
tokenId
}
}
VITE_SEPOLIA_RPC_URL=
VITE_SEPOLIA_WSS_URL=
VITE_SUBGRAPH_URL=
VITE_WALLETCONNECT_PROJECT_ID=npm install
npm run devnpm run build- Contracts are not upgradeable
- Ownership indexing depends on The Graph sync speed
- No backend caching layer
- Designed for Sepolia/demo usage
- Public mint toggle does not emit a dedicated event; frontend uses refetch/polling fallback.
- The app is deployed on Sepolia testnet.
- Users should not interact with unknown contracts using mainnet assets.
- Staking requires NFT approval for the staking contract.


