Skip to content

Commit

Permalink
Move towards using react-query for account data lifecycles (#215)
Browse files Browse the repository at this point in the history
* yes, I think this is less code :)

Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>

* move the react-query query function to getAccountss.ts

Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>

* WIP - i get a blank electron, no dev-tools, and no errors in the console :(

Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>

* WIP - i get a blank electron, no dev-tools, and no errors in the console :(

Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>

* why do I keep having to fix this?

Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>

* and now it works - useQuery for tokenlinst

Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>

* token metadata react-query

Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>

* use react-query for top level AccountView getParsedAccount request

Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>

* how does it look when we have a useParsedAccount(net, pubKey) hook?

Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>

* invalidate the react-query cache on demand, and on mint - but ... it needs a tiny delay :/

Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>

* replace useInterval with useQuery - not perfect, but not spamming the rpic endpoint either - for #207

Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>

* linties

Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>

* ok, weird fix, but letting the mint info retry seems to make the Mint accordion work

Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>

* sssshhhh those logs

Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>

* sssshhhh those logs

Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>

* noidea what changed this, remove

Signed-off-by: Sven Dowideit <SvenDowideit@home.org.au>
  • Loading branch information
SvenDowideit authored Jul 15, 2022
1 parent 43f3509 commit 773b7ae
Show file tree
Hide file tree
Showing 11 changed files with 439 additions and 312 deletions.
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@
"[json]": {
"editor.defaultFormatter": "vscode.json-language-features"
}
}
}
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -222,17 +222,17 @@
"@fortawesome/react-fontawesome": "^0.1.18",
"@metaplex/js": "^4.12.0",
"@reduxjs/toolkit": "^1.7.2",
"@solana/spl-token": "^0.2.0",
"@solana/wallet-adapter-base": "^0.9.5",
"@solana/wallet-adapter-react": "^0.15.4",
"@solana/wallet-adapter-react-ui": "^0.9.6",
"@solana/spl-token": "^0.2.0",
"amplitude-js": "^8.12.0",
"ansi_up": "^5.1.0",
"bip39": "^3.0.4",
"bootstrap": "^5.1.3",
"buffer": "^6.0.3",
"classnames": "^2.3.1",
"dockerode": "^3.3.2",
"buffer": "^6.0.3",
"dompurify": "^2.3.8",
"electron-cfg": "^1.2.7",
"electron-debug": "^3.2.0",
Expand All @@ -247,6 +247,7 @@
"react-dom": "^18.1.0",
"react-editext": "^4.2.1",
"react-outside-click-handler": "^1.3.0",
"react-query": "^3.39.1",
"react-redux": "^8.0.1",
"react-router": "^6.2.2",
"react-router-dom": "^6.2.2",
Expand Down
9 changes: 5 additions & 4 deletions src/renderer/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ import {
import '@solana/wallet-adapter-react-ui/styles.css';
import * as sol from '@solana/web3.js';
import isElectron from 'is-electron';
import { FC, useMemo, useState } from 'react';
import React, { FC, useMemo, useState } from 'react';
import { Button, Form } from 'react-bootstrap';
import Container from 'react-bootstrap/Container';
import OverlayTrigger from 'react-bootstrap/OverlayTrigger';
import Tooltip from 'react-bootstrap/Tooltip';
import { NavLink, Outlet, Route, Routes } from 'react-router-dom';
import { ToastContainer } from 'react-toastify';

import { logger } from './common/globals';
import 'react-toastify/dist/ReactToastify.css';
import './App.scss';
Expand Down Expand Up @@ -55,9 +56,9 @@ declare global {
}

const TooltipNavItem: React.FC<{
to: string;
tooltipMessage: string;
eventKey: string;
to?: string;
tooltipMessage?: string;
eventKey?: string;
children?: React.ReactNode;
}> = ({ to, tooltipMessage, eventKey, children }) => {
return (
Expand Down
157 changes: 19 additions & 138 deletions src/renderer/components/AccountView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,64 +3,63 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import React, { useEffect, useState } from 'react';
import ButtonToolbar from 'react-bootstrap/ButtonToolbar';
import Container from 'react-bootstrap/Container';
import Table from 'react-bootstrap/Table';
import { Accordion, Button, Card } from 'react-bootstrap';
import { Button } from 'react-bootstrap';
import {
useConnection,
useWallet,
useAnchorWallet,
} from '@solana/wallet-adapter-react';
import { Program, AnchorProvider, setProvider } from '@project-serum/anchor';
import * as sol from '@solana/web3.js';
import { useQueryClient } from 'react-query';
import { logger } from '../common/globals';
import { useInterval, useAppDispatch, useAppSelector } from '../hooks';
import { useAppDispatch, useAppSelector } from '../hooks';

import { AccountInfo } from '../data/accounts/accountInfo';
import {
setAccountValues,
useAccountMeta,
} from '../data/accounts/accountState';
import {
truncateSolAmount,
getHumanName,
getParsedAccount,
getTokenAccounts,
TokenAccountArray,
forceRequestAccount,
renderRawData,
truncateLamportAmount,
useParsedAccount,
} from '../data/accounts/getAccount';
import {
NetStatus,
netToURL,
selectValidatorNetworkState,
} from '../data/ValidatorNetwork/validatorNetworkState';
import AirDropSolButton from './AirDropSolButton';
import EditableText from './base/EditableText';
import InlinePK from './InlinePK';
import TransferSolButton from './TransferSolButton';
import { MintInfoView } from './MintInfoView';
import { MetaplexMintMetaDataView } from './tokens/MetaplexMintMetaDataView';

import CreateNewMintButton, {
ensureAtaFor,
} from './tokens/CreateNewMintButton';
import MintTokenToButton from './tokens/MintTokenToButton';
import TransferTokenButton from './tokens/TransferTokenButton';

import { TokensListView } from './tokens/TokensListView';

function AccountView(props: { pubKey: string | undefined }) {
const { pubKey } = props;
const { net, status } = useAppSelector(selectValidatorNetworkState);
const { net } = useAppSelector(selectValidatorNetworkState);
const dispatch = useAppDispatch();
const accountMeta = useAccountMeta(pubKey);
const [humanName, setHumanName] = useState<string>('');
const accountPubKey = pubKey ? new sol.PublicKey(pubKey) : undefined;
const fromKey = useWallet(); // pay from wallet adapter
const { connection } = useConnection();
const queryClient = useQueryClient();

const [account, setSelectedAccountInfo] = useState<AccountInfo | undefined>(
undefined
const { /* loadStatus, */ account /* , error */ } = useParsedAccount(
net,
pubKey
);
const [tokenAccounts, setTokenAccounts] = useState<TokenAccountArray>([]);

// ("idle" or "error" or "loading" or "success").
// TODO: this can't be here before the query
// TODO: there's a better way in query v4 - https://tkdodo.eu/blog/offline-react-query

// create dummy keypair wallet if none is selected by user
// eslint-disable-next-line react-hooks/exhaustive-deps
Expand Down Expand Up @@ -122,32 +121,9 @@ function AccountView(props: { pubKey: string | undefined }) {
decodeAnchor();
}, [account, net, wallet]);

useInterval(() => {
// TODO: really would like to subscribe to a list of accounts - even if its via the getAccounts cache
if (status !== NetStatus.Running) {
return;
}
if (pubKey) {
getParsedAccount(net, pubKey)
.then((info) => {
if (info) {
setSelectedAccountInfo(info);
}
return info;
})
.catch(logger.error);
getTokenAccounts(net, pubKey)
.then((b) => setTokenAccounts(b?.value))
.catch(logger.info);
} else {
setSelectedAccountInfo(undefined);
}
}, 6666);

useEffect(() => {
const alias = getHumanName(accountMeta);
setHumanName(alias);
logger.info(`get human name for pubKey ${pubKey} == ${alias}`);
}, [pubKey, accountMeta]);

const handleHumanNameSave = (val: string) => {
Expand Down Expand Up @@ -177,6 +153,7 @@ function AccountView(props: { pubKey: string | undefined }) {
if (pubKey) {
forceRequestAccount(net, pubKey);
// force refresh for ATA's, PDA's etc?
queryClient.invalidateQueries(); // TODO: this is too broad
}
}}
>
Expand Down Expand Up @@ -278,9 +255,7 @@ function AccountView(props: { pubKey: string | undefined }) {

<div className="ms-1">
<div>
<small className="text-muted">
Token Accounts ({tokenAccounts?.length})
</small>
<small className="text-muted">Token Accounts </small>
{/* this button should only be enabled for accounts that you can create a new mint for... */}
<CreateNewMintButton
disabled={
Expand All @@ -299,101 +274,7 @@ function AccountView(props: { pubKey: string | undefined }) {
/>
</div>
<div>
<Table hover size="sm">
<tbody>
{tokenAccounts?.map(
(tAccount: {
pubkey: sol.PublicKey;
account: sol.AccountInfo<sol.ParsedAccountData>;
}) => {
// TODO: extract to its own component
return (
<Card>
<Card.Body>
<Card.Title />
<Card.Text>
<Accordion flush>
<Accordion.Item eventKey="1">
<Accordion.Header>
<div>
<b>ATA</b>
<InlinePK
pk={tAccount.pubkey.toString()}
formatLength={9}
/>{' '}
</div>
<div>
holds{' '}
{
tAccount.account.data.parsed.info
.tokenAmount.amount
}{' '}
tokens (
{truncateSolAmount(
tAccount.account.lamports /
sol.LAMPORTS_PER_SOL
)}{' '}
SOL)
<MintTokenToButton
disabled={
// TODO: ONLY IF the wallet user has mint-auth (and should mint to this user...)
fromKey.publicKey?.toString() !==
accountPubKey?.toString()
}
connection={connection}
fromKey={fromKey}
mintKey={
new sol.PublicKey(
tAccount.account.data.parsed.info.mint.toString()
)
}
mintTo={accountPubKey}
andThen={(): void => {}}
/>
<TransferTokenButton
disabled={
// TODO: ONLY IF the wallet user has permission to mutate this ATA's tokens...
fromKey.publicKey?.toString() !==
accountPubKey?.toString()
}
connection={connection}
fromKey={fromKey}
mintKey={tAccount.account.data.parsed.info.mint.toString()}
transferFrom={pubKey}
/>
</div>
</Accordion.Header>
<Accordion.Body>
<pre className="exe-hexdump p-2 rounded">
<code>
{JSON.stringify(
tAccount.account,
null,
2
)}
</code>
</pre>
</Accordion.Body>
</Accordion.Item>
<MintInfoView
mintKey={
tAccount.account.data.parsed.info.mint
}
/>
<MetaplexMintMetaDataView
mintKey={
tAccount.account.data.parsed.info.mint
}
/>
</Accordion>
</Card.Text>
</Card.Body>
</Card>
);
}
)}
</tbody>
</Table>
<TokensListView pubKey={pubKey} />
</div>
</div>
</div>
Expand Down
Loading

0 comments on commit 773b7ae

Please sign in to comment.