Skip to content

Commit

Permalink
Load Programs from Indexer (#2946)
Browse files Browse the repository at this point in the history
* load programs

* fix: tests

* ad temporary message to create program

* ad temporary message to create program
  • Loading branch information
boudra authored Feb 16, 2024
1 parent 7b303a3 commit 7f2292b
Show file tree
Hide file tree
Showing 8 changed files with 170 additions and 151 deletions.
66 changes: 44 additions & 22 deletions packages/data-layer/src/data-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {
Round,
RoundOverview,
SearchBasedProjectCategory,
Tags,
TimestampVariables,
V2RoundWithRoles,
v2Project,
Expand All @@ -38,6 +37,7 @@ import {
getProgramByUserAndTag,
getRoundByIdAndChainId,
getRoundsByProgramIdAndUserAddress,
getProgramByIdAndUser,
} from "./queries";
import { Address } from "viem";

Expand Down Expand Up @@ -125,7 +125,7 @@ export class DataLayer {
* @example
* Here is an example:
* ```
* const program = await dataLayer.getProgramByUser({
* const program = await dataLayer.getProgramsByUser({
* address: "0x1234",
* chainId: 1,
* alloVersion: "allo-v1",
Expand All @@ -145,56 +145,78 @@ export class DataLayer {
address: string;
chainId: number;
alloVersion: AlloVersion;
}): Promise<{ programs: Program[] } | null> {
const filterByTag = alloVersion === "allo-v1" ? "program" : "allo-v2";
}): Promise<{ programs: Program[] }> {
const requestVariables = {
alloVersion,
address,
chainId,
filterByTag,
};

let programs: Program[] = [];

if (alloVersion === "allo-v1") {
let response: { projects: Program[] } = { projects: [] };

response = await request(
const response: { projects: Program[] } = await request(
this.gsIndexerEndpoint,
getProgramByUserAndTag,
requestVariables,
{ ...requestVariables, filterByTag: "program" },
);

programs = response.projects;
} else if (alloVersion === "allo-v2") {
let response: { projects: v2Project[] } = { projects: [] };

response = await request(
const response: { projects: v2Project[] } = await request(
this.gsIndexerEndpoint,
getProgramByUserAndTag,
requestVariables,
{ ...requestVariables, filterByTag: "allo-v2" },
);

const projects = response.projects;

programs = projects.map((project) => {
programs = response.projects.map((project) => {
return {
id: project.id,
chainId: project.chainId,
...project,
metadata: {
name: project.metadata?.title,
},
tags: project.tags as Tags[],
roles: project.roles,
};
});
}

if (!programs) return null;

return { programs };
}

async getProgramByIdAndUser({
userAddress,
programId,
chainId,
}: {
userAddress: string;
programId: string;
chainId: number;
}): Promise<{ program: Program | null }> {
const response: { projects: (Program | v2Project)[] } = await request(
this.gsIndexerEndpoint,
getProgramByIdAndUser,
{ programId, chainId, userAddress },
);

if (response.projects.length === 0) {
return { program: null };
}

const projectOrProgram = response.projects[0];

if ("name" in projectOrProgram.metadata) {
return { program: projectOrProgram as Program };
}

return {
program: {
...projectOrProgram,
metadata: {
name: projectOrProgram.metadata?.title,
},
},
};
}

/**
* Allo v1 & v2 builder queries
*/
Expand Down
29 changes: 11 additions & 18 deletions packages/data-layer/src/data.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,23 +107,6 @@ export type ProjectRole = {
projectId: string;
};

export type Tags = "allo-v1" | "program update";

/**
* The program type for v1
**/

export type Program = {
id: string;
chainId: number;
metadata: {
name: string;
};
metadataCid?: MetadataPointer;
tags: Tags[];
roles: AddressAndRole[];
};

/**
* The project type for v2
*
Expand Down Expand Up @@ -185,7 +168,7 @@ export type v2Project = {
*
* The tags are used to filter the projects based on the version of Allo.
*/
tags: [string];
tags: ("allo-v1" | "allo-v2" | "program")[];
/**
* The block the project was created at
*/
Expand All @@ -199,6 +182,16 @@ export type v2Project = {
anchorAddress?: string;
};

/**
* The program type for v1
**/

export type Program = Omit<v2Project, "metadata"> & {
metadata: {
name: string;
};
};

/**
* The project application type for v2
*
Expand Down
11 changes: 5 additions & 6 deletions packages/data-layer/src/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const getProgramByUserAndTag = gql`
filter: {
tags: { contains: [$filterByTag] }
roles: { some: { address: { equalTo: $address } } }
and: { chainId: { equalTo: $chainId } }
chainId: { equalTo: $chainId }
}
) {
id
Expand All @@ -39,14 +39,13 @@ export const getProgramByUserAndTag = gql`
*
* @returns The programs
*/
export const getProgramById = gql`
query ($alloVersion: [String!]!, $programId: String!, $chainId: Int!) {
export const getProgramByIdAndUser = gql`
query ($userAddress: String!, $programId: String!, $chainId: Int!) {
projects(
filter: {
tags: { equalTo: $alloVersion }
tags: { contains: "program" }
id: { equalTo: $programId }
and: { chainId: { equalTo: $chainId } }
roles: { some: { address: { equalTo: $userAddress } } }
chainId: { equalTo: $chainId }
}
) {
id
Expand Down
21 changes: 18 additions & 3 deletions packages/round-manager/src/context/program/ReadProgramContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ const fetchProgramsByAddress = async (

const fetchProgramsById = async (
dispatch: Dispatch,
address: string,
programId: string,
dataLayer: DataLayer,
walletProvider: Web3Provider
) => {
datadogLogs.logger.info(`fetchProgramsById: programId - ${programId}`);
Expand All @@ -86,7 +88,12 @@ const fetchProgramsById = async (
payload: ProgressStatus.IN_PROGRESS,
});
try {
const program = await getProgramById(programId, walletProvider);
const program = await getProgramById(
address,
programId,
walletProvider,
dataLayer
);
dispatch({ type: ActionType.SET_PROGRAMS, payload: [program] });
dispatch({
type: ActionType.SET_FETCH_PROGRAM_STATUS,
Expand Down Expand Up @@ -173,19 +180,27 @@ export const useProgramById = (
getProgramByIdError?: Error;
} => {
const context = useContext(ReadProgramContext);
const dataLayer = useDataLayer();
if (context === undefined) {
throw new Error("useProgramById must be used within a ProgramProvider");
}

const { provider: walletProvider } = useWallet();
const { address, provider: walletProvider } = useWallet();

useEffect(() => {
if (id) {
const existingProgram = context.state.programs.find(
(program) => program.id === id
);

if (!existingProgram) {
fetchProgramsById(context.dispatch, id, walletProvider);
fetchProgramsById(
context.dispatch,
address.toLowerCase(),
id,
dataLayer,
walletProvider
);
}
}
}, [id, walletProvider]); // eslint-disable-line react-hooks/exhaustive-deps
Expand Down
64 changes: 20 additions & 44 deletions packages/round-manager/src/features/api/__tests__/program.test.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,9 @@
import { getProgramById, listPrograms } from "../program";
import { Program } from "../types";
import { makeProgramData } from "../../../test-utils";
import { fetchFromIPFS, CHAINS } from "../utils";
import { graphql_fetch } from "common";
import { CHAINS } from "../utils";
import { ChainId } from "common";

jest.mock("../utils", () => ({
...jest.requireActual("../utils"),
fetchFromIPFS: jest.fn(),
}));

jest.mock("common", () => ({
...jest.requireActual("common"),
graphql_fetch: jest.fn(),
}));
import { zeroAddress } from "viem";

jest.mock("data-layer", () => ({
DataLayer: jest.fn().mockImplementation(() => ({
Expand Down Expand Up @@ -63,42 +53,28 @@ describe("getProgramById", () => {
chain: CHAINS[ChainId.MAINNET],
});
const programId = expectedProgram.id;
(graphql_fetch as jest.Mock).mockResolvedValue({
data: {
programs: [
{

const actualProgram = await getProgramById(
zeroAddress,
programId as string,
{
getNetwork: async () =>
// @ts-expect-error Test file
Promise.resolve({ chainId: ChainId.MAINNET }),
},
{
getProgramByIdAndUser: jest.fn().mockResolvedValue({
program: {
id: expectedProgram.id,
roles: [
{
accounts: [
{
address: expectedProgram.operatorWallets[0],
},
],
},
],
metaPtr: {
protocol: 1,
pointer:
"uwijkhxkpkdgkszraqzqvhssqulctxzvntxwconznfkelzbtgtqysrzkehl",
roles: [{ address: expectedProgram.operatorWallets[0] }],
metadata: {
name: expectedProgram.metadata?.name,
},
},
],
},
});
(fetchFromIPFS as jest.Mock).mockResolvedValue({
name: expectedProgram.metadata?.name,
});

const actualProgram = await getProgramById(programId as string, {
getNetwork: async () =>
// @ts-expect-error Test file
Promise.resolve({ chainId: ChainId.MAINNET }),
});
}),
}
);

expect(actualProgram).toEqual(expectedProgram);
const graphqlFetchCall = (graphql_fetch as jest.Mock).mock.calls[0];
const actualQuery = graphqlFetchCall[0];
expect(actualQuery).toContain("id: $programId");
});
});
Loading

0 comments on commit 7f2292b

Please sign in to comment.