Skip to content

Commit

Permalink
♻️ Refactored daily job route for multi-chain support
Browse files Browse the repository at this point in the history
- Renamed the `dailyJob` route to support different chains
- Moved chain-specific variables inside the `updateScoresOnChain` function
- Changed `GET` method to `POST` and added authorization check
- Added new cron jobs in vercel.json for different chains
- Included 'CRON_SECRET' in environment variables in turbo.json

:alarm_clock: Updated job schedule frequency

The frequency of the daily-job in the passport-oracles API has been updated.

- The job was previously running every minute, but it's now set to run every 15 minutes. This change should help reduce server load and improve overall performance.

:lock: Added unauthorized access logging

- Enhanced security by adding a console error log for unauthorized attempts to access the dailyJob route.
- The log includes details such as the request URL and chain parameter.

:alarm_clock: Updated cron job configurations

- Added POST method to all scheduled jobs
- No changes in the schedule timings, they remain at every 15 minutes
- This update ensures that the correct HTTP method is used when these jobs are triggered

:recycle: Refactor code to support multiple chains

- Renamed routes to include chain parameter
- Moved chain-specific variables inside functions, allowing them to use the new chain parameter
- Replaced local URLs with Vercel URL for fetching scores and passport data
- Removed unused environment variables (CHAIN_ID, HOST, PORT)
- Added authorization check in POST methods using CRON_SECRET environment variable
- Updated cron jobs in vercel.json to remove method specification

:sparkles: Added chain ID to API endpoints

- Imported `useChainIdFromPath` hook in CheckPassport, PoolForm and SubmitPassport components
- Updated the WRITE_SCORER_URI and fetch URL for addStrategy to include `chainFromPath`
- This allows the application to dynamically use the correct chain ID based on the current path

Fix paths

:truck: Standardize route naming

Renamed several routes to follow a consistent kebab-case naming convention. This change improves readability and consistency across the codebase.

- Changed 'addStrategy' to 'add-strategy'
- Renamed 'dailyJob' to 'daily-job'
- Updated 'writeScore' to 'write-score'
- Altered 'signMessage' to 'sign-message'
- Modified 'submitPassport' to 'submit-passport'

Also updated references in components where these routes were used.

:recycle: Improved URL handling and response messages

- Modified the way URLs are constructed to handle both production and development environments
- Enhanced response message to provide more accurate status of score updates
  • Loading branch information
Corantin committed Oct 11, 2024
1 parent 9670645 commit 8cd160d
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 55 deletions.
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
Expand Up @@ -19,8 +19,11 @@ import { getViemChain } from "@/utils/web3";

const LIST_MANAGER_PRIVATE_KEY = process.env.LIST_MANAGER_PRIVATE_KEY ?? "";
const LOCAL_RPC = "http://127.0.0.1:8545";
<<<<<<<< HEAD:apps/web/app/api/passport-oracle/dailyJob/[chain]/route.ts

const API_ENDPOINT = "/api/passport/scores";
========
>>>>>>>> 648e2f64 (:recycle: Refactored daily job route for multi-chain support):apps/web/app/api/passport-oracle/daily-job/[chain]/route.ts

