Skip to content

Commit

Permalink
Merge pull request #160 from skip-mev/fix/leaky
Browse files Browse the repository at this point in the history
  • Loading branch information
Griko Nibras authored Feb 13, 2024
2 parents f07aa23 + cc4c64d commit 0de2d55
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 63 deletions.
2 changes: 2 additions & 0 deletions env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ declare namespace NodeJS {
readonly WALLETCONNECT_VERIFY_KEY?: string;
}
}

declare type MaybePromise<T> = T | Promise<T>;
50 changes: 44 additions & 6 deletions src/config/endpoints.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,53 @@
// @ts-check

/**
* @typedef {{ endpoint: string | undefined; isPrivate: boolean } | undefined} EndpointConfig
*/

/**
* @typedef {(chainID: string) => MaybePromise<EndpointConfig>} FallbackEndpointFn
*/

/**
* @param {string} chainID
* @param {"api" | "rpc"} type
* @returns {EndpointConfig}
*/
exports.getWhitelabelEndpoint = (chainID, type) => {
/** @type {string | undefined} */
let endpoint;

if (type === "api") {
endpoint = exports.CUSTOM_API_CHAIN_IDS[chainID];
} else {
endpoint = exports.CUSTOM_RPC_CHAIN_IDS[chainID];
}

if (endpoint) {
return {
endpoint,
isPrivate: false,
};
}

/** @type {true | number | undefined} */
const config = exports.WHITELABEL_CHAIN_IDS[chainID];

if (!config) return;
if (!config) {
return undefined;
}

const nodeID = exports.WHITELABEL_CUSTOM_NODE_IDS[chainID] || chainID;

const parts = [chainID, "skip", type];
const parts = [nodeID, "skip", type]; // e.g. 'cosmoshub-4-skip-rpc'
if (typeof config === "number") {
parts.push(config.toString());
parts.push(config.toString()); // e.g. 'osmosis-1-skip-rpc-1'
}

const endpoint = `https://${parts.join("-")}.polkachu.com`;

return endpoint;
return {
endpoint: `https://${parts.join("-")}.polkachu.com`,
isPrivate: true,
};
};

/**
Expand Down Expand Up @@ -105,3 +135,11 @@ exports.WHITELABEL_CHAIN_IDS = {
"ununifi-beta-v1": true,
"dimension_37-1": true,
};

/**
* @type {Record<string, string>}
*/
exports.WHITELABEL_CUSTOM_NODE_IDS = {
"crypto-org-chain-mainnet-1": "crypto-org-mainnet",
"shentu-2.2": "shentu-22",
};
33 changes: 5 additions & 28 deletions src/pages/api/rest/handler.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { PageConfig } from "next";
import { NextRequest } from "next/server";

import { chainRecord } from "@/chains/chains";
import { getWhitelabelEndpoint } from "@/config/endpoints";
import { getPolkachuAuthHeader } from "@/utils/api";
import { createProxyHandler } from "@/utils/api";

export const config: PageConfig = {
api: {
Expand All @@ -13,28 +11,7 @@ export const config: PageConfig = {
runtime: "edge",
};

export default async function handler(req: NextRequest) {
try {
const [chainID, ...args] = req.url.split("/api/rest/").pop()!.split("/");

const endpoint = getWhitelabelEndpoint(chainID, "api") ?? chainRecord[chainID]?.apis?.rest?.[0]?.address;
if (!endpoint) {
return new Response(null, { status: 404 }); // Not Found
}

const headers = new Headers();
if (endpoint.includes("skip-api") && endpoint.endsWith(".polkachu.com")) {
headers.set("authorization", getPolkachuAuthHeader());
}

const uri = [endpoint, ...args].join("/");
return fetch(uri, {
body: req.body,
headers,
method: req.method,
});
} catch (error) {
const data = JSON.stringify({ error });
return new Response(data, { status: 500 }); // Internal Server Error
}
}
export default createProxyHandler("api", (chainID) => ({
endpoint: chainRecord[chainID]?.apis?.rest?.[0]?.address,
isPrivate: false,
}));
33 changes: 5 additions & 28 deletions src/pages/api/rpc/handler.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { PageConfig } from "next";
import { NextRequest } from "next/server";

import { chainRecord } from "@/chains/chains";
import { getWhitelabelEndpoint } from "@/config/endpoints";
import { getPolkachuAuthHeader } from "@/utils/api";
import { createProxyHandler } from "@/utils/api";

export const config: PageConfig = {
api: {
Expand All @@ -13,28 +11,7 @@ export const config: PageConfig = {
runtime: "edge",
};

export default async function handler(req: NextRequest) {
try {
const [chainID, ...args] = req.url.split("/api/rpc/").pop()!.split("/");

const endpoint = getWhitelabelEndpoint(chainID, "rpc") ?? chainRecord[chainID]?.apis?.rpc?.[0]?.address;
if (!endpoint) {
return new Response(null, { status: 404 }); // Not Found
}

const headers = new Headers();
if (endpoint.includes("skip-rpc") && endpoint.endsWith(".polkachu.com")) {
headers.set("authorization", getPolkachuAuthHeader());
}

const uri = [endpoint, ...args].join("/");
return fetch(uri, {
body: req.body,
headers,
method: req.method,
});
} catch (error) {
const data = JSON.stringify({ error });
return new Response(data, { status: 500 }); // Internal Server Error
}
}
export default createProxyHandler("rpc", (chainID) => ({
endpoint: chainRecord[chainID]?.apis?.rpc?.[0]?.address,
isPrivate: false,
}));
36 changes: 35 additions & 1 deletion src/utils/api.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,38 @@
export function getPolkachuAuthHeader() {
import { NextRequest } from "next/server";

import { type FallbackEndpointFn, getWhitelabelEndpoint } from "@/config/endpoints";

export function createProxyHandler(type: "api" | "rpc", fallbackFn?: FallbackEndpointFn) {
return async function handler(req: NextRequest) {
try {
const [chainID, ...args] = req.url.split(`/api/${type}/`).pop()!.split("/");

let data = getWhitelabelEndpoint(chainID, type);
fallbackFn && (data ??= await fallbackFn(chainID));

if (!data) {
return new Response(null, { status: 404 }); // Not Found
}

const headers = new Headers();
if (data.isPrivate) {
headers.set("authorization", getPrivateAuthHeader());
}

const uri = [data.endpoint, ...args].join("/");
return fetch(uri, {
body: req.body,
headers,
method: req.method,
});
} catch (error) {
const data = JSON.stringify({ error });
return new Response(data, { status: 500 }); // Internal Server Error
}
};
}

export function getPrivateAuthHeader() {
if (!(process.env.POLKACHU_USER && process.env.POLKACHU_PASSWORD)) {
throw new Error("env POLKACHU_USER or POLKACHU_PASSWORD is not set");
}
Expand Down

0 comments on commit 0de2d55

Please sign in to comment.