fix: dapps metadata (#96)

* fix: metadata to react-dapp-v2

* fix: metadata react app with ethers

* fix: metadata react app with web3

* feat: adds web3modal to web3 example dapp

* feat: adds web3modal to ethers example dapp
This commit is contained in:
Gancho Radkov 2022-12-22 11:34:36 +02:00 committed by GitHub
parent 7a3886073b
commit c7890ae0b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 165 additions and 88 deletions

View File

@ -30,10 +30,10 @@
"dependencies": {
"@ethereumjs/tx": "^3.5.0",
"@walletconnect/encoding": "^1.0.1",
"@walletconnect/qrcode-modal": "^1.7.1",
"@walletconnect/types": "^2.1.1",
"@walletconnect/universal-provider": "^2.1.1",
"@walletconnect/utils": "^2.1.1",
"@walletconnect/types": "^2.1.4",
"@walletconnect/universal-provider": "^2.1.4",
"@walletconnect/utils": "^2.1.4",
"@web3modal/standalone": "^2.0.0-beta.10",
"axios": "^0.21.1",
"blockies-ts": "^1.0.0",
"caip-api": "^2.0.0-beta.1",

View File

@ -0,0 +1,17 @@
import Head from "next/head";
import * as React from "react";
import { DEFAULT_APP_METADATA } from "../constants";
const Metadata = () => (
<Head>
<title>{DEFAULT_APP_METADATA.name}</title>
<meta name="description" content={DEFAULT_APP_METADATA.description} />
<meta name="url" content={DEFAULT_APP_METADATA.url} />
{DEFAULT_APP_METADATA.icons.map((icon, index) => (
<link key={index} rel="icon" href={icon} />
))}
</Head>
);
export default Metadata;

View File

@ -33,7 +33,7 @@ export enum DEFAULT_EIP_155_EVENTS {
export const DEFAULT_LOGGER = "debug";
export const DEFAULT_APP_METADATA = {
name: "React App",
name: "React App with ethers",
description: "React App for WalletConnect",
url: "https://walletconnect.com/",
icons: ["https://avatars.githubusercontent.com/u/37784886"],

View File

@ -8,7 +8,7 @@ import {
useState,
} from "react";
import QRCodeModal from "@walletconnect/qrcode-modal";
import { Web3Modal } from "@web3modal/standalone";
import { apiGetChainNamespace, ChainsMap } from "caip-api";
import UniversalProvider from "@walletconnect/universal-provider";
import { PairingTypes, SessionTypes } from "@walletconnect/types";
@ -62,6 +62,7 @@ export function ClientContextProvider({ children }: { children: ReactNode | Reac
const [accounts, setAccounts] = useState<string[]>([]);
const [chainData, setChainData] = useState<ChainNamespaces>({});
const [chain, setChain] = useState<string>("");
const [web3Modal, setWeb3Modal] = useState<Web3Modal>();
const resetApp = () => {
setPairings([]);
@ -98,46 +99,47 @@ export function ClientContextProvider({ children }: { children: ReactNode | Reac
resetApp();
}, [ethereumProvider]);
const _subscribeToProviderEvents = useCallback(async (_client: UniversalProvider) => {
if (typeof _client === "undefined") {
throw new Error("WalletConnect is not initialized");
}
const _subscribeToProviderEvents = useCallback(
async (_client: UniversalProvider) => {
if (typeof _client === "undefined") {
throw new Error("WalletConnect is not initialized");
}
_client.on("display_uri", async (uri: string) => {
console.log("EVENT", "QR Code Modal open");
QRCodeModal.open(uri, () => {
console.log("EVENT", "QR Code Modal closed");
_client.on("display_uri", async (uri: string) => {
console.log("EVENT", "QR Code Modal open");
web3Modal?.openModal({ uri });
});
});
// Subscribe to session ping
_client.on("session_ping", ({ id, topic }: { id: number; topic: string }) => {
console.log("EVENT", "session_ping");
console.log(id, topic);
});
// Subscribe to session ping
_client.on("session_ping", ({ id, topic }: { id: number; topic: string }) => {
console.log("EVENT", "session_ping");
console.log(id, topic);
});
// Subscribe to session event
_client.on("session_event", ({ event, chainId }: { event: any; chainId: string }) => {
console.log("EVENT", "session_event");
console.log(event, chainId);
});
// Subscribe to session event
_client.on("session_event", ({ event, chainId }: { event: any; chainId: string }) => {
console.log("EVENT", "session_event");
console.log(event, chainId);
});
// Subscribe to session update
_client.on(
"session_update",
({ topic, session }: { topic: string; session: SessionTypes.Struct }) => {
console.log("EVENT", "session_updated");
setSession(session);
},
);
// Subscribe to session update
_client.on(
"session_update",
({ topic, session }: { topic: string; session: SessionTypes.Struct }) => {
console.log("EVENT", "session_updated");
setSession(session);
},
);
// Subscribe to session delete
_client.on("session_delete", ({ id, topic }: { id: number; topic: string }) => {
console.log("EVENT", "session_deleted");
console.log(id, topic);
resetApp();
});
}, []);
// Subscribe to session delete
_client.on("session_delete", ({ id, topic }: { id: number; topic: string }) => {
console.log("EVENT", "session_deleted");
console.log(id, topic);
resetApp();
});
},
[web3Modal],
);
const createClient = useCallback(async () => {
try {
@ -149,15 +151,19 @@ export function ClientContextProvider({ children }: { children: ReactNode | Reac
relayUrl: DEFAULT_RELAY_URL,
});
const web3Modal = new Web3Modal({
projectId: DEFAULT_PROJECT_ID,
});
setEthereumProvider(provider);
setClient(provider.client);
await _subscribeToProviderEvents(provider);
setWeb3Modal(web3Modal);
} catch (err) {
throw err;
} finally {
setIsInitializing(false);
}
}, [_subscribeToProviderEvents]);
}, []);
const createWeb3Provider = useCallback((ethereumProvider: UniversalProvider) => {
const web3Provider = new providers.Web3Provider(ethereumProvider);
@ -207,9 +213,9 @@ export function ClientContextProvider({ children }: { children: ReactNode | Reac
setSession(session);
setChain(caipChainId);
QRCodeModal.close();
web3Modal?.closeModal();
},
[ethereumProvider, chainData.eip155, createWeb3Provider],
[ethereumProvider, chainData.eip155, createWeb3Provider, web3Modal],
);
const onSessionConnected = useCallback(
@ -265,6 +271,10 @@ export function ClientContextProvider({ children }: { children: ReactNode | Reac
}
}, [client, createClient]);
useEffect(() => {
if (ethereumProvider && web3Modal) _subscribeToProviderEvents(ethereumProvider);
}, [_subscribeToProviderEvents, ethereumProvider, web3Modal]);
useEffect(() => {
const fetchBalances = async () => {
if (!web3Provider || !accounts) return;

View File

@ -1,5 +1,6 @@
import type { AppProps } from "next/app";
import { createGlobalStyle } from "styled-components";
import Metadata from "../components/Metadata";
import { ClientContextProvider } from "../contexts/ClientContext";
@ -11,6 +12,7 @@ const GlobalStyle = createGlobalStyle`
function MyApp({ Component, pageProps }: AppProps) {
return (
<>
<Metadata />
<GlobalStyle />
<ClientContextProvider>
<Component {...pageProps} />

View File

@ -30,10 +30,10 @@
"dependencies": {
"@ethereumjs/tx": "^3.5.0",
"@walletconnect/encoding": "^1.0.1",
"@walletconnect/universal-provider": "2.1.1",
"@walletconnect/qrcode-modal": "^1.7.1",
"@walletconnect/types": "2.1.1",
"@walletconnect/utils": "2.1.1",
"@walletconnect/universal-provider": "2.1.4",
"@walletconnect/utils": "2.1.4",
"@web3modal/standalone": "^2.0.0-beta.10",
"axios": "^0.21.1",
"blockies-ts": "^1.0.0",
"caip-api": "^2.0.0-beta.1",
@ -41,9 +41,9 @@
"eth-sig-util": "^2.5.3",
"ethereumjs-util": "^7.0.6",
"ethers": "^5.3.0",
"next": "12.2.4",
"prop-types": "^15.7.2",
"qr-image": "^3.2.0",
"next": "12.2.4",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "^4.0.3",

View File

@ -0,0 +1,17 @@
import Head from "next/head";
import * as React from "react";
import { DEFAULT_APP_METADATA } from "../constants";
const Metadata = () => (
<Head>
<title>{DEFAULT_APP_METADATA.name}</title>
<meta name="description" content={DEFAULT_APP_METADATA.description} />
<meta name="url" content={DEFAULT_APP_METADATA.url} />
{DEFAULT_APP_METADATA.icons.map((icon, index) => (
<link key={index} rel="icon" href={icon} />
))}
</Head>
);
export default Metadata;

View File

@ -28,7 +28,7 @@ export const DEFAULT_EIP155_METHODS = ["eth_sendTransaction", "personal_sign", "
export const DEFAULT_LOGGER = "debug";
export const DEFAULT_APP_METADATA = {
name: "React App",
name: "React App with web3",
description: "React App for WalletConnect",
url: "https://walletconnect.com/",
icons: ["https://avatars.githubusercontent.com/u/37784886"],

View File

@ -8,7 +8,7 @@ import {
useState,
} from "react";
import QRCodeModal from "@walletconnect/qrcode-modal";
import { Web3Modal } from "@web3modal/standalone";
import { apiGetChainNamespace, ChainsMap } from "caip-api";
import UniversalProvider from "@walletconnect/universal-provider";
import Client from "@walletconnect/sign-client";
@ -59,6 +59,7 @@ export function ClientContextProvider({ children }: { children: ReactNode | Reac
const [accounts, setAccounts] = useState<string[]>([]);
const [chainData, setChainData] = useState<ChainNamespaces>({});
const [chain, setChain] = useState<string>("");
const [web3Modal, setWeb3Modal] = useState<Web3Modal>();
const resetApp = () => {
setPairings([]);
@ -95,46 +96,47 @@ export function ClientContextProvider({ children }: { children: ReactNode | Reac
resetApp();
}, [ethereumProvider]);
const _subscribeToProviderEvents = useCallback(async (_client: UniversalProvider) => {
if (typeof _client === "undefined") {
throw new Error("WalletConnect is not initialized");
}
const _subscribeToProviderEvents = useCallback(
async (_client: UniversalProvider) => {
if (typeof _client === "undefined") {
throw new Error("WalletConnect is not initialized");
}
_client.on("display_uri", async (uri: string) => {
console.log("EVENT", "QR Code Modal open");
QRCodeModal.open(uri, () => {
console.log("EVENT", "QR Code Modal closed");
_client.on("display_uri", async (uri: string) => {
console.log("EVENT", "QR Code Modal open");
web3Modal?.openModal({ uri });
});
});
// Subscribe to session ping
_client.on("session_ping", ({ id, topic }: { id: number; topic: string }) => {
console.log("EVENT", "session_ping");
console.log(id, topic);
});
// Subscribe to session ping
_client.on("session_ping", ({ id, topic }: { id: number; topic: string }) => {
console.log("EVENT", "session_ping");
console.log(id, topic);
});
// Subscribe to session event
_client.on("session_event", ({ event, chainId }: { event: any; chainId: string }) => {
console.log("EVENT", "session_event");
console.log(event, chainId);
});
// Subscribe to session event
_client.on("session_event", ({ event, chainId }: { event: any; chainId: string }) => {
console.log("EVENT", "session_event");
console.log(event, chainId);
});
// Subscribe to session update
_client.on(
"session_update",
({ topic, session }: { topic: string; session: SessionTypes.Struct }) => {
console.log("EVENT", "session_updated");
setSession(session);
},
);
// Subscribe to session update
_client.on(
"session_update",
({ topic, session }: { topic: string; session: SessionTypes.Struct }) => {
console.log("EVENT", "session_updated");
setSession(session);
},
);
// Subscribe to session delete
_client.on("session_delete", ({ id, topic }: { id: number; topic: string }) => {
console.log("EVENT", "session_deleted");
console.log(id, topic);
resetApp();
});
}, []);
// Subscribe to session delete
_client.on("session_delete", ({ id, topic }: { id: number; topic: string }) => {
console.log("EVENT", "session_deleted");
console.log(id, topic);
resetApp();
});
},
[web3Modal],
);
const createClient = useCallback(async () => {
try {
@ -146,15 +148,19 @@ export function ClientContextProvider({ children }: { children: ReactNode | Reac
relayUrl: DEFAULT_RELAY_URL,
});
const web3Modal = new Web3Modal({
projectId: DEFAULT_PROJECT_ID,
});
setEthereumProvider(provider);
setClient(provider.client);
await _subscribeToProviderEvents(provider);
setWeb3Modal(web3Modal);
} catch (err) {
throw err;
} finally {
setIsInitializing(false);
}
}, [_subscribeToProviderEvents]);
}, []);
const createWeb3Provider = useCallback((ethereumProvider: UniversalProvider) => {
const web3Provider = new Web3(ethereumProvider);
@ -204,9 +210,9 @@ export function ClientContextProvider({ children }: { children: ReactNode | Reac
setSession(session);
setChain(caipChainId);
QRCodeModal.close();
web3Modal?.closeModal();
},
[ethereumProvider, chainData.eip155, createWeb3Provider],
[ethereumProvider, chainData.eip155, createWeb3Provider, web3Modal],
);
const onSessionConnected = useCallback(
@ -262,6 +268,10 @@ export function ClientContextProvider({ children }: { children: ReactNode | Reac
}
}, [client, createClient]);
useEffect(() => {
if (ethereumProvider && web3Modal) _subscribeToProviderEvents(ethereumProvider);
}, [_subscribeToProviderEvents, ethereumProvider, web3Modal]);
useEffect(() => {
const fetchBalances = async () => {
if (!web3Provider || !accounts) return;

View File

@ -1,5 +1,6 @@
import type { AppProps } from "next/app";
import { createGlobalStyle } from "styled-components";
import Metadata from "../components/Metadata";
import { ClientContextProvider } from "../contexts/ClientContext";
@ -11,6 +12,7 @@ const GlobalStyle = createGlobalStyle`
function MyApp({ Component, pageProps }: AppProps) {
return (
<>
<Metadata />
<GlobalStyle />
<ClientContextProvider>
<Component {...pageProps} />

View File

@ -0,0 +1,17 @@
import Head from "next/head";
import * as React from "react";
import { DEFAULT_APP_METADATA } from "../constants";
const Metadata = () => (
<Head>
<title>{DEFAULT_APP_METADATA.name}</title>
<meta name="description" content={DEFAULT_APP_METADATA.description} />
<meta name="url" content={DEFAULT_APP_METADATA.url} />
{DEFAULT_APP_METADATA.icons.map((icon, index) => (
<link key={index} rel="icon" href={icon} />
))}
</Head>
);
export default Metadata;

View File

@ -5,6 +5,7 @@ import { createGlobalStyle } from "styled-components";
import { ClientContextProvider } from "../contexts/ClientContext";
import { JsonRpcContextProvider } from "../contexts/JsonRpcContext";
import { ChainDataContextProvider } from "../contexts/ChainDataContext";
import Metadata from "../components/Metadata";
import { globalStyle } from "../styles";
const GlobalStyle = createGlobalStyle`
@ -14,6 +15,7 @@ const GlobalStyle = createGlobalStyle`
function MyApp({ Component, pageProps }: AppProps) {
return (
<>
<Metadata />
<GlobalStyle />
<ChainDataContextProvider>
<ClientContextProvider>