Create engaging loyalty programs with point systems and leaderboard analytics
query GetQuestPoints($questId: ID!) { quest(id: $questId) { id name loyaltyPoints status space { id name } } }
{ "data": { "quest": { "id": "GChdWUjXX3", "name": "Introduction to Web3!", "loyaltyPoints": 100, "status": "Active", "space": { "id": "40", "name": "BNB Chain" } } } }
query GetLeaderboard($spaceId: Int!, $cursorAfter: String) { space(id: $spaceId) { id name loyaltyPointsRanks(cursorAfter: $cursorAfter) { totalCount pageInfo { hasNextPage endCursor } list { rank points address { username avatar address } } } } }
async function findUserPoints(spaceId, userAddress, accessToken) { let cursorAfter = null; let pageCount = 0; const maxPages = 20; // Reasonable search limit while (pageCount < maxPages) { const response = await fetch('https://graphigo-business.prd.galaxy.eco/query', { method: 'POST', headers: { 'Content-Type': 'application/json', 'access-token': accessToken }, body: JSON.stringify({ query: `query GetLeaderboard($spaceId: Int!, $cursorAfter: String) { space(id: $spaceId) { loyaltyPointsRanks(cursorAfter: $cursorAfter) { totalCount pageInfo { hasNextPage endCursor } list { rank points address { address username avatar } } } } }`, variables: { spaceId, cursorAfter } }) }); const data = await response.json(); const ranks = data.data.space.loyaltyPointsRanks; // Search current page const userRank = ranks.list.find(item => item.address.address.toLowerCase() === userAddress.toLowerCase() ); if (userRank) { return { found: true, points: userRank.points, rank: userRank.rank, username: userRank.address.username, totalParticipants: ranks.totalCount, searchPages: pageCount + 1 }; } if (!ranks.pageInfo.hasNextPage) break; cursorAfter = ranks.pageInfo.endCursor; pageCount++; // Rate limiting await new Promise(resolve => setTimeout(resolve, 100)); } return { found: false, points: 0, rank: null, totalParticipants: pageCount > 0 ? ranks.totalCount : 0, searchPages: pageCount }; }
async function getQuestPointValue(questId, accessToken) { const response = await fetch('https://graphigo-business.prd.galaxy.eco/query', { method: 'POST', headers: { 'Content-Type': 'application/json', 'access-token': accessToken }, body: JSON.stringify({ query: `query GetQuestPoints($questId: ID!) { quest(id: $questId) { id name loyaltyPoints status space { id name } } }`, variables: { questId } }) }); const data = await response.json(); return data.data.quest; }
query GetSprintLeaderboard($spaceId: Int!, $sprintId: Int!, $cursorAfter: String) { space(id: $spaceId) { loyaltyPointsRanks( sprintId: $sprintId cursorAfter: $cursorAfter ) { totalCount list { rank points address { username address } } } } }
async function compareUserProgress(spaceId, userAddress, sprintId, accessToken) { const [overall, sprint] = await Promise.all([ findUserPoints(spaceId, userAddress, accessToken), findUserPointsInSprint(spaceId, userAddress, sprintId, accessToken) ]); return { overall: { points: overall.points, rank: overall.rank, found: overall.found }, sprint: { points: sprint.points, rank: sprint.rank, found: sprint.found, sprintId }, comparison: { pointsDifference: sprint.points - overall.points, rankImprovement: overall.rank && sprint.rank ? overall.rank - sprint.rank : null, sprintPerformance: sprint.rank && overall.rank ? sprint.rank < overall.rank ? 'better' : 'worse' : 'unknown' } }; } // Similar to findUserPoints but with sprintId parameter async function findUserPointsInSprint(spaceId, userAddress, sprintId, accessToken) { // Implementation follows same pattern as findUserPoints // but includes sprintId in the loyaltyPointsRanks query }
async function createUserDashboard(spaceId, userAddress, accessToken) { const userData = await findUserPoints(spaceId, userAddress, accessToken); if (!userData.found) { return { user: { address: userAddress, points: 0, rank: null, isRanked: false, message: 'User not found in top rankings' }, leaderboard: { totalParticipants: userData.totalParticipants, searchedPages: userData.searchPages } }; } // Calculate percentile const percentile = userData.totalParticipants ? ((userData.totalParticipants - userData.rank) / userData.totalParticipants) * 100 : 0; return { user: { address: userAddress, username: userData.username, points: userData.points, rank: userData.rank, isRanked: true, percentile: Math.round(percentile) }, leaderboard: { totalParticipants: userData.totalParticipants, searchedPages: userData.searchPages }, spaceInfo: { id: spaceId } }; }
async function trackQuestCompletion(questId, userAddress, accessToken) { const quest = await getQuestPointValue(questId, accessToken); if (!quest) { return { error: 'Quest not found' }; } if (quest.loyaltyPoints === 0) { return { message: 'Quest does not award loyalty points' }; } const userPoints = await findUserPoints( parseInt(quest.space.id), userAddress, accessToken ); return { quest: { id: quest.id, name: quest.name, points: quest.loyaltyPoints, status: quest.status, space: quest.space }, user: { currentPoints: userPoints.points, currentRank: userPoints.rank, projectedPoints: userPoints.points + quest.loyaltyPoints, isCurrentlyRanked: userPoints.found }, impact: { pointsGain: quest.loyaltyPoints } }; }
async function checkPointsRequirement(spaceId, userAddress, requiredPoints, accessToken) { const userPoints = await findUserPoints(spaceId, userAddress, accessToken); return { hasAccess: userPoints.points >= requiredPoints, userPoints: userPoints.points, requiredPoints, deficit: Math.max(0, requiredPoints - userPoints.points), rank: userPoints.rank, isRanked: userPoints.found }; }
function calculateAchievements(userPoints) { const thresholds = [ { name: 'Newcomer', points: 10 }, { name: 'Explorer', points: 100 }, { name: 'Adventurer', points: 500 }, { name: 'Champion', points: 1000 }, { name: 'Legend', points: 5000 } ]; const achieved = thresholds.filter(t => userPoints >= t.points); const nextThreshold = thresholds.find(t => userPoints < t.points); return { current: achieved[achieved.length - 1] || { name: 'Beginner', points: 0 }, next: nextThreshold, progress: nextThreshold ? (userPoints - achieved[achieved.length - 1]?.points || 0) / (nextThreshold.points - (achieved[achieved.length - 1]?.points || 0)) : 1, totalAchieved: achieved.length }; }
// Get user loyalty program status const accessToken = process.env.GALXE_ACCESS_TOKEN; const spaceId = 40; // BNB Chain space const userAddress = '0x1234567890123456789012345678901234567890'; const dashboard = await createUserDashboard(spaceId, userAddress, accessToken); console.log('User Points:', dashboard.user.points); console.log('User Rank:', dashboard.user.rank); console.log('Percentile:', dashboard.user.percentile + '%'); console.log('Total Participants:', dashboard.leaderboard.totalParticipants);
// Show potential rewards before quest participation async function showQuestRewards(questId, userAddress, accessToken) { const tracking = await trackQuestCompletion(questId, userAddress, accessToken); if (tracking.error || tracking.message) { console.log(tracking.error || tracking.message); return; } console.log(`Quest: ${tracking.quest.name}`); console.log(`Potential Points: +${tracking.quest.points}`); console.log(`Current Points: ${tracking.user.currentPoints}`); console.log(`After Completion: ${tracking.user.projectedPoints}`); console.log(`Current Rank: ${tracking.user.currentRank || 'Unranked'}`); }
// Check user achievements const userPoints = await findUserPoints(spaceId, userAddress, accessToken); const achievements = calculateAchievements(userPoints.points); console.log(`Current Level: ${achievements.current.name}`); if (achievements.next) { console.log(`Next Level: ${achievements.next.name} (${achievements.next.points} points)`); console.log(`Progress: ${Math.round(achievements.progress * 100)}%`); } console.log(`Total Achievements: ${achievements.totalAchieved}/5`);
Was this page helpful?