1
0
mirror of https://github.com/oceanprotocol/market.git synced 2024-12-02 05:57:29 +01:00

Merge pull request #993 from oceanprotocol/v4-subgraph

This commit is contained in:
Matthias Kretschmann 2022-01-17 14:30:23 +00:00 committed by GitHub
commit 04e0d687ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 465 additions and 4578 deletions

2
.gitignore vendored
View File

@ -10,7 +10,7 @@ coverage
.vercel .vercel
repo-metadata.json repo-metadata.json
networks-metadata.json networks-metadata.json
src/@types/apollo src/@types/subgraph
graphql.schema.json graphql.schema.json
src/@types/graph.types.ts src/@types/graph.types.ts
tsconfig.tsbuildinfo tsconfig.tsbuildinfo

View File

@ -1,10 +0,0 @@
module.exports = {
client: {
service: {
name: 'ocean',
url: 'https://subgraph.rinkeby.oceanprotocol.com/subgraphs/name/oceanprotocol/ocean-subgraph',
// optional disable SSL validation check
skipSSLValidation: true
}
}
}

View File

@ -1,22 +0,0 @@
overwrite: true
schema: 'https://subgraph.rinkeby.oceanprotocol.com/subgraphs/name/oceanprotocol/ocean-subgraph'
documents:
- './src/@utils/aquarius.ts'
- './src/@utils/subgraph.ts'
- './src/@context/Profile.tsx'
- './src/components/@shared/PoolTransactions/index.tsx'
- './src/components/@shared/Asset/AssetActions/Consume.tsx'
- './src/components/@shared/Asset/AssetActions/Pool/index.tsx'
- './src/components/@shared/Asset/AssetActions/Pool/Graph.tsx'
- './src/components/@shared/Asset/AssetContent/EditHistory.tsx'
- './src/components/Profile/Header/Stats.tsx'
- './src/components/Profile/History/PoolShares.tsx'
generates:
./src/@types/graph.types.ts:
plugins:
- 'typescript'
- 'typescript-operations'
- 'typescript-react-apollo'
./graphql.schema.json:
plugins:
- 'introspection'

4077
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -10,14 +10,12 @@
"serve": "serve -s public/", "serve": "serve -s public/",
"pregenerate": "bash scripts/pregenerate.sh", "pregenerate": "bash scripts/pregenerate.sh",
"test": "npm run pregenerate && npm run lint && npm run type-check", "test": "npm run pregenerate && npm run lint && npm run type-check",
"test:graphql": "npm run codegen:graphql && npm run lint",
"lint": "eslint --ignore-path .gitignore --ext .js --ext .ts --ext .tsx .", "lint": "eslint --ignore-path .gitignore --ext .js --ext .ts --ext .tsx .",
"format": "prettier --ignore-path .gitignore './**/*.{css,yml,js,ts,tsx,json}' --write", "format": "prettier --ignore-path .gitignore './**/*.{css,yml,js,ts,tsx,json}' --write",
"type-check": "tsc --noEmit", "type-check": "tsc --noEmit",
"deploy:s3": "bash scripts/deploy-s3.sh", "deploy:s3": "bash scripts/deploy-s3.sh",
"postinstall": "husky install", "postinstall": "husky install",
"codegen:apollo": "apollo client:codegen --target typescript --tsFileExtension=d.ts --outputFlat src/@types/apollo/", "codegen:apollo": "apollo client:codegen --endpoint=https://subgraphv4.rinkeby.oceanprotocol.com/subgraphs/name/oceanprotocol/ocean-subgraph --target typescript --tsFileExtension=d.ts --outputFlat src/@types/subgraph/"
"codegen:graphql": "graphql-codegen --config codegen.yml"
}, },
"dependencies": { "dependencies": {
"@coingecko/cryptoformat": "^0.4.4", "@coingecko/cryptoformat": "^0.4.4",
@ -75,11 +73,6 @@
"yup": "^0.32.11" "yup": "^0.32.11"
}, },
"devDependencies": { "devDependencies": {
"@graphql-codegen/cli": "^2.3.1",
"@graphql-codegen/introspection": "^2.1.1",
"@graphql-codegen/typescript": "^2.4.2",
"@graphql-codegen/typescript-operations": "^2.2.2",
"@graphql-codegen/typescript-react-apollo": "^3.2.3",
"@svgr/webpack": "^6.2.0", "@svgr/webpack": "^6.2.0",
"@types/chart.js": "^2.9.35", "@types/chart.js": "^2.9.35",
"@types/d3": "^7.1.0", "@types/d3": "^7.1.0",

View File

@ -3,9 +3,6 @@
# Write out repo metadata # Write out repo metadata
node ./scripts/write-repo-metadata > content/repo-metadata.json node ./scripts/write-repo-metadata > content/repo-metadata.json
# Generate GraphQL typings for urql
# npm run codegen:graphql
# Generate Apollo typings # Generate Apollo typings
npm run codegen:apollo npm run codegen:apollo

View File

@ -13,7 +13,7 @@ import {
getUserTokenOrders getUserTokenOrders
} from '@utils/subgraph' } from '@utils/subgraph'
import { useUserPreferences } from './UserPreferences' import { useUserPreferences } from './UserPreferences'
import { PoolShares_poolShares as PoolShare } from '../@types/apollo/PoolShares' import { PoolShares_poolShares as PoolShare } from '../@types/subgraph/PoolShares'
import { Asset, LoggerInstance } from '@oceanprotocol/lib' import { Asset, LoggerInstance } from '@oceanprotocol/lib'
import { getDownloadAssets, getPublishedAssets } from '@utils/aquarius' import { getDownloadAssets, getPublishedAssets } from '@utils/aquarius'
import { useSiteMetadata } from '@hooks/useSiteMetadata' import { useSiteMetadata } from '@hooks/useSiteMetadata'
@ -226,7 +226,7 @@ function ProfileProvider({
for (let i = 0; i < tokenOrders?.length; i++) { for (let i = 0; i < tokenOrders?.length; i++) {
const did = web3.utils const did = web3.utils
.toChecksumAddress(tokenOrders[i].datatokenId.address) .toChecksumAddress(tokenOrders[i].token.address)
.replace('0x', 'did:op:') .replace('0x', 'did:op:')
didList.push(did) didList.push(did)
} }

View File

@ -7,10 +7,10 @@ import { getOceanConfig } from '@utils/ocean'
const blockDifferenceThreshold = 30 const blockDifferenceThreshold = 30
const ethGraphUrl = `https://api.thegraph.com/subgraphs/name/blocklytics/ethereum-blocks` const ethGraphUrl = `https://api.thegraph.com/subgraphs/name/blocklytics/ethereum-blocks`
const ethGraphQuery = const ethGraphQueryBody =
'{"query":" query Blocks{ blocks(first: 1, skip: 0, orderBy: number, orderDirection: desc, where: {number_gt: 9300000}) { id number timestamp author difficulty gasUsed gasLimit } }","variables":{},"operationName":"Blocks"}' '{"query":" query Blocks{ blocks(first: 1, skip: 0, orderBy: number, orderDirection: desc, where: {number_gt: 9300000}) { id number timestamp author difficulty gasUsed gasLimit } }","variables":{},"operationName":"Blocks"}'
const graphQuery = const graphQueryBody =
'{"query":" query Meta { _meta { block { hash number } deployment hasIndexingErrors } }","variables":{},"operationName":"Meta"}' '{"query": "query Meta { _meta { block { hash number } deployment hasIndexingErrors } }", "variables": {},"operationName":"Meta"}'
export interface UseGraphSyncStatus { export interface UseGraphSyncStatus {
isGraphSynced: boolean isGraphSynced: boolean
@ -34,7 +34,7 @@ async function getBlockHead(config: Config) {
if (!config) return if (!config) return
// for ETH main, get block from graph fetch // for ETH main, get block from graph fetch
if (config.network === 'mainnet') { if (config.network === 'mainnet') {
const response: any = await fetchGraph(ethGraphUrl, ethGraphQuery) const response: any = await fetchGraph(ethGraphUrl, ethGraphQueryBody)
return Number(response?.data?.blocks[0]?.number) return Number(response?.data?.blocks[0]?.number)
} }
@ -47,9 +47,9 @@ async function getBlockHead(config: Config) {
async function getBlockSubgraph(subgraphUri: string) { async function getBlockSubgraph(subgraphUri: string) {
const response: any = await fetchGraph( const response: any = await fetchGraph(
`${subgraphUri}/subgraphs/name/oceanprotocol/ocean-subgraph`, `${subgraphUri}/subgraphs/name/oceanprotocol/ocean-subgraph`,
graphQuery graphQueryBody
) )
const blockNumberGraph = Number(response?.data?._meta?.block?.number) const blockNumberGraph = Number(response?.data?.data?._meta?.block?.number)
return blockNumberGraph return blockNumberGraph
} }

View File

@ -6,7 +6,7 @@ import {
import { AssetSelectionAsset } from '@shared/FormFields/AssetSelection' import { AssetSelectionAsset } from '@shared/FormFields/AssetSelection'
import { PriceList, getAssetsPriceList } from './subgraph' import { PriceList, getAssetsPriceList } from './subgraph'
import axios, { CancelToken, AxiosResponse } from 'axios' import axios, { CancelToken, AxiosResponse } from 'axios'
import { OrdersData_tokenOrders as OrdersData } from '../@types/apollo/OrdersData' import { OrdersData_orders as OrdersData } from '../@types/subgraph/OrdersData'
import { metadataCacheUri } from '../../app.config' import { metadataCacheUri } from '../../app.config'
import { import {
SortDirectionOptions, SortDirectionOptions,
@ -348,16 +348,16 @@ export async function getDownloadAssets(
const downloadedAssets: DownloadedAsset[] = result.results const downloadedAssets: DownloadedAsset[] = result.results
.map((ddo) => { .map((ddo) => {
const order = tokenOrders.find( const order = tokenOrders.find(
({ datatokenId }) => ({ token }) =>
datatokenId?.address.toLowerCase() === token?.address.toLowerCase() ===
ddo.services[0].datatokenAddress.toLowerCase() ddo.services[0].datatokenAddress.toLowerCase()
) )
return { return {
ddo, ddo,
networkId: ddo.chainId, networkId: ddo.chainId,
dtSymbol: order?.datatokenId?.symbol, dtSymbol: order?.token?.symbol,
timestamp: order?.timestamp timestamp: order?.createdTimestamp
} }
}) })
.sort((a, b) => b.timestamp - a.timestamp) .sort((a, b) => b.timestamp - a.timestamp)

View File

@ -17,18 +17,19 @@ import { fetchDataForMultipleChains } from './subgraph'
const getComputeOrders = gql` const getComputeOrders = gql`
query ComputeOrders($user: String!) { query ComputeOrders($user: String!) {
tokenOrders( orders(
orderBy: timestamp orderBy: createdTimestamp
orderDirection: desc orderDirection: desc
where: { payer: $user } where: { payer: $user }
) { ) {
id id
serviceId serviceId
datatokenId { token {
address address
isDatatoken
} }
tx tx
timestamp createdTimestamp
} }
} }
` `
@ -38,18 +39,19 @@ const getComputeOrdersByDatatokenAddress = gql`
$user: String! $user: String!
$datatokenAddress: String! $datatokenAddress: String!
) { ) {
tokenOrders( orders(
orderBy: timestamp orderBy: createdTimestamp
orderDirection: desc orderDirection: desc
where: { payer: $user, datatokenId: $datatokenAddress } where: { payer: $user, token: $datatokenAddress }
) { ) {
id id
serviceId serviceId
datatokenId { token {
address address
isDatatoken
} }
tx tx
timestamp createdTimestamp
} }
} }
` `

View File

@ -31,7 +31,7 @@ export function getDevelopmentConfig(): Config {
// metadataContractAddress: contractAddresses.development?.Metadata, // metadataContractAddress: contractAddresses.development?.Metadata,
// oceanTokenAddress: contractAddresses.development?.Ocean, // oceanTokenAddress: contractAddresses.development?.Ocean,
// There is no subgraph in barge so we hardcode the Rinkeby one for now // There is no subgraph in barge so we hardcode the Rinkeby one for now
subgraphUri: 'https://subgraph.rinkeby.oceanprotocol.com' subgraphUri: 'https://subgraphv4.rinkeby.oceanprotocol.com'
} as Config } as Config
} }

View File

@ -5,29 +5,26 @@ import { getOceanConfig } from './ocean'
import { import {
AssetsPoolPrice, AssetsPoolPrice,
AssetsPoolPrice_pools as AssetsPoolPricePool AssetsPoolPrice_pools as AssetsPoolPricePool
} from '../@types/apollo/AssetsPoolPrice' } from '../@types/subgraph/AssetsPoolPrice'
import { import {
AssetsFrePrice, AssetsFrePrice,
AssetsFrePrice_fixedRateExchanges as AssetsFrePriceFixedRateExchange AssetsFrePrice_fixedRateExchanges as AssetsFrePriceFixedRateExchange
} from '../@types/apollo/AssetsFrePrice' } from '../@types/subgraph/AssetsFrePrice'
import { import {
AssetsFreePrice, AssetsFreePrice,
AssetsFreePrice_dispensers as AssetFreePriceDispenser AssetsFreePrice_dispensers as AssetFreePriceDispenser
} from '../@types/apollo/AssetsFreePrice' } from '../@types/subgraph/AssetsFreePrice'
import { AssetPreviousOrder } from '../@types/apollo/AssetPreviousOrder' import { AssetPreviousOrder } from '../@types/subgraph/AssetPreviousOrder'
import { import {
HighestLiquidityAssets_pools as HighestLiquidityAssetsPool, HighestLiquidityAssets_pools as HighestLiquidityAssetsPool,
HighestLiquidityAssets as HighestLiquidityGraphAssets HighestLiquidityAssets as HighestLiquidityGraphAssets
} from '../@types/apollo/HighestLiquidityAssets' } from '../@types/subgraph/HighestLiquidityAssets'
import { import {
PoolShares as PoolSharesList, PoolShares as PoolSharesList,
PoolShares_poolShares as PoolShare PoolShares_poolShares as PoolShare
} from '../@types/apollo/PoolShares' } from '../@types/subgraph/PoolShares'
import { OrdersData_tokenOrders as OrdersData } from '../@types/apollo/OrdersData' import { OrdersData_orders as OrdersData } from '../@types/subgraph/OrdersData'
import { import { UserSalesQuery as UsersSalesList } from '../@types/subgraph/UserSalesQuery'
UserSalesQuery_users as UserSales,
UserSalesQuery as UsersSalesList
} from '../@types/apollo/UserSalesQuery'
export interface UserLiquidity { export interface UserLiquidity {
price: string price: string
@ -49,8 +46,8 @@ interface DidAndDatatokenMap {
const FreeQuery = gql` const FreeQuery = gql`
query AssetsFreePrice($datatoken_in: [String!]) { query AssetsFreePrice($datatoken_in: [String!]) {
dispensers(orderBy: id, where: { datatoken_in: $datatoken_in }) { dispensers(orderBy: id, where: { token_in: $datatoken_in }) {
datatoken { token {
id id
address address
} }
@ -60,18 +57,16 @@ const FreeQuery = gql`
const AssetFreeQuery = gql` const AssetFreeQuery = gql`
query AssetFreePrice($datatoken: String) { query AssetFreePrice($datatoken: String) {
dispensers(orderBy: id, where: { datatoken: $datatoken }) { dispensers(orderBy: id, where: { token: $datatoken }) {
active active
owner { owner
id isMinter
}
minterApproved
isTrueMinter
maxTokens maxTokens
maxBalance maxBalance
balance balance
datatoken { token {
id id
isDatatoken
} }
} }
} }
@ -80,9 +75,11 @@ const AssetFreeQuery = gql`
const FreQuery = gql` const FreQuery = gql`
query AssetsFrePrice($datatoken_in: [String!]) { query AssetsFrePrice($datatoken_in: [String!]) {
fixedRateExchanges(orderBy: id, where: { datatoken_in: $datatoken_in }) { fixedRateExchanges(orderBy: id, where: { datatoken_in: $datatoken_in }) {
rate
id id
baseTokenSymbol price
baseToken {
symbol
}
datatoken { datatoken {
id id
address address
@ -95,9 +92,11 @@ const FreQuery = gql`
const AssetFreQuery = gql` const AssetFreQuery = gql`
query AssetFrePrice($datatoken: String) { query AssetFrePrice($datatoken: String) {
fixedRateExchanges(orderBy: id, where: { datatoken: $datatoken }) { fixedRateExchanges(orderBy: id, where: { datatoken: $datatoken }) {
rate
id id
baseTokenSymbol price
baseToken {
symbol
}
datatoken { datatoken {
id id
address address
@ -109,46 +108,50 @@ const AssetFreQuery = gql`
const PoolQuery = gql` const PoolQuery = gql`
query AssetsPoolPrice($datatokenAddress_in: [String!]) { query AssetsPoolPrice($datatokenAddress_in: [String!]) {
pools(where: { datatokenAddress_in: $datatokenAddress_in }) { pools(where: { datatoken_in: $datatokenAddress_in }) {
id id
spotPrice spotPrice
consumePrice datatoken {
datatokenAddress address
datatokenReserve
oceanReserve
tokens(where: { isDatatoken: false }) {
isDatatoken
symbol symbol
} }
baseToken {
address
symbol
}
datatokenLiquidity
baseTokenLiquidity
} }
} }
` `
const AssetPoolPriceQuery = gql` const AssetPoolPriceQuery = gql`
query AssetPoolPrice($datatokenAddress: String) { query AssetPoolPrice($datatokenAddress: String) {
pools(where: { datatokenAddress: $datatokenAddress }) { pools(where: { datatoken: $datatokenAddress }) {
id id
spotPrice spotPrice
consumePrice datatoken {
datatokenAddress address
datatokenReserve
oceanReserve
tokens(where: { isDatatoken: false }) {
symbol symbol
} }
baseToken {
symbol
}
datatokenLiquidity
baseTokenLiquidity
} }
} }
` `
const PreviousOrderQuery = gql` const PreviousOrderQuery = gql`
query AssetPreviousOrder($id: String!, $account: String!) { query AssetPreviousOrder($id: String!, $account: String!) {
tokenOrders( orders(
first: 1 first: 1
where: { datatokenId: $id, payer: $account } where: { token: $id, payer: $account }
orderBy: timestamp orderBy: createdTimestamp
orderDirection: desc orderDirection: desc
) { ) {
timestamp createdTimestamp
tx tx
} }
} }
@ -156,42 +159,46 @@ const PreviousOrderQuery = gql`
const HighestLiquidityAssets = gql` const HighestLiquidityAssets = gql`
query HighestLiquidityAssets { query HighestLiquidityAssets {
pools( pools(
where: { datatokenReserve_gte: 1 } where: { datatokenLiquidity_gte: 1 }
orderBy: oceanReserve orderBy: baseTokenLiquidity
orderDirection: desc orderDirection: desc
first: 15 first: 15
) { ) {
id id
datatokenAddress datatoken {
valueLocked address
oceanReserve }
baseToken {
symbol
}
baseTokenLiquidity
} }
} }
` `
const UserSharesQuery = gql` const UserSharesQuery = gql`
query UserSharesQuery($user: String, $pools: [String!]) { query UserSharesQuery($user: String, $pools: [String!]) {
poolShares(where: { userAddress: $user, poolId_in: $pools }) { poolShares(where: { user: $user, pool_in: $pools }) {
id id
balance shares
userAddress { user {
id id
} }
poolId { pool {
id id
datatokenAddress datatoken {
valueLocked address
tokens { symbol
tokenId {
symbol
}
} }
oceanReserve baseToken {
datatokenReserve address
symbol
}
datatokenLiquidity
baseTokenLiquidity
totalShares totalShares
consumePrice
spotPrice spotPrice
createTime createdTimestamp
} }
} }
} }
@ -199,27 +206,29 @@ const UserSharesQuery = gql`
const userPoolSharesQuery = gql` const userPoolSharesQuery = gql`
query PoolShares($user: String) { query PoolShares($user: String) {
poolShares(where: { userAddress: $user, balance_gt: 0.001 }, first: 1000) { poolShares(where: { user: $user, shares_gt: 0.001 }, first: 1000) {
id id
balance shares
userAddress { user {
id id
} }
poolId { pool {
id id
datatokenAddress datatoken {
valueLocked
tokens {
id id
isDatatoken address
symbol symbol
} }
oceanReserve baseToken {
datatokenReserve id
address
symbol
}
baseTokenLiquidity
datatokenLiquidity
totalShares totalShares
consumePrice
spotPrice spotPrice
createTime createdTimestamp
} }
} }
} }
@ -227,39 +236,47 @@ const userPoolSharesQuery = gql`
const UserTokenOrders = gql` const UserTokenOrders = gql`
query OrdersData($user: String!) { query OrdersData($user: String!) {
tokenOrders( orders(
orderBy: timestamp orderBy: createdTimestamp
orderDirection: desc orderDirection: desc
where: { consumer: $user } where: { consumer: $user }
) { ) {
datatokenId { token {
address address
symbol symbol
isDatatoken
} }
timestamp createdTimestamp
tx tx
} }
} }
` `
// TODO: counting orders might be enough here to get sales for a user
const UserSalesQuery = gql` const UserSalesQuery = gql`
query UserSalesQuery($userSalesId: ID) { query UserSalesQuery($userSalesId: ID) {
users(where: { id: $userSalesId }) { users(where: { id: $userSalesId }) {
id id
nrSales orders(first: 10000) {
id
}
} }
} }
` `
// TODO: figure out some way to get this
const TopSalesQuery = gql` const TopSalesQuery = gql`
query TopSalesQuery { query TopSalesQuery {
users( users(
first: 20 first: 20
orderBy: nrSales orderBy: tokensOwned
orderDirection: desc orderDirection: desc
where: { nrSales_not: 0 } where: { tokenBalancesOwned_not: "0" }
) { ) {
id id
nrSales tokenBalancesOwned {
value
}
} }
} }
` `
@ -329,15 +346,15 @@ export async function getPreviousOrders(
} }
const fetchedPreviousOrders: OperationResult<AssetPreviousOrder> = const fetchedPreviousOrders: OperationResult<AssetPreviousOrder> =
await fetchData(PreviousOrderQuery, variables, null) await fetchData(PreviousOrderQuery, variables, null)
if (fetchedPreviousOrders.data?.tokenOrders?.length === 0) return null if (fetchedPreviousOrders.data?.orders?.length === 0) return null
if (assetTimeout === '0') { if (assetTimeout === '0') {
return fetchedPreviousOrders?.data?.tokenOrders[0]?.tx return fetchedPreviousOrders?.data?.orders[0]?.tx
} else { } else {
const expiry = const expiry =
fetchedPreviousOrders?.data?.tokenOrders[0]?.timestamp * 1000 + fetchedPreviousOrders?.data?.orders[0]?.createdTimestamp * 1000 +
Number(assetTimeout) * 1000 Number(assetTimeout) * 1000
if (Date.now() <= expiry) { if (Date.now() <= expiry) {
return fetchedPreviousOrders?.data?.tokenOrders[0]?.tx return fetchedPreviousOrders?.data?.orders[0]?.tx
} else { } else {
return null return null
} }
@ -353,15 +370,12 @@ function transformPriceToBestPrice(
const price: BestPrice = { const price: BestPrice = {
type: 'dynamic', type: 'dynamic',
address: poolPrice[0]?.id, address: poolPrice[0]?.id,
value: value: poolPrice[0]?.spotPrice,
poolPrice[0]?.consumePrice === '-1' ocean: poolPrice[0]?.baseTokenLiquidity,
? poolPrice[0]?.spotPrice oceanSymbol: poolPrice[0]?.baseToken.symbol,
: poolPrice[0]?.consumePrice, datatoken: poolPrice[0]?.datatokenLiquidity,
ocean: poolPrice[0]?.oceanReserve,
oceanSymbol: poolPrice[0]?.tokens[0]?.symbol,
datatoken: poolPrice[0]?.datatokenReserve,
pools: [poolPrice[0]?.id], pools: [poolPrice[0]?.id],
isConsumable: poolPrice[0]?.consumePrice === '-1' ? 'false' : 'true' isConsumable: poolPrice[0]?.spotPrice === '-1' ? 'false' : 'true'
} }
return price return price
} else if (frePrice?.length > 0) { } else if (frePrice?.length > 0) {
@ -369,10 +383,10 @@ function transformPriceToBestPrice(
// isConsumable: 'true' // isConsumable: 'true'
const price: BestPrice = { const price: BestPrice = {
type: 'fixed', type: 'fixed',
value: frePrice[0]?.rate, value: frePrice[0]?.price,
address: frePrice[0]?.id, address: frePrice[0]?.id,
exchangeId: frePrice[0]?.id, exchangeId: frePrice[0]?.id,
oceanSymbol: frePrice[0]?.baseTokenSymbol, oceanSymbol: frePrice[0]?.baseToken.symbol,
ocean: 0, ocean: 0,
datatoken: 0, datatoken: 0,
pools: [], pools: [],
@ -383,7 +397,7 @@ function transformPriceToBestPrice(
const price: BestPrice = { const price: BestPrice = {
type: 'free', type: 'free',
value: 0, value: 0,
address: freePrice[0]?.datatoken.id, address: freePrice[0]?.token.id,
exchangeId: '', exchangeId: '',
ocean: 0, ocean: 0,
datatoken: 0, datatoken: 0,
@ -488,16 +502,13 @@ export async function getAssetsPriceList(assets: Asset[]): Promise<PriceList> {
const didDTMap: DidAndDatatokenMap = values[3] const didDTMap: DidAndDatatokenMap = values[3]
for (const poolPrice of poolPriceResponse) { for (const poolPrice of poolPriceResponse) {
priceList[didDTMap[poolPrice.datatokenAddress]] = priceList[didDTMap[poolPrice.datatoken.address]] = poolPrice.spotPrice
poolPrice.consumePrice === '-1'
? poolPrice.spotPrice
: poolPrice.consumePrice
} }
for (const frePrice of frePriceResponse) { for (const frePrice of frePriceResponse) {
priceList[didDTMap[frePrice.datatoken?.address]] = frePrice.rate priceList[didDTMap[frePrice.datatoken?.address]] = frePrice.price
} }
for (const freePrice of freePriceResponse) { for (const freePrice of freePriceResponse) {
priceList[didDTMap[freePrice.datatoken?.address]] = '0' priceList[didDTMap[freePrice.token?.address]] = '0'
} }
return priceList return priceList
} }
@ -575,7 +586,7 @@ export async function getAssetsBestPrices(
const frePrice: AssetsFrePriceFixedRateExchange[] = [] const frePrice: AssetsFrePriceFixedRateExchange[] = []
const freePrice: AssetFreePriceDispenser[] = [] const freePrice: AssetFreePriceDispenser[] = []
const pool = poolPriceResponse.find( const pool = poolPriceResponse.find(
(pool: AssetsPoolPricePool) => pool.datatokenAddress === dataToken (pool: AssetsPoolPricePool) => pool.datatoken.address === dataToken
) )
pool && poolPrice.push(pool) pool && poolPrice.push(pool)
const fre = frePriceResponse.find( const fre = frePriceResponse.find(
@ -584,7 +595,7 @@ export async function getAssetsBestPrices(
) )
fre && frePrice.push(fre) fre && frePrice.push(fre)
const free = freePriceResponse.find( const free = freePriceResponse.find(
(free: AssetFreePriceDispenser) => free.datatoken.address === dataToken (free: AssetFreePriceDispenser) => free.token.address === dataToken
) )
free && freePrice.push(free) free && freePrice.push(free)
const bestPrice = transformPriceToBestPrice(frePrice, poolPrice, freePrice) const bestPrice = transformPriceToBestPrice(frePrice, poolPrice, freePrice)
@ -610,22 +621,24 @@ export async function getHighestLiquidityDatatokens(
fetchedPools.data.pools fetchedPools.data.pools
) )
} }
highestLiquidityAssets.sort((a, b) => b.oceanReserve - a.oceanReserve) highestLiquidityAssets.sort(
(a, b) => b.baseTokenLiquidity - a.baseTokenLiquidity
)
for (let i = 0; i < highestLiquidityAssets.length; i++) { for (let i = 0; i < highestLiquidityAssets.length; i++) {
if (!highestLiquidityAssets[i].datatokenAddress) continue if (!highestLiquidityAssets[i].datatoken.address) continue
dtList.push(highestLiquidityAssets[i].datatokenAddress) dtList.push(highestLiquidityAssets[i].datatoken.address)
} }
return dtList return dtList
} }
export function calculateUserLiquidity(poolShare: PoolShare): number { export function calculateUserLiquidity(poolShare: PoolShare): number {
const ocean = const ocean =
(poolShare.balance / poolShare.poolId.totalShares) * (poolShare.shares / poolShare.pool.totalShares) *
poolShare.poolId.oceanReserve poolShare.pool.baseTokenLiquidity
const datatokens = const datatokens =
(poolShare.balance / poolShare.poolId.totalShares) * (poolShare.shares / poolShare.pool.totalShares) *
poolShare.poolId.datatokenReserve poolShare.pool.datatokenLiquidity
const totalLiquidity = ocean + datatokens * poolShare.poolId.spotPrice const totalLiquidity = ocean + datatokens * poolShare.pool.spotPrice
return totalLiquidity return totalLiquidity
} }
@ -648,8 +661,8 @@ export async function getAccountLiquidityInOwnAssets(
for (const result of results) { for (const result of results) {
for (const poolShare of result.poolShares) { for (const poolShare of result.poolShares) {
const userShare = poolShare.balance / poolShare.poolId.totalShares const userShare = poolShare.shares / poolShare.pool.totalShares
const userBalance = userShare * poolShare.poolId.oceanReserve const userBalance = userShare * poolShare.pool.baseTokenLiquidity
totalOceanLiquidity += userBalance totalOceanLiquidity += userBalance
const poolLiquidity = calculateUserLiquidity(poolShare) const poolLiquidity = calculateUserLiquidity(poolShare)
totalLiquidity += poolLiquidity totalLiquidity += poolLiquidity
@ -749,7 +762,7 @@ export async function getTopAssetsPublishers(
if (publishersIndex === -1) { if (publishersIndex === -1) {
const publisher: AccountTeaserVM = { const publisher: AccountTeaserVM = {
address: fetchedUsers.data.users[i].id, address: fetchedUsers.data.users[i].id,
nrSales: fetchedUsers.data.users[i].nrSales nrSales: fetchedUsers.data.users[i].orders.length
} }
publisherSales.push(publisher) publisherSales.push(publisher)
} else { } else {

View File

@ -5,14 +5,22 @@ import ExplorerLink from '@shared/ExplorerLink'
import { formatPrice } from '@shared/Price/PriceUnit' import { formatPrice } from '@shared/Price/PriceUnit'
import styles from './Title.module.css' import styles from './Title.module.css'
async function getTitle(row: PoolTransaction, locale: string) { function getTitle(row: PoolTransaction, locale: string) {
let title = '' let title = ''
switch (row.event) {
case 'swap': { switch (row.type) {
const inToken = row.tokens.filter((x) => x.type === 'in')[0] case 'SWAP': {
const inTokenSymbol = inToken?.poolToken.symbol const { datatoken, baseToken } = row
const outToken = row.tokens.filter((x) => x.type === 'out')[0] const outToken =
const outTokenSymbol = outToken?.poolToken.symbol (datatoken.value < 0 && datatoken.value) ||
(baseToken.value < 0 && baseToken.value)
const outTokenSymbol = outToken?.token.symbol
const inToken =
(datatoken.value > 0 && datatoken.value) ||
(baseToken.value > 0 && baseToken.value)
const inTokenSymbol = inToken?.token.symbol
title += `Swap ${formatPrice( title += `Swap ${formatPrice(
Math.abs(inToken?.value).toString(), Math.abs(inToken?.value).toString(),
locale locale
@ -23,19 +31,11 @@ async function getTitle(row: PoolTransaction, locale: string) {
break break
} }
case 'setup': { case 'SETUP': {
const firstToken = row.tokens.filter( const firstToken = row.baseToken
(x) => const firstTokenSymbol = firstToken?.token.symbol
x.tokenAddress.toLowerCase() !== const secondToken = row.datatoken
row.poolAddress.datatokenAddress.toLowerCase() const secondTokenSymbol = secondToken?.token.symbol
)[0]
const firstTokenSymbol = firstToken?.poolToken.symbol
const secondToken = row.tokens.filter(
(x) =>
x.tokenAddress.toLowerCase() ===
row.poolAddress.datatokenAddress.toLowerCase()
)[0]
const secondTokenSymbol = secondToken?.poolToken.symbol
title += `Create pool with ${formatPrice( title += `Create pool with ${formatPrice(
Math.abs(firstToken?.value).toString(), Math.abs(firstToken?.value).toString(),
locale locale
@ -45,16 +45,16 @@ async function getTitle(row: PoolTransaction, locale: string) {
)}${secondTokenSymbol}` )}${secondTokenSymbol}`
break break
} }
case 'join': case 'JOIN':
case 'exit': { case 'EXIT': {
for (let i = 0; i < row.tokens.length; i++) { const tokenMoved = row.baseToken.value > 0 ? row.baseToken : row.datatoken
const tokenSymbol = row.tokens[i].poolToken.symbol const tokenSymbol = tokenMoved.token.symbol
if (i > 0) title += '\n'
title += `${row.event === 'join' ? 'Add' : 'Remove'} ${formatPrice( title += `${row.type === 'JOIN' ? 'Add' : 'Remove'} ${formatPrice(
Math.abs(row.tokens[i].value).toString(), Math.abs(tokenMoved.value).toString(),
locale locale
)}${tokenSymbol}` )}${tokenSymbol}`
}
break break
} }
} }
@ -69,11 +69,8 @@ export default function Title({ row }: { row: PoolTransaction }): ReactElement {
useEffect(() => { useEffect(() => {
if (!locale || !row) return if (!locale || !row) return
async function init() { const title = getTitle(row, locale)
const title = await getTitle(row, locale) setTitle(title)
setTitle(title)
}
init()
}, [row, locale]) }, [row, locale])
return title ? ( return title ? (

View File

@ -4,7 +4,7 @@ import Table from '@shared/atoms/Table'
import AssetTitle from '@shared/AssetList/AssetListTitle' import AssetTitle from '@shared/AssetList/AssetListTitle'
import { useUserPreferences } from '@context/UserPreferences' import { useUserPreferences } from '@context/UserPreferences'
import { gql } from 'urql' import { gql } from 'urql'
import { TransactionHistory_poolTransactions as TransactionHistoryPoolTransactions } from '../../../@types/apollo/TransactionHistory' import { TransactionHistory_poolTransactions as TransactionHistoryPoolTransactions } from '../../../@types/subgraph/TransactionHistory'
import web3 from 'web3' import web3 from 'web3'
import { fetchDataForMultipleChains } from '@utils/subgraph' import { fetchDataForMultipleChains } from '@utils/subgraph'
import { useSiteMetadata } from '@hooks/useSiteMetadata' import { useSiteMetadata } from '@hooks/useSiteMetadata'
@ -23,23 +23,30 @@ const txHistoryQueryByPool = gql`
poolTransactions( poolTransactions(
orderBy: timestamp orderBy: timestamp
orderDirection: desc orderDirection: desc
where: { userAddress: $user, poolAddress: $pool } where: { user: $user, pool: $pool }
first: 1000 first: 1000
) { ) {
tokens { baseToken {
poolToken { id
id
symbol
}
value value
type token {
tokenAddress symbol
address
}
} }
datatoken {
id
value
token {
symbol
address
}
}
type
tx tx
event
timestamp timestamp
poolAddress { pool {
datatokenAddress id
} }
} }
} }
@ -49,32 +56,35 @@ const txHistoryQuery = gql`
poolTransactions( poolTransactions(
orderBy: timestamp orderBy: timestamp
orderDirection: desc orderDirection: desc
where: { userAddress: $user } where: { user: $user }
first: 1000 first: 1000
) { ) {
tokens { baseToken {
poolToken { id
id
symbol
}
value value
type token {
tokenAddress symbol
address
}
} }
datatoken {
id
value
token {
symbol
address
}
}
type
tx tx
event
timestamp timestamp
poolAddress { pool {
datatokenAddress id
} }
} }
} }
` `
export interface Datatoken {
symbol: string
}
export interface PoolTransaction extends TransactionHistoryPoolTransactions { export interface PoolTransaction extends TransactionHistoryPoolTransactions {
networkId: number networkId: number
ddo: Asset ddo: Asset
@ -170,9 +180,9 @@ export default function PoolTransactions({
const didList: string[] = [] const didList: string[] = []
for (let i = 0; i < data.length; i++) { for (let i = 0; i < data.length; i++) {
const { datatokenAddress } = data[i].poolAddress const { address } = data[i].datatoken.token
const did = web3.utils const did = web3.utils
.toChecksumAddress(datatokenAddress) .toChecksumAddress(address)
.replace('0x', 'did:op:') .replace('0x', 'did:op:')
didList.push(did) didList.push(did)
} }

View File

@ -6,7 +6,7 @@ import { useSiteMetadata } from '@hooks/useSiteMetadata'
import { useAsset } from '@context/Asset' import { useAsset } from '@context/Asset'
import { gql } from 'urql' import { gql } from 'urql'
import { fetchData, getQueryContext } from '@utils/subgraph' import { fetchData, getQueryContext } from '@utils/subgraph'
import { OrdersData } from '../../../@types/apollo/OrdersData' import { OrdersData } from '../../../@types/subgraph/OrdersData'
import BigNumber from 'bignumber.js' import BigNumber from 'bignumber.js'
import { useWeb3 } from '@context/Web3' import { useWeb3 } from '@context/Web3'
import { usePricing } from '@hooks/usePricing' import { usePricing } from '@hooks/usePricing'
@ -20,13 +20,13 @@ import { Asset, FileMetadata } from '@oceanprotocol/lib'
const previousOrderQuery = gql` const previousOrderQuery = gql`
query PreviousOrder($id: String!, $account: String!) { query PreviousOrder($id: String!, $account: String!) {
tokenOrders( orders(
first: 1 first: 1
where: { datatokenId: $id, payer: $account } where: { token: $id, payer: $account }
orderBy: timestamp orderBy: createdTimestamp
orderDirection: desc orderDirection: desc
) { ) {
timestamp createdTimestamp
tx tx
} }
} }
@ -68,6 +68,7 @@ export default function Consume({
useEffect(() => { useEffect(() => {
if (!ddo || !accountId) return if (!ddo || !accountId) return
const context = getQueryContext(ddo.chainId) const context = getQueryContext(ddo.chainId)
const variables = { const variables = {
id: ddo.services[0].datatokenAddress?.toLowerCase(), id: ddo.services[0].datatokenAddress?.toLowerCase(),
@ -82,18 +83,20 @@ export default function Consume({
if ( if (
!data || !data ||
!assetTimeout || !assetTimeout ||
data.tokenOrders.length === 0 || data.orders.length === 0 ||
!accountId || !accountId ||
!isAssetNetwork !isAssetNetwork
) )
return return
const lastOrder = data.tokenOrders[0] const lastOrder = data.orders[0]
if (assetTimeout === '0') { if (assetTimeout === '0') {
setPreviousOrderId(lastOrder.tx) setPreviousOrderId(lastOrder.tx)
setHasPreviousOrder(true) setHasPreviousOrder(true)
} else { } else {
const expiry = new BigNumber(lastOrder.timestamp).plus(assetTimeout) const expiry = new BigNumber(lastOrder.createdTimestamp).plus(
assetTimeout
)
const unixTime = new BigNumber(Math.floor(Date.now() / 1000)) const unixTime = new BigNumber(Math.floor(Date.now() / 1000))
if (unixTime.isLessThan(expiry)) { if (unixTime.isLessThan(expiry)) {
setPreviousOrderId(lastOrder.tx) setPreviousOrderId(lastOrder.tx)

View File

@ -13,6 +13,7 @@ import DebugOutput from '@shared/DebugOutput'
import { useWeb3 } from '@context/Web3' import { useWeb3 } from '@context/Web3'
import { useAsset } from '@context/Asset' import { useAsset } from '@context/Asset'
import content from '../../../../../../content/price.json' import content from '../../../../../../content/price.json'
import { Datatoken } from '@oceanprotocol/lib'
export interface FormAddLiquidity { export interface FormAddLiquidity {
amount: number amount: number
@ -41,7 +42,7 @@ export default function Add({
dtSymbol: string dtSymbol: string
dtAddress: string dtAddress: string
}): ReactElement { }): ReactElement {
const { accountId, balance } = useWeb3() const { accountId, balance, web3 } = useWeb3()
const { isAssetNetwork } = useAsset() const { isAssetNetwork } = useAsset()
const { debug } = useUserPreferences() const { debug } = useUserPreferences()
const [txId, setTxId] = useState<string>() const [txId, setTxId] = useState<string>()
@ -67,13 +68,15 @@ export default function Add({
// Get datatoken balance when datatoken selected // Get datatoken balance when datatoken selected
useEffect(() => { useEffect(() => {
// if (!accountId || !isAssetNetwork || coin === 'OCEAN') return if (!web3 || !accountId || !isAssetNetwork || coin === 'OCEAN') return
// async function getDtBalance() {
// const dtBalance = await ocean.datatokens.balance(dtAddress, accountId) async function getDtBalance() {
// setDtBalance(dtBalance) const datatokenInstance = new Datatoken(web3)
// } const dtBalance = await datatokenInstance.balance(dtAddress, accountId)
// getDtBalance() setDtBalance(dtBalance)
}, [accountId, dtAddress, coin]) }
getDtBalance()
}, [web3, accountId, dtAddress, coin])
// Get maximum amount for either OCEAN or datatoken // Get maximum amount for either OCEAN or datatoken
useEffect(() => { useEffect(() => {

View File

@ -1,5 +1,11 @@
/* eslint-disable camelcase */ /* eslint-disable camelcase */
import React, { ChangeEvent, ReactElement, useEffect, useState } from 'react' import React, {
ChangeEvent,
ReactElement,
useCallback,
useEffect,
useState
} from 'react'
import { Line, defaults } from 'react-chartjs-2' import { Line, defaults } from 'react-chartjs-2'
import { import {
ChartData, ChartData,
@ -17,7 +23,7 @@ import Button from '@shared/atoms/Button'
import { LoggerInstance } from '@oceanprotocol/lib' import { LoggerInstance } from '@oceanprotocol/lib'
import { useAsset } from '@context/Asset' import { useAsset } from '@context/Asset'
import { gql, OperationResult } from 'urql' import { gql, OperationResult } from 'urql'
import { PoolHistory } from '../../../../@types/apollo/PoolHistory' import { PoolHistory } from '../../../../@types/subgraph/PoolHistory'
import { fetchData, getQueryContext } from '@utils/subgraph' import { fetchData, getQueryContext } from '@utils/subgraph'
import styles from './Graph.module.css' import styles from './Graph.module.css'
@ -103,74 +109,49 @@ function getOptions(locale: string, isDarkMode: boolean): ChartOptions {
const graphTypes = ['Liquidity', 'Price'] const graphTypes = ['Liquidity', 'Price']
const poolHistory = gql` const poolHistoryQuery = gql`
query PoolHistory($id: String!, $block: Int) { query PoolHistory($id: String!) {
poolTransactions( poolSnapshots(first: 1000, where: { pool: $id }, orderBy: date) {
first: 1000 date
where: { poolAddress: $id, block_gt: $block }
orderBy: block
) {
block
spotPrice spotPrice
timestamp baseTokenLiquidity
oceanReserve datatokenLiquidity
} }
} }
` `
export default function Graph(): ReactElement { export default function Graph(): ReactElement {
const { locale } = useUserPreferences() const { locale } = useUserPreferences()
const { price, ddo } = useAsset()
const darkMode = useDarkMode(false, darkModeConfig) const darkMode = useDarkMode(false, darkModeConfig)
const [options, setOptions] = useState<ChartOptions>() const [options, setOptions] = useState<ChartOptions>()
const [graphType, setGraphType] = useState<GraphType>('liquidity') const [graphType, setGraphType] = useState<GraphType>('liquidity')
const { price, ddo } = useAsset()
const [lastBlock, setLastBlock] = useState<number>(0)
const [priceHistory, setPriceHistory] = useState([])
const [error, setError] = useState<Error>() const [error, setError] = useState<Error>()
const [liquidityHistory, setLiquidityHistory] = useState([])
const [timestamps, setTimestamps] = useState([])
const [isLoading, setIsLoading] = useState(true) const [isLoading, setIsLoading] = useState(true)
const [dataHistory, setDataHistory] = useState<PoolHistory>() const [dataHistory, setDataHistory] = useState<PoolHistory>()
const [graphData, setGraphData] = useState<ChartData>() const [graphData, setGraphData] = useState<ChartData>()
const [graphFetchInterval, setGraphFetchInterval] = useState<NodeJS.Timeout>() const [graphFetchInterval, setGraphFetchInterval] = useState<NodeJS.Timeout>()
async function getPoolHistory() { const getPoolHistory = useCallback(async () => {
try { try {
const queryContext = getQueryContext(ddo.chainId)
const queryVariables = {
id: price.address.toLowerCase(),
block: lastBlock
}
const queryResult: OperationResult<PoolHistory> = await fetchData( const queryResult: OperationResult<PoolHistory> = await fetchData(
poolHistory, poolHistoryQuery,
queryVariables, { id: price.address.toLowerCase() },
queryContext getQueryContext(ddo.chainId)
) )
setDataHistory(queryResult?.data) setDataHistory(queryResult?.data)
} catch (error) { } catch (error) {
console.error('Error fetchData: ', error.message) console.error('Error fetchData: ', error.message)
setError(error) setError(error)
} }
} }, [ddo?.chainId, price?.address])
function refetchGraph() { const refetchGraph = useCallback(async () => {
if (!graphFetchInterval) { if (graphFetchInterval) return
setGraphFetchInterval(
setInterval(function () {
getPoolHistory()
}, REFETCH_INTERVAL)
)
}
}
useEffect(() => { const newInterval = setInterval(() => getPoolHistory(), REFETCH_INTERVAL)
return () => { setGraphFetchInterval(newInterval)
clearInterval(graphFetchInterval) }, [getPoolHistory, graphFetchInterval])
}
}, [graphFetchInterval])
useEffect(() => { useEffect(() => {
LoggerInstance.log('Fired GraphOptions!') LoggerInstance.log('Fired GraphOptions!')
@ -178,71 +159,51 @@ export default function Graph(): ReactElement {
setOptions(options) setOptions(options)
}, [locale, darkMode.value]) }, [locale, darkMode.value])
useEffect(() => {
getPoolHistory()
}, [lastBlock])
useEffect(() => { useEffect(() => {
async function init() { async function init() {
const data: PoolHistory = dataHistory if (!dataHistory) {
if (!data) {
await getPoolHistory() await getPoolHistory()
return return
} }
LoggerInstance.log('Fired GraphData!') LoggerInstance.log('Fired GraphData!')
const latestTimestamps = [ const latestTimestamps = [
...timestamps, ...dataHistory.poolSnapshots.map((item) => {
...data.poolTransactions.map((item) => { const date = new Date(item.date * 1000)
const date = new Date(item.timestamp * 1000)
return `${date.toLocaleDateString()} ${date.toLocaleTimeString()}` return `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`
}) })
] ]
setTimestamps(latestTimestamps)
const latestLiquidtyHistory = [ const latestLiquidityHistory = [
...liquidityHistory, ...dataHistory.poolSnapshots.map((item) => item.baseTokenLiquidity)
...data.poolTransactions.map((item) => item.oceanReserve)
] ]
setLiquidityHistory(latestLiquidtyHistory)
const latestPriceHistory = [ const latestPriceHistory = [
...priceHistory, ...dataHistory.poolSnapshots.map((item) => item.datatokenLiquidity)
...data.poolTransactions.map((item) => item.spotPrice)
] ]
setPriceHistory(latestPriceHistory) setGraphData({
labels: latestTimestamps.slice(0),
if (data.poolTransactions.length > 0) { datasets: [
const newBlock = {
data.poolTransactions[data.poolTransactions.length - 1].block ...lineStyle,
if (newBlock === lastBlock) return label: 'Liquidity (OCEAN)',
setLastBlock( data:
data.poolTransactions[data.poolTransactions.length - 1].block graphType === 'liquidity'
) ? latestLiquidityHistory.slice(0)
} else { : latestPriceHistory.slice(0),
setGraphData({ borderColor: `#8b98a9`,
labels: latestTimestamps.slice(0), pointBackgroundColor: `#8b98a9`
datasets: [ }
{ ]
...lineStyle, })
label: 'Liquidity (OCEAN)', setIsLoading(false)
data: refetchGraph()
graphType === 'liquidity'
? latestLiquidtyHistory.slice(0)
: latestPriceHistory.slice(0),
borderColor: `#8b98a9`,
pointBackgroundColor: `#8b98a9`
}
]
})
setIsLoading(false)
refetchGraph()
}
} }
init() init()
}, [dataHistory, graphType])
return () => clearInterval(graphFetchInterval)
}, [dataHistory, graphType, graphFetchInterval, getPoolHistory, refetchGraph])
function handleGraphTypeSwitch(e: ChangeEvent<HTMLButtonElement>) { function handleGraphTypeSwitch(e: ChangeEvent<HTMLButtonElement>) {
e.preventDefault() e.preventDefault()

View File

@ -1,4 +1,4 @@
import React, { ReactElement, useEffect, useState } from 'react' import React, { ReactElement, useCallback, useEffect, useState } from 'react'
import { LoggerInstance } from '@oceanprotocol/lib' import { LoggerInstance } from '@oceanprotocol/lib'
import styles from './index.module.css' import styles from './index.module.css'
import stylesActions from './Actions.module.css' import stylesActions from './Actions.module.css'
@ -14,7 +14,7 @@ import AssetActionHistoryTable from '../AssetActionHistoryTable'
import Graph from './Graph' import Graph from './Graph'
import { useAsset } from '@context/Asset' import { useAsset } from '@context/Asset'
import { gql, OperationResult } from 'urql' import { gql, OperationResult } from 'urql'
import { PoolLiquidity } from '../../../../@types/apollo/PoolLiquidity' import { PoolLiquidity } from '../../../../@types/subgraph/PoolLiquidity'
import { useWeb3 } from '@context/Web3' import { useWeb3 } from '@context/Web3'
import PoolTransactions from '@shared/PoolTransactions' import PoolTransactions from '@shared/PoolTransactions'
import { fetchData, getQueryContext } from '@utils/subgraph' import { fetchData, getQueryContext } from '@utils/subgraph'
@ -22,39 +22,42 @@ import { isValidNumber } from '@utils/numbers'
import Decimal from 'decimal.js' import Decimal from 'decimal.js'
import content from '../../../../../content/price.json' import content from '../../../../../content/price.json'
const REFETCH_INTERVAL = 5000
Decimal.set({ toExpNeg: -18, precision: 18, rounding: 1 }) Decimal.set({ toExpNeg: -18, precision: 18, rounding: 1 })
const poolLiquidityQuery = gql` const poolLiquidityQuery = gql`
query PoolLiquidity($id: ID!, $shareId: ID) { query PoolLiquidity($pool: ID!, $owner: ID) {
pool(id: $id) { pool(id: $pool) {
id id
totalShares totalShares
swapFee poolFee
opfFee
marketFee
spotPrice spotPrice
tokens { baseToken {
address address
symbol symbol
isDatatoken
balance
denormWeight
} }
shares(where: { id: $shareId }) { baseTokenWeight
id baseTokenLiquidity
balance datatoken {
address
symbol
}
datatokenWeight
datatokenLiquidity
shares(where: { user: $owner }) {
shares
} }
} }
} }
` `
const userPoolShareQuery = gql` const userPoolShareQuery = gql`
query PoolShare($id: ID!, $shareId: ID) { query PoolShare($pool: ID!, $user: ID) {
pool(id: $id) { pool(id: $pool) {
id id
shares(where: { id: $shareId }) { shares(where: { user: $user }) {
id shares
balance
} }
} }
} }
@ -99,45 +102,40 @@ export default function Pool(): ReactElement {
// the purpose of the value is just to trigger the effect // the purpose of the value is just to trigger the effect
const [refreshPool, setRefreshPool] = useState(false) const [refreshPool, setRefreshPool] = useState(false)
async function getPoolLiquidity() { const getPoolLiquidity = useCallback(async () => {
const queryContext = getQueryContext(ddo.chainId) if (!ddo?.chainId || !price?.address || !owner) return
const queryVariables = {
id: price.address.toLowerCase(),
shareId: `${price.address.toLowerCase()}-${ddo.nft.owner.toLowerCase()}`
}
const queryVariables = {
pool: price.address.toLowerCase(),
owner: owner.toLowerCase()
}
const queryResult: OperationResult<PoolLiquidity> = await fetchData( const queryResult: OperationResult<PoolLiquidity> = await fetchData(
poolLiquidityQuery, poolLiquidityQuery,
queryVariables, queryVariables,
queryContext getQueryContext(ddo.chainId)
) )
setdataLiquidity(queryResult?.data) setdataLiquidity(queryResult?.data)
} }, [ddo?.chainId, price?.address, owner])
async function getUserPoolShareBalance() { async function getUserPoolShareBalance() {
const queryContext = getQueryContext(ddo.chainId)
const queryVariables = { const queryVariables = {
id: price.address.toLowerCase(), pool: price.address.toLowerCase(),
shareId: `${price.address.toLowerCase()}-${accountId.toLowerCase()}` user: accountId.toLowerCase()
} }
const queryResult: OperationResult<PoolLiquidity> = await fetchData( const queryResult: OperationResult<PoolLiquidity> = await fetchData(
userPoolShareQuery, userPoolShareQuery,
queryVariables, queryVariables,
queryContext getQueryContext(ddo.chainId)
) )
return queryResult?.data.pool.shares[0]?.balance return queryResult?.data.pool.shares[0]?.shares
} }
function refetchLiquidity() { const refetchLiquidity = useCallback(() => {
if (!liquidityFetchInterval) { if (liquidityFetchInterval) return
setLiquidityFetchInterval(
setInterval(function () { const newInterval = setInterval(() => getPoolLiquidity(), refreshInterval)
getPoolLiquidity() setLiquidityFetchInterval(newInterval)
}, REFETCH_INTERVAL) }, [liquidityFetchInterval, getPoolLiquidity, refreshInterval])
)
}
}
useEffect(() => { useEffect(() => {
return () => { return () => {
@ -147,52 +145,44 @@ export default function Pool(): ReactElement {
useEffect(() => { useEffect(() => {
async function init() { async function init() {
if (!dataLiquidity || !dataLiquidity.pool) { if (!dataLiquidity?.pool) {
await getPoolLiquidity() await getPoolLiquidity()
return return
} }
// Set symbols // Set symbols
dataLiquidity.pool.tokens.forEach((token) => { setOceanSymbol(dataLiquidity.pool.baseToken.symbol)
token.isDatatoken setDtSymbol(dataLiquidity.pool.datatoken.symbol)
? setDtSymbol(token.symbol)
: setOceanSymbol(token.symbol)
})
// Total pool shares // Total pool shares
const totalPoolTokens = dataLiquidity.pool.totalShares const totalPoolTokens = dataLiquidity.pool.totalShares
setTotalPoolTokens(totalPoolTokens) setTotalPoolTokens(totalPoolTokens)
// Get swap fee // Get poolFee
// swapFee is tricky: to get 0.1% you need to convert from 0.001 // poolFee is tricky: to get 0.1% you need to convert from 0.001
const swapFee = isValidNumber(dataLiquidity.pool.swapFee) const swapFee = isValidNumber(dataLiquidity.pool.poolFee)
? new Decimal(dataLiquidity.pool.swapFee).mul(100).toString() ? new Decimal(dataLiquidity.pool.poolFee).mul(100).toString()
: '0' : '0'
setSwapFee(swapFee) setSwapFee(swapFee)
// Get weights // Get weights
const weightDt = dataLiquidity.pool.tokens.filter( function getWeight(weight: string) {
(token: any) => return isValidNumber(weight)
token.address === ddo.services[0].datatokenAddress.toLowerCase() ? new Decimal(weight).mul(10).toString()
)[0].denormWeight : '0'
}
const weightDtDecimal = isValidNumber(weightDt) const weightDt = dataLiquidity.pool.datatokenWeight
? new Decimal(weightDt).mul(10).toString() const weightDtDecimal = getWeight(weightDt)
: '0'
setWeightDt(weightDtDecimal) setWeightDt(weightDtDecimal)
const weightOceanDecimal = isValidNumber(weightDt) const weightOcean = dataLiquidity.pool.baseTokenWeight
? new Decimal(100).minus(new Decimal(weightDt).mul(10)).toString() const weightOceanDecimal = getWeight(weightOcean)
: '0'
setWeightOcean(weightOceanDecimal) setWeightOcean(weightOceanDecimal)
// //
// Get everything the creator put into the pool // Get everything the creator put into the pool
// //
const creatorPoolTokens = dataLiquidity.pool.shares[0]?.shares
const creatorPoolTokens = dataLiquidity.pool.shares[0].balance
setCreatorPoolTokens(creatorPoolTokens) setCreatorPoolTokens(creatorPoolTokens)
const creatorOceanBalance = const creatorOceanBalance =
@ -250,7 +240,13 @@ export default function Pool(): ReactElement {
refetchLiquidity() refetchLiquidity()
} }
init() init()
}, [dataLiquidity, ddo, price.datatoken, price.ocean, price?.value]) }, [
dataLiquidity,
price?.datatoken,
price?.ocean,
getPoolLiquidity,
refetchLiquidity
])
useEffect(() => { useEffect(() => {
setIsRemoveDisabled(isInPurgatory && owner === accountId) setIsRemoveDisabled(isInPurgatory && owner === accountId)
@ -258,6 +254,7 @@ export default function Pool(): ReactElement {
useEffect(() => { useEffect(() => {
if (!dataLiquidity) return if (!dataLiquidity) return
const poolShare = const poolShare =
isValidNumber(poolTokens) && isValidNumber(poolTokens) &&
isValidNumber(totalPoolTokens) && isValidNumber(totalPoolTokens) &&
@ -294,10 +291,11 @@ export default function Pool(): ReactElement {
: new Decimal(0) : new Decimal(0)
setTotalLiquidityInOcean(totalLiquidityInOcean) setTotalLiquidityInOcean(totalLiquidityInOcean)
}, [userLiquidity, price, poolTokens, totalPoolTokens]) }, [dataLiquidity, userLiquidity, price, poolTokens, totalPoolTokens])
useEffect(() => { useEffect(() => {
if (!accountId || !price) return if (!accountId || !price) return
async function init() { async function init() {
try { try {
// //

View File

@ -5,11 +5,12 @@ import { useWeb3 } from '@context/Web3'
import { isValidNumber } from '@utils/numbers' import { isValidNumber } from '@utils/numbers'
import Decimal from 'decimal.js' import Decimal from 'decimal.js'
import { Datatoken } from '@oceanprotocol/lib'
Decimal.set({ toExpNeg: -18, precision: 18, rounding: 1 }) Decimal.set({ toExpNeg: -18, precision: 18, rounding: 1 })
export default function Trade(): ReactElement { export default function Trade(): ReactElement {
const { accountId, balance } = useWeb3() const { accountId, balance, web3 } = useWeb3()
const { isAssetNetwork } = useAsset() const { isAssetNetwork } = useAsset()
const [tokenBalance, setTokenBalance] = useState<PoolBalance>() const [tokenBalance, setTokenBalance] = useState<PoolBalance>()
const { price, ddo } = useAsset() const { price, ddo } = useAsset()
@ -19,6 +20,7 @@ export default function Trade(): ReactElement {
// Get datatoken balance, and combine with OCEAN balance from hooks into one object // Get datatoken balance, and combine with OCEAN balance from hooks into one object
useEffect(() => { useEffect(() => {
if ( if (
!web3 ||
!accountId || !accountId ||
!isAssetNetwork || !isAssetNetwork ||
!balance?.ocean || !balance?.ocean ||
@ -28,17 +30,18 @@ export default function Trade(): ReactElement {
return return
async function getTokenBalance() { async function getTokenBalance() {
// const dtBalance = await ocean.datatokens.balance( const datatokenInstance = new Datatoken(web3)
// ddo.services[0].datatokenAddress, const dtBalance = await datatokenInstance.balance(
// accountId ddo.services[0].datatokenAddress,
// ) accountId
// setTokenBalance({ )
// ocean: new Decimal(balance.ocean).toString(), setTokenBalance({
// datatoken: new Decimal(dtBalance).toString() ocean: new Decimal(balance.ocean).toString(),
// }) datatoken: new Decimal(dtBalance).toString()
})
} }
getTokenBalance() getTokenBalance()
}, [balance.ocean, accountId, ddo, isAssetNetwork]) }, [web3, balance.ocean, accountId, ddo, isAssetNetwork])
// Get maximum amount for either OCEAN or datatoken // Get maximum amount for either OCEAN or datatoken
useEffect(() => { useEffect(() => {

View File

@ -1,7 +1,12 @@
import React, { ReactElement, useState, useEffect } from 'react' import React, { ReactElement, useState, useEffect } from 'react'
import Compute from './Compute' import Compute from './Compute'
import Consume from './Consume' import Consume from './Consume'
import { Asset, FileMetadata, LoggerInstance } from '@oceanprotocol/lib' import {
Asset,
FileMetadata,
LoggerInstance,
Datatoken
} from '@oceanprotocol/lib'
import Tabs, { TabsItem } from '@shared/atoms/Tabs' import Tabs, { TabsItem } from '@shared/atoms/Tabs'
import { compareAsBN } from '@utils/numbers' import { compareAsBN } from '@utils/numbers'
import Pool from './Pool' import Pool from './Pool'
@ -24,8 +29,13 @@ export default function AssetActions({
ddo: Asset ddo: Asset
price: BestPrice price: BestPrice
}): ReactElement { }): ReactElement {
const { accountId, balance } = useWeb3() const { accountId, balance, web3 } = useWeb3()
const { isAssetNetwork } = useAsset() const { isAssetNetwork } = useAsset()
// TODO: using this for the publish preview works fine, but produces a console warning
// on asset details page as there is no formik context there:
// Warning: Formik context is undefined, please verify you are calling useFormikContext()
// as child of a <Formik> component.
const formikState = useFormikContext<FormPublishData>() const formikState = useFormikContext<FormPublishData>()
const [isBalanceSufficient, setIsBalanceSufficient] = useState<boolean>() const [isBalanceSufficient, setIsBalanceSufficient] = useState<boolean>()
@ -82,20 +92,22 @@ export default function AssetActions({
// Get and set user DT balance // Get and set user DT balance
useEffect(() => { useEffect(() => {
if (!accountId || !isAssetNetwork) return if (!web3 || !accountId || !isAssetNetwork) return
async function init() { async function init() {
try { try {
// const dtBalance = await ocean.datatokens.balance( const datatokenInstance = new Datatoken(web3)
// ddo.services[0].datatokenAddress, const dtBalance = await datatokenInstance.balance(
// accountId ddo.services[0].datatokenAddress,
// ) accountId
// setDtBalance(dtBalance) )
setDtBalance(dtBalance)
} catch (e) { } catch (e) {
LoggerInstance.error(e.message) LoggerInstance.error(e.message)
} }
} }
init() init()
}, [accountId, ddo, isAssetNetwork]) }, [web3, accountId, ddo, isAssetNetwork])
// Check user balance against price // Check user balance against price
useEffect(() => { useEffect(() => {

View File

@ -3,18 +3,20 @@ import { useAsset } from '@context/Asset'
import ExplorerLink from '@shared/ExplorerLink' import ExplorerLink from '@shared/ExplorerLink'
import Time from '@shared/atoms/Time' import Time from '@shared/atoms/Time'
import { gql, OperationContext, useQuery } from 'urql' import { gql, OperationContext, useQuery } from 'urql'
import { ReceiptData_datatokens_updates as ReceiptData } from '../../../@types/apollo/ReceiptData' import { ReceiptData_nftUpdates as ReceiptData } from '../../../@types/subgraph/ReceiptData'
import { getQueryContext } from '@utils/subgraph' import { getQueryContext } from '@utils/subgraph'
import styles from './EditHistory.module.css' import styles from './EditHistory.module.css'
const getReceipts = gql` const getReceipts = gql`
query ReceiptData($address: ID!) { query ReceiptData($address: ID!) {
datatokens(where: { id: $address }) { nftUpdates(
updates(orderBy: timestamp, orderDirection: desc) { where: { id: $address }
id orderBy: timestamp
tx orderDirection: desc
timestamp ) {
} id
tx
timestamp
} }
} }
` `
@ -50,13 +52,13 @@ export default function EditHistory(): ReactElement {
const [creationTx, setCreationTx] = useState<string>() const [creationTx, setCreationTx] = useState<string>()
useEffect(() => { useEffect(() => {
if (!data || data.datatokens.length === 0) return if (!data || data.nftUpdates.length === 0) return
const receiptCollectionLength = data.datatokens[0].updates.length const receiptCollectionLength = data.nftUpdates.length
const creationData = data.datatokens[0].updates[receiptCollectionLength - 1] const creationData = data.nftUpdates[receiptCollectionLength - 1]
setCreationTx(creationData.tx) setCreationTx(creationData.tx)
const receiptCollection = [...data.datatokens[0].updates] const receiptCollection = [...data.nftUpdates]
receiptCollection.splice(-1, 1) receiptCollection.splice(-1, 1)
setReceipts(receiptCollection) setReceipts(receiptCollection)

View File

@ -11,13 +11,23 @@ import useNetworkMetadata, {
} from '@hooks/useNetworkMetadata' } from '@hooks/useNetworkMetadata'
import { LoggerInstance } from '@oceanprotocol/lib' import { LoggerInstance } from '@oceanprotocol/lib'
import styles from './MarketStats.module.css' import styles from './MarketStats.module.css'
import { FooterStatsValues_globalStats_totalLiquidity_token as LiquidityToken } from 'src/@types/subgraph/FooterStatsValues'
const getTotalPoolsValues = gql` const getGlobalStatsValues = gql`
query PoolsData { query FooterStatsValues {
poolFactories { globalStats {
totalValueLocked poolCount
totalOceanLiquidity nftCount
finalizedPoolCount datatokenCount
orderCount
totalLiquidity {
token {
id
name
symbol
}
value
}
} }
} }
` `
@ -109,7 +119,7 @@ export default function MarketStats(): ReactElement {
setMainChainIds(mainChainIdsList) setMainChainIds(mainChainIdsList)
let newTotalValueLockedSum = 0 let newTotalValueLockedSum = 0
let newTotalOceanLiquiditySum = 0 const newTotalOceanLiquiditySum = 0
let newPoolCountSum = 0 let newPoolCountSum = 0
for (const chainId of mainChainIdsList) { for (const chainId of mainChainIdsList) {
@ -121,28 +131,36 @@ export default function MarketStats(): ReactElement {
} }
try { try {
const response = await fetchData(getTotalPoolsValues, null, context) const response = await fetchData(getGlobalStatsValues, null, context)
if (!response) continue if (!response) continue
const { totalValueLocked, totalOceanLiquidity, finalizedPoolCount } = const {
response?.data?.poolFactories[0] poolCount,
nftCount,
datatokenCount,
orderCount,
totalLiquidity
} = response?.data?.globalStats[0]
await setTotalValueLocked((prevState) => ({ await setTotalValueLocked((prevState) => ({
...prevState, ...prevState,
[chainId]: totalValueLocked [chainId]: totalLiquidity.value
})) }))
// TODO: how to get total OCEAN liquidity? Does this work?
await setTotalOceanLiquidity((prevState) => ({ await setTotalOceanLiquidity((prevState) => ({
...prevState, ...prevState,
[chainId]: totalOceanLiquidity [chainId]: totalLiquidity.filter(
(token: LiquidityToken) => token.symbol === 'OCEAN'
)[0]
})) }))
await setPoolCount((prevState) => ({ await setPoolCount((prevState) => ({
...prevState, ...prevState,
[chainId]: finalizedPoolCount [chainId]: poolCount
})) }))
newTotalValueLockedSum += parseInt(totalValueLocked) newTotalValueLockedSum += parseInt(totalLiquidity.value)
newTotalOceanLiquiditySum += parseInt(totalOceanLiquidity) // newTotalOceanLiquiditySum += parseInt(totalOceanLiquidity.value)
newPoolCountSum += parseInt(finalizedPoolCount) newPoolCountSum += parseInt(poolCount)
} catch (error) { } catch (error) {
LoggerInstance.error('Error fetchData: ', error.message) LoggerInstance.error('Error fetchData: ', error.message)
} }

View File

@ -11,7 +11,7 @@ import Conversion from '@shared/Price/Conversion'
import NumberUnit from './NumberUnit' import NumberUnit from './NumberUnit'
import styles from './Stats.module.css' import styles from './Stats.module.css'
import { useProfile } from '@context/Profile' import { useProfile } from '@context/Profile'
import { PoolShares_poolShares as PoolShare } from '../../../@types/apollo/PoolShares' import { PoolShares_poolShares as PoolShare } from '../../../@types/subgraph/PoolShares'
async function getPoolSharesLiquidity( async function getPoolSharesLiquidity(
poolShares: PoolShare[] poolShares: PoolShare[]

View File

@ -3,10 +3,7 @@ import Table from '@shared/atoms/Table'
import Conversion from '@shared/Price/Conversion' import Conversion from '@shared/Price/Conversion'
import styles from './PoolShares.module.css' import styles from './PoolShares.module.css'
import AssetTitle from '@shared/AssetList/AssetListTitle' import AssetTitle from '@shared/AssetList/AssetListTitle'
import { import { PoolShares_poolShares as PoolShare } from '../../../@types/subgraph/PoolShares'
PoolShares_poolShares as PoolShare,
PoolShares_poolShares_poolId_tokens as PoolSharePoolIdTokens
} from '../../../@types/apollo/PoolShares'
import web3 from 'web3' import web3 from 'web3'
import Token from '../../Asset/AssetActions/Pool/Token' import Token from '../../Asset/AssetActions/Pool/Token'
import { calculateUserLiquidity } from '@utils/subgraph' import { calculateUserLiquidity } from '@utils/subgraph'
@ -33,46 +30,33 @@ interface AssetPoolShare {
ddo: Asset ddo: Asset
} }
function findTokenByType(tokens: PoolSharePoolIdTokens[], type: string) {
const { symbol } = tokens.find((token) =>
type === 'datatoken'
? token.isDatatoken === true
: token.isDatatoken === false
)
return symbol
}
function Symbol({ tokens }: { tokens: PoolSharePoolIdTokens[] }) {
return <>{findTokenByType(tokens, 'datatoken')}</>
}
function Liquidity({ row, type }: { row: AssetPoolShare; type: string }) { function Liquidity({ row, type }: { row: AssetPoolShare; type: string }) {
let price = `` let price = ``
let oceanTokenBalance = '' let oceanTokenBalance = ''
let dataTokenBalance = '' let dataTokenBalance = ''
if (type === 'user') { if (type === 'user') {
price = `${row.userLiquidity}` price = `${row.userLiquidity}`
const userShare = row.poolShare.balance / row.poolShare.poolId.totalShares const userShare = row.poolShare.shares / row.poolShare.pool.totalShares
oceanTokenBalance = ( oceanTokenBalance = (
userShare * row.poolShare.poolId.oceanReserve userShare * row.poolShare.pool.baseTokenLiquidity
).toString() ).toString()
dataTokenBalance = ( dataTokenBalance = (
userShare * row.poolShare.poolId.datatokenReserve userShare * row.poolShare.pool.datatokenLiquidity
).toString() ).toString()
} }
if (type === 'pool') { if (type === 'pool') {
price = price =
isValidNumber(row.poolShare.poolId.oceanReserve) && isValidNumber(row.poolShare.pool.baseTokenLiquidity) &&
isValidNumber(row.poolShare.poolId.datatokenReserve) && isValidNumber(row.poolShare.pool.datatokenLiquidity) &&
isValidNumber(row.poolShare.poolId.spotPrice) isValidNumber(row.poolShare.pool.spotPrice)
? new Decimal(row.poolShare.poolId.datatokenReserve) ? new Decimal(row.poolShare.pool.datatokenLiquidity)
.mul(new Decimal(row.poolShare.poolId.spotPrice)) .mul(new Decimal(row.poolShare.pool.spotPrice))
.plus(row.poolShare.poolId.oceanReserve) .plus(row.poolShare.pool.baseTokenLiquidity)
.toString() .toString()
: '0' : '0'
oceanTokenBalance = row.poolShare.poolId.oceanReserve.toString() oceanTokenBalance = row.poolShare.pool.baseTokenLiquidity.toString()
dataTokenBalance = row.poolShare.poolId.datatokenReserve.toString() dataTokenBalance = row.poolShare.pool.datatokenLiquidity.toString()
} }
return ( return (
<div className={styles.userLiquidity}> <div className={styles.userLiquidity}>
@ -82,12 +66,12 @@ function Liquidity({ row, type }: { row: AssetPoolShare; type: string }) {
hideApproximateSymbol hideApproximateSymbol
/> />
<Token <Token
symbol={findTokenByType(row.poolShare.poolId.tokens, 'ocean')} symbol={row.poolShare.pool.baseToken.symbol}
balance={oceanTokenBalance} balance={oceanTokenBalance}
noIcon noIcon
/> />
<Token <Token
symbol={findTokenByType(row.poolShare.poolId.tokens, 'datatoken')} symbol={row.poolShare.pool.datatoken.symbol}
balance={dataTokenBalance} balance={dataTokenBalance}
noIcon noIcon
/> />
@ -112,7 +96,7 @@ const columns = [
{ {
name: 'Datatoken', name: 'Datatoken',
selector: function getSymbol(row: AssetPoolShare) { selector: function getSymbol(row: AssetPoolShare) {
return <Symbol tokens={row.poolShare.poolId.tokens} /> return <>{row.poolShare.pool.datatoken.symbol}</>
} }
}, },
{ {
@ -143,7 +127,7 @@ async function getPoolSharesAssets(
for (let i = 0; i < data.length; i++) { for (let i = 0; i < data.length; i++) {
const did = web3.utils const did = web3.utils
.toChecksumAddress(data[i].poolId.datatokenAddress) .toChecksumAddress(data[i].pool.datatoken.address)
.replace('0x', 'did:op:') .replace('0x', 'did:op:')
didList.push(did) didList.push(did)
} }
@ -155,7 +139,7 @@ async function getPoolSharesAssets(
poolShare: data[i], poolShare: data[i],
userLiquidity: userLiquidity, userLiquidity: userLiquidity,
networkId: ddoList[i].chainId, networkId: ddoList[i].chainId,
createTime: data[i].poolId.createTime, createTime: data[i].pool.createdTimestamp,
ddo: ddoList[i] ddo: ddoList[i]
}) })
} }