wisdom-sdk
Version:
Core business logic and data access layer for prediction markets
390 lines (388 loc) • 13.2 kB
JavaScript
import { generateUUID } from './chunk-7CBIP22I.js';
import { userBalanceStore } from './chunk-SL5BKWK6.js';
import { getSetMembers, getEntity, startTransaction, storeEntity, deleteEntity, removeFromSet } from './chunk-FIJAO3BQ.js';
import { logger, AppError } from './chunk-2OHF4QSJ.js';
// src/bug-report-store.ts
var bugReportLogger = logger.child({ context: "bug-report-store" });
var DEFAULT_INITIAL_REWARD = 10;
var DEFAULT_CONFIRMATION_REWARD = 90;
var BugReportStore = class {
/**
* Get all bug reports
*/
async getAllBugReports() {
try {
const reportIds = await getSetMembers("BUG_REPORT_IDS", "");
if (!reportIds || reportIds.length === 0) {
return [];
}
const reports = await Promise.all(
reportIds.map(async (id) => {
const report = await getEntity("BUG_REPORT", id);
return report;
})
);
return reports.filter((report) => report !== null);
} catch (error) {
throw new AppError({
message: "Failed to retrieve bug reports",
context: "bug-report-store",
code: "BUG_REPORT_FETCH_ERROR",
originalError: error instanceof Error ? error : new Error(String(error))
}).log();
}
}
/**
* Get specific bug report by ID
*/
async getBugReport(id) {
if (!id) {
bugReportLogger.warn({}, "Attempted to get bug report with empty ID");
return null;
}
const report = await getEntity("BUG_REPORT", id);
if (!report) {
bugReportLogger.debug({ reportId: id }, `Bug report ${id} not found`);
}
return report;
}
/**
* Get all bug reports for a specific user
*/
async getUserBugReports(userId) {
try {
if (!userId) {
return [];
}
const reportIds = await getSetMembers("USER_BUG_REPORTS", userId);
if (reportIds.length === 0) {
return [];
}
const reports = await Promise.all(
reportIds.map((id) => this.getBugReport(id))
);
return reports.filter((report) => report !== null);
} catch (error) {
throw new AppError({
message: `Failed to retrieve bug reports for user ${userId}`,
context: "bug-report-store",
code: "USER_BUG_REPORTS_ERROR",
originalError: error instanceof Error ? error : new Error(String(error)),
data: { userId }
}).log();
}
}
/**
* Create a new bug report
*/
async createBugReport(data) {
try {
if (!data.title || !data.description || !data.createdBy) {
throw new AppError({
message: "Missing required bug report data",
context: "bug-report-store",
code: "BUG_REPORT_VALIDATION_ERROR",
data: {
hasTitle: !!data.title,
hasDescription: !!data.description,
hasCreatedBy: !!data.createdBy
}
}).log();
}
const id = generateUUID();
const now = (/* @__PURE__ */ new Date()).toISOString();
const bugReport = {
id,
title: data.title,
description: data.description,
severity: data.severity,
url: data.url,
createdBy: data.createdBy,
createdAt: now,
status: "open"
};
const tx = await startTransaction();
try {
await tx.addEntity("BUG_REPORT", id, bugReport);
await tx.addToSetInTransaction("BUG_REPORT_IDS", "", id);
await tx.addToSetInTransaction("USER_BUG_REPORTS", data.createdBy, id);
const success = await tx.execute();
if (!success) {
throw new AppError({
message: "Failed to create bug report - transaction failed",
context: "bug-report-store",
code: "BUG_REPORT_TRANSACTION_ERROR",
data: { reportId: id }
}).log();
}
bugReportLogger.info(
{ reportId: id, userId: data.createdBy },
`Bug report created: ${data.title}`
);
return bugReport;
} catch (error) {
if (error instanceof AppError) {
throw error;
} else {
throw new AppError({
message: "Error during bug report creation transaction",
context: "bug-report-store",
code: "BUG_REPORT_CREATE_TRANSACTION_ERROR",
originalError: error instanceof Error ? error : new Error(String(error)),
data: { title: data.title }
}).log();
}
}
} catch (error) {
if (error instanceof AppError) {
throw error;
} else {
throw new AppError({
message: "Failed to create bug report",
context: "bug-report-store",
code: "BUG_REPORT_CREATE_ERROR",
originalError: error instanceof Error ? error : new Error(String(error)),
data: { title: data.title }
}).log();
}
}
}
/**
* Update an existing bug report
*/
async updateBugReport(id, data) {
try {
const existingReport = await this.getBugReport(id);
if (!existingReport) {
bugReportLogger.warn({ reportId: id }, `Cannot update non-existent bug report with ID ${id}`);
return null;
}
const safeData = { ...data };
if (safeData.id && safeData.id !== id) {
delete safeData.id;
bugReportLogger.warn(
{ reportId: id, attemptedId: data.id },
"Attempted to change bug report ID during update - ignoring"
);
}
const updatedReport = {
...existingReport,
...safeData,
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
};
await storeEntity("BUG_REPORT", id, updatedReport);
bugReportLogger.debug(
{ reportId: id },
`Bug report updated: ${existingReport.title}`
);
return updatedReport;
} catch (error) {
throw new AppError({
message: `Failed to update bug report ${id}`,
context: "bug-report-store",
code: "BUG_REPORT_UPDATE_ERROR",
originalError: error instanceof Error ? error : new Error(String(error)),
data: { reportId: id }
}).log();
}
}
async deleteBugReport(id) {
try {
const report = await this.getBugReport(id);
if (!report) {
throw new Error(`Bug report ${id} not found`);
}
await deleteEntity("BUG_REPORT", id);
await removeFromSet("BUG_REPORT_IDS", "", id);
await removeFromSet("USER_BUG_REPORTS", report.createdBy, id);
return true;
} catch (error) {
console.error(`Error deleting bug report ${id}:`, error);
return false;
}
}
/**
* Process a reward payment for a bug report
* This handles giving the initial or confirmation reward to a user
*
* @param reportId Bug report ID
* @param userId User ID to receive the reward
* @param rewardType Type of reward (initial or confirmation)
* @param customAmount Optional custom amount (overrides defaults)
* @returns Result object with success/error status
*/
/**
* Confirm a bug report (mark as verified by admin)
* @param id Bug report ID
* @param adminId ID of the admin confirming the report
*/
async confirmBugReport(id, adminId) {
try {
const report = await this.getBugReport(id);
if (!report) {
bugReportLogger.warn({ reportId: id }, `Cannot confirm non-existent bug report: ${id}`);
return null;
}
if (report.status === "resolved") {
bugReportLogger.warn({ reportId: id }, `Bug report ${id} is already resolved`);
return report;
}
const now = (/* @__PURE__ */ new Date()).toISOString();
const updatedReport = await this.updateBugReport(id, {
status: "resolved",
confirmedBy: adminId,
confirmedAt: now,
updatedBy: adminId,
updatedAt: now
});
bugReportLogger.info(
{ reportId: id, adminId },
`Bug report confirmed: ${report.title}`
);
return updatedReport;
} catch (error) {
throw new AppError({
message: `Failed to confirm bug report ${id}`,
context: "bug-report-store",
code: "BUG_REPORT_CONFIRM_ERROR",
originalError: error instanceof Error ? error : new Error(String(error)),
data: { reportId: id, adminId }
}).log();
}
}
/**
* Pay a reward for a bug report
* @param id Bug report ID
* @param isInitialReward Whether to pay the initial (true) or confirmation (false) reward
*/
async payReward(id, isInitialReward) {
try {
const report = await this.getBugReport(id);
if (!report) {
bugReportLogger.warn({ reportId: id }, `Cannot pay reward for non-existent bug report: ${id}`);
return null;
}
const recipientId = report.createdBy;
const rewardType = isInitialReward ? "initial" : "confirmation";
const result = await this.processRewardPayment(id, recipientId, rewardType);
if (!result.success) {
throw new AppError({
message: result.error || "Failed to pay reward",
context: "bug-report-store",
code: "REWARD_PAYMENT_FAILED",
data: {
reportId: id,
userId: recipientId,
rewardType,
error: result.error
}
});
}
return result.report || null;
} catch (error) {
if (error instanceof AppError) {
throw error;
} else {
throw new AppError({
message: `Failed to pay ${isInitialReward ? "initial" : "confirmation"} reward for bug report ${id}`,
context: "bug-report-store",
code: "REWARD_PAYMENT_ERROR",
originalError: error instanceof Error ? error : new Error(String(error)),
data: { reportId: id, isInitialReward }
}).log();
}
}
}
/**
* Internal helper method to process reward payments
* This handles giving the initial or confirmation reward to a user
*/
async processRewardPayment(reportId, userId, rewardType, customAmount) {
try {
const opLogger = bugReportLogger.child({
operation: "processRewardPayment",
reportId,
userId,
rewardType
});
opLogger.info({}, `Processing ${rewardType} reward payment`);
const report = await this.getBugReport(reportId);
if (!report) {
return { success: false, error: "Bug report not found" };
}
const amount = customAmount || (rewardType === "initial" ? DEFAULT_INITIAL_REWARD : DEFAULT_CONFIRMATION_REWARD);
if (rewardType === "initial" && report.initialRewardPaid) {
opLogger.warn({}, "Initial reward already paid for this report");
return {
success: false,
error: "Initial reward already paid for this report",
report
};
}
if (rewardType === "confirmation" && report.confirmationRewardPaid) {
opLogger.warn({}, "Confirmation reward already paid for this report");
return {
success: false,
error: "Confirmation reward already paid for this report",
report
};
}
opLogger.debug({ amount }, `Processing payment of ${amount} tokens`);
const updatedBalance = await userBalanceStore.addFunds(userId, amount);
if (!updatedBalance) {
throw new AppError({
message: "Failed to update user balance",
context: "bug-report-store",
code: "BALANCE_UPDATE_FAILED",
data: { userId, amount, reportId }
});
}
const updateData = {};
if (rewardType === "initial") {
updateData.initialRewardPaid = true;
} else {
updateData.confirmationRewardPaid = true;
if (report.status !== "resolved") {
updateData.status = "resolved";
updateData.confirmedAt = (/* @__PURE__ */ new Date()).toISOString();
}
}
const updatedReport = await this.updateBugReport(reportId, updateData);
if (!updatedReport) {
throw new AppError({
message: "Failed to update bug report after payment",
context: "bug-report-store",
code: "REPORT_UPDATE_FAILED",
data: { reportId, rewardType }
});
}
opLogger.info(
{ amount, reportId, userId },
`Successfully processed ${rewardType} reward payment`
);
return {
success: true,
amount,
report: updatedReport
};
} catch (error) {
if (error instanceof AppError) {
error.log();
return { success: false, error: error.message };
} else {
const appError = new AppError({
message: `Error processing reward payment for report ${reportId}`,
context: "bug-report-store",
code: "REWARD_PROCESS_ERROR",
originalError: error instanceof Error ? error : new Error(String(error)),
data: { reportId, userId, rewardType }
}).log();
return { success: false, error: appError.message };
}
}
}
};
var bugReportStore = new BugReportStore();
export { BugReportStore, bugReportStore };
//# sourceMappingURL=chunk-NNOTRTHN.js.map
//# sourceMappingURL=chunk-NNOTRTHN.js.map