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

Pick nodes consistently in "npm run dev", and query fixes #394

Merged
merged 6 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 8 additions & 15 deletions ui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,23 @@
This is a light-weight compact UI used for development/debugging purposes.

### Setup
1. Install client dependencies
1. Install dependencies
```
cd client
npm i
```
2. Build client
2. Run UI against Paladin node 1
```
npm run build
npm run dev:node1
```
3. Install server dependencies
3. Run UI against Paladin node 2
```
cd ..
cd server
npm i
```
4. Build server
```
npm run build
npm run dev:node2
```
5. Start server
4. Run UI against Paladin node 3
```
npm run start
npm run dev:node3
```

### Using the UI
Open a web browser and navigate to `http://localhost:3555`
Transactions and events are shown on screen. These are updated automatically.
Open a web browser and navigate to `http://localhost:3000`, `http://localhost:3002` and `http://localhost:3003` for nodes 1, 2 and 3 respectively.
50 changes: 0 additions & 50 deletions ui/client/README.md

This file was deleted.

4 changes: 2 additions & 2 deletions ui/client/src/components/EVMPrivateDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ const EVMPrivateTransaction: React.FC<EVMTxnProps> = ({
enabled: !!dataString,
queryKey: ["decodeEVMCall", transactionId],
queryFn: () => fetchDecodedCallData(dataString),
retry: false
retry: true
});

return (
Expand Down Expand Up @@ -136,7 +136,7 @@ const EVMPrivateLog: React.FC<EVMLogProps> = ({
enabled: !!log.topics && !!log.data,
queryKey: ["decodeEVMLog", transactionId, logIndex],
queryFn: () => fetchDecodedEvent(log.topics!, log.data!),
retry: false
retry: true
});

return (
Expand Down
17 changes: 13 additions & 4 deletions ui/client/src/components/Events.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import { Box, Typography, useTheme } from "@mui/material";
import { Alert, Box, Typography, useTheme } from "@mui/material";
import { useQuery } from "@tanstack/react-query";
import { t } from "i18next";
import { fetchEvents } from "../queries/events";
Expand All @@ -24,14 +24,23 @@ import { ApplicationContext } from "../contexts/ApplicationContext";
import { altDarkModeScrollbarStyle, altLightModeScrollbarStyle } from "../themes/default";

export const Events: React.FC = () => {

const { lastBlockWithTransactions } = useContext(ApplicationContext);
const { data: events } = useQuery({
const theme = useTheme();
const addedStyle = theme.palette.mode === 'light'? altLightModeScrollbarStyle : altDarkModeScrollbarStyle;

const { data: events, error, isFetching } = useQuery({
queryKey: ["events", lastBlockWithTransactions],
queryFn: () => fetchEvents(),
});

const theme = useTheme();
const addedStyle = theme.palette.mode === 'light'? altLightModeScrollbarStyle : altDarkModeScrollbarStyle;
if(isFetching) {
return <></>;
}

if (error) {
return <Alert sx={{ margin: '30px' }} severity="error" variant="filled">{error.message}</Alert>
}

return (
<>
Expand Down
2 changes: 1 addition & 1 deletion ui/client/src/components/Hash.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const Hash: React.FC<Props> = ({ title, hash }) => {

return (
<>
<Button disableElevation onClick={() => setHashDialogOpen(true)} fullWidth variant="contained" sx={{ paddingTop: 0, paddingBottom: 0, textTransform: 'none', fontWeight: '400'}} size="small">
<Button disableElevation onClick={() => setHashDialogOpen(true)} fullWidth variant="contained" sx={{ paddingTop: 0, paddingBottom: 0, textTransform: 'none', fontWeight: '400', whiteSpace: 'nowrap'}} size="small">
{`${title} | ${getHash(hash)}`}
</Button>
<HashDialog dialogOpen={hashDialogOpen} setDialogOpen={setHashDialogOpen} title={title} hash={hash} />
Expand Down
6 changes: 4 additions & 2 deletions ui/client/src/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import { AppBar, Box, Grid2, IconButton, Tab, Tabs, Toolbar, Tooltip, useTheme } from "@mui/material";
import { AppBar, Box, Grid2, IconButton, Tab, Tabs, Toolbar, Tooltip, useMediaQuery, useTheme } from "@mui/material";
import { useContext, useState } from "react";
import { useTranslation } from "react-i18next";
import { useLocation, useNavigate } from "react-router-dom";
Expand All @@ -29,6 +29,7 @@ export const Header: React.FC = () => {
const navigate = useNavigate();
const pathname = useLocation().pathname.toLowerCase();
const theme = useTheme();
const lessThanMedium = useMediaQuery(theme.breakpoints.down("md"));

const getTabFromPath = (path: string) => {
if (path.startsWith('/ui/indexer')) {
Expand Down Expand Up @@ -79,7 +80,8 @@ export const Header: React.FC = () => {
</Grid2>
</Toolbar>
</AppBar>
<Box sx={{ height: theme => theme.mixins.toolbar }} />
<Box sx={{ height: theme => lessThanMedium? '134px' :
theme.mixins.toolbar }} />
</>
);

Expand Down
1 change: 1 addition & 0 deletions ui/client/src/components/Registry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export const Registry: React.FC<Props> = ({ registryName }) => {
fetchRegistryEntries(registryName).then((entries) =>
entries.sort((a, b) => (a.name < b.name ? -1 : 0))
),
retry: true
});

return (
Expand Down
8 changes: 4 additions & 4 deletions ui/client/src/components/TransactionDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,16 @@ export const PaladinTransactionsDetails: React.FC<Props> = ({

const { data: stateReceipt } = useQuery({
enabled: !!transactionId,
queryKey: ["stateReceipt", paladinTransaction],
queryKey: ["stateReceipt", transactionId],
queryFn: () => fetchStateReceipt(transactionId),
retry: false
retry: true
});

const { data: domainReceipt } = useQuery({
enabled: !!domain && !!transactionId,
queryKey: ["domainReceipt", paladinTransaction],
queryKey: ["domainReceipt", domain, transactionId],
queryFn: () => fetchDomainReceipt(domain, transactionId),
retry: false
retry: true
});

return (
Expand Down
16 changes: 12 additions & 4 deletions ui/client/src/components/Transactions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import { Box, Typography, useTheme } from "@mui/material";
import { Alert, Box, Typography, useTheme } from "@mui/material";
import { useQuery } from "@tanstack/react-query";
import { t } from "i18next";
import { useContext } from "react";
Expand All @@ -34,23 +34,31 @@ export const Transactions: React.FC = () => {
const theme = useTheme();
const addedStyle = theme.palette.mode === 'light'? altLightModeScrollbarStyle : altDarkModeScrollbarStyle;

const { data: transactions } = useQuery({
const { data: transactions, error: transactionError, isRefetching: transactionFetching } = useQuery({
queryKey: ["transactions", lastBlockWithTransactions],
queryFn: () => fetchIndexedTransactions(),
});

const { data: transactionReceipts } = useQuery({
const { data: transactionReceipts, error: receiptError, isFetching: receiptFetching } = useQuery({
queryKey: ["transactionReceipts", transactions],
queryFn: () => fetchTransactionReceipts(transactions ?? []),
enabled: transactions !== undefined,
});

const { data: paladinTransactions } = useQuery({
const { data: paladinTransactions, error: paladinTransactionError, isFetching: paladinTransactionFetching } = useQuery({
queryKey: ["paladinTransactions", transactionReceipts],
queryFn: () => fetchPaladinTransactions(transactionReceipts ?? []),
enabled: transactionReceipts !== undefined,
});

if(transactionFetching || receiptFetching || paladinTransactionFetching) {
return <></>;
}

if (transactionError || receiptError || paladinTransactionError) {
return <Alert sx={{ margin: '30px' }} severity="error" variant="filled">{transactionError?.message ?? receiptError?.message ?? paladinTransactionError?.message}</Alert>
}

return (
<>
<Typography align="center" variant="h5" sx={{ marginBottom: '20px' }}>
Expand Down
4 changes: 2 additions & 2 deletions ui/client/src/queries/abiDecode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const fetchDecodedCallData = async (

return <Promise<IABIDecodedEntry>>(
returnResponse(
await fetch(RpcEndpoint, generatePostReq(JSON.stringify(payload))), "", [500]
() => fetch(RpcEndpoint, generatePostReq(JSON.stringify(payload))), "", [500]
)
);
};
Expand All @@ -48,7 +48,7 @@ export const fetchDecodedEvent = async (

return <Promise<IABIDecodedEntry>>(
returnResponse(
await fetch(RpcEndpoint, generatePostReq(JSON.stringify(payload))), "", [500]
() => fetch(RpcEndpoint, generatePostReq(JSON.stringify(payload))), "", [500]
)
);
};
2 changes: 1 addition & 1 deletion ui/client/src/queries/blocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const fetchLatestBlockWithTxs = async (): Promise<ITransaction[]> => {

return <Promise<ITransaction[]>>(
returnResponse(
await fetch(RpcEndpoint, generatePostReq(JSON.stringify(payload))),
() => fetch(RpcEndpoint, generatePostReq(JSON.stringify(payload))),
i18next.t("errorFetchingLatestBlock")
)
);
Expand Down
9 changes: 3 additions & 6 deletions ui/client/src/queries/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,13 @@ export const generatePostReq = (stringBody: string): RequestInit => {
};

export const returnResponse = async (
res: Response,
resFn: () => Promise<Response>,
errorMsg: string,
ignoreStatuses: number[] = []
) => {
const res = await resFn();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this was the key fix - that resFn wasn't being await'ed in the previous param structure of returnResponse

if (!res.ok && !ignoreStatuses.includes(res.status)) {
throw new Error(errorMsg);
}
try {
return (await res.json()).result;
} catch {
return {};
}
return (await res.json()).result;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original goal of this try catch was to quietly handle cases where the value returned is not a valid JSON. Note that with this change we assume the response will always be a valid JSON.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very helpful to have that - I couldn't work that out from the code alone, as it seemed to be deliberately translating errors in a success payload. I thought that was the intent of the code.

A note that I didn't see a change / comments / intent described in the changes under #399, so if you have more updates to make a single approach to the different types of errors coming back to the UI true, that would be great.

The "error" categories include:

  • Something that isn't JSON/RPC came back - like a 504 gateway error, which won't be JSON parsable
  • An error specific to a JSON/RPC call came back, with an error code, which could be displayed to a user
  • An error specific to a JSON/RPC call came back, which in that particular case the UI wants to hide from the user (like the fact there is no domain receipt on the node)
  • null came back from a query describing a straight forward not found scenario

};
2 changes: 1 addition & 1 deletion ui/client/src/queries/domains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const fetchDomainReceipt = async (

return <Promise<any>>(
returnResponse(
await fetch(RpcEndpoint, generatePostReq(JSON.stringify(payload))),
() => fetch(RpcEndpoint, generatePostReq(JSON.stringify(payload))),
i18next.t("errorFetchingDomainReceipt")
)
);
Expand Down
2 changes: 1 addition & 1 deletion ui/client/src/queries/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const fetchEvents = async (): Promise<IEvent[]> => {

return <Promise<IEvent[]>>(
returnResponse(
await fetch(RpcEndpoint, generatePostReq(JSON.stringify(requestPayload))),
() => fetch(RpcEndpoint, generatePostReq(JSON.stringify(requestPayload))),
i18next.t("errorFetchingLatestEvents")
)
);
Expand Down
4 changes: 2 additions & 2 deletions ui/client/src/queries/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const fetchRegistries = async (): Promise<string[]> => {

return <Promise<string[]>>(
returnResponse(
await fetch(RpcEndpoint, generatePostReq(JSON.stringify(requestPayload))),
() => fetch(RpcEndpoint, generatePostReq(JSON.stringify(requestPayload))),
i18next.t("errorFetchingRegistries")
)
);
Expand All @@ -51,7 +51,7 @@ export const fetchRegistryEntries = async (

return <Promise<IRegistryEntry[]>>(
returnResponse(
await fetch(RpcEndpoint, generatePostReq(JSON.stringify(requestPayload))),
() => fetch(RpcEndpoint, generatePostReq(JSON.stringify(requestPayload))),
i18next.t("errorFetchingRegistryEntries")
)
);
Expand Down
2 changes: 1 addition & 1 deletion ui/client/src/queries/states.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const fetchStateReceipt = async (

return <Promise<IStateReceipt>>(
returnResponse(
await fetch(RpcEndpoint, generatePostReq(JSON.stringify(payload))),
() => fetch(RpcEndpoint, generatePostReq(JSON.stringify(payload))),
i18next.t("errorFetchingStateReceipt")
)
);
Expand Down
10 changes: 5 additions & 5 deletions ui/client/src/queries/transactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export const fetchIndexedTransactions = async (): Promise<ITransaction[]> => {

return <Promise<ITransaction[]>>(
returnResponse(
await fetch(RpcEndpoint, generatePostReq(JSON.stringify(payload))),
() => fetch(RpcEndpoint, generatePostReq(JSON.stringify(payload))),
i18next.t("errorFetchingTransactions")
)
);
Expand Down Expand Up @@ -67,7 +67,7 @@ export const fetchSubmissions = async (

return <Promise<IPaladinTransaction[]>>(
returnResponse(
await fetch(RpcEndpoint, generatePostReq(JSON.stringify(payload))),
() => fetch(RpcEndpoint, generatePostReq(JSON.stringify(payload))),
i18next.t("errorFetchingSubmissions")
)
);
Expand All @@ -85,7 +85,7 @@ export const fetchTransactionReceipt = async (

return <Promise<ITransactionReceipt>>(
returnResponse(
await fetch(RpcEndpoint, generatePostReq(JSON.stringify(payload))),
() => fetch(RpcEndpoint, generatePostReq(JSON.stringify(payload))),
i18next.t("errorFetchingTransactionReceipt")
)
);
Expand Down Expand Up @@ -115,7 +115,7 @@ export const fetchTransactionReceipts = async (

return <Promise<ITransactionReceipt[]>>(
returnResponse(
await fetch(RpcEndpoint, generatePostReq(JSON.stringify(payload))),
() => fetch(RpcEndpoint, generatePostReq(JSON.stringify(payload))),
i18next.t("errorFetchingTransactionReceipts")
)
);
Expand Down Expand Up @@ -143,7 +143,7 @@ export const fetchPaladinTransactions = async (

return <Promise<IPaladinTransaction[]>>(
returnResponse(
await fetch(RpcEndpoint, generatePostReq(JSON.stringify(payload))),
() => fetch(RpcEndpoint, generatePostReq(JSON.stringify(payload))),
i18next.t("errorFetchingPaladinTransactions")
)
);
Expand Down
Loading
Loading