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

Fixup coin holders page / Add transactions #918

Merged
merged 2 commits into from
Nov 15, 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
48 changes: 48 additions & 0 deletions src/api/hooks/useGetCoinActivities.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {useQuery as useGraphqlQuery} from "@apollo/client/react/hooks/useQuery";
import {gql} from "@apollo/client";

export type FAActivity = {
transaction_version: number;
transaction_timestamp: string;
owner_address: string;
};

export function useGetCoinActivities(
asset: string,
offset?: number,
): {
isLoading: boolean;
error: any;
data: FAActivity[] | undefined;
} {
const {loading, error, data} = useGraphqlQuery<{
fungible_asset_activities: FAActivity[];
}>(
// Exclude gas fees from the list
gql`
query GetFungibleAssetActivities($asset: String, $offset: Int) {
fungible_asset_activities(
where: {
asset_type: {_eq: $asset}
type: {_neq: "0x1::aptos_coin::GasFeeEvent"}
}
offset: $offset
limit: 100
order_by: {transaction_version: desc}
distinct_on: transaction_version
) {
transaction_version
owner_address
transaction_timestamp
}
}
`,
{variables: {asset, offset: offset ?? 0}},
);

return {
isLoading: loading,
error,
data: data?.fungible_asset_activities,
};
}
10 changes: 7 additions & 3 deletions src/api/hooks/useGetCoinHolders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ export type CoinHolder = {
amount: number;
};

