From 46e6c0b9223aa729755e66bd36dbab80f035aa03 Mon Sep 17 00:00:00 2001 From: "Justin R. Evans" Date: Thu, 29 Aug 2024 12:09:02 -0400 Subject: [PATCH 1/4] fix: clean up, fix faucet form UI issue --- apps/faucet/src/App/App.tsx | 55 +++++++------------ apps/faucet/src/App/Common/AppBanner.tsx | 19 +++++++ apps/faucet/src/App/Common/AppHeader.tsx | 23 ++++++++ .../src/App/Common/Banner.components.ts | 21 +++++++ .../src/App/{ => Common}/CallToActionCard.tsx | 4 +- .../src/App/{ => Common}/Card.components.tsx | 0 .../src/App/{ => Common}/Faq.components.tsx | 0 apps/faucet/src/App/{ => Common}/Faq.tsx | 0 .../src/App/{ => Common}/FaqDropdown.tsx | 2 +- apps/faucet/src/App/Common/index.ts | 6 ++ apps/faucet/src/App/Faucet.tsx | 10 +++- 11 files changed, 100 insertions(+), 40 deletions(-) create mode 100644 apps/faucet/src/App/Common/AppBanner.tsx create mode 100644 apps/faucet/src/App/Common/AppHeader.tsx create mode 100644 apps/faucet/src/App/Common/Banner.components.ts rename apps/faucet/src/App/{ => Common}/CallToActionCard.tsx (88%) rename apps/faucet/src/App/{ => Common}/Card.components.tsx (100%) rename apps/faucet/src/App/{ => Common}/Faq.components.tsx (100%) rename apps/faucet/src/App/{ => Common}/Faq.tsx (100%) rename apps/faucet/src/App/{ => Common}/FaqDropdown.tsx (93%) create mode 100644 apps/faucet/src/App/Common/index.ts diff --git a/apps/faucet/src/App/App.tsx b/apps/faucet/src/App/App.tsx index 8c3b473d7..50927e892 100644 --- a/apps/faucet/src/App/App.tsx +++ b/apps/faucet/src/App/App.tsx @@ -1,15 +1,13 @@ import React, { createContext, useCallback, useEffect, useState } from "react"; import { ThemeProvider } from "styled-components"; -import { ActionButton, Alert, Heading } from "@namada/components"; +import { ActionButton, Alert } from "@namada/components"; import { Namada } from "@namada/integrations"; import { ColorMode, getTheme } from "@namada/utils"; import { AppContainer, BackgroundImage, - Banner, - BannerContents, BottomSection, ContentContainer, FaucetContainer, @@ -24,9 +22,13 @@ import { useUntil } from "@namada/hooks"; import { Account } from "@namada/types"; import { API } from "utils"; import dotsBackground from "../../public/bg-dots.svg"; -import { CallToActionCard } from "./CallToActionCard"; -import { CardsContainer } from "./Card.components"; -import { Faq } from "./Faq"; +import { + AppBanner, + AppHeader, + CallToActionCard, + CardsContainer, + Faq, +} from "./Common"; const DEFAULT_URL = "http://localhost:5000"; const DEFAULT_ENDPOINT = "/api/v1/faucet"; @@ -42,7 +44,6 @@ const { const apiUrl = isProxied ? `http://localhost:${proxyPort}/proxy` : faucetApiUrl; const url = `${apiUrl}${faucetApiEndpoint}`; -const api = new API(url); const limit = parseInt(faucetLimit); const runFullNodeUrl = "https://docs.namada.net/operators/ledger"; const becomeBuilderUrl = "https://docs.namada.net/integrating-with-namada"; @@ -54,11 +55,13 @@ type Settings = { startsAtText?: string; }; -type AppContext = Settings & { +type AppContext = { limit: number; url: string; settingsError?: string; api: API; + isTestnetLive: boolean; + settings: Settings; }; const START_TIME_UTC = 1702918800; @@ -74,17 +77,7 @@ const START_TIME_TEXT = new Date(START_TIME_UTC * 1000).toLocaleString( } ); -const defaults = { - startsAt: START_TIME_UTC, - startsAtText: `${START_TIME_TEXT} UTC`, -}; - -export const AppContext = createContext({ - ...defaults, - limit, - url, - api, -}); +export const AppContext = createContext(null); enum ExtensionAttachStatus { PendingDetection, @@ -104,8 +97,10 @@ export const App: React.FC = () => { const [colorMode, _] = useState(initialColorMode); const [isTestnetLive, setIsTestnetLive] = useState(true); const [settings, setSettings] = useState({ - ...defaults, + startsAt: START_TIME_UTC, + startsAtText: `${START_TIME_TEXT} UTC`, }); + const [api, setApi] = useState(new API(url)); const [settingsError, setSettingsError] = useState(); const theme = getTheme(colorMode); @@ -186,30 +181,22 @@ export const App: React.FC = () => { return ( - {!isTestnetLive && settings?.startsAtText && ( - - - Testnet will go live {settings.startsAtText}! Faucet is disabled - until then. - - - )} + - - Namada Faucet - + {extensionAttachStatus === diff --git a/apps/faucet/src/App/Common/AppBanner.tsx b/apps/faucet/src/App/Common/AppBanner.tsx new file mode 100644 index 000000000..9ec0cab60 --- /dev/null +++ b/apps/faucet/src/App/Common/AppBanner.tsx @@ -0,0 +1,19 @@ +import { AppContext } from "App/App"; +import React, { useContext } from "react"; +import { Banner, BannerContents } from "./Banner.components"; + +export const AppBanner: React.FC = () => { + const { isTestnetLive, settings } = useContext(AppContext)!; + return ( + <> + {!isTestnetLive && settings?.startsAtText && ( + + + Testnet will go live {settings.startsAtText}! Faucet is disabled + until then. + + + )} + + ); +}; diff --git a/apps/faucet/src/App/Common/AppHeader.tsx b/apps/faucet/src/App/Common/AppHeader.tsx new file mode 100644 index 000000000..0563504fa --- /dev/null +++ b/apps/faucet/src/App/Common/AppHeader.tsx @@ -0,0 +1,23 @@ +import { Heading } from "@namada/components"; +import clsx from "clsx"; +import React from "react"; +import { GoGear } from "react-icons/go"; + +const iconsClassList = clsx( + "flex h-full absolute items-center text-black cursor-pointer text-[22px]", + "top-0 transition-colors ease-out active:top-px hover:text-cyan" +); + +export const AppHeader: React.FC = () => { + return ( + + Namada Faucet + console.log("SETTINGS")} + > + + + + ); +}; diff --git a/apps/faucet/src/App/Common/Banner.components.ts b/apps/faucet/src/App/Common/Banner.components.ts new file mode 100644 index 000000000..f1a85b7a3 --- /dev/null +++ b/apps/faucet/src/App/Common/Banner.components.ts @@ -0,0 +1,21 @@ +import styled from "styled-components"; + +export const Banner = styled.div` + width: 100%; + display: flex; + justify-content: center; + align-items: center; + background-color: ${(props) => props.theme.colors.utility3.highAttention}; + color: ${(props) => props.theme.colors.primary.main20}; + font-size: 13px; + font-weight: bold; +`; + +export const BannerContents = styled.div` + display: flex; + width: 100%; + align-items: center; + max-width: 762px; + padding: 8px 0; + margin: 0 20px; +`; diff --git a/apps/faucet/src/App/CallToActionCard.tsx b/apps/faucet/src/App/Common/CallToActionCard.tsx similarity index 88% rename from apps/faucet/src/App/CallToActionCard.tsx rename to apps/faucet/src/App/Common/CallToActionCard.tsx index 1f9e807ff..725ee8f30 100644 --- a/apps/faucet/src/App/CallToActionCard.tsx +++ b/apps/faucet/src/App/Common/CallToActionCard.tsx @@ -1,6 +1,6 @@ import React, { useState } from "react"; -import InclineArrowBlack from "../../public/incline-arrow-black.svg"; -import InclineArrowYellow from "../../public/incline-arrow-yellow.svg"; +import InclineArrowBlack from "../../../public/incline-arrow-black.svg"; +import InclineArrowYellow from "../../../public/incline-arrow-yellow.svg"; import { BottomBorder, CallToActionContainer, diff --git a/apps/faucet/src/App/Card.components.tsx b/apps/faucet/src/App/Common/Card.components.tsx similarity index 100% rename from apps/faucet/src/App/Card.components.tsx rename to apps/faucet/src/App/Common/Card.components.tsx diff --git a/apps/faucet/src/App/Faq.components.tsx b/apps/faucet/src/App/Common/Faq.components.tsx similarity index 100% rename from apps/faucet/src/App/Faq.components.tsx rename to apps/faucet/src/App/Common/Faq.components.tsx diff --git a/apps/faucet/src/App/Faq.tsx b/apps/faucet/src/App/Common/Faq.tsx similarity index 100% rename from apps/faucet/src/App/Faq.tsx rename to apps/faucet/src/App/Common/Faq.tsx diff --git a/apps/faucet/src/App/FaqDropdown.tsx b/apps/faucet/src/App/Common/FaqDropdown.tsx similarity index 93% rename from apps/faucet/src/App/FaqDropdown.tsx rename to apps/faucet/src/App/Common/FaqDropdown.tsx index a9d7a149f..02f557268 100644 --- a/apps/faucet/src/App/FaqDropdown.tsx +++ b/apps/faucet/src/App/Common/FaqDropdown.tsx @@ -1,5 +1,5 @@ import React, { useState } from "react"; -import plusIcon from "../../public/plus-icon.svg"; +import plusIcon from "../../../public/plus-icon.svg"; import { DropDownTitle, DropDownTitleText, diff --git a/apps/faucet/src/App/Common/index.ts b/apps/faucet/src/App/Common/index.ts new file mode 100644 index 000000000..448948934 --- /dev/null +++ b/apps/faucet/src/App/Common/index.ts @@ -0,0 +1,6 @@ +export * from "./AppBanner"; +export * from "./AppHeader"; +export * from "./CallToActionCard"; +export * from "./Card.components"; +export * from "./Faq"; +export * from "./FaqDropdown"; diff --git a/apps/faucet/src/App/Faucet.tsx b/apps/faucet/src/App/Faucet.tsx index 2b8e6dcc5..a884715d7 100644 --- a/apps/faucet/src/App/Faucet.tsx +++ b/apps/faucet/src/App/Faucet.tsx @@ -43,8 +43,12 @@ export const FaucetForm: React.FC = ({ integration, isTestnetLive, }) => { - const { api, difficulty, settingsError, limit, tokens } = - useContext(AppContext); + const { + api, + settingsError, + limit, + settings: { difficulty, tokens }, + } = useContext(AppContext)!; const accountLookup = accounts.reduce( (acc, account) => { @@ -223,7 +227,7 @@ export const FaucetForm: React.FC = ({ Processing faucet transfer... )} - {status === Status.Completed && ( + {status === Status.Completed && statusText && ( {statusText} From 0aebf8386368435f48bf84b8cf472293dabb791f Mon Sep 17 00:00:00 2001 From: "Justin R. Evans" Date: Thu, 29 Aug 2024 12:34:44 -0400 Subject: [PATCH 2/4] feat: hook up settings modal --- apps/faucet/src/App/App.tsx | 13 +++++++- .../src/App/Common/AppHeader.components.ts | 17 ++++++++++ apps/faucet/src/App/Common/AppHeader.tsx | 26 +++++++-------- apps/faucet/src/App/SettingsForm.tsx | 32 +++++++++++++++++++ apps/faucet/src/utils/api.ts | 2 +- 5 files changed, 73 insertions(+), 17 deletions(-) create mode 100644 apps/faucet/src/App/Common/AppHeader.components.ts create mode 100644 apps/faucet/src/App/SettingsForm.tsx diff --git a/apps/faucet/src/App/App.tsx b/apps/faucet/src/App/App.tsx index 50927e892..91d1ded32 100644 --- a/apps/faucet/src/App/App.tsx +++ b/apps/faucet/src/App/App.tsx @@ -1,7 +1,7 @@ import React, { createContext, useCallback, useEffect, useState } from "react"; import { ThemeProvider } from "styled-components"; -import { ActionButton, Alert } from "@namada/components"; +import { ActionButton, Alert, Modal } from "@namada/components"; import { Namada } from "@namada/integrations"; import { ColorMode, getTheme } from "@namada/utils"; @@ -29,6 +29,7 @@ import { CardsContainer, Faq, } from "./Common"; +import { SettingsForm } from "./SettingsForm"; const DEFAULT_URL = "http://localhost:5000"; const DEFAULT_ENDPOINT = "/api/v1/faucet"; @@ -62,6 +63,8 @@ type AppContext = { api: API; isTestnetLive: boolean; settings: Settings; + setApi: (api: API) => void; + setIsModalOpen: (value: boolean) => void; }; const START_TIME_UTC = 1702918800; @@ -101,6 +104,7 @@ export const App: React.FC = () => { startsAtText: `${START_TIME_TEXT} UTC`, }); const [api, setApi] = useState(new API(url)); + const [isModalOpen, setIsModalOpen] = useState(false); const [settingsError, setSettingsError] = useState(); const theme = getTheme(colorMode); @@ -187,6 +191,8 @@ export const App: React.FC = () => { url, settingsError, settings, + setApi, + setIsModalOpen, }} > @@ -226,6 +232,11 @@ export const App: React.FC = () => { )} + {isModalOpen && ( + setIsModalOpen(false)}> + + + )} props.theme.colors.primary.main20}; + cursor: pointer; +`; diff --git a/apps/faucet/src/App/Common/AppHeader.tsx b/apps/faucet/src/App/Common/AppHeader.tsx index 0563504fa..c205fe46f 100644 --- a/apps/faucet/src/App/Common/AppHeader.tsx +++ b/apps/faucet/src/App/Common/AppHeader.tsx @@ -1,23 +1,19 @@ import { Heading } from "@namada/components"; -import clsx from "clsx"; -import React from "react"; +import { AppContext } from "App/App"; +import React, { useContext } from "react"; import { GoGear } from "react-icons/go"; - -const iconsClassList = clsx( - "flex h-full absolute items-center text-black cursor-pointer text-[22px]", - "top-0 transition-colors ease-out active:top-px hover:text-cyan" -); +import { AppHeaderContainer, SettingsButton } from "./AppHeader.components"; export const AppHeader: React.FC = () => { + const { setIsModalOpen } = useContext(AppContext)!; return ( - - Namada Faucet - console.log("SETTINGS")} - > + + + Namada Faucet + + setIsModalOpen(true)}> - - + + ); }; diff --git a/apps/faucet/src/App/SettingsForm.tsx b/apps/faucet/src/App/SettingsForm.tsx new file mode 100644 index 000000000..f67fd9086 --- /dev/null +++ b/apps/faucet/src/App/SettingsForm.tsx @@ -0,0 +1,32 @@ +import { ActionButton, Input } from "@namada/components"; +import { AppContext } from "App/App"; +import React, { useContext, useState } from "react"; +import { API } from "utils"; + +const DEFAULT_ENDPOINT = "/api/v1/faucet"; +const { NAMADA_INTERFACE_FAUCET_API_ENDPOINT: endpoint = DEFAULT_ENDPOINT } = + process.env; + +export const SettingsForm: React.FC = () => { + const { api, setApi, setIsModalOpen } = useContext(AppContext)!; + const [url, setUrl] = useState(api.url); + const handleFocus = (e: React.ChangeEvent): void => + e.target.select(); + + const handleSetApi = (url: string): void => { + setApi(new API(`${url}${endpoint}`)); + setIsModalOpen(false); + }; + + return ( + <> + setUrl(e.target.value)} + /> + handleSetApi(url)}>Update URL + + ); +}; diff --git a/apps/faucet/src/utils/api.ts b/apps/faucet/src/utils/api.ts index 41550a51e..b903f452f 100644 --- a/apps/faucet/src/utils/api.ts +++ b/apps/faucet/src/utils/api.ts @@ -7,7 +7,7 @@ import { } from "./types"; export class API { - constructor(protected readonly url: string) {} + constructor(public readonly url: string) {} /** * Wrapper for fetch requests to handle ReadableStream response when errors are received from API From 77d9ab0841c71bbed08eaea220d8e8f98c4761e3 Mon Sep 17 00:00:00 2001 From: "Justin R. Evans" Date: Fri, 30 Aug 2024 09:38:33 -0400 Subject: [PATCH 3/4] feat: improve forms & components --- apps/faucet/src/App/App.components.ts | 32 +++++++++++ apps/faucet/src/App/App.tsx | 63 +++++++++++++--------- apps/faucet/src/App/Faucet.components.ts | 14 +---- apps/faucet/src/App/Faucet.tsx | 23 ++++---- apps/faucet/src/App/SettingsForm.tsx | 69 +++++++++++++++++------- apps/faucet/src/utils/api.ts | 12 ++++- apps/faucet/src/utils/helpers.ts | 6 +++ apps/faucet/src/utils/index.ts | 1 + apps/faucet/src/utils/types.ts | 1 + 9 files changed, 150 insertions(+), 71 deletions(-) create mode 100644 apps/faucet/src/utils/helpers.ts diff --git a/apps/faucet/src/App/App.components.ts b/apps/faucet/src/App/App.components.ts index ea4de2696..7d3df94ca 100644 --- a/apps/faucet/src/App/App.components.ts +++ b/apps/faucet/src/App/App.components.ts @@ -140,3 +140,35 @@ export const ContentContainer = styled.div` padding: 0 16px; } `; + +export const InputContainer = styled.div` + margin: 12px 0; +`; + +export const ButtonContainer = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + margin: 13px 0 0 0; +`; + +export const SettingsContainer = styled.div` + flex-direction: column; + justify-content: start; + align-items: center; + box-sizing: border-box; + background-color: ${(props) => + getColor(ComponentColor.BackgroundColor, props.theme)}; + border: 1px solid ${(props) => props.theme.colors.primary.main20}; + border-radius: ${(props) => props.theme.borderRadius.mainContainer}; + transition: background-color 0.3s linear; +`; + +export const SettingsFormContainer = styled.form` + flex-direction: column; + justify-content: start; + align-items: center; + padding: 32px 40px; + width: 500px; +`; diff --git a/apps/faucet/src/App/App.tsx b/apps/faucet/src/App/App.tsx index 91d1ded32..0dca1878c 100644 --- a/apps/faucet/src/App/App.tsx +++ b/apps/faucet/src/App/App.tsx @@ -20,7 +20,7 @@ import { FaucetForm } from "App/Faucet"; import { chains } from "@namada/chains"; import { useUntil } from "@namada/hooks"; import { Account } from "@namada/types"; -import { API } from "utils"; +import { API, toNam } from "utils"; import dotsBackground from "../../public/bg-dots.svg"; import { AppBanner, @@ -32,20 +32,16 @@ import { import { SettingsForm } from "./SettingsForm"; const DEFAULT_URL = "http://localhost:5000"; -const DEFAULT_ENDPOINT = "/api/v1/faucet"; -const DEFAULT_FAUCET_LIMIT = "1000"; +const DEFAULT_LIMIT = 1_000_000_000; 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_PROXY: isProxied, NAMADA_INTERFACE_PROXY_PORT: proxyPort = 9000, } = process.env; -const apiUrl = isProxied ? `http://localhost:${proxyPort}/proxy` : faucetApiUrl; -const url = `${apiUrl}${faucetApiEndpoint}`; -const limit = parseInt(faucetLimit); +const baseUrl = + isProxied ? `http://localhost:${proxyPort}/proxy` : faucetApiUrl; const runFullNodeUrl = "https://docs.namada.net/operators/ledger"; const becomeBuilderUrl = "https://docs.namada.net/integrating-with-namada"; @@ -54,16 +50,17 @@ type Settings = { tokens?: Record; startsAt: number; startsAtText?: string; + withdrawLimit: number; }; type AppContext = { - limit: number; - url: string; + baseUrl: string; settingsError?: string; api: API; isTestnetLive: boolean; settings: Settings; setApi: (api: API) => void; + setUrl: (url: string) => void; setIsModalOpen: (value: boolean) => void; }; @@ -102,7 +99,9 @@ export const App: React.FC = () => { const [settings, setSettings] = useState({ startsAt: START_TIME_UTC, startsAtText: `${START_TIME_TEXT} UTC`, + withdrawLimit: toNam(DEFAULT_LIMIT), }); + const [url, setUrl] = useState(localStorage.getItem("baseUrl") || baseUrl); const [api, setApi] = useState(new API(url)); const [isModalOpen, setIsModalOpen] = useState(false); const [settingsError, setSettingsError] = useState(); @@ -123,6 +122,11 @@ export const App: React.FC = () => { ); useEffect(() => { + console.log("RECEIVED NEW URL, UPDATE API!", url); + // Sync url to localStorage + localStorage.setItem("baseUrl", url); + const api = new API(url); + setApi(api); const { startsAt } = settings; const now = new Date(); const nowUTC = Date.UTC( @@ -140,26 +144,28 @@ export const App: React.FC = () => { // Fetch settings from faucet API (async () => { try { - const { difficulty, tokens_alias_to_address: tokens } = await api - .settings() - .catch((e) => { - const message = e.errors?.message; - setSettingsError( - `Error requesting settings: ${message?.join(" ")}` - ); - throw new Error(e); - }); + const { + difficulty, + tokens_alias_to_address: tokens, + withdraw_limit: withdrawLimit = DEFAULT_LIMIT, + } = await api.settings().catch((e) => { + const message = e.errors?.message; + setSettingsError(`Error requesting settings: ${message?.join(" ")}`); + throw new Error(e); + }); // Append difficulty level and tokens to settings setSettings({ ...settings, difficulty, tokens, + withdrawLimit: toNam(withdrawLimit), }); + setSettingsError(undefined); } catch (e) { setSettingsError(`Failed to load settings! ${e}`); } })(); - }, []); + }, [url]); const handleConnectExtensionClick = useCallback(async (): Promise => { if (integration) { @@ -187,11 +193,11 @@ export const App: React.FC = () => { value={{ api, isTestnetLive, - limit, - url, + baseUrl: url, settingsError, settings, setApi, + setUrl, setIsModalOpen, }} > @@ -205,17 +211,24 @@ export const App: React.FC = () => { - {extensionAttachStatus === - ExtensionAttachStatus.PendingDetection && ( + {settingsError && ( - Detecting extension... + {settingsError} )} + + {extensionAttachStatus === + ExtensionAttachStatus.PendingDetection && ( + + Detecting extension... + + )} {extensionAttachStatus === ExtensionAttachStatus.NotInstalled && ( You must download the extension! )} + {isExtensionConnected && ( props.theme.colors.utility2.main20}; diff --git a/apps/faucet/src/App/Faucet.tsx b/apps/faucet/src/App/Faucet.tsx index a884715d7..051c62685 100644 --- a/apps/faucet/src/App/Faucet.tsx +++ b/apps/faucet/src/App/Faucet.tsx @@ -15,12 +15,14 @@ import { bech32mValidation, shortenAddress } from "@namada/utils"; import { TransferResponse, computePowSolution } from "../utils"; import { AppContext } from "./App"; -import { InfoContainer } from "./App.components"; import { ButtonContainer, + InfoContainer, + InputContainer, +} from "./App.components"; +import { FaucetFormContainer, FormStatus, - InputContainer, PreFormatted, } from "./Faucet.components"; @@ -45,9 +47,7 @@ export const FaucetForm: React.FC = ({ }) => { const { api, - settingsError, - limit, - settings: { difficulty, tokens }, + settings: { difficulty, tokens, withdrawLimit }, } = useContext(AppContext)!; const accountLookup = accounts.reduce( @@ -79,7 +79,7 @@ export const FaucetForm: React.FC = ({ const isFormValid: boolean = Boolean(tokenAddress) && Boolean(amount) && - (amount || 0) <= limit && + (amount || 0) <= withdrawLimit && Boolean(account) && status !== Status.Pending && typeof difficulty !== "undefined" && @@ -178,7 +178,6 @@ export const FaucetForm: React.FC = ({ return ( - {settingsError && {settingsError}} {accounts.length > 0 ? setUrl(e.target.value)} - /> - handleSetApi(url)}>Update URL - + + + + { + setApiUrl(e.target.value); + validateUrl(e.target.value); + }} + /> + + + handleSetUrl(apiUrl)} + disabled={!isFormValid || apiUrl === baseUrl} + > + Update URL + + + + ); }; diff --git a/apps/faucet/src/utils/api.ts b/apps/faucet/src/utils/api.ts index b903f452f..48a200dd9 100644 --- a/apps/faucet/src/utils/api.ts +++ b/apps/faucet/src/utils/api.ts @@ -6,8 +6,12 @@ import { TransferResponse, } from "./types"; +export const { + NAMADA_INTERFACE_FAUCET_API_ENDPOINT: endpoint = "/api/v1/faucet", +} = process.env; + export class API { - constructor(public readonly url: string) {} + constructor(public readonly baseUrl: string) { } /** * Wrapper for fetch requests to handle ReadableStream response when errors are received from API @@ -21,7 +25,7 @@ export class API { endpoint: string, options: RequestInit = { method: "GET" } ): Promise { - return await fetch(new URL(`${this.url}${endpoint}`), { + return await fetch(this.endpoint(endpoint), { ...options, }) .then((response) => { @@ -84,4 +88,8 @@ export class API { }, }); } + + private endpoint(path?: string): URL { + return new URL(`${this.baseUrl}${endpoint}${path ? path : ""}`); + } } diff --git a/apps/faucet/src/utils/helpers.ts b/apps/faucet/src/utils/helpers.ts new file mode 100644 index 000000000..c87d8d9f2 --- /dev/null +++ b/apps/faucet/src/utils/helpers.ts @@ -0,0 +1,6 @@ +/** + * Take a value in namnam, return NAM + */ +export const toNam = (amount: number): number => { + return amount / 1_000_000; +}; diff --git a/apps/faucet/src/utils/index.ts b/apps/faucet/src/utils/index.ts index 17f61411c..a9333307e 100644 --- a/apps/faucet/src/utils/index.ts +++ b/apps/faucet/src/utils/index.ts @@ -1,3 +1,4 @@ export * from "./api"; +export * from "./helpers"; export * from "./pow"; export * from "./types"; diff --git a/apps/faucet/src/utils/types.ts b/apps/faucet/src/utils/types.ts index 325aaef3c..2f93c03ea 100644 --- a/apps/faucet/src/utils/types.ts +++ b/apps/faucet/src/utils/types.ts @@ -8,6 +8,7 @@ export type SettingsResponse = { chain_id: string; start_at: number; tokens_alias_to_address: Record; + withdraw_limit: number; }; export type TransferDetails = { From e739d4b27513860822627b9e0449991b9af9a55a Mon Sep 17 00:00:00 2001 From: "Justin R. Evans" Date: Fri, 30 Aug 2024 09:56:29 -0400 Subject: [PATCH 4/4] fix: touch up styles --- apps/faucet/src/App/App.components.ts | 15 +++++++++++++++ apps/faucet/src/App/App.tsx | 13 ++++++++++++- .../faucet/src/App/Common/AppHeader.components.ts | 10 ---------- apps/faucet/src/App/Common/AppHeader.tsx | 10 ++-------- 4 files changed, 29 insertions(+), 19 deletions(-) diff --git a/apps/faucet/src/App/App.components.ts b/apps/faucet/src/App/App.components.ts index 7d3df94ca..e47bf5acb 100644 --- a/apps/faucet/src/App/App.components.ts +++ b/apps/faucet/src/App/App.components.ts @@ -153,6 +153,21 @@ export const ButtonContainer = styled.div` margin: 13px 0 0 0; `; +export const SettingsButtonContainer = styled.div` + display: flex; + align-items: center; + justify-content: flex-end; + width: 100%; +`; + +export const SettingsButton = styled.button` + & > svg { + width: 20px; + height: 20px; + color: ${(props) => props.theme.colors.primary.main20}; + } +`; + export const SettingsContainer = styled.div` flex-direction: column; justify-content: start; diff --git a/apps/faucet/src/App/App.tsx b/apps/faucet/src/App/App.tsx index 0dca1878c..5314cd835 100644 --- a/apps/faucet/src/App/App.tsx +++ b/apps/faucet/src/App/App.tsx @@ -1,4 +1,5 @@ import React, { createContext, useCallback, useEffect, useState } from "react"; +import { GoGear } from "react-icons/go"; import { ThemeProvider } from "styled-components"; import { ActionButton, Alert, Modal } from "@namada/components"; @@ -13,6 +14,8 @@ import { FaucetContainer, GlobalStyles, InfoContainer, + SettingsButton, + SettingsButtonContainer, TopSection, } from "App/App.components"; import { FaucetForm } from "App/Faucet"; @@ -122,7 +125,6 @@ export const App: React.FC = () => { ); useEffect(() => { - console.log("RECEIVED NEW URL, UPDATE API!", url); // Sync url to localStorage localStorage.setItem("baseUrl", url); const api = new API(url); @@ -207,6 +209,15 @@ export const App: React.FC = () => { + + setIsModalOpen(true)} + title="Settings" + > + + + + diff --git a/apps/faucet/src/App/Common/AppHeader.components.ts b/apps/faucet/src/App/Common/AppHeader.components.ts index 56c930b77..a3fae7d74 100644 --- a/apps/faucet/src/App/Common/AppHeader.components.ts +++ b/apps/faucet/src/App/Common/AppHeader.components.ts @@ -1,17 +1,7 @@ import styled from "styled-components"; export const AppHeaderContainer = styled.div` - width: 100%; display: flex; align-items: center; justify-content: center; `; - -export const SettingsButton = styled.a` - align-items: center; - justify-content: center; - width: 40px; - height: 40px; - color: ${(props) => props.theme.colors.primary.main20}; - cursor: pointer; -`; diff --git a/apps/faucet/src/App/Common/AppHeader.tsx b/apps/faucet/src/App/Common/AppHeader.tsx index c205fe46f..95ec56c21 100644 --- a/apps/faucet/src/App/Common/AppHeader.tsx +++ b/apps/faucet/src/App/Common/AppHeader.tsx @@ -1,19 +1,13 @@ import { Heading } from "@namada/components"; -import { AppContext } from "App/App"; -import React, { useContext } from "react"; -import { GoGear } from "react-icons/go"; -import { AppHeaderContainer, SettingsButton } from "./AppHeader.components"; +import React from "react"; +import { AppHeaderContainer } from "./AppHeader.components"; export const AppHeader: React.FC = () => { - const { setIsModalOpen } = useContext(AppContext)!; return ( Namada Faucet - setIsModalOpen(true)}> - - ); };