From c3a9e47a33deb484e9d8051a0cde07610f81ffa1 Mon Sep 17 00:00:00 2001 From: TrofimovAnton85 <98453427+TrofimovAnton85@users.noreply.github.com> Date: Wed, 10 Jul 2024 10:18:25 +0200 Subject: [PATCH] feat(reference): act-1327 - added support eip-6963 (#1389) * feat(reference): act-1327 - added support eip-6963 * feat(reference): remove selecte wallets --- .../ParserOpenRPC/AuthBox/index.tsx | 36 ++++++++++++-- .../ParserOpenRPC/AuthBox/styles.module.css | 34 +++++++++++++ src/components/ParserOpenRPC/index.tsx | 31 +++++++++--- src/hooks/store.ts | 49 +++++++++++++++++++ src/hooks/useSyncProviders.ts | 4 ++ wallet/reference/new-reference.mdx | 2 +- 6 files changed, 144 insertions(+), 12 deletions(-) create mode 100644 src/hooks/store.ts create mode 100644 src/hooks/useSyncProviders.ts diff --git a/src/components/ParserOpenRPC/AuthBox/index.tsx b/src/components/ParserOpenRPC/AuthBox/index.tsx index 37ed0492e3b..fd0eebde152 100644 --- a/src/components/ParserOpenRPC/AuthBox/index.tsx +++ b/src/components/ParserOpenRPC/AuthBox/index.tsx @@ -2,9 +2,12 @@ import React from "react"; import Link from "@docusaurus/Link"; import styles from "./styles.module.css"; import global from "../global.module.css"; +import { EIP6963ProviderDetail } from "@site/src/hooks/store.ts" interface AuthBoxProps { - isMetamaskInstalled: boolean; + metamaskProviders: any; + handleConnect: (i) => void; + selectedProvider?: number; } const MetamaskInstallMessage = () => ( @@ -15,10 +18,33 @@ const MetamaskInstallMessage = () => ( ); -export const AuthBox = ({ isMetamaskInstalled }: AuthBoxProps) => { +export const AuthBox = ({ metamaskProviders = [], selectedProvider, handleConnect }: AuthBoxProps) => { + if (metamaskProviders.length === 0) { + return + } + + if (metamaskProviders.length > 0) { + return null + } + return ( - <> - {!isMetamaskInstalled ? : null} - +
+

Select a MetaMask provider to use interactive features:

+
+ {metamaskProviders.map((provider: EIP6963ProviderDetail, i) => ( +
+ +
+ ))} +
+
); }; diff --git a/src/components/ParserOpenRPC/AuthBox/styles.module.css b/src/components/ParserOpenRPC/AuthBox/styles.module.css index c8562f6d322..d7d2a8e8eff 100644 --- a/src/components/ParserOpenRPC/AuthBox/styles.module.css +++ b/src/components/ParserOpenRPC/AuthBox/styles.module.css @@ -17,3 +17,37 @@ font-size: 14px; line-height: 22px; } + +.mmBtnRow { + display: flex; + flex-wrap: wrap; +} + +.mmBtnCol { + width: 100%; + margin-bottom: 10px; +} + +.mmBtn { + position: relative; + display: flex; + align-items: center; + padding: 16px 30px 16px 20px; + width: 100%; + background: none; + border-radius: 10px; + outline: none; + font-size: 16px; + font-weight: 500; + line-height: 22px; + border: 1px solid rgba(3, 118, 201, 1); + color: rgba(3, 118, 201, 1); +} + +.mmBtnCheck { + position: absolute; + top: 50%; + transform: translateY(-50%); + right: 15px; + font-size: 16px; +} diff --git a/src/components/ParserOpenRPC/index.tsx b/src/components/ParserOpenRPC/index.tsx index 7cd7d9f61a8..20bf5c87c40 100644 --- a/src/components/ParserOpenRPC/index.tsx +++ b/src/components/ParserOpenRPC/index.tsx @@ -17,6 +17,7 @@ import { trackInputChangeForSegment } from "@site/src/lib/segmentAnalytics"; import { useLocation } from "@docusaurus/router"; +import { useSyncProviders } from "@site/src/hooks/useSyncProviders.ts" interface ParserProps { network: NETWORK_NAMES; @@ -34,7 +35,6 @@ export const ParserOpenRPCContext = createContext { + setSelectedWallet(i); + } + useEffect(() => { - const installed = !!(window as any)?.ethereum; - setMetamaskInstalled(installed); trackPageViewForSegment({ name: "Reference page", path: location.pathname, @@ -100,6 +105,15 @@ export default function ParserOpenRPC({ network, method }: ParserProps) { }) }, []); + const metamaskProviders = useMemo(() => { + const isMetamasks = providers.filter(pr => pr?.info?.name?.includes("MetaMask")); + if (isMetamasks.length > 1) { + const indexWallet = isMetamasks.findIndex(item => item.info.name === "MetaMask"); + setSelectedWallet(indexWallet); + } + return isMetamasks; + }, [providers]); + const onParamsChangeHandle = (data) => { if (typeof data !== 'object' || data === null || Object.keys(data).length === 0) { setParamsData([]); @@ -112,8 +126,9 @@ export default function ParserOpenRPC({ network, method }: ParserProps) { } const onSubmitRequestHandle = async () => { + if (metamaskProviders.length === 0) return try { - const response = await (window as any).ethereum.request({ + const response = await metamaskProviders[selectedWallet].provider.request({ method: method, params: paramsData }) @@ -188,9 +203,13 @@ export default function ParserOpenRPC({ network, method }: ParserProps) {
- + 0} method={method} params={currentMethodData.params} paramsData={paramsData} diff --git a/src/hooks/store.ts b/src/hooks/store.ts new file mode 100644 index 00000000000..2556b9d107b --- /dev/null +++ b/src/hooks/store.ts @@ -0,0 +1,49 @@ +declare global{ + interface WindowEventMap { + "eip6963:announceProvider": CustomEvent + } +} + +export interface EIP6963ProviderInfo { + walletId: string; + uuid: string; + name: string; + icon: string; +} + +export interface EIP1193Provider { + isStatus?: boolean; + host?: string; + path?: string; + sendAsync?: (request: { method: string, params?: Array }, callback: (error: Error | null, response: unknown) => void) => void; + send?: (request: { method: string, params?: Array }, callback: (error: Error | null, response: unknown) => void) => void; + request: (request: { method: string, params?: Array }) => Promise; +} + +export interface EIP6963ProviderDetail { + info: EIP6963ProviderInfo; + provider: EIP1193Provider; +} + +type EIP6963AnnounceProviderEvent = { + detail: { + info: EIP6963ProviderInfo; + provider: EIP1193Provider; + } +} + +let providers: EIP6963ProviderDetail[] = [] +export const store = { + value: ()=> providers, + subscribe: (callback: ()=> void) => { + function onAnnouncement(event: EIP6963AnnounceProviderEvent){ + if(providers.map(p => p.info.uuid).includes(event.detail.info.uuid)) return + providers = [...providers, event.detail] + callback() + } + window.addEventListener("eip6963:announceProvider", onAnnouncement); + window.dispatchEvent(new Event("eip6963:requestProvider")); + + return () => window.removeEventListener("eip6963:announceProvider", onAnnouncement) + } +} \ No newline at end of file diff --git a/src/hooks/useSyncProviders.ts b/src/hooks/useSyncProviders.ts new file mode 100644 index 00000000000..b9db3eff98f --- /dev/null +++ b/src/hooks/useSyncProviders.ts @@ -0,0 +1,4 @@ +import { useSyncExternalStore } from "react"; +import { store } from "./store"; + +export const useSyncProviders = ()=> useSyncExternalStore(store.subscribe, store.value, store.value) \ No newline at end of file diff --git a/wallet/reference/new-reference.mdx b/wallet/reference/new-reference.mdx index cbbf4f7a0c6..5d209868a06 100644 --- a/wallet/reference/new-reference.mdx +++ b/wallet/reference/new-reference.mdx @@ -8,4 +8,4 @@ sidebar_class_name: "hidden" import ParserOpenRPC from "@site/src/components/ParserOpenRPC"; import { NETWORK_NAMES } from "@site/src/plugins/plugin-json-rpc"; - \ No newline at end of file + \ No newline at end of file