Skip to content

Commit

Permalink
feat(ledger-browser): use react query in eth app
Browse files Browse the repository at this point in the history
- Use react query to fetch data instead of manual fetches.
- Remove dead / duplicated code where applicable.
- Minor refactors and fixes.

Depends on hyperledger-cacti#3203

Signed-off-by: Michal Bajer <[email protected]>
  • Loading branch information
outSH committed Jun 24, 2024
1 parent 51d64ee commit 4d3fb7e
Show file tree
Hide file tree
Showing 23 changed files with 553 additions and 687 deletions.
3 changes: 3 additions & 0 deletions packages/cacti-ledger-browser/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"@mui/icons-material": "5.15.10",
"@mui/material": "5.15.15",
"@supabase/supabase-js": "1.35.6",
"@tanstack/react-query": "5.29.2",
"apexcharts": "3.45.2",
"localforage": "1.10.0",
"match-sorter": "6.3.3",
Expand All @@ -70,6 +71,8 @@
"web3": "4.1.1"
},
"devDependencies": {
"@tanstack/eslint-plugin-query": "5.28.11",
"@tanstack/react-query-devtools": "5.29.2",
"@types/react": "18.2.43",
"@types/react-dom": "18.2.17",
"@types/sort-by": "1",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useRoutes, BrowserRouter, RouteObject } from "react-router-dom";
import CssBaseline from "@mui/material/CssBaseline";
import { ThemeProvider, createTheme } from "@mui/material/styles";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

import { themeOptions } from "./theme";
import ContentLayout from "./components/Layout/ContentLayout";
Expand Down Expand Up @@ -105,14 +106,21 @@ const App: React.FC<AppConfigProps> = ({ appConfig }) => {
);
};

// MUI Theme
const theme = createTheme(themeOptions);

// React Query client
const queryClient = new QueryClient();

const CactiLedgerBrowserApp: React.FC<AppConfigProps> = ({ appConfig }) => {
return (
<BrowserRouter>
<ThemeProvider theme={theme}>
<CssBaseline />
<App appConfig={appConfig} />
<QueryClientProvider client={queryClient}>
<CssBaseline />
<App appConfig={appConfig} />
{/* <ReactQueryDevtools initialIsOpen={false} /> */}
</QueryClientProvider>
</ThemeProvider>
</BrowserRouter>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,39 +1,15 @@
import { useEffect, useState } from "react";
import { supabase } from "../../../common/supabase-client";
import CardWrapper from "../../../components/ui/CardWrapper";
import { useQuery } from "@tanstack/react-query";
import { persistencePluginStatusQuery } from "../queries";

function StatusPage() {
const [getPluginStatus, setPluginStatuse] = useState<unknown[]>([]);

const fetchPluginStatus = async () => {
try {
const { data, error } = await supabase.from("plugin_status").select();
if (error) {
throw new Error(
`Could not get plugin statuses from the DB: ${error.message}`,
);
}

if (data) {
setPluginStatuse(
data.map((p) => {
return {
...p,
is_schema_initialized: p.is_schema_initialized
? "Setup complete"
: "No schema",
};
}),
);
}
} catch (error) {
console.error("Error when fetching plugin statuses:", error);
}
};
const { isSuccess, isError, data, error } = useQuery(
persistencePluginStatusQuery(),
);

useEffect(() => {
fetchPluginStatus();
}, []);
if (isError) {
console.error("Data fetch error:", error);
}

return (
<div>
Expand All @@ -49,7 +25,18 @@ function StatusPage() {
],
} as any
}
data={getPluginStatus}
data={
isSuccess
? (data as any).map((p: any) => {
return {
...p,
is_schema_initialized: p.is_schema_initialized
? "Setup complete"
: "No schema",
};
})
: []
}
title={"Persistence Plugins"}
display={"All"}
trimmed={false}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { supabaseQueryTable } from "../../common/supabase-client";

export function persistencePluginStatusQuery() {
return supabaseQueryTable("plugin_status");
}
Original file line number Diff line number Diff line change
@@ -1,46 +1,33 @@
import TokenAccount from "./TokenAccount";
import styles from "./TokenHeader.module.css";
import { useEffect, useState } from "react";
import { ethTokenDetails } from "../../queries";
import { useQuery } from "@tanstack/react-query";
import { TokenMetadata20 } from "../../../../common/supabase-types";
import { supabase } from "../../../../common/supabase-client";

function TokenHeader(props: Record<string, any>) {
const [tokenData, setTokenData] = useState<TokenMetadata20 | any>();
function TokenHeader(props: { accountNum: string; tokenAddress: string }) {
const { isError, data, error } = useQuery(
ethTokenDetails("erc20", props.tokenAddress),
);

const fetchData = async () => {
try {
const { data } = await supabase
.from(`token_metadata_erc20`)
.select("*")
.match({ address: props.token_address });
console.log(data);
if (data?.[0]) {
setTokenData(data[0]);
} else {
throw new Error("Failed to load token details");
}
} catch (error: any) {
console.error(error.message);
}
};
if (isError) {
console.error("Token header fetch error:", error);
}

useEffect(() => {
fetchData();
}, []);
console.log(data);

return (
<div className={styles["token-header"]}>
<TokenAccount accountNum={props.accountNum} />
<div className={styles["token-details"]}>
<p>
<b>Address:</b> {props.token_address}
<b>Address:</b> {props.tokenAddress}
</p>
<p>
<b>Created at:</b> {tokenData?.created_at}
<b>Created at:</b> {data?.created_at}
</p>
<p>
<b>Total supply: </b>
{tokenData?.total_supply}
{(data as TokenMetadata20).total_supply}
</p>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import Dashboard from "./pages/Dashboard/Dashboard";
import Blocks from "./pages/Blocks/Blocks";
import Transactions from "./pages/Transactions/Transactions";
import Accounts from "./pages/Accounts/Accounts";
import TokenTransactionDetails from "./pages/Details/TokenTransactionDetails";
import TransactionDetails from "./pages/Details/TransactionDetails";
import ERC20 from "./pages/ERC20/ERC20";
import SingleTokenHistory from "./pages/SingleTokenHistory/SingleTokenHistory";
Expand Down Expand Up @@ -61,16 +60,6 @@ const ethConfig: AppConfig = {
},
],
},
{
path: "token-txn-details",
element: <Outlet />,
children: [
{
path: ":standard/:address",
element: <TokenTransactionDetails />,
},
],
},
{
path: "token-details",
element: <Outlet />,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
import { supabase } from "../../../../common/supabase-client";
import CardWrapper from "../../../../components/ui/CardWrapper";
import { useNavigate, useParams } from "react-router-dom";
import { useEffect, useState } from "react";
import { useState } from "react";
import { useQuery } from "@tanstack/react-query";
import { ethGetTokenOwners } from "../../queries";

function Accounts() {
const params = useParams();
if (typeof params.standard === "undefined") {
throw new Error(`Accounts called with empty token standard ${params}`);
}
const navigate = useNavigate();
const [accounts, setAccounts] = useState<{ address: string }[]>([]);
const { isError, data, error } = useQuery(
ethGetTokenOwners(params.standard.toLowerCase()),
);
const [searchKey, setSearchKey] = useState("");

if (isError) {
console.error("Token owners fetch error:", error);
}

const tableProps = {
onClick: {
action: (param: string) => navigate(`/eth/${params.standard}/${param}`),
Expand All @@ -22,36 +32,13 @@ function Accounts() {
],
};

const fetchAccounts = async () => {
try {
const { data, error } = await supabase
.from(`token_${params.standard?.toLowerCase()}`)
.select("account_address");
if (data) {
const objData = [...new Set(data.map((el) => el.account_address))].map(
(el) => ({ address: el }),
);
setAccounts(objData);
}
if (error) {
console.error(error.message);
}
} catch (error: any) {
console.error(error.message);
}
};

useEffect(() => {
fetchAccounts();
}, []);

return (
<div>
<CardWrapper
display={"All"}
title={"Accounts"}
columns={tableProps}
data={accounts}
data={data ?? []}
filters={["address"]}
trimmed={false}
getSearchValue={(e: any) => setSearchKey(e)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import { supabase } from "../../../../common/supabase-client";
import { useNavigate } from "react-router-dom";
import CardWrapper from "../../../../components/ui/CardWrapper";

import styles from "./Blocks.module.css";
import { useEffect, useState } from "react";
import { Block } from "web3";
import { useQuery } from "@tanstack/react-query";
import { ethereumAllBlocksQuery } from "../../queries";

type ObjectKey = keyof typeof styles;

function Blocks() {
const navigate = useNavigate();
const [block, setBlock] = useState<Block[]>([]);
const { isError, data, error } = useQuery(ethereumAllBlocksQuery());

if (isError) {
console.error("Transactions fetch error:", error);
}

const blocksTableProps = {
onClick: {
Expand All @@ -24,30 +27,11 @@ function Blocks() {
],
};

const fetchBlock = async () => {
try {
const { data, error } = await supabase.from("block").select("*");
if (data) {
console.log(JSON.stringify(data));
setBlock(data);
}
if (error) {
console.error(error.message);
}
} catch (error: any) {
console.error(error.message);
}
};

useEffect(() => {
fetchBlock();
}, []);

return (
<div className={styles["blocks" as ObjectKey]}>
<CardWrapper
columns={blocksTableProps}
data={block}
data={data ?? []}
title={"Blocks"}
display={"All"}
filters={["number", "hash"]}
Expand Down
Loading

0 comments on commit 4d3fb7e

Please sign in to comment.