mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
Highest liquidity list based on subgraph (#512)
* fetch pools from graph, fetch ddos for pools * WIP on displaying highest liquidity assets * loader added * check ddo state for each asset * data ordered by valueLocked, logger added * filter ddos for purgatory * verify ddo isConsumable price attribute * moved query into subgraph.ts * send did list, fix assets display * fixes on assets display * assets sorted by dids * get assets on correct order * get assets in correct order * loading assets fixes * correct order and loading, network overloaded * fixes on loading * fixed on network change, added loading * fixed on network change when no wallet connected, improved loading Co-authored-by: claudia.holhos <claudia.holhos@hpm.ro> Co-authored-by: Matthias Kretschmann <m@kretschmann.io> Co-authored-by: Norbi <katunanorbert@gmai.com>
This commit is contained in:
parent
94139f42b4
commit
88663d812a
@ -12,19 +12,10 @@ import Button from '../atoms/Button'
|
|||||||
import Bookmarks from '../molecules/Bookmarks'
|
import Bookmarks from '../molecules/Bookmarks'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { queryMetadata } from '../../utils/aquarius'
|
import { queryMetadata } from '../../utils/aquarius'
|
||||||
|
import { getHighestLiquidityDIDs } from '../../utils/subgraph'
|
||||||
|
import { DDO, Logger } from '@oceanprotocol/lib'
|
||||||
import { useWeb3 } from '../../providers/Web3'
|
import { useWeb3 } from '../../providers/Web3'
|
||||||
|
|
||||||
const queryHighest = {
|
|
||||||
page: 1,
|
|
||||||
offset: 9,
|
|
||||||
query: {
|
|
||||||
query_string: {
|
|
||||||
query: `(price.type:pool) -isInPurgatory:true`
|
|
||||||
}
|
|
||||||
},
|
|
||||||
sort: { 'price.ocean': -1 }
|
|
||||||
}
|
|
||||||
|
|
||||||
const queryLatest = {
|
const queryLatest = {
|
||||||
page: 1,
|
page: 1,
|
||||||
offset: 9,
|
offset: 9,
|
||||||
@ -36,48 +27,99 @@ const queryLatest = {
|
|||||||
sort: { created: -1 }
|
sort: { created: -1 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sortElements(items: DDO[], sorted: string[]) {
|
||||||
|
items.sort(function (a, b) {
|
||||||
|
return sorted.indexOf(a.dataToken) - sorted.indexOf(b.dataToken)
|
||||||
|
})
|
||||||
|
return items
|
||||||
|
}
|
||||||
|
|
||||||
function SectionQueryResult({
|
function SectionQueryResult({
|
||||||
title,
|
title,
|
||||||
query,
|
query,
|
||||||
action
|
action,
|
||||||
|
queryData
|
||||||
}: {
|
}: {
|
||||||
title: ReactElement | string
|
title: ReactElement | string
|
||||||
query: SearchQuery
|
query: SearchQuery
|
||||||
action?: ReactElement
|
action?: ReactElement
|
||||||
|
queryData?: string
|
||||||
}) {
|
}) {
|
||||||
const { config } = useOcean()
|
const { config } = useOcean()
|
||||||
const [result, setResult] = useState<QueryResult>()
|
const [result, setResult] = useState<QueryResult>()
|
||||||
const { web3Loading } = useWeb3()
|
const [loading, setLoading] = useState<boolean>()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!config?.metadataCacheUri || web3Loading) return
|
if (!config?.metadataCacheUri) return
|
||||||
const source = axios.CancelToken.source()
|
const source = axios.CancelToken.source()
|
||||||
|
|
||||||
async function init() {
|
async function init() {
|
||||||
|
try {
|
||||||
|
setLoading(true)
|
||||||
const result = await queryMetadata(
|
const result = await queryMetadata(
|
||||||
query,
|
query,
|
||||||
config.metadataCacheUri,
|
config.metadataCacheUri,
|
||||||
source.token
|
source.token
|
||||||
)
|
)
|
||||||
|
if (result.totalResults <= 15) {
|
||||||
|
const searchDIDs = queryData.split(' ')
|
||||||
|
const sortedAssets = sortElements(result.results, searchDIDs)
|
||||||
|
// We take more assets than we need from the subgraph (to make sure
|
||||||
|
// all the 9 assets with highest liquidity we need are in OceanDB)
|
||||||
|
// so we need to get rid of the surplus
|
||||||
|
const overflow = sortedAssets.length - 9
|
||||||
|
sortedAssets.splice(sortedAssets.length - overflow, overflow)
|
||||||
|
result.results = sortedAssets
|
||||||
|
}
|
||||||
|
if (result.results.length === 0) return
|
||||||
setResult(result)
|
setResult(result)
|
||||||
|
setLoading(false)
|
||||||
|
} catch (error) {
|
||||||
|
Logger.log(error.message)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
init()
|
init()
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
source.cancel()
|
source.cancel()
|
||||||
}
|
}
|
||||||
}, [config?.metadataCacheUri, query, web3Loading])
|
}, [query, config?.metadataCacheUri])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={styles.section}>
|
<section className={styles.section}>
|
||||||
<h3>{title}</h3>
|
<h3>{title}</h3>
|
||||||
<AssetList assets={result?.results} showPagination={false} />
|
<AssetList
|
||||||
|
assets={result?.results}
|
||||||
|
showPagination={false}
|
||||||
|
isLoading={loading}
|
||||||
|
/>
|
||||||
{action && action}
|
{action && action}
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function HomePage(): ReactElement {
|
export default function HomePage(): ReactElement {
|
||||||
|
const { config, loading } = useOcean()
|
||||||
|
const [queryAndDids, setQueryAndDids] = useState<[SearchQuery, string]>()
|
||||||
|
const { web3Loading, web3Provider } = useWeb3()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (loading || (web3Loading && web3Provider)) return
|
||||||
|
getHighestLiquidityDIDs().then((results) => {
|
||||||
|
const queryHighest = {
|
||||||
|
page: 1,
|
||||||
|
offset: 15,
|
||||||
|
query: {
|
||||||
|
query_string: {
|
||||||
|
query: `(${results}) AND -isInPurgatory:true AND price.isConsumable:true`,
|
||||||
|
fields: ['dataToken']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setQueryAndDids([queryHighest, results])
|
||||||
|
})
|
||||||
|
}, [config.subgraphUri, loading, web3Loading])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Container narrow className={styles.searchWrap}>
|
<Container narrow className={styles.searchWrap}>
|
||||||
@ -89,18 +131,13 @@ export default function HomePage(): ReactElement {
|
|||||||
<Bookmarks />
|
<Bookmarks />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
{queryAndDids && (
|
||||||
<SectionQueryResult
|
<SectionQueryResult
|
||||||
title="Highest Liquidity"
|
title="Highest Liquidity"
|
||||||
query={queryHighest}
|
query={queryAndDids[0]}
|
||||||
action={
|
queryData={queryAndDids[1]}
|
||||||
<Button
|
|
||||||
style="text"
|
|
||||||
to="/search?priceType=pool&sort=liquidity&sortOrder=desc"
|
|
||||||
>
|
|
||||||
Data sets and algorithms with pool →
|
|
||||||
</Button>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<SectionQueryResult
|
<SectionQueryResult
|
||||||
title="Recently Published"
|
title="Recently Published"
|
||||||
|
@ -30,6 +30,7 @@ interface OceanProviderValue {
|
|||||||
config: ConfigHelperConfig
|
config: ConfigHelperConfig
|
||||||
account: Account
|
account: Account
|
||||||
balance: UserBalance
|
balance: UserBalance
|
||||||
|
loading: boolean
|
||||||
connect: (config?: Config) => Promise<void>
|
connect: (config?: Config) => Promise<void>
|
||||||
refreshBalance: () => Promise<void>
|
refreshBalance: () => Promise<void>
|
||||||
}
|
}
|
||||||
@ -53,27 +54,29 @@ function OceanProvider({
|
|||||||
const [config, setConfig] = useState<ConfigHelperConfig | Config>(
|
const [config, setConfig] = useState<ConfigHelperConfig | Config>(
|
||||||
initialConfig
|
initialConfig
|
||||||
)
|
)
|
||||||
|
const [loading, setLoading] = useState<boolean>()
|
||||||
|
|
||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
// Create Ocean instance
|
// Create Ocean instance
|
||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
const connect = useCallback(
|
const connect = useCallback(
|
||||||
async (newConfig?: ConfigHelperConfig | Config) => {
|
async (newConfig?: ConfigHelperConfig | Config) => {
|
||||||
|
setLoading(true)
|
||||||
try {
|
try {
|
||||||
const usedConfig = newConfig || config
|
const usedConfig = newConfig || config
|
||||||
Logger.log('[ocean] Connecting Ocean...', usedConfig)
|
Logger.log('[ocean] Connecting Ocean...', usedConfig)
|
||||||
|
|
||||||
usedConfig.web3Provider = web3 || initialConfig.web3Provider
|
usedConfig.web3Provider = web3 || initialConfig.web3Provider
|
||||||
|
|
||||||
if (newConfig) {
|
if (newConfig) {
|
||||||
setConfig(usedConfig)
|
await setConfig(usedConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usedConfig.web3Provider) {
|
if (usedConfig.web3Provider) {
|
||||||
const newOcean = await Ocean.getInstance(usedConfig)
|
const newOcean = await Ocean.getInstance(usedConfig)
|
||||||
setOcean(newOcean)
|
await setOcean(newOcean)
|
||||||
Logger.log('[ocean] Ocean instance created.', newOcean)
|
Logger.log('[ocean] Ocean instance created.', newOcean)
|
||||||
}
|
}
|
||||||
|
setLoading(false)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
Logger.error('[ocean] Error: ', error.message)
|
Logger.error('[ocean] Error: ', error.message)
|
||||||
}
|
}
|
||||||
@ -136,7 +139,9 @@ function OceanProvider({
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
setLoading(true)
|
||||||
await connect(newConfig)
|
await connect(newConfig)
|
||||||
|
setLoading(false)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
Logger.error('[ocean] Error: ', error.message)
|
Logger.error('[ocean] Error: ', error.message)
|
||||||
}
|
}
|
||||||
@ -152,6 +157,7 @@ function OceanProvider({
|
|||||||
account,
|
account,
|
||||||
balance,
|
balance,
|
||||||
config,
|
config,
|
||||||
|
loading,
|
||||||
connect,
|
connect,
|
||||||
refreshBalance
|
refreshBalance
|
||||||
} as OceanProviderValue
|
} as OceanProviderValue
|
||||||
|
@ -10,7 +10,7 @@ import {
|
|||||||
AssetsFrePrice_fixedRateExchanges as AssetsFrePriceFixedRateExchanges
|
AssetsFrePrice_fixedRateExchanges as AssetsFrePriceFixedRateExchanges
|
||||||
} from '../@types/apollo/AssetsFrePrice'
|
} from '../@types/apollo/AssetsFrePrice'
|
||||||
import { AssetPreviousOrder } from '../@types/apollo/AssetPreviousOrder'
|
import { AssetPreviousOrder } from '../@types/apollo/AssetPreviousOrder'
|
||||||
import BigNumber from 'bignumber.js'
|
import web3 from 'web3'
|
||||||
|
|
||||||
export interface PriceList {
|
export interface PriceList {
|
||||||
[key: string]: string
|
[key: string]: string
|
||||||
@ -86,6 +86,20 @@ const PreviousOrderQuery = gql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
const HighestLiquidityAssets = gql`
|
||||||
|
query HighestLiquidiyAssets {
|
||||||
|
pools(orderBy: valueLocked, orderDirection: desc, first: 15) {
|
||||||
|
id
|
||||||
|
consumePrice
|
||||||
|
spotPrice
|
||||||
|
tx
|
||||||
|
symbol
|
||||||
|
name
|
||||||
|
datatokenAddress
|
||||||
|
valueLocked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
async function fetchData(
|
async function fetchData(
|
||||||
query: DocumentNode,
|
query: DocumentNode,
|
||||||
@ -298,3 +312,22 @@ export async function getAssetsBestPrices(
|
|||||||
|
|
||||||
return assetsWithPrice
|
return assetsWithPrice
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getHighestLiquidityDIDs(): Promise<string> {
|
||||||
|
const didList: string[] = []
|
||||||
|
const fetchedPools = await fetchData(HighestLiquidityAssets, null)
|
||||||
|
if (fetchedPools.data?.pools?.length === 0) return null
|
||||||
|
for (let i = 0; i < fetchedPools.data.pools.length; i++) {
|
||||||
|
if (!fetchedPools.data.pools[i].datatokenAddress) continue
|
||||||
|
const did = web3.utils
|
||||||
|
.toChecksumAddress(fetchedPools.data.pools[i].datatokenAddress)
|
||||||
|
.replace('0x', 'did:op:')
|
||||||
|
didList.push(did)
|
||||||
|
}
|
||||||
|
const searchDids = JSON.stringify(didList)
|
||||||
|
.replace(/,/g, ' ')
|
||||||
|
.replace(/"/g, '')
|
||||||
|
.replace(/(\[|\])/g, '')
|
||||||
|
.replace(/(did:op:)/g, '0x')
|
||||||
|
return searchDids
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user