Skip to content

Commit

Permalink
feat(firehose): initial work for firehose
Browse files Browse the repository at this point in the history
  • Loading branch information
plondon committed Apr 28, 2022
1 parent 859f74e commit 5761fe2
Show file tree
Hide file tree
Showing 17 changed files with 2,920 additions and 34 deletions.
2,639 changes: 2,639 additions & 0 deletions packages/blockchain-wallet-v4-frontend/src/generated/graphql.ts

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
fragment AssetItemResultFragment on Asset {
name
token_id
contract {
address
}
image_url
permalink
owners {
address
}
listings {
payment_token_symbol
starting_price
}
collection {
name
image_url
}
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,5 @@
query Assets($filter: [AssetFilter], $traitFilter: [TraitFilter], $sort: AssetSort, $forSale: Boolean, $limit: Int, $offset: Int) {
assets(filter: $filter, traitFilter: $traitFilter, sort: $sort, forSale: $forSale, limit: $limit, offset: $offset) {
name
token_id
contract {
address
}
image_url
permalink
owners {
address
}
listings {
payment_token_symbol
starting_price
}
collection {
name
image_url
}
...AssetItemResultFragment
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
query Firehose($filter: [EventFilter], $sort: EventSort, $limit:Int, $offset: Int) {
events(filter: $filter, sort: $sort, limit: $limit, offset: $offset) {
event_type
asset {
...AssetItemResultFragment
}
total_price
bid_amount
from {
address
}
to {
address
}
winner {
address
}
seller {
address
}
created_date
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { IconUser, IconWallet } from '@blockchain-com/icons'
import { reduxForm } from 'redux-form'
import styled from 'styled-components'

import { Button, Image, Text } from 'blockchain-info-components'
import { Button, Image, Link, Text } from 'blockchain-info-components'
import { Flex } from 'components/Flex'
import AppSwitcher from 'components/NavbarV2/AppSwitcher'
import { Logo, NavContainer, NavLeft, NavRight } from 'components/NavbarV2/Navbar'
Expand All @@ -33,17 +33,14 @@ const NavCenter = styled.div`
align-items: center;
width: 50%;
`
const NavLinkButton = styled(NavLink)`
const NavLinkButton = styled(Link)`
padding: 8px 10px;
border-radius: 8px;
text-decoration: none;
margin-right: 12px;
background-color: transparent;
&.active {
background-color: ${(props) => props.theme.blue000};
* {
color: ${(props) => props.theme.blue600};
}
background-color: ${(props) => props.theme.blue000};
* {
color: ${(props) => props.theme.blue600};
}
`

Expand All @@ -66,11 +63,16 @@ const ExploreHeader: React.FC<Props> = ({
<AppSwitcher />
</NavLeft>
<NavCenter>
<NavLinkButton to='/nfts' activeClassName='active'>
<Text size='14px' weight={600}>
<FormattedMessage id='copy.explore' defaultMessage='Explore' />
</Text>
</NavLinkButton>
<LinkContainer to='/nfts/explore'>
<NavLinkButton>
<Flex alignItems='center' gap={4}>
<Text size='14px' weight={600}>
<FormattedMessage id='copy.explore' defaultMessage='Explore' />
</Text>
🚀
</Flex>
</NavLinkButton>
</LinkContainer>
<NftSearch />
</NavCenter>
<NavRight>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import React, { useEffect } from 'react'
import { FormattedMessage } from 'react-intl'
import { LinkContainer } from 'react-router-bootstrap'
import { CombinedError } from 'urql'

import { NFT_ORDER_PAGE_LIMIT } from '@core/network/api/nfts'
import { Button, Text, TooltipHost, TooltipIcon } from 'blockchain-info-components'
import CoinDisplay from 'components/Display/CoinDisplay'
import FiatDisplay from 'components/Display/FiatDisplay'
import { EventSortFields, useFirehoseQuery } from 'generated/graphql'
import { EventFilterFields, SortDirection } from 'generated/graphql.types'

import { Asset, AssetCollection, AssetDetails, AssetImageContainer, PriceCTA } from '../components'
import { NftFilterFormValuesType } from '../NftFilter'

const NftFirehoseResults: React.FC<Props> = ({
page,
setIsFetchingNextPage,
setMaxItemsFetched,
setNextPageFetchError
}) => {
const [result] = useFirehoseQuery({
variables: {
limit: NFT_ORDER_PAGE_LIMIT,
offset: page * NFT_ORDER_PAGE_LIMIT,
sort: { by: EventSortFields.CreatedDate, direction: SortDirection.Desc }
}
})

useEffect(() => {
setNextPageFetchError(result.error)
}, [result.error])

useEffect(() => {
setIsFetchingNextPage(result.fetching)
}, [result.fetching])

useEffect(() => {
if (result.data?.events.length !== undefined) {
setMaxItemsFetched(result.data.events.length < NFT_ORDER_PAGE_LIMIT)
}
}, [result.data?.events?.length, setMaxItemsFetched])

return (
<>
{result?.data?.events?.map((event) => {
const lowestListing = event.asset?.listings
? event.asset?.listings.sort(
(a, b) => Number(a?.starting_price) - Number(b?.starting_price)
)[0]
: null

return event.asset ? (
<Asset key={event.asset.token_id}>
<LinkContainer
to={`/nfts/asset/${event.asset.contract?.address}/${event.asset.token_id}`}
>
<AssetImageContainer
background={`url(${event.asset.image_url?.replace(/=s\d*/, '')})`}
/>
</LinkContainer>
<AssetDetails>
<div>
<AssetCollection>
<Text style={{ whiteSpace: 'nowrap' }} size='14px' color='grey800' weight={600}>
{event.asset.collection?.name}
</Text>
</AssetCollection>
<Text style={{ marginTop: '4px' }} size='16px' color='black' weight={600}>
{event.asset.name}
</Text>
</div>

<PriceCTA>
<div>
<Text size='12px' color='black' weight={600}>
<FormattedMessage id='copy.price' defaultMessage='Price' />
</Text>
{lowestListing && lowestListing.starting_price ? (
<Text color='black' style={{ marginTop: '4px', textAlign: 'left' }}>
<CoinDisplay
size='14px'
color='black'
weight={600}
coin={lowestListing.payment_token_symbol || 'ETH'}
>
{lowestListing.starting_price}
</CoinDisplay>
<FiatDisplay
size='12px'
color='grey600'
weight={600}
currency='USD'
coin={lowestListing.payment_token_symbol || 'ETH'}
>
{lowestListing.starting_price}
</FiatDisplay>
</Text>
) : (
<Text
size='12px'
color='grey600'
weight={600}
style={{ display: 'flex', marginBottom: '4px', marginTop: '6px' }}
>
<FormattedMessage id='copy.not_for_sale' defaultMessage='Not for sale' />
<TooltipHost id='tooltip.nft_asset_not_for_sale'>
<TooltipIcon name='question-in-circle-filled' />
</TooltipHost>
</Text>
)}
</div>
<LinkContainer
to={`/nfts/asset/${event.asset.contract?.address}/${event.asset.token_id}`}
>
<Button data-e2e='nftAssetPage' nature='primary' small>
<FormattedMessage id='copy.view_details' defaultMessage='View Details' />
</Button>
</LinkContainer>
</PriceCTA>
</AssetDetails>
</Asset>
) : null
})}
</>
)
}

type Props = {
formValues: NftFilterFormValuesType
page: number
setIsFetchingNextPage: (isFetching: boolean) => void
setMaxItemsFetched: (maxItemsFetched: boolean) => void
setNextPageFetchError: (error: CombinedError | undefined) => void
slug: string
}

export default NftFirehoseResults
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import React, { useEffect, useState } from 'react'
import { CombinedError } from 'urql'

import LazyLoadContainer from 'components/LazyLoadContainer'

import { Grid } from '../components'
import NftError from '../components/NftError'
import NftGridLoading from '../components/NftGridLoading'
import NftPageLazyLoadWrapper from '../components/NftPageLazyLoadWrapper'
import { NftFilterFormValuesType } from '../NftFilter'
import NftFirehoseResults from './Firehose.results'

const NftFirehose: React.FC<Props> = ({ formValues, slug }) => {
const [pageVariables, setPageVariables] = useState([{ page: 0 }])
const [maxItemsFetched, setMaxItemsFetched] = useState(false)
const [isFetchingNextPage, setIsFetchingNextPage] = useState(true)
const [errorFetchingNextPage, setNextPageFetchError] = useState<CombinedError | undefined>(
undefined
)

useEffect(() => {
setIsFetchingNextPage(true)
setPageVariables([])
setMaxItemsFetched(false)
setTimeout(() => {
setPageVariables([{ page: 0 }])
}, 100)
}, [slug, formValues])

const isFetching = isFetchingNextPage

return (
<NftPageLazyLoadWrapper>
<LazyLoadContainer
triggerDistance={50}
onLazyLoad={() =>
isFetching || maxItemsFetched
? null
: setPageVariables((pages) => [...pages, { page: pages.length + 1 }])
}
>
<Grid>
{pageVariables.length
? pageVariables.map(({ page }) => (
<NftFirehoseResults
page={page}
// @ts-ignore
formValues={formValues}
key={page}
slug={slug}
setMaxItemsFetched={setMaxItemsFetched}
setNextPageFetchError={setNextPageFetchError}
setIsFetchingNextPage={setIsFetchingNextPage}
/>
))
: null}
{isFetching ? <NftGridLoading /> : null}
</Grid>
{errorFetchingNextPage ? <NftError error={errorFetchingNextPage} /> : null}
</LazyLoadContainer>
</NftPageLazyLoadWrapper>
)
}

type Props = {
formValues: NftFilterFormValuesType
slug: string
}

export default NftFirehose
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './Firehose'
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useSortBy, useTable } from 'react-table'
import { ExplorerGatewayNftCollectionType } from '@core/network/api/nfts/types'
import { HeaderText, HeaderToggle, StickyTableHeader, TableWrapper } from 'components/Table'

import { Props as OwnProps } from '..'
import { Props as OwnProps } from '../Home'
import { getFloorPriceColumn } from './floor_price'
import { getNameColumn } from './name.column'
import { getOwnersColumn } from './owners.column'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './Home'
13 changes: 11 additions & 2 deletions packages/blockchain-wallet-v4-frontend/src/scenes/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ const VerifyEmailToken = React.lazy(() => import('./VerifyEmailToken'))
const VerifyEmail = React.lazy(() => import('./VerifyEmail'))

// EXPLORE (mixed)
const NftsExplorer = React.lazy(() => import('./Nfts/Explore'))
const NftsHome = React.lazy(() => import('./Nfts/Home'))
const NftsFirehose = React.lazy(() => import('./Nfts/Firehose'))
const NftsCollection = React.lazy(() => import('./Nfts/Collection/Collection'))
const NftsAsset = React.lazy(() => import('./Nfts/Asset'))

Expand Down Expand Up @@ -189,7 +190,15 @@ const App = ({
<NftsLayout
path='/nfts'
exact
component={NftsExplorer}
component={NftsHome}
pageTitle={`${BLOCKCHAIN_TITLE} | NFT Explorer`}
/>
)}
{nftExplorer && (
<NftsLayout
path='/nfts/explore'
exact
component={NftsFirehose}
pageTitle={`${BLOCKCHAIN_TITLE} | NFT Explorer`}
/>
)}
Expand Down

0 comments on commit 5761fe2

Please sign in to comment.