diff --git a/README.md b/README.md
index 90f89a7f934..5372b410df5 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,6 @@ Build the documentation site locally using the following steps.
### Prerequisites
- [Node.js](https://nodejs.org/) version 18+
-- [Yarn](https://yarnpkg.com/) version 3
- [Git](https://git-scm.com/)
### Steps
diff --git a/docusaurus.config.js b/docusaurus.config.js
index bf5cd242713..a63e234c787 100644
--- a/docusaurus.config.js
+++ b/docusaurus.config.js
@@ -199,6 +199,10 @@ const config = {
label: "Infura dashboard",
to: "developer-tools/dashboard",
},
+ {
+ label: "Faucet",
+ to: "developer-tools/faucet",
+ },
],
},
{
diff --git a/src/components/Accordion/accordion.module.scss b/src/components/Accordion/accordion.module.scss
new file mode 100644
index 00000000000..60e06d25f46
--- /dev/null
+++ b/src/components/Accordion/accordion.module.scss
@@ -0,0 +1,55 @@
+:root[data-theme="dark"] {
+ --accordion-background: #24272a;
+ --accordion-border: rgba(132, 140, 150, 0.16);
+}
+
+:root[data-theme="light"] {
+ --accordion-background: #ffffff;
+ --accordion-border: rgba(187, 192, 197, 0.4);
+}
+
+.accordion {
+ background: var(--accordion-background);
+ border: 1px solid var(--accordion-border);
+ border-radius: 8px;
+ margin-bottom: 24px;
+
+ .header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ cursor: pointer;
+
+ .closeButton {
+ cursor: pointer;
+ margin-left: 24px;
+ margin-right: 24px;
+ display: block;
+ height: 16px;
+ line-height: 1;
+
+ .image {
+ min-width: 16px;
+ width: 16px;
+ min-height: 16px;
+ height: 16px;
+ transition: all 0.5s;
+ transform: rotate(45deg);
+
+ &.opened {
+ transform: rotate(0);
+ }
+ }
+ }
+ }
+
+ .content {
+ visibility: hidden;
+ display: none;
+
+ &.opened {
+ visibility: visible;
+ display: block;
+ }
+ }
+}
diff --git a/src/components/Accordion/close.svg b/src/components/Accordion/close.svg
new file mode 100644
index 00000000000..afe93c72b6f
--- /dev/null
+++ b/src/components/Accordion/close.svg
@@ -0,0 +1,4 @@
+
diff --git a/src/components/Accordion/index.tsx b/src/components/Accordion/index.tsx
new file mode 100644
index 00000000000..8b55e24d218
--- /dev/null
+++ b/src/components/Accordion/index.tsx
@@ -0,0 +1,52 @@
+import React, { useState } from "react";
+import clsx from "clsx";
+import styles from "./accordion.module.scss";
+import CloseImg from "./close.svg";
+import { trackClickForSegment } from "@site/src/lib/segmentAnalytics";
+
+interface IAccordion {
+ children: [React.ReactElement, React.ReactElement];
+ opened?: boolean;
+}
+
+export default function Accordion({
+ children: [title, body],
+ opened = false,
+}: IAccordion) {
+ const [isOpened, setIsOpened] = useState(opened);
+
+ const handleToggle = () => {
+ trackClickForSegment({
+ eventName: `${isOpened ? "Expanded" : "Collapsed"} - ${title}`,
+ clickType: "Accordion",
+ userExperience: "B",
+ responseStatus: null,
+ responseMsg: null,
+ timestamp: Date.now(),
+ });
+ setIsOpened((value) => !value);
+ };
+
+ return (
+
+
+ {title}
+
+
+
+
+
+ {body}
+
+
+ );
+}
diff --git a/src/components/Alert/index.tsx b/src/components/Alert/index.tsx
index e7e90cfc8bf..9ea7acb3f8d 100644
--- a/src/components/Alert/index.tsx
+++ b/src/components/Alert/index.tsx
@@ -7,6 +7,7 @@ import SuccessImg from "./success.svg";
import ErrorImg from "./error.svg";
import Text from "@site/src/components/Text";
import styles from "./alert.module.scss";
+import { trackClickForSegment } from "@site/src/lib/segmentAnalytics";
export const options = {
position: positions.TOP_CENTER,
@@ -18,25 +19,44 @@ export const options = {
},
};
-export const AlertTemplate = ({ style, options, message, close }) => (
-
- {options.type === types.INFO && }
- {options.type === types.SUCCESS && }
- {options.type === types.ERROR && }
- {message}
-
-
-
-
-);
+export const AlertTemplate = ({ style, options, message, close }) => {
+ const handleCloseAlert = () => {
+ trackClickForSegment({
+ eventName: "Close",
+ clickType: "Alert",
+ userExperience: "B",
+ responseStatus: null,
+ responseMsg: null,
+ timestamp: Date.now(),
+ });
+ close();
+ };
+
+ return (
+
+ {options.type === types.INFO && }
+ {options.type === types.SUCCESS && }
+ {options.type === types.ERROR && }
+ {message}
+
+
+
+
+ );
+};
export const AlertTitle = ({
children,
diff --git a/src/components/AuthLogin/AuthModal.tsx b/src/components/AuthLogin/AuthModal.tsx
index 689865c67f8..2cbd4021e39 100644
--- a/src/components/AuthLogin/AuthModal.tsx
+++ b/src/components/AuthLogin/AuthModal.tsx
@@ -7,15 +7,14 @@ import global from "../ParserOpenRPC/global.module.css";
import Icon from "../Icon/Icon";
import {
authenticateAndAuthorize,
+ AUTH_WALLET_PAIRING,
+ AUTH_WALLET_SESSION_NAME,
+ AUTH_WALLET_PROJECTS,
saveTokenString,
getUserIdFromJwtToken,
+ AUTH_WALLET_USER_PLAN,
} from "../../lib/siwsrp/auth";
-import {
- DASHBOARD_URL,
- REQUEST_PARAMS,
- AUTH_WALLET_SESSION_NAME,
- AUTH_WALLET_PROJECTS,
-} from "@site/src/lib/constants";
+import { DASHBOARD_URL, REQUEST_PARAMS } from "@site/src/lib/constants";
import { MetamaskProviderContext } from "@site/src/theme/Root";
Modal.setAppElement("#__docusaurus");
@@ -23,8 +22,10 @@ type AuthModalProps = {
open: boolean;
setOpen: (arg: boolean) => void;
setUser: (arg: string) => void;
+ setToken: (arg: string) => void;
step: AUTH_LOGIN_STEP;
setStep: (arg: AUTH_LOGIN_STEP) => void;
+ setUksTier: (arg: string) => void;
};
export enum AUTH_LOGIN_STEP {
@@ -134,7 +135,15 @@ const ConnectionErrorModal = ({
);
};
-const AuthModal = ({ open, setOpen, step, setStep }: AuthModalProps) => {
+const AuthModal = ({
+ open,
+ setOpen,
+ step,
+ setStep,
+ setUser,
+ setToken,
+ setUksTier,
+}: AuthModalProps) => {
const { siteConfig } = useDocusaurusContext();
const { DASHBOARD_PREVIEW_URL, VERCEL_ENV } = siteConfig?.customFields || {};
const {
@@ -168,30 +177,29 @@ const AuthModal = ({ open, setOpen, step, setStep }: AuthModalProps) => {
// Call Profile SDK API to retrieve Hydra Access Token & Wallet userProfile
// Hydra Access Token will be used to fetch Infura API
const { accessToken, userProfile } = await authenticateAndAuthorize(
- VERCEL_ENV as string
+ VERCEL_ENV as string,
);
const loginResponse = await (
await fetch(
`${DASHBOARD_URL(DASHBOARD_PREVIEW_URL, VERCEL_ENV)}/api/wallet/login`,
{
- ...REQUEST_PARAMS(),
- headers: {
- ...REQUEST_PARAMS().headers,
+ ...REQUEST_PARAMS("POST", {
hydra_token: accessToken,
token: "true",
- },
+ }),
body: JSON.stringify({
profileId: userProfile.profileId,
redirect_to: window.location.href,
}),
- }
+ },
)
).json();
if (!loginResponse) throw new Error("Something went wrong");
const { data, session, token } = loginResponse;
+ localStorage.setItem(AUTH_WALLET_PAIRING, JSON.stringify({ data }));
if (data.step) {
// Handling no wallet pairing or multiple pairing
@@ -201,7 +209,7 @@ const AuthModal = ({ open, setOpen, step, setStep }: AuthModalProps) => {
mmAuthSession: localStorage.getItem(AUTH_WALLET_SESSION_NAME),
walletPairing: data.pairing,
token: true,
- })
+ }),
).toString("base64");
const walletLinkUrl = `${DASHBOARD_URL(DASHBOARD_PREVIEW_URL, VERCEL_ENV)}/login?mm_auth=${mm_auth}&redirect_to=${session.redirect_to}`;
@@ -229,25 +237,43 @@ const AuthModal = ({ open, setOpen, step, setStep }: AuthModalProps) => {
}
saveTokenString(token);
+ if (setToken) {
+ setToken(token);
+ }
setStep(AUTH_LOGIN_STEP.CONNECTION_SUCCESS);
const userId = getUserIdFromJwtToken();
+ if (setUser) {
+ setUser(userId);
+ }
// You can use Infura Access Token to fetch any Infura API endpoint
const projectsResponse = await fetch(
`${DASHBOARD_URL(DASHBOARD_PREVIEW_URL, VERCEL_ENV)}/api/v1/users/${userId}/projects`,
{
- ...REQUEST_PARAMS("GET"),
- headers: {
- ...REQUEST_PARAMS("GET").headers,
- Authorization: `Bearer ${token}`,
- },
- }
+ ...REQUEST_PARAMS("GET", { Authorization: `Bearer ${token}` }),
+ },
);
const {
result: { projects },
} = await projectsResponse.json();
sessionStorage.setItem(AUTH_WALLET_PROJECTS, JSON.stringify(projects));
setProjects(projects);
+
+ const uksUserRawResp = await fetch(
+ `${DASHBOARD_URL(DASHBOARD_PREVIEW_URL, VERCEL_ENV)}/api/v1/users/${userId}`,
+ {
+ ...REQUEST_PARAMS("GET", { Authorization: `Bearer ${token}` }),
+ },
+ );
+ const {
+ result: {
+ servicePlan: { tier },
+ },
+ } = await uksUserRawResp.json();
+ sessionStorage.setItem(AUTH_WALLET_USER_PLAN, JSON.stringify(tier));
+ if (setUser) {
+ setUksTier(tier);
+ }
setOpen(false);
} catch (e: any) {
if (pathname.startsWith("/wallet/reference")) {
diff --git a/src/components/Badge/badge.module.scss b/src/components/Badge/badge.module.scss
new file mode 100644
index 00000000000..363bdcb8367
--- /dev/null
+++ b/src/components/Badge/badge.module.scss
@@ -0,0 +1,46 @@
+:root {
+ --badge-default-color: #6a737d;
+ --badge-default-bg-color: #f2f4f6;
+ --badge-default-border-color: transparent;
+ --badge-success-color: #1c8234;
+ --badge-success-bg-color: rgba(28, 130, 52, 0.1);
+ --badge-error-color: #d73847;
+ --badge-error-bg-color: rgba(215, 56, 71, 0.1);
+}
+
+:root[data-theme="dark"] {
+ --badge-default-color: #bbc0c5;
+ --badge-default-bg-color: #24272a;
+ --badge-default-border-color: #bbc0c5;
+ --badge-success-color: #28a745;
+ --badge-success-bg-color: rgba(40, 167, 69, 0.15);
+ --badge-error-color: #e06470;
+ --badge-error-bg-color: rgba(224, 100, 112, 0.15);
+}
+
+.badge {
+ display: inline-flex;
+ align-items: center;
+ font-size: 12px;
+ line-height: 20px;
+ font-weight: 500;
+ letter-spacing: 0.25px;
+ border-radius: 999px;
+ border: 1px solid var(--badge-default-border-color);
+ padding: 2px 8px;
+ color: var(--badge-default-color);
+ background-color: var(--badge-default-bg-color);
+ text-transform: capitalize;
+
+ &.success {
+ color: var(--badge-success-color);
+ background-color: var(--badge-success-bg-color);
+ border-color: transparent;
+ }
+
+ &.error {
+ color: var(--badge-error-color);
+ background-color: var(--badge-error-bg-color);
+ border-color: transparent;
+ }
+}
diff --git a/src/components/Badge/index.tsx b/src/components/Badge/index.tsx
new file mode 100644
index 00000000000..a0c14c7cec4
--- /dev/null
+++ b/src/components/Badge/index.tsx
@@ -0,0 +1,14 @@
+import React from "react";
+import styles from "./badge.module.scss";
+import clsx from "clsx";
+
+type variant = "error" | "success" | "default";
+
+interface IBadge {
+ variant?: variant;
+ label: string;
+}
+
+export default function Badge({ variant = "default", label }: IBadge) {
+ return {label};
+}
diff --git a/src/components/Button/button.module.scss b/src/components/Button/button.module.scss
index 46674966a0f..de71208ae00 100644
--- a/src/components/Button/button.module.scss
+++ b/src/components/Button/button.module.scss
@@ -1,6 +1,7 @@
:root[data-theme="dark"] {
--button-primary-background-color: #1098fc;
--button-secondary-background-color: transparent;
+ --button-background-color: #1098fc;
--button-color: #141618;
--button-hover-background-color: #036ab5;
--button-hover-shadow: 0px 2px 8px 0px rgba(16, 152, 252, 0.4);
@@ -11,6 +12,7 @@
:root[data-theme="light"] {
--button-primary-background-color: #0376c9;
--button-secondary-background-color: transparent;
+ --button-background-color: #0376c9;
--button-color: #ffffff;
--button-hover-background-color: #036ab5;
--button-hover-shadow: 0px 2px 8px 0px rgba(3, 118, 201, 0.2);
@@ -35,6 +37,7 @@ a.button {
.button {
color: var(--button-color);
+ background-color: var(--button-background-color);
border: none;
padding: 0 16px;
height: 48px;
diff --git a/src/components/Button/index.tsx b/src/components/Button/index.tsx
index 3178f1ddc22..8fea17e551a 100644
--- a/src/components/Button/index.tsx
+++ b/src/components/Button/index.tsx
@@ -5,6 +5,7 @@ import clsx from "clsx";
import styles from "./button.module.scss";
interface IButton {
+ testId?: string;
onClick?: VoidFunction;
children: string | React.ReactElement;
disabled?: boolean;
@@ -20,6 +21,7 @@ interface IButton {
}
export const Button = ({
+ testId,
className,
onClick = () => {},
children,
@@ -50,6 +52,7 @@ export const Button = ({
return !href ? (