Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(explorer): active chain as dynamic param #3181

Merged
merged 28 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
c8db0bf
initial chain name as url refactoring
karooolis Sep 13, 2024
67d7279
fix nav urls
karooolis Sep 13, 2024
c8c26b8
redirect chain name
karooolis Sep 13, 2024
a0d2f83
use wagmi config from useConfig
karooolis Sep 13, 2024
632cd23
use chain id from url params
karooolis Sep 13, 2024
552a1c2
dynamically set anvil connectors
karooolis Sep 13, 2024
b7e2520
check isAnvil in ConnectButton
karooolis Sep 13, 2024
03e36e1
check isAnvil in ConnectButton
karooolis Sep 13, 2024
c6c1252
useChain helper
karooolis Sep 13, 2024
af9dfe1
useChain helper
karooolis Sep 13, 2024
f91da90
fix 404 and error pages, add favicon
karooolis Sep 16, 2024
a0fa830
remove isAnvil helper
karooolis Sep 16, 2024
025af62
add chain id + name validation
karooolis Sep 16, 2024
3009ef4
use asserts for chain checking
karooolis Sep 16, 2024
ea4573b
typecheck chain id within router
karooolis Sep 16, 2024
9c64ece
typecheck chain id within router
karooolis Sep 16, 2024
fafc6d4
memoize wagmi config
karooolis Sep 16, 2024
99c2069
move provider, remove redundant layout
karooolis Sep 16, 2024
748929e
cleanup
karooolis Sep 16, 2024
359bc50
explicitly add favicon
karooolis Sep 16, 2024
7b4575b
move chainName into explorer, modify supported chains
karooolis Sep 17, 2024
c01e743
get correct chain in world route
karooolis Sep 17, 2024
90ab818
add favicon crisp
karooolis Sep 17, 2024
b527702
update favicon
karooolis Sep 17, 2024
07b1af3
add explorer to explore redirect
karooolis Sep 17, 2024
f25d4f2
Create perfect-plants-hang.md
karooolis Sep 17, 2024
8a92562
correct redirect url
karooolis Sep 17, 2024
a57f74b
Merge branch 'main' into kumpis/chain-url-path
karooolis Sep 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions packages/explorer/public/favicon.svg
karooolis marked this conversation as resolved.
Show resolved Hide resolved
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 0 additions & 5 deletions packages/explorer/src/app/(explorer)/page.tsx

This file was deleted.

This file was deleted.

9 changes: 0 additions & 9 deletions packages/explorer/src/app/(explorer)/worlds/page.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,37 @@

import { WagmiProvider, createConfig, http } from "wagmi";
import { injected, metaMask, safe } from "wagmi/connectors";
import { ReactNode } from "react";
import { ReactNode, useMemo } from "react";
import { RainbowKitProvider, darkTheme } from "@rainbow-me/rainbowkit";
import "@rainbow-me/rainbowkit/styles.css";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { getChain } from "../../common";
import { defaultAnvilConnectors } from "../../connectors/anvil";
import { getDefaultAnvilConnectors } from "../../../../../connectors/anvil";
import { useChain } from "../../../../../hooks/useChain";

const queryClient = new QueryClient();

const chain = getChain();
export const wagmiConfig = createConfig({
chains: [chain],
connectors: [
injected(),
metaMask({
dappMetadata: {
name: "World Explorer",
export function Providers({ children }: { children: ReactNode }) {
const chain = useChain();
const wagmiConfig = useMemo(() => {
return createConfig({
chains: [chain],
connectors: [
injected(),
metaMask({
dappMetadata: {
name: "World Explorer",
},
}),
safe(),
...getDefaultAnvilConnectors(chain.id),
],
transports: {
[chain.id]: http(),
},
}),
safe(),
...defaultAnvilConnectors,
],
transports: {
[chain.id]: http(),
},
ssr: true,
});
ssr: true,
});
}, [chain]);

export function Providers({ children }: { children: ReactNode }) {
return (
<WagmiProvider config={wagmiConfig}>
<QueryClientProvider client={queryClient}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,17 @@ import { Loader } from "lucide-react";
import { useParams } from "next/navigation";
import { toast } from "sonner";
import { Hex } from "viem";
import { useAccount } from "wagmi";
import { useAccount, useConfig } from "wagmi";
import { ChangeEvent, useState } from "react";
import { encodeField, getFieldIndex } from "@latticexyz/protocol-parser/internal";
import { SchemaAbiType } from "@latticexyz/schema-type/internal";
import IBaseWorldAbi from "@latticexyz/world/out/IBaseWorld.sol/IBaseWorld.abi.json";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { waitForTransactionReceipt, writeContract } from "@wagmi/core";
import { getChain } from "../../../../../common";
import { Checkbox } from "../../../../../components/ui/Checkbox";
import { camelCase, cn } from "../../../../../lib/utils";
import { TableConfig } from "../../../../api/table/route";
import { wagmiConfig } from "../../../Providers";
import { Checkbox } from "../../../../../../components/ui/Checkbox";
import { useChainId } from "../../../../../../hooks/useChain";
import { camelCase, cn } from "../../../../../../lib/utils";
import { TableConfig } from "../../../../../api/table/route";

type Props = {
name: string;
Expand All @@ -22,12 +21,11 @@ type Props = {
config: TableConfig;
};

const chain = getChain();
const chainId = chain.id;

export function EditableTableCell({ name, config, keyTuple, value: defaultValue }: Props) {
const wagmiConfig = useConfig();
const queryClient = useQueryClient();
const { worldAddress } = useParams();
const chainId = useChainId();
const account = useAccount();

const [value, setValue] = useState<unknown>(defaultValue);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Lock } from "lucide-react";
import { useParams } from "next/navigation";
import { internalTableNames } from "@latticexyz/store-sync/sqlite";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../../../../components/ui/Select";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../../../../../components/ui/Select";

type Props = {
value: string | undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ import {
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table";
import { Button } from "../../../../../components/ui/Button";
import { Checkbox } from "../../../../../components/ui/Checkbox";
import { Input } from "../../../../../components/ui/Input";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "../../../../../components/ui/Table";
import { Button } from "../../../../../../components/ui/Button";
import { Checkbox } from "../../../../../../components/ui/Checkbox";
import { Input } from "../../../../../../components/ui/Input";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "../../../../../../components/ui/Table";
import { bufferToBigInt } from "../utils/bufferToBigInt";
import { EditableTableCell } from "./EditableTableCell";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
import { Coins, Eye, Send } from "lucide-react";
import { AbiFunction } from "viem";
import { useDeferredValue, useState } from "react";
import { Input } from "../../../../../components/ui/Input";
import { Separator } from "../../../../../components/ui/Separator";
import { Skeleton } from "../../../../../components/ui/Skeleton";
import { useHashState } from "../../../../../hooks/useHashState";
import { cn } from "../../../../../lib/utils";
import { useAbiQuery } from "../../../../../queries/useAbiQuery";
import { Input } from "../../../../../../components/ui/Input";
import { Separator } from "../../../../../../components/ui/Separator";
import { Skeleton } from "../../../../../../components/ui/Skeleton";
import { useHashState } from "../../../../../../hooks/useHashState";
import { cn } from "../../../../../../lib/utils";
import { useAbiQuery } from "../../../../../../queries/useAbiQuery";
import { FunctionField } from "./FunctionField";

export function Form() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import { z } from "zod";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { Button } from "../../../../../components/ui/Button";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "../../../../../components/ui/Form";
import { Input } from "../../../../../components/ui/Input";
import { Separator } from "../../../../../components/ui/Separator";
import { Button } from "../../../../../../components/ui/Button";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "../../../../../../components/ui/Form";
import { Input } from "../../../../../../components/ui/Input";
import { Separator } from "../../../../../../components/ui/Separator";
import { useContractMutation } from "./useContractMutation";

export enum FunctionType {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
import { useParams } from "next/navigation";
import { toast } from "sonner";
import { Abi, AbiFunction, Hex } from "viem";
import { useAccount } from "wagmi";
import { useAccount, useConfig } from "wagmi";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { readContract, waitForTransactionReceipt, writeContract } from "@wagmi/core";
import { getChain } from "../../../../../common";
import { wagmiConfig } from "../../../Providers";
import { useChainId } from "../../../../../../hooks/useChain";
import { FunctionType } from "./FunctionField";

type UseContractMutationProps = {
abi: AbiFunction;
operationType: FunctionType;
};

const chain = getChain();
const chainId = chain.id;

export function useContractMutation({ abi, operationType }: UseContractMutationProps) {
const queryClient = useQueryClient();
const { worldAddress } = useParams();
const chainId = useChainId();
const queryClient = useQueryClient();
const wagmiConfig = useConfig();
const account = useAccount();

return useMutation({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
"use client";

import { Navigation } from "../../../../components/Navigation";
import { Navigation } from "../../../../../components/Navigation";
import { Providers } from "./Providers";

export default function WorldLayout({ children }: { children: React.ReactNode }) {
return (
<div>
<Providers>
<Navigation />
{children}
</div>
</Providers>
);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import { type Write } from "../../../../../observer/store";
import { type Write } from "../../../../../../observer/store";
import { msPerViewportWidth } from "./common";

export type Props = Write;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"use client";

import { useStore } from "zustand";
import { KeepInView } from "../../../../../components/KeepInView";
import { store } from "../../../../../observer/store";
import { KeepInView } from "../../../../../../components/KeepInView";
import { store } from "../../../../../../observer/store";
import { Write } from "./Write";

export function Writes() {
Expand Down
karooolis marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { redirect } from "next/navigation";

type Props = {
params: {
chainName: string;
worldAddress: string;
};
};

export default async function WorldPage({ params }: Props) {
const { chainName, worldAddress } = params;
return redirect(`/${chainName}/worlds/${worldAddress}/explore`);
}
15 changes: 15 additions & 0 deletions packages/explorer/src/app/[chainName]/(explorer)/worlds/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { notFound, redirect } from "next/navigation";

export const dynamic = "force-dynamic";

type Props = {
params: {
chainName: string;
};
};

export default function WorldsPage({ params }: Props) {
const worldAddress = process.env.WORLD_ADDRESS;
if (worldAddress) return redirect(`/${params.chainName}/worlds/${worldAddress}`);
return notFound();
}
11 changes: 11 additions & 0 deletions packages/explorer/src/app/[chainName]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { redirect } from "next/navigation";

type Props = {
params: {
chainName: string;
};
};

export default async function ChainPage({ params }: Props) {
return redirect(`/${params.chainName}/worlds`);
}
18 changes: 10 additions & 8 deletions packages/explorer/src/app/api/world/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,21 @@ import { getBlockNumber, getLogs } from "viem/actions";
import { helloStoreEvent } from "@latticexyz/store";
import { helloWorldEvent } from "@latticexyz/world";
import { getWorldAbi } from "@latticexyz/world/internal";
import { getChain } from "../../../common";
import { SupportedChainIds, chains, isValidChainId } from "../../../common";

export const dynamic = "force-dynamic";

async function getClient() {
async function getClient(chainId: SupportedChainIds) {
const client = createWalletClient({
chain: getChain(),
chain: chains[chainId],
transport: http(),
});

return client;
}

async function getParameters(worldAddress: Address) {
const client = await getClient();
async function getParameters(chainId: SupportedChainIds, worldAddress: Address) {
const client = await getClient(chainId);
const toBlock = await getBlockNumber(client);
const logs = await getLogs(client, {
strict: true,
Expand All @@ -35,15 +35,17 @@ async function getParameters(worldAddress: Address) {

export async function GET(req: Request) {
const { searchParams } = new URL(req.url);
const worldAddress = searchParams.get("address") as Hex;
const worldAddress = searchParams.get("worldAddress") as Hex;
const chainId = Number(searchParams.get("chainId"));
isValidChainId(chainId);

if (!worldAddress) {
return Response.json({ error: "address is required" }, { status: 400 });
}

try {
const client = await getClient();
const { fromBlock, toBlock, isWorldDeployed } = await getParameters(worldAddress);
const client = await getClient(chainId);
const { fromBlock, toBlock, isWorldDeployed } = await getParameters(chainId, worldAddress);
const worldAbiResponse = await getWorldAbi({
client,
worldAddress,
Expand Down
Loading
Loading