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 sdk, {
FrameNotificationDetails,
@ -11,11 +13,14 @@ import {
useWaitForTransactionReceipt,
useDisconnect,
useConnect,
useSwitchChain,
useChainId,
} from "wagmi";
import { config } from "~/components/providers/WagmiProvider";
import { Button } from "~/components/ui/Button";
import { truncateAddress } from "~/lib/truncateAddress";
import { base } from "wagmi/chains";
export default function Demo(
{ title }: { title?: string } = { title: "Frames v2 Demo" }
@ -30,6 +35,8 @@ export default function Demo(
const [sendNotificationResult, setSendNotificationResult] = useState("");
const { address, isConnected } = useAccount();
const chainId = useChainId();
const {
sendTransaction,
error: sendTxError,
@ -42,13 +49,6 @@ export default function Demo(
hash: txHash as `0x${string}`,
});
const {
signMessage,
error: signError,
isError: isSignError,
isPending: isSignPending,
} = useSignMessage();
const {
signTypedData,
error: signTypedError,
@ -150,10 +150,6 @@ export default function Demo(
);
}, [sendTransaction]);
const sign = useCallback(() => {
signMessage({ message: "Hello from Frames v2!" });
}, [signMessage]);
const signTyped = useCallback(() => {
signTypedData({
domain: {
@ -280,6 +276,12 @@ export default function Demo(
</div>
)}
{chainId && (
<div className="my-2 text-xs">
Chain ID: <pre className="inline">{chainId}</pre>
</div>
)}
<div className="mb-4">
<Button
onClick={() =>
@ -292,15 +294,22 @@ export default function Demo(
</Button>
</div>
<div className="mb-4">
<SignMessage />
</div>
{isConnected && (
<>
<div className="mb-4">
<SendEth />
</div>
<div className="mb-4">
<Button
onClick={sendTx}
disabled={!isConnected || isSendTxPending}
isLoading={isSendTxPending}
>
Send Transaction
Send Transaction (contract)
</Button>
{isSendTxError && renderError(sendTxError)}
{txHash && (
@ -317,16 +326,6 @@ export default function Demo(
</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">
<Button
onClick={signTyped}
@ -337,9 +336,141 @@ export default function Demo(
</Button>
{isSignTypedError && renderError(signTypedError)}
</div>
<div className="mb-4">
<SwitchChain />
</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 { base } from "wagmi/chains";
import { base, mainnet } from "wagmi/chains";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { frameConnector } from "~/lib/connector";
export const config = createConfig({
chains: [base],
chains: [base, mainnet],
transports: {
// Configure dedicated RPC providers when using in production
[base.id]: http(),
[mainnet.id]: http(),
},
connectors: [frameConnector()],
});

View File

@ -67,6 +67,11 @@ export function frameConnector() {
method: "wallet_switchEthereumChain",
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;
},
onAccountsChanged(accounts) {