@myria/leaderboard-ts-sdk
Version:
Myria Leaderboard typescripts SDK which will manage leaderboard for game developers
381 lines • 35.1 kB
JavaScript
;
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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