From e5925f049a892ee160eac3f4410ee062f8b36bfe Mon Sep 17 00:00:00 2001 From: givingmittal Date: Sun, 24 Mar 2024 10:30:24 +0530 Subject: [PATCH] feat: fetch startAt from chainsData api --- apps/faucet/.env.sample | 4 +- apps/faucet/src/App/App.tsx | 47 +++++++++++++++++---- apps/faucet/src/utils/chainsApi.ts | 66 ++++++++++++++++++++++++++++++ apps/faucet/src/utils/index.ts | 1 + apps/faucet/src/utils/types.ts | 12 ++++++ 5 files changed, 120 insertions(+), 10 deletions(-) create mode 100644 apps/faucet/src/utils/chainsApi.ts diff --git a/apps/faucet/.env.sample b/apps/faucet/.env.sample index ff7567be4..f2aadc5a3 100644 --- a/apps/faucet/.env.sample +++ b/apps/faucet/.env.sample @@ -1,6 +1,8 @@ # Faucet API Endpoint override -NAMADA_INTERFACE_FAUCET_API_URL=http://127.0.0.1:5000 +NAMADA_INTERFACE_FAUCET_API_URL=http://127.0.0.1:5000/ NAMADA_INTERFACE_FAUCET_API_ENDPOINT=/api/v1/faucet +NAMADA_INTERFACE_CHAIN_ID=shielded-expedition.88f17d1d14 +NAMADA_INTERFACE_CHAINS_URL=https://chains.heliax.click/ # Faucet limit, as defined in genesis toml NAMADA_INTERFACE_FAUCET_LIMIT=1000 diff --git a/apps/faucet/src/App/App.tsx b/apps/faucet/src/App/App.tsx index 37b37afed..5e173afeb 100644 --- a/apps/faucet/src/App/App.tsx +++ b/apps/faucet/src/App/App.tsx @@ -22,27 +22,32 @@ import { FaucetForm } from "App/Faucet"; import { chains } from "@namada/chains"; import { useUntil } from "@namada/hooks"; import { Account, AccountType } from "@namada/types"; -import { API } from "utils"; +import { API, ChainsAPI } from "utils"; import dotsBackground from "../../public/bg-dots.svg"; import { CallToActionCard } from "./CallToActionCard"; import { CardsContainer } from "./Card.components"; import { Faq } from "./Faq"; -const DEFAULT_URL = "http://localhost:5000"; +const DEFAULT_URL = "http://localhost:5000/"; const DEFAULT_ENDPOINT = "/api/v1/faucet"; const DEFAULT_FAUCET_LIMIT = "1000"; +const DEFAULT_CHAIN_ID = "shielded-expedition.88f17d1d14"; +const DEFAULT_CHAINS_URL = ""; const { NAMADA_INTERFACE_FAUCET_API_URL: faucetApiUrl = DEFAULT_URL, NAMADA_INTERFACE_FAUCET_API_ENDPOINT: faucetApiEndpoint = DEFAULT_ENDPOINT, NAMADA_INTERFACE_FAUCET_LIMIT: faucetLimit = DEFAULT_FAUCET_LIMIT, + NAMADA_INTERFACE_CHAIN_ID: chainId = DEFAULT_CHAIN_ID, + NAMADA_INTERFACE_CHAINS_URL: chainsURL = DEFAULT_CHAINS_URL, NAMADA_INTERFACE_PROXY: isProxied, NAMADA_INTERFACE_PROXY_PORT: proxyPort = 9000, } = process.env; const apiUrl = isProxied ? `http://localhost:${proxyPort}/proxy` : faucetApiUrl; -const url = `${apiUrl}${faucetApiEndpoint}`; +const url = `${apiUrl}${chainId}${faucetApiEndpoint}`; const api = new API(url); +const chainsApi = new ChainsAPI(chainsURL, chainId) const limit = parseInt(faucetLimit); const runFullNodeUrl = "https://docs.namada.net/operators/ledger"; const becomeBuilderUrl = "https://docs.namada.net/integrating-with-namada"; @@ -124,7 +129,7 @@ export const App: React.FC = () => { ); useEffect(() => { - const { startsAt } = settings; + let { startsAt } = settings; const now = new Date(); const nowUTC = Date.UTC( now.getUTCFullYear(), @@ -133,14 +138,37 @@ export const App: React.FC = () => { now.getUTCHours(), now.getUTCMinutes() ); - const startsAtToMilliseconds = startsAt * 1000; - if (nowUTC < startsAtToMilliseconds) { - setIsTestnetLive(false); - } // Fetch settings from faucet API (async () => { try { + let startsAtToMilliseconds = startsAt * 1000; + let startsAtText = defaults.startsAtText + try{ + const chainsData = await chainsApi.chainsData() + let validFrom = 0; + chainsData["chains"].filter(chain => chain.chain_id === chainId).forEach(chain => { + validFrom = Date.parse(chain.valid_from) / 1000; + }) + validFrom != 0 ? startsAt = validFrom : startsAt = START_TIME_UTC + startsAtToMilliseconds = startsAt * 1000; + startsAtText = new Date(startsAtToMilliseconds).toLocaleString( + "en-gb", + { + timeZone: "UTC", + month: "long", + day: "numeric", + year: "numeric", + hour: "numeric", + minute: "numeric", + } + ); + } catch(e) {} + + if (nowUTC < startsAtToMilliseconds) { + setIsTestnetLive(false); + } + const { difficulty, tokens_alias_to_address: tokens } = await api .settings() .catch((e) => { @@ -152,9 +180,10 @@ export const App: React.FC = () => { }); // Append difficulty level and tokens to settings setSettings({ - ...settings, difficulty, tokens, + startsAt, + startsAtText }); } catch (e) { setSettingsError(`Failed to load settings! ${e}`); diff --git a/apps/faucet/src/utils/chainsApi.ts b/apps/faucet/src/utils/chainsApi.ts new file mode 100644 index 000000000..d76d0aa9c --- /dev/null +++ b/apps/faucet/src/utils/chainsApi.ts @@ -0,0 +1,66 @@ +import { + ChallengeResponse, + Data, + ErrorResponse, + ChainsResponse, + } from "./types"; + + enum Endpoint { + ChainsData = "", + } + + export class ChainsAPI { + constructor(protected readonly url: string, protected readonly chainId: string) {} + + /** + * Wrapper for fetch requests to handle ReadableStream response when errors are received from API + * + * @param {string} endpoint + * @param {RequestInit} options + * + * @returns Object + */ + async request( + endpoint: string, + options: RequestInit = { method: "GET" } + ): Promise { + return await fetch(new URL(`${this.url}${endpoint}`), { + ...options, + }) + .then((response) => { + if (response.ok) { + return response.json(); + } + const reader = response?.body?.getReader(); + const errors = reader?.read().then((data): Promise => { + const response = JSON.parse( + new TextDecoder().decode(data.value) + ) as ErrorResponse; + // If code 429 is received on any request, rate limiting is blocking + // requests from this this IP, so provide a specific message: + if (response.code === 429) { + response.message = "Too many requests! Try again in one hour."; + } + return Promise.reject(response); + }); + if (!errors) { + throw new Error("Unable to parse error response"); + } + return errors; + }) + .catch((e) => { + console.error(e); + return Promise.reject(e); + }); + } + + /** + * Request faucet settings + * + * @returns Object + */ + async chainsData(): Promise { + return this.request(Endpoint.ChainsData); + } +} + \ No newline at end of file diff --git a/apps/faucet/src/utils/index.ts b/apps/faucet/src/utils/index.ts index 17f61411c..9d15a7fec 100644 --- a/apps/faucet/src/utils/index.ts +++ b/apps/faucet/src/utils/index.ts @@ -1,3 +1,4 @@ export * from "./api"; +export * from "./chainsApi"; export * from "./pow"; export * from "./types"; diff --git a/apps/faucet/src/utils/types.ts b/apps/faucet/src/utils/types.ts index 8a0eb9735..0a9e5eaad 100644 --- a/apps/faucet/src/utils/types.ts +++ b/apps/faucet/src/utils/types.ts @@ -10,6 +10,18 @@ export type SettingsResponse = { tokens_alias_to_address: Record; }; +export type ChainsResponse = { + chains: ChainData[] +} + +export type ChainData = { + chain_id: string; + valid_from: string; + valid_until: string; + network_type: string; + namada_version: string; +} + export type TransferDetails = { target: string; token: string;