From ee50cec1bd1c34141e3e83cbbf89fc1a6367c88a Mon Sep 17 00:00:00 2001 From: Sem <931684+sembrestels@users.noreply.github.com> Date: Mon, 22 Jul 2024 17:11:28 +0200 Subject: [PATCH] Use a CORS proxy to access giveth project info --- packages/cors-proxy/README.md | 39 +++++++ packages/cors-proxy/biome.json | 22 ++++ packages/cors-proxy/package.json | 21 ++++ packages/cors-proxy/rollup.config.js | 16 +++ packages/cors-proxy/src/main.ts | 103 ++++++++++++++++++ .../src/modules/giveth/helpers/projectAddr.ts | 27 +++-- 6 files changed, 216 insertions(+), 12 deletions(-) create mode 100644 packages/cors-proxy/README.md create mode 100644 packages/cors-proxy/biome.json create mode 100644 packages/cors-proxy/package.json create mode 100644 packages/cors-proxy/rollup.config.js create mode 100644 packages/cors-proxy/src/main.ts diff --git a/packages/cors-proxy/README.md b/packages/cors-proxy/README.md new file mode 100644 index 00000000..4f1297eb --- /dev/null +++ b/packages/cors-proxy/README.md @@ -0,0 +1,39 @@ +# CORS Proxy + +## Installation and Usage + +### Installation + +First, install the required dependencies using: + +```sh +bun i +``` + +### Building the Project + +To build the project, use the following command: + +```sh +bun run build +``` + +This will create a `./dist/main.js` bundle that includes all tree-shaken dependencies. + +### Deployment + +To deploy the project, follow these steps: + +1. Create a function: + +```sh +bun create-func $NAME +``` + +2. Deploy the function: + +```sh +bun deploy-func $NAME +``` + +Replace `$NAME` with the desired name of your function. diff --git a/packages/cors-proxy/biome.json b/packages/cors-proxy/biome.json new file mode 100644 index 00000000..1109c405 --- /dev/null +++ b/packages/cors-proxy/biome.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.8.3/schema.json", + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true + }, + "organizeImports": { + "enabled": false + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true + } + }, + "formatter": { + "enabled": true, + "indentWidth": 2, + "indentStyle": "space" + } +} diff --git a/packages/cors-proxy/package.json b/packages/cors-proxy/package.json new file mode 100644 index 00000000..fe7f48e3 --- /dev/null +++ b/packages/cors-proxy/package.json @@ -0,0 +1,21 @@ +{ + "name": "evmcrispr-cors-proxy", + "private": true, + "version": "0.0.0", + "type": "module", + "main": "./src/main.ts", + "scripts": { + "build": "tsc src/main.ts && rollup -c", + "create-func": "fleek functions create --name", + "deploy-func": "fleek functions deploy --noBundle --path dist/main.js --name", + "lint": "biome check --write && biome format --write && biome lint --write" + }, + "devDependencies": { + "@biomejs/biome": "^1.8.3", + "@rollup/plugin-node-resolve": "^13.0.6", + "@rollup/plugin-typescript": "^11.1.6", + "rollup": "^2.60.0", + "typescript": "^5.2.2" + }, + "license": "MIT" +} diff --git a/packages/cors-proxy/rollup.config.js b/packages/cors-proxy/rollup.config.js new file mode 100644 index 00000000..8c22c832 --- /dev/null +++ b/packages/cors-proxy/rollup.config.js @@ -0,0 +1,16 @@ +import { nodeResolve } from "@rollup/plugin-node-resolve"; +import typescript from "@rollup/plugin-typescript"; + +export default { + input: "src/main.ts", + output: { + dir: "dist", + format: "es", + inlineDynamicImports: true, + banner: 'import { Buffer } from "node:buffer";', + }, + plugins: [ + nodeResolve(), // Needed to bundle the assets from node_modules + typescript(), + ], +}; diff --git a/packages/cors-proxy/src/main.ts b/packages/cors-proxy/src/main.ts new file mode 100644 index 00000000..d4b20816 --- /dev/null +++ b/packages/cors-proxy/src/main.ts @@ -0,0 +1,103 @@ +type RequestObject = { + method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "HEAD"; + headers?: { + [key: string]: string; + } | null; + path: string; + query?: { + [key: string]: string | string[]; + } | null; + body?: string | null; +}; + +type ResponseObject = + | { + status: number; + headers?: { + [key: string]: string; + } | null; + body?: string; + } + | string + | ArrayBuffer; + +export async function main(params: RequestObject): Promise { + try { + const { url } = processParams(params); + + const response = await fetch(url, { + method: params.method, + headers: params.headers ?? {}, + body: JSON.stringify(params.body), + }); + const body = await response.text(); + const headers = Object.fromEntries((response.headers as any).entries()); + headers["Access-Control-Allow-Origin"] = "*"; + const status = response.status; + + return { + status, + headers, + body, + }; + } catch (error) { + if (isErrorWithStatusAndBody(error)) { + return error; + } + return { + status: 500, + body: "Internal Server Error: " + error.message + error.stack, + }; + } +} + +// const slug = "evmcrispr"; +// main({ +// method: "POST", +// path: "/v0/https://mainnet.serve.giveth.io/graphql", +// headers: { +// "Content-Type": "application/json", +// }, +// body: JSON.stringify({ +// query: ` +// query GetLearnWithJasonEpisodes($slug: String!) { +// projectBySlug(slug: $slug) { +// id +// addresses { +// address +// networkId +// } +// } +// } +// `, +// variables: { +// slug, +// }, +// }), +// }).then((res) => { +// console.log(res); +// }); + +function isErrorWithStatusAndBody( + error: unknown, +): error is { status: number; body: string } { + const err = error as { [key: string]: unknown }; + return ( + err && + typeof err === "object" && + typeof err.status === "number" && + typeof err.body === "string" + ); +} + +function processParams(params: RequestObject): { url: string } { + const { path } = params; + if (!path.startsWith("/v0/")) { + throw { + status: 400, + body: "Invalid URL", + }; + } + const url = path.replace("/v0/", ""); + return { url }; +} diff --git a/packages/evmcrispr/src/modules/giveth/helpers/projectAddr.ts b/packages/evmcrispr/src/modules/giveth/helpers/projectAddr.ts index 3e119695..4322b5db 100644 --- a/packages/evmcrispr/src/modules/giveth/helpers/projectAddr.ts +++ b/packages/evmcrispr/src/modules/giveth/helpers/projectAddr.ts @@ -10,13 +10,15 @@ export const _projectAddr = async ( slug: string, ): Promise<[string, number]> => { const chainId = await module.getChainId(); - const result = await fetch("https://mainnet.serve.giveth.io/graphql", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - query: ` + const result = await fetch( + "https://cors-proxy.functions.on-fleek.app/v0/https://mainnet.serve.giveth.io/graphql", + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + query: ` query GetLearnWithJasonEpisodes($slug: String!) { projectBySlug(slug: $slug) { id @@ -27,11 +29,12 @@ export const _projectAddr = async ( } } `, - variables: { - slug, - }, - }), - }) + variables: { + slug, + }, + }), + }, + ) .then((res) => res.json()) .then((res) => [ res.data.projectBySlug.addresses.find((x: any) => x.networkId === chainId)