Skip to content

Commit

Permalink
feat: matching estimate prototype
Browse files Browse the repository at this point in the history
  • Loading branch information
vacekj committed Jun 22, 2023
1 parent 55bdceb commit 75eadc4
Show file tree
Hide file tree
Showing 5 changed files with 433 additions and 171 deletions.
4 changes: 3 additions & 1 deletion packages/grant-explorer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
"msw": "^0.47.4",
"node-fetch": "^3.3.1",
"os-browserify": "^0.3.0",
"pluralistic": "github:gitcoinco/pluralistic.js",
"process": "^0.11.10",
"react": "^18.1.0",
"react-datetime": "^3.1.1",
Expand All @@ -93,9 +94,10 @@
"stream-browserify": "^3.0.0",
"stream-http": "^3.2.0",
"swr": "^2.0.0",
"typescript": "^4.6.0",
"typescript": "^5.1.3",
"url": "^0.11.0",
"util": "^0.12.4",
"viem": "^1.1.4",
"wagmi": "0.6.8",
"web-vitals": "^2.1.0",
"webpack": ">=2"
Expand Down
102 changes: 102 additions & 0 deletions packages/grant-explorer/src/features/common/MatchingEstimations.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { useMemo } from "react";
import { Client } from "allo-indexer-client";
import { useWallet } from "./Auth";
import { Contribution, linearQF } from "pluralistic";
import useSWR from "swr";
import { Round } from "allo-indexer-client";
import { useAccount, useNetwork } from "wagmi";
import { getAddress, Hex, zeroAddress } from "viem";

export function useAlloIndexerClient(): Client {
const { chain } = useNetwork();

return useMemo(() => {
return new Client(
fetch.bind(window),
process.env.REACT_APP_ALLO_API_URL ?? "",
chain?.id ?? 1
);
}, [chain?.id]);
}

export function useProjectContributions(roundId: string, projectId: string) {
const client = useAlloIndexerClient();
return useSWR([roundId, "/applications"], ([roundId]) => {
return client.getVotes(roundId);
});
}

export function useRound(roundId: string) {
const client = useAlloIndexerClient();
return useSWR([roundId, "/stats"], ([roundId]) => {
return client.getRoundBy("id", roundId);
});
}

/**
* Pseudocode
* - get matching amount without user contribution
* for each donation amount:
* - get amount after user contribution by running linearQF with the added vote
* - deduct match amount w/o user contribution to get new matching
* - return new matching
* */
export function MatchingEstimations({
roundId,
projectId,
recipient,
}: {
projectId: string;
roundId: string;
recipient: string;
}) {
const { address } = useAccount();
const { data: round } = useRound(getAddress(roundId));
const { data: votes } = useProjectContributions(
getAddress(roundId),
projectId
);

if (!round || !votes) {
return null;
}
const rawContributions: Contribution[] = (votes ?? []).map((vote) => ({
amount: BigInt(Math.round(vote.amountUSD)),
recipient: vote.grantAddress,
contributor: vote.voter,
}));

const amountMatchedBeforeUserContribution = linearQF(
rawContributions,
BigInt(Math.round(round?.matchAmountUSD) ?? 0),
BigInt(18)
// TODO: fetch additional options for round
);

const matchingBeforeUserContribution =
amountMatchedBeforeUserContribution[recipient]?.matched;

const matchingPredictions = [0, 1, 10, 100, 1000]
.map((donationAmount) => {
const contributions: Contribution[] = [
...rawContributions,
{
amount: BigInt(Math.round(donationAmount)),
contributor: address ?? zeroAddress,
recipient: recipient,
},
];
const amountMatchedAfterUserContribution = linearQF(
contributions,
BigInt(Math.round(round?.matchAmountUSD) ?? 0),
BigInt(18)
// TODO: fetch additional options for round
)[recipient]?.matched;

return (
amountMatchedAfterUserContribution - matchingBeforeUserContribution
);
})
.map((bigint) => Number(bigint));
return <div>{JSON.stringify(matchingPredictions)}</div>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import PassportBanner from "../common/PassportBanner";
import { ProjectBanner } from "../common/ProjectBanner";
import RoundEndedBanner from "../common/RoundEndedBanner";
import Breadcrumb, { BreadcrumbItem } from "../common/Breadcrumb";
import { linearQF } from "pluralistic";
import { MatchingEstimations } from "../common/MatchingEstimations";

const CalendarIcon = (props: React.SVGProps<SVGSVGElement>) => {
return (
Expand Down Expand Up @@ -547,6 +549,13 @@ export function ProjectStats() {
"rounded bg-gray-50 mb-4 p-4 gap-4 grid grid-cols-3 md:flex md:flex-col"
}
>
{projectToRender && (
<MatchingEstimations
projectId={projectToRender.grantApplicationId}
roundId={roundId as string}
recipient={projectToRender.recipient}
/>
)}
<div>
<h3>${application?.amountUSD.toFixed(2) ?? "-"}</h3>
<p>funding received in current round</p>
Expand Down
2 changes: 1 addition & 1 deletion packages/grant-explorer/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"compilerOptions": {
"target": "es5",
"target": "es2020",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
Expand Down
Loading

0 comments on commit 75eadc4

Please sign in to comment.