Skip to content

Commit

Permalink
Merge pull request #111 from Giveth/feat/handle-attestors-with-no-org…
Browse files Browse the repository at this point in the history
…anization

Feat/handle attestors with no organization
  • Loading branch information
MohammadPCh committed Sep 2, 2024
2 parents 968cb33 + a64d441 commit cdd94bb
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 13 deletions.
28 changes: 28 additions & 0 deletions db/migrations/1735226891776-AddNo Affiliation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const ethers = require("ethers");
const easSdk = require("@ethereum-attestation-service/eas-sdk");

const ZERO_UID = easSdk.ZERO_BYTES32;
module.exports = class AddNoAffiliation1735226891776 {
name = "AddNoAffiliation1735226891776";

async up(db) {
// Add organisation with name "No Affiliation"
await db.query(
`INSERT INTO "organisation" ("id", "name", "issuer", "color", "start_block")
VALUES (
'${ZERO_UID}',
'No Affiliation',
'${ethers.ZeroAddress}',
'#0049b7',
null
)`
);
}

async down(db) {
// Remove organisation with name "No Affiliation"
await db.query(
`DELETE FROM "organisation" WHERE "id" = '${ZERO_UID}'`
);
}
};
4 changes: 3 additions & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ZERO_BYTES32 } from "@ethereum-attestation-service/eas-sdk";
import { assertNotNull } from "@subsquid/evm-processor";
import { map } from "zod";

const SQUID_NETWORK = process.env.SQUID_NETWORK || "eth-sepolia";

Expand Down Expand Up @@ -39,3 +39,5 @@ export const DESCRIPTION_SUMMARY_LENGTH = Number(
);

export const AGORA_API_KEY = process.env.AGORA_API_KEY;

export const ZERO_UID = ZERO_BYTES32;
19 changes: 10 additions & 9 deletions src/controllers/projectVerificationAttestation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {
} from "./utils/easHelper";
import { AttestorOrganisation, ProjectAttestation } from "../model";
import {
getAttestor,
getOrCreateAttestorOrganisation,
getProject,
updateProjectAttestationCounts,
} from "./utils/modelHelper";
Expand All @@ -30,15 +32,14 @@ export const handleProjectAttestation = async (
schemaUid
);

const attestorOrganisation = await ctx.store.get(AttestorOrganisation, {
where: {
id: refUID.toLowerCase(),
},
relations: {
organisation: true,
attestor: true,
},
});
const attestor = await getAttestor(ctx, issuer);

const attestorOrganisation = await getOrCreateAttestorOrganisation(
ctx,
attestor,
refUID,
new Date(log.block.timestamp)
);

if (!attestorOrganisation) {
ctx.log.debug(
Expand Down
51 changes: 51 additions & 0 deletions src/controllers/utils/modelHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import { DataHandlerContext } from "@subsquid/evm-processor";
import { Store } from "@subsquid/typeorm-store";
import {
Attestor,
AttestorOrganisation,
Organisation,
OrganisationProject,
Project,
} from "../../model";
import { getEntityMangerByContext } from "./databaseHelper";
import { ProjectStats } from "./types";
import { ZERO_UID } from "../../constants";

export const upsertOrganisatoinProject = async (
ctx: DataHandlerContext<Store>,
Expand Down Expand Up @@ -182,3 +184,52 @@ export const getProjectStats = async (

return ProjectStats.parse(result[0]);
};

export const getOrCreateAttestorOrganisation = async (
ctx: DataHandlerContext<Store>,
attestor: Attestor,
refUID?: string,
attestTimestamp?: Date
): Promise<AttestorOrganisation | undefined> => {
// Check if refUID is valid and not a placeholder for an empty reference
if (refUID && refUID !== ZERO_UID) {
// Attempt to find existing AttestorOrganisation
const attestorOrganisation = await ctx.store.get(AttestorOrganisation, {
where: { id: refUID.toLowerCase() },
relations: { organisation: true, attestor: true },
});

if (attestorOrganisation) {
ctx.log.debug(
`Found existing attestorOrganisation: ${attestorOrganisation}`
);
return attestorOrganisation;
}
}

// Attempt to retrieve default organisation
let organisation = await ctx.store.get(Organisation, ZERO_UID);

if (!organisation) {
ctx.log.error("No Affiliation organisation not found");
return undefined;
}

// Ensure timestamp is set
const timestamp = attestTimestamp || new Date();

// Generate unique key
const key = `NO_AFFILIATION${attestor.id}`;

const newAttestorOrganisation = new AttestorOrganisation({
id: key,
attestor,
organisation,
attestTimestamp: timestamp,
});

await ctx.store.upsert(newAttestorOrganisation);
ctx.log.debug(`Created new attestorOrganisation: ${newAttestorOrganisation}`);

return newAttestorOrganisation;
};
2 changes: 1 addition & 1 deletion src/controllers/utils/types.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { orgCountTuplesTypes } from "./types";

describe.only("parse database query", () => {
describe("parse database query", () => {
it("should parse project stats query", () => {
const raw = `{"(0x2e22df9a11e06c306ed8f64ca45ceae02efcf8a443371395a78371bc4fb6f722,1)","(0xf63f2a7159ee674aa6fce42196a8bb0605eafcf20c19e91a7eafba8d39fa0404,1)"}`;

Expand Down
27 changes: 25 additions & 2 deletions src/test/store.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import { describe, expect, test, afterAll } from "@jest/globals";
import { closeConnection, getTestCtx } from "./utils";
import { closeConnection, getTestCtx, getTestEntityManager } from "./utils";
import { Organisation } from "../model";

describe("simple storage", () => {
beforeAll(async () => {
const em = await getTestEntityManager();
await em.getRepository(Organisation).delete({});
});
afterAll(async () => {
await closeConnection();
});

test("sample authorized attest", async () => {
test("should save sample authorized attest", async () => {
const ctx = await getTestCtx();
const organization = new Organisation({
id: "schemaUid",
Expand All @@ -24,4 +28,23 @@ describe("simple storage", () => {
expect(fetchOrganization).toBeDefined();
expect(fetchOrganization?.name).toBe("name");
});

test("should not fail on upserting the same entity", async () => {
const ctx = await getTestCtx();
const organization = new Organisation({
id: "schemaUid",
name: "name",
issuer: "issuer",
});

await ctx.store.upsert(organization);
await ctx.store.upsert(organization);

const fetchOrganization = await ctx.store.findOneBy(Organisation, {
name: "name",
});

expect(fetchOrganization).toBeDefined();
expect(fetchOrganization?.name).toBe("name");
});
});

0 comments on commit cdd94bb

Please sign in to comment.