Commit fcde6016 authored by tom's avatar tom

noves assets flow tab

parent ffc87f4d
......@@ -15,7 +15,7 @@ export type TransactionRevertReason = {
raw: string;
} | DecodedInput;
type WrappedTransactionFields = 'decoded_input' | 'fee' | 'gas_limit' | 'gas_price' | 'hash' | 'max_fee_per_gas' |
export type WrappedTransactionFields = 'decoded_input' | 'fee' | 'gas_limit' | 'gas_price' | 'hash' | 'max_fee_per_gas' |
'max_priority_fee_per_gas' | 'method' | 'nonce' | 'raw_input' | 'to' | 'type' | 'value';
export interface OpWithdrawal {
......
......@@ -52,12 +52,12 @@ const TransactionPageContent = () => {
title: config.features.suave.isEnabled && data?.wrapped ? 'Confidential compute tx details' : 'Details',
component: detailsComponent,
},
// txInterpretation.isEnabled && txInterpretation.provider === 'noves' ?
// { id: 'asset_flows', title: 'Asset Flows', component: <TxAssetFlows hash={ hash }/> } :
// undefined,
// config.features.suave.isEnabled && data?.wrapped ?
// { id: 'wrapped', title: 'Regular tx details', component: <TxDetailsWrapped data={ data.wrapped }/> } :
// undefined,
txInterpretation.isEnabled && txInterpretation.provider === 'noves' ?
{ id: 'asset_flows', title: 'Asset Flows', component: <TxAssetFlows hash={ hash }/> } :
undefined,
config.features.suave.isEnabled && data?.wrapped ?
{ id: 'wrapped', title: 'Regular tx details', component: <TxDetailsWrapped data={ data.wrapped }/> } :
undefined,
{ id: 'token_transfers', title: 'Token transfers', component: <TxTokenTransfer txQuery={ txQuery }/> },
config.features.userOps.isEnabled ?
{ id: 'user_ops', title: 'User operations', component: <TxUserOps txQuery={ txQuery }/> } :
......
......@@ -4,10 +4,10 @@ import React from 'react';
import type { NovesResponseData } from 'types/api/noves';
import Skeleton from 'ui/shared/chakra/Skeleton';
import { Badge } from 'toolkit/chakra/badge';
import { Skeleton } from 'toolkit/chakra/skeleton';
import type { NovesFlowViewItem } from 'ui/tx/assetFlows/utils/generateFlowViewData';
import Tag from '../chakra/Tag';
import AddressEntity from '../entities/address/AddressEntity';
import { getActionFromTo, getFromTo } from './utils';
......@@ -35,16 +35,17 @@ const NovesFromTo: FC<Props> = ({ isLoaded, txData, currentAddress = '', item })
const address = { hash: data.address || '', name: data.name || '' };
return (
<Skeleton borderRadius="sm" isLoaded={ isLoaded }>
<Skeleton borderRadius="sm" loading={ !isLoaded }>
<Box display="flex">
<Tag
colorScheme={ isSent ? 'yellow' : 'green' }
<Badge
colorPalette={ isSent ? 'yellow' : 'green' }
px={ 0 }
w="113px"
textAlign="center"
flexShrink={ 0 }
justifyContent="center"
>
{ data.text }
</Tag>
</Badge>
<AddressEntity
address={ address }
......
......@@ -144,13 +144,12 @@ export interface EntityProps extends EntityBase.EntityBaseProps {
const TokenEntity = (props: EntityProps) => {
const partsProps = distributeEntityProps(props);
const content = <Content { ...partsProps.content }/>;
return (
<Container w="100%" { ...partsProps.container }>
<Icon { ...partsProps.icon }/>
<Link { ...partsProps.link }>
<Content { ...partsProps.content }/>
</Link>
{ props.noLink ? content : <Link { ...partsProps.link }>{ content }</Link> }
<Symbol { ...partsProps.symbol }/>
<Copy { ...partsProps.copy }/>
</Container>
......
import { chakra } from '@chakra-ui/react';
import React from 'react';
import type { Transaction } from 'types/api/transaction';
import type { Transaction, WrappedTransactionFields } from 'types/api/transaction';
import config from 'configs/app';
import getCurrencyValue from 'lib/getCurrencyValue';
......@@ -13,7 +13,7 @@ import TokenEntity from 'ui/shared/entities/token/TokenEntity';
interface Props {
className?: string;
isLoading?: boolean;
tx: Transaction;
tx: Transaction | Pick<Transaction, WrappedTransactionFields>;
withCurrency?: boolean;
withUsd?: boolean;
accuracy?: number;
......@@ -22,7 +22,7 @@ interface Props {
const TxFee = ({ className, tx, accuracy, accuracyUsd, isLoading, withCurrency = true, withUsd }: Props) => {
if (tx.celo?.gas_token) {
if ('celo' in tx && tx.celo?.gas_token) {
const token = tx.celo.gas_token;
const { valueStr, usd } = getCurrencyValue({
value: tx.fee.value || '0',
......@@ -40,7 +40,7 @@ const TxFee = ({ className, tx, accuracy, accuracyUsd, isLoading, withCurrency =
);
}
if (tx.stability_fee) {
if ('stability_fee' in tx && tx.stability_fee) {
const token = tx.stability_fee.token;
const { valueStr, usd } = getCurrencyValue({
value: tx.stability_fee.total_fee,
......@@ -65,7 +65,7 @@ const TxFee = ({ className, tx, accuracy, accuracyUsd, isLoading, withCurrency =
<CurrencyValue
value={ tx.fee.value }
currency={ showCurrency ? currencyUnits.ether : '' }
exchangeRate={ withUsd ? tx.exchange_rate : null }
exchangeRate={ withUsd && 'exchange_rate' in tx ? tx.exchange_rate : null }
accuracy={ accuracy }
accuracyUsd={ accuracyUsd }
flexWrap="wrap"
......
import { Table, Tbody, Tr, Th, Box, Text, Show, Hide } from '@chakra-ui/react';
import { Box, Text } from '@chakra-ui/react';
import { chunk } from 'es-toolkit';
import React, { useMemo, useState } from 'react';
......@@ -6,12 +6,12 @@ import type { PaginationParams } from 'ui/shared/pagination/types';
import useApiQuery from 'lib/api/useApiQuery';
import { NOVES_TRANSLATE } from 'stubs/noves/NovesTranslate';
import { Skeleton } from 'toolkit/chakra/skeleton';
import { TableBody, TableColumnHeader, TableHeaderSticky, TableRoot, TableRow } from 'toolkit/chakra/table';
import ActionBar from 'ui/shared/ActionBar';
import Skeleton from 'ui/shared/chakra/Skeleton';
import DataListDisplay from 'ui/shared/DataListDisplay';
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import Pagination from 'ui/shared/pagination/Pagination';
import TheadSticky from 'ui/shared/TheadSticky';
import TxAssetFlowsListItem from './assetFlows/TxAssetFlowsListItem';
import TxAssetFlowsTableItem from './assetFlows/TxAssetFlowsTableItem';
......@@ -53,7 +53,7 @@ export default function TxAssetFlows(props: FlowViewProps) {
const actionBar = (
<ActionBar mt={ -6 } pb={{ base: 6, md: 5 }} flexDir={{ base: 'column', md: 'initial' }} gap={{ base: '2', md: 'initial' }} >
<Box display="flex" alignItems="center" gap={ 1 }>
<Skeleton borderRadius="sm" isLoaded={ !isPlaceholderData } >
<Skeleton borderRadius="sm" loading={ isPlaceholderData } >
<Text fontWeight="400" mr={ 1 }>
Wallet
</Text>
......@@ -72,7 +72,7 @@ export default function TxAssetFlows(props: FlowViewProps) {
const content = (
<>
<Hide above="lg" >
<Box hideFrom="lg">
{ data?.map((item, i) => (
<TxAssetFlowsListItem
key={ `${ i }-${ item.accountAddress }` }
......@@ -80,21 +80,21 @@ export default function TxAssetFlows(props: FlowViewProps) {
isPlaceholderData={ isPlaceholderData }
/>
)) }
</Hide>
</Box>
<Show above="lg">
<Table>
<TheadSticky top={ 75 }>
<Tr>
<Th>
<Box hideBelow="lg">
<TableRoot>
<TableHeaderSticky top={ 75 }>
<TableRow>
<TableColumnHeader>
Actions
</Th>
<Th width="450px">
</TableColumnHeader>
<TableColumnHeader width="450px">
From/To
</Th>
</Tr>
</TheadSticky>
<Tbody>
</TableColumnHeader>
</TableRow>
</TableHeaderSticky>
<TableBody>
{ data?.map((item, i) => (
<TxAssetFlowsTableItem
key={ `${ i }-${ item.accountAddress }` }
......@@ -102,19 +102,20 @@ export default function TxAssetFlows(props: FlowViewProps) {
isPlaceholderData={ isPlaceholderData }
/>
)) }
</Tbody>
</Table>
</Show>
</TableBody>
</TableRoot>
</Box>
</>
);
return (
<DataListDisplay
isError={ isError }
items={ data }
itemsNum={ data?.length }
emptyText="There are no transfers."
content={ content }
actionBar={ actionBar }
/>
>
{ content }
</DataListDisplay>
);
}
......@@ -6,7 +6,7 @@ import type { Transaction } from 'types/api/transaction';
import type { ExcludeUndefined } from 'types/utils';
import { currencyUnits } from 'lib/units';
import Tag from 'ui/shared/chakra/Tag';
import { Badge } from 'toolkit/chakra/badge';
import CurrencyValue from 'ui/shared/CurrencyValue';
import * as DetailsInfoItem from 'ui/shared/DetailsInfoItem';
import DetailsInfoItemDivider from 'ui/shared/DetailsInfoItemDivider';
......@@ -40,9 +40,9 @@ const TxDetailsWrapped = ({ data }: Props) => {
Method
</DetailsInfoItem.Label>
<DetailsInfoItem.Value>
<Tag colorScheme="gray">
<Badge colorPalette="gray">
{ data.method }
</Tag>
</Badge>
</DetailsInfoItem.Value>
<DetailsInfoItemDivider/>
......
import { Box, Text } from '@chakra-ui/react';
import React from 'react';
import Skeleton from 'ui/shared/chakra/Skeleton';
import { Skeleton } from 'toolkit/chakra/skeleton';
import IconSvg from 'ui/shared/IconSvg';
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
import NovesFromTo from 'ui/shared/Noves/NovesFromTo';
......@@ -18,7 +18,7 @@ const TxAssetFlowsListItem = (props: Props) => {
return (
<ListItemMobile rowGap={ 4 } w="full" >
<Skeleton borderRadius="sm" isLoaded={ !props.isPlaceholderData } w="full">
<Skeleton borderRadius="sm" loading={ props.isPlaceholderData } w="full">
<Box display="flex" >
<IconSvg
......@@ -28,7 +28,7 @@ const TxAssetFlowsListItem = (props: Props) => {
color="text_secondary"
/>
<Text fontSize="sm" fontWeight={ 500 }>
<Text textStyle="sm" fontWeight="medium">
Action
</Text>
</Box>
......
import { Td, Tr } from '@chakra-ui/react';
import React from 'react';
import { TableRow, TableCell } from 'toolkit/chakra/table';
import NovesFromTo from 'ui/shared/Noves/NovesFromTo';
import NovesActionSnippet from './components/NovesActionSnippet';
......@@ -14,14 +14,14 @@ type Props = {
const TxAssetFlowsTableItem = (props: Props) => {
return (
<Tr >
<Td px={ 3 } py={ 5 } fontSize="sm" borderColor="gray.200" _dark={{ borderColor: 'whiteAlpha.200' }}>
<TableRow>
<TableCell px={ 3 } py={ 5 } textStyle="sm" borderColor={{ _light: 'gray.200', _dark: 'whiteAlpha.200' }}>
<NovesActionSnippet item={ props.item } isLoaded={ !props.isPlaceholderData }/>
</Td>
<Td px={ 3 } py="18px" fontSize="sm" borderColor="gray.200" _dark={{ borderColor: 'whiteAlpha.200' }}>
</TableCell>
<TableCell px={ 3 } py="18px" textStyle="sm" borderColor={{ _light: 'gray.200', _dark: 'whiteAlpha.200' }}>
<NovesFromTo item={ props.item } isLoaded={ !props.isPlaceholderData }/>
</Td>
</Tr>
</TableCell>
</TableRow>
);
};
......
import { Box, Hide, PopoverArrow, PopoverContent, PopoverTrigger, Show, Text, useColorModeValue } from '@chakra-ui/react';
import { Box, Text } from '@chakra-ui/react';
import type { FC } from 'react';
import React from 'react';
import { HEX_REGEXP } from 'lib/regexp';
import Popover from 'ui/shared/chakra/Popover';
import Skeleton from 'ui/shared/chakra/Skeleton';
import { Skeleton } from 'toolkit/chakra/skeleton';
import { Tooltip } from 'toolkit/chakra/tooltip';
import TokenEntity from 'ui/shared/entities/token/TokenEntity';
import IconSvg from 'ui/shared/IconSvg';
......@@ -17,8 +17,6 @@ interface Props {
}
const NovesActionSnippet: FC<Props> = ({ item, isLoaded }) => {
const popoverBg = useColorModeValue('gray.700', 'gray.300');
const token = React.useMemo(() => {
const action = item.action;
......@@ -38,10 +36,16 @@ const NovesActionSnippet: FC<Props> = ({ item, isLoaded }) => {
const validTokenAddress = token.address ? HEX_REGEXP.test(token.address) : false;
const tooltipContent = (
<NovesTokenTooltipContent
token={ item.action.token || item.action.nft }
amount={ item.action.amount }
/>
);
return (
<Skeleton borderRadius="sm" isLoaded={ isLoaded }>
<Hide above="lg">
<Box display="flex" gap={ 2 } cursor="pointer" flexWrap="wrap">
<Skeleton borderRadius="sm" loading={ !isLoaded }>
<Box hideFrom="lg" display="flex" gap={ 2 } cursor="pointer" flexWrap="wrap">
<Text fontWeight="700" >
{ item.action.label }
</Text>
......@@ -58,26 +62,20 @@ const NovesActionSnippet: FC<Props> = ({ item, isLoaded }) => {
w="fit-content"
/>
</Box>
</Hide>
<Show above="lg">
<Popover
trigger="hover"
<Tooltip
content={ tooltipContent }
openDelay={ 50 }
closeDelay={ 50 }
arrowSize={ 15 }
arrowShadowColor="transparent"
placement="bottom"
flip={ false }
positioning={{ placement: 'bottom' }}
interactive
>
<PopoverTrigger>
<Box display="flex" gap={ 2 } cursor="pointer" w="fit-content" maxW="100%" alignItems="center">
<Box hideBelow="lg" display="flex" gap={ 2 } cursor="pointer" w="fit-content" maxW="100%" alignItems="center">
<IconSvg
name="lightning"
height="5"
width="5"
color="gray.500"
_dark={{ color: 'gray.400' }}
color={{ _light: 'gray.500', _dark: 'gray.400' }}
/>
<Text fontWeight="700" >
{ item.action.label }
......@@ -95,24 +93,7 @@ const NovesActionSnippet: FC<Props> = ({ item, isLoaded }) => {
w="fit-content"
/>
</Box>
</PopoverTrigger>
<PopoverContent
bg={ popoverBg }
shadow="lg"
width="fit-content"
zIndex="modal"
padding={ 2 }
>
<PopoverArrow bg={ popoverBg }/>
<NovesTokenTooltipContent
token={ item.action.token || item.action.nft }
amount={ item.action.amount }
/>
</PopoverContent>
</Popover>
</Show>
</Tooltip>
</Skeleton>
);
};
......
import { Box, Text, useColorModeValue } from '@chakra-ui/react';
import { Box, Text } from '@chakra-ui/react';
import type { FC } from 'react';
import React from 'react';
......@@ -13,8 +13,6 @@ interface Props {
}
const NovesTokenTooltipContent: FC<Props> = ({ token, amount }) => {
const textColor = useColorModeValue('white', 'blackAlpha.900');
if (!token) {
return null;
}
......@@ -23,8 +21,8 @@ const NovesTokenTooltipContent: FC<Props> = ({ token, amount }) => {
const showTokenAddress = HEX_REGEXP.test(token.address);
return (
<Box color={ textColor } display="flex" flexDir="column" alignItems="center" gap={ 1 }>
<Text as="p" color="inherit" fontWeight="600">
<Box color={{ _light: 'white', _dark: 'blackAlpha.900' }} display="flex" flexDir="column" alignItems="center" gap={ 1 }>
<Text as="p" color="inherit" fontWeight="semibold">
<Text color="inherit" as="span">
{ amount }
</Text>
......@@ -34,14 +32,14 @@ const NovesTokenTooltipContent: FC<Props> = ({ token, amount }) => {
</Text>
{ showTokenName && (
<Text as="p" color="inherit" fontWeight="600" mt="6px">
<Text as="p" color="inherit" fontWeight="semibold" mt="6px">
{ token.name }
</Text>
) }
{ showTokenAddress && (
<Box display="flex" alignItems="center">
<Text color="inherit" fontWeight="400">
<Text color="inherit" fontWeight="normal">
{ token.address }
</Text>
<CopyToClipboard text={ token.address }/>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment