Skip to content
Snippets Groups Projects
Commit d04dbf91 authored by Lukas's avatar Lukas
Browse files

Merge branch 'develop' into lbudginas/#485_collapsible_filters_on_balance_history_page

parents 2658a6e4 192ad2a7
No related branches found
No related tags found
1 merge request!588Lbudginas/#485 collapsible filters on balance history page
Pipeline #117646 failed
import { useState } from "react";
import { QueryObserverResult } from "@tanstack/react-query";
import { config } from "@/Config";
import Hive from "@/types/Hive";
import useWitnessDetails from "@/hooks/api/common/useWitnessDetails";
import AccountMainCard from "./AccountMainCard";
import AccountDetailsCard from "./AccountDetailsCard";
......@@ -16,6 +14,7 @@ import AccountRcDelegationsCard from "./AccountRcDelegationsCard";
import AccountBalanceCard from "./AccountBalanceCard";
import Explorer from "@/types/Explorer";
import AccountBalanceHistoryCard from "./AccountBalanceHistoryCard";
interface AccountDetailsSectionProps {
accountName: string;
liveDataEnabled: boolean;
......@@ -101,6 +100,13 @@ const AccountDetailsSection: React.FC<AccountDetailsSectionProps> = ({
proxy={accountDetails.proxy}
/>
<AccountVestingDelegationsCard
direction="outgoing"
delegatorAccount={accountName}
liveDataEnabled={liveDataEnabled}
dynamicGlobalData={dynamicGlobalData}
/>
<AccountVestingDelegationsCard
direction="incoming"
delegatorAccount={accountName}
liveDataEnabled={liveDataEnabled}
dynamicGlobalData={dynamicGlobalData}
......
......@@ -14,26 +14,40 @@ import {
import Explorer from "@/types/Explorer";
import useConvertedVestingShares from "@/hooks/common/useConvertedVestingShares";
import { buildTableHead, handleSortDelegations } from "@/utils/DelegationsSort";
import { capitalizeFirst } from "@/utils/StringUtils";
type AccountVestingDelegationsCardProps = {
direction: "incoming" | "outgoing";
delegatorAccount: string;
liveDataEnabled: boolean;
dynamicGlobalData?: Explorer.HeadBlockCardData;
};
const buildTableBody = (delegations: Explorer.VestingDelegation[]) => {
const buildTableBody = (
direction: "outgoing" | "incoming",
delegations: Explorer.VestingDelegation[]
) => {
return delegations.map((delegation, index: number) => {
return (
<Fragment key={index}>
<TableRow className={"border-b border-gray-700 hover:bg-inherit"}>
<TableCell>{index + 1}</TableCell>
<TableCell className="text-right">
<Link
className="text-blue-400"
href={`/@${delegation.delegatee}`}
>
{delegation.delegatee}
</Link>
{direction === "outgoing" ? (
<Link
className="text-link"
href={`/@${delegation.delegatee}`}
>
{delegation.delegatee}
</Link>
) : (
<Link
className="text-link"
href={`/@${delegation.delegator}`}
>
{delegation.delegator}
</Link>
)}
</TableCell>
<TableCell className="text-right">
{delegation.vesting_shares}
......@@ -45,10 +59,11 @@ const buildTableBody = (delegations: Explorer.VestingDelegation[]) => {
};
const AccountVestingDelegationsCard: React.FC<
AccountVestingDelegationsCardProps
> = ({ delegatorAccount, liveDataEnabled, dynamicGlobalData }) => {
> = ({ direction, delegatorAccount, liveDataEnabled, dynamicGlobalData }) => {
const [isPropertiesHidden, setIsPropertiesHidden] = useState(true);
const { hiveChain } = useHiveChainContext();
const delegations = useConvertedVestingShares(
direction,
delegatorAccount,
liveDataEnabled,
dynamicGlobalData
......@@ -57,7 +72,7 @@ const AccountVestingDelegationsCard: React.FC<
key: string;
isAscending: boolean;
}>({
key: "recipient",
key: direction === "outgoing" ? "recipient" : "delegator",
isAscending: true,
});
......@@ -65,7 +80,6 @@ const AccountVestingDelegationsCard: React.FC<
if (!hiveChain || !dynamicGlobalData || !delegations || !delegations.length)
return;
const handlePropertiesVisibility = () => {
setIsPropertiesHidden(!isPropertiesHidden);
};
......@@ -78,10 +92,14 @@ const AccountVestingDelegationsCard: React.FC<
delegations,
key,
isAscending,
recipient: "delegatee",
recipient: direction === "outgoing" ? "delegatee" : "delegator",
amount: "vesting_shares",
}) as Explorer.VestingDelegation[];
const headerText = `${capitalizeFirst(direction)} HP Delegations (${
delegations.length
})`;
return (
<Card
data-testid="vesting-delegations-dropdown"
......@@ -92,16 +110,18 @@ const AccountVestingDelegationsCard: React.FC<
onClick={handlePropertiesVisibility}
className="h-full flex justify-between align-center p-2 hover:bg-rowHover cursor-pointer px-4"
>
<div className="text-lg">HP Delegations ({delegations.length})</div>
<div className="text-lg">{headerText}</div>
{isPropertiesHidden ? <ArrowDown /> : <ArrowUp />}
</div>
</CardHeader>
<CardContent hidden={isPropertiesHidden}>
<Table>
<TableHeader>
<TableRow>{buildTableHead(sortBy, key, isAscending)}</TableRow>
<TableRow>
{buildTableHead(sortBy, key, isAscending, direction)}
</TableRow>
</TableHeader>
<TableBody>{buildTableBody(sortedDelegations)}</TableBody>
<TableBody>{buildTableBody(direction, sortedDelegations)}</TableBody>
</Table>
</CardContent>
</Card>
......
......@@ -13,23 +13,16 @@ const useVestingDelegations = (
data: vestingDelegationsData,
isLoading: isVestingDelegationsLoading,
isError: isVestingDelegationsError,
}: UseQueryResult<Hive.VestingDelegations[]> = useQuery({
}: UseQueryResult<Hive.TwoDirectionDelegations> = useQuery({
queryKey: ["vestingDelegations", delegatorAccount, liveDataEnabled],
queryFn: () => fetchingService.getVestingDelegations(delegatorAccount),
enabled: !!delegatorAccount,
select: (data) => {
const sortedData = data.sort(
(a: Hive.VestingDelegations, b: Hive.VestingDelegations) =>
a.delegatee.toLowerCase().localeCompare(b.delegatee.toLowerCase())
);
return sortedData;
},
refetchOnWindowFocus: false,
});
return {
vestingDelegationsData,
outgoingDelegations: vestingDelegationsData?.outgoing_delegations,
incomingDelegations: vestingDelegationsData?.incoming_delegations,
isVestingDelegationsLoading,
isVestingDelegationsError,
};
......
import { useHiveChainContext } from "@/contexts/HiveChainContext";
import useAccountDetails from "../api/accountPage/useAccountDetails";
import useDynamicGlobal from "../api/homePage/useDynamicGlobal";
import { formatAndDelocalizeTime } from "@/utils/TimeUtils";
import Explorer from "@/types/Explorer";
import {convertVestsToHP } from "@/utils/Calculations";
import { convertVestsToHP } from "@/utils/Calculations";
import { config } from "@/Config";
import useVestingDelegations from "../api/common/useVestingDelegations";
const useConvertedVestingShares = (accountName: string, liveDataEnabled: boolean, dynamicGlobalData?: Explorer.HeadBlockCardData) => {
const useConvertedVestingShares = (
direction: "outgoing" | "incoming",
accountName: string,
liveDataEnabled: boolean,
dynamicGlobalData?: Explorer.HeadBlockCardData
) => {
const { hiveChain } = useHiveChainContext();
const { vestingDelegationsData: delegations } = useVestingDelegations(
const { incomingDelegations, outgoingDelegations } = useVestingDelegations(
accountName,
null,
config.maxDelegatorsCount,
liveDataEnabled
);
if (!dynamicGlobalData || !hiveChain || !delegations) return [];
if (!dynamicGlobalData || !hiveChain) return [];
const {
headBlockDetails: { rawFeedPrice, rawQuote, rawTotalVestingFundHive, rawTotalVestingShares },
headBlockDetails: { rawTotalVestingFundHive, rawTotalVestingShares },
} = dynamicGlobalData;
const convertedDelgations = delegations?.map(
(delegation) => ({...delegation, vesting_shares: convertVestsToHP(hiveChain, delegation.vesting_shares, rawTotalVestingFundHive, rawTotalVestingShares)})
) as Explorer.VestingDelegation[];
return convertedDelgations;
}
export default useConvertedVestingShares;
\ No newline at end of file
if (direction === "outgoing") {
const convertedOutgoingDelegations = outgoingDelegations?.map(
(delegation) => ({
...delegation,
vesting_shares: convertVestsToHP(
hiveChain,
delegation.amount,
rawTotalVestingFundHive,
rawTotalVestingShares
),
})
) as Explorer.VestingDelegation[];
return convertedOutgoingDelegations;
}
if (direction === "incoming") {
const convertedIncomingDelegations = incomingDelegations?.map(
(delegation) => ({
...delegation,
vesting_shares: convertVestsToHP(
hiveChain,
delegation.amount,
rawTotalVestingFundHive,
rawTotalVestingShares
),
})
) as Explorer.VestingDelegation[];
return convertedIncomingDelegations;
}
};
export default useConvertedVestingShares;
......@@ -262,12 +262,10 @@ class FetchingService {
async getVestingDelegations(
delegatorAccount: string
): Promise<Hive.VestingDelegations[]> {
return await this.extendedHiveChain!.api.database_api.find_vesting_delegations(
{
account: delegatorAccount,
}
).then((response) => response.delegations);
): Promise<Hive.VestingDelegationsResponse> {
return await this.extendedHiveChain!.restApi["balance-api"].delegations({
accountName: delegatorAccount,
});
}
async getRcDelegations(
......
......@@ -653,8 +653,9 @@ namespace Hive {
export class VestingDelegations {
delegatee!: string;
delegator!: string;
id!: number;
min_delegation_time!: string;
amount!: string;
operation_id!: string;
block_num!: number;
vesting_shares!: Supply;
}
......@@ -664,24 +665,6 @@ namespace Hive {
to!: string;
}
export interface VestingDelegations {
delegatee: string;
delegator: string;
id: number;
min_delegation_time: string;
vesting_shares: {
amount: string;
precision: number;
nai: string;
};
}
export interface RCDelegations {
delegated_rc: number;
from: string;
to: string;
}
export interface BlockByOpResponse {
block_num: number;
op_type_id: number[];
......@@ -793,6 +776,26 @@ namespace Hive {
total_pages!: number;
operations_result!: AccountBalanceHistory[];
}
export class Delegation {
delegator!: string;
amount!: string;
operation_id!: string;
block_num!: number;
}
export class TwoDirectionDelegations {
outgoing_delegations!: Delegation[];
incoming_delegations!: Delegation[];
}
export class GetVestingDelegationsParams {
accountName!: string;
}
export class VestingDelegationsResponse {
total_operations!: number;
total_pages!: number;
operations_result!: TwoDirectionDelegations[];
}
}
export default Hive;
......@@ -140,12 +140,16 @@ export const extendedRest = {
urlPath: "block-number-by-date/{date}",
},
},
"balance-api" : {
balanceHistory: {
params: Hive.GetAccountBalanceHistoryParams,
result: Hive.AccountBalanceHistoryResponse,
urlPath: "accounts/{accountName}/balance-history",
},
"balance-api": {
balanceHistory: {
params: Hive.GetAccountBalanceHistoryParams,
result: Hive.AccountBalanceHistoryResponse,
urlPath: "accounts/{accountName}/balance-history",
},
delegations: {
params: Hive.GetVestingDelegationsParams,
result: Hive.VestingDelegationsResponse,
urlPath: "accounts/{accountName}/delegations",
},
},
};
......@@ -20,7 +20,8 @@ type SortedDelegations = {
amount: string | number;
};
export const TABLE_HEADER_CELLS = ["", "Recipient", "Amount"];
export const TABLE_HEADER_CELLS_OUTGOING = ["", "Recipient", "Amount"];
export const TABLE_HEADER_CELLS_INCOMING = ["", "Delegator", "Amount"];
export const handleSortDelegations = ({
delegations,
......@@ -30,7 +31,7 @@ export const handleSortDelegations = ({
amount,
}: SortedDelegations) => {
return [...delegations].sort((a: any, b: any) => {
if (key === "recipient") {
if (key === "recipient" || key === "delegator") {
const delegateeA = a[recipient].toLowerCase();
const delegateeB = b[recipient].toLowerCase();
return isAscending
......@@ -86,9 +87,15 @@ const renderChevron = (
export const buildTableHead = (
handleSort: (key: string) => void,
sortKey: string,
isOrderAscending: boolean
isOrderAscending: boolean,
direction?: "incoming" | "outgoing"
) => {
return TABLE_HEADER_CELLS.map((cellName: string) => {
const tableHeaderCells =
direction === "incoming"
? TABLE_HEADER_CELLS_INCOMING
: TABLE_HEADER_CELLS_OUTGOING;
return tableHeaderCells.map((cellName: string) => {
return (
<Fragment key={cellName}>
<TableHead
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment