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
repo-metadata.json
networks-metadata.json
src/@types/apollo
src/@types/subgraph
graphql.schema.json
src/@types/graph.types.ts
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/",
"pregenerate": "bash scripts/pregenerate.sh",
"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 .",
"format": "prettier --ignore-path .gitignore './**/*.{css,yml,js,ts,tsx,json}' --write",
"type-check": "tsc --noEmit",
"deploy:s3": "bash scripts/deploy-s3.sh",
"postinstall": "husky install",
"codegen:apollo": "apollo client:codegen --target typescript --tsFileExtension=d.ts --outputFlat src/@types/apollo/",
"codegen:graphql": "graphql-codegen --config codegen.yml"
"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/"
},
"dependencies": {
"@coingecko/cryptoformat": "^0.4.4",
@ -75,11 +73,6 @@
"yup": "^0.32.11"
},
"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",
"@types/chart.js": "^2.9.35",
"@types/d3": "^7.1.0",

View File

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

View File

@ -13,7 +13,7 @@ import {
getUserTokenOrders
} from '@utils/subgraph'
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 { getDownloadAssets, getPublishedAssets } from '@utils/aquarius'
import { useSiteMetadata } from '@hooks/useSiteMetadata'
@ -226,7 +226,7 @@ function ProfileProvider({
for (let i = 0; i < tokenOrders?.length; i++) {
const did = web3.utils
.toChecksumAddress(tokenOrders[i].datatokenId.address)
.toChecksumAddress(tokenOrders[i].token.address)
.replace('0x', 'did:op:')
didList.push(did)
}

View File

@ -7,10 +7,10 @@ import { getOceanConfig } from '@utils/ocean'
const blockDifferenceThreshold = 30
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"}'
const graphQuery =
'{"query":" query Meta { _meta { block { hash number } deployment hasIndexingErrors } }","variables":{},"operationName":"Meta"}'
const graphQueryBody =
'{"query": "query Meta { _meta { block { hash number } deployment hasIndexingErrors } }", "variables": {},"operationName":"Meta"}'
export interface UseGraphSyncStatus {
isGraphSynced: boolean
@ -34,7 +34,7 @@ async function getBlockHead(config: Config) {
if (!config) return
// for ETH main, get block from graph fetch
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)
}
@ -47,9 +47,9 @@ async function getBlockHead(config: Config) {
async function getBlockSubgraph(subgraphUri: string) {
const response: any = await fetchGraph(
`${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
}

View File

@ -6,7 +6,7 @@ import {
import { AssetSelectionAsset } from '@shared/FormFields/AssetSelection'
import { PriceList, getAssetsPriceList } from './subgraph'
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 {
SortDirectionOptions,
@ -348,16 +348,16 @@ export async function getDownloadAssets(
const downloadedAssets: DownloadedAsset[] = result.results
.map((ddo) => {
const order = tokenOrders.find(
({ datatokenId }) =>
datatokenId?.address.toLowerCase() ===
({ token }) =>
token?.address.toLowerCase() ===
ddo.services[0].datatokenAddress.toLowerCase()
)
return {
ddo,
networkId: ddo.chainId,
dtSymbol: order?.datatokenId?.symbol,
timestamp: order?.timestamp
dtSymbol: order?.token?.symbol,
timestamp: order?.createdTimestamp
}
})
.sort((a, b) => b.timestamp - a.timestamp)

View File

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

View File

@ -31,7 +31,7 @@ export function getDevelopmentConfig(): Config {
// metadataContractAddress: contractAddresses.development?.Metadata,
// oceanTokenAddress: contractAddresses.development?.Ocean,
// 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
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,5 +1,11 @@
/* 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 {
ChartData,
@ -17,7 +23,7 @@ import Button from '@shared/atoms/Button'
import { LoggerInstance } from '@oceanprotocol/lib'
import { useAsset } from '@context/Asset'
import { gql, OperationResult } from 'urql'
import { PoolHistory } from '../../../../@types/apollo/PoolHistory'
import { PoolHistory } from '../../../../@types/subgraph/PoolHistory'
import { fetchData, getQueryContext } from '@utils/subgraph'
import styles from './Graph.module.css'
@ -103,74 +109,49 @@ function getOptions(locale: string, isDarkMode: boolean): ChartOptions {
const graphTypes = ['Liquidity', 'Price']
const poolHistory = gql`
query PoolHistory($id: String!, $block: Int) {
poolTransactions(
first: 1000
where: { poolAddress: $id, block_gt: $block }
orderBy: block
) {
block
const poolHistoryQuery = gql`
query PoolHistory($id: String!) {
poolSnapshots(first: 1000, where: { pool: $id }, orderBy: date) {
date
spotPrice
timestamp
oceanReserve
baseTokenLiquidity
datatokenLiquidity
}
}
`
export default function Graph(): ReactElement {
const { locale } = useUserPreferences()
const { price, ddo } = useAsset()
const darkMode = useDarkMode(false, darkModeConfig)
const [options, setOptions] = useState<ChartOptions>()
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 [liquidityHistory, setLiquidityHistory] = useState([])
const [timestamps, setTimestamps] = useState([])
const [isLoading, setIsLoading] = useState(true)
const [dataHistory, setDataHistory] = useState<PoolHistory>()
const [graphData, setGraphData] = useState<ChartData>()
const [graphFetchInterval, setGraphFetchInterval] = useState<NodeJS.Timeout>()
async function getPoolHistory() {
const getPoolHistory = useCallback(async () => {
try {
const queryContext = getQueryContext(ddo.chainId)
const queryVariables = {
id: price.address.toLowerCase(),
block: lastBlock
}
const queryResult: OperationResult<PoolHistory> = await fetchData(
poolHistory,
queryVariables,
queryContext
poolHistoryQuery,
{ id: price.address.toLowerCase() },
getQueryContext(ddo.chainId)
)
setDataHistory(queryResult?.data)
} catch (error) {
console.error('Error fetchData: ', error.message)
setError(error)
}
}
}, [ddo?.chainId, price?.address])
function refetchGraph() {
if (!graphFetchInterval) {
setGraphFetchInterval(
setInterval(function () {
getPoolHistory()
}, REFETCH_INTERVAL)
)
}
}
const refetchGraph = useCallback(async () => {
if (graphFetchInterval) return
useEffect(() => {
return () => {
clearInterval(graphFetchInterval)
}
}, [graphFetchInterval])
const newInterval = setInterval(() => getPoolHistory(), REFETCH_INTERVAL)
setGraphFetchInterval(newInterval)
}, [getPoolHistory, graphFetchInterval])
useEffect(() => {
LoggerInstance.log('Fired GraphOptions!')
@ -178,71 +159,51 @@ export default function Graph(): ReactElement {
setOptions(options)
}, [locale, darkMode.value])
useEffect(() => {
getPoolHistory()
}, [lastBlock])
useEffect(() => {
async function init() {
const data: PoolHistory = dataHistory
if (!data) {
if (!dataHistory) {
await getPoolHistory()
return
}
LoggerInstance.log('Fired GraphData!')
const latestTimestamps = [
...timestamps,
...data.poolTransactions.map((item) => {
const date = new Date(item.timestamp * 1000)
...dataHistory.poolSnapshots.map((item) => {
const date = new Date(item.date * 1000)
return `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`
})
]
setTimestamps(latestTimestamps)
const latestLiquidtyHistory = [
...liquidityHistory,
...data.poolTransactions.map((item) => item.oceanReserve)
const latestLiquidityHistory = [
...dataHistory.poolSnapshots.map((item) => item.baseTokenLiquidity)
]
setLiquidityHistory(latestLiquidtyHistory)
const latestPriceHistory = [
...priceHistory,
...data.poolTransactions.map((item) => item.spotPrice)
...dataHistory.poolSnapshots.map((item) => item.datatokenLiquidity)
]
setPriceHistory(latestPriceHistory)
if (data.poolTransactions.length > 0) {
const newBlock =
data.poolTransactions[data.poolTransactions.length - 1].block
if (newBlock === lastBlock) return
setLastBlock(
data.poolTransactions[data.poolTransactions.length - 1].block
)
} else {
setGraphData({
labels: latestTimestamps.slice(0),
datasets: [
{
...lineStyle,
label: 'Liquidity (OCEAN)',
data:
graphType === 'liquidity'
? latestLiquidtyHistory.slice(0)
: latestPriceHistory.slice(0),
borderColor: `#8b98a9`,
pointBackgroundColor: `#8b98a9`
}
]
})
setIsLoading(false)
refetchGraph()
}
setGraphData({
labels: latestTimestamps.slice(0),
datasets: [
{
...lineStyle,
label: 'Liquidity (OCEAN)',
data:
graphType === 'liquidity'
? latestLiquidityHistory.slice(0)
: latestPriceHistory.slice(0),
borderColor: `#8b98a9`,
pointBackgroundColor: `#8b98a9`
}
]
})
setIsLoading(false)
refetchGraph()
}
init()
}, [dataHistory, graphType])
return () => clearInterval(graphFetchInterval)
}, [dataHistory, graphType, graphFetchInterval, getPoolHistory, refetchGraph])
function handleGraphTypeSwitch(e: ChangeEvent<HTMLButtonElement>) {
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 styles from './index.module.css'
import stylesActions from './Actions.module.css'
@ -14,7 +14,7 @@ import AssetActionHistoryTable from '../AssetActionHistoryTable'
import Graph from './Graph'
import { useAsset } from '@context/Asset'
import { gql, OperationResult } from 'urql'
import { PoolLiquidity } from '../../../../@types/apollo/PoolLiquidity'
import { PoolLiquidity } from '../../../../@types/subgraph/PoolLiquidity'
import { useWeb3 } from '@context/Web3'
import PoolTransactions from '@shared/PoolTransactions'
import { fetchData, getQueryContext } from '@utils/subgraph'
@ -22,39 +22,42 @@ import { isValidNumber } from '@utils/numbers'
import Decimal from 'decimal.js'
import content from '../../../../../content/price.json'
const REFETCH_INTERVAL = 5000
Decimal.set({ toExpNeg: -18, precision: 18, rounding: 1 })
const poolLiquidityQuery = gql`
query PoolLiquidity($id: ID!, $shareId: ID) {
pool(id: $id) {
query PoolLiquidity($pool: ID!, $owner: ID) {
pool(id: $pool) {
id
totalShares
swapFee
poolFee
opfFee
marketFee
spotPrice
tokens {
baseToken {
address
symbol
isDatatoken
balance
denormWeight
}
shares(where: { id: $shareId }) {
id
balance
baseTokenWeight
baseTokenLiquidity
datatoken {
address
symbol
}
datatokenWeight
datatokenLiquidity
shares(where: { user: $owner }) {
shares
}
}
}
`
const userPoolShareQuery = gql`
query PoolShare($id: ID!, $shareId: ID) {
pool(id: $id) {
query PoolShare($pool: ID!, $user: ID) {
pool(id: $pool) {
id
shares(where: { id: $shareId }) {
id
balance
shares(where: { user: $user }) {
shares
}
}
}
@ -99,45 +102,40 @@ export default function Pool(): ReactElement {
// the purpose of the value is just to trigger the effect
const [refreshPool, setRefreshPool] = useState(false)
async function getPoolLiquidity() {
const queryContext = getQueryContext(ddo.chainId)
const queryVariables = {
id: price.address.toLowerCase(),
shareId: `${price.address.toLowerCase()}-${ddo.nft.owner.toLowerCase()}`
}
const getPoolLiquidity = useCallback(async () => {
if (!ddo?.chainId || !price?.address || !owner) return
const queryVariables = {
pool: price.address.toLowerCase(),
owner: owner.toLowerCase()
}
const queryResult: OperationResult<PoolLiquidity> = await fetchData(
poolLiquidityQuery,
queryVariables,
queryContext
getQueryContext(ddo.chainId)
)
setdataLiquidity(queryResult?.data)
}
}, [ddo?.chainId, price?.address, owner])
async function getUserPoolShareBalance() {
const queryContext = getQueryContext(ddo.chainId)
const queryVariables = {
id: price.address.toLowerCase(),
shareId: `${price.address.toLowerCase()}-${accountId.toLowerCase()}`
pool: price.address.toLowerCase(),
user: accountId.toLowerCase()
}
const queryResult: OperationResult<PoolLiquidity> = await fetchData(
userPoolShareQuery,
queryVariables,
queryContext
getQueryContext(ddo.chainId)
)
return queryResult?.data.pool.shares[0]?.balance
return queryResult?.data.pool.shares[0]?.shares
}
function refetchLiquidity() {
if (!liquidityFetchInterval) {
setLiquidityFetchInterval(
setInterval(function () {
getPoolLiquidity()
}, REFETCH_INTERVAL)
)
}
}
const refetchLiquidity = useCallback(() => {
if (liquidityFetchInterval) return
const newInterval = setInterval(() => getPoolLiquidity(), refreshInterval)
setLiquidityFetchInterval(newInterval)
}, [liquidityFetchInterval, getPoolLiquidity, refreshInterval])
useEffect(() => {
return () => {
@ -147,52 +145,44 @@ export default function Pool(): ReactElement {
useEffect(() => {
async function init() {
if (!dataLiquidity || !dataLiquidity.pool) {
if (!dataLiquidity?.pool) {
await getPoolLiquidity()
return
}
// Set symbols
dataLiquidity.pool.tokens.forEach((token) => {
token.isDatatoken
? setDtSymbol(token.symbol)
: setOceanSymbol(token.symbol)
})
setOceanSymbol(dataLiquidity.pool.baseToken.symbol)
setDtSymbol(dataLiquidity.pool.datatoken.symbol)
// Total pool shares
const totalPoolTokens = dataLiquidity.pool.totalShares
setTotalPoolTokens(totalPoolTokens)
// Get swap fee
// swapFee is tricky: to get 0.1% you need to convert from 0.001
const swapFee = isValidNumber(dataLiquidity.pool.swapFee)
? new Decimal(dataLiquidity.pool.swapFee).mul(100).toString()
// Get poolFee
// poolFee is tricky: to get 0.1% you need to convert from 0.001
const swapFee = isValidNumber(dataLiquidity.pool.poolFee)
? new Decimal(dataLiquidity.pool.poolFee).mul(100).toString()
: '0'
setSwapFee(swapFee)
// Get weights
const weightDt = dataLiquidity.pool.tokens.filter(
(token: any) =>
token.address === ddo.services[0].datatokenAddress.toLowerCase()
)[0].denormWeight
const weightDtDecimal = isValidNumber(weightDt)
? new Decimal(weightDt).mul(10).toString()
: '0'
function getWeight(weight: string) {
return isValidNumber(weight)
? new Decimal(weight).mul(10).toString()
: '0'
}
const weightDt = dataLiquidity.pool.datatokenWeight
const weightDtDecimal = getWeight(weightDt)
setWeightDt(weightDtDecimal)
const weightOceanDecimal = isValidNumber(weightDt)
? new Decimal(100).minus(new Decimal(weightDt).mul(10)).toString()
: '0'
const weightOcean = dataLiquidity.pool.baseTokenWeight
const weightOceanDecimal = getWeight(weightOcean)
setWeightOcean(weightOceanDecimal)
//
// Get everything the creator put into the pool
//
const creatorPoolTokens = dataLiquidity.pool.shares[0].balance
const creatorPoolTokens = dataLiquidity.pool.shares[0]?.shares
setCreatorPoolTokens(creatorPoolTokens)
const creatorOceanBalance =
@ -250,7 +240,13 @@ export default function Pool(): ReactElement {
refetchLiquidity()
}
init()
}, [dataLiquidity, ddo, price.datatoken, price.ocean, price?.value])
}, [
dataLiquidity,
price?.datatoken,
price?.ocean,
getPoolLiquidity,
refetchLiquidity
])
useEffect(() => {
setIsRemoveDisabled(isInPurgatory && owner === accountId)
@ -258,6 +254,7 @@ export default function Pool(): ReactElement {
useEffect(() => {
if (!dataLiquidity) return
const poolShare =
isValidNumber(poolTokens) &&
isValidNumber(totalPoolTokens) &&
@ -294,10 +291,11 @@ export default function Pool(): ReactElement {
: new Decimal(0)
setTotalLiquidityInOcean(totalLiquidityInOcean)
}, [userLiquidity, price, poolTokens, totalPoolTokens])
}, [dataLiquidity, userLiquidity, price, poolTokens, totalPoolTokens])
useEffect(() => {
if (!accountId || !price) return
async function init() {
try {
//

View File

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

View File

@ -1,7 +1,12 @@
import React, { ReactElement, useState, useEffect } from 'react'
import Compute from './Compute'
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 { compareAsBN } from '@utils/numbers'
import Pool from './Pool'
@ -24,8 +29,13 @@ export default function AssetActions({
ddo: Asset
price: BestPrice
}): ReactElement {
const { accountId, balance } = useWeb3()
const { accountId, balance, web3 } = useWeb3()
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 [isBalanceSufficient, setIsBalanceSufficient] = useState<boolean>()
@ -82,20 +92,22 @@ export default function AssetActions({
// Get and set user DT balance
useEffect(() => {
if (!accountId || !isAssetNetwork) return
if (!web3 || !accountId || !isAssetNetwork) return
async function init() {
try {
// const dtBalance = await ocean.datatokens.balance(
// ddo.services[0].datatokenAddress,
// accountId
// )
// setDtBalance(dtBalance)
const datatokenInstance = new Datatoken(web3)
const dtBalance = await datatokenInstance.balance(
ddo.services[0].datatokenAddress,
accountId
)
setDtBalance(dtBalance)
} catch (e) {
LoggerInstance.error(e.message)
}
}
init()
}, [accountId, ddo, isAssetNetwork])
}, [web3, accountId, ddo, isAssetNetwork])
// Check user balance against price
useEffect(() => {

View File

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

View File

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

View File

@ -11,7 +11,7 @@ import Conversion from '@shared/Price/Conversion'
import NumberUnit from './NumberUnit'
import styles from './Stats.module.css'
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(
poolShares: PoolShare[]

View File

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