diff --git a/src/components/Button/button.module.scss b/src/components/Button/button.module.scss
index 4c54487586c..b92f953d68a 100644
--- a/src/components/Button/button.module.scss
+++ b/src/components/Button/button.module.scss
@@ -1,14 +1,16 @@
:root[data-theme="dark"] {
- --button-background-color: #1098fc;
+ --button-primary-background-color: #1098fc;
+ --button-secondary-background-color: transparent;
--button-color: #141618;
- --button-hover-background-color: #26a2fc;
+ --button-hover-background-color: #036ab5;
--button-hover-shadow: 0px 2px 8px 0px rgba(16, 152, 252, 0.4);
--button-active-background-color: #3baafd;
--button-danger: #e88f97
}
:root[data-theme="light"] {
- --button-background-color: #0376c9;
+ --button-primary-background-color: #0376c9;
+ --button-secondary-background-color: transparent;
--button-color: #ffffff;
--button-hover-background-color: #036ab5;
--button-hover-shadow: 0px 2px 8px 0px rgba(3, 118, 201, 0.2);
@@ -33,7 +35,6 @@ a.button {
.button {
color: var(--button-color);
- background-color: var(--button-background-color);
border: none;
padding: 0 16px;
height: 48px;
@@ -47,6 +48,19 @@ a.button {
align-items: center;
min-width: 145px;
+ &.primary {
+ background-color: var(--button-primary-background-color);
+ }
+
+ &.secondary {
+ border: 1px solid rgba(3, 118, 201, 1);
+ --button-color: rgba(3, 118, 201, 1);
+ background-color: var(--button-secondary-background-color);
+ &:hover {
+ --button-color: #141618
+ }
+ }
+
&:hover {
background-color: var(--button-hover-background-color);
box-shadow: var(--button-hover-shadow);
@@ -78,6 +92,14 @@ a.button {
pointer-events: none;
}
+ &.nowrap {
+ white-space: nowrap;
+ }
+
+ &.textLight {
+ color: #ffffff;
+ }
+
.isLoading {
animation: spinner-infinite 1.2s linear infinite;
}
diff --git a/src/components/Button/index.tsx b/src/components/Button/index.tsx
index f2c1d1d4e4e..3178f1ddc22 100644
--- a/src/components/Button/index.tsx
+++ b/src/components/Button/index.tsx
@@ -14,6 +14,9 @@ interface IButton {
target?: string;
thin?: boolean;
type?: "default" | "danger";
+ variant?: "primary" | "secondary";
+ wrapText?: boolean;
+ textColor?: "dark" | "light",
}
export const Button = ({
@@ -26,11 +29,17 @@ export const Button = ({
target = "_blank",
thin = false,
type = "default",
+ variant="primary",
+ wrapText = true,
+ textColor = "dark"
}: IButton) => {
const buttonRootClass = clsx(
styles.button,
thin && styles.thin,
type === "danger" && styles.danger,
+ variant === "primary" ? styles.primary : styles.secondary,
+ !wrapText && styles.nowrap,
+ textColor === "light" && styles.textLight,
className,
);
const isLoadingChild = !isLoading ? (
diff --git a/src/components/NavbarWallet/index.tsx b/src/components/NavbarWallet/index.tsx
index 260bd5d6c20..ae70b4c5b7e 100644
--- a/src/components/NavbarWallet/index.tsx
+++ b/src/components/NavbarWallet/index.tsx
@@ -69,6 +69,7 @@ const NavbarWalletComponent: FC = ({
thin
onClick={metaMaskWalletIdConnectHandler}
className={styles.navbarButton}
+ textColor="light"
>
{!isExtensionActive ? "Install MetaMask" : "Connect MetaMask"}
diff --git a/src/components/ParserOpenRPC/ProjectsBox/index.tsx b/src/components/ParserOpenRPC/ProjectsBox/index.tsx
index a1ab614ceff..52f2713165d 100644
--- a/src/components/ParserOpenRPC/ProjectsBox/index.tsx
+++ b/src/components/ParserOpenRPC/ProjectsBox/index.tsx
@@ -3,7 +3,7 @@ import ldClient from "launchdarkly";
import { MetamaskProviderContext } from "@site/src/theme/Root";
import Select from "react-dropdown-select";
import Button from "@site/src/components/Button";
-import styles from "./styles.module.css";
+import styles from "./styles.module.scss";
import { WALLET_LINK_TYPE } from "@site/src/components/AuthLogin/AuthModal";
const LOGIN_FF = "mm-unified-login";
@@ -15,6 +15,7 @@ const ProjectsBox = () => {
walletLinked,
metaMaskWalletIdConnectHandler,
walletLinkUrl,
+ setUserAPIKey,
} = useContext(MetamaskProviderContext);
const options = Object.keys(projects).map((v) => ({
value: v,
@@ -25,6 +26,12 @@ const ProjectsBox = () => {
);
const [ldReady, setLdReady] = useState(false);
const [loginEnabled, setLoginEnabled] = useState(false);
+ const [isWalletLinking, setIsWalletLinking] = useState(false);
+
+ const metaMaskWalletConnectionHandler = () => {
+ setIsWalletLinking(true);
+ metaMaskWalletIdConnectHandler();
+ }
useEffect(() => {
ldClient.waitUntilReady().then(() => {
@@ -41,9 +48,24 @@ const ProjectsBox = () => {
}, []);
useEffect(() => {
- if (!currentProject.length && options[0]) setCurrentProject([options[0]]);
+ if (!currentProject.length && options[0]) {
+ setCurrentProject([options[0]]);
+ setUserAPIKey(options[0].value);
+ }
}, [projects]);
+ useEffect(() => {
+ if (options?.length > 0) {
+ setUserAPIKey(options[0].value);
+ }
+ }, [options.length]);
+
+ useEffect(() => {
+ if (walletLinked) {
+ setIsWalletLinking(false);
+ }
+ }, [walletLinked])
+
return (
ldReady &&
loginEnabled && (
@@ -57,14 +79,17 @@ const ProjectsBox = () => {
searchable={false}
options={options}
values={currentProject}
- onChange={(value) => setCurrentProject(value)}
+ onChange={(value) => {
+ setCurrentProject(value);
+ setUserAPIKey(value[0].value);
+ }}
contentRenderer={({ state }) => {
return (
{state.values.map((item) => (
-
{item.label}
-
{item.value}
+
{item.label}
+
{item.value}
))}
@@ -75,12 +100,12 @@ const ProjectsBox = () => {
{options.map((option) => (
methods.addItem(option)}
>
-
{option.label}
-
{option.value}
+
{option.label}
+
{option.value}
))}
@@ -92,13 +117,17 @@ const ProjectsBox = () => {
{walletLinked === undefined && (
<>
- Connect your MetaMask wallet to start sending requests to your
- Infura API keys.
+ {isWalletLinking ?
+ "Don’t close or exit this page. Please continue connecting on your extension." :
+ "Connect your MetaMask wallet to start sending requests to your Infura API keys."
+ }
Connect Wallet
@@ -112,7 +141,8 @@ const ProjectsBox = () => {
(window.location.href = walletLinkUrl)}
>
Link Infura Account
diff --git a/src/components/ParserOpenRPC/ProjectsBox/styles.module.css b/src/components/ParserOpenRPC/ProjectsBox/styles.module.css
deleted file mode 100644
index 956c3e2342e..00000000000
--- a/src/components/ParserOpenRPC/ProjectsBox/styles.module.css
+++ /dev/null
@@ -1,40 +0,0 @@
-.selectWrapper {
- padding: 0 0 24px 0;
-}
-
-.selectTitle {
-font-size: 16px;
-font-weight: 500;
-line-height: 24px;
-text-align: left;
-padding: 0 0 8px 0;
-}
-
-.selectProjects {
- border: 1px solid #848C96 !important;
- border-radius: 8px !important;
- padding: 12px 16px 12px 16px !important;
- font-size: 16px !important;
- display: flex;
- justify-content: center;
- flex-direction: grid;
- justify-content: center;
- align-items: center;
-}
-
-.selectDropdown {
- border: 1px solid #848C96 !important;
- border-radius: 8px !important;
- padding: 12px 16px 12px 16px !important;
- font-size: 16px !important;
-}
-
-.selectDropdown {
- padding: 4px 0 !important;
-}
-
-.connectButton {
- order: 100;
- margin-left: 12px;
- text-wrap: nowrap;
-}
\ No newline at end of file
diff --git a/src/components/ParserOpenRPC/ProjectsBox/styles.module.scss b/src/components/ParserOpenRPC/ProjectsBox/styles.module.scss
new file mode 100644
index 00000000000..ec7a7f13dbb
--- /dev/null
+++ b/src/components/ParserOpenRPC/ProjectsBox/styles.module.scss
@@ -0,0 +1,56 @@
+:root {
+ --select-bg: #24272A;
+ --select-value-color: #BBC0C5;
+}
+
+.selectWrapper {
+ padding: 0 0 24px 0;
+}
+
+.selectTitle {
+ font-size: 16px;
+ font-weight: 500;
+ line-height: 24px;
+ text-align: left;
+ padding: 0 0 8px 0;
+}
+
+.selectProjects {
+ border: 1px solid #848C96 !important;
+ border-radius: 8px !important;
+ padding: 12px 16px 12px 16px !important;
+ font-size: 16px !important;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ background-color: var(--select-bg);
+ color: #ffffff;
+}
+
+.selectDropdown {
+ border-radius: 8px !important;
+ font-size: 16px !important;
+}
+
+.selectDropdownOption {
+ background-color: var(--select-bg);
+ padding: 8px 16px;
+ &:hover {
+ background-color: #000000;
+ }
+}
+
+.selectDropdownValue {
+ font-size: 14px;
+ color: var(--select-value-color);
+}
+
+.selectDropdownLabel {
+ color: #ffffff;
+}
+
+.connectButton {
+ order: 100;
+ margin-left: 12px;
+ font-weight: 500;
+}
\ No newline at end of file
diff --git a/src/components/ParserOpenRPC/RequestBox/index.tsx b/src/components/ParserOpenRPC/RequestBox/index.tsx
index c55b9ad1770..2acceadcb35 100644
--- a/src/components/ParserOpenRPC/RequestBox/index.tsx
+++ b/src/components/ParserOpenRPC/RequestBox/index.tsx
@@ -1,10 +1,12 @@
-import React, { useMemo } from "react";
+import React, { useContext, useMemo } from "react";
import clsx from "clsx";
import CodeBlock from "@theme/CodeBlock";
import { MethodParam } from "@site/src/components/ParserOpenRPC/interfaces";
import styles from "./styles.module.css";
import global from "../global.module.css";
import { Tooltip } from "@site/src/components/Tooltip";
+import { MetamaskProviderContext } from "@site/src/theme/Root";
+import { LINEA_REQUEST_URL } from "@site/src/lib/constants";
interface RequestBoxProps {
isMetamaskInstalled: boolean;
@@ -31,17 +33,16 @@ export default function RequestBox({
defExampleResponse,
resetResponseHandle,
}: RequestBoxProps) {
-
+ const { userAPIKey } = useContext(MetamaskProviderContext);
const exampleRequest = useMemo(() => {
const preparedParams = JSON.stringify(paramsData, null, 2);
const preparedShellParams = JSON.stringify(paramsData);
- const NETWORK_URL = "https://linea-mainnet.infura.io";
- const API_KEY = "";
+ const API_KEY = userAPIKey ? userAPIKey : "";
if (isMetamaskNetwork) {
return `await window.ethereum.request({\n "method": "${method}",\n "params": ${preparedParams.replace(/"([^"]+)":/g, '$1:')},\n});`;
}
- return `curl ${NETWORK_URL}/v3/${API_KEY} \\\n -X POST \\\n -H "Content-Type: application/json" \\\n -d '{\n "jsonrpc": "2.0",\n "method": "${method}",\n "params": ${preparedShellParams},\n "id": 1\n }'`;
- }, [method, paramsData]);
+ return `curl ${LINEA_REQUEST_URL}/v3/${API_KEY} \\\n -X POST \\\n -H "Content-Type: application/json" \\\n -d '{\n "jsonrpc": "2.0",\n "method": "${method}",\n "params": ${preparedShellParams},\n "id": 1\n }'`;
+ }, [userAPIKey, method, paramsData]);
const exampleResponse = useMemo(() => {
if (defExampleResponse && response === undefined) {
diff --git a/src/components/ParserOpenRPC/index.tsx b/src/components/ParserOpenRPC/index.tsx
index f665172c525..94b9d9dac80 100644
--- a/src/components/ParserOpenRPC/index.tsx
+++ b/src/components/ParserOpenRPC/index.tsx
@@ -18,7 +18,7 @@ import {
import { AuthBox } from "@site/src/components/ParserOpenRPC/AuthBox";
import { MetamaskProviderContext } from "@site/src/theme/Root";
import ProjectsBox from "@site/src/components/ParserOpenRPC/ProjectsBox";
-import { REF_PATH } from "@site/src/lib/constants";
+import { LINEA_REQUEST_URL, REF_PATH } from "@site/src/lib/constants";
interface ParserProps {
network: NETWORK_NAMES;
@@ -51,11 +51,17 @@ export default function ParserOpenRPC({
const [isDrawerContentFixed, setIsDrawerContentFixed] = useState(false);
const [drawerLabel, setDrawerLabel] = useState(null);
const [isComplexTypeView, setIsComplexTypeView] = useState(false);
+ const { metaMaskAccount, metaMaskProvider, userAPIKey } = useContext(MetamaskProviderContext);
const [defExampleResponse, setDefExampleResponse] = useState(undefined);
- const { metaMaskAccount, metaMaskProvider } = useContext(
- MetamaskProviderContext
- );
const { colorMode } = useColorMode();
+ const trackAnalyticsForRequest = (response) => {
+ trackClickForSegment({
+ eventName: "Request Sent",
+ clickType: "Request Sent",
+ userExperience: "B",
+ ...(response?.code && { responseStatus: response.code }),
+ });
+ }
const openModal = () => {
setModalOpen(true);
trackClickForSegment({
@@ -169,21 +175,38 @@ export default function ParserOpenRPC({
};
const onSubmitRequestHandle = async () => {
- if (!metaMaskProvider) return;
- try {
- const response = await metaMaskProvider?.request({
- method: method,
- params: paramsData,
- });
- setReqResult(response);
- trackClickForSegment({
- eventName: "Request Sent",
- clickType: "Request Sent",
- userExperience: "B",
- ...(response?.code && { responseStatus: response.code }),
- });
- } catch (e) {
- setReqResult(e);
+ if (isMetamaskNetwork) {
+ if (!metaMaskProvider) return
+ try {
+ const response = await metaMaskProvider?.request({
+ method: method,
+ params: paramsData
+ })
+ setReqResult(response);
+ trackAnalyticsForRequest(response);
+ } catch (e) {
+ setReqResult(e);
+ }
+ } else {
+ const URL = `${LINEA_REQUEST_URL}/v3/${userAPIKey}`;
+ let params = {
+ method: "POST",
+ "Content-Type": "application/json",
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ method,
+ params: paramsData,
+ id: 1,
+ }),
+ };
+ const res = await fetch(URL, params);
+ if (res.ok) {
+ const response = await res.json();
+ setReqResult(response.result);
+ trackAnalyticsForRequest(response.result);
+ } else {
+ console.error("error");
+ }
}
};
diff --git a/src/css/custom.css b/src/css/custom.css
index ffa31bd7b37..17dd333a0a6 100644
--- a/src/css/custom.css
+++ b/src/css/custom.css
@@ -341,6 +341,15 @@ button:hover {
border-bottom-color: rgba(255, 255, 255, 1);
}
+.react-dropdown-select-dropdown {
+ border-radius: 8px !important;
+ border: 1px solid #848C96 !important;
+}
+
+.react-dropdown-select-dropdown-handle {
+ color: #ffffff;
+}
+
@media (max-width: 1200px) {
.navbar__item,
.navbar__link {
diff --git a/src/lib/constants.js b/src/lib/constants.js
index db899f68212..f10a18bdc57 100644
--- a/src/lib/constants.js
+++ b/src/lib/constants.js
@@ -474,3 +474,8 @@ export const REQUEST_PARAMS = (method = "POST") => ({
export const AUTH_WALLET_SESSION_NAME = "auth.wallet.session";
export const AUTH_WALLET_TOKEN = "auth.wallet.token";
export const AUTH_WALLET_PROJECTS = "auth.wallet.projects";
+export const LINEA_DEV_URL = "https://linea-mainnet.dev.infura.org";
+export const LINEA_PROD_URL = "https://linea-mainnet.infura.io";
+export const LINEA_REQUEST_URL = process.env.VERCEL_ENV === "production"
+ ? LINEA_PROD_URL
+ : LINEA_DEV_URL;
diff --git a/src/theme/Root.tsx b/src/theme/Root.tsx
index b97de5b208d..f6ea1acd791 100644
--- a/src/theme/Root.tsx
+++ b/src/theme/Root.tsx
@@ -56,6 +56,8 @@ interface IMetamaskProviderContext {
walletLinked: WALLET_LINK_TYPE | undefined;
setWalletLinkUrl: (arg: string) => void;
walletLinkUrl: string;
+ userAPIKey?: string;
+ setUserAPIKey?: (key: string) => void;
}
export const MetamaskProviderContext = createContext({
@@ -74,6 +76,8 @@ export const MetamaskProviderContext = createContext({
walletLinked: undefined,
setWalletLinkUrl: () => {},
walletLinkUrl: "",
+ userAPIKey: "",
+ setUserAPIKey: () => {},
});
const sdk = new MetaMaskSDK({
@@ -101,6 +105,7 @@ export const LoginProvider = ({ children }) => {
WALLET_LINK_TYPE | undefined
>(undefined);
const [walletLinkUrl, setWalletLinkUrl] = useState("");
+ const [userAPIKey, setUserAPIKey] = useState("");
const { siteConfig } = useDocusaurusContext();
const { DASHBOARD_PREVIEW_URL, VERCEL_ENV } = siteConfig?.customFields || {};
@@ -197,6 +202,7 @@ export const LoginProvider = ({ children }) => {
setMetaMaskAccount(undefined);
setProjects({});
setWalletLinked(undefined);
+ setUserAPIKey("");
clearStorage();
} catch (err) {
console.warn("failed to disconnect..", err);
@@ -223,6 +229,8 @@ export const LoginProvider = ({ children }) => {
setWalletLinked,
walletLinkUrl,
setWalletLinkUrl,
+ userAPIKey,
+ setUserAPIKey,
} as IMetamaskProviderContext
}
>