export function useGetCoinHolders(coin_type: string): {
export function useGetCoinHolders(
coin_type: string,
offset?: number,
): {
isLoading: boolean;
error: any;
data: CoinHolder[] | undefined;
Expand All @@ -15,18 +18,19 @@ export function useGetCoinHolders(coin_type: string): {
current_fungible_asset_balances: CoinHolder[];
}>(
gql`
query GetFungibleAssetBalances($coin_type: String!) {
query GetFungibleAssetBalances($coin_type: String!, $offset: Int!) {
current_fungible_asset_balances(
where: {asset_type: {_eq: $coin_type}}
limit: 100
offset: $offset
order_by: {amount: desc}
) {
owner_address
amount
}
}
`,
{variables: {coin_type}},
{variables: {coin_type, offset: offset ?? 0}},
);

return {
Expand Down
2 changes: 1 addition & 1 deletion src/pages/Coin/Index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {useGetCoinSupplyLimit} from "../../api/hooks/useGetCoinSupplyLimit";
import {useGetCoinList} from "../../api/hooks/useGetCoinList";
import {findCoinData} from "../Transaction/Tabs/BalanceChangeTab";

const TAB_VALUES_FULL: TabValue[] = ["info", "holders"];
const TAB_VALUES_FULL: TabValue[] = ["info", "holders", "transactions"];

const TAB_VALUES: TabValue[] = ["info"];

Expand Down
8 changes: 7 additions & 1 deletion src/pages/Coin/Tabs/HoldersTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import GeneralTableRow from "../../../components/Table/GeneralTableRow";
import GeneralTableCell from "../../../components/Table/GeneralTableCell";
import HashButton, {HashType} from "../../../components/HashButton";
import {getFormattedBalanceStr} from "../../../components/IndividualPageContent/ContentValue/CurrencyValue";
import LoadingModal from "../../../components/LoadingModal";

type HoldersTabProps = {
struct: string;
Expand All @@ -22,6 +23,9 @@ type HoldersTabProps = {

export default function HoldersTab({struct, data}: HoldersTabProps) {
const holderData = useGetCoinHolders(struct);
if (holderData?.isLoading) {
return <LoadingModal open={true} />;
}
if (!data || Array.isArray(data) || !holderData?.data) {
return <EmptyTabContent />;
}
Expand All @@ -40,14 +44,16 @@ export function HoldersTable({
<Table>
<TableHead>
<TableRow>
<GeneralTableHeaderCell header="rank" />
<GeneralTableHeaderCell header="address" />
<GeneralTableHeaderCell header="amount" textAlignRight={true} />
</TableRow>
</TableHead>
<GeneralTableBody>
{holders.map((holder) => {
{holders.map((holder, i) => {
return (
<GeneralTableRow>
<GeneralTableCell>{i}</GeneralTableCell>
<GeneralTableCell>
<HashButton
hash={holder.owner_address}
Expand Down
64 changes: 61 additions & 3 deletions src/pages/Coin/Tabs/TransactionsTab.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,71 @@
import React from "react";
import EmptyTabContent from "../../../components/IndividualPageContent/EmptyTabContent";
import LoadingModal from "../../../components/LoadingModal";
import Table from "@mui/material/Table";
import TableHead from "@mui/material/TableHead";
import TableRow from "@mui/material/TableRow";
import GeneralTableHeaderCell from "../../../components/Table/GeneralTableHeaderCell";
import GeneralTableBody from "../../../components/Table/GeneralTableBody";
import GeneralTableRow from "../../../components/Table/GeneralTableRow";
import GeneralTableCell from "../../../components/Table/GeneralTableCell";
import HashButton, {HashType} from "../../../components/HashButton";
import {
FAActivity,
useGetCoinActivities,
} from "../../../api/hooks/useGetCoinActivities";
import {CoinData} from "../Components/CoinData";

type TransactionsTabProps = {
struct: string;
data: CoinData | undefined;
};

export default function TransactionsTab({}: TransactionsTabProps) {
// TODO: Lookup transactions by coin
return <EmptyTabContent />;
export default function TransactionsTab({struct, data}: TransactionsTabProps) {
const holderData = useGetCoinActivities(struct);
if (holderData?.isLoading) {
return <LoadingModal open={true} />;
}
if (!data || Array.isArray(data) || !holderData?.data) {
return <EmptyTabContent />;
}

return <FAActivityTable data={data} activities={holderData.data} />;
}

export function FAActivityTable({
activities,
}: {
activities: FAActivity[];
data: CoinData;
}) {
return (
<Table>
<TableHead>
<TableRow>
<GeneralTableHeaderCell header="version" />
<GeneralTableHeaderCell header="sender" />
</TableRow>
</TableHead>
<GeneralTableBody>
{activities.map((activity) => {
return (
<GeneralTableRow>
<GeneralTableCell>
<HashButton
hash={activity.transaction_version.toString()}
type={HashType.TRANSACTION}
/>
</GeneralTableCell>
<GeneralTableCell>
<HashButton
hash={activity.owner_address}
type={HashType.ACCOUNT}
/>
</GeneralTableCell>
</GeneralTableRow>
);
})}
</GeneralTableBody>
</Table>
);
}
2 changes: 1 addition & 1 deletion src/pages/FungibleAsset/Index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {useGetFASupply} from "../../api/hooks/useGetFaSupply";
import {CoinDescription, useGetCoinList} from "../../api/hooks/useGetCoinList";
import {findCoinData} from "../Transaction/Tabs/BalanceChangeTab";

const TAB_VALUES_FULL: TabValue[] = ["info", "holders"];
const TAB_VALUES_FULL: TabValue[] = ["info", "holders", "transactions"];

const TAB_VALUES: TabValue[] = ["info"];

Expand Down
4 changes: 4 additions & 0 deletions src/pages/FungibleAsset/Tabs/HoldersTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import GeneralTableCell from "../../../components/Table/GeneralTableCell";
import HashButton, {HashType} from "../../../components/HashButton";
import {getFormattedBalanceStr} from "../../../components/IndividualPageContent/ContentValue/CurrencyValue";
import {FACombinedData} from "../Index";
import LoadingModal from "../../../components/LoadingModal";

type HoldersTabProps = {
address: string;
Expand All @@ -22,6 +23,9 @@ type HoldersTabProps = {

export default function HoldersTab({address, data}: HoldersTabProps) {
const holderData = useGetCoinHolders(address);
if (holderData?.isLoading) {
return <LoadingModal open={true} />;
}
if (!data || Array.isArray(data) || !holderData?.data) {
return <EmptyTabContent />;
}
Expand Down
64 changes: 61 additions & 3 deletions src/pages/FungibleAsset/Tabs/TransactionsTab.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,71 @@
import React from "react";
import EmptyTabContent from "../../../components/IndividualPageContent/EmptyTabContent";
import {FACombinedData} from "../Index";
import LoadingModal from "../../../components/LoadingModal";
import Table from "@mui/material/Table";
import TableHead from "@mui/material/TableHead";
import TableRow from "@mui/material/TableRow";
import GeneralTableHeaderCell from "../../../components/Table/GeneralTableHeaderCell";
import GeneralTableBody from "../../../components/Table/GeneralTableBody";
import GeneralTableRow from "../../../components/Table/GeneralTableRow";
import GeneralTableCell from "../../../components/Table/GeneralTableCell";
import HashButton, {HashType} from "../../../components/HashButton";
import {
FAActivity,
useGetCoinActivities,
} from "../../../api/hooks/useGetCoinActivities";

type TransactionsTabProps = {
address: string;
data: FACombinedData | undefined;
};

export default function TransactionsTab({}: TransactionsTabProps) {
// TODO: Lookup transactions by coin
return <EmptyTabContent />;
export default function TransactionsTab({address, data}: TransactionsTabProps) {
const holderData = useGetCoinActivities(address);
if (holderData?.isLoading) {
return <LoadingModal open={true} />;
}
if (!data || Array.isArray(data) || !holderData?.data) {
return <EmptyTabContent />;
}

return <FAActivityTable data={data} activities={holderData.data} />;
}

export function FAActivityTable({
activities,
}: {
activities: FAActivity[];
data: FACombinedData;
}) {
return (
<Table>
<TableHead>
<TableRow>
<GeneralTableHeaderCell header="version" />
<GeneralTableHeaderCell header="sender" />
</TableRow>
</TableHead>
<GeneralTableBody>
{activities.map((activity) => {
return (
<GeneralTableRow>
<GeneralTableCell>
<HashButton
hash={activity.transaction_version.toString()}
type={HashType.TRANSACTION}
/>
</GeneralTableCell>
<GeneralTableCell>
<HashButton
hash={activity.owner_address}
type={HashType.ACCOUNT}
/>
</GeneralTableCell>
</GeneralTableRow>
);
})}
</GeneralTableBody>
</Table>
);
}