diff --git a/src/components/pages/Profile/History/Downloads.tsx b/src/components/pages/Profile/History/Downloads.tsx
index 0d206b631..ef06b9f01 100644
--- a/src/components/pages/Profile/History/Downloads.tsx
+++ b/src/components/pages/Profile/History/Downloads.tsx
@@ -1,64 +1,33 @@
-import React, { ReactElement, useEffect, useState } from 'react'
+import React, { ReactElement } from 'react'
import Table from '../../../atoms/Table'
-import { gql } from 'urql'
import Time from '../../../atoms/Time'
-import web3 from 'web3'
import AssetTitle from '../../../molecules/AssetListTitle'
-import axios from 'axios'
-import { retrieveDDO } from '../../../../utils/aquarius'
-import { Logger } from '@oceanprotocol/lib'
-import { useSiteMetadata } from '../../../../hooks/useSiteMetadata'
-import { useUserPreferences } from '../../../../providers/UserPreferences'
-import { fetchDataForMultipleChains } from '../../../../utils/subgraph'
-import { OrdersData_tokenOrders as OrdersData } from '../../../../@types/apollo/OrdersData'
import NetworkName from '../../../atoms/NetworkName'
-
-const getTokenOrders = gql`
- query OrdersData($user: String!) {
- tokenOrders(
- orderBy: timestamp
- orderDirection: desc
- where: { consumer: $user }
- ) {
- datatokenId {
- address
- symbol
- }
- timestamp
- tx
- }
- }
-`
-
-interface DownloadedAssets {
- did: string
- dtSymbol: string
- timestamp: number
- networkId: number
-}
+import { useProfile } from '../../../../providers/Profile'
+import { DownloadedAsset } from '../../../../utils/aquarius'
const columns = [
{
name: 'Data Set',
- selector: function getAssetRow(row: DownloadedAssets) {
- return
+ selector: function getAssetRow(row: DownloadedAsset) {
+ return
}
},
{
name: 'Network',
- selector: function getNetwork(row: DownloadedAssets) {
+ selector: function getNetwork(row: DownloadedAsset) {
return
}
},
{
name: 'Datatoken',
- selector: function getTitleRow(row: DownloadedAssets) {
+ selector: function getTitleRow(row: DownloadedAsset) {
return row.dtSymbol
}
},
{
name: 'Time',
- selector: function getTimeRow(row: DownloadedAssets) {
+ selector: function getTimeRow(row: DownloadedAsset) {
return
}
}
@@ -69,67 +38,14 @@ export default function ComputeDownloads({
}: {
accountId: string
}): ReactElement {
- const { appConfig } = useSiteMetadata()
- const [isLoading, setIsLoading] = useState(false)
- const [orders, setOrders] = useState
()
- const { chainIds } = useUserPreferences()
-
- useEffect(() => {
- const variables = { user: accountId?.toLowerCase() }
-
- async function filterAssets() {
- const filteredOrders: DownloadedAssets[] = []
- const source = axios.CancelToken.source()
- try {
- setIsLoading(true)
- const response = await fetchDataForMultipleChains(
- getTokenOrders,
- variables,
- chainIds
- )
-
- const data: OrdersData[] = []
- for (let i = 0; i < response.length; i++) {
- response[i].tokenOrders.forEach((tokenOrder: OrdersData) => {
- data.push(tokenOrder)
- })
- }
-
- for (let i = 0; i < data.length; i++) {
- const did = web3.utils
- .toChecksumAddress(data[i].datatokenId.address)
- .replace('0x', 'did:op:')
- const ddo = await retrieveDDO(did, source.token)
- if (!ddo) continue
- if (ddo.service[1].type === 'access') {
- filteredOrders.push({
- did: did,
- networkId: ddo.chainId,
- dtSymbol: data[i].datatokenId.symbol,
- timestamp: data[i].timestamp
- })
- }
- }
- const sortedOrders = filteredOrders.sort(
- (a, b) => b.timestamp - a.timestamp
- )
- setOrders(sortedOrders)
- } catch (err) {
- Logger.log(err.message)
- } finally {
- setIsLoading(false)
- }
- }
-
- filterAssets()
- }, [accountId, appConfig.metadataCacheUri, chainIds])
+ const { downloads, isDownloadsLoading } = useProfile()
return accountId ? (
) : (
Please connect your Web3 wallet.
diff --git a/src/components/pages/Profile/History/PoolShares.tsx b/src/components/pages/Profile/History/PoolShares.tsx
index 48d6e2945..80c1a1a98 100644
--- a/src/components/pages/Profile/History/PoolShares.tsx
+++ b/src/components/pages/Profile/History/PoolShares.tsx
@@ -3,61 +3,31 @@ import Table from '../../../atoms/Table'
import Conversion from '../../../atoms/Price/Conversion'
import styles from './PoolShares.module.css'
import AssetTitle from '../../../molecules/AssetListTitle'
-import { gql } from 'urql'
import {
PoolShares_poolShares as PoolShare,
PoolShares_poolShares_poolId_tokens as PoolSharePoolIdTokens
} from '../../../../@types/apollo/PoolShares'
import web3 from 'web3'
import Token from '../../../organisms/AssetActions/Pool/Token'
-import { useUserPreferences } from '../../../../providers/UserPreferences'
-import {
- fetchDataForMultipleChains,
- calculateUserLiquidity
-} from '../../../../utils/subgraph'
+import { calculateUserLiquidity } from '../../../../utils/subgraph'
import NetworkName from '../../../atoms/NetworkName'
-import axios from 'axios'
+import axios, { CancelToken } from 'axios'
import { retrieveDDO } from '../../../../utils/aquarius'
import { isValidNumber } from '../../../../utils/numberValidations'
import Decimal from 'decimal.js'
+import { useProfile } from '../../../../providers/Profile'
+import { DDO } from '@oceanprotocol/lib'
Decimal.set({ toExpNeg: -18, precision: 18, rounding: 1 })
const REFETCH_INTERVAL = 20000
-const poolSharesQuery = gql`
- query PoolShares($user: String) {
- poolShares(where: { userAddress: $user, balance_gt: 0.001 }, first: 1000) {
- id
- balance
- userAddress {
- id
- }
- poolId {
- id
- datatokenAddress
- valueLocked
- tokens {
- id
- isDatatoken
- symbol
- }
- oceanReserve
- datatokenReserve
- totalShares
- consumePrice
- spotPrice
- createTime
- }
- }
- }
-`
-
interface Asset {
userLiquidity: number
poolShare: PoolShare
networkId: number
createTime: number
+ ddo: DDO
}
function findTokenByType(tokens: PoolSharePoolIdTokens[], type: string) {
@@ -126,10 +96,7 @@ const columns = [
{
name: 'Data Set',
selector: function getAssetRow(row: Asset) {
- const did = web3.utils
- .toChecksumAddress(row.poolShare.poolId.datatokenAddress)
- .replace('0x', 'did:op:')
- return
+ return
},
grow: 2
},
@@ -161,38 +128,27 @@ const columns = [
}
]
-async function getPoolSharesData(accountId: string, chainIds: number[]) {
- const variables = { user: accountId?.toLowerCase() }
- const data: PoolShare[] = []
- const result = await fetchDataForMultipleChains(
- poolSharesQuery,
- variables,
- chainIds
- )
- for (let i = 0; i < result.length; i++) {
- result[i].poolShares.forEach((poolShare: PoolShare) => {
- data.push(poolShare)
- })
- }
- return data
-}
-
-async function getPoolSharesAssets(data: PoolShare[]) {
+async function getPoolSharesAssets(
+ data: PoolShare[],
+ cancelToken: CancelToken
+) {
const assetList: Asset[] = []
- const source = axios.CancelToken.source()
for (let i = 0; i < data.length; i++) {
const did = web3.utils
.toChecksumAddress(data[i].poolId.datatokenAddress)
.replace('0x', 'did:op:')
- const ddo = await retrieveDDO(did, source.token)
+ const ddo = await retrieveDDO(did, cancelToken)
const userLiquidity = calculateUserLiquidity(data[i])
- assetList.push({
- poolShare: data[i],
- userLiquidity: userLiquidity,
- networkId: ddo?.chainId,
- createTime: data[i].poolId.createTime
- })
+
+ ddo &&
+ assetList.push({
+ poolShare: data[i],
+ userLiquidity: userLiquidity,
+ networkId: ddo?.chainId,
+ createTime: data[i].poolId.createTime,
+ ddo
+ })
}
const assets = assetList.sort((a, b) => b.createTime - a.createTime)
return assets
@@ -203,33 +159,36 @@ export default function PoolShares({
}: {
accountId: string
}): ReactElement {
+ const { poolShares, isPoolSharesLoading } = useProfile()
const [assets, setAssets] = useState()
const [loading, setLoading] = useState(false)
const [dataFetchInterval, setDataFetchInterval] = useState()
- const { chainIds } = useUserPreferences()
- const fetchPoolSharesData = useCallback(async () => {
- try {
- const data = await getPoolSharesData(accountId, chainIds)
- const newAssets = await getPoolSharesAssets(data)
+ const fetchPoolSharesAssets = useCallback(
+ async (cancelToken: CancelToken) => {
+ if (!poolShares || isPoolSharesLoading) return
- if (JSON.stringify(assets) !== JSON.stringify(newAssets)) {
- setAssets(newAssets)
+ try {
+ const assets = await getPoolSharesAssets(poolShares, cancelToken)
+ setAssets(assets)
+ } catch (error) {
+ console.error('Error fetching pool shares: ', error.message)
}
- } catch (error) {
- console.error('Error fetching pool shares: ', error.message)
- }
- }, [accountId, assets, chainIds])
+ },
+ [poolShares, isPoolSharesLoading]
+ )
useEffect(() => {
+ const cancelTokenSource = axios.CancelToken.source()
+
async function init() {
setLoading(true)
- await fetchPoolSharesData()
+ await fetchPoolSharesAssets(cancelTokenSource.token)
setLoading(false)
if (dataFetchInterval) return
const interval = setInterval(async () => {
- await fetchPoolSharesData()
+ await fetchPoolSharesAssets(cancelTokenSource.token)
}, REFETCH_INTERVAL)
setDataFetchInterval(interval)
}
@@ -237,8 +196,9 @@ export default function PoolShares({
return () => {
clearInterval(dataFetchInterval)
+ cancelTokenSource.cancel()
}
- }, [dataFetchInterval, fetchPoolSharesData])
+ }, [dataFetchInterval, fetchPoolSharesAssets])
return accountId ? (
()
const [isLoading, setIsLoading] = useState(false)
const [page, setPage] = useState(1)
- const [service, setServiceType] = useState()
+ const [service, setServiceType] = useState('dataset OR algorithm')
useEffect(() => {
- async function getPublished() {
- const serviceFiter =
- service === undefined ? 'dataset OR algorithm' : `${service}`
- if (!accountId) return
- const queryPublishedAssets = {
- page: page,
- offset: 9,
- query: {
- query_string: {
- query: `(publicKey.owner:${accountId}) AND (service.attributes.main.type:${serviceFiter}) AND (${transformChainIdsListToQuery(
- chainIds
- )})`
- }
- },
- sort: { created: -1 }
- }
- try {
- const source = axios.CancelToken.source()
+ if (!accountId) return
+ const cancelTokenSource = axios.CancelToken.source()
+
+ async function getPublished() {
+ try {
setIsLoading(true)
- const result = await queryMetadata(queryPublishedAssets, source.token)
+ const result = await getPublishedAssets(
+ accountId,
+ chainIds,
+ cancelTokenSource.token,
+ page,
+ service
+ )
setQueryResult(result)
} catch (error) {
Logger.error(error.message)
@@ -55,6 +45,10 @@ export default function PublishedList({
}
}
getPublished()
+
+ return () => {
+ cancelTokenSource.cancel()
+ }
}, [accountId, page, appConfig.metadataCacheUri, chainIds, service])
return accountId ? (
@@ -75,6 +69,7 @@ export default function PublishedList({
setPage(newPage)
}}
className={styles.assets}
+ noPublisher
/>
>
) : (
diff --git a/src/pages/profile/index.tsx b/src/pages/profile/index.tsx
index 451a639ea..2c2012f03 100644
--- a/src/pages/profile/index.tsx
+++ b/src/pages/profile/index.tsx
@@ -4,6 +4,7 @@ import { graphql, PageProps } from 'gatsby'
import ProfilePage from '../../components/pages/Profile'
import { accountTruncate } from '../../utils/web3'
import { useWeb3 } from '../../providers/Web3'
+import ProfileProvider from '../../providers/Profile'
export default function PageGatsbyProfile(props: PageProps): ReactElement {
const { accountId } = useWeb3()
@@ -18,7 +19,9 @@ export default function PageGatsbyProfile(props: PageProps): ReactElement {
return (
-
+
+
+
)
}
diff --git a/src/providers/Profile.tsx b/src/providers/Profile.tsx
new file mode 100644
index 000000000..cbe8d3bd2
--- /dev/null
+++ b/src/providers/Profile.tsx
@@ -0,0 +1,291 @@
+import React, {
+ useContext,
+ useState,
+ useEffect,
+ createContext,
+ ReactElement,
+ useCallback,
+ ReactNode
+} from 'react'
+import { getPoolSharesData, getUserTokenOrders } from '../utils/subgraph'
+import { useUserPreferences } from './UserPreferences'
+import { PoolShares_poolShares as PoolShare } from '../@types/apollo/PoolShares'
+import { DDO, Logger } from '@oceanprotocol/lib'
+import {
+ DownloadedAsset,
+ getDownloadAssets,
+ getPublishedAssets
+} from '../utils/aquarius'
+import { useSiteMetadata } from '../hooks/useSiteMetadata'
+import { Profile } from '../models/Profile'
+import { accountTruncate } from '../utils/web3'
+import axios, { CancelToken } from 'axios'
+import ethereumAddress from 'ethereum-address'
+import get3BoxProfile from '../utils/profile'
+import web3 from 'web3'
+
+interface ProfileProviderValue {
+ profile: Profile
+ poolShares: PoolShare[]
+ isPoolSharesLoading: boolean
+ assets: DDO[]
+ assetsTotal: number
+ isEthAddress: boolean
+ downloads: DownloadedAsset[]
+ downloadsTotal: number
+ isDownloadsLoading: boolean
+}
+
+const ProfileContext = createContext({} as ProfileProviderValue)
+
+const refreshInterval = 10000 // 10 sec.
+
+function ProfileProvider({
+ accountId,
+ children
+}: {
+ accountId: string
+ children: ReactNode
+}): ReactElement {
+ const { chainIds } = useUserPreferences()
+ const { appConfig } = useSiteMetadata()
+
+ const [isEthAddress, setIsEthAddress] = useState()
+
+ //
+ // Do nothing in all following effects
+ // when accountId is no ETH address
+ //
+ useEffect(() => {
+ const isEthAddress = ethereumAddress.isAddress(accountId)
+ setIsEthAddress(isEthAddress)
+ }, [accountId])
+
+ //
+ // 3Box
+ //
+ const [profile, setProfile] = useState({
+ name: accountTruncate(accountId),
+ image: null,
+ description: null,
+ links: null
+ })
+
+ useEffect(() => {
+ const clearedProfile: Profile = {
+ name: null,
+ image: null,
+ description: null,
+ links: null
+ }
+
+ if (!accountId || !isEthAddress) {
+ setProfile(clearedProfile)
+ return
+ }
+
+ const cancelTokenSource = axios.CancelToken.source()
+
+ async function getInfoFrom3Box() {
+ const profile3Box = await get3BoxProfile(
+ accountId,
+ cancelTokenSource.token
+ )
+ if (profile3Box) {
+ const { name, emoji, description, image, links } = profile3Box
+ const newName = `${emoji || ''} ${name || accountTruncate(accountId)}`
+ const newProfile = {
+ name: newName,
+ image,
+ description,
+ links
+ }
+ setProfile(newProfile)
+ Logger.log('[profile] Found and set 3box profile.', newProfile)
+ } else {
+ setProfile(clearedProfile)
+ Logger.log('[profile] No 3box profile found.')
+ }
+ }
+ getInfoFrom3Box()
+
+ return () => {
+ cancelTokenSource.cancel()
+ }
+ }, [accountId, isEthAddress])
+
+ //
+ // POOL SHARES
+ //
+ const [poolShares, setPoolShares] = useState()
+ const [isPoolSharesLoading, setIsPoolSharesLoading] = useState(false)
+ const [poolSharesInterval, setPoolSharesInterval] = useState()
+
+ const fetchPoolShares = useCallback(async () => {
+ if (!accountId || !chainIds || !isEthAddress) return
+
+ try {
+ setIsPoolSharesLoading(true)
+ const poolShares = await getPoolSharesData(accountId, chainIds)
+ setPoolShares(poolShares)
+ Logger.log(
+ `[profile] Fetched ${poolShares.length} pool shares.`,
+ poolShares
+ )
+ } catch (error) {
+ Logger.error('Error fetching pool shares: ', error.message)
+ } finally {
+ setIsPoolSharesLoading(false)
+ }
+ }, [accountId, chainIds, isEthAddress])
+
+ useEffect(() => {
+ async function init() {
+ await fetchPoolShares()
+
+ if (poolSharesInterval) return
+ const interval = setInterval(async () => {
+ await fetchPoolShares()
+ }, refreshInterval)
+ setPoolSharesInterval(interval)
+ }
+ init()
+
+ return () => {
+ clearInterval(poolSharesInterval)
+ }
+ }, [poolSharesInterval, fetchPoolShares])
+
+ //
+ // PUBLISHED ASSETS
+ //
+ const [assets, setAssets] = useState()
+ const [assetsTotal, setAssetsTotal] = useState(0)
+ // const [assetsWithPrices, setAssetsWithPrices] = useState()
+
+ useEffect(() => {
+ if (!accountId || !isEthAddress) return
+
+ const cancelTokenSource = axios.CancelToken.source()
+
+ async function getAllPublished() {
+ try {
+ const result = await getPublishedAssets(
+ accountId,
+ chainIds,
+ cancelTokenSource.token
+ )
+ setAssets(result.results)
+ setAssetsTotal(result.totalResults)
+ Logger.log(
+ `[profile] Fetched ${result.totalResults} assets.`,
+ result.results
+ )
+
+ // Hint: this would only make sense if we "search" in all subcomponents
+ // against this provider's state, meaning filtering via js rather then sending
+ // more queries to Aquarius.
+ // const assetsWithPrices = await getAssetsBestPrices(result.results)
+ // setAssetsWithPrices(assetsWithPrices)
+ } catch (error) {
+ Logger.error(error.message)
+ }
+ }
+ getAllPublished()
+
+ return () => {
+ cancelTokenSource.cancel()
+ }
+ }, [accountId, appConfig.metadataCacheUri, chainIds, isEthAddress])
+
+ //
+ // DOWNLOADS
+ //
+ const [downloads, setDownloads] = useState()
+ const [downloadsTotal, setDownloadsTotal] = useState(0)
+ const [isDownloadsLoading, setIsDownloadsLoading] = useState()
+ const [downloadsInterval, setDownloadsInterval] = useState()
+
+ const fetchDownloads = useCallback(
+ async (cancelToken: CancelToken) => {
+ if (!accountId || !chainIds) return
+
+ const didList: string[] = []
+ const tokenOrders = await getUserTokenOrders(accountId, chainIds)
+
+ for (let i = 0; i < tokenOrders?.length; i++) {
+ const did = web3.utils
+ .toChecksumAddress(tokenOrders[i].datatokenId.address)
+ .replace('0x', 'did:op:')
+ didList.push(did)
+ }
+
+ const downloads = await getDownloadAssets(
+ didList,
+ tokenOrders,
+ chainIds,
+ cancelToken
+ )
+ setDownloads(downloads)
+ setDownloadsTotal(downloads.length)
+ Logger.log(
+ `[profile] Fetched ${downloads.length} download orders.`,
+ downloads
+ )
+ },
+ [accountId, chainIds]
+ )
+
+ useEffect(() => {
+ const cancelTokenSource = axios.CancelToken.source()
+
+ async function getDownloadAssets() {
+ if (!appConfig?.metadataCacheUri) return
+
+ try {
+ setIsDownloadsLoading(true)
+ await fetchDownloads(cancelTokenSource.token)
+ } catch (err) {
+ Logger.log(err.message)
+ } finally {
+ setIsDownloadsLoading(false)
+ }
+ }
+ getDownloadAssets()
+
+ if (downloadsInterval) return
+ const interval = setInterval(async () => {
+ await fetchDownloads(cancelTokenSource.token)
+ }, refreshInterval)
+ setDownloadsInterval(interval)
+
+ return () => {
+ cancelTokenSource.cancel()
+ clearInterval(downloadsInterval)
+ }
+ }, [fetchDownloads, appConfig.metadataCacheUri, downloadsInterval])
+
+ return (
+
+ {children}
+
+ )
+}
+
+// Helper hook to access the provider values
+const useProfile = (): ProfileProviderValue => useContext(ProfileContext)
+
+export { ProfileProvider, useProfile, ProfileProviderValue, ProfileContext }
+export default ProfileProvider
diff --git a/src/utils/aquarius.ts b/src/utils/aquarius.ts
index 10adee35c..54cd909ba 100644
--- a/src/utils/aquarius.ts
+++ b/src/utils/aquarius.ts
@@ -12,7 +12,16 @@ import {
import { AssetSelectionAsset } from '../components/molecules/FormFields/AssetSelection'
import { PriceList, getAssetsPriceList } from './subgraph'
import axios, { CancelToken, AxiosResponse } from 'axios'
+import { OrdersData_tokenOrders as OrdersData } from '../@types/apollo/OrdersData'
import { metadataCacheUri } from '../../app.config'
+import web3 from '../../tests/unit/__mocks__/web3'
+
+export interface DownloadedAsset {
+ dtSymbol: string
+ timestamp: number
+ networkId: number
+ ddo: DDO
+}
function getQueryForAlgorithmDatasets(algorithmDid: string, chainId?: number) {
return {
@@ -66,7 +75,8 @@ export async function queryMetadata(
try {
const response: AxiosResponse = await axios.post(
`${metadataCacheUri}/api/v1/aquarius/assets/ddo/query`,
- { ...query, cancelToken }
+ { ...query },
+ { cancelToken }
)
if (!response || response.status !== 200 || !response.data) return
return transformQueryResult(response.data)
@@ -108,10 +118,8 @@ export async function getAssetsNames(
try {
const response: AxiosResponse> = await axios.post(
`${metadataCacheUri}/api/v1/aquarius/assets/names`,
- {
- didList,
- cancelToken
- }
+ { didList },
+ { cancelToken }
)
if (!response || response.status !== 200 || !response.data) return
return response.data
@@ -204,3 +212,122 @@ export async function getAlgorithmDatasetsForCompute(
)
return datasets
}
+
+export async function getPublishedAssets(
+ accountId: string,
+ chainIds: number[],
+ cancelToken: CancelToken,
+ page?: number,
+ type?: string
+): Promise {
+ if (!accountId) return
+
+ page = page || 1
+ type = type || 'dataset OR algorithm'
+
+ const queryPublishedAssets = {
+ page,
+ offset: 9,
+ query: {
+ query_string: {
+ query: `(publicKey.owner:${accountId}) AND (service.attributes.main.type:${type}) AND (${transformChainIdsListToQuery(
+ chainIds
+ )})`
+ }
+ },
+ sort: { created: -1 }
+ }
+
+ try {
+ const result = await queryMetadata(queryPublishedAssets, cancelToken)
+ return result
+ } catch (error) {
+ if (axios.isCancel(error)) {
+ Logger.log(error.message)
+ } else {
+ Logger.error(error.message)
+ }
+ }
+}
+
+export async function getAssetsFromDidList(
+ didList: string[],
+ chainIds: number[],
+ cancelToken: CancelToken
+): Promise {
+ try {
+ // TODO: figure out cleaner way to transform string[] into csv
+ const searchDids = JSON.stringify(didList)
+ .replace(/,/g, ' ')
+ .replace(/"/g, '')
+ .replace(/(\[|\])/g, '')
+ // for whatever reason ddo.id is not searchable, so use ddo.dataToken instead
+ .replace(/(did:op:)/g, '0x')
+
+ // safeguard against passed empty didList, preventing 500 from Aquarius
+ if (!searchDids) return
+
+ const query = {
+ page: 1,
+ offset: 1000,
+ query: {
+ query_string: {
+ query: `(${searchDids}) AND (${transformChainIdsListToQuery(
+ chainIds
+ )})`,
+ fields: ['dataToken'],
+ default_operator: 'OR'
+ }
+ },
+ sort: { created: -1 }
+ }
+
+ const queryResult = await queryMetadata(query, cancelToken)
+ return queryResult
+ } catch (error) {
+ Logger.error(error.message)
+ }
+}
+
+export async function getDownloadAssets(
+ didList: string[],
+ tokenOrders: OrdersData[],
+ chainIds: number[],
+ cancelToken: CancelToken
+): Promise {
+ const downloadedAssets: DownloadedAsset[] = []
+
+ try {
+ const queryResult = await getAssetsFromDidList(
+ didList,
+ chainIds,
+ cancelToken
+ )
+ const ddoList = queryResult?.results
+
+ for (let i = 0; i < tokenOrders?.length; i++) {
+ const ddo = ddoList.filter(
+ (ddo) =>
+ tokenOrders[i].datatokenId.address.toLowerCase() ===
+ ddo.dataToken.toLowerCase()
+ )[0]
+
+ // make sure we are only pushing download orders
+ if (ddo.service[1].type !== 'access') continue
+
+ downloadedAssets.push({
+ ddo,
+ networkId: ddo.chainId,
+ dtSymbol: tokenOrders[i].datatokenId.symbol,
+ timestamp: tokenOrders[i].timestamp
+ })
+ }
+
+ const sortedOrders = downloadedAssets.sort(
+ (a, b) => b.timestamp - a.timestamp
+ )
+ return sortedOrders
+ } catch (error) {
+ Logger.error(error.message)
+ }
+}
diff --git a/src/utils/subgraph.ts b/src/utils/subgraph.ts
index 182245347..ed253ed81 100644
--- a/src/utils/subgraph.ts
+++ b/src/utils/subgraph.ts
@@ -1,5 +1,5 @@
import { gql, OperationResult, TypedDocumentNode, OperationContext } from 'urql'
-import { DDO } from '@oceanprotocol/lib'
+import { DDO, Logger } from '@oceanprotocol/lib'
import { getUrqlClientInstance } from '../providers/UrqlProvider'
import { getOceanConfig } from './ocean'
import web3 from 'web3'
@@ -25,8 +25,9 @@ import {
PoolShares_poolShares as PoolShare
} from '../@types/apollo/PoolShares'
import { BestPrice } from '../models/BestPrice'
+import { OrdersData_tokenOrders as OrdersData } from '../@types/apollo/OrdersData'
-export interface UserTVL {
+export interface UserLiquidity {
price: string
oceanBalance: string
}
@@ -206,6 +207,52 @@ const UserSharesQuery = gql`
}
}
`
+
+const userPoolSharesQuery = gql`
+ query PoolShares($user: String) {
+ poolShares(where: { userAddress: $user, balance_gt: 0.001 }, first: 1000) {
+ id
+ balance
+ userAddress {
+ id
+ }
+ poolId {
+ id
+ datatokenAddress
+ valueLocked
+ tokens {
+ id
+ isDatatoken
+ symbol
+ }
+ oceanReserve
+ datatokenReserve
+ totalShares
+ consumePrice
+ spotPrice
+ createTime
+ }
+ }
+ }
+`
+
+const UserTokenOrders = gql`
+ query OrdersData($user: String!) {
+ tokenOrders(
+ orderBy: timestamp
+ orderDirection: desc
+ where: { consumer: $user }
+ ) {
+ datatokenId {
+ address
+ symbol
+ }
+ timestamp
+ tx
+ }
+ }
+`
+
export function getSubgraphUri(chainId: number): string {
const config = getOceanConfig(chainId)
return config.subgraphUri
@@ -604,7 +651,7 @@ export async function getAccountLiquidityInOwnAssets(
accountId: string,
chainIds: number[],
pools: string[]
-): Promise {
+): Promise {
const queryVariables = {
user: accountId.toLowerCase(),
pools: pools
@@ -630,3 +677,48 @@ export async function getAccountLiquidityInOwnAssets(
oceanBalance: totalOceanLiquidity.toString()
}
}
+
+export async function getPoolSharesData(
+ accountId: string,
+ chainIds: number[]
+): Promise {
+ const variables = { user: accountId?.toLowerCase() }
+ const data: PoolShare[] = []
+ const result = await fetchDataForMultipleChains(
+ userPoolSharesQuery,
+ variables,
+ chainIds
+ )
+ for (let i = 0; i < result.length; i++) {
+ result[i].poolShares.forEach((poolShare: PoolShare) => {
+ data.push(poolShare)
+ })
+ }
+ return data
+}
+
+export async function getUserTokenOrders(
+ accountId: string,
+ chainIds: number[]
+): Promise {
+ const data: OrdersData[] = []
+ const variables = { user: accountId?.toLowerCase() }
+
+ try {
+ const tokenOrders = await fetchDataForMultipleChains(
+ UserTokenOrders,
+ variables,
+ chainIds
+ )
+
+ for (let i = 0; i < tokenOrders?.length; i++) {
+ tokenOrders[i].tokenOrders.forEach((tokenOrder: OrdersData) => {
+ data.push(tokenOrder)
+ })
+ }
+
+ return data
+ } catch (error) {
+ Logger.error(error.message)
+ }
+}