UNPKG

@b3dotfun/leaderboards

Version:

SDK to interact with leaderboards smart contract

495 lines 15.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Leaderboard = void 0; const viem_1 = require("viem"); const accounts_1 = require("viem/accounts"); const LeaderboardABI_1 = require("./abis/LeaderboardABI"); const config_1 = require("./config"); class Leaderboard { contract; contractAddress; chain; walletKey; constructor(chainId, walletKey, contractAddress) { if (walletKey && !walletKey.startsWith("0x")) { walletKey = `0x${walletKey}`; } if (contractAddress && !contractAddress.startsWith("0x")) { contractAddress = `0x${contractAddress}`; } const config = (0, config_1.getConfig)(chainId); this.chain = config.chain; this.walletKey = walletKey || ""; this.contractAddress = (contractAddress || "0x"); } connect(provider) { try { const client = (0, viem_1.createWalletClient)({ chain: this.chain, transport: provider ? (0, viem_1.custom)(provider) : (0, viem_1.http)(), }); this.contract = (0, viem_1.getContract)({ address: this.contractAddress, abi: LeaderboardABI_1.LeaderboardABI, client: client, }); return true; } catch (error) { console.error("Connection failed:", error); return false; } } async handleError(error) { if (error.data === "0xa741a045") { throw new Error("Score already set for this user"); } else if (error.data === "0x4456a11e") { throw new Error("Cannot decrement score below zero"); } else if (error.data === "0x441dfbd6") { throw new Error("Score not set for this user"); } else if (error.data === "0xb8b000dd") { throw new Error("Leaderboard has not started yet"); } else if (error.data === "0x9fde1257") { throw new Error("Leaderboard has ended"); } else if (error.data === "0x929fcbb9") { throw new Error("Leaderboard capacity reached"); } else { throw error; } } async addAdmin(newAdmin) { if (!this.walletKey) { throw new Error("Wallet key not set"); } try { return await this.contract.write.addAdmin([newAdmin], { account: (0, accounts_1.privateKeyToAccount)(this.walletKey), chain: this.chain, }); } catch (error) { return await this.handleError(error); } } async removeAdmin(admin) { if (!this.walletKey) { throw new Error("Wallet key not set"); } try { return await this.contract.write.removeAdmin([admin], { account: (0, accounts_1.privateKeyToAccount)(this.walletKey), chain: this.chain, }); } catch (error) { return await this.handleError(error); } } async updateLeaderboard(startTime, endTime, title) { if (!this.walletKey) { throw new Error("Wallet key not set"); } try { return await this.contract.write.updateLeaderboard([BigInt(startTime), BigInt(endTime), title], { account: (0, accounts_1.privateKeyToAccount)(this.walletKey), chain: this.chain, }); } catch (error) { return await this.handleError(error); } } async incrementScores(inputs) { if (!this.walletKey) { throw new Error("Wallet key not set"); } // if this is a private leaderboard, filter out users that are not eligible if (await this.isPrivate()) { const eligibleUsers = await this.getEligibleUsers(); inputs = inputs.filter((input) => eligibleUsers.includes(input.user)); } const formattedInputs = inputs.map((input) => ({ user: input.user, score: BigInt(input.score), timestamp: BigInt(input.timestamp), })); try { return await this.contract.write.incrementScores([formattedInputs], { account: (0, accounts_1.privateKeyToAccount)(this.walletKey), chain: this.chain, }); } catch (error) { return await this.handleError(error); } } async decrementScores(inputs) { if (!this.walletKey) { throw new Error("Wallet key not set"); } // if this is a private leaderboard, filter out users that are not eligible if (await this.isPrivate()) { const eligibleUsers = await this.getEligibleUsers(); inputs = inputs.filter((input) => eligibleUsers.includes(input.user)); } const formattedInputs = inputs.map((input) => ({ user: input.user, score: BigInt(input.score), timestamp: BigInt(input.timestamp), })); try { return await this.contract.write.decrementScores([formattedInputs], { account: (0, accounts_1.privateKeyToAccount)(this.walletKey), chain: this.chain, }); } catch (error) { return await this.handleError(error); } } async updateScores(inputs) { if (!this.walletKey) { throw new Error("Wallet key not set"); } // if this is a private leaderboard, filter out users that are not eligible if (await this.isPrivate()) { const eligibleUsers = await this.getEligibleUsers(); inputs = inputs.filter((input) => eligibleUsers.includes(input.user)); } const formattedInputs = inputs.map((input) => ({ user: input.user, score: BigInt(input.score), timestamp: BigInt(input.timestamp), })); try { return await this.contract.write.updateScores([formattedInputs], { account: (0, accounts_1.privateKeyToAccount)(this.walletKey), chain: this.chain, }); } catch (error) { return await this.handleError(error); } } async overwriteScores(inputs) { if (!this.walletKey) { throw new Error("Wallet key not set"); } // if this is a private leaderboard, filter out users that are not eligible if (await this.isPrivate()) { const eligibleUsers = await this.getEligibleUsers(); inputs = inputs.filter((input) => eligibleUsers.includes(input.user)); } const formattedInputs = inputs.map((input) => ({ user: input.user, score: BigInt(input.score), timestamp: BigInt(input.timestamp), })); try { return await this.contract.write.overwriteScores([formattedInputs], { account: (0, accounts_1.privateKeyToAccount)(this.walletKey), chain: this.chain, }); } catch (error) { return await this.handleError(error); } } async blacklistUsers(users) { if (!this.walletKey) { throw new Error("Wallet key not set"); } try { return await this.contract.write.blacklistUsers([users], { account: (0, accounts_1.privateKeyToAccount)(this.walletKey), chain: this.chain, }); } catch (error) { return await this.handleError(error); } } async unblacklistUser(user) { if (!this.walletKey) { throw new Error("Wallet key not set"); } try { return await this.contract.write.unblacklistUser([user], { account: (0, accounts_1.privateKeyToAccount)(this.walletKey), chain: this.chain, }); } catch (error) { return await this.handleError(error); } } async addEligibleUsers(users) { if (!this.walletKey) { throw new Error("Wallet key not set"); } try { return await this.contract.write.addEligibleUsers([users], { account: (0, accounts_1.privateKeyToAccount)(this.walletKey), chain: this.chain, }); } catch (error) { return await this.handleError(error); } } async removeEligibleUsers(users) { if (!this.walletKey) { throw new Error("Wallet key not set"); } try { return await this.contract.write.removeEligibleUsers([users], { account: (0, accounts_1.privateKeyToAccount)(this.walletKey), chain: this.chain, }); } catch (error) { return await this.handleError(error); } } async increaseUserAttempts(user, amount) { if (!this.walletKey) { throw new Error("Wallet key not set"); } try { return await this.contract.write.increaseUserAttempts([user, BigInt(amount)], { account: (0, accounts_1.privateKeyToAccount)(this.walletKey), chain: this.chain, }); } catch (error) { return await this.handleError(error); } } async decreaseUserAttempts(user, amount) { if (!this.walletKey) { throw new Error("Wallet key not set"); } try { return await this.contract.write.decreaseUserAttempts([user, BigInt(amount)], { account: (0, accounts_1.privateKeyToAccount)(this.walletKey), chain: this.chain, }); } catch (error) { return await this.handleError(error); } } async getUserAttempts(user) { try { return Number(await this.contract.read.getUserAttempts([user])); } catch (error) { return undefined; } } /** * Get all users and their scores, sorted by score in descending order */ async getAllScores() { try { if (this.contractAddress === "0x") { return []; } const [addresses, scores, timestamps] = (await this.contract.read.getLeaderboard()); // Create array of score objects const scoreObjects = addresses.map((user, index) => ({ player: user, score: Number(scores[index]), timestamp: Number(timestamps[index]), })); // Sort by score in descending order return scoreObjects .sort((a, b) => b.score - a.score) .map((score, index) => ({ ...score, rank: index + 1, })); } catch (error) { return []; } } /** * Get top N users and their scores * @param limit Number of top users to return */ async getTopScores(limit, startIndex = 0) { const allScores = await this.getAllScores(); return allScores.slice(startIndex, startIndex + limit); } /** * Get player ranking and score * @param userAddress Address of the player to look up */ async getPlayerRanking(userAddress) { const allScores = await this.getAllScores(); return allScores.find((score) => score.player.toLowerCase() === userAddress.toLowerCase()); } async getUserScore(user) { try { const [score, lastUpdated] = (await this.contract.read.getUserScore([ user, ])); return { score: Number(score), lastUpdated: Number(lastUpdated), }; } catch (error) { return undefined; } } async getLeaderboardUserCount() { try { return Number(await this.contract.read.getLeaderboardUserCount()); } catch (error) { return undefined; } } async getLeaderboardStartTime() { try { return Number(await this.contract.read.getLeaderboardStartTime()); } catch (error) { return undefined; } } async getLeaderboardEndTime() { try { return Number(await this.contract.read.getLeaderboardEndTime()); } catch (error) { return undefined; } } async isLeaderboardActive() { try { return (await this.contract.read.isLeaderboardActive()); } catch (error) { return false; } } async isLeaderboardEnded() { try { return (await this.contract.read.isLeaderboardEnded()); } catch (error) { return false; } } async isPrivate() { try { return (await this.contract.read.isPrivate()); } catch (error) { return false; } } async isUserBlacklisted(user) { try { return (await this.contract.read.isUserBlacklisted([user])); } catch (error) { return false; } } async isUserEligible(user) { try { return (await this.contract.read.isUserEligible([user])); } catch (error) { return false; } } async getEligibleUsers() { try { return (await this.contract.read.getEligibleUsers()); } catch (error) { return []; } } async getAdmins() { try { return (await this.contract.read.getAdmins()); } catch (error) { return []; } } async getBlacklistUsers() { try { return (await this.contract.read.getBlacklistUsers()); } catch (error) { return []; } } async getLeaderboardProperties() { try { const props = await this.contract.read.getLeaderboardProps(); return { startTime: Number(props.startTime), endTime: Number(props.endTime), hasConcluded: props.hasConcluded, slug: props.slug, title: props.title, isPrivate: props.isPrivate, useLatestScore: props.useLatestScore, hasAttemptLimit: props.hasAttemptLimit, initialAttempts: Number(props.initialAttempts), isReverseSort: props.isReverseSort, }; } catch (error) { return undefined; } } async getRemainingTime() { try { return Number(await this.contract.read.getRemainingTime()); } catch (error) { return undefined; } } async getTimeUntilStart() { try { return Number(await this.contract.read.getTimeUntilStart()); } catch (error) { return undefined; } } async getSlug() { try { return await this.contract.read.getSlug(); } catch (error) { return undefined; } } async getTitle() { try { return await this.contract.read.getTitle(); } catch (error) { return undefined; } } } exports.Leaderboard = Leaderboard; //# sourceMappingURL=leaderboard.js.map