Skip to content

Commit

Permalink
Merge pull request #410 from 1Hive/ui-allowlist
Browse files Browse the repository at this point in the history
UI allowlist
  • Loading branch information
Corantin authored Oct 15, 2024
2 parents fc2d52e + eaea92f commit eaf327d
Show file tree
Hide file tree
Showing 137 changed files with 19,200 additions and 2,323 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
d# Gardens v2
# Gardens v2

> Gardens is a **coordination platform**
> that fosters **vibrant ecosystems of shared wealth**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { useMetadataIpfsFetch } from "@/hooks/useIpfsFetch";
import { useSubgraphQuery } from "@/hooks/useSubgraphQuery";
import { alloABI } from "@/src/generated";
import { PoolTypes, ProposalStatus } from "@/types";
import { abiWithErrors } from "@/utils/abiWithErrors";
import { abiWithErrors } from "@/utils/abi";
import { useErrorDetails } from "@/utils/getErrorName";
import { prettyTimestamp } from "@/utils/text";

Expand Down Expand Up @@ -124,7 +124,7 @@ export default function Page({
abi: abiWithErrors(alloABI),
functionName: "distribute",
contractName: "Allo",
fallbackErrorMessage: "Error executing proposal. Please try again.",
fallbackErrorMessage: "Error executing proposal, please report a bug.",
onConfirmations: () => {
publish({
topic: "proposal",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import { useCollectQueryParams } from "@/contexts/collectQueryParams.context";
import { useMetadataIpfsFetch } from "@/hooks/useIpfsFetch";
import { useSubgraphQuery } from "@/hooks/useSubgraphQuery";
import { PoolTypes } from "@/types";
import { CV_SCALE_PRECISION } from "@/utils/numbers";

export const dynamic = "force-dynamic";

Expand All @@ -28,7 +27,7 @@ export default function Page({
params: { chain: string; poolId: number; garden: string };
}) {
const searchParams = useCollectQueryParams();

const { data, refetch, error } = useSubgraphQuery<getPoolDataQuery>({
query: getPoolDataDocument,
variables: { poolId: poolId, garden: garden },
Expand Down Expand Up @@ -109,12 +108,9 @@ export default function Page({
return <div className="mt-52 text-center">Pool {poolId} not found</div>;
}

const pointSystem = data.cvstrategies?.[0].config.pointSystem;
const communityAddress = strategyObj.registryCommunity.id as Address;
const alloInfo = data.allos[0];
const poolAmount = strategyObj.poolAmount as number;
const spendingLimitPct =
(Number(strategyObj.config.maxRatio || 0) / CV_SCALE_PRECISION) * 100;

const isEnabled = data.cvstrategies?.[0]?.isEnabled as boolean;

Expand All @@ -128,10 +124,7 @@ export default function Page({
poolId={poolId}
ipfsResult={ipfsResult}
isEnabled={isEnabled}
pointSystem={pointSystem}
chainId={chain}
proposalType={proposalType}
spendingLimitPct={spendingLimitPct}
/>
{isEnabled && (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export default function Page({

if (!token) {
return (
<div className="mt-96">
<div className="my-40">
<LoadingSpinner />
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// api/add-strategy

import { Params } from "next/dist/shared/lib/router/utils/route-matcher";
import { NextResponse } from "next/server";
import {
createPublicClient,
Expand All @@ -19,26 +20,20 @@ import { getViemChain } from "@/utils/web3";

const LIST_MANAGER_PRIVATE_KEY = process.env.LIST_MANAGER_PRIVATE_KEY;

const CHAIN_ID = process.env.CHAIN_ID ? parseInt(process.env.CHAIN_ID) : 1337;
const LOCAL_RPC = "http://127.0.0.1:8545";

const RPC_URL = getConfigByChain(CHAIN_ID)?.rpcUrl ?? LOCAL_RPC;
export async function POST(req: Request, { params }: Params) {
const apiKey = req.headers.get("Authorization");
const { chain } = params;

const PASSPORT_SCORER_ADDRESS = getConfigByChain(CHAIN_ID)
?.passportScorer as Address;

const client = createPublicClient({
chain: getViemChain(CHAIN_ID),
transport: http(RPC_URL),
});

const walletClient = createWalletClient({
account: privateKeyToAccount(`${LIST_MANAGER_PRIVATE_KEY}` as Address),
chain: getViemChain(CHAIN_ID),
transport: custom(client.transport),
});
if (apiKey !== process.env.CRON_SECRET) {
console.error("Unauthorized", {
req: req.url,
chain,
});
return NextResponse.json({ message: "Unauthorized" }, { status: 401 });
}

export async function POST(req: Request) {
const { strategy, threshold } = await req.json();

if (!strategy || !threshold) {
Expand All @@ -52,6 +47,22 @@ export async function POST(req: Request) {
}

try {
const RPC_URL = getConfigByChain(chain)?.rpcUrl ?? LOCAL_RPC;

const PASSPORT_SCORER_ADDRESS = getConfigByChain(chain)
?.passportScorer as Address;

const client = createPublicClient({
chain: getViemChain(chain),
transport: http(RPC_URL),
});

const walletClient = createWalletClient({
account: privateKeyToAccount(`${LIST_MANAGER_PRIVATE_KEY}` as Address),
chain: getViemChain(chain),
transport: custom(client.transport),
});

// Get registryCommunity address from CVStrategy
let registryCommunityAddress: Address;
try {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// api/passport-oracles/daily-job

import { Params } from "next/dist/shared/lib/router/utils/route-matcher";
import { NextResponse } from "next/server";
import { gql } from "urql";
import {
Expand All @@ -13,16 +14,11 @@ import { privateKeyToAccount } from "viem/accounts";
import { getConfigByChain } from "@/configs/chains";
import { initUrqlClient } from "@/providers/urql";
import { passportScorerABI } from "@/src/generated";
import { CV_PERCENTAGE_SCALE } from "@/utils/numbers";
import { CV_PASSPORT_THRESHOLD_SCALE } from "@/utils/numbers";
import { getViemChain } from "@/utils/web3";

const LIST_MANAGER_PRIVATE_KEY = process.env.LIST_MANAGER_PRIVATE_KEY ?? "";
const CHAIN_ID = process.env.CHAIN_ID ? parseInt(process.env.CHAIN_ID) : 1337;
const LOCAL_RPC = "http://127.0.0.1:8545";
const RPC_URL = getConfigByChain(CHAIN_ID)?.rpcUrl ?? LOCAL_RPC;
const CONTRACT_ADDRESS = getConfigByChain(CHAIN_ID)?.passportScorer as Address;
const SUBGRAPH = getConfigByChain(CHAIN_ID)?.subgraphUrl as string;
const API_ENDPOINT = "/api/passport/scores";

interface PassportUser {
id: string;
Expand All @@ -42,19 +38,6 @@ interface ApiScore {
stamp_scores: Record<string, number>;
}

const client = createPublicClient({
chain: getViemChain(CHAIN_ID),
transport: http(RPC_URL),
});

const walletClient = createWalletClient({
account: privateKeyToAccount(LIST_MANAGER_PRIVATE_KEY as Address),
chain: getViemChain(CHAIN_ID),
transport: custom(client.transport),
});

const { urqlClient } = initUrqlClient({ chainId: CHAIN_ID });

const query = gql`
query {
passportUsers {
Expand All @@ -67,12 +50,9 @@ const query = gql`
`;

const fetchScoresFromService = async (): Promise<ApiScore[]> => {
const url = new URL(
API_ENDPOINT,
`http://${process.env.HOST ?? "localhost"}:${process.env.PORT ?? 3000}`,
);
const url = `${process.env.VERCEL_URL ? "https://" + process.env.VERCEL_URL : "http://localhost:3000"}/api/passport/scores/`;

const response = await fetch(url.toString(), {
const response = await fetch(url, {
method: "GET",
headers: {
"Content-Type": "application/json",
Expand Down Expand Up @@ -120,35 +100,45 @@ const compareScores = (
};

const updateScoresOnChain = async (
chain: string,
updates: { userAddress: Address; score: number; lastUpdated: number }[],
) => {
const RPC_URL = getConfigByChain(chain)?.rpcUrl ?? LOCAL_RPC;
const CONTRACT_ADDRESS = getConfigByChain(chain)?.passportScorer as Address;

for (const update of updates) {
const integerScore = Number(update.score) * CV_PERCENTAGE_SCALE;
const data = {
const integerScore = Number(update.score) * CV_PASSPORT_THRESHOLD_SCALE;

const client = createPublicClient({
chain: getViemChain(chain),
transport: http(RPC_URL),
});

const walletClient = createWalletClient({
account: privateKeyToAccount(LIST_MANAGER_PRIVATE_KEY as Address),
chain: getViemChain(chain),
transport: custom(client.transport),
});

const hash = await walletClient.writeContract({
abi: passportScorerABI,
address: CONTRACT_ADDRESS,
functionName: "addUserScore" as const,
args: [
update.userAddress,
{
score: BigInt(integerScore),
lastUpdated: BigInt(Date.now()),
},
] as const,
};

const hash = await walletClient.writeContract(data);
args: [update.userAddress, BigInt(integerScore)] as const,
});
await client.waitForTransactionReceipt({ hash });
}
};

const updateScores = async () => {
const updateScores = async (chain: string) => {
const subgraphUrl = getConfigByChain(chain)?.subgraphUrl as string;
const { urqlClient } = initUrqlClient({ chainId: chain });
const subgraphResponse = await urqlClient
.query<{ passportUsers: PassportUser[] }>(
query,
{},
{
url: SUBGRAPH,
url: subgraphUrl,
requestPolicy: "network-only",
},
)
Expand All @@ -164,17 +154,34 @@ const updateScores = async () => {
const updates = compareScores(subgraphUsers, apiScores);

if (updates.length > 0) {
await updateScoresOnChain(updates);
await updateScoresOnChain(chain, updates);
}

return updates;
};

export async function GET() {
export async function GET(req: Request, { params }: Params) {
const apiKey = req.headers.get("Authorization");
const { chain } = params;

if (apiKey !== process.env.CRON_SECRET) {
console.error("Unauthorized", {
req: req.url,
chain,
});
return NextResponse.json({ message: "Unauthorized" }, { status: 401 });
}

try {
const updates = await updateScores();
const updates = await updateScores(chain);
return NextResponse.json(
{ message: "Scores updated successfully", updates },
{
message:
updates.length ?
"Scores updated successfully"
: "No updates required",
updates,
},
{ status: 200 },
);
} catch (error) {
Expand Down
Loading

0 comments on commit eaf327d

Please sign in to comment.