Skip to content

Commit

Permalink
tx table and expandable transfer descriptions looking great and user …
Browse files Browse the repository at this point in the history
…history container has been integrated into the jar stats page nicely
  • Loading branch information
bcstryker committed Aug 23, 2022
1 parent e782118 commit 595f077
Show file tree
Hide file tree
Showing 9 changed files with 309 additions and 11 deletions.
60 changes: 51 additions & 9 deletions v2/features/stats/JarStats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@ import { useSelector } from "react-redux";
import { PickleModelJson } from "picklefinance-core";

import { AssetWithData, CoreSelectors } from "v2/store/core";
import type { JarChartData, SetFunction } from "v2/types";
import type { JarChartData, SetFunction, UserTx } from "v2/types";
import ChartContainer from "v2/features/stats/jar/ChartContainer";
import DocContainer from "v2/features/stats/jar/DocContainer";
import DocContainer, { RelatedTokens } from "v2/features/stats/jar/DocContainer";
import RevTableContainer from "v2/features/stats/jar/RevTableContainer";
import FarmsTable from "v2/features/farms/FarmsTable";
import { JarSelectData } from "./JarSelect";
import { readyState } from "pages/stats";
import { useAccount } from "v2/hooks";
import TxHistoryTable from "./jar/userHistory/TxHistoryContainer";
import { JarDefinition } from "picklefinance-core/lib/model/PickleModelJson";
import { useTranslation } from "next-i18next";
import TxHistoryContainer from "./jar/userHistory/TxHistoryContainer";

