diff --git a/src/controllers/evaluationController.ts b/src/controllers/evaluationController.ts index 9f8e6c8..80ea3ce 100644 --- a/src/controllers/evaluationController.ts +++ b/src/controllers/evaluationController.ts @@ -108,13 +108,27 @@ export const recreateEvaluationQuestions = async ( return; } - await evaluationQuestionService.resetEvaluationQuestions( - chainId, - alloPoolId, - evaluationQuestions + const [errorReset] = await catchError( + evaluationQuestionService.resetEvaluationQuestions( + chainId, + alloPoolId, + evaluationQuestions + ) ); - await evaluationService.cleanEvaluations(); + if (errorReset !== undefined) { + logger.error('Failed to reset evaluation questions', { errorReset }); + res.status(500).json({ message: 'Failed to reset evaluation questions' }); + return; + } + + const [errorClean] = await catchError(evaluationService.cleanEvaluations()); + + if (errorClean !== undefined) { + logger.error('Failed to clean evaluations', { errorClean }); + res.status(500).json({ message: 'Failed to clean evaluations' }); + return; + } res.status(200).json(evaluationQuestions); }; @@ -150,14 +164,16 @@ export const evaluateApplication = async ( summaryInput, }; - const isAllowed = await isPoolManager( - createEvaluationParams, - signature, - chainId, - alloPoolId + const [isAllowedError, isAllowed] = await catchError( + isPoolManager( + createEvaluationParams, + signature, + chainId, + alloPoolId + ) ); - if (!isAllowed) { + if (isAllowedError !== undefined || isAllowed === undefined) { logger.warn( `User with address: ${evaluator} is not allowed to evaluate application` ); @@ -301,16 +317,17 @@ export const triggerLLMEvaluation = async ( questions, }; - try { - await createLLMEvaluations([data]); - res.status(200).json({ message: 'LLM evaluation triggered successfully' }); - } catch (error) { + const [error] = await catchError(createLLMEvaluations([data])); + if (error !== undefined) { logger.error('Failed to create evaluations:', error); res.status(500).json({ message: 'Failed to create evaluations', error: error.message, }); } + + logger.info('LLM evaluation triggered successfully'); + res.status(200).json({ message: 'LLM evaluation triggered successfully' }); }; const batchPromises = (array: T[], batchSize: number): T[][] => { diff --git a/src/controllers/passportValidationController.ts b/src/controllers/passportValidationController.ts index 11899fd..3981371 100644 --- a/src/controllers/passportValidationController.ts +++ b/src/controllers/passportValidationController.ts @@ -1,12 +1,15 @@ import type { Request, Response } from 'express'; -import { validateRequest } from '@/utils'; +import { catchError, validateRequest } from '@/utils'; import type { ProjectApplicationForManager } from '@/ext/passport/types'; import { isVerified } from '@/ext/passport/credentialverification'; +import { createLogger } from '@/logger'; interface SocialCredentialBody { application: Partial; } +const logger = createLogger(); + export const validateSocialCredential = async ( req: Request, res: Response @@ -15,13 +18,16 @@ export const validateSocialCredential = async ( const { application } = req.body as SocialCredentialBody; - try { - const result = await isVerified(application); - res.json({ - message: 'Social credential validated', - provider: result, - }); - } catch (error) { + const [error, result] = await catchError(isVerified(application)); + if (error !== undefined) { + logger.error('Failed to validate social credential:', error); res.status(400).json({ message: 'Error validating social credential' }); + return; } + + logger.info('Social credential validated', { result }); + res.json({ + message: 'Social credential validated', + provider: result, + }); }; diff --git a/src/controllers/poolController.ts b/src/controllers/poolController.ts index b288916..5914bcf 100644 --- a/src/controllers/poolController.ts +++ b/src/controllers/poolController.ts @@ -186,11 +186,17 @@ const handlePoolEvaluationQuestions = async ( pool: Pool, poolMetadata: IndexerRoundMetadata ): Promise => { - const questions = - await evaluationQuestionService.getEvaluationQuestionsByAlloPoolId( + const [error, questions] = await catchError( + evaluationQuestionService.getEvaluationQuestionsByAlloPoolId( pool.alloPoolId, pool.chainId - ); + ) + ); + + if (error !== undefined || questions === undefined) { + logger.error('Failed to get evaluation questions:', error); + throw new Error('Failed to get evaluation questions'); + } if (questions.length > 0) { return questions.map(question => question.question); diff --git a/src/ext/indexer/indexer.ts b/src/ext/indexer/indexer.ts index 224cfcb..93be1ac 100644 --- a/src/ext/indexer/indexer.ts +++ b/src/ext/indexer/indexer.ts @@ -87,7 +87,6 @@ class IndexerClient { getRoundManager, requestVariables ); - if (response.rounds.length === 0) { this.logger.warn( `No round found for poolId: ${alloPoolId} on chainId: ${chainId}` @@ -97,7 +96,7 @@ class IndexerClient { const round = response.rounds[0]; - if (round.roles.length === 0) { + if (round.roundRoles.length === 0) { this.logger.warn( `No manager found for poolId: ${alloPoolId} on chainId: ${chainId}` ); @@ -105,7 +104,7 @@ class IndexerClient { } this.logger.info(`Successfully fetched round manager`); - return round.roles.map(role => role.address); + return round.roundRoles.map(role => role.address); } catch (error) { this.logger.error(`Failed to fetch round manager: ${error.message}`, { error, @@ -157,7 +156,16 @@ class IndexerClient { return null; } - const round = response.rounds[0]; + const round = { + chainId: response.rounds[0].chainId, + id: response.rounds[0].id, + roundMetadata: response.rounds[0].roundMetadata, + roundMetadataCid: response.rounds[0].roundMetadataCid, + applications: response.rounds[0].applications.map(application => ({ + ...application, + project: application.projects[0], + })), + }; // Cache the result this.cache.set(cacheKey, round); @@ -197,7 +205,7 @@ class IndexerClient { requestVariables ); - const application = response.application; + const application = response.applications[0]; if (application == null) { this.logger.warn( @@ -205,7 +213,7 @@ class IndexerClient { ); return null; } - return response.application; + return application; } catch (error) { this.logger.error( `Failed to fetch round with single application: ${error.message}`, diff --git a/src/ext/indexer/queries.ts b/src/ext/indexer/queries.ts index 7758b9f..cd51645 100644 --- a/src/ext/indexer/queries.ts +++ b/src/ext/indexer/queries.ts @@ -2,10 +2,8 @@ import { gql } from 'graphql-request'; export const getRoundManager = gql` query RoundManager($chainId: Int!, $alloPoolId: String!) { - rounds( - filter: { chainId: { equalTo: $chainId }, id: { equalTo: $alloPoolId } } - ) { - roles { + rounds(where: { chainId: { _eq: $chainId }, id: { _eq: $alloPoolId } }) { + roundRoles { address } } @@ -14,9 +12,7 @@ export const getRoundManager = gql` export const getRoundWithApplications = gql` query RoundApplications($chainId: Int!, $roundId: String!) { - rounds( - filter: { chainId: { equalTo: $chainId }, id: { equalTo: $roundId } } - ) { + rounds(where: { chainId: { _eq: $chainId }, id: { _eq: $roundId } }) { chainId id roundMetadata @@ -27,7 +23,7 @@ export const getRoundWithApplications = gql` metadataCid status projectId - project: canonicalProject { + projects(where: { projectType: { _eq: "canonical" } }) { metadata metadataCid } @@ -42,7 +38,13 @@ export const getApplicationWithRound = gql` $roundId: String! $applicationId: String! ) { - application(chainId: $chainId, roundId: $roundId, id: $applicationId) { + applications( + where: { + chainId: { _eq: $chainId } + roundId: { _eq: $roundId } + id: { _eq: $applicationId } + } + ) { metadata metadataCid round { diff --git a/src/ext/indexer/types.ts b/src/ext/indexer/types.ts index 5a76268..1cb5d36 100644 --- a/src/ext/indexer/types.ts +++ b/src/ext/indexer/types.ts @@ -1,3 +1,4 @@ +// 1. Basic Types & Enums export type Address = `0x${string}`; export enum Status { @@ -6,6 +7,7 @@ export enum Status { REJECTED = 'REJECTED', } +// 2. Metadata & Supporting Interfaces export interface ApplicationMetadata { signature: string; application: { @@ -52,34 +54,48 @@ export interface ProjectMetadata { projectTwitter?: string; userGithub?: string; projectGithub?: string; - // credentials: ProjectCredentials; owners: Array<{ address: string }>; createdAt: number; lastUpdated: number; } -export interface Application { +// 3. Base Interfaces (Used in Multiple Places) +export interface BaseProject { + metadata: ProjectMetadata; + metadataCid: string; +} + +export interface BaseApplication { id: string; metadata: ApplicationMetadata; metadataCid: string; status: Status; projectId: string; - project: { - metadata: ProjectMetadata; - metadataCid: string; - }; } -export interface RoundWithApplications { +// 4. Extended Implementations +export interface Application extends BaseApplication { + project: BaseProject; +} + +export interface ApplicationQuery extends BaseApplication { + projects: BaseProject[]; +} + +export interface BaseRound { chainId: number; id: string; roundMetadata: RoundMetadata; roundMetadataCid: string; - applications: Application[]; + applications: T[]; } +export type RoundWithApplications = BaseRound; +export type RoundWithApplicationsQuery = BaseRound; + +// 5. API Response Structures export interface RoundApplicationsQueryResponse { - rounds: RoundWithApplications[]; + rounds: RoundWithApplicationsQuery[]; } export interface ApplicationWithRound { @@ -94,12 +110,12 @@ export interface ApplicationWithRound { } export interface ApplicationRoundQueryResponse { - application: ApplicationWithRound; + applications: ApplicationWithRound[]; } export interface ManagerRolesResponse { rounds: Array<{ - roles: Array<{ + roundRoles: Array<{ address: string; }>; }>; diff --git a/src/utils.ts b/src/utils.ts index c817a72..86d6a1b 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -59,14 +59,23 @@ export async function isPoolManager( chainId: number, alloPoolId: string ): Promise { - const validAddresses = await indexerClient.getRoundManager({ - chainId, - alloPoolId, - }); + const [error, validAddresses] = await catchError( + indexerClient.getRoundManager({ + chainId, + alloPoolId, + }) + ); + + if (error !== undefined || validAddresses === undefined) { + logger.error('Failed to fetch pool manager', { error }); + return false; + } + if (env.NODE_ENV === 'development' && signature === '0xdeadbeef') { logger.info('Skipping signature check in development mode'); return true; } + try { const address = await recoverSignerAddress(obj, signature); logger.info(`Recovered address: ${address}`);