explicitly update config on switchChain

This commit is contained in:
Tony D'Addeo 2024-12-03 12:05:13 -06:00 committed by lucas-neynar
parent 6691998a1d
commit e89dd14566
No known key found for this signature in database
3 changed files with 162 additions and 24 deletions

View File

@ -1,3 +1,5 @@
"use client";
import { useEffect, useCallback, useState } from "react"; import { useEffect, useCallback, useState } from "react";
import sdk, { import sdk, {
FrameNotificationDetails, FrameNotificationDetails,
@ -11,11 +13,14 @@ import {
useWaitForTransactionReceipt, useWaitForTransactionReceipt,
useDisconnect, useDisconnect,
useConnect, useConnect,
useSwitchChain,
useChainId,
} from "wagmi"; } from "wagmi";
import { config } from "~/components/providers/WagmiProvider"; import { config } from "~/components/providers/WagmiProvider";
import { Button } from "~/components/ui/Button"; import { Button } from "~/components/ui/Button";
import { truncateAddress } from "~/lib/truncateAddress"; import { truncateAddress } from "~/lib/truncateAddress";
import { base } from "wagmi/chains";
export default function Demo( export default function Demo(
{ title }: { title?: string } = { title: "Frames v2 Demo" } { title }: { title?: string } = { title: "Frames v2 Demo" }
@ -30,6 +35,8 @@ export default function Demo(
const [sendNotificationResult, setSendNotificationResult] = useState(""); const [sendNotificationResult, setSendNotificationResult] = useState("");
const { address, isConnected } = useAccount(); const { address, isConnected } = useAccount();
const chainId = useChainId();
const { const {
sendTransaction, sendTransaction,
error: sendTxError, error: sendTxError,
@ -42,13 +49,6 @@ export default function Demo(
hash: txHash as `0x${string}`, hash: txHash as `0x${string}`,
}); });
const {
signMessage,
error: signError,
isError: isSignError,
isPending: isSignPending,
} = useSignMessage();
const { const {
signTypedData, signTypedData,
error: signTypedError, error: signTypedError,
@ -150,10 +150,6 @@ export default function Demo(
); );
}, [sendTransaction]); }, [sendTransaction]);
const sign = useCallback(() => {
signMessage({ message: "Hello from Frames v2!" });
}, [signMessage]);
const signTyped = useCallback(() => { const signTyped = useCallback(() => {
signTypedData({ signTypedData({
domain: { domain: {
@ -280,6 +276,12 @@ export default function Demo(
</div> </div>
)} )}
{chainId && (
<div className="my-2 text-xs">
Chain ID: <pre className="inline">{chainId}</pre>
</div>
)}
<div className="mb-4"> <div className="mb-4">
<Button <Button
onClick={() => onClick={() =>
@ -291,16 +293,23 @@ export default function Demo(
{isConnected ? "Disconnect" : "Connect"} {isConnected ? "Disconnect" : "Connect"}
</Button> </Button>
</div> </div>
<div className="mb-4">
<SignMessage />
</div>
{isConnected && ( {isConnected && (
<> <>
<div className="mb-4">
<SendEth />
</div>
<div className="mb-4"> <div className="mb-4">
<Button <Button
onClick={sendTx} onClick={sendTx}
disabled={!isConnected || isSendTxPending} disabled={!isConnected || isSendTxPending}
isLoading={isSendTxPending} isLoading={isSendTxPending}
> >
Send Transaction Send Transaction (contract)
</Button> </Button>
{isSendTxError && renderError(sendTxError)} {isSendTxError && renderError(sendTxError)}
{txHash && ( {txHash && (
@ -317,16 +326,6 @@ export default function Demo(
</div> </div>
)} )}
</div> </div>
<div className="mb-4">
<Button
onClick={sign}
disabled={!isConnected || isSignPending}
isLoading={isSignPending}
>
Sign Message
</Button>
{isSignError && renderError(signError)}
</div>
<div className="mb-4"> <div className="mb-4">
<Button <Button
onClick={signTyped} onClick={signTyped}
@ -337,9 +336,141 @@ export default function Demo(
</Button> </Button>
{isSignTypedError && renderError(signTypedError)} {isSignTypedError && renderError(signTypedError)}
</div> </div>
<div className="mb-4">
<SwitchChain />
</div>
</> </>
)} )}
</div> </div>
</div> </div>
); );
} }
function SwitchChain() {
const chainId = useChainId();
const {
switchChain,
error: switchChainError,
isError: isSwitchChainError,
isPending: isSwitchChainPending,
} = useSwitchChain();
const handleSwitchChain = useCallback(() => {
switchChain({ chainId: chainId === 1 ? 8453 : 1 });
}, [switchChain, chainId]);
return (
<>
<Button
onClick={handleSwitchChain}
disabled={isSwitchChainPending}
isLoading={isSwitchChainPending}
>
Switch chain
</Button>
{isSwitchChainError && renderError(switchChainError)}
</>
);
}
function SignMessage() {
const { isConnected } = useAccount();
const { connectAsync } = useConnect();
const {
signMessage,
data: signature,
error: signError,
isError: isSignError,
isPending: isSignPending,
} = useSignMessage();
const handleSignMessage = useCallback(async () => {
if (!isConnected) {
await connectAsync({
chainId: base.id,
connector: config.connectors[0]
})
}
signMessage({ message: "Hello from Frames v2!" });
}, [connectAsync, isConnected, signMessage]);
return (
<>
<Button
onClick={handleSignMessage}
disabled={isSignPending}
isLoading={isSignPending}
>
Sign Message
</Button>
{isSignError && renderError(signError)}
{signature && (
<div className="mt-2 text-xs">
<div>Signature: {signature}</div>
</div>
)}
</>
);
}
function SendEth() {
const { isConnected } = useAccount();
const {
sendTransaction,
data,
error: sendTxError,
isError: isSendTxError,
isPending: isSendTxPending,
} = useSendTransaction();
const { isLoading: isConfirming, isSuccess: isConfirmed } =
useWaitForTransactionReceipt({
hash: data
});
const handleSend = useCallback(() => {
sendTransaction(
{
to: "0x4bBFD120d9f352A0BEd7a014bd67913a2007a878",
value: 1n,
}
);
}, [sendTransaction]);
return (
<>
<Button
onClick={handleSend}
disabled={!isConnected || isSendTxPending}
isLoading={isSendTxPending}
>
Send Transaction (eth)
</Button>
{isSendTxError && renderError(sendTxError)}
{data && (
<div className="mt-2 text-xs">
<div>Hash: {truncateAddress(data)}</div>
<div>
Status:{" "}
{isConfirming
? "Confirming..."
: isConfirmed
? "Confirmed!"
: "Pending"}
</div>
</div>
)}
</>
);
}
const renderError = (error: Error | null) => {
if (!error) return null;
return <div className="text-red-500 text-xs mt-1">{error.message}</div>;
};

View File

@ -1,12 +1,14 @@
import { createConfig, http, WagmiProvider } from "wagmi"; import { createConfig, http, WagmiProvider } from "wagmi";
import { base } from "wagmi/chains"; import { base, mainnet } from "wagmi/chains";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { frameConnector } from "~/lib/connector"; import { frameConnector } from "~/lib/connector";
export const config = createConfig({ export const config = createConfig({
chains: [base], chains: [base, mainnet],
transports: { transports: {
// Configure dedicated RPC providers when using in production
[base.id]: http(), [base.id]: http(),
[mainnet.id]: http(),
}, },
connectors: [frameConnector()], connectors: [frameConnector()],
}); });

View File

@ -67,6 +67,11 @@ export function frameConnector() {
method: "wallet_switchEthereumChain", method: "wallet_switchEthereumChain",
params: [{ chainId: numberToHex(chainId) }], params: [{ chainId: numberToHex(chainId) }],
}); });
// explicitly emit this event as a workaround for ethereum provider not
// emitting events, can remove once events are flowing
config.emitter.emit("change", { chainId });
return chain; return chain;
}, },
onAccountsChanged(accounts) { onAccountsChanged(accounts) {