const JarStats: FC<{
core: PickleModelJson.PickleModelJson | undefined;
Expand All @@ -18,14 +23,28 @@ const JarStats: FC<{
setReady: SetFunction;
page: "platform" | "chain" | "jar" | undefined;
}> = ({ core, jar, ready, setReady, page }) => {
const { t } = useTranslation("common");
const account = useAccount();
let assets = useSelector(CoreSelectors.makeAssetsSelector({ filtered: false, paginated: false }));

const [jarData, setJarData] = useState<JarChartData>({} as JarChartData);
const [userJarHistory, setUserJarHistory] = useState<UserTx[]>([]);

let asset: AssetWithData | undefined = {} as AssetWithData;
let assetJar: JarDefinition | undefined = {} as JarDefinition;
if (jar && jar.value)
asset = assets.find((a) => a.details.apiKey.toLowerCase() === jar.value.toLowerCase());
if (asset) assetJar = core?.assets.jars.find((j) => j.contract == asset?.contract);

const addrs = Object.fromEntries(
Object.entries({
User: "0xfeedc450742ac0d9bb38341d9939449e3270f76f", //account,
Jar: assetJar ? assetJar.contract.toLowerCase() : "jar not found",
Farm: assetJar && assetJar.farm ? assetJar.farm.farmAddress.toLowerCase() : "farm not found",
Null: "0x0000000000000000000000000000000000000000",
}).map(([key, value]) => [value, key]),
);
// console.log(addrs);
useEffect(() => {
const getData = async (): Promise<void> => {
if (Object.keys(jar).length > 0)
Expand All @@ -36,6 +55,19 @@ const JarStats: FC<{
getData();
}, [jar]);

useEffect(() => {
const getUserJarHistory = async (account: string | null | undefined): Promise<void> => {
account = "0xfeedc450742ac0d9bb38341d9939449e3270f76f";
account &&
(await fetch(`https://api.pickle.finance/prod/protocol/userhistory/${account}`)
.then((resp) => resp.json())
.then((jsonResp) => {
setUserJarHistory(jsonResp && jsonResp[jar.value] ? jsonResp[jar.value].reverse() : []);
}));
};
getUserJarHistory(account);
}, [account]);

if (asset && page === "jar" && ready[page])
return (
<>
Expand All @@ -46,14 +78,24 @@ const JarStats: FC<{
</div>
<ChartContainer jarData={jarData} />
{jarData && jarData.documentation && <DocContainer docs={jarData.documentation} />}
{jarData &&
jarData.revenueExpenses &&
jarData.revenueExpenses.recentHarvests.length > 0 && (
<RevTableContainer
revs={jarData.revenueExpenses}
pfCore={core ? core : ({} as PickleModelJson.PickleModelJson)}
/>
<div className="flex">
{userJarHistory && userJarHistory.length > 0 && (
<TxHistoryContainer txHistory={userJarHistory} addrs={addrs} t={t} />
)}
<div>
{jarData && jarData.documentation && (
<RelatedTokens componentTokens={jarData.documentation.componentTokens} t={t} />
)}
{jarData &&
jarData.revenueExpenses &&
jarData.revenueExpenses.recentHarvests.length > 0 && (
<RevTableContainer
revs={jarData.revenueExpenses}
pfCore={core ? core : ({} as PickleModelJson.PickleModelJson)}
/>
)}
</div>
</div>
</>
);
return null;
Expand Down
4 changes: 2 additions & 2 deletions v2/features/stats/jar/DocContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const DocContainer: FC<{ docs: AssetDocumentationResult }> = ({ docs }) => {
<Social social={social} t={t} />
<Risks risks={risks} t={t} />
</div>
<RelatedTokens componentTokens={componentTokens} t={t} />
{/* <RelatedTokens componentTokens={componentTokens} t={t} /> */}
</>
);
};
Expand Down Expand Up @@ -98,7 +98,7 @@ const Risks: FC<{ risks: string[]; t: TFunction }> = ({ risks, t }) => (
</div>
);

const RelatedTokens: FC<{ componentTokens: { [key: string]: string }; t: TFunction }> = ({
export const RelatedTokens: FC<{ componentTokens: { [key: string]: string }; t: TFunction }> = ({
componentTokens,
t,
}) => {
Expand Down
21 changes: 21 additions & 0 deletions v2/features/stats/jar/userHistory/TxHistoryContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { TFunction } from "next-i18next";
import { FC } from "react";
import { UserTx } from "v2/types";
import { classNames } from "v2/utils";
import TxHistoryTable from "./TxHistoryTable";

const TxHistoryContainer: FC<{
txHistory: UserTx[];
addrs: { [key: string]: string };
t: TFunction;
className?: string;
}> = ({ txHistory, addrs, t, className }) => (
<div className={classNames("pr-5", className)}>
<h2 className="font-body font-bold text-xl text-foreground-alt-200 mt-3 mb-5">
{"User History"}
</h2>
<TxHistoryTable txHistory={txHistory} addrs={addrs} />
</div>
);

export default TxHistoryContainer;
47 changes: 47 additions & 0 deletions v2/features/stats/jar/userHistory/TxHistoryTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { FC } from "react";
import { UserTx } from "v2/types";
import { classNames } from "v2/utils";
import TxTableBody from "./TxTableBody";

const TxHistoryTable: FC<{
txHistory: UserTx[];
addrs: { [key: string]: string };
className?: string;
}> = ({ txHistory, addrs, className }) => {
return (
<div className={classNames("flex flex-col", className)}>
<div className="-my-2 overflow-x-auto">
<div className="py-2 align-middle inline-block min-w-full">
<table className="min-w-1/2 table-auto border-collapse">
<thead className="bg-background uppercase">
<tr>
<TxTableHeaderCell label="Date/Time" />
<TxTableHeaderCell label="Block Num." />
<TxTableHeaderCell label="TX Type" />
<TxTableHeaderCell label="TX Hash" />
{/* Chevron down/up column */}
</tr>
</thead>
<tbody className="text-foreground">
<TxTableBody txs={txHistory} addrs={addrs} />
</tbody>
</table>
{/* <div className="flex justify-center mt-4">
<Pagination />
</div> */}
</div>
</div>
</div>
);
};

const TxTableHeaderCell: FC<{ label: string }> = ({ label }) => (
<th
scope="col"
className="px-4 py-1 h-8 text-left text-xs font-bold text-foreground-alt-200 tracking-normal sm:px-6"
>
{label}
</th>
);

export default TxHistoryTable;
46 changes: 46 additions & 0 deletions v2/features/stats/jar/userHistory/TxTableBody.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Disclosure, Transition } from "@headlessui/react";
import { FC, Fragment } from "react";
import { UserTx } from "v2/types";
import { classNames } from "v2/utils";
import TxTableRowBody from "./TxTableRowBody";
import TxTableRowHeader from "./TxTableRowHeader";
import TxTableSpacerRow from "./TxTableSpacerRow";

const TxTableBody: FC<{ txs: UserTx[]; addrs: { [key: string]: string } }> = ({ txs, addrs }) => (
<>{txs && txs.map((tx) => <TxTableRow key={tx.hash} tx={tx} addrs={addrs} />)}</>
);

const TxTableRow: FC<{ tx: UserTx; addrs: { [key: string]: string } }> = ({ tx, addrs }) => (
<>
<Disclosure as={Fragment}>
{({ open }) => (
<>
<Disclosure.Button
as="tr"
// No hover state when the row is expaned.
className={classNames(!open && "group", "cursor-pointer")}
>
<TxTableRowHeader tx={tx} open={open} />
</Disclosure.Button>

<Transition
as={Fragment}
enter="transition duration-100 ease-out"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transition duration-100 ease-out"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<Disclosure.Panel as="tr">
<TxTableRowBody transfers={tx.transfers} addrs={addrs} />
</Disclosure.Panel>
</Transition>
</>
)}
</Disclosure>
<TxTableSpacerRow />
</>
);

export default TxTableBody;
47 changes: 47 additions & 0 deletions v2/features/stats/jar/userHistory/TxTableRowBody.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { FC } from "react";
import { UserTransfer } from "v2/types";
import { formatNumber } from "v2/utils";

const TxTableRowBody: FC<{ transfers: UserTransfer[]; addrs: { [key: string]: string } }> = ({
transfers,
addrs,
}) => (
<td
colSpan={6}
className="bg-background-light rounded-b-xl p-6 border-t border-foreground-alt-500"
>
<div className="flex justify-evenly">
<div className="py-2 flex-shrink-0 mr-6">
{transfers.map((t) => (
<p className="text-foreground-alt-200" key={t.log_index}>
{transferToString(t, addrs)}
</p>
))}
</div>
</div>
</td>
);

const transferToString = (transfer: UserTransfer, addrs: { [key: string]: string }) => {
const fromAddr =
addrs[transfer.fromAddress] ||
transfer.fromAddress.slice(0, 5) + "..." + transfer.fromAddress.slice(-3);
const toAddr =
addrs[transfer.toAddress] ||
transfer.toAddress.slice(0, 5) + "..." + transfer.toAddress.slice(-3);

const burned = toAddr === "Null";
const minted = fromAddr === "Null";
const nTokens =
transfer.price && transfer.value
? formatNumber(+transfer.price / transfer.value, 8)
: "an unknown number of";
const value = transfer.value ? "(" + formatNumber(transfer.value, 2) + " USD)" : "";
return burned
? `${fromAddr} burned ${nTokens} tokens ${value}`
: minted
? `${nTokens} ${value} were minted and sent to ${toAddr}`
: `${fromAddr} sent ${nTokens} tokens ${value} to ${toAddr}`;
};

export default TxTableRowBody;
63 changes: 63 additions & 0 deletions v2/features/stats/jar/userHistory/TxTableRowHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { ChevronDownIcon } from "@heroicons/react/solid";
import { FC, HTMLAttributes } from "react";
import { UserTx } from "v2/types";
import { classNames, formatDate } from "v2/utils";

const TxTableRowHeader: FC<{ tx: UserTx; open: boolean }> = ({ tx, open }) => {
return (
<>
<RowCell className={classNames(!open && "rounded-bl-xl", "rounded-tl-xl flex items-center")}>
<p className="font-title font-medium text-base leading-5 text-foreground-alt-200">
{formatDate(new Date(tx.timestamp * 1000))}
</p>
</RowCell>
<RowCell>
<p className="font-title font-medium text-base leading-5 text-foreground-alt-200">
{tx.blocknumber}
</p>
</RowCell>
<RowCell>
<div className="flex items-center">
<div className="ml-2">
<p className="font-title font-medium text-base leading-5 text-foreground-alt-200">
{tx.transaction_type}
</p>
</div>
</div>
</RowCell>
<RowCell>
<p
className={classNames(
"font-title font-medium text-base leading-5 text-foreground-alt-200",
)}
>
{tx.hash.slice(0, 5) + "..." + tx.hash.slice(-3)}
</p>
</RowCell>
<RowCell className={classNames(!open && "rounded-br-xl", "rounded-tr-xl w-10")}>
<div className="flex justify-end pr-3">
<ChevronDownIcon
className={classNames(
open && "rotate-180",
"text-foreground ml-2 h-5 w-5 transition duration-300 ease-in-out",
)}
aria-hidden="true"
/>
</div>
</RowCell>
</>
);
};

const RowCell: FC<HTMLAttributes<HTMLElement>> = ({ children, className }) => (
<td
className={classNames(
"bg-background-light p-4 whitespace-nowrap text-sm text-foreground sm:p-6 group-hover:bg-background-lightest transition duration-300 ease-in-out",
className,
)}
>
{children}
</td>
);

export default TxTableRowHeader;
11 changes: 11 additions & 0 deletions v2/features/stats/jar/userHistory/TxTableSpacerRow.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { FC } from "react";

const TxTableSpacerRow: FC = () => {
return (
<tr>
<td colSpan={5} className="bg-background p-1"></td>
</tr>
);
};

export default TxTableSpacerRow;
21 changes: 21 additions & 0 deletions v2/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,27 @@ export interface Transfer {
weiSent: string;
}

export interface UserTx {
hash: string;
transaction_type: string;
chain_id: number;
timestamp: number;
blocknumber: number;
indexInBlock: number;
transfers: UserTransfer[];
}

export interface UserTransfer {
amount: string;
transfer_type: string;
log_index: number;
fromAddress: string;
toAddress: string;
tokenAddress: string;
price: string;
value: number;
}

export interface ApyChartData {
timestamp: number;
jarApr: number;
Expand Down

0 comments on commit 595f077

Please sign in to comment.