diff --git a/packages/example-react-app/src/AccountDetail.tsx b/packages/example-react-app/src/AccountDetail.tsx deleted file mode 100644 index 3e25fa3..0000000 --- a/packages/example-react-app/src/AccountDetail.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { type MutableRefObject, useContext, useEffect, useRef, useState } from 'react'; - -import { type IWeb3Context, Web3Context } from './web3/Web3Context'; - -function AccountDetail({ address }: { address: string }) { - const web3Context: IWeb3Context = useContext(Web3Context); - - const [balance, setBalance] = useState(NaN); - const subscriptionId: MutableRefObject = useRef(undefined); - - // update balance - useEffect(() => { - updateBalance(); - - if (!web3Context.web3.subscriptionManager.supportsSubscriptions()) { - return; - } - - web3Context.web3.eth.subscribe('newBlockHeaders').then((newBlockSubscription) => { - subscriptionId.current = newBlockSubscription.id; - newBlockSubscription.on('data', () => { - updateBalance(); - }); - }); - - return () => { - web3Context.web3.eth.subscriptionManager.unsubscribe( - ({ id }) => subscriptionId.current === id, - ); - }; - }); - - function updateBalance(): void { - web3Context.web3.eth.getBalance(address).then((balance: bigint) => { - setBalance(parseFloat(web3Context.web3.utils.fromWei(balance, 'ether'))); - }); - } - - return ( - <> -
{address}
-
Balance in native token: {`${balance}`}
- - ); -} - -export default AccountDetail; diff --git a/packages/example-react-app/src/App.tsx b/packages/example-react-app/src/App.tsx index 4408954..01c1ecf 100644 --- a/packages/example-react-app/src/App.tsx +++ b/packages/example-react-app/src/App.tsx @@ -1,12 +1,12 @@ import { useContext, useEffect, useState } from 'react'; import type { ProviderChainId, providers } from 'web3'; +import { Accounts } from './components/Accounts'; +import { ProviderButton } from './components/ProviderButton'; +import { SwitchEthereumChain } from './wallet-components/SwitchEthereumChain'; import { AccountProvider } from './web3/AccountContext'; import { type IWeb3Context, Web3Context } from './web3/Web3Context'; - -import Accounts from './Accounts'; -import ProviderButton from './ProviderButton'; -import WalletRpcPlugComponent from './WalletRpcPlugComponent'; +import { AddEthereumChain } from './wallet-components/AddEthereumChain'; function App() { const web3Context: IWeb3Context = useContext(Web3Context); @@ -74,14 +74,20 @@ function App() { })} ) : null} +

Network Details

Chain ID: {`${chainId}`}
Network ID: {`${networkId}`}
+ - + - +

Wallet RPC Methods

+
+ + +
)}
diff --git a/packages/example-react-app/src/ProviderButton.tsx b/packages/example-react-app/src/ProviderButton.tsx deleted file mode 100644 index dd7b8d5..0000000 --- a/packages/example-react-app/src/ProviderButton.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { useContext } from 'react'; -import { EIP6963ProviderDetail } from 'web3'; - -import './ProviderButton.css'; -import { IWeb3Context, Web3Context } from './web3/Web3Context'; - -function ProviderButton({ provider }: { provider: EIP6963ProviderDetail }) { - const web3Context: IWeb3Context = useContext(Web3Context); - - return ( - - ); -} - -export default ProviderButton; diff --git a/packages/example-react-app/src/WalletRpcPlugComponent.tsx b/packages/example-react-app/src/WalletRpcPlugComponent.tsx deleted file mode 100644 index 6bfd0c4..0000000 --- a/packages/example-react-app/src/WalletRpcPlugComponent.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { useContext } from 'react'; -import { Web3Context } from './web3/Web3Context'; - -function WalletRpcPlugComponent() { - const { web3 } = useContext(Web3Context); - - return ( -
- - -
- ); -} - -export default WalletRpcPlugComponent; diff --git a/packages/example-react-app/src/components/AccountDetail.tsx b/packages/example-react-app/src/components/AccountDetail.tsx new file mode 100644 index 0000000..2614e4b --- /dev/null +++ b/packages/example-react-app/src/components/AccountDetail.tsx @@ -0,0 +1,44 @@ +import { type MutableRefObject, useContext, useEffect, useRef, useState } from 'react'; + +import { type IWeb3Context, Web3Context } from '../web3/Web3Context'; + +export function AccountDetail({ address }: { address: string }) { + const web3Context: IWeb3Context = useContext(Web3Context); + + const [balance, setBalance] = useState(NaN); + const subscriptionId: MutableRefObject = useRef(undefined); + + async function updateBalance(): Promise { + const newBalance = await web3Context.web3.eth.getBalance(address); + + setBalance(parseFloat(web3Context.web3.utils.fromWei(newBalance, 'ether'))); + } + + useEffect(() => { + async function subscribeToNewBlockHeaders() { + const newBlockSubscription = + await web3Context.web3.eth.subscribe('newBlockHeaders'); + + subscriptionId.current = newBlockSubscription.id; + + newBlockSubscription.on('data', () => { + void updateBalance(); + }); + } + + void subscribeToNewBlockHeaders(); + + return () => { + void web3Context.web3.eth.subscriptionManager.unsubscribe( + ({ id }) => subscriptionId.current === id, + ); + }; + }); + + return ( + <> +
{address}
+
Balance in native token: {`${balance}`}
+ + ); +} diff --git a/packages/example-react-app/src/Accounts.tsx b/packages/example-react-app/src/components/Accounts.tsx similarity index 70% rename from packages/example-react-app/src/Accounts.tsx rename to packages/example-react-app/src/components/Accounts.tsx index 71d1f64..34fdfc6 100644 --- a/packages/example-react-app/src/Accounts.tsx +++ b/packages/example-react-app/src/components/Accounts.tsx @@ -1,8 +1,10 @@ import { useContext } from 'react'; -import { AccountContext, type IAccountContext } from './web3/AccountContext'; -import AccountDetail from './AccountDetail'; -function Accounts() { +import { AccountContext, type IAccountContext } from '../web3/AccountContext'; + +import { AccountDetail } from './AccountDetail'; + +export function Accounts() { const accountContext: IAccountContext = useContext(AccountContext); return ( @@ -10,16 +12,18 @@ function Accounts() {

Accounts

{accountContext.selectedAccount === undefined ? ( - + ) : ( <>

Selected Account

- + {accountContext.accounts.length > 1 ? ( <>

Other Accounts

{accountContext.accounts.slice(1).map((account: string) => ( - + ))} ) : null} @@ -29,5 +33,3 @@ function Accounts() { ); } - -export default Accounts; diff --git a/packages/example-react-app/src/ProviderButton.css b/packages/example-react-app/src/components/ProviderButton.css similarity index 100% rename from packages/example-react-app/src/ProviderButton.css rename to packages/example-react-app/src/components/ProviderButton.css diff --git a/packages/example-react-app/src/components/ProviderButton.tsx b/packages/example-react-app/src/components/ProviderButton.tsx new file mode 100644 index 0000000..5754738 --- /dev/null +++ b/packages/example-react-app/src/components/ProviderButton.tsx @@ -0,0 +1,18 @@ +import { useContext } from 'react'; +import type { EIP6963ProviderDetail } from 'web3'; + +import type { IWeb3Context } from '../web3/Web3Context'; +import { Web3Context } from '../web3/Web3Context'; + +import './ProviderButton.css'; + +export function ProviderButton({ provider }: { provider: EIP6963ProviderDetail }) { + const web3Context: IWeb3Context = useContext(Web3Context); + + return ( + + ); +} diff --git a/packages/example-react-app/src/wallet-components/AddEthereumChain.tsx b/packages/example-react-app/src/wallet-components/AddEthereumChain.tsx new file mode 100644 index 0000000..d4a2652 --- /dev/null +++ b/packages/example-react-app/src/wallet-components/AddEthereumChain.tsx @@ -0,0 +1,74 @@ +import { AddEthereumChainRequest } from 'web3-plugin-wallet-rpc'; +import { Web3Context } from '../web3/Web3Context'; +import { useContext, useState } from 'react'; + +const chains: Record = { + mantle: { + chainId: 5000, + blockExplorerUrls: ['https://mantlescan.xyz'], + chainName: 'Mantle', + iconUrls: ['https://icons.llamao.fi/icons/chains/rsz_mantle.jpg'], + nativeCurrency: { + name: 'Mantle', + symbol: 'MNT', + decimals: 18, + }, + rpcUrls: ['https://rpc.mantle.xyz'], + }, + scroll: { + chainId: 534352, + blockExplorerUrls: ['https://scrollscan.com'], + chainName: 'Scroll', + iconUrls: ['https://icons.llamao.fi/icons/chains/rsz_scroll.jpg'], + nativeCurrency: { + name: 'ETH', + symbol: 'ETH', + decimals: 18, + }, + rpcUrls: ['https://rpc.scroll.io'], + }, +}; + +function AddChainButton({ chainDetails }: { chainDetails: AddEthereumChainRequest }) { + const { web3 } = useContext(Web3Context); + const [error, setError] = useState(undefined); + + const handleClick = () => { + web3.walletRpc + .addEthereumChain(chainDetails) + .then((response) => { + // eslint-disable-next-line no-console + console.log( + `Successfully added chain ${chainDetails.chainId} with response`, + response, + ); + }) + .catch((e) => { + // eslint-disable-next-line no-console + console.error(e); + + if (e instanceof Error) { + setError(e); + } + }); + }; + + return ( + <> + + {error &&
{error.message}
} + + ); +} + +export function AddEthereumChain() { + return ( +
+

Add EVM Chain

+ + +
+ ); +} diff --git a/packages/example-react-app/src/wallet-components/SwitchEthereumChain.tsx b/packages/example-react-app/src/wallet-components/SwitchEthereumChain.tsx new file mode 100644 index 0000000..66202c0 --- /dev/null +++ b/packages/example-react-app/src/wallet-components/SwitchEthereumChain.tsx @@ -0,0 +1,45 @@ +import { useContext, useState } from 'react'; + +import { Web3Context } from '../web3/Web3Context'; + +function SwitchChainButton({ chainId }: { chainId: number }) { + const { web3 } = useContext(Web3Context); + const [error, setError] = useState(undefined); + + const handleClick = () => { + web3.walletRpc + .switchEthereumChain(chainId) + .then((response) => { + // eslint-disable-next-line no-console + console.log(`Successfully switched to chain ${chainId} with response`, response); + }) + .catch((e) => { + // eslint-disable-next-line no-console + console.error(e); + + if (e instanceof Error) { + setError(e); + } + }); + }; + + return ( + <> + + {error &&
{error.message}
} + + ); +} + +export function SwitchEthereumChain() { + return ( +
+

Switch Chain (must be known by the wallet)

+ + + +
+ ); +}