Skip to content

Commit

Permalink
Merge pull request #1066 from oasisprotocol/mz/instanceTokenTransfer
Browse files Browse the repository at this point in the history
NFT instance token transfers tab
  • Loading branch information
buberdds authored Jan 24, 2024
2 parents dca2aa7 + 206e3d5 commit 7a6d25c
Show file tree
Hide file tree
Showing 8 changed files with 130 additions and 21 deletions.
1 change: 1 addition & 0 deletions .changelog/1066.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add NFT instance token transfers tab
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const AccountTokenTransfersCard: FC<AccountDetailsContext> = ({ scope, ad

const AccountTokenTransfers: FC<AccountDetailsContext> = ({ scope, address, account }) => {
const { t } = useTranslation()
const { isLoading, isFetched, results } = useTokenTransfers(scope, address)
const { isLoading, isFetched, results } = useTokenTransfers(scope, { address })

const transfers = results.data

Expand Down
52 changes: 52 additions & 0 deletions src/app/pages/NFTInstanceDashboardPage/NFTTokenTransfersCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { FC } from 'react'
import { useTranslation } from 'react-i18next'
import Card from '@mui/material/Card'
import CardHeader from '@mui/material/CardHeader'
import CardContent from '@mui/material/CardContent'
import { NUMBER_OF_ITEMS_ON_SEPARATE_PAGE } from '../../config'
import { ErrorBoundary } from '../../components/ErrorBoundary'
import { TokenTransfers } from '../../components/Tokens/TokenTransfers'
import { LinkableDiv } from '../../components/PageLayout/LinkableDiv'
import { NftDashboardContext } from './'
import { CardEmptyState } from '../AccountDetailsPage/CardEmptyState'
import { useNFTInstanceTransfers } from '../TokenDashboardPage/hook'

export const nftTokenTransfersContainerId = 'nftTokenTransfers'

export const NFTTokenTransfersCard: FC<NftDashboardContext> = props => {
const { t } = useTranslation()

return (
<Card>
<LinkableDiv id={nftTokenTransfersContainerId}>
<CardHeader disableTypography component="h3" title={t('tokens.transfers')} />
</LinkableDiv>
<CardContent>
<ErrorBoundary light={true}>
<NFTTokenTransfersView {...props} />
</ErrorBoundary>
</CardContent>
</Card>
)
}

const NFTTokenTransfersView: FC<NftDashboardContext> = ({ scope, address, instanceId }) => {
const { t } = useTranslation()
const { isLoading, isFetched, results } = useNFTInstanceTransfers(scope, {
contract_address: address,
nft_id: instanceId,
})
const transfers = results.data

return (
<>
{isFetched && !transfers?.length && <CardEmptyState label={t('account.emptyTokenTransferList')} />}
<TokenTransfers
transfers={transfers}
isLoading={isLoading}
limit={NUMBER_OF_ITEMS_ON_SEPARATE_PAGE}
pagination={results.tablePaginationProps}
/>
</>
)
}
12 changes: 10 additions & 2 deletions src/app/pages/NFTInstanceDashboardPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { AppErrors } from '../../../types/errors'
import { RouterTabs } from 'app/components/RouterTabs'
import { SearchScope } from '../../../types/searchScope'
import { useNFTInstance } from '../TokenDashboardPage/hook'
import { nftMetadataId } from './NFTMetadataCard'

export type NftDashboardContext = {
scope: SearchScope
Expand All @@ -28,7 +29,8 @@ export const NFTInstanceDashboardPage: FC = () => {
}
const { isFetched, isLoading, nft } = useNFTInstance(scope, address, instanceId)

const metadataLink = useHref('')
const tokenTransfersLink = useHref('')
const metadataLink = useHref(`metadata#${nftMetadataId}`)
const context: NftDashboardContext = {
scope,
address,
Expand All @@ -45,7 +47,13 @@ export const NFTInstanceDashboardPage: FC = () => {
scope={scope}
contractAddress={address!}
/>
<RouterTabs tabs={[{ label: t('nft.metadata'), to: metadataLink }]} context={context} />
<RouterTabs
tabs={[
{ label: t('tokens.transfers'), to: tokenTransfersLink },
{ label: t('nft.metadata'), to: metadataLink },
]}
context={context}
/>
</PageLayout>
)
}
2 changes: 1 addition & 1 deletion src/app/pages/TokenDashboardPage/TokenTransfersCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const TokenTransfersCard: FC<TokenDashboardContext> = ({ scope, address }
const TokenTransfersView: FC<TokenDashboardContext> = ({ scope, address }) => {
const { t } = useTranslation()

const { isLoading: areTransfersLoading, isFetched, results } = useTokenTransfers(scope, address)
const { isLoading: areTransfersLoading, isFetched, results } = useTokenTransfers(scope, { address })

const { isLoading: isTokenLoading } = useTokenInfo(scope, address)

Expand Down
32 changes: 26 additions & 6 deletions src/app/pages/TokenDashboardPage/hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {
useGetRuntimeEvmTokensAddressNfts,
useGetRuntimeAccountsAddressNfts,
useGetRuntimeEvmTokensAddressNftsId,
RuntimeEventType,
GetRuntimeEventsParams,
} from '../../../oasis-nexus/api'
import { AppErrors } from '../../../types/errors'
import { SearchScope } from '../../../types/searchScope'
Expand Down Expand Up @@ -35,7 +37,27 @@ export const useTokenInfo = (scope: SearchScope, address: string, enabled = true
}
}

export const useTokenTransfers = (scope: SearchScope, address: string) => {
export const useTokenTransfers = (scope: SearchScope, params: { address: string }) => {
const oasisAddress = useTransformToOasisAddress(params.address)
return _useTokenTransfers(scope, oasisAddress ? { rel: oasisAddress } : undefined)
}

export const useNFTInstanceTransfers = (
scope: SearchScope,
params: { nft_id: string; contract_address: string },
) => {
const oasisAddress = useTransformToOasisAddress(params.contract_address)
return _useTokenTransfers(
scope,
oasisAddress ? { nft_id: params.nft_id, contract_address: oasisAddress } : undefined,
)
}

export const _useTokenTransfers = (scope: SearchScope, params: undefined | GetRuntimeEventsParams) => {
if (params && Object.values(params).some(value => value === undefined || value === null)) {
throw new Error('Must set params=undefined while some values are unavailable')
}

const { network, layer } = scope
const pagination = useComprehensiveSearchParamsPagination<RuntimeEvent, RuntimeEventList>({
paramName: 'page',
Expand All @@ -46,21 +68,19 @@ export const useTokenTransfers = (scope: SearchScope, address: string) => {
// Loading transactions on the consensus layer is not supported yet.
// We should use useGetConsensusTransactions()
}

const oasisAddress = useTransformToOasisAddress(address)
const query = useGetRuntimeEvents(
network,
layer, // This is OK since consensus has been handled separately
{
...pagination.paramsForQuery,
rel: oasisAddress!,
type: 'evm.log',
type: RuntimeEventType.evmlog,
// The following is the hex-encoded signature for Transfer(address,address,uint256)
evm_log_signature: 'ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
...params,
},
{
query: {
enabled: !!oasisAddress,
enabled: !!params,
},
},
)
Expand Down
45 changes: 34 additions & 11 deletions src/oasis-nexus/generated/api.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { TokenHoldersCard } from './app/pages/TokenDashboardPage/TokenHoldersCar
import { TokenInventoryCard } from './app/pages/TokenDashboardPage/TokenInventoryCard'
import { NFTInstanceDashboardPage, useNftDetailsProps } from './app/pages/NFTInstanceDashboardPage'
import { NFTMetadataCard } from './app/pages/NFTInstanceDashboardPage/NFTMetadataCard'
import { NFTTokenTransfersCard } from './app/pages/NFTInstanceDashboardPage/NFTTokenTransfersCard'
import { ConsensusDashboardPage } from 'app/pages/ConsensusDashboardPage'
import { Layer } from './oasis-nexus/api'
import { SearchScope } from './types/searchScope'
Expand Down Expand Up @@ -158,6 +159,10 @@ export const routes: RouteObject[] = [
children: [
{
path: '',
Component: () => <NFTTokenTransfersCard {...useNftDetailsProps()} />,
},
{
path: 'metadata',
Component: () => <NFTMetadataCard {...useNftDetailsProps()} />,
},
],
Expand Down

0 comments on commit 7a6d25c

Please sign in to comment.