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

[CFE-381]: Feature - bonded changes transaction #831

Merged
merged 25 commits into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
cb930e3
refactor(types): update zod validation schema to apply with new api spec
Poafs1 Mar 18, 2024
bbd8b7a
feat: update changelog
Poafs1 Mar 18, 2024
ca5bc6c
feat(components): add bonded token changes delegation related transac…
Poafs1 Mar 19, 2024
0a0ae17
feat: update changelog
Poafs1 Mar 19, 2024
3d0fc9b
feat(components): delegation related transactions mobile card view
Poafs1 Mar 19, 2024
3fe2429
feat(components): update related transactions table fraction
Poafs1 Mar 19, 2024
11e764d
Merge pull request #832 from alleslabs/feature/cfe-52-bonded-transact…
evilpeach Mar 19, 2024
e29fde0
refactor(components): bonded token change add link to transactions tab
Poafs1 Mar 19, 2024
468a047
feat: update changelog
Poafs1 Mar 19, 2024
3b02540
feat(components): fix pr comments
Poafs1 Mar 20, 2024
40bb9c4
feat(components): fix acceptance test ui
Poafs1 Mar 20, 2024
c8c2ada
feat(components): change button to ghost variant
Poafs1 Mar 20, 2024
184e8f0
feat(components): use button size md instead of sm
Poafs1 Mar 20, 2024
f401814
Merge branch 'feature/cfe-35-voting-power-overview' into feature/cfe-…
Poafs1 Mar 20, 2024
24945a2
feat(components): fix pr comments
Poafs1 Mar 20, 2024
bcc03e7
feat(components): fix pr comments
Poafs1 Mar 21, 2024
cc23206
Merge branch 'feature/cfe-35-voting-power-overview' into feature/cfe-…
Poafs1 Mar 21, 2024
492ee23
feat(components): fix pr comments
Poafs1 Mar 21, 2024
32231dc
feat(components): fix pr comments
Poafs1 Mar 21, 2024
715999c
feat(components): fix pr comments
Poafs1 Mar 21, 2024
4a680e3
refactor(utils): totoken function test case
Poafs1 Mar 21, 2024
b1b2da4
feat(components): fix coin icon layout
Poafs1 Mar 21, 2024
ae64d18
Merge branch 'feature/cfe-35-voting-power-overview' into feature/cfe-…
Poafs1 Mar 21, 2024
10947c7
Merge pull request #833 from alleslabs/feature/cfe-37-current-bonded-…
evilpeach Mar 21, 2024
baa08bc
feat(components): fix related transaction table props
Poafs1 Mar 21, 2024
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Features

- [#833](https://github.com/alleslabs/celatone-frontend/pull/833) Add link to transactions page to current bonded token component
- [#832](https://github.com/alleslabs/celatone-frontend/pull/832) Add bonded token changes delegation related transactions
- [#831](https://github.com/alleslabs/celatone-frontend/pull/831) Update zod schema to apply with new validator delegation related txs api spec
- [#828](https://github.com/alleslabs/celatone-frontend/pull/828) Add validator detail voting power overview section with data from APIs
- [#835](https://github.com/alleslabs/celatone-frontend/pull/835) Add amp view in json - block and proposal details
- [#823](https://github.com/alleslabs/celatone-frontend/pull/823) Add validator uptime and penalty events
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { Box, Flex, Heading, Text } from "@chakra-ui/react";
import { Box, Button, Flex, Heading, Text } from "@chakra-ui/react";
import type { BigSource } from "big.js";
import type { ScriptableContext, TooltipModel } from "chart.js";

import { TabIndex } from "../../types";
import { useInternalNavigate } from "lib/app-provider";
import { LineChart } from "lib/components/chart/LineChart";
import { CustomIcon } from "lib/components/icon";
import { Loading } from "lib/components/Loading";
import { ErrorFetching } from "lib/components/state";
import { useValidatorHistoricalPowers } from "lib/services/validatorService";
Expand All @@ -17,13 +20,17 @@ interface VotingPowerChartProps {
validatorAddress: ValidatorAddr;
singleStakingDenom: Option<string>;
assetInfos: Option<AssetInfos>;
isOverview?: boolean;
}

export const VotingPowerChart = ({
validatorAddress,
singleStakingDenom,
assetInfos,
isOverview,
}: VotingPowerChartProps) => {
const navigate = useInternalNavigate();

const { data: historicalPowers, isLoading } =
useValidatorHistoricalPowers(validatorAddress);

Expand Down Expand Up @@ -115,27 +122,50 @@ export const VotingPowerChart = ({
rounded={8}
w="100%"
>
<Flex gap={2} direction="column" w={250} minW={250}>
<Heading variant="h6">
{singleStakingDenom
? "Current Bonded Token"
: "Current Voting Powers"}
</Heading>
<Heading variant="h5" fontWeight={600}>
{currentPrice} {currency}
</Heading>
<Text variant="body1">
<Text
as="span"
fontWeight={700}
color={diffInLast24Hr >= 0 ? "success.main" : "error.main"}
<Flex gap={6} direction="column" w={250} minW={250}>
<Flex gap={2} direction="column">
<Heading variant="h6">
{singleStakingDenom
? "Current Bonded Token"
: "Current Voting Powers"}
</Heading>
<Heading variant="h5" fontWeight={600}>
{currentPrice} {currency}
</Heading>
<Text variant="body1">
<Text
as="span"
fontWeight={700}
color={diffInLast24Hr >= 0 ? "success.main" : "error.main"}
>
{diffInLast24Hr >= 0
? `+${handleFormatValue(diffInLast24Hr)}`
: `-${handleFormatValue(-diffInLast24Hr)}`}
</Text>{" "}
{currency} in last 24 hr
</Text>
</Flex>
{isOverview && (
<Button
variant="ghost-secondary"
p="unset"
size="md"
pl={2}
onClick={() =>
navigate({
pathname: "/validators/[validatorAddress]/[tab]",
query: {
validatorAddress,
tab: TabIndex.BondedTokenChanges,
},
options: { shallow: true },
})
}
>
{diffInLast24Hr >= 0
? `+${handleFormatValue(diffInLast24Hr)}`
: `-${handleFormatValue(-diffInLast24Hr)}`}
</Text>{" "}
{currency} in last 24 hr
</Text>
See all related transactions
<CustomIcon name="chevron-right" boxSize={3} />
</Button>
)}
</Flex>
<Box w="100%" h="272px" id="voting-power-chart-container">
<LineChart
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { Flex } from "@chakra-ui/react";
import { Box, Flex } from "@chakra-ui/react";

import { RelatedTransactionTable } from "../tables/RelatedTransactionsTable";
import { RelatedTransactionTable } from "../tables";
import { useMobile } from "lib/app-provider";
import { Pagination } from "lib/components/pagination";
import { usePaginator } from "lib/components/pagination/usePaginator";
import { TableTitle } from "lib/components/table";
import { useValidatorDelegationRelatedTxs } from "lib/services/validatorService";
import type { AssetInfos, Option, ValidatorAddr } from "lib/types";

import { VotingPowerChart } from "./VotingPowerChart";
Expand All @@ -15,13 +20,74 @@ export const BondedTokenChanges = ({
validatorAddress,
singleStakingDenom,
assetInfos,
}: BondedTokenChangesProps) => (
<Flex direction="column" gap={{ base: 4, md: 8 }} pt={6}>
<VotingPowerChart
validatorAddress={validatorAddress}
singleStakingDenom={singleStakingDenom}
assetInfos={assetInfos}
/>
<RelatedTransactionTable />
</Flex>
);
}: BondedTokenChangesProps) => {
const isMobile = useMobile();

const {
pagesQuantity,
setTotalData,
currentPage,
setCurrentPage,
pageSize,
setPageSize,
offset,
} = usePaginator({
initialState: {
pageSize: 10,
currentPage: 1,
isDisabled: false,
},
});

const { data, isLoading } = useValidatorDelegationRelatedTxs(
validatorAddress,
pageSize,
offset,
{
onSuccess: ({ total }) => setTotalData(total),
}
);

const tableHeaderId = "relatedTransactionTableHeader";

return (
<Flex direction="column" gap={{ base: 4, md: 8 }} pt={6}>
<VotingPowerChart
validatorAddress={validatorAddress}
singleStakingDenom={singleStakingDenom}
assetInfos={assetInfos}
/>
<Box>
{!isMobile && (
<TableTitle
title="Delegation-Related Transactions"
count={data?.total ?? 0}
id={tableHeaderId}
helperText="Shows transactions relevant to changes in delegated tokens, excluding any token reduction due to slashing."
/>
)}
<RelatedTransactionTable
delegationRelatedTxs={data?.items}
isLoading={isLoading}
assetInfos={assetInfos}
/>
{!!data?.total && data.total > 10 && (
<Pagination
currentPage={currentPage}
pagesQuantity={pagesQuantity}
offset={offset}
totalData={data.total}
scrollComponentId={tableHeaderId}
pageSize={pageSize}
onPageChange={setCurrentPage}
onPageSizeChange={(e) => {
const size = Number(e.target.value);
setPageSize(size);
setCurrentPage(1);
}}
/>
)}
</Box>
</Flex>
);
};

This file was deleted.

2 changes: 1 addition & 1 deletion src/lib/pages/validator-details/components/tables/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * from "./ProposedBlocksTable";
export * from "./RelatedTransactionsTable";
export * from "./VotedProposalsTable";
export * from "./related-transactions";
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { Box, Flex, Text } from "@chakra-ui/react";
import type { BigSource } from "big.js";
import type Big from "big.js";

import { TokenImageRender } from "lib/components/token";
import { getUndefinedTokenIcon } from "lib/pages/pools/utils";
import type { AssetInfos, Coin, Option, Token, U, USD } from "lib/types";
import {
coinToTokenWithValue,
formatPrice,
formatUTokenWithPrecision,
getTokenLabel,
} from "lib/utils";

interface RelatedTransactionsBondedTokenChangesProps {
txHash: string;
coin: Coin;
assetInfos: Option<AssetInfos>;
}

export const RelatedTransactionsBondedTokenChanges = ({
txHash,
coin,
assetInfos,
}: RelatedTransactionsBondedTokenChangesProps) => {
const token = coinToTokenWithValue(coin.denom, coin.amount, assetInfos);
const isPositiveAmount = token.amount.gte(0);
const formattedAmount = `${isPositiveAmount ? "+" : "-"}${formatUTokenWithPrecision(token.amount.abs() as U<Token<Big>>, token.precision ?? 0, false, 2)}`;

return (
<Flex
gap={2}
key={`${txHash}-${coin.denom}`}
w="100%"
justifyContent={{ base: "start", md: "end" }}
alignItems="center"
>
<Box textAlign={{ base: "left", md: "right" }}>
<Flex alignItems="center" gap={1}>
<Text
fontWeight={700}
color={isPositiveAmount ? "success.main" : "error.main"}
>
{formattedAmount}
</Text>
<Text>{getTokenLabel(token.denom, token.symbol)}</Text>
<TokenImageRender
display={{ base: "block", md: "none" }}
boxSize={4}
logo={token.logo ?? getUndefinedTokenIcon(token.denom)}
/>
</Flex>
<Text variant="body3" color="text.dark">
{token.value
? `(${formatPrice(token.value.abs() as USD<BigSource>)})`
: "-"}
</Text>
</Box>
<TokenImageRender
display={{ base: "none", md: "block" }}
boxSize={6}
logo={token.logo ?? getUndefinedTokenIcon(token.denom)}
/>
</Flex>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { Badge, Box, Flex, Grid, GridItem, Text } from "@chakra-ui/react";

import { ExplorerLink } from "lib/components/ExplorerLink";
import { MobileCardTemplate } from "lib/components/table";
import type { ValidatorDelegationRelatedTxsResponseItem } from "lib/services/validator";
import type { AssetInfos, Option } from "lib/types";
import { dateFromNow, extractMsgType, formatUTC } from "lib/utils";

import { RelatedTransactionsBondedTokenChanges } from "./RelatedTransactionsBondedTokenChanges";

interface RelatedTransactionsMobileCardProps {
delegationRelatedTx: ValidatorDelegationRelatedTxsResponseItem;
assetInfos: Option<AssetInfos>;
onRowSelect: (txHash: string) => void;
}

export const RelatedTransactionsMobileCard = ({
delegationRelatedTx,
assetInfos,
onRowSelect,
}: RelatedTransactionsMobileCardProps) => (
<MobileCardTemplate
topContent={
<Flex w="100%" flexDirection="column" gap={2}>
<Grid templateColumns="1fr 1fr" gap={2}>
<GridItem>
<Text variant="body3" color="text.dark" fontWeight={600}>
Transaction Hash
</Text>
<ExplorerLink
value={delegationRelatedTx.txHash.toLocaleUpperCase()}
type="tx_hash"
showCopyOnHover
/>
{delegationRelatedTx.messages.length > 1 && (
<Badge variant="secondary" ml={2}>
{delegationRelatedTx.messages.length}
</Badge>
)}
</GridItem>
<GridItem>
<Text variant="body3" color="text.dark" fontWeight={600}>
Sender
</Text>
<ExplorerLink
value={delegationRelatedTx.sender}
type="user_address"
showCopyOnHover
/>
</GridItem>
</Grid>
<Box>
<Text variant="body3" color="text.dark" fontWeight={600}>
Action
</Text>
<Text variant="body2" color="white">
{delegationRelatedTx.messages.length > 1
? `${delegationRelatedTx.messages.length} Messages`
: extractMsgType(delegationRelatedTx.messages[0].type)}
</Text>
</Box>
<Box>
<Text variant="body3" color="text.dark" fontWeight={600}>
Bonded Token Changes
</Text>
{delegationRelatedTx.tokens.map((token) => (
<RelatedTransactionsBondedTokenChanges
txHash={delegationRelatedTx.txHash}
coin={token}
assetInfos={assetInfos}
key={delegationRelatedTx.txHash + token.amount + token.denom}
/>
))}
</Box>
</Flex>
}
bottomContent={
<Box>
<Text variant="body2" color="text.dark">
{formatUTC(delegationRelatedTx.timestamp)}
</Text>
<Text variant="body3" color="text.disabled">
{`(${dateFromNow(delegationRelatedTx.timestamp)})`}
</Text>
</Box>
}
onClick={() => onRowSelect(delegationRelatedTx.txHash)}
/>
);
Loading
Loading