{displayHeaders[displayType]}
- {!isLoading &&
- applications.length > 0 &&
- applications.map((app) => (
-
+ {userApplications.length > 0 ? (
+ userApplications.map((app) => (
+
- ))}
- {!isLoading && applications.length === 0 && (
+ ))
+ ) : (
- No Data
-
- )}
- {isLoading && (
-
- Loading your information, please stand by...
-
+ No Data
)}
+
);
@@ -142,8 +141,7 @@ export default function Rounds() {
{renderStatGroup(
displayType as RoundDisplayType,
// when props.applications is undefined, we are still loading, when it's not undefined, we check if any of the rounds are still loading
- props.applications?.some((a) => a.isLoading) ?? true,
- props.applications?.flatMap(({ app, category }) =>
+ props.mappedApplications?.flatMap(({ app, category }) =>
category === displayType ? [app] : []
) ?? []
)}
diff --git a/packages/builder/src/components/grants/rounds/__tests__/Rounds.test.tsx b/packages/builder/src/components/grants/rounds/__tests__/Rounds.test.tsx
index e80c3d2062..33b50b5163 100644
--- a/packages/builder/src/components/grants/rounds/__tests__/Rounds.test.tsx
+++ b/packages/builder/src/components/grants/rounds/__tests__/Rounds.test.tsx
@@ -1,5 +1,6 @@
import "@testing-library/jest-dom";
import { act, cleanup, screen } from "@testing-library/react";
+import { ProjectApplication } from "data-layer";
import { web3ChainIDLoaded } from "../../../../actions/web3";
import setupStore from "../../../../store";
import {
@@ -21,60 +22,60 @@ jest.mock("react-router-dom", () => ({
}));
const buildActiveRound = (roundData: any) => {
- const now = Date.now() / 1000;
+ const now = Date.now();
- const applicationsStartTime = now - 20000;
- const applicationsEndTime = now - 10000;
+ const applicationsStartTime = new Date(now - 2000000);
+ const applicationsEndTime = new Date(now - 1000000);
const roundStartTime = applicationsEndTime;
- const roundEndTime = now + 20000;
+ const roundEndTime = new Date(now + 20000000);
const round = buildRound({
address: addressFrom(1),
applicationsStartTime,
applicationsEndTime,
- roundStartTime,
- roundEndTime,
+ donationsStartTime: roundStartTime,
+ donationsEndTime: roundEndTime,
...roundData,
});
return round;
};
const buildPastRound = (roundData: any) => {
- const now = Date.now() / 1000;
+ const now = Date.now();
- const applicationsStartTime = now - 2000;
- const applicationsEndTime = now - 1000;
+ const applicationsStartTime = new Date(now - 2000000);
+ const applicationsEndTime = new Date(now - 1000000);
const roundStartTime = applicationsEndTime;
- const roundEndTime = now - 900;
+ const roundEndTime = new Date(now - 900000);
const round = buildRound({
address: addressFrom(1),
applicationsStartTime,
applicationsEndTime,
- roundStartTime,
- roundEndTime,
+ donationsStartTime: roundStartTime,
+ donationsEndTime: roundEndTime,
...roundData,
});
return round;
};
const buildCurrentApplication = (roundData: any) => {
- const now = Date.now() / 1000;
+ const now = Date.now();
- const applicationsStartTime = now - 2000;
- const applicationsEndTime = now + 2000;
+ const applicationsStartTime = new Date(now - 2000);
+ const applicationsEndTime = new Date(now + 2000);
const roundStartTime = applicationsEndTime;
- const roundEndTime = now + 3000;
+ const roundEndTime = new Date(now + 3000);
const round = buildRound({
address: addressFrom(1),
applicationsStartTime,
applicationsEndTime,
- roundStartTime,
- roundEndTime,
+ donationsStartTime: roundStartTime,
+ donationsEndTime: roundEndTime,
...roundData,
});
return round;
@@ -85,19 +86,6 @@ describe("
", () => {
cleanup();
});
- describe("When the data is loading", () => {
- test("should show loading", async () => {
- await act(async () => {
- renderWrapped(
, setupStore());
- });
-
- expect(
- screen.queryAllByText("Loading your information, please stand by...")
- .length
- ).toBeGreaterThan(0);
- });
- });
-
describe("when the data is loaded", () => {
test("should show the active rounds, badges and buttons", async () => {
const store = setupStore();
@@ -120,13 +108,21 @@ describe("
", () => {
address: addressFrom(2),
round: round2,
});
- const applications = [];
+ const applications: ProjectApplication[] = [];
applications.push(
- buildProjectApplication({ roundID: addressFrom(1), status: "APPROVED" })
+ buildProjectApplication({
+ roundId: addressFrom(1),
+ status: "APPROVED",
+ round: round1,
+ })
// set the status directly here, saves some pain
);
applications.push(
- buildProjectApplication({ roundID: addressFrom(2), status: "REJECTED" })
+ buildProjectApplication({
+ roundId: addressFrom(2),
+ status: "REJECTED",
+ round: round2,
+ })
);
store.dispatch({
type: "PROJECT_APPLICATIONS_LOADED",
@@ -135,7 +131,7 @@ describe("
", () => {
});
await act(async () => {
- renderWrapped(
, store);
+ renderWrapped(
, store);
});
expect(screen.getByText("Active Rounds")).toBeInTheDocument();
@@ -163,13 +159,21 @@ describe("
", () => {
address: addressFrom(2),
round: round2,
});
- const applications = [];
+ const applications: ProjectApplication[] = [];
applications.push(
- buildProjectApplication({ roundID: addressFrom(1), status: "APPROVED" })
+ buildProjectApplication({
+ roundId: addressFrom(1),
+ status: "APPROVED",
+ round: round1,
+ })
// set the status directly here, saves some pain
);
applications.push(
- buildProjectApplication({ roundID: addressFrom(2), status: "REJECTED" })
+ buildProjectApplication({
+ roundId: addressFrom(2),
+ status: "REJECTED",
+ round: round2,
+ })
);
store.dispatch({
type: "PROJECT_APPLICATIONS_LOADED",
@@ -178,7 +182,7 @@ describe("
", () => {
});
await act(async () => {
- renderWrapped(
, store);
+ renderWrapped(
, store);
});
expect(screen.getByText("Current Applications")).toBeInTheDocument();
@@ -205,13 +209,21 @@ describe("
", () => {
address: addressFrom(2),
round: round2,
});
- const applications = [];
+ const applications: ProjectApplication[] = [];
applications.push(
- buildProjectApplication({ roundID: addressFrom(1), status: "APPROVED" })
+ buildProjectApplication({
+ roundId: addressFrom(1),
+ status: "APPROVED",
+ round: round1,
+ })
// set the status directly here, saves some pain
);
applications.push(
- buildProjectApplication({ roundID: addressFrom(2), status: "REJECTED" })
+ buildProjectApplication({
+ roundId: addressFrom(2),
+ status: "REJECTED",
+ round: round2,
+ })
);
store.dispatch({
type: "PROJECT_APPLICATIONS_LOADED",
@@ -220,7 +232,7 @@ describe("
", () => {
});
await act(async () => {
- renderWrapped(
, store);
+ renderWrapped(
, store);
});
expect(screen.getByText("Past Rounds")).toBeInTheDocument();
diff --git a/packages/builder/src/components/grants/stats/Stats.tsx b/packages/builder/src/components/grants/stats/Stats.tsx
index 9c6a99c756..1927c45383 100644
--- a/packages/builder/src/components/grants/stats/Stats.tsx
+++ b/packages/builder/src/components/grants/stats/Stats.tsx
@@ -1,5 +1,5 @@
import { Spinner } from "@chakra-ui/react";
-import { ChainId, RoundPayoutType, ROUND_PAYOUT_MERKLE } from "common";
+import { ChainId, ROUND_PAYOUT_MERKLE, RoundPayoutType } from "common";
import { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { useParams } from "react-router-dom";
@@ -24,11 +24,14 @@ export default function RoundStats() {
});
const props = useSelector((state: RootState) => {
const stats: ProjectStats[] = state.projects?.stats[params.id!];
+ const allApplications = state.projects.applications
+ ? state.projects.applications[params.id!]
+ : [];
return {
projectID: params.id!,
stats,
- projectApplications: state.projects?.applications[params.id!] ?? [],
+ projectApplications: allApplications,
rounds: state.rounds,
};
});
@@ -48,10 +51,10 @@ export default function RoundStats() {
}> = [];
applications.forEach((app) => {
const roundType =
- props.rounds[app.roundID]?.round?.payoutStrategy || "";
+ props.rounds[app.roundId]?.round?.payoutStrategy || "";
if (roundType !== "" && roundType === ROUND_PAYOUT_MERKLE) {
rounds.push({
- roundId: app.roundID,
+ roundId: app.roundId,
chainId: app.chainId,
roundType,
});
diff --git a/packages/builder/src/components/providers/Github.tsx b/packages/builder/src/components/providers/Github.tsx
index 4457f33eee..1d562821c7 100644
--- a/packages/builder/src/components/providers/Github.tsx
+++ b/packages/builder/src/components/providers/Github.tsx
@@ -56,15 +56,6 @@ export default function Github({
props.formMetadata.projectGithub
);
- // console.log(
- // "GITHUB",
- // "credential",
- // props.verifiableCredential,
- // props.formMetadata.projectTwitter,
- // "isValid: ",
- // validCredential
- // );
-
async function handleVerify(): Promise
{
// Fetch data from external API
try {
diff --git a/packages/builder/src/components/providers/Twitter.tsx b/packages/builder/src/components/providers/Twitter.tsx
index 6ac0e5aa9e..a49e70fc4e 100644
--- a/packages/builder/src/components/providers/Twitter.tsx
+++ b/packages/builder/src/components/providers/Twitter.tsx
@@ -45,15 +45,6 @@ export default function Twitter({
props.formMetadata.projectTwitter
);
- // console.log(
- // "TWITTER",
- // "credential",
- // props.verifiableCredential,
- // props.formMetadata.projectTwitter,
- // "isValid: ",
- // validCredential
- // );
-
const { signer } = global;
// Fetch Twitter OAuth2 url from the IAM procedure
diff --git a/packages/builder/src/components/rounds/Apply.tsx b/packages/builder/src/components/rounds/Apply.tsx
index 2cf8701751..0765508119 100644
--- a/packages/builder/src/components/rounds/Apply.tsx
+++ b/packages/builder/src/components/rounds/Apply.tsx
@@ -1,6 +1,8 @@
import { useEffect, useState } from "react";
import { shallowEqual, useDispatch, useSelector } from "react-redux";
import { useNavigate, useParams } from "react-router-dom";
+import { RoundApplicationAnswers } from "data-layer/dist/roundApplication.types";
+import { useAllo } from "common";
import {
resetApplication,
submitApplication,
@@ -16,7 +18,6 @@ import { Status as RoundStatus } from "../../reducers/rounds";
import { grantsPath, projectPath, roundPath } from "../../routes";
import colors from "../../styles/colors";
import { Round } from "../../types";
-import { RoundApplicationAnswers } from "../../types/roundApplication";
import { applicationSteps } from "../../utils/steps";
import {
ROUND_PAYOUT_DIRECT,
@@ -38,6 +39,7 @@ function Apply() {
const params = useParams();
const dispatch = useDispatch();
const navigate = useNavigate();
+ const allo = useAllo();
const [modalOpen, toggleModal] = useState(false);
const [roundData, setRoundData] = useState();
@@ -249,7 +251,8 @@ function Apply() {
Application Period:
{formatDate(props.round.applicationsStartTime * 1000)} -{" "}
- {isInfinite(props.round.applicationsEndTime)
+ {isInfinite(props.round.applicationsEndTime) ||
+ !props.round.applicationsEndTime
? "No End Date"
: formatDate(props.round.applicationsEndTime * 1000)}
@@ -258,7 +261,8 @@ function Apply() {
Round Dates:
{formatDate(props.round.roundStartTime * 1000)} -{" "}
- {isInfinite(props.round.applicationsEndTime)
+ {isInfinite(props.round.applicationsEndTime) ||
+ !props.round.applicationsEndTime
? "No End Date"
: formatDate(props.round.roundEndTime * 1000)}
@@ -289,7 +293,9 @@ function Apply() {
showErrorModal={props.showErrorModal || false}
round={props.round}
onSubmit={(answers: RoundApplicationAnswers) => {
- dispatch(submitApplication(props.round!.address, answers));
+ dispatch(
+ submitApplication(props.round!.address, answers, allo)
+ );
toggleStatusModal(true);
}}
/>
diff --git a/packages/builder/src/components/rounds/Show.tsx b/packages/builder/src/components/rounds/Show.tsx
index 615df83a77..20bb6519bb 100644
--- a/packages/builder/src/components/rounds/Show.tsx
+++ b/packages/builder/src/components/rounds/Show.tsx
@@ -136,7 +136,7 @@ function ShowRound() {
const web3ChainId = state.web3.chainID;
const roundChainId = Number(chainId);
- const now = Math.trunc(Date.now() / 1000);
+ const now = new Date().getTime() / 1000;
let applicationsHaveStarted = false;
let applicationsHaveEnded = false;
@@ -181,7 +181,8 @@ function ShowRound() {
roundData && (
<>
{formatTimeUTC(roundData.applicationsStartTime)} -{" "}
- {isInfinite(roundData.applicationsEndTime)
+ {isInfinite(roundData.applicationsEndTime) ||
+ !roundData.applicationsEndTime
? "No End Date"
: formatTimeUTC(roundData.applicationsEndTime)}
>
@@ -191,7 +192,7 @@ function ShowRound() {
roundData && (
<>
{formatTimeUTC(roundData.roundStartTime)} -{" "}
- {isInfinite(roundData.roundEndTime)
+ {isInfinite(roundData.roundEndTime) || !roundData.roundEndTime
? "No End Date"
: formatTimeUTC(roundData.roundEndTime)}
{}
@@ -223,7 +224,11 @@ function ShowRound() {
if (roundId !== undefined) {
dispatch(unloadRounds());
dispatch(
- loadRound(roundId, Number(props.roundChainId || props.web3ChainId))
+ loadRound(
+ roundId,
+ dataLayer,
+ Number(props.roundChainId || props.web3ChainId)
+ )
);
}
}, [dispatch, roundId]);
diff --git a/packages/builder/src/components/rounds/ViewApplication.tsx b/packages/builder/src/components/rounds/ViewApplication.tsx
index dbeb32d49f..e0aae7d715 100644
--- a/packages/builder/src/components/rounds/ViewApplication.tsx
+++ b/packages/builder/src/components/rounds/ViewApplication.tsx
@@ -1,24 +1,26 @@
+import { useDataLayer } from "data-layer";
+import { RoundApplicationAnswers } from "data-layer/dist/roundApplication.types";
import { useEffect } from "react";
import { shallowEqual, useDispatch, useSelector } from "react-redux";
import { useNavigate, useParams } from "react-router-dom";
+import { useAllo } from "common";
import {
fetchApplicationData,
submitApplication,
} from "../../actions/roundApplication";
import { loadRound, unloadRounds } from "../../actions/rounds";
import { RootState } from "../../reducers";
-import Button, { ButtonVariants } from "../base/Button";
import { Status as ApplicationStatus } from "../../reducers/roundApplication";
import { Status as RoundStatus } from "../../reducers/rounds";
import { grantsPath, projectPathByID } from "../../routes";
import colors from "../../styles/colors";
+import { isInfinite } from "../../utils/components";
+import { ROUND_PAYOUT_DIRECT } from "../../utils/utils";
import Form from "../application/Form";
+import Button, { ButtonVariants } from "../base/Button";
import ErrorModal from "../base/ErrorModal";
import LoadingSpinner from "../base/LoadingSpinner";
import Cross from "../icons/Cross";
-import { RoundApplicationAnswers } from "../../types/roundApplication";
-import { isInfinite } from "../../utils/components";
-import { ROUND_PAYOUT_DIRECT } from "../../utils/utils";
const formatDate = (unixTS: number) =>
new Date(unixTS).toLocaleDateString(undefined);
@@ -27,6 +29,9 @@ function ViewApplication() {
const params = useParams();
const navigate = useNavigate();
const dispatch = useDispatch();
+ const allo = useAllo();
+
+ const dataLayer = useDataLayer();
const { chainId, roundId, ipfsHash } = params;
@@ -49,11 +54,10 @@ function ViewApplication() {
const publishedApplicationMetadata = applicationState
? applicationState.metadataFromIpfs![ipfsHash!]
- : null;
+ : undefined;
const roundApplicationStatus =
- applicationState?.metadataFromIpfs![ipfsHash!].publishedApplicationData
- .status;
+ publishedApplicationMetadata?.status ?? "IN_REVIEW";
const web3ChainId = state.web3.chainID;
const roundChainId = Number(chainId);
@@ -80,9 +84,9 @@ function ViewApplication() {
}, shallowEqual);
useEffect(() => {
- if (roundId !== undefined) {
+ if (roundId !== undefined || !props.publishedApplicationMetadata) {
dispatch(unloadRounds());
- dispatch(loadRound(roundId, props.roundChainId));
+ dispatch(loadRound(roundId!, dataLayer, props.roundChainId));
}
}, [dispatch, roundId]);
@@ -120,7 +124,6 @@ function ViewApplication() {
}
const isDirectRound = props.round?.payoutStrategy === ROUND_PAYOUT_DIRECT;
-
const roundInReview = props.roundApplicationStatus === "IN_REVIEW";
const roundApproved = props.roundApplicationStatus === "APPROVED";
const hasProperStatus = roundInReview || roundApproved;
@@ -128,7 +131,7 @@ function ViewApplication() {
if (
props.roundState === undefined ||
props.round === undefined ||
- props.publishedApplicationMetadata === null
+ props.publishedApplicationMetadata === undefined
) {
return (
Application Period:
{formatDate(props.round.applicationsStartTime * 1000)} -{" "}
- {isInfinite(props.round.applicationsEndTime)
+ {isInfinite(props.round.applicationsEndTime) ||
+ !props.round.applicationsEndTime
? "No End Date"
: formatDate(props.round.applicationsEndTime * 1000)}
@@ -201,7 +205,8 @@ function ViewApplication() {
Round Dates:
{formatDate(props.round.roundStartTime * 1000)} -{" "}
- {isInfinite(props.round.applicationsEndTime)
+ {isInfinite(props.round.applicationsEndTime) ||
+ !props.round.applicationsEndTime
? "No End Date"
: formatDate(props.round.roundEndTime * 1000)}
@@ -235,7 +240,9 @@ function ViewApplication() {
showErrorModal={props.showErrorModal || false}
round={props.round}
onSubmit={(answers: RoundApplicationAnswers) => {
- dispatch(submitApplication(props.round!.address, answers));
+ dispatch(
+ submitApplication(props.round!.address, answers, allo)
+ );
}}
readOnly
/>
diff --git a/packages/builder/src/hooks/useValidateCredential.tsx b/packages/builder/src/hooks/useValidateCredential.tsx
index 55a5dd3e07..3680d5f7ec 100644
--- a/packages/builder/src/hooks/useValidateCredential.tsx
+++ b/packages/builder/src/hooks/useValidateCredential.tsx
@@ -26,14 +26,6 @@ export async function validateCredential(
const validIssuer = IAM_SERVER === credential.issuer;
- // console.log(
- // "validating",
- // credential,
- // validCredentialProvider,
- // validCredential,
- // validIssuer
- // );
-
return validCredentialProvider && validCredential && validIssuer;
}
diff --git a/packages/builder/src/index.tsx b/packages/builder/src/index.tsx
index 7e07e09df9..9083d1ff19 100644
--- a/packages/builder/src/index.tsx
+++ b/packages/builder/src/index.tsx
@@ -146,7 +146,4 @@ root.render(
);
-// If you want to start measuring performance in your app, pass a function
-// to log results (for example: reportWebVitals(console.log))
-// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
diff --git a/packages/builder/src/reducers/projects.ts b/packages/builder/src/reducers/projects.ts
index 77990b9ebe..05533b9417 100644
--- a/packages/builder/src/reducers/projects.ts
+++ b/packages/builder/src/reducers/projects.ts
@@ -1,7 +1,6 @@
-import { ChainId } from "common";
-import { ProjectEventsMap } from "data-layer";
+import { ProjectApplication, ProjectEventsMap } from "data-layer";
+
import {
- ProjectsActions,
PROJECTS_ERROR,
PROJECTS_LOADED,
PROJECTS_LOADING,
@@ -13,6 +12,7 @@ import {
PROJECT_OWNERS_LOADED,
PROJECT_STATS_LOADED,
PROJECT_STATS_LOADING,
+ ProjectsActions,
} from "../actions/projects";
export enum Status {
@@ -22,27 +22,7 @@ export enum Status {
Error,
}
-export type AppStatus =
- | "PENDING"
- | "APPROVED"
- | "REJECTED"
- | "APPEAL"
- | "FRAUD"
- | "RECEIVED";
-
-export type Application = {
- roundID: string;
- status: AppStatus;
- inReview: boolean;
- chainId: ChainId;
- metaPtr?: {
- protocol: string;
- pointer: string;
- };
-};
-
export type ProjectOwners = { [projectID: string]: string[] };
-
export interface ProjectsState {
status: Status;
loadingChains: number[];
@@ -50,8 +30,8 @@ export interface ProjectsState {
ids: string[];
events: ProjectEventsMap;
owners: ProjectOwners;
- applications: {
- [projectID: string]: Application[];
+ applications?: {
+ [projectID: string]: ProjectApplication[];
};
stats: {
[projectID: string]: ProjectStats[];
@@ -136,7 +116,7 @@ export const projectsReducer = (
case PROJECT_APPLICATIONS_LOADING: {
// Remove the project applications key
const { [action.projectID]: projectApplications, ...applications } =
- state.applications;
+ state.applications || {};
return {
...state,
@@ -156,9 +136,9 @@ export const projectsReducer = (
}
case PROJECT_APPLICATION_UPDATED: {
- const projectApplications = state.applications[action.projectID] || [];
+ const projectApplications = state.applications?.[action.projectID] || [];
const index = projectApplications.findIndex(
- (app: Application) => app.roundID === action.roundID
+ (app: ProjectApplication) => app.roundId === action.roundID
);
if (index < 0) {
diff --git a/packages/builder/src/types/index.ts b/packages/builder/src/types/index.ts
index bcaa2cec8a..84b7aa4be8 100644
--- a/packages/builder/src/types/index.ts
+++ b/packages/builder/src/types/index.ts
@@ -1,8 +1,8 @@
+import { ProjectApplication } from "data-layer";
import { VerifiableCredential } from "@gitcoinco/passport-sdk-types";
import { ChainId } from "common";
import { ReactNode } from "react";
-import { Application } from "../reducers/projects";
-import { RoundApplicationMetadata } from "./roundApplication";
+import { RoundApplicationMetadata } from "data-layer/dist/roundApplication.types";
export type Images = {
bannerImg?: Blob;
@@ -153,7 +153,7 @@ export enum RoundDisplayType {
}
export type ApplicationCardType = {
- application: Application;
+ application: ProjectApplication;
roundID: string;
chainId: ChainId;
};
@@ -235,9 +235,3 @@ export enum CredentialProvider {
Twitter = "ClearTextTwitter",
Github = "ClearTextGithubOrg",
}
-
-export type {
- ProjectRequirements,
- RoundApplicationMetadata,
- RoundApplicationQuestion,
-} from "./roundApplication";
diff --git a/packages/builder/src/utils/AlloWrapper.tsx b/packages/builder/src/utils/AlloWrapper.tsx
index 464c3e46ae..ea947847fc 100644
--- a/packages/builder/src/utils/AlloWrapper.tsx
+++ b/packages/builder/src/utils/AlloWrapper.tsx
@@ -3,13 +3,14 @@ import {
AlloProvider,
AlloV1,
AlloV2,
+ ChainId,
createEthersTransactionSender,
createPinataIpfsUploader,
createWaitForIndexerSyncTo,
} from "common";
-import { useEffect, useState } from "react";
-import { useNetwork, useProvider, useSigner } from "wagmi";
import { getConfig } from "common/src/config";
+import React, { useEffect, useState } from "react";
+import { useNetwork, useProvider, useSigner } from "wagmi";
import { addressesByChainID } from "../contracts/deployments";
function AlloWrapper({ children }: { children: JSX.Element | JSX.Element[] }) {
@@ -24,13 +25,16 @@ function AlloWrapper({ children }: { children: JSX.Element | JSX.Element[] }) {
if (!web3Provider || !signer || !chainID) {
setBackend(null);
} else {
- const addresses = addressesByChainID(chainID);
+ const addresses = addressesByChainID(chainID) ?? addressesByChainID(1);
+
+ const chainIdSupported = Object.values(ChainId).includes(chainID);
+
const config = getConfig();
let alloBackend: Allo;
if (config.allo.version === "allo-v2") {
alloBackend = new AlloV2({
- chainId: chainID,
+ chainId: chainIdSupported ? chainID : 1,
transactionSender: createEthersTransactionSender(
signer,
web3Provider
@@ -48,7 +52,7 @@ function AlloWrapper({ children }: { children: JSX.Element | JSX.Element[] }) {
setBackend(alloBackend);
} else {
alloBackend = new AlloV1({
- chainId: chainID,
+ chainId: chainIdSupported ? chainID : 1,
transactionSender: createEthersTransactionSender(
signer,
web3Provider
diff --git a/packages/builder/src/utils/RoundApplicationBuilder.ts b/packages/builder/src/utils/RoundApplicationBuilder.ts
index 2fd17c3b6d..54ecaff8c8 100644
--- a/packages/builder/src/utils/RoundApplicationBuilder.ts
+++ b/packages/builder/src/utils/RoundApplicationBuilder.ts
@@ -1,6 +1,9 @@
+import {
+ RoundApplicationAnswers,
+ RoundApplicationMetadata,
+} from "data-layer/dist/roundApplication.types";
import Lit from "../services/lit";
-import { RoundApplicationMetadata, Project, RoundApplication } from "../types";
-import { RoundApplicationAnswers } from "../types/roundApplication";
+import { Project, RoundApplication } from "../types";
export default class RoundApplicationBuilder {
enableEncryption: boolean;
diff --git a/packages/builder/src/utils/components.ts b/packages/builder/src/utils/components.ts
index e00908a5fa..e670c5f72c 100644
--- a/packages/builder/src/utils/components.ts
+++ b/packages/builder/src/utils/components.ts
@@ -1,7 +1,7 @@
import { getConfig } from "common/src/config";
-import { Metadata, Project } from "../types";
-import PinataClient from "../services/pinata";
import { DefaultProjectBanner, DefaultProjectLogo } from "../assets";
+import PinataClient from "../services/pinata";
+import { Metadata, Project } from "../types";
export enum ImgTypes {
bannerImg = "bannerImg",
@@ -52,5 +52,10 @@ export const formatTimeUTC = (ts: number) => {
return date.toUTCString().replace("GMT", "UTC");
};
+export const formatDateFromString = (ts: string) =>
+ new Date(ts).toLocaleDateString();
+
export const isInfinite = (number: Number) =>
- number === Number.MAX_SAFE_INTEGER;
+ number === Number.MAX_SAFE_INTEGER || !number;
+
+export const formatDateAsNumber = (ts: string) => Date.parse(ts) / 1000;
diff --git a/packages/builder/src/utils/roundApplication.ts b/packages/builder/src/utils/roundApplication.ts
index 5dde7f7771..7dce39c4f8 100644
--- a/packages/builder/src/utils/roundApplication.ts
+++ b/packages/builder/src/utils/roundApplication.ts
@@ -1,12 +1,9 @@
import { ChainId } from "common";
+import { RoundApplicationMetadata, RoundApplicationQuestion } from "data-layer";
import { ethers } from "ethers";
-import {
- RoundApplicationMetadata,
- RoundApplicationQuestion,
-} from "../types/roundApplication";
const generateUniqueRoundApplicationID = (
- projectChainId: ChainId | number,
+ projectChainId: ChainId,
projectNumber: string,
projectRegistryAddress: string
) =>
diff --git a/packages/builder/src/utils/test_utils.tsx b/packages/builder/src/utils/test_utils.tsx
index 54ec28c22f..b2ae723365 100644
--- a/packages/builder/src/utils/test_utils.tsx
+++ b/packages/builder/src/utils/test_utils.tsx
@@ -2,8 +2,13 @@ import { ChakraProvider } from "@chakra-ui/react";
import { VerifiableCredential } from "@gitcoinco/passport-sdk-types";
import { ReduxRouter } from "@lagunovsky/redux-react-router";
import { render } from "@testing-library/react";
-import { AlloProvider, AlloV2, createMockTransactionSender } from "common";
-import { DataLayer, DataLayerProvider } from "data-layer";
+import {
+ AlloProvider,
+ AlloV2,
+ RoundVisibilityType,
+ createMockTransactionSender,
+} from "common";
+import { DataLayer, DataLayerProvider, ProjectApplication } from "data-layer";
import { ethers } from "ethers";
import { Provider } from "react-redux";
import { zeroAddress } from "viem";
@@ -25,12 +30,14 @@ export const buildAlert = (attrs = {}): Alert => ({
...attrs,
});
+export const now = new Date().getTime() / 1000;
+
export const buildRound = (round: any): Round => ({
address: addressFrom(1),
- applicationsStartTime: 1663751953,
- applicationsEndTime: Date.now() / 1000 + 36000,
- roundStartTime: 1663751953,
- roundEndTime: Date.now() / 1000 + 36000,
+ applicationsStartTime: now,
+ applicationsEndTime: now + 3600,
+ roundStartTime: now + 3600,
+ roundEndTime: now + 7200,
token: "0x0000000000000000000000000000000000000000",
roundMetaPtr: {},
roundMetadata: {},
@@ -101,10 +108,36 @@ export const buildFormMetadata = (metadata: any): FormInputs => ({
...metadata,
});
-export const buildProjectApplication = (application: any): any => ({
+export const buildProjectApplication = (
+ application: any
+): ProjectApplication => ({
chainId: 5,
- roundID: addressFrom(1),
+ roundId: addressFrom(1),
status: "APPROVED",
+ inReview: false,
+ id: "1",
+ metadataCid: "0x1",
+ metadata: {},
+ round: {
+ applicationsStartTime: "0",
+ applicationsEndTime: "0",
+ donationsStartTime: "0",
+ donationsEndTime: "0",
+ roundMetadata: {
+ name: "Round 1",
+ roundType: "public" as RoundVisibilityType,
+ eligibility: {
+ description: "Eligibility description",
+ requirements: [{ requirement: "Requirement 1" }],
+ },
+ programContractAddress: "0x1",
+ support: {
+ info: "https://support.com",
+ type: "WEBSITE",
+ },
+ },
+ name: "Round 1",
+ },
...application,
});
diff --git a/packages/builder/src/utils/utils.ts b/packages/builder/src/utils/utils.ts
index 01b3861e80..da3cb0df6c 100644
--- a/packages/builder/src/utils/utils.ts
+++ b/packages/builder/src/utils/utils.ts
@@ -123,6 +123,7 @@ export const getProviderByChainId = (chainId: ChainId) => {
*/
export const getV1HashedProjectId = (projectId: string) => {
const { chainId, registryAddress, id } = getProjectURIComponents(projectId);
+
const generatedProjectId = generateUniqueRoundApplicationID(
Number(chainId),
id,
diff --git a/packages/builder/tailwind.config.js b/packages/builder/tailwind.config.js
index e7dd90d12e..e4329a5afd 100644
--- a/packages/builder/tailwind.config.js
+++ b/packages/builder/tailwind.config.js
@@ -1,7 +1,7 @@
module.exports = {
// if this is not set it will default to user's operating system preferences
darkMode: "class",
- content: ["./src/**/*.{js,jsx,ts,tsx}"],
+ content: ["./src/**/*.{js,jsx,ts,tsx}", "../common/src/**/*.{js,jsx,ts,tsx}"],
theme: {
extend: {
boxShadow: {
diff --git a/packages/builder/tsconfig.json b/packages/builder/tsconfig.json
index 5d36adfab3..8dfe0f6c60 100644
--- a/packages/builder/tsconfig.json
+++ b/packages/builder/tsconfig.json
@@ -15,7 +15,8 @@
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
- "sourceMap": true
+ "sourceMap": true,
+ "incremental": true
},
- "include": ["src", "craco.config.js"]
+ "include": ["src", "craco.config.js", ".eslintrc.js"]
}
diff --git a/packages/common/package.json b/packages/common/package.json
index d3d0b2352d..00e5d91d50 100644
--- a/packages/common/package.json
+++ b/packages/common/package.json
@@ -8,13 +8,14 @@
"scripts": {
"test": "vitest --run",
"prepare": "tsc",
+ "dev:fast": "esbuild src/**/*.ts src/**/*.tsx src/*.ts src/*.tsx --outdir=dist --watch",
"build": "tsc",
"dev": "tsc --watch",
"typecheck": "tsc --noEmit",
"test:watch": "vitest watch"
},
"dependencies": {
- "@allo-team/allo-v2-sdk": "^1.0.38",
+ "@allo-team/allo-v2-sdk": "^1.0.46",
"@ethersproject/providers": "^5.7.2",
"@ethersproject/abstract-signer": "^5.7.0",
"@rainbow-me/rainbowkit": "^0.12.16",
diff --git a/packages/common/src/allo/allo.ts b/packages/common/src/allo/allo.ts
index 2da0e1793b..ffbe828cb9 100644
--- a/packages/common/src/allo/allo.ts
+++ b/packages/common/src/allo/allo.ts
@@ -1,11 +1,11 @@
+import { Signer } from "@ethersproject/abstract-signer";
+import { Round } from "data-layer";
import { Address, Hex } from "viem";
import { AnyJson } from "..";
+import { CreateRoundData, RoundCategory } from "../types";
import { Result } from "./common";
import { AlloOperation } from "./operation";
import { TransactionReceipt } from "./transaction-sender";
-import { CreateRoundData, RoundCategory } from "../types";
-import { Round } from "data-layer";
-import { Signer } from "@ethersproject/abstract-signer";
export type CreateRoundArguments = {
roundData: {
@@ -60,10 +60,54 @@ export interface Allo {
indexingStatus: Result;
}
>;
+
+ /**
+ * Applies to a round
+ *
+ * @param args { projectId: Hex; roundId: Hex|Number; metadata: AnyJson }
+ * @dev roundId is round address in allo v1
+ * @dev roundId is poolId in allo v2
+ * @returns AlloOperation, { ipfs: Result; transaction: Result; transactionStatus: Result }>
+ */
+ applyToRound: (args: {
+ projectId: Hex;
+ roundId: Hex|number;
+ metadata: AnyJson;
+ }) => AlloOperation<
+ Result,
+ {
+ ipfs: Result;
+ transaction: Result;
+ transactionStatus: Result;
+ }
+ >;
}
export { AlloOperation };
+/**
+ * Represents an error that occurred while interacting with Allo.
+ *
+ * @remarks
+ *
+ * This error is thrown when an error occurs while interacting with Allo contracts.
+ *
+ * @public
+ *
+ * @extends Error
+ *
+ * @example
+ *
+ * ```typescript
+ * try {
+ * const result = await allo.createProject({ name: "Project", metadata: {} });
+ * } catch (error) {
+ * if (error instanceof AlloError) {
+ * console.error("An error occurred while creating the project", error);
+ * }
+ * }
+ * ```
+ */
export class AlloError extends Error {
constructor(
message: string,
diff --git a/packages/common/src/allo/backends/allo-v1.test.ts b/packages/common/src/allo/backends/allo-v1.test.ts
index 307c79a038..eb58bad92e 100644
--- a/packages/common/src/allo/backends/allo-v1.test.ts
+++ b/packages/common/src/allo/backends/allo-v1.test.ts
@@ -1,12 +1,13 @@
+import { Hex, encodeEventTopics, zeroAddress } from "viem";
import { beforeEach, describe, expect, test, vi } from "vitest";
-import { AlloV1 } from "./allo-v1";
-import { encodeEventTopics, Hex, zeroAddress } from "viem";
+import ProjectRegistry from "../abis/allo-v1/ProjectRegistry";
+import RoundImplementation from "../abis/allo-v1/RoundImplementation";
+import { Result, success } from "../common";
import {
- createMockTransactionSender,
TransactionReceipt,
+ createMockTransactionSender,
} from "../transaction-sender";
-import { Result, success } from "../common";
-import ProjectRegistry from "../abis/allo-v1/ProjectRegistry";
+import { AlloV1 } from "./allo-v1";
const zeroTxHash = ("0x" + "0".repeat(64)) as Hex;
const ipfsUploader = vi.fn().mockResolvedValue(success("ipfsHash"));
@@ -16,6 +17,10 @@ const chainId = 1;
describe("AlloV1", () => {
let allo: AlloV1;
+ let ipfsResult: Result;
+ let txResult: Result<`0x${string}`>;
+ let txStatusResult: Result;
+
beforeEach(() => {
allo = new AlloV1({
chainId,
@@ -26,10 +31,6 @@ describe("AlloV1", () => {
});
test("createProject", async () => {
- let ipfsResult: Result;
- let txResult: Result<`0x${string}`>;
- let txStatusResult: Result;
-
const result = await allo
.createProject({
name: "My Project",
@@ -73,4 +74,49 @@ describe("AlloV1", () => {
expect(txResult!).toEqual(success(zeroTxHash));
expect(txStatusResult!).toBeTruthy();
});
+
+ test("applyToRound", async () => {
+ const result = await allo
+ .applyToRound({
+ projectId: "0x123",
+ roundId: "0x456",
+ metadata: { foo: "bar" },
+ })
+ .on("ipfs", (r) => (ipfsResult = r))
+ .on("transaction", (r) => {
+ txResult = r;
+
+ /** mock transaction receipt */
+ transactionSender.wait = vi.fn().mockResolvedValueOnce({
+ transactionHash: zeroTxHash,
+ blockNumber: 1n,
+ blockHash: "0x0",
+ // todo: finish this
+ logs: [
+ {
+ topics: encodeEventTopics({
+ abi: RoundImplementation,
+ eventName: "NewProjectApplication",
+ args: {
+ projectID:
+ "0xa0affa31521afe084aee15c3ff5570c600b014cae2a9c45a9cc1e50b0c9852e5",
+ },
+ }),
+ data: "0x0",
+ },
+ ],
+ });
+ })
+ .on("transactionStatus", (r) => (txStatusResult = r))
+ .execute();
+
+ // expect(result).toEqual(
+ // success({
+ // projectID:
+ // "0xa0affa31521afe084aee15c3ff5570c600b014cae2a9c45a9cc1e50b0c9852e5",
+ // })
+ // );
+ expect(transactionSender.sentTransactions).toHaveLength(1);
+ expect(txStatusResult).toBeTruthy();
+ });
});
diff --git a/packages/common/src/allo/backends/allo-v1.ts b/packages/common/src/allo/backends/allo-v1.ts
index 57f2f09131..c6fc06a783 100644
--- a/packages/common/src/allo/backends/allo-v1.ts
+++ b/packages/common/src/allo/backends/allo-v1.ts
@@ -11,21 +11,13 @@ import {
parseUnits,
zeroAddress,
} from "viem";
-import { Allo, AlloError, AlloOperation, CreateRoundArguments } from "../allo";
-import { error, Result, success } from "../common";
-import { WaitUntilIndexerSynced } from "../indexer";
-import { IpfsUploader } from "../ipfs";
-import {
- decodeEventFromReceipt,
- sendTransaction,
- TransactionReceipt,
- TransactionSender,
-} from "../transaction-sender";
-import ProjectRegistryABI from "../abis/allo-v1/ProjectRegistry";
-import RoundFactoryABI from "../abis/allo-v1/RoundFactory";
import { AnyJson, ChainId } from "../..";
-import { RoundCategory } from "../../types";
import { parseChainId } from "../../chains";
+import { payoutTokens } from "../../payoutTokens";
+import { RoundCategory } from "../../types";
+import ProjectRegistryABI from "../abis/allo-v1/ProjectRegistry";
+import RoundFactoryABI from "../abis/allo-v1/RoundFactory";
+import RoundImplementation from "../abis/allo-v1/RoundImplementation";
import {
dgVotingStrategyDummyContractMap,
directPayoutStrategyFactoryContractMap,
@@ -34,7 +26,16 @@ import {
qfVotingStrategyFactoryMap,
roundFactoryMap,
} from "../addresses/allo-v1";
-import { payoutTokens } from "../../payoutTokens";
+import { Allo, AlloError, AlloOperation, CreateRoundArguments } from "../allo";
+import { error, Result, success } from "../common";
+import { WaitUntilIndexerSynced } from "../indexer";
+import { IpfsUploader } from "../ipfs";
+import {
+ decodeEventFromReceipt,
+ sendTransaction,
+ TransactionReceipt,
+ TransactionSender,
+} from "../transaction-sender";
function createProjectId(args: {
chainId: number;
@@ -375,6 +376,76 @@ export class AlloV1 implements Allo {
}
});
}
+
+ /**
+ * Applies to a round for Allo v1
+ *
+ * @param args { projectId: Hex; roundId: Hex; metadata: AnyJson }
+ *
+ * @public
+ *
+ * @returns AllotOperation, { ipfs: Result; transaction: Result; transactionStatus: Result }>
+ */
+ applyToRound(args: {
+ projectId: Hex;
+ roundId: Hex|number;
+ metadata: AnyJson;
+ }): AlloOperation<
+ Result,
+ {
+ ipfs: Result;
+ transaction: Result;
+ transactionStatus: Result;
+ }
+ > {
+ return new AlloOperation(async ({ emit }) => {
+
+ if (typeof args.roundId == "number") {
+ return error(
+ new AlloError("roundId must be Hex")
+ );
+ }
+
+ const ipfsResult = await this.ipfsUploader(args.metadata);
+
+ emit("ipfs", ipfsResult);
+
+ if (ipfsResult.type === "error") {
+ return ipfsResult;
+ }
+
+ const txResult = await sendTransaction(this.transactionSender, {
+ address: args.roundId,
+ abi: RoundImplementation,
+ functionName: "applyToRound",
+ args: [args.projectId, { protocol: 1n, pointer: ipfsResult.value }],
+ });
+
+ emit("transaction", txResult);
+
+ if (txResult.type === "error") {
+ return txResult;
+ }
+
+ let receipt: TransactionReceipt;
+ try {
+ receipt = await this.transactionSender.wait(txResult.value);
+
+ await this.waitUntilIndexerSynced({
+ chainId: this.chainId,
+ blockNumber: receipt.blockNumber,
+ });
+
+ emit("transactionStatus", success(receipt));
+ } catch (err) {
+ const result = new AlloError("Failed to apply to round");
+ emit("transactionStatus", error(result));
+ return error(result);
+ }
+
+ return success(args.projectId);
+ });
+ }
}
export type CreateRoundArgs = {
diff --git a/packages/common/src/allo/backends/allo-v2.test.ts b/packages/common/src/allo/backends/allo-v2.test.ts
index f936362c67..b9cd5a361a 100644
--- a/packages/common/src/allo/backends/allo-v2.test.ts
+++ b/packages/common/src/allo/backends/allo-v2.test.ts
@@ -1,21 +1,23 @@
-import { Hex, encodeEventTopics, zeroAddress } from "viem";
+import { Abi, Hex, encodeEventTopics, zeroAddress } from "viem";
import { beforeEach, describe, expect, test, vi } from "vitest";
-import RegistryABI from "../abis/allo-v2/Registry";
import { Result, success } from "../common";
import {
TransactionReceipt,
createMockTransactionSender,
} from "../transaction-sender";
import { AlloV2 } from "./allo-v2";
+import {
+ DonationVotingMerkleDistributionDirectTransferStrategyAbi,
+ RegistryAbi,
+} from "@allo-team/allo-v2-sdk";
const zeroTxHash = ("0x" + "0".repeat(64)) as Hex;
const ipfsUploader = vi.fn().mockResolvedValue(success("ipfsHash"));
const waitUntilIndexerSynced = vi.fn().mockResolvedValue(success(null));
const transactionSender = createMockTransactionSender();
const chainId = 1;
-const alloContractAddress = zeroAddress;
-const alloV2RegistryAddress = "0x4AAcca72145e1dF2aeC137E1f3C5E3D75DB8b5f3";
+const alloV2RegistryAddress = "0x4aacca72145e1df2aec137e1f3c5e3d75db8b5f3";
const profileCreationEvent = {
indexed: {
@@ -25,8 +27,19 @@ const profileCreationEvent = {
data: "0x0000000000000000000000000000000000000000000000000000000000001e6600000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000bbeeed010f67978d410cefdb416ca5f0207fad9c000000000000000000000000f839f6561167a018c0f488e05c2e65bbf0fbd628000000000000000000000000000000000000000000000000000000000000000f4d7920746573742070726f66696c65000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002e516d5339586946734371324e673662754a6d424c764e574e70637348733475594268566d4266534b32444670736d000000000000000000000000000000000000",
};
+const roundApplicationEvent = {
+ indexed: {
+ recipientId: "0x8C180840fcBb90CE8464B4eCd12ab0f840c6647C",
+ },
+ data: "0x0000000000000000000000000000000000000000000000000000000000001e6600000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000bbeeed010f67978d410cefdb416ca5f0207fad9c000000000000000000000000f839f6561167a018c0f488e05c2e65bbf0fbd628000000000000000000000000000000000000000000000000000000000000000f4d7920746573742070726f66696c65000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000002e516d5339586946734371324e673662754a6d424c764e574e70637348733475594268566d4266534b32444670736d000000000000000000000000000000000000",
+};
+
describe("AlloV2", () => {
let allo: AlloV2;
+ let ipfsResult: Result;
+ let txResult: Result<`0x${string}`>;
+ let txStatusResult: Result;
+
beforeEach(() => {
allo = new AlloV2({
chainId,
@@ -38,10 +51,6 @@ describe("AlloV2", () => {
});
test("createProject", async () => {
- let ipfsResult: Result;
- let txResult: Result<`0x${string}`>;
- let txStatusResult: Result;
-
const result = await allo
.createProject({
name: "My Project",
@@ -59,7 +68,7 @@ describe("AlloV2", () => {
logs: [
{
topics: encodeEventTopics({
- abi: RegistryABI,
+ abi: RegistryAbi as Abi,
eventName: "ProfileCreated",
args: {
profileId: profileCreationEvent.indexed.profileId as Hex,
@@ -86,4 +95,52 @@ describe("AlloV2", () => {
);
expect(txStatusResult!).toBeTruthy();
});
+
+ test("applyToRound", async () => {
+ const result = await allo
+ .applyToRound({
+ projectId: "0x123",
+ roundId: "0x456",
+ metadata: {
+ application: {
+ recipient: "0x789",
+ },
+ },
+ })
+ .on("ipfs", (r) => (ipfsResult = r))
+ .on("transaction", (r) => {
+ txResult = r;
+
+ /** mock transaction receipt */
+ transactionSender.wait = vi.fn().mockResolvedValueOnce({
+ transactionHash: zeroTxHash,
+ blockNumber: 1n,
+ blockHash: "0x0",
+ logs: [
+ {
+ topics: encodeEventTopics({
+ abi: DonationVotingMerkleDistributionDirectTransferStrategyAbi,
+ eventName: "Registered",
+ args: {
+ recipientId: roundApplicationEvent.indexed.recipientId as Hex,
+ },
+ }),
+ data: roundApplicationEvent.data,
+ },
+ ],
+ });
+ })
+ .on("transactionStatus", (r) => (txStatusResult = r))
+ .execute();
+
+ // expect(result).toEqual(
+ // success({ recipientId: roundApplicationEvent.indexed.recipientId as Hex })
+ // );
+ expect(transactionSender.sentTransactions).toHaveLength(1);
+ expect(transactionSender.sentTransactions[0].to.toLowerCase()).toEqual(
+ "0x4aacca72145e1df2aec137e1f3c5e3d75db8b5f3".toLocaleLowerCase()
+ );
+ expect(txResult!).toEqual(success(zeroTxHash));
+ expect(txStatusResult).toBeTruthy();
+ });
});
diff --git a/packages/common/src/allo/backends/allo-v2.ts b/packages/common/src/allo/backends/allo-v2.ts
index 47a047894e..0198f17e9c 100644
--- a/packages/common/src/allo/backends/allo-v2.ts
+++ b/packages/common/src/allo/backends/allo-v2.ts
@@ -1,21 +1,23 @@
-import { Address, Hex } from "viem";
+import {
+ Allo as AlloV2Contract,
+ CreateProfileArgs,
+ DonationVotingMerkleDistributionStrategy,
+ Registry,
+ RegistryAbi,
+ TransactionData,
+} from "@allo-team/allo-v2-sdk/";
+import { Abi, Address, Hex } from "viem";
+import { AnyJson } from "../..";
import { Allo, AlloError, AlloOperation, CreateRoundArguments } from "../allo";
-import { error, Result, success } from "../common";
+import { Result, error, success } from "../common";
import { WaitUntilIndexerSynced } from "../indexer";
import { IpfsUploader } from "../ipfs";
import {
- decodeEventFromReceipt,
- sendRawTransaction,
TransactionReceipt,
TransactionSender,
+ decodeEventFromReceipt,
+ sendRawTransaction,
} from "../transaction-sender";
-import RegistryABI from "../abis/allo-v2/Registry";
-import {
- CreateProfileArgs,
- TransactionData,
-} from "@allo-team/allo-v2-sdk/dist/types";
-import { Allo as AlloV2Contract, Registry } from "@allo-team/allo-v2-sdk/";
-import { AnyJson } from "../..";
export class AlloV2 implements Allo {
private transactionSender: TransactionSender;
@@ -111,10 +113,10 @@ export class AlloV2 implements Allo {
}
const projectCreatedEvent = decodeEventFromReceipt({
- abi: RegistryABI,
+ abi: RegistryAbi as Abi,
receipt,
event: "ProfileCreated",
- });
+ }) as { profileId: Hex };
return success({
projectId: projectCreatedEvent.profileId,
@@ -201,4 +203,90 @@ export class AlloV2 implements Allo {
indexingStatus: Result;
}
>;
+
+ /**
+ * Applies to a round for Allo v2
+ *
+ * @param args
+ *
+ * @public
+ *
+ * @returns AllotOperation, { ipfs: Result; transaction: Result; transactionStatus: Result }>
+ */
+ applyToRound(args: {
+ projectId: Hex;
+ roundId: Hex | number;
+ metadata: AnyJson;
+ }): AlloOperation<
+ Result,
+ {
+ ipfs: Result;
+ transaction: Result;
+ transactionStatus: Result;
+ }
+ > {
+ return new AlloOperation(async ({ emit }) => {
+ if (typeof args.roundId != "number") {
+ return error(new AlloError("roundId must be number"));
+ }
+
+ const strategyInstance = new DonationVotingMerkleDistributionStrategy({
+ chain: this.chainId,
+ poolId: args.roundId,
+ });
+
+ const ipfsResult = await this.ipfsUploader(args.metadata);
+
+ console.log("ipfsResult", ipfsResult);
+
+ emit("ipfs", ipfsResult);
+
+ if (ipfsResult.type === "error") {
+ return ipfsResult;
+ }
+
+ const metadata = args.metadata as unknown as {
+ application: { recipient: Hex };
+ };
+
+ const registerRecipientTx = strategyInstance.getRegisterRecipientData({
+ registryAnchor: args.projectId,
+ recipientAddress: metadata.application.recipient,
+ metadata: {
+ protocol: 1n,
+ pointer: ipfsResult.value,
+ },
+ });
+
+ const txResult = await sendRawTransaction(this.transactionSender, {
+ to: registerRecipientTx.to,
+ data: registerRecipientTx.data,
+ value: BigInt(registerRecipientTx.value),
+ });
+
+ emit("transaction", txResult);
+
+ if (txResult.type === "error") {
+ return txResult;
+ }
+
+ let receipt: TransactionReceipt;
+
+ try {
+ receipt = await this.transactionSender.wait(txResult.value);
+ await this.waitUntilIndexerSynced({
+ chainId: this.chainId,
+ blockNumber: receipt.blockNumber,
+ });
+
+ emit("transactionStatus", success(receipt));
+ } catch (err) {
+ const result = new AlloError("Failed to apply to round");
+ emit("transactionStatus", error(result));
+ return error(result);
+ }
+
+ return success(receipt.transactionHash);
+ });
+ }
}
diff --git a/packages/common/src/chain-ids.ts b/packages/common/src/chain-ids.ts
index aa9402eb43..25acf07774 100644
--- a/packages/common/src/chain-ids.ts
+++ b/packages/common/src/chain-ids.ts
@@ -34,4 +34,5 @@ export const RedstoneTokenIds = {
MUTE: "MUTE",
mkUSD: "mkUSD",
DATA: "DATA",
+ USDGLO: "USDGLO",
} as const;
diff --git a/packages/common/src/components/Footer.tsx b/packages/common/src/components/Footer.tsx
index 4a24a6a176..76f20433de 100644
--- a/packages/common/src/components/Footer.tsx
+++ b/packages/common/src/components/Footer.tsx
@@ -2,7 +2,7 @@ import Discord from "../icons/Discord";
import Support from "../icons/Support";
import Github from "../icons/Github";
import Gitbook from "../icons/Gitbook";
-import { getConfig } from "../config";
+import { getConfig, setLocalStorageConfigOverride } from "../config";
const navigation = [
{
@@ -31,17 +31,35 @@ const navigation = [
},
];
+const config = getConfig();
const COMMIT_HASH = process.env.REACT_APP_GIT_SHA ?? "localhost";
-const ALLO_VERSION = getConfig().allo.version;
+const ALLO_VERSION = config.allo.version;
+
+function switchAlloVersion(version: string) {
+ setLocalStorageConfigOverride("allo-version", version);
+ window.location.reload();
+}
export default function Footer() {
+ const alloVersionAlternative =
+ ALLO_VERSION === "allo-v1" ? "allo-v2" : "allo-v1";
+
return (
-