interface PassportUser {
id: string;
Expand Down Expand Up @@ -52,12 +55,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 @@ -172,18 +172,35 @@ const updateScores = async (chain: string) => {
return updates;
};

<<<<<<<< HEAD:apps/web/app/api/passport-oracle/dailyJob/[chain]/route.ts
export async function POST(req: Request, { params }: Params) {
========
export async function GET(req: Request, { params }: Params) {
>>>>>>>> 648e2f64 (:recycle: Refactored daily job route for multi-chain support):apps/web/app/api/passport-oracle/daily-job/[chain]/route.ts
const apiKey = req.headers.get("Authorization");
const { chain } = params;

if (apiKey !== process.env.CRON_SECRET) {
<<<<<<<< HEAD:apps/web/app/api/passport-oracle/dailyJob/[chain]/route.ts
========
console.error("Unauthorized", {
req: req.url,
chain,
});
>>>>>>>> 648e2f64 (:recycle: Refactored daily job route for multi-chain support):apps/web/app/api/passport-oracle/daily-job/[chain]/route.ts
return NextResponse.json({ message: "Unauthorized" }, { status: 401 });
}

try {
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// api/passport-oracle/write-score

import { Params } from "next/dist/shared/lib/router/utils/route-matcher";
import { NextResponse } from "next/server";
import {
createPublicClient,
Expand All @@ -15,33 +16,10 @@ import { CV_PERCENTAGE_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 API_ENDPOINT = "/api/passport";

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 fetchScoreFromGitcoin = async (user: string) => {
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`;
const response = await fetch(`${url}/${user}`, {
method: "GET",
headers: {
Expand All @@ -58,7 +36,18 @@ const fetchScoreFromGitcoin = async (user: string) => {
}
};

export async function POST(req: Request) {
export async function POST(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 });
}

const { user } = await req.json();

if (!user) {
Expand All @@ -71,6 +60,23 @@ export async function POST(req: Request) {
}

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

const CONTRACT_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),
});

const score = await fetchScoreFromGitcoin(user);
const integerScore = Number(score) * CV_PERCENTAGE_SCALE;
const data = {
Expand Down
6 changes: 4 additions & 2 deletions apps/web/components/CheckPassport.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
import { Button } from "./Button";
import { Modal } from "@/components";
import { isProd } from "@/configs/isProd";
import { useChainIdFromPath } from "@/hooks/useChainIdFromPath";
import { useSubgraphQuery } from "@/hooks/useSubgraphQuery";
import { CV_PERCENTAGE_SCALE } from "@/utils/numbers";

Expand Down Expand Up @@ -39,6 +40,7 @@ export function CheckPassport({
const [score, setScore] = useState<number>(0);
const [shouldOpenModal, setShouldOpenModal] = useState(false);
const [isSubmiting, setIsSubmiting] = useState<boolean>(false);
const chainFromPath = useChainIdFromPath();

//pool threshold should be ready on!

Expand Down Expand Up @@ -157,7 +159,7 @@ export function CheckPassport({
const submitPassport = async (
address: string,
): Promise<SubmitPassportResponse> => {
const SUBMIT_SIGNED_PASSPORT_URI = "/api/passport/submitPassport";
const SUBMIT_SIGNED_PASSPORT_URI = "/api/passport/submit-passport";

try {
const response = await fetch(SUBMIT_SIGNED_PASSPORT_URI, {
Expand Down Expand Up @@ -187,7 +189,7 @@ export function CheckPassport({
};

const writeScorer = async (address: string): Promise<any> => {
const WRITE_SCORER_URI = "/api/passport-oracle/writeScore";
const WRITE_SCORER_URI = `/api/passport-oracle/writeScore/${chainFromPath}`;
try {
const response = await fetch(WRITE_SCORER_URI, {
method: "POST",
Expand Down
2 changes: 1 addition & 1 deletion apps/web/components/Forms/PoolForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ export function PoolForm({ token, communityAddr }: Props) {
>["args"],
) => {
try {
const res = await fetch("/api/passport-oracle/addStrategy", {
const res = await fetch(`/api/passport-oracle/addStrategy/${chain.id}`, {
method: "POST",
body: JSON.stringify({
strategy: newPoolData._strategy,
Expand Down
6 changes: 4 additions & 2 deletions apps/web/components/SubmitPassport.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React from "react";
import { toast } from "react-toastify";
import { useAccount } from "wagmi";
import { Button } from "@/components/";
import { useChainIdFromPath } from "@/hooks/useChainIdFromPath";

interface SubmitPassportResponse {
data: any;
Expand All @@ -11,11 +12,12 @@ interface SubmitPassportResponse {

export function SubmitPassport() {
const { address: connectedAccount } = useAccount();
const chainFromPath = useChainIdFromPath();

const submitPassport = async (
address: string,
): Promise<SubmitPassportResponse> => {
const SUBMIT_SIGNED_PASSPORT_URI = "/api/passport/submitPassport";
const SUBMIT_SIGNED_PASSPORT_URI = "/api/passport/submit-passport";

try {
const response = await fetch(SUBMIT_SIGNED_PASSPORT_URI, {
Expand Down Expand Up @@ -47,7 +49,7 @@ export function SubmitPassport() {
};

const writeScorer = async (address: string, score: string): Promise<any> => {
const WRITE_SCORER_URI = "/api/passport-oracle/writeScore";
const WRITE_SCORER_URI = `/api/passport-oracle/writeScore/${chainFromPath}`;

try {
const response = await fetch(WRITE_SCORER_URI, {
Expand Down
4 changes: 1 addition & 3 deletions turbo.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,9 @@
"SCORER_ID",
"PASSPORT_SCORER_ADDRESS",
"LIST_MANAGER_PRIVATE_KEY",
"CHAIN_ID",
"NODE_ENV",
"NEXT_ABLY_API_KEY",
"HOST",
"PORT",
"VERCEL_URL",
"NEXT_PUBLIC_ENV_GARDENS",
"NEXT_RUNTIME",
"NEXT_PUBLIC_SENTRY_DSN",
Expand Down

0 comments on commit 8cd160d

Please sign in to comment.