Skip to content

Commit

Permalink
Merge pull request #105 from Giveth/feat/handle-rf-projects-rounds
Browse files Browse the repository at this point in the history
Feat/handle rf projects rounds
  • Loading branch information
MohammadPCh authored Aug 22, 2024
2 parents 53bdebf + a778112 commit 56d036b
Show file tree
Hide file tree
Showing 16 changed files with 146 additions and 98 deletions.
13 changes: 13 additions & 0 deletions db/migrations/1724279465327-Data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module.exports = class Data1724279465327 {
name = "Data1724279465327";

async up(db) {
await db.query(`ALTER TABLE "project" DROP COLUMN "source_status"`);
await db.query(`ALTER TABLE "project" ADD "rf_rounds" integer array`);
}

async down(db) {
await db.query(`ALTER TABLE "project" DROP COLUMN "rf_rounds"`);
await db.query(`ALTER TABLE "project" ADD "source_status" text`);
}
};
4 changes: 2 additions & 2 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,13 @@ type Project @entity {
url: String
"Image of the project"
image: String
"Project status at the source. e.g. Keeped, Removed, Missing in rf4"
sourceStatus: String
"project data is imported from a source or not"
imported: Boolean! @index
lastUpdatedTimestamp: DateTime!
attests: [ProjectAttestation!]! @derivedFrom(field: "project")
attestedOrganisations: [OrganisationProject!]! @derivedFrom(field: "project")
"Rounds in which the project is included"
rfRounds: [Int!]
}

type OrganisationProject @entity {
Expand Down
14 changes: 9 additions & 5 deletions src/controllers/projectVerificationAttestation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,15 @@ export const handleProjectAttestation = async (

ctx.log.debug(`Processing project attestation with uid: ${uid}`);

const project = await getProject(
ctx,
projectVerificationAttestation.projectSource,
projectVerificationAttestation.projectId
);
let projectId = projectVerificationAttestation.projectId;
let projectSource = projectVerificationAttestation.projectSource;

if (projectVerificationAttestation.projectSource === "rf4") {
projectId = projectVerificationAttestation.projectId.replace("rf4-", "rf-");
projectSource = "rf";
}

const project = await getProject(ctx, projectSource, projectId);

// Delete the previous attestation
await removeDuplicateProjectAttestations(
Expand Down
12 changes: 7 additions & 5 deletions src/features/import-projects/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const updateOrCreateProject = async (
descriptionHtmlField,
urlField,
imageField,
sourceStatusField,
rfRoundField,
} = sourConfig;

const projectId = project[idField].toLowerCase();
Expand All @@ -42,15 +42,15 @@ export const updateOrCreateProject = async (
const url = project[urlField];
const image = project[imageField];
const descriptionHtml = descriptionHtmlField && project[descriptionHtmlField];
const sourceStatus = sourceStatusField && project[sourceStatusField];
const rfRound = rfRoundField && project[rfRoundField];

if (existingProject) {
const isUpdated =
existingProject.title !== title ||
existingProject.description !== description ||
existingProject.url !== url ||
existingProject.image !== image ||
existingProject.sourceStatus !== sourceStatus ||
(rfRound && !existingProject.rfRounds?.some((rfr) => rfr === rfRound)) ||
existingProject.descriptionHtml !== descriptionHtml ||
(!existingProject.descriptionSummary && description);

Expand All @@ -59,6 +59,8 @@ export const updateOrCreateProject = async (
);

if (isUpdated) {
const rfRounds = new Set(existingProject.rfRounds || []);
rfRound && rfRounds.add(rfRound);
const updatedProject = new Project({
...existingProject,
title,
Expand All @@ -67,8 +69,8 @@ export const updateOrCreateProject = async (
url,
descriptionHtml,
descriptionSummary,
sourceStatus,
lastUpdatedTimestamp: new Date(),
rfRounds: Array.from(rfRounds),
imported: true,
});

Expand Down Expand Up @@ -97,7 +99,7 @@ export const updateOrCreateProject = async (
descriptionSummary,
projectId,
source,
sourceStatus,
rfRounds: rfRound ? [rfRound] : [],
totalVouches: 0,
totalFlags: 0,
totalAttests: 0,
Expand Down
6 changes: 4 additions & 2 deletions src/features/import-projects/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import { fetchAndProcessGivethProjects } from "./giveth/index";
import { fetchAndProcessRpgf3Projects } from "./rpgf";
import { fetchAndProcessGitcoinProjects } from "./gitcoin";
import { fetchAndProcessRf4Projects } from "./rf4";
import { fetchRFProjectsByRound } from "./rf";

export const task = async () => {
console.log("Importing Projects", new Date());
fetchAndProcessGivethProjects();
// fetchAndProcessRpgf3Projects();
fetchAndProcessGitcoinProjects();
fetchAndProcessRf4Projects();
// fetchAndProcessRpgf3Projects();
await fetchRFProjectsByRound(4);
await fetchRFProjectsByRound(5);
};

export const importProjects = async () => {
Expand Down
14 changes: 14 additions & 0 deletions src/features/import-projects/rf/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { SourceConfig } from "../types";

export const RF_API_URL =
process.env.RF4_API_URL || "https://vote.optimism.io/api/v1";

export const rfSourceConfig: SourceConfig = {
source: "rf",
idField: "id",
titleField: "name",
descriptionField: "description",
imageField: "projectCoverImageUrl",
urlField: "url",
rfRoundField: "rfRound",
};
26 changes: 26 additions & 0 deletions src/features/import-projects/rf/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { updateOrCreateProject } from "../helpers";
import { rfSourceConfig } from "./constants";
import { RfProjectInfo } from "./type";

export const generateRfUrl = (project: RfProjectInfo) => {
return `/project/${project.id}`;
};

const processProject = (project: RfProjectInfo, round: number) => {
const projectData = {
...project,
url: generateRfUrl(project),
rfRound: round,
};
return projectData;
};

export const saveBatchProjects = async (
projects: RfProjectInfo[],
round: number
) => {
for (const _project of projects) {
const project = processProject(_project, round);
await updateOrCreateProject(project, rfSourceConfig);
}
};
42 changes: 42 additions & 0 deletions src/features/import-projects/rf/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { RF_API_URL } from "./constants";
import { saveBatchProjects } from "./helpers";
import { RfApiResponse, RfProjectInfo } from "./type";

export const fetchRFProjectsByRound = async (round: number) => {
let offset = 0;
const limit = 10;
let hasNext = true;

try {
while (hasNext) {
const response = await fetch(
`${RF_API_URL}/retrofunding/rounds/${round}/projects?limit=${limit}&offset=${offset}`,
{
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.AGORA_API_KEY}`,
},
}
);

if (!response.ok) {
throw new Error(
`HTTP error! status: ${response.status} for round: ${round} at offset: ${offset}`
);
}

const res: RfApiResponse = await response.json();

await saveBatchProjects(res.data, round);

hasNext = res.meta.has_next;
offset = res.meta.next_offset;
}
} catch (error) {
console.error(
`Error fetching projects for round: ${round} at offset: ${offset}`,
error
);
}
};
22 changes: 22 additions & 0 deletions src/features/import-projects/rf/type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export interface RfProjectInfo {
id: string;
category: string;
organization: string | null;
name: string;
description: string;
profileAvatarUrl: string;
projectCoverImageUrl: string;
team: string[];
github: string[];
packages: string[];
links: string[];
}

export interface RfApiResponse {
meta: {
has_next: boolean;
total_returned: number;
next_offset: number;
};
data: RfProjectInfo[];
}
14 changes: 0 additions & 14 deletions src/features/import-projects/rf4/constants.ts

This file was deleted.

6 changes: 0 additions & 6 deletions src/features/import-projects/rf4/helpers.ts

This file was deleted.

22 changes: 0 additions & 22 deletions src/features/import-projects/rf4/index.ts

This file was deleted.

19 changes: 0 additions & 19 deletions src/features/import-projects/rf4/service.ts

This file was deleted.

16 changes: 0 additions & 16 deletions src/features/import-projects/rf4/type.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/features/import-projects/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ export interface SourceConfig {
descriptionHtmlField?: string;
urlField: string;
imageField: string;
sourceStatusField?: string;
rfRoundField?: string;
}
12 changes: 6 additions & 6 deletions src/model/generated/project.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,6 @@ export class Project {
@Column_("text", {nullable: true})
image!: string | undefined | null

/**
* Project status at the source. e.g. Keeped, Removed, Missing in rf4
*/
@Column_("text", {nullable: true})
sourceStatus!: string | undefined | null

/**
* project data is imported from a source or not
*/
Expand All @@ -103,4 +97,10 @@ export class Project {

@OneToMany_(() => OrganisationProject, e => e.project)
attestedOrganisations!: OrganisationProject[]

/**
* Rounds in which the project is included
*/
@Column_("int4", {array: true, nullable: true})
rfRounds!: (number)[] | undefined | null
}

0 comments on commit 56d036b

Please sign in to comment.