Building an NFT Community Ecosystem
Red Ape Family needed a comprehensive digital ecosystem to support their NFT community beyond just trading. The challenge was creating multiple interconnected applications that would provide utility, engagement, and value to NFT holders while maintaining seamless Web3 integration.
Project Overview
I developed three core applications for the Red Ape Family ecosystem:
- TRAF Page: Community hub and NFT showcase platform
- Raffle System: Fair distribution mechanism for exclusive NFTs
- Staking Platform: Utility platform for NFT holders to earn rewards
All applications were built using our Celeste-JS SDK to ensure consistent Web3 integration and user experience.
TRAF Page - Community Hub
Project Architecture
Technology Stack:
- Framework: React with functional components
- Web3 Integration: Celeste-JS SDK v1.3.0
- Styling: Custom SCSS with responsive design
- State Management: React hooks and context
Core Features Implementation
NFT Collection Display
import { useCeleste } from "@celeste-js/react";
const NFTShowcase = () => {
const { address, isConnected } = useCeleste();
const [userNFTs, setUserNFTs] = useState([]);
const [loading, setLoading] = useState(false);
const fetchUserNFTs = async () => {
if (!isConnected || !address) return;
setLoading(true);
try {
const nftContract = new web3.eth.Contract(
RED_APE_FAMILY_ABI,
RED_APE_FAMILY_CONTRACT
);
const balance = await nftContract.methods.balanceOf(address).call();
const nfts = [];
for (let i = 0; i < balance; i++) {
const tokenId = await nftContract.methods
.tokenOfOwnerByIndex(address, i)
.call();
const tokenURI = await nftContract.methods
.tokenURI(tokenId)
.call();
const metadata = await fetch(tokenURI).then((res) =>
res.json()
);
nfts.push({ tokenId, metadata });
}
setUserNFTs(nfts);
} catch (error) {
console.error("Failed to fetch NFTs:", error);
} finally {
setLoading(false);
}
};
useEffect(() => {
fetchUserNFTs();
}, [address, isConnected]);
return (
<div className="nft-showcase">
<h2>Your Red Ape Family Collection</h2>
{loading ? (
<LoadingSpinner />
) : (
<div className="nft-grid">
{userNFTs.map(({ tokenId, metadata }) => (
<NFTCard
key={tokenId}
tokenId={tokenId}
name={metadata.name}
image={metadata.image}
attributes={metadata.attributes}
/>
))}
</div>
)}
</div>
);
};
Community Features
const CommunityHub = () => {
const [communityStats, setCommunityStats] = useState({
totalHolders: 0,
totalNFTs: 0,
floorPrice: 0,
volume24h: 0,
});
const fetchCommunityStats = async () => {
try {
const contract = new web3.eth.Contract(
RED_APE_FAMILY_ABI,
RED_APE_FAMILY_CONTRACT
);
const totalSupply = await contract.methods.totalSupply().call();
const holderCount = await getUniqueHoldersCount(contract);
const marketData = await fetchMarketplaceData();
setCommunityStats({
totalHolders: holderCount,
totalNFTs: totalSupply,
floorPrice: marketData.floorPrice,
volume24h: marketData.volume24h,
});
} catch (error) {
console.error("Failed to fetch community stats:", error);
}
};
return (
<div className="community-hub">
<div className="stats-grid">
<StatCard
title="Total Holders"
value={communityStats.totalHolders}
/>
<StatCard title="Total NFTs" value={communityStats.totalNFTs} />
<StatCard
title="Floor Price"
value={`${communityStats.floorPrice} ETH`}
/>
<StatCard
title="Daily Volume"
value={`${communityStats.volume24h} ETH`}
/>
</div>
</div>
);
};
Raffle System - Fair Distribution
Smart Contract Integration
Technology Stack:
- Framework: React with Next.js
- Web3 Integration: Celeste-JS SDK v1.1.1
- Backend: Node.js API routes
- Database: Local state management
Raffle Mechanics Implementation
Entry System
const RaffleEntry = ({ raffleId, entryPrice, maxEntries }) => {
const { address, isConnected, smartContracts } = useCeleste();
const [entryCount, setEntryCount] = useState(1);
const [userEntries, setUserEntries] = useState(0);
const handleEnterRaffle = async () => {
if (!isConnected) {
showConnectWalletModal();
return;
}
try {
const raffleContract = smartContracts.RAFFLE_CONTRACT;
const totalCost = web3.utils.toWei(
(entryPrice * entryCount).toString(),
"ether"
);
const tx = await raffleContract.methods
.enterRaffle(raffleId, entryCount)
.send({
from: address,
value: totalCost,
});
showNotification("Successfully entered raffle!", "success");
updateUserEntries();
} catch (error) {
if (error.code === "INSUFFICIENT_FUNDS") {
showNotification("Insufficient funds for entry", "error");
} else if (error.message.includes("Max entries exceeded")) {
showNotification("Maximum entries reached", "error");
} else {
showNotification("Failed to enter raffle", "error");
}
}
};
const updateUserEntries = async () => {
try {
const entries = await smartContracts.RAFFLE_CONTRACT.methods
.getUserEntries(raffleId, address)
.call();
setUserEntries(parseInt(entries));
} catch (error) {
console.error("Failed to fetch user entries:", error);
}
};
return (
<div className="raffle-entry">
<div className="entry-controls">
<label>Number of Entries</label>
<input
type="number"
min="1"
max={maxEntries - userEntries}
value={entryCount}
onChange={(e) => setEntryCount(parseInt(e.target.value))}
/>
<div className="cost-display">
Total Cost: {entryPrice * entryCount} ETH
</div>
</div>
<div className="user-stats">
<p>Your Entries: {userEntries}</p>
<p>Remaining: {maxEntries - userEntries}</p>
</div>
<button
className="enter-button"
onClick={handleEnterRaffle}
disabled={!isConnected || userEntries >= maxEntries}
>
{isConnected ? "Enter Raffle" : "Connect Wallet"}
</button>
</div>
);
};
Winner Selection & Verification
const RaffleManagement = () => {
const { smartContracts, address } = useCeleste();
const [raffles, setRaffles] = useState([]);
const drawWinner = async (raffleId) => {
try {
// Only raffle admin can draw winners
const isAdmin = await smartContracts.RAFFLE_CONTRACT.methods
.isAdmin(address)
.call();
if (!isAdmin) {
throw new Error("Unauthorized: Admin access required");
}
const tx = await smartContracts.RAFFLE_CONTRACT.methods
.drawWinner(raffleId)
.send({ from: address });
// Get winner from transaction events
const winner = await getWinnerFromTransaction(tx);
showNotification(
`Winner selected: ${winner.substring(0, 6)}...${winner.substring(38)}`,
"success"
);
updateRaffleList();
} catch (error) {
showNotification("Failed to draw winner", "error");
}
};
const getWinnerFromTransaction = async (tx) => {
const receipt = await web3.eth.getTransactionReceipt(
tx.transactionHash
);
const winnerEvent = receipt.logs.find(
(log) =>
log.topics[0] ===
web3.utils.keccak256("WinnerDrawn(uint256,address)")
);
return web3.eth.abi.decodeParameters(
["uint256", "address"],
winnerEvent.data
)[1];
};
return (
<div className="raffle-management">
{raffles.map((raffle) => (
<div key={raffle.id} className="raffle-card">
<h3>{raffle.title}</h3>
<p>Entries: {raffle.entryCount}</p>
<p>Prize: {raffle.prizeDescription}</p>
{raffle.status === "active" && (
<button onClick={() => drawWinner(raffle.id)}>
Draw Winner
</button>
)}
{raffle.winner && (
<div className="winner-display">
Winner: {raffle.winner}
</div>
)}
</div>
))}
</div>
);
};
Staking Platform - NFT Utility
Advanced Staking Mechanics
Technology Stack:
- Framework: React with advanced hooks
- Web3 Integration: Celeste-Framework v1.3.7
- Staking Logic: Custom smart contract integration
- Rewards: Token-based reward system
Staking Implementation
NFT Staking Interface
const NFTStaking = () => {
const { address, isConnected } = useCeleste();
const [stakedNFTs, setStakedNFTs] = useState([]);
const [availableNFTs, setAvailableNFTs] = useState([]);
const [rewards, setRewards] = useState("0");
const stakeNFT = async (tokenId) => {
try {
// First approve the staking contract
const nftContract = new web3.eth.Contract(
RED_APE_FAMILY_ABI,
RED_APE_FAMILY_CONTRACT
);
const isApproved = await nftContract.methods
.isApprovedForAll(address, STAKING_CONTRACT_ADDRESS)
.call();
if (!isApproved) {
await nftContract.methods
.setApprovalForAll(STAKING_CONTRACT_ADDRESS, true)
.send({ from: address });
}
// Stake the NFT
const stakingContract = new web3.eth.Contract(
STAKING_ABI,
STAKING_CONTRACT_ADDRESS
);
const tx = await stakingContract.methods
.stakeNFT(tokenId)
.send({ from: address });
showNotification("NFT staked successfully!", "success");
updateStakingData();
} catch (error) {
showNotification("Failed to stake NFT", "error");
}
};
const unstakeNFT = async (tokenId) => {
try {
const stakingContract = new web3.eth.Contract(
STAKING_ABI,
STAKING_CONTRACT_ADDRESS
);
const tx = await stakingContract.methods
.unstakeNFT(tokenId)
.send({ from: address });
showNotification("NFT unstaked successfully!", "success");
updateStakingData();
} catch (error) {
showNotification("Failed to unstake NFT", "error");
}
};
const claimRewards = async () => {
try {
const stakingContract = new web3.eth.Contract(
STAKING_ABI,
STAKING_CONTRACT_ADDRESS
);
const tx = await stakingContract.methods
.claimRewards()
.send({ from: address });
showNotification("Rewards claimed successfully!", "success");
updateRewards();
} catch (error) {
showNotification("Failed to claim rewards", "error");
}
};
return (
<div className="nft-staking">
<div className="rewards-section">
<h2>Pending Rewards</h2>
<div className="rewards-display">
{web3.utils.fromWei(rewards, "ether")} REWARD
</div>
<button
onClick={claimRewards}
disabled={rewards === "0"}
className="claim-button"
>
Claim Rewards
</button>
</div>
<div className="staking-sections">
<div className="available-nfts">
<h3>Available to Stake</h3>
<div className="nft-grid">
{availableNFTs.map((nft) => (
<NFTCard
key={nft.tokenId}
{...nft}
action={
<button
onClick={() => stakeNFT(nft.tokenId)}
>
Stake
</button>
}
/>
))}
</div>
</div>
<div className="staked-nfts">
<h3>Currently Staked</h3>
<div className="nft-grid">
{stakedNFTs.map((nft) => (
<NFTCard
key={nft.tokenId}
{...nft}
stakingInfo={nft.stakingData}
action={
<button
onClick={() => unstakeNFT(nft.tokenId)}
>
Unstake
</button>
}
/>
))}
</div>
</div>
</div>
</div>
);
};
Rewards Calculation
const RewardsCalculator = () => {
const calculateRewards = (stakingData) => {
const stakingDuration = Date.now() - stakingData.startTime;
const daysStaked = stakingDuration / (1000 * 60 * 60 * 24);
// Base rate: 1 token per day per NFT
const baseRate = 1;
// Bonus multipliers based on rarity
const rarityMultiplier = getRarityMultiplier(stakingData.nftRarity);
// Loyalty bonus for long-term staking
const loyaltyBonus = daysStaked > 30 ? 1.2 : 1;
return daysStaked * baseRate * rarityMultiplier * loyaltyBonus;
};
const getRarityMultiplier = (rarity) => {
const multipliers = {
common: 1,
uncommon: 1.2,
rare: 1.5,
epic: 2,
legendary: 3,
};
return multipliers[rarity] || 1;
};
return {
calculateRewards,
getRarityMultiplier,
};
};
Technical Integration & Architecture
Celeste-JS SDK Evolution
The Red Ape Family projects showcased the evolution of our Celeste-JS SDK:
Version Progression:
- TRAF Page: v1.3.0 - Latest features and optimizations
- Initial Raffle: v1.1.1 - Core functionality
- Staking Platform: v1.3.7 - Advanced framework features
Cross-Application State Management
// Shared context for Red Ape Family ecosystem
const RedApeFamilyContext = createContext();
export const RedApeFamilyProvider = ({ children }) => {
const [userProfile, setUserProfile] = useState({
nftBalance: 0,
stakedNFTs: [],
raffleEntries: [],
totalRewards: "0",
});
const updateUserProfile = async (address) => {
const nftBalance = await getNFTBalance(address);
const stakedNFTs = await getStakedNFTs(address);
const raffleEntries = await getRaffleEntries(address);
const totalRewards = await getTotalRewards(address);
setUserProfile({
nftBalance,
stakedNFTs,
raffleEntries,
totalRewards,
});
};
return (
<RedApeFamilyContext.Provider
value={{
userProfile,
updateUserProfile,
}}
>
{children}
</RedApeFamilyContext.Provider>
);
};
Smart Contract Architecture
The ecosystem used modular smart contracts:
- NFT Contract: ERC-721 with enumerable extension
- Raffle Contract: Fair randomness with Chainlink VRF
- Staking Contract: Time-locked staking with rewards
- Rewards Token: ERC-20 token for staking rewards
Security & Best Practices
Smart Contract Security
// Staking contract security measures
const SecurityChecks = {
// Reentrancy protection
nonReentrant: true,
// Ownership verification
verifyOwnership: async (tokenId, address) => {
const owner = await nftContract.methods.ownerOf(tokenId).call();
return owner.toLowerCase() === address.toLowerCase();
},
// Time-lock validation
validateUnstaking: (stakingData) => {
const minStakingPeriod = 24 * 60 * 60 * 1000; // 24 hours
const stakingDuration = Date.now() - stakingData.startTime;
return stakingDuration >= minStakingPeriod;
},
};
Frontend Security
// Input validation and sanitization
const ValidationUtils = {
validateTokenId: (tokenId) => {
if (!tokenId || isNaN(tokenId) || tokenId < 1) {
throw new Error("Invalid token ID");
}
return parseInt(tokenId);
},
validateAmount: (amount, maxAmount) => {
if (!amount || isNaN(amount) || amount <= 0) {
throw new Error("Invalid amount");
}
if (amount > maxAmount) {
throw new Error("Amount exceeds maximum");
}
return parseFloat(amount);
},
};
Performance Metrics & Results
Technical Performance
- Load Times: Under 2 seconds for NFT data fetching
- Transaction Success: 98.5% success rate
- User Experience: Seamless wallet integration
- Scalability: Supports 10,000+ NFT collection
Community Engagement
- Active Users: Consistent daily engagement
- Staking Participation: High adoption rate
- Raffle Entries: Fair distribution achieved
- Platform Utility: Multiple use cases for NFT holders
Project Impact & Learning
Technical Innovation
- Multi-Application Ecosystem: Created interconnected dApps
- Advanced Web3 Integration: Leveraged custom SDK capabilities
- NFT Utility Development: Built beyond simple trading
- Community Platform Architecture: Scalable, modular design
Blockchain Development Skills
- NFT Standards: Deep understanding of ERC-721
- Smart Contract Integration: Complex multi-contract systems
- Web3 User Experience: Seamless blockchain interaction
- DeFi Mechanics: Staking and rewards systems
SDK Evolution Contribution
The Red Ape Family projects directly contributed to Celeste-JS SDK improvements:
- Performance Optimizations: Based on real-world usage
- Feature Enhancements: Community-driven requirements
- Bug Fixes: Production environment testing
- Documentation: Real implementation examples
Technical Stack Summary
Frontend Technologies
- React: Modern hooks-based architecture
- Next.js: Server-side rendering and routing
- SCSS: Custom styling with responsive design
- Redux: State management for complex applications
Blockchain Integration
- Celeste-JS SDK: Custom Web3 abstraction layer
- Web3.js: Direct blockchain interaction
- Smart Contracts: Solidity-based contract integration
- NFT Standards: ERC-721 implementation
Development Tools
- ESLint: Code quality and consistency
- Prettier: Code formatting standards
- Git: Version control and collaboration
- npm: Package management and dependencies
The Red Ape Family ecosystem demonstrated comprehensive NFT platform development, showcasing advanced Web3 integration, community engagement features, and sophisticated blockchain mechanics. This project established expertise in NFT ecosystem development, multi-application architecture, and community-driven blockchain platforms.
This case study highlights advanced NFT development skills, community platform architecture, and comprehensive Web3 ecosystem design.