{withName && accountName}
diff --git a/src/components/topMenu/TopMeny.module.sass b/src/components/topMenu/TopMeny.module.sass
index abb84561..8ff378a3 100644
--- a/src/components/topMenu/TopMeny.module.sass
+++ b/src/components/topMenu/TopMeny.module.sass
@@ -6,7 +6,7 @@
border-style: solid
border-width: 0 1px 1px 1px
position: fixed !important
- z-index: 1
+ z-index: 11
max-height: 100%
overflow-y: auto
overflow-x: hidden
diff --git a/src/components/txHistory/CustomDataList.tsx b/src/components/txHistory/CustomDataList.tsx
new file mode 100644
index 00000000..0539bdaa
--- /dev/null
+++ b/src/components/txHistory/CustomDataList.tsx
@@ -0,0 +1,56 @@
+import React from 'react'
+import NoData from 'src/components/utils/EmptyList'
+import { DataListProps } from '../list'
+import { groupBy } from 'lodash'
+import { Transaction } from './types'
+import styles from './Index.module.sass'
+import utc from 'dayjs/plugin/utc'
+import dayjs from 'dayjs'
+
+dayjs.extend(utc)
+
+function CustomDataList (props: DataListProps
) {
+ const {
+ dataSource,
+ renderItem,
+ getKey,
+ noDataDesc = null,
+ noDataExt,
+ customNoData,
+ } = props
+
+ const total = dataSource.length
+
+ const hasData = total > 0
+
+ const groupedData = groupBy(dataSource, (x) =>
+ dayjs(x.timestamp).format('MMMM D, YYYY')
+ )
+
+ if (!hasData) {
+ return (
+ <>
+ {customNoData || {noDataExt}}
+ >
+ )
+ }
+
+ return (
+
+ {Object.entries(groupedData).map(([ date, item ], i) => {
+ return (
+
+
{date}
+
+ {item.map((x, i) => (
+
{renderItem(x, i, item.length)}
+ ))}
+
+
+ )
+ })}
+
+ )
+}
+
+export default CustomDataList
diff --git a/src/components/txHistory/Index.module.sass b/src/components/txHistory/Index.module.sass
new file mode 100644
index 00000000..d85a2340
--- /dev/null
+++ b/src/components/txHistory/Index.module.sass
@@ -0,0 +1,117 @@
+@import 'src/styles/subsocial-vars.scss'
+
+.HistoryBlock
+ background-color: #fff
+ // padding: $space_normal
+ box-shadow: $shadow
+ border-radius: $border_radius_normal
+ margin-bottom: 0.1rem
+
+ display: flex
+ flex-direction: column
+ gap: $space_tiny
+
+.TransactionsList
+ padding: 0 $space_normal $space_normal $space_normal
+
+.MenuItemAll
+ height: 24px
+ width: 24px
+ align-items: center
+ justify-content: center
+ background: #F0F0F0
+ border-radius: 50%
+
+.AllEventsIcon
+ svg
+ margin-top: 1px
+ margin-left: 2px
+
+.IconBox
+ svg
+ height: 25px
+ width: 24px
+
+.AllEvents
+ &:global(.ant-menu-item-selected)
+ svg
+ path
+ stroke: $color_primary !important
+
+ li
+ &:hover
+ path
+ stroke: $color_primary !important
+
+.TxHistoryActionBlock
+ position: sticky
+ z-index: 9
+ top: 64px
+ background-color: #fff
+ border-radius: inherit
+ border-bottom-left-radius: 0
+ border-bottom-right-radius: 0
+ padding: $space_normal
+
+.TxHistoryButtons
+ display: flex
+ align-items: center
+ justify-content: space-between
+ gap: $space_normal
+
+.CommonActionButtonsParts
+ display: flex
+ align-items: center
+ gap: $space_tiny
+
+.TransactionByDateContainer
+ display: flex
+ flex-direction: column
+ gap: $space_tiny
+
+.LabelWithCount
+ display: flex
+ align-items: center
+ gap: $space_mini
+
+.DownloadButton
+ border-radius: 18px
+
+ &:hover
+ path[stroke]
+ stroke: $color_primary
+
+ &:focus
+ path[stroke]
+ stroke: $color_primary
+
+.LeftPart,
+.RightPart
+ @extend .CommonActionButtonsParts
+
+.Date
+ font-size: $font_medium
+ font-weight: 600
+
+.InfiniteListLoading
+ height: 300px !important
+
+.GroupedData
+ display: flex
+ flex-direction: column
+ gap: $space_big
+
+@media ( max-width: $max_mobile_width )
+ .TransactionsList
+ \:global .infinite-scroll-component
+ margin-top: 1rem
+
+ .HistoryBlock
+ gap: 0
+
+ .TxHistoryActionBlock
+ border-bottom: 1px solid #F0F0F0
+
+ .TransactionByDateContainer
+ gap: 0
+
diff --git a/src/components/txHistory/filter/ListFilter.tsx b/src/components/txHistory/filter/ListFilter.tsx
new file mode 100644
index 00000000..20d8cdcd
--- /dev/null
+++ b/src/components/txHistory/filter/ListFilter.tsx
@@ -0,0 +1,66 @@
+import SelectbleDropdown, {
+ DropdownActionKind,
+} from '@/components/utils/Dropdowns/SelectableDropdown'
+import { MenuItem } from '@/components/utils/Dropdowns/types'
+import styles from '../Index.module.sass'
+import { LabelWithIcon } from '@/components/table/balancesTable/utils'
+import { useState } from 'react'
+import { useResponsiveSize } from '@/components/responsive'
+
+type ListFilterProps = {
+ menus: MenuItem[]
+ filters: string[]
+ setFilters: (filter: string[]) => void
+ label: string
+ labelImage: React.ReactNode
+ scrollPosition?: number
+}
+
+const ListFilter = ({ filters, setFilters, menus, label, labelImage, scrollPosition }: ListFilterProps) => {
+ const [ visible, setVisible ] = useState(false)
+ const { isMobile } = useResponsiveSize()
+
+ const onChange = (values: string[], kind: DropdownActionKind) => {
+ const newValue = values.find((x) => !filters.includes(x))
+
+ const isAll = newValue === 'all'
+
+ if (kind === 'select' && values.includes('all') && !isAll) {
+ setFilters(values.filter((x) => x !== 'all'))
+ } else if (kind === 'select' && isAll) {
+ setFilters([ 'all' ])
+ setVisible(false)
+ } else if (kind === 'deselect' && values.length < 1) {
+ setFilters([ 'all' ])
+ } else {
+ setFilters(values)
+ }
+
+
+ window.scrollTo(0, isMobile ? scrollPosition || 0 : 0)
+ }
+
+ return (
+ <>
+
+
+ {!filters.includes('all') ? `(${filters.length})` : ''}
+
+ }
+ />
+ >
+ )
+}
+
+export default ListFilter
diff --git a/src/components/txHistory/filter/filterItems.tsx b/src/components/txHistory/filter/filterItems.tsx
new file mode 100644
index 00000000..99c4a8c5
--- /dev/null
+++ b/src/components/txHistory/filter/filterItems.tsx
@@ -0,0 +1,115 @@
+import { PiShareNetworkLight } from 'react-icons/pi'
+import { LabelWithIcon } from '../../table/balancesTable/utils'
+import { getIconUrl } from '../../utils'
+import styles from '../Index.module.sass'
+import EventsIcon from '@/assets/icons/events.svg'
+import clsx from 'clsx'
+import SentIcon from '@/assets/icons/sent-big.svg'
+import ReceivedIcon from '@/assets/icons/received-big.svg'
+
+export const networksVariantsWithIconOpt = [
+ {
+ label: (
+
}
+ />
+ ),
+ key: 'all',
+ },
+ {
+ label: (
+
+ ),
+ key: 'polkadot',
+ },
+ {
+ label: (
+
+ ),
+ key: 'kusama',
+ },
+ {
+ label: (
+
+ ),
+ key: 'astar',
+ },
+ {
+ label: (
+
+ ),
+ key: 'moonbeam',
+ },
+ {
+ label: (
+
+ ),
+ key: 'moonriver',
+ },
+ {
+ label: (
+
+ ),
+ key: 'subsocial',
+ },
+]
+
+export const eventsVariantsOpt = [
+ {
+ label: (
+
}
+ />
+ ),
+ key: 'all',
+ className: styles.AllEvents,
+ },
+ {
+ label: (
+
}
+ />
+ ),
+ key: 'transfer_from',
+ },
+ {
+ label: (
+
}
+ />
+ ),
+ key: 'transfer_to',
+ },
+]
\ No newline at end of file
diff --git a/src/components/txHistory/index.tsx b/src/components/txHistory/index.tsx
new file mode 100644
index 00000000..530927fd
--- /dev/null
+++ b/src/components/txHistory/index.tsx
@@ -0,0 +1,230 @@
+import { DataListProps, InfiniteListByData } from '../list'
+import styles from './Index.module.sass'
+import { getTxHistory } from '@/api/txHistory'
+import { TransferRow } from './transactions/Transfer'
+import { Transaction } from './types'
+import CustomDataList from './CustomDataList'
+import { useCallback, useEffect, useRef, useState } from 'react'
+import useGetInitialTxHistoryData from './useGetTxHistory'
+import { Button, Tooltip } from 'antd'
+import { SubDate, isEmptyArray } from '@subsocial/utils'
+import { LoadingOutlined, ReloadOutlined } from '@ant-design/icons'
+import { MutedDiv } from '../utils/MutedText'
+import { useResponsiveSize } from '../responsive'
+import ListFilter from './filter/ListFilter'
+import EventsIcon from '@/assets/icons/events.svg'
+import {
+ eventsVariantsOpt,
+ // networksVariantsWithIconOpt,
+} from './filter/filterItems'
+// import { PiShareNetworkLight } from 'react-icons/pi'
+import { toGenericAccountId } from '../../rtk/app/util'
+import { useFetchIdentities } from '@/rtk/features/identities/identitiesHooks'
+
+const itemsByTxKind: Record
= {
+ TRANSFER_FROM: TransferRow,
+ TRANSFER_TO: TransferRow,
+}
+
+type LoadMoreProps = {
+ address: string
+ page: number
+ size: number
+ networks: string[]
+ events: string[]
+}
+
+const loadMore = async ({
+ address,
+ page,
+ size,
+ networks,
+ events,
+}: LoadMoreProps) => {
+ const offset = (page - 1) * size
+
+ const history = await getTxHistory({
+ address,
+ pageSize: size,
+ offset,
+ networks,
+ events,
+ })
+
+ return history
+}
+
+type TxHistoryLayoutProps = {
+ addresses: string[]
+}
+
+const supportedNetowrks = [ 'subsocial' ]
+
+const TxHistoryLayout = ({ addresses }: TxHistoryLayoutProps) => {
+ // const [ networks, setNetworks ] = useState([ 'all' ])
+ const [ events, setEvents ] = useState([ 'all' ])
+ const address = addresses[0]
+ const [ refresh, setRefresh ] = useState(false)
+ const { isMobile } = useResponsiveSize()
+ const historySection = useRef(null)
+
+ const { initialData, lastUpdateDate } = useGetInitialTxHistoryData({
+ address,
+ refresh,
+ setRefresh,
+ })
+
+ const renderItem = (item: Transaction, i: number, dataLength?: number) => {
+ const { txKind } = item
+
+ const Component = itemsByTxKind[txKind]
+
+ return (
+
+ )
+ }
+
+ const dataLoading = isEmptyArray(initialData.txs) && !initialData.actualData
+
+ const List = useCallback(() => {
+ return (
+
+
+ loadMore({
+ address,
+ page,
+ size,
+ networks: supportedNetowrks.filter((x) => x !== 'all'),
+ events: events.filter((x) => x !== 'all'),
+ })
+ }
+ dataLoading={dataLoading}
+ dataLoadingClassName={styles.InfiniteListLoading}
+ noDataDesc='No transactions yet'
+ dataSource={
+ supportedNetowrks.includes('all') && events.includes('all')
+ ? initialData.txs
+ : undefined
+ }
+ getKey={(data) => data.id}
+ renderItem={renderItem}
+ >
+ {(dataListProps) => {
+ return
+ }}
+
+
+ )
+ }, [
+ dataLoading,
+ address,
+ JSON.stringify(initialData.txs),
+ supportedNetowrks.join(','),
+ events.join(','),
+ ])
+
+ return (
+
+
+
+
+ {/* }
+ /> */}
+ }
+ scrollPosition={(historySection.current as any)?.offsetTop - 180}
+ />
+
+
+ {!isMobile && (
+
+ )}
+
+
+
+ {isMobile && (
+
+ Last update:
+
+
+ )}
+
+
+
+
+ )
+}
+
+type TransactionsDataListProps = {
+ dataListProps: DataListProps
+}
+
+const TransactionsDataList = ({ dataListProps }: TransactionsDataListProps) => {
+ const addresses = dataListProps.dataSource.map((x) =>
+ toGenericAccountId(x.senderOrTargetPublicKey)
+ )
+
+ useFetchIdentities(addresses)
+
+ return
+}
+
+type LastUpdateProps = {
+ lastUpdateDate?: Date
+ refresh: boolean
+}
+
+const LastUpdate = ({ lastUpdateDate, refresh }: LastUpdateProps) => {
+ const [ lastUpdate, setLastUpdate ] = useState(null)
+
+ useEffect(() => {
+ if (!lastUpdateDate) return
+
+ const intervalId = setInterval(() => {
+ setLastUpdate(SubDate.formatDate(lastUpdateDate.getTime()))
+ }, 1000)
+
+ return () => {
+ clearInterval(intervalId)
+ }
+ }, [ lastUpdateDate?.getTime() ])
+
+ return (
+
+
+
+ {refresh || !lastUpdateDate ? 'updating...' : lastUpdate}
+
+
+
+ )
+}
+
+export default TxHistoryLayout
diff --git a/src/components/txHistory/transactions/MobileTransferModal.tsx b/src/components/txHistory/transactions/MobileTransferModal.tsx
new file mode 100644
index 00000000..673edc1f
--- /dev/null
+++ b/src/components/txHistory/transactions/MobileTransferModal.tsx
@@ -0,0 +1,158 @@
+import FloatingModal from '@/components/utils/FloatingModal'
+import styles from './Transactions.module.sass'
+import dayjs from 'dayjs'
+import { Button } from 'antd'
+import { RiArrowRightUpLine } from 'react-icons/ri'
+import { useCurrentAccount } from '@/components/providers/MyExtensionAccountsContext'
+import { AccountPreview, AvatarOrSkeleton } from '@/components/table/utils'
+import { CopyAddress } from '../../homePage/address-views/utils/index'
+import { toShortAddress } from '../../utils/index'
+import Link from 'next/link'
+import clsx from 'clsx'
+
+type TransferInfo = {
+ icon: string
+ address: string
+ balance: React.ReactNode
+ totalBalance: React.ReactNode
+ txKind: string
+ timestamp: string
+ extrinsicHash: string
+ networkName: string
+ subscanUrl: string
+}
+
+type MobileTransferModalProps = {
+ open: boolean
+ closeModal: () => void
+ transferInfo: TransferInfo
+}
+
+const MobileTransferModal = ({
+ open,
+ closeModal,
+ transferInfo,
+}: MobileTransferModalProps) => {
+ const {
+ icon,
+ address: senderOrTarget,
+ balance,
+ totalBalance,
+ txKind,
+ timestamp,
+ extrinsicHash,
+ networkName,
+ subscanUrl,
+ } = transferInfo
+
+ const currentAddresses = useCurrentAccount()
+
+ const currentAddress = currentAddresses?.[0]
+
+ const date = dayjs(timestamp).format('MMM DD, YYYY [at] HH:mm:ss ')
+
+ const isRecieved = txKind === 'TRANSFER_TO'
+
+ const sender = isRecieved ? senderOrTarget : currentAddress
+ const recipient = isRecieved ? currentAddress : senderOrTarget
+
+ return (
+
+
+
+
+
+ {isRecieved ? '+' : '-'}
+ {balance}
+
+
{totalBalance}
+
+
+
+
+
Network
+
+
+ {networkName}
+
+
+
+
+
+ Transaction ID
+
+
+ {toShortAddress(extrinsicHash, 8)}
+
+
+
+
{date}
+
+
+
+
+
+ )
+}
+
+export default MobileTransferModal
diff --git a/src/components/txHistory/transactions/Transactions.module.sass b/src/components/txHistory/transactions/Transactions.module.sass
new file mode 100644
index 00000000..585d6d1b
--- /dev/null
+++ b/src/components/txHistory/transactions/Transactions.module.sass
@@ -0,0 +1,126 @@
+@import 'src/styles/subsocial-vars.scss'
+
+.TransferRow
+ display: grid
+ grid-template-columns: 1fr 1fr 1fr
+ align-items: center
+ gap: $space_normal
+
+ min-height: 62px
+
+.Tokens
+ font-size: $font_normal
+ font-weight: 600
+
+.Dollars
+ font-size: $font_small
+
+.FirstCol
+ width: 250px
+
+.TransferTitle
+ display: flex
+ align-items: center
+ gap: $space_mini
+
+.RecievedTokens
+ color: #16A34A
+
+.TransactionDivider
+ display: flex
+ justify-content: flex-end
+
+ \:global .ant-divider
+ margin: 0
+ margin-top: $space_mini
+ max-width: 94.5%
+ min-width: auto
+ border-top-color: #f0f0f0
+
+.TransactionIcon
+ position: absolute
+ bottom: -1px
+ right: -2px
+
+.ModalContent
+ display: flex
+ flex-direction: column
+ gap: $space_normal
+
+ justify-content: space-between
+ height: 100%
+
+.TxContent
+ display: flex
+ flex-direction: column
+ gap: $space_normal
+
+ margin-top: $space_normal
+
+.SenderBlock
+ display: flex
+ flex-direction: column
+ align-items: center
+ gap: $space_normal
+
+ background: #F8FAFC
+ border-radius: 10px
+ padding: $space_normal
+
+ div
+ width: 100%
+ display: flex
+ justify-content: space-between
+
+.GrayLabel
+ color: #888
+
+.TextBlock
+ width: 100%
+ display: flex
+ justify-content: space-between
+ gap: $space_mini
+
+ background: #F8FAFC
+ border-radius: 10px
+ padding: $space_normal
+
+.Tokens-Send
+ color: #000
+ font-size: $font_big
+ line-height: 25.144px
+ font-weight: 600
+
+.Tokens-Recieved
+ color: #16A34A
+ font-size: $font_big
+ line-height: 25.144px
+ font-weight: 600
+
+.BalanceInDollar
+ font-size: $font_normal
+ line-height: 25.144px
+
+ span
+ color: #64748B
+
+.Date
+ color: #64748B
+ line-height: 25.144px
+ margin-top: $space_tiny
+
+.EllipsisPreview
+ max-width: 168px
+ display: block
+ white-space: nowrap
+ overflow: hidden
+ text-overflow: ellipsis
+
+ font-weight: 600
+
+@media ( max-width: $max_mobile_width )
+ .TransferRow
+ display: flex
+ align-items: center
+ justify-content: space-between
+ gap: $space_mini
diff --git a/src/components/txHistory/transactions/Transfer.tsx b/src/components/txHistory/transactions/Transfer.tsx
new file mode 100644
index 00000000..95a7e263
--- /dev/null
+++ b/src/components/txHistory/transactions/Transfer.tsx
@@ -0,0 +1,315 @@
+import styles from './Transactions.module.sass'
+import {
+ Address,
+ AccountPreview,
+ AvatarOrSkeleton,
+ getPrice,
+} from '../../table/utils'
+import { MutedDiv } from '../../utils/MutedText'
+import { HiOutlineExternalLink } from 'react-icons/hi'
+import clsx from 'clsx'
+import { Transaction } from '../types'
+import { toGenericAccountId } from '@/rtk/app/util'
+import { usePrices } from '@/rtk/features/prices/pricesHooks'
+import { useGetChainDataByNetwork } from '@/components/utils/useGetDecimalsAndSymbolByNetwork'
+import { FormatBalance } from '@/components/common/balances'
+import { convertToBalanceWithDecimal } from '@subsocial/utils'
+import { BalanceView } from '../../homePage/address-views/utils/index'
+import { ExternalLink } from '../../identity/utils'
+import dayjs from 'dayjs'
+import utc from 'dayjs/plugin/utc'
+import BN from 'bignumber.js'
+import { useResponsiveSize } from '@/components/responsive'
+import useGetProfileName from '@/hooks/useGetProfileName'
+import { AvatarSize } from 'antd/lib/avatar/SizeContext'
+import SentIcon from '@/assets/icons/sent.svg'
+import RecievedIcon from '@/assets/icons/received.svg'
+import { Divider } from 'antd'
+import Link from 'next/link'
+import { useState } from 'react'
+import MobileTransferModal from './MobileTransferModal'
+
+dayjs.extend(utc)
+
+const subscanLinksByNetwork: Record = {
+ polkadot: 'https://polkadot.subscan.io/extrinsic/',
+ kusama: 'https://kusama.subscan.io/extrinsic/',
+ astar: 'https://astar.subscan.io/extrinsic/',
+ moonbeam: 'https://moonbeam.subscan.io/extrinsic/',
+ moonriver: 'https://moonriver.subscan.io/extrinsic/',
+ subsocial: 'https://calamar.app/search?network=subsocial&query=',
+}
+
+type TransferRowProps = {
+ item: Transaction
+ isLastElement?: boolean
+}
+
+export const TransferRow = ({ item, isLastElement }: TransferRowProps) => {
+ const { isMobile } = useResponsiveSize()
+ const prices = usePrices()
+ const {
+ txKind,
+ amount,
+ senderOrTargetPublicKey,
+ blockchainTag,
+ transaction,
+ } = item
+
+ const { decimal, tokenSymbol, icon, name } = useGetChainDataByNetwork(
+ blockchainTag.toLowerCase()
+ )
+
+ const address = toGenericAccountId(senderOrTargetPublicKey)
+
+ const balanceWithDecimals = convertToBalanceWithDecimal(amount, decimal)
+
+ const price = getPrice(prices, 'symbol', tokenSymbol)
+
+ const totalBalanceBN = balanceWithDecimals.multipliedBy(price || '0')
+
+ const totalBalance = (
+
+ )
+
+ const extrinsicHash = transaction.transferNative.extrinsicHash
+
+ const subscanUrl = `${
+ subscanLinksByNetwork[blockchainTag.toLowerCase()]
+ }${extrinsicHash}`
+
+ const amountBN = new BN(amount)
+
+ const balance = amountBN.isZero() ? (
+ '0'
+ ) : (
+
+ )
+
+ const props = {
+ icon: icon,
+ subscanUrl: subscanUrl,
+ timestamp: item.timestamp,
+ address: address,
+ balance: balance,
+ totalBalance: totalBalance,
+ txKind: txKind,
+ extrinsicHash,
+ networkName: name,
+ }
+
+ return (
+
+ {isMobile ? (
+
+ ) : (
+
+ )}
+ {!isLastElement && !isMobile && (
+
+ )}
+
+ )
+}
+
+type DesktopTransferRowProps = {
+ icon: string
+ subscanUrl: string
+ timestamp: string
+ address: string
+ balance: React.ReactNode
+ totalBalance: React.ReactNode
+ txKind: string
+ extrinsicHash: string
+ networkName: string
+}
+
+const DesktopTransfer = ({
+ icon,
+ timestamp,
+ address,
+ balance,
+ subscanUrl,
+ totalBalance,
+ txKind,
+}: DesktopTransferRowProps) => {
+ const name = useGetProfileName(address)
+
+ const titleByKind = txKind === 'TRANSFER_TO' ? 'Received' : 'Sent'
+ const time = dayjs(timestamp).format('HH:mm')
+
+ const title = (
+
+ {titleByKind} •{' '}
+
+ Transfer
+
+ }
+ />
+
+ )
+
+ return (
+
+
+
+
{txKind === 'TRANSFER_TO' ? 'From' : 'To'}
+
+
+
+
+
+
+ )
+}
+
+const MobileTransfer = ({
+ icon,
+ address,
+ balance,
+ totalBalance,
+ txKind,
+ timestamp,
+ extrinsicHash,
+ networkName,
+ subscanUrl,
+}: DesktopTransferRowProps) => {
+ const [ open, setOpen ] = useState(false)
+ const titleByKind = txKind === 'TRANSFER_TO' ? 'Received from' : 'Sent to'
+
+ console.log(extrinsicHash)
+ return (
+ <>
+
+ setOpen(false)}
+ transferInfo={{
+ icon,
+ address,
+ balance,
+ totalBalance,
+ txKind,
+ timestamp,
+ extrinsicHash,
+ networkName,
+ subscanUrl,
+ }}
+ />
+ >
+ )
+}
+
+type BalancePartProps = {
+ txKind: string
+ balance: React.ReactNode
+ totalBalance: React.ReactNode
+}
+
+const BalancePart = ({ txKind, balance, totalBalance }: BalancePartProps) => (
+
+
+ {txKind === 'TRANSFER_TO' ? '+' : '-'}
+ {balance}
+
+
{totalBalance}
+
+)
+
+type TxHistoryImageProps = {
+ icon: string
+ size: AvatarSize
+ txKind: string
+}
+
+const TxHistoryImage = ({ icon, size, txKind }: TxHistoryImageProps) => {
+ const TxIconByTxKind = txKind === 'TRANSFER_TO' ? RecievedIcon : SentIcon
+
+ return (
+
+ )
+}
diff --git a/src/components/txHistory/types.ts b/src/components/txHistory/types.ts
new file mode 100644
index 00000000..1276ed47
--- /dev/null
+++ b/src/components/txHistory/types.ts
@@ -0,0 +1,14 @@
+export type Transaction = {
+ id: string
+ txKind: string
+ blockchainTag: string
+ amount: string
+ senderOrTargetPublicKey: string
+ timestamp: string
+ success: string
+ transaction: {
+ transferNative: {
+ extrinsicHash: string
+ }
+ }
+}
diff --git a/src/components/txHistory/useGetTxHistory.tsx b/src/components/txHistory/useGetTxHistory.tsx
new file mode 100644
index 00000000..a20c1512
--- /dev/null
+++ b/src/components/txHistory/useGetTxHistory.tsx
@@ -0,0 +1,63 @@
+import { useEffect, useState } from 'react'
+import { getTxHistoryQueue } from '../../api/txHistory'
+import { Transaction } from './types'
+
+type InitialData = {
+ txs: Transaction[]
+ actualData: boolean
+}
+
+type GetIniTitalTxHistoryDataProps = {
+ address?: string
+ refresh: boolean
+ setRefresh: (refresh: boolean) => void
+}
+
+const defaultInitialData = { txs: [], actualData: false }
+
+const useGetInitialTxHistoryData = ({
+ address,
+ refresh,
+ setRefresh,
+}: GetIniTitalTxHistoryDataProps) => {
+ const [ initialData, setInitialData ] =
+ useState(defaultInitialData)
+ const [ lastUpdateDate, setLastUpdateDate ] = useState(
+ undefined
+ )
+
+ useEffect(() => {
+ setInitialData(defaultInitialData)
+ setRefresh(true)
+ }, [ address ])
+
+ useEffect(() => {
+ if (!address || !refresh) return
+
+ const interval = setInterval(async () => {
+ const history: InitialData = await getTxHistoryQueue({
+ address,
+ offset: 0,
+ pageSize: 30,
+ })
+
+ setInitialData(history)
+
+ if (history?.actualData) {
+ clearInterval(interval)
+ setRefresh(false)
+ setLastUpdateDate(new Date())
+
+ return
+ }
+ }, 2000)
+
+ return () => {
+ clearInterval(interval)
+ }
+ }, [ address, refresh ])
+
+ return { initialData: initialData || {}, lastUpdateDate }
+}
+
+export default useGetInitialTxHistoryData
diff --git a/src/components/utils/DfAvatar.tsx b/src/components/utils/DfAvatar.tsx
index 35a812b7..3c7e69a6 100644
--- a/src/components/utils/DfAvatar.tsx
+++ b/src/components/utils/DfAvatar.tsx
@@ -18,7 +18,7 @@ export const BaseAvatar = (props: BaseAvatarProps) => {
const { size = DEFAULT_AVATAR_SIZE, avatar, style, address } = props
if (!avatar || isEmptyStr(avatar)) {
- return
+ return
}
return
diff --git a/src/components/table/balancesTable/utils/TableDropdownButton.tsx b/src/components/utils/Dropdowns/Dropdown.tsx
similarity index 84%
rename from src/components/table/balancesTable/utils/TableDropdownButton.tsx
rename to src/components/utils/Dropdowns/Dropdown.tsx
index 544ca8bc..fcfdb27b 100644
--- a/src/components/table/balancesTable/utils/TableDropdownButton.tsx
+++ b/src/components/utils/Dropdowns/Dropdown.tsx
@@ -1,5 +1,7 @@
import { Button, Dropdown, Menu } from 'antd'
-import { MenuItem } from '../types'
+import styles from './Index.module.sass'
+import clsx from 'clsx'
+import { MenuItem } from './types'
type MenuItemsProps = {
items: MenuItem[]
@@ -15,7 +17,7 @@ const MenuItems = ({
defaultValue,
}: MenuItemsProps) => (