Skip to content

Commit

Permalink
Refactor state management and improve app (bh2smith#478)
Browse files Browse the repository at this point in the history
- We query asset balances and collectible balances using RTK Query
- The editors raw and parsed data will be stored in the csvEditorSlice
- When the raw data of the editor gets changed a middleware triggers, which will parse the CSV file, generate the parsed transfer data and store it in the store.
- All components can simply query the data from the store to display / interact with the CSV data

Other fixes:
- default to 1 for erc1155 transfers
- ignores metadata interface and always tries to fetch metadata for NFTs
- Uses collectible endpoint v2 instead of v1
- fixes github workflow's node version
  • Loading branch information
schmanu authored Feb 20, 2023
1 parent 104b5ae commit a282e08
Show file tree
Hide file tree
Showing 38 changed files with 1,697 additions and 895 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
test:
strategy:
matrix:
node-version: [14.x]
node: [16.x]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"@material-ui/core": "^4.12.3",
"@material-ui/lab": "^4.0.0-alpha.60",
"@openzeppelin/contracts": "^4.8.1",
"@reduxjs/toolkit": "^1.8.1",
"ace-builds": "^1.15.0",
"bignumber.js": "^9.0.2",
"ethers": "^5.7.2",
Expand All @@ -36,6 +37,7 @@
"react-csv-reader": "^3.4.0",
"react-dom": "^17.0.2",
"react-dropzone": "^14.2.3",
"react-redux": "^8.0.1",
"react-scripts": "^4.0.3",
"react-svg": "^15.1.7",
"react-virtualized-auto-sizer": "^1.0.6",
Expand All @@ -48,6 +50,7 @@
"@simbathesailor/use-what-changed": "^2.0.0",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^12.1.3",
"@testing-library/react-hooks": "^8.0.1",
"@typechain/ethers-v5": "^7.1.2",
"@types/chai": "^4.3.4",
"@types/chai-as-promised": "^7.1.5",
Expand Down
46 changes: 31 additions & 15 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,51 @@ import { useSafeAppsSDK } from "@gnosis.pm/safe-apps-react-sdk";
import { BaseTransaction, GatewayTransactionDetails } from "@gnosis.pm/safe-apps-sdk";
import { Breadcrumb, BreadcrumbElement, Button, Card, Divider, Loader } from "@gnosis.pm/safe-react-components";
import { setUseWhatChange } from "@simbathesailor/use-what-changed";
import React, { useCallback, useState, useContext } from "react";
import React, { useCallback, useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Unsubscribe } from "redux";
import styled from "styled-components";

import { CSVForm } from "./components/CSVForm";
import { Header } from "./components/Header";
import { Loading } from "./components/Loading";
import { Summary } from "./components/Summary";
import { TransactionStatusScreen } from "./components/TransactionStatusScreen";
import { MessageContext } from "./contexts/MessageContextProvider";
import { useBalances } from "./hooks/balances";
import { useEnsResolver } from "./hooks/ens";
import { useTokenList } from "./hooks/token";
import { AssetTransfer, CollectibleTransfer, Transfer } from "./parser/csvParser";
import { AssetTransfer, CollectibleTransfer, useCsvParser } from "./hooks/useCsvParser";
import { useGetAssetBalanceQuery, useGetAllNFTsQuery } from "./stores/api/balanceApi";
import { setupParserListener } from "./stores/middleware/parseListener";
import { setSafeInfo } from "./stores/slices/safeInfoSlice";
import { RootState, startAppListening } from "./stores/store";
import { buildAssetTransfers, buildCollectibleTransfers } from "./transfers/transfers";

setUseWhatChange(process.env.NODE_ENV === "development");

const App: React.FC = () => {
const { isLoading } = useTokenList();
const balanceLoader = useBalances();
const [tokenTransfers, setTokenTransfers] = useState<Transfer[]>([]);
const { messages } = useContext(MessageContext);
const [parsing, setParsing] = useState(false);
const { sdk } = useSafeAppsSDK();
const { sdk, safe } = useSafeAppsSDK();
const assetBalanceQuery = useGetAssetBalanceQuery();
const nftBalanceQuery = useGetAllNFTsQuery();

const { messages } = useSelector((state: RootState) => state.messages);
const { transfers, parsing } = useSelector((state: RootState) => state.csvEditor);

const [pendingTx, setPendingTx] = useState<GatewayTransactionDetails>();
const assetTransfers = tokenTransfers.filter(
const { parseCsv } = useCsvParser();
const ensResolver = useEnsResolver();
const dispatch = useDispatch();

useEffect(() => {
dispatch(setSafeInfo(safe));
const subscriptions: Unsubscribe[] = [setupParserListener(startAppListening, parseCsv, ensResolver)];
return () => subscriptions.forEach((unsubscribe) => unsubscribe());
}, [dispatch, safe, sdk, parseCsv, ensResolver]);

const assetTransfers = transfers.filter(
(transfer) => transfer.token_type === "erc20" || transfer.token_type === "native",
) as AssetTransfer[];
const collectibleTransfers = tokenTransfers.filter(
const collectibleTransfers = transfers.filter(
(transfer) => transfer.token_type === "erc1155" || transfer.token_type === "erc721",
) as CollectibleTransfer[];

Expand All @@ -39,7 +56,6 @@ const App: React.FC = () => {
txs.push(...buildAssetTransfers(assetTransfers));
txs.push(...buildCollectibleTransfers(collectibleTransfers));

console.log(`Encoded ${txs.length} transfers.`);
const sendTxResponse = await sdk.txs.send({ txs });
const safeTx = await sdk.txs.getBySafeTxHash(sendTxResponse.safeTxHash);
setPendingTx(safeTx);
Expand All @@ -53,7 +69,7 @@ const App: React.FC = () => {
<Header />
{
<>
{isLoading || balanceLoader.isLoading ? (
{isLoading || assetBalanceQuery.isLoading || nftBalanceQuery.isLoading ? (
<Loading />
) : (
<Card className="cardWithCustomShadow">
Expand All @@ -62,7 +78,7 @@ const App: React.FC = () => {
<Breadcrumb>
<BreadcrumbElement text="CSV Transfer File" iconType="paste" />
</Breadcrumb>
<CSVForm updateTransferTable={setTokenTransfers} setParsing={setParsing} />
<CSVForm />
<Divider />
</>
)}
Expand All @@ -79,7 +95,7 @@ const App: React.FC = () => {
size="lg"
color={messages.length === 0 ? "primary" : "error"}
onClick={submitTx}
disabled={parsing || tokenTransfers.length + collectibleTransfers.length === 0}
disabled={parsing || transfers.length + collectibleTransfers.length === 0}
>
{parsing ? (
<Loader size="sm" color="primaryLight" />
Expand Down
Loading

0 comments on commit a282e08

Please sign in to comment.