UNPKG

@myria/leaderboard-ts-sdk

Version:

Myria Leaderboard typescripts SDK which will manage leaderboard for game developers

381 lines 35.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.LeaderboardManager = void 0; const LeaderboardAPI_1 = require("../core/apis/LeaderboardAPI"); const types_1 = require("../types"); class LeaderboardManager { constructor(params) { this.env = params.env; this.apiKey = params.apiKey; this.leaderboardAPI = new LeaderboardAPI_1.LeaderboardAPI(params.env); } async createLeaderboard(leaderboardParams) { /** * Validation rules */ if (!leaderboardParams.name) { throw new Error('Leaderboard name is required'); } if (!leaderboardParams.description) { throw new Error('Leaderboard description is required'); } if (!leaderboardParams.gameName) { throw new Error('Leaderboard name is required'); } if (!leaderboardParams.livePeriodInDays) { throw new Error('Leaderboard live period in days is required'); } if (!leaderboardParams.totalPeriods) { throw new Error('Leaderboard total periods are required'); } if (!leaderboardParams.updateScoreStrategy) { throw new Error('Leaderboard score strategy are required'); } try { const createdLeaderboardResponse = await this.leaderboardAPI.createLeaderboard(leaderboardParams, this.apiKey); if (createdLeaderboardResponse.status === 'success') { return createdLeaderboardResponse === null || createdLeaderboardResponse === void 0 ? void 0 : createdLeaderboardResponse.data; } else { throw new Error(`Create leaderboard failed: ${JSON.stringify(createdLeaderboardResponse)}`); } } catch (error) { console.error('Error creating leaderboard:', error); const errorMessage = `Failed to create the leaderboard: ${(error === null || error === void 0 ? void 0 : error.message) || (error === null || error === void 0 ? void 0 : error.status) || 'Unknown error occurred'}`; throw new Error(errorMessage); } } async deleteLeaderboardById(leaderboardId) { try { return await this.leaderboardAPI.deleteLeaderboardById(leaderboardId, this.apiKey); } catch (error) { console.error('Error deleting leaderboard:', error); const errorMessage = `Failed to delete the leaderboard: ${(error === null || error === void 0 ? void 0 : error.message) || (error === null || error === void 0 ? void 0 : error.status) || 'Unknown error occurred'}`; throw new Error(errorMessage); } } async getLeaderboards(params) { try { return await this.leaderboardAPI.getLeaderboards(params, this.apiKey); } catch (error) { console.error('Error retrieve leaderboard:', error); const errorMessage = `Get leaderboard error: ${(error === null || error === void 0 ? void 0 : error.message) || (error === null || error === void 0 ? void 0 : error.status) || 'Unknown error occurred'}`; throw new Error(errorMessage); } } /** * * @param queryScoreParams * limit */ async queryScoresByLeaderboardId(queryScoreParams) { var _a; /** * Validation rules */ if (queryScoreParams.leaderboardId === undefined || (queryScoreParams.leaderboardId !== undefined && queryScoreParams.leaderboardId === 0)) { throw new Error('Leaderboard id is required or invalid'); } if (queryScoreParams.page !== undefined && queryScoreParams.page === 0) { throw new Error('Page is invalid'); } if (queryScoreParams.filters && ((_a = queryScoreParams.filters.userId) === null || _a === void 0 ? void 0 : _a.length) === 0) { throw new Error('UserId is required'); } try { return await this.leaderboardAPI.getScoresByLeaderboardId(queryScoreParams, this.apiKey); } catch (error) { console.error('Error querying scores by leaderboard id:', error); const errorMessage = `Failed to query scores: ${(error === null || error === void 0 ? void 0 : error.message) || (error === null || error === void 0 ? void 0 : error.status) || 'Unknown error occurred'}`; throw new Error(errorMessage); } } /** * * @param queryScoreByUserIdParams * limit */ async getScoresByPlayerId(queryScoreByUserIdParams) { /** * Validation rules */ if (!queryScoreByUserIdParams.leaderboardId || (queryScoreByUserIdParams.leaderboardId && queryScoreByUserIdParams.leaderboardId === 0)) { throw new Error('Leaderboard id is required'); } if (!queryScoreByUserIdParams.userId || (queryScoreByUserIdParams.userId && queryScoreByUserIdParams.userId.length === 0)) { throw new Error('userId is required'); } try { return await this.leaderboardAPI.getScoresByLeaderboardIdAndUserId(queryScoreByUserIdParams, this.apiKey); } catch (error) { console.error('Error querying scores by player id:', error); const errorMessage = `Failed to query scores by player id: ${(error === null || error === void 0 ? void 0 : error.message) || (error === null || error === void 0 ? void 0 : error.status) || 'Unknown error occurred'}`; throw new Error(errorMessage); } } /** * * @param postScoreParams * limit */ async postPlayerScore(postScoreParams) { /** * Validation rules */ if (!postScoreParams.leaderboardId) { throw new Error('Leaderboard id is required'); } if (!postScoreParams.items) { throw new Error('Leaderboard id is required'); } if (postScoreParams.items) { const isExistedUserId = postScoreParams.items.some((value) => value.userId.length > 0); if (!isExistedUserId) { throw new Error('userId is required'); } } try { return await this.leaderboardAPI.postNewScore(postScoreParams, this.apiKey); } catch (error) { console.error('Error Post new scores by leaderboard id:', error); const errorMessage = `Failed to post score for players: ${(error === null || error === void 0 ? void 0 : error.message) || (error === null || error === void 0 ? void 0 : error.status) || 'Unknown error occurred'}`; // UPDATE TODO : Need logic to parse Axios error throw new Error(errorMessage); } } async createOrUpdateRewardDistributionConfig(createRewardConfig) { var _a; if (!createRewardConfig.leaderboardId) { throw new Error('Leaderboard ID is required'); } if (!createRewardConfig.rewardConfig) { throw new Error('Reward config is required'); } if (!createRewardConfig.rewardConfig.distributionType || (createRewardConfig.rewardConfig.distributionType !== types_1.DistributionType.FIXED && createRewardConfig.rewardConfig.distributionType !== types_1.DistributionType.PERCENTAGE)) { throw new Error('Distribution type is required to be enum of [FIXED, PERCENTAGE]'); } if (!createRewardConfig.rewardConfig.period || createRewardConfig.rewardConfig.period === 0) { throw new Error('Period is required for rewards config'); } if (!createRewardConfig.rewardConfig.items || ((_a = createRewardConfig.rewardConfig.items) === null || _a === void 0 ? void 0 : _a.length) === 0) { throw new Error('Item is required for rewards config'); } createRewardConfig.rewardConfig.items.forEach((item) => { if (!item.detail) { throw new Error('Details of reward item are required'); } if (item.detail.type !== 'ERC20') { throw new Error('Only ERC20 token type is supported at this version'); } if (!item.detail.amount) { throw new Error('Require to specify the amount of token distribution'); } }); const rewardConfigResponseData = await this.leaderboardAPI.updateRewardDistributionConfig(createRewardConfig, this.apiKey); if (rewardConfigResponseData && rewardConfigResponseData.status !== 'success') { throw new Error('Reward config updated has failed due to server error'); } const rewardConfigResp = { distributionType: createRewardConfig.rewardConfig.distributionType, period: createRewardConfig.rewardConfig.period, isApplyRewardAllPeriods: createRewardConfig.rewardConfig.isApplyRewardAllPeriods, rewardPoolAmount: createRewardConfig.rewardConfig.rewardPoolAmount, items: createRewardConfig.rewardConfig.items, }; return rewardConfigResp; } async getSimplifiedRewardConfig(getLeaderboardDetailsParams, period) { var _a, _b, _c; if (!getLeaderboardDetailsParams.leaderboardIdOrName || getLeaderboardDetailsParams.leaderboardIdOrName.length === 0) { throw new Error('Require leaderboard ID or leaderboard name'); } const leaderboardDetailsResponse = await this.leaderboardAPI.getLeaderboardDetailsInfo(getLeaderboardDetailsParams, this.apiKey); if (leaderboardDetailsResponse.status !== 'success') { throw new Error('Leaderboard fetch error with internal server error - please contact admin supports'); } const leaderboardDetails = leaderboardDetailsResponse.data; if (leaderboardDetails.rewards && period && !leaderboardDetails.rewards[period]) { throw new Error(`No reward configuration is available for the specified period: ${period}.`); } const queriedPeriod = period || leaderboardDetails.currentPeriod; const rewards = leaderboardDetails.rewards; const rewardDistributionConfigResp = { isApplyRewardAllPeriods: leaderboardDetails.isApplyRewardAllPeriods, distributionType: ((_a = rewards[queriedPeriod]) === null || _a === void 0 ? void 0 : _a.distributionType) || types_1.DistributionType.FIXED, period: queriedPeriod, rewardPoolAmount: ((_b = rewards[queriedPeriod]) === null || _b === void 0 ? void 0 : _b.rewardPoolAmount) || 0, items: ((_c = rewards[queriedPeriod]) === null || _c === void 0 ? void 0 : _c.items) || [], }; return rewardDistributionConfigResp; } async getRewardDistributionInfo(getLeaderboardDetailsParams) { if (!getLeaderboardDetailsParams.leaderboardIdOrName || getLeaderboardDetailsParams.leaderboardIdOrName.length === 0) { throw new Error('Require leaderboard ID or leaderboard name'); } const leaderboardDetailsResponse = await this.leaderboardAPI.getLeaderboardDetailsInfo(getLeaderboardDetailsParams, this.apiKey); if (leaderboardDetailsResponse.status !== 'success') { throw new Error('Leaderboard fetch error with internal server error - please contact admin supports'); } const leaderboardDetails = leaderboardDetailsResponse.data; if (!leaderboardDetailsResponse.data.rewards) { throw new Error('No rewards distribution config are available !'); } const rewards = leaderboardDetails.rewards; const rewardConfigResp = { isApplyRewardAllPeriods: leaderboardDetails.isApplyRewardAllPeriods, currentPeriod: leaderboardDetails.currentPeriod, rewardPoolAmountInCurrentPeriod: rewards[leaderboardDetails.currentPeriod].rewardPoolAmount, data: rewards, }; return rewardConfigResp; } async getRewardsInCurrrentPeriod(getLeaderboardDetailsParams) { if (!getLeaderboardDetailsParams.leaderboardIdOrName || getLeaderboardDetailsParams.leaderboardIdOrName.length === 0) { throw new Error('Require leaderboard ID or leaderboard name'); } const leaderboardDetailsResponse = await this.leaderboardAPI.getLeaderboardDetailsInfo(getLeaderboardDetailsParams, this.apiKey); if (leaderboardDetailsResponse.status !== 'success') { throw new Error('Leaderboard fetch error with internal server error - please contact admin supports'); } const leaderboardDetails = leaderboardDetailsResponse.data; if (!leaderboardDetailsResponse.data.rewards) { throw new Error('No rewards distribution config are available !'); } const rewards = leaderboardDetails.rewards; const rewardInCurrentPeriod = { isApplyRewardAllPeriods: leaderboardDetails.isApplyRewardAllPeriods, currentPeriod: leaderboardDetails.currentPeriod, data: rewards[leaderboardDetails.currentPeriod], }; return rewardInCurrentPeriod; } async getRewardsWithPeriod(getRewardWithPeriod) { if (!getRewardWithPeriod.leaderboardIdOrName || getRewardWithPeriod.leaderboardIdOrName.length === 0) { throw new Error('Require leaderboard ID or leaderboard name'); } const leaderboardDetailsResponse = await this.leaderboardAPI.getLeaderboardDetailsInfo(getRewardWithPeriod, this.apiKey); if (leaderboardDetailsResponse.status !== 'success') { throw new Error('Leaderboard fetch error with internal server error - please contact admin supports'); } const leaderboardDetails = leaderboardDetailsResponse.data; if (!leaderboardDetailsResponse.data.rewards) { throw new Error('No rewards distribution config are available !'); } const rewards = leaderboardDetails.rewards; if (!rewards[getRewardWithPeriod.period]) { throw new Error(`This leaderboad ${leaderboardDetails.id} does not contains period ${getRewardWithPeriod.period}`); } const rewardInPeriod = { isApplyRewardAllPeriods: leaderboardDetails.isApplyRewardAllPeriods, period: getRewardWithPeriod.period, data: rewards[getRewardWithPeriod.period], }; return rewardInPeriod; } async getLeaderboardDetailsInfo(getLeaderboardDetailsParams) { if (!getLeaderboardDetailsParams.leaderboardIdOrName || getLeaderboardDetailsParams.leaderboardIdOrName.length === 0) { throw new Error('Require leaderboard ID or leaderboard name'); } const leaderboardDetails = await this.leaderboardAPI.getLeaderboardDetailsInfo(getLeaderboardDetailsParams, this.apiKey); if (leaderboardDetails.status !== 'success') { throw new Error('Leaderboard fetch error with internal server error - please contact admin supports'); } return leaderboardDetails.data; } async setGameMetadata(params) { if (!params.leaderboardId) { throw new Error('Leaderboard ID is required'); } if (!params.gameMetadata) { throw new Error('Game metadata json object is required'); } if (Object.keys(params.gameMetadata).length === 0) { throw new Error('Game metadata json object required the object value'); } const leaderboardData = await this.leaderboardAPI.updateGameMetadata(params, this.apiKey); if (leaderboardData.status !== 'success') { throw new Error('There is an internal server error when update. Please contact admin for support'); } return leaderboardData.data; } async setConfigMetadata(params) { if (!params.leaderboardId) { throw new Error('Leaderboard ID is required'); } if (!params.configMetadata) { throw new Error('Config metadata json object is required'); } if (Object.keys(params.configMetadata).length === 0) { throw new Error('Config metadata json object required the object value'); } const leaderboardData = await this.leaderboardAPI.updateConfigMetadata(params, this.apiKey); if (leaderboardData.status !== 'success') { throw new Error('There is an internal server error when update. Please contact admin for support'); } return leaderboardData.data; } async setGlobalMetadata(params) { if (!params.leaderboardId) { throw new Error('Leaderboard ID is required'); } if (!params.gameMetadata) { throw new Error('Game metadata json object is required'); } if (!params.configMetadata) { throw new Error('Config metadata json object is required'); } if (Object.keys(params.configMetadata).length === 0) { throw new Error('Config metadata json object required the object value'); } if (Object.keys(params.gameMetadata).length === 0) { throw new Error('Game metadata json object required the object value'); } const leaderboardData = await this.leaderboardAPI.updateGlobalMetadata(params, this.apiKey); if (leaderboardData.status !== 'success') { throw new Error('There is an internal server error when update. Please contact admin for support'); } return leaderboardData.data; } async updateUserInfo(params) { if (!params.userId) { throw new Error('User ID is required'); } if (!params.username) { throw new Error('Username is required'); } const userResponseData = await this.leaderboardAPI.updateUserInfo(params, this.apiKey); if (userResponseData.status !== 'success') { throw new Error('There is an internal server error when update. Please contact admin for support'); } return userResponseData.data; } } exports.LeaderboardManager = LeaderboardManager; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTGVhZGVyYm9hcmRNYW5hZ2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL21vZHVsZXMvTGVhZGVyYm9hcmRNYW5hZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLGdFQUE2RDtBQW9CN0Qsb0NBV2tCO0FBR2xCLE1BQU0sa0JBQWtCO0lBS3RCLFlBQVksTUFBNkI7UUFDdkMsSUFBSSxDQUFDLEdBQUcsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDO1FBQ3RCLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQztRQUM1QixJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksK0JBQWMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDdkQsQ0FBQztJQUVNLEtBQUssQ0FBQyxpQkFBaUIsQ0FDNUIsaUJBQTBDO1FBRTFDOztXQUVHO1FBQ0gsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksRUFBRTtZQUMzQixNQUFNLElBQUksS0FBSyxDQUFDLDhCQUE4QixDQUFDLENBQUM7U0FDakQ7UUFDRCxJQUFJLENBQUMsaUJBQWlCLENBQUMsV0FBVyxFQUFFO1lBQ2xDLE1BQU0sSUFBSSxLQUFLLENBQUMscUNBQXFDLENBQUMsQ0FBQztTQUN4RDtRQUNELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLEVBQUU7WUFDL0IsTUFBTSxJQUFJLEtBQUssQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDO1NBQ2pEO1FBQ0QsSUFBSSxDQUFDLGlCQUFpQixDQUFDLGdCQUFnQixFQUFFO1lBQ3ZDLE1BQU0sSUFBSSxLQUFLLENBQUMsNkNBQTZDLENBQUMsQ0FBQztTQUNoRTtRQUNELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLEVBQUU7WUFDbkMsTUFBTSxJQUFJLEtBQUssQ0FBQyx3Q0FBd0MsQ0FBQyxDQUFDO1NBQzNEO1FBQ0QsSUFBSSxDQUFDLGlCQUFpQixDQUFDLG1CQUFtQixFQUFFO1lBQzFD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