mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
Restore Pool Shares section (#1139)
* get poolShares dt addresses * style fixes * class names fix * remove useless changes * fix * try/catch blocks, loading fix * show pool shares fix * delete logs, fix build * more try/catch blocks * check subgraph url, add try/catch block * fixes * pool fields fix * minor code fixes * fix subgraph fetch Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * remove unused function, fixes * use LoggerInstance, remove useless setter * error messages fix, get rid of dt column * small tweaks and tests * fixes * fixes * modified flow for pool shares * loading UX fixes * unified calculations for pool liquidity * stop the refetch madness * profile provider already sets interval fetching for pool shares * pool shares will change when chainIds, accountId is changed so no need to listen for changes again * calculation tweaks * pool stats tweak * fix pool transactions * fix data display in pool shares section * minor fix, delete comment * subgraph typings generation fix * pool stats display tweaks * price sizing fix * rabbit hole fixes * more price UI fixes * cleanup * wording consistency * render all frontpage sections by default, load in assets after Co-authored-by: ClaudiaHolhos <claudia@oceanprotocol.com> Co-authored-by: mihaisc <mihai.scarlat@smartcontrol.ro> Co-authored-by: mihaisc <mihai@oceanprotocol.com> Co-authored-by: Matthias Kretschmann <m@kretschmann.io>
This commit is contained in:
parent
af60018500
commit
4331c24c0d
@ -172,7 +172,6 @@ function PoolProvider({ children }: { children: ReactNode }): ReactElement {
|
|||||||
.mul(100)
|
.mul(100)
|
||||||
.toFixed(2)
|
.toFixed(2)
|
||||||
: '0'
|
: '0'
|
||||||
|
|
||||||
const newPoolOwnerInfo = {
|
const newPoolOwnerInfo = {
|
||||||
liquidity,
|
liquidity,
|
||||||
poolShares: ownerPoolShares,
|
poolShares: ownerPoolShares,
|
||||||
|
@ -154,7 +154,11 @@ function ProfileProvider({
|
|||||||
await fetchPoolShares(accountId, chainIds, isEthAddress)
|
await fetchPoolShares(accountId, chainIds, isEthAddress)
|
||||||
|
|
||||||
if (poolSharesInterval) return
|
if (poolSharesInterval) return
|
||||||
|
|
||||||
const interval = setInterval(async () => {
|
const interval = setInterval(async () => {
|
||||||
|
LoggerInstance.log(
|
||||||
|
`[profile] Re-fetching pool shares after ${refreshInterval / 1000}s.`
|
||||||
|
)
|
||||||
await fetchPoolShares(accountId, chainIds, isEthAddress)
|
await fetchPoolShares(accountId, chainIds, isEthAddress)
|
||||||
}, refreshInterval)
|
}, refreshInterval)
|
||||||
setPoolSharesInterval(interval)
|
setPoolSharesInterval(interval)
|
||||||
|
@ -8,7 +8,7 @@ import {
|
|||||||
TokensPriceQuery,
|
TokensPriceQuery,
|
||||||
TokensPriceQuery_tokens as TokensPrice
|
TokensPriceQuery_tokens as TokensPrice
|
||||||
} from '../@types/subgraph/TokensPriceQuery'
|
} from '../@types/subgraph/TokensPriceQuery'
|
||||||
import { Asset, ProviderInstance } from '@oceanprotocol/lib'
|
import { Asset, LoggerInstance, ProviderInstance } from '@oceanprotocol/lib'
|
||||||
import { AssetExtended } from 'src/@types/AssetExtended'
|
import { AssetExtended } from 'src/@types/AssetExtended'
|
||||||
import { calculateBuyPrice } from './pool'
|
import { calculateBuyPrice } from './pool'
|
||||||
import { getFixedBuyPrice } from './fixedRateExchange'
|
import { getFixedBuyPrice } from './fixedRateExchange'
|
||||||
@ -229,41 +229,42 @@ function getAccessDetailsFromTokenPrice(
|
|||||||
*/
|
*/
|
||||||
export async function getOrderPriceAndFees(
|
export async function getOrderPriceAndFees(
|
||||||
asset: AssetExtended,
|
asset: AssetExtended,
|
||||||
accountId?: string
|
accountId: string
|
||||||
): Promise<OrderPriceAndFees> {
|
): Promise<OrderPriceAndFees> {
|
||||||
const orderPriceAndFee = {
|
|
||||||
price: '0',
|
|
||||||
publisherMarketOrderFee: '0',
|
|
||||||
publisherMarketPoolSwapFee: '0',
|
|
||||||
publisherMarketFixedSwapFee: '0',
|
|
||||||
consumeMarketOrderFee: '0',
|
|
||||||
consumeMarketPoolSwapFee: '0',
|
|
||||||
consumeMarketFixedSwapFee: '0',
|
|
||||||
providerFee: {},
|
|
||||||
opcFee: '0'
|
|
||||||
} as OrderPriceAndFees
|
|
||||||
const { accessDetails } = asset
|
|
||||||
const { appConfig } = getSiteMetadata()
|
const { appConfig } = getSiteMetadata()
|
||||||
|
|
||||||
// fetch publish market order fee
|
const orderPriceAndFee = {
|
||||||
orderPriceAndFee.publisherMarketOrderFee =
|
price: '0',
|
||||||
asset.accessDetails.publisherMarketOrderFee
|
publisherMarketOrderFee:
|
||||||
// fetch consume market order fee
|
asset?.accessDetails?.publisherMarketOrderFee || '0',
|
||||||
orderPriceAndFee.consumeMarketOrderFee = appConfig.consumeMarketOrderFee
|
publisherMarketPoolSwapFee: '0',
|
||||||
|
publisherMarketFixedSwapFee: '0',
|
||||||
|
consumeMarketOrderFee: appConfig.consumeMarketOrderFee || '0',
|
||||||
|
consumeMarketPoolSwapFee: '0',
|
||||||
|
consumeMarketFixedSwapFee: '0',
|
||||||
|
providerFee: {
|
||||||
|
providerFeeAmount: '0'
|
||||||
|
},
|
||||||
|
opcFee: '0'
|
||||||
|
} as OrderPriceAndFees
|
||||||
|
|
||||||
// fetch provider fee
|
// fetch provider fee
|
||||||
const initializeData = await ProviderInstance.initialize(
|
const initializeData = await ProviderInstance.initialize(
|
||||||
asset.id,
|
asset?.id,
|
||||||
asset.services[0].id,
|
asset.services[0].id,
|
||||||
0,
|
0,
|
||||||
accountId,
|
accountId,
|
||||||
asset.services[0].serviceEndpoint
|
asset?.services[0].serviceEndpoint
|
||||||
)
|
)
|
||||||
orderPriceAndFee.providerFee = initializeData.providerFee
|
orderPriceAndFee.providerFee = initializeData.providerFee
|
||||||
|
|
||||||
// fetch price and swap fees
|
// fetch price and swap fees
|
||||||
switch (accessDetails.type) {
|
switch (asset?.accessDetails?.type) {
|
||||||
case 'dynamic': {
|
case 'dynamic': {
|
||||||
const poolPrice = await calculateBuyPrice(accessDetails, asset.chainId)
|
const poolPrice = await calculateBuyPrice(
|
||||||
|
asset?.accessDetails,
|
||||||
|
asset?.chainId
|
||||||
|
)
|
||||||
orderPriceAndFee.price = poolPrice.tokenAmount
|
orderPriceAndFee.price = poolPrice.tokenAmount
|
||||||
orderPriceAndFee.liquidityProviderSwapFee =
|
orderPriceAndFee.liquidityProviderSwapFee =
|
||||||
poolPrice.liquidityProviderSwapFeeAmount
|
poolPrice.liquidityProviderSwapFeeAmount
|
||||||
@ -274,7 +275,7 @@ export async function getOrderPriceAndFees(
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'fixed': {
|
case 'fixed': {
|
||||||
const fixed = await getFixedBuyPrice(accessDetails, asset.chainId)
|
const fixed = await getFixedBuyPrice(asset?.accessDetails, asset?.chainId)
|
||||||
orderPriceAndFee.price = fixed.baseTokenAmount
|
orderPriceAndFee.price = fixed.baseTokenAmount
|
||||||
orderPriceAndFee.opcFee = fixed.oceanFeeAmount
|
orderPriceAndFee.opcFee = fixed.oceanFeeAmount
|
||||||
orderPriceAndFee.publisherMarketFixedSwapFee = fixed.marketFeeAmount
|
orderPriceAndFee.publisherMarketFixedSwapFee = fixed.marketFeeAmount
|
||||||
@ -297,9 +298,9 @@ export async function getOrderPriceAndFees(
|
|||||||
/**
|
/**
|
||||||
* @param {number} chain
|
* @param {number} chain
|
||||||
* @param {string} datatokenAddress
|
* @param {string} datatokenAddress
|
||||||
* @param {number=} timeout timout of the service, this is needed to return order details
|
* @param {number} timeout timout of the service, this is needed to return order details
|
||||||
* @param {string=} account account that wants to buy, is needed to return order details
|
* @param {string} account account that wants to buy, is needed to return order details
|
||||||
* @param {bool=} includeOrderPriceAndFees if false price will be spot price (pool) and rate (fre), if true you will get the order price including fees !! fees not yet done
|
* @param {bool} includeOrderPriceAndFees if false price will be spot price (pool) and rate (fre), if true you will get the order price including fees !! fees not yet done
|
||||||
* @returns {Promise<AccessDetails>}
|
* @returns {Promise<AccessDetails>}
|
||||||
*/
|
*/
|
||||||
export async function getAccessDetails(
|
export async function getAccessDetails(
|
||||||
@ -308,22 +309,26 @@ export async function getAccessDetails(
|
|||||||
timeout?: number,
|
timeout?: number,
|
||||||
account = ''
|
account = ''
|
||||||
): Promise<AccessDetails> {
|
): Promise<AccessDetails> {
|
||||||
const queryContext = getQueryContext(Number(chainId))
|
try {
|
||||||
const tokenQueryResult: OperationResult<
|
const queryContext = getQueryContext(Number(chainId))
|
||||||
TokenPriceQuery,
|
const tokenQueryResult: OperationResult<
|
||||||
{ datatokenId: string; account: string }
|
TokenPriceQuery,
|
||||||
> = await fetchData(
|
{ datatokenId: string; account: string }
|
||||||
TokenPriceQuery,
|
> = await fetchData(
|
||||||
{
|
TokenPriceQuery,
|
||||||
datatokenId: datatokenAddress.toLowerCase(),
|
{
|
||||||
account: account?.toLowerCase()
|
datatokenId: datatokenAddress.toLowerCase(),
|
||||||
},
|
account: account?.toLowerCase()
|
||||||
queryContext
|
},
|
||||||
)
|
queryContext
|
||||||
|
)
|
||||||
|
|
||||||
const tokenPrice: TokenPrice = tokenQueryResult.data.token
|
const tokenPrice: TokenPrice = tokenQueryResult.data.token
|
||||||
const accessDetails = getAccessDetailsFromTokenPrice(tokenPrice, timeout)
|
const accessDetails = getAccessDetailsFromTokenPrice(tokenPrice, timeout)
|
||||||
return accessDetails
|
return accessDetails
|
||||||
|
} catch (error) {
|
||||||
|
LoggerInstance.error('Error getting access details: ', error.message)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getAccessDetailsForAssets(
|
export async function getAccessDetailsForAssets(
|
||||||
@ -333,43 +338,48 @@ export async function getAccessDetailsForAssets(
|
|||||||
const assetsExtended: AssetExtended[] = assets
|
const assetsExtended: AssetExtended[] = assets
|
||||||
const chainAssetLists: { [key: number]: string[] } = {}
|
const chainAssetLists: { [key: number]: string[] } = {}
|
||||||
|
|
||||||
for (const asset of assets) {
|
try {
|
||||||
if (chainAssetLists[asset.chainId]) {
|
for (const asset of assets) {
|
||||||
chainAssetLists[asset.chainId].push(
|
if (chainAssetLists[asset.chainId]) {
|
||||||
asset.services[0].datatokenAddress.toLowerCase()
|
chainAssetLists[asset.chainId].push(
|
||||||
)
|
asset.services[0].datatokenAddress.toLowerCase()
|
||||||
} else {
|
)
|
||||||
chainAssetLists[asset.chainId] = []
|
} else {
|
||||||
chainAssetLists[asset.chainId].push(
|
chainAssetLists[asset.chainId] = []
|
||||||
asset.services[0].datatokenAddress.toLowerCase()
|
chainAssetLists[asset.chainId].push(
|
||||||
)
|
asset.services[0].datatokenAddress.toLowerCase()
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (const chainKey in chainAssetLists) {
|
for (const chainKey in chainAssetLists) {
|
||||||
const queryContext = getQueryContext(Number(chainKey))
|
const queryContext = getQueryContext(Number(chainKey))
|
||||||
const tokenQueryResult: OperationResult<
|
const tokenQueryResult: OperationResult<
|
||||||
TokensPriceQuery,
|
TokensPriceQuery,
|
||||||
{ datatokenIds: [string]; account: string }
|
{ datatokenIds: [string]; account: string }
|
||||||
> = await fetchData(
|
> = await fetchData(
|
||||||
TokensPriceQuery,
|
TokensPriceQuery,
|
||||||
{
|
{
|
||||||
datatokenIds: chainAssetLists[chainKey],
|
datatokenIds: chainAssetLists[chainKey],
|
||||||
account: account?.toLowerCase()
|
account: account?.toLowerCase()
|
||||||
},
|
},
|
||||||
queryContext
|
queryContext
|
||||||
)
|
|
||||||
tokenQueryResult.data?.tokens.forEach((token) => {
|
|
||||||
const currentAsset = assetsExtended.find(
|
|
||||||
(asset) => asset.services[0].datatokenAddress.toLowerCase() === token.id
|
|
||||||
)
|
|
||||||
const accessDetails = getAccessDetailsFromTokenPrice(
|
|
||||||
token,
|
|
||||||
currentAsset?.services[0]?.timeout
|
|
||||||
)
|
)
|
||||||
|
tokenQueryResult.data?.tokens.forEach((token) => {
|
||||||
|
const currentAsset = assetsExtended.find(
|
||||||
|
(asset) =>
|
||||||
|
asset.services[0].datatokenAddress.toLowerCase() === token.id
|
||||||
|
)
|
||||||
|
const accessDetails = getAccessDetailsFromTokenPrice(
|
||||||
|
token,
|
||||||
|
currentAsset?.services[0]?.timeout
|
||||||
|
)
|
||||||
|
|
||||||
currentAsset.accessDetails = accessDetails
|
currentAsset.accessDetails = accessDetails
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
return assetsExtended
|
||||||
|
} catch (error) {
|
||||||
|
LoggerInstance.error('Error getting access details: ', error.message)
|
||||||
}
|
}
|
||||||
return assetsExtended
|
|
||||||
}
|
}
|
||||||
|
@ -170,6 +170,28 @@ export async function getAssetsFromDidList(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getAssetsFromDtList(
|
||||||
|
dtList: string[],
|
||||||
|
chainIds: number[],
|
||||||
|
cancelToken: CancelToken
|
||||||
|
): Promise<Asset[]> {
|
||||||
|
try {
|
||||||
|
if (!(dtList.length > 0)) return
|
||||||
|
|
||||||
|
const baseParams = {
|
||||||
|
chainIds: chainIds,
|
||||||
|
filters: [getFilterTerm('services.datatokenAddress', dtList)],
|
||||||
|
ignorePurgatory: true
|
||||||
|
} as BaseQueryParams
|
||||||
|
const query = generateBaseQuery(baseParams)
|
||||||
|
|
||||||
|
const queryResult = await queryMetadata(query, cancelToken)
|
||||||
|
return queryResult?.results
|
||||||
|
} catch (error) {
|
||||||
|
LoggerInstance.error(error.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function retrieveDDOListByDIDs(
|
export async function retrieveDDOListByDIDs(
|
||||||
didList: string[],
|
didList: string[],
|
||||||
chainIds: number[],
|
chainIds: number[],
|
||||||
|
@ -16,9 +16,6 @@ export function getOceanConfig(network: string | number): Config {
|
|||||||
? undefined
|
? undefined
|
||||||
: process.env.NEXT_PUBLIC_INFURA_PROJECT_ID
|
: process.env.NEXT_PUBLIC_INFURA_PROJECT_ID
|
||||||
) as Config
|
) as Config
|
||||||
// TODO: remove hack once address is fixed
|
|
||||||
if (network === 'rinkeby' || network === 4)
|
|
||||||
config.oceanTokenAddress = '0x8967bcf84170c91b0d24d4302c2376283b0b3a07'
|
|
||||||
return config as Config
|
return config as Config
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,7 +27,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://subgraphv4.rinkeby.oceanprotocol.com'
|
subgraphUri: 'https://v4.subgraph.rinkeby.oceanprotocol.com'
|
||||||
} as Config
|
} as Config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,8 @@ import { getDummyWeb3 } from './web3'
|
|||||||
import { TransactionReceipt } from 'web3-eth'
|
import { TransactionReceipt } from 'web3-eth'
|
||||||
import Decimal from 'decimal.js'
|
import Decimal from 'decimal.js'
|
||||||
import { AccessDetails } from 'src/@types/Price'
|
import { AccessDetails } from 'src/@types/Price'
|
||||||
|
import { isValidNumber } from './numbers'
|
||||||
|
import { MAX_DECIMALS } from './constants'
|
||||||
/**
|
/**
|
||||||
* This is used to calculate the price to buy one datatoken from a pool, that is different from spot price. You need to pass either a web3 object or a chainId. If you pass a chainId a dummy web3 object will be created
|
* This is used to calculate the price to buy one datatoken from a pool, that is different from spot price. You need to pass either a web3 object or a chainId. If you pass a chainId a dummy web3 object will be created
|
||||||
* @param {AccessDetails} accessDetails
|
* @param {AccessDetails} accessDetails
|
||||||
@ -73,3 +74,40 @@ export async function buyDtFromPool(
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the base token liquidity based on shares info
|
||||||
|
* @param {string} shares
|
||||||
|
* @param {string} totalShares
|
||||||
|
* @param {string} baseTokenLiquidity
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function calculateUserLiquidity(
|
||||||
|
shares: string,
|
||||||
|
totalShares: string,
|
||||||
|
baseTokenLiquidity: string
|
||||||
|
): string {
|
||||||
|
const totalLiquidity =
|
||||||
|
isValidNumber(shares) &&
|
||||||
|
isValidNumber(totalShares) &&
|
||||||
|
isValidNumber(baseTokenLiquidity)
|
||||||
|
? new Decimal(shares)
|
||||||
|
.dividedBy(new Decimal(totalShares))
|
||||||
|
.mul(baseTokenLiquidity)
|
||||||
|
: new Decimal(0)
|
||||||
|
return totalLiquidity.toDecimalPlaces(MAX_DECIMALS).toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
export function calculateUserTVL(
|
||||||
|
shares: string,
|
||||||
|
totalShares: string,
|
||||||
|
baseTokenLiquidity: string
|
||||||
|
): string {
|
||||||
|
const liquidity = calculateUserLiquidity(
|
||||||
|
shares,
|
||||||
|
totalShares,
|
||||||
|
baseTokenLiquidity
|
||||||
|
)
|
||||||
|
const tvl = new Decimal(liquidity).mul(2) // we multiply by 2 because of 50/50 weight
|
||||||
|
return tvl.toDecimalPlaces(MAX_DECIMALS).toString()
|
||||||
|
}
|
||||||
|
@ -12,12 +12,12 @@ import {
|
|||||||
PoolShares as PoolSharesList,
|
PoolShares as PoolSharesList,
|
||||||
PoolShares_poolShares as PoolShare
|
PoolShares_poolShares as PoolShare
|
||||||
} from '../@types/subgraph/PoolShares'
|
} from '../@types/subgraph/PoolShares'
|
||||||
import {
|
import { OrdersData_orders as OrdersData } from '../@types/subgraph/OrdersData'
|
||||||
OrdersData_orders as OrdersData,
|
|
||||||
OrdersData_orders_datatoken as OrdersDatatoken
|
|
||||||
} from '../@types/subgraph/OrdersData'
|
|
||||||
import { UserSalesQuery as UsersSalesList } from '../@types/subgraph/UserSalesQuery'
|
import { UserSalesQuery as UsersSalesList } from '../@types/subgraph/UserSalesQuery'
|
||||||
import { OpcFeesQuery as OpcFeesData } from '../@types/subgraph/OpcFeesQuery'
|
import { OpcFeesQuery as OpcFeesData } from '../@types/subgraph/OpcFeesQuery'
|
||||||
|
import { calculateUserTVL } from './pool'
|
||||||
|
import Decimal from 'decimal.js'
|
||||||
|
import { MAX_DECIMALS } from './constants'
|
||||||
|
|
||||||
export interface UserLiquidity {
|
export interface UserLiquidity {
|
||||||
price: string
|
price: string
|
||||||
@ -164,7 +164,7 @@ const UserTokenOrders = gql`
|
|||||||
`
|
`
|
||||||
|
|
||||||
const UserSalesQuery = gql`
|
const UserSalesQuery = gql`
|
||||||
query UserSalesQuery($user: String!) {
|
query UserSalesQuery($user: ID!) {
|
||||||
users(where: { id: $user }) {
|
users(where: { id: $user }) {
|
||||||
id
|
id
|
||||||
totalSales
|
totalSales
|
||||||
@ -177,7 +177,7 @@ const TopSalesQuery = gql`
|
|||||||
query TopSalesQuery {
|
query TopSalesQuery {
|
||||||
users(
|
users(
|
||||||
first: 20
|
first: 20
|
||||||
orderBy: tokensOwned
|
orderBy: sharesOwned
|
||||||
orderDirection: desc
|
orderDirection: desc
|
||||||
where: { tokenBalancesOwned_not: "0" }
|
where: { tokenBalancesOwned_not: "0" }
|
||||||
) {
|
) {
|
||||||
@ -206,14 +206,17 @@ export function getSubgraphUri(chainId: number): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getQueryContext(chainId: number): OperationContext {
|
export function getQueryContext(chainId: number): OperationContext {
|
||||||
const queryContext: OperationContext = {
|
try {
|
||||||
url: `${getSubgraphUri(
|
const queryContext: OperationContext = {
|
||||||
Number(chainId)
|
url: `${getSubgraphUri(
|
||||||
)}/subgraphs/name/oceanprotocol/ocean-subgraph`,
|
Number(chainId)
|
||||||
requestPolicy: 'cache-and-network'
|
)}/subgraphs/name/oceanprotocol/ocean-subgraph`,
|
||||||
|
requestPolicy: 'cache-and-network'
|
||||||
|
}
|
||||||
|
return queryContext
|
||||||
|
} catch (error) {
|
||||||
|
LoggerInstance.error('Get query context error: ', error.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
return queryContext
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchData(
|
export async function fetchData(
|
||||||
@ -223,12 +226,13 @@ export async function fetchData(
|
|||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
try {
|
try {
|
||||||
const client = getUrqlClientInstance()
|
const client = getUrqlClientInstance()
|
||||||
|
|
||||||
const response = await client.query(query, variables, context).toPromise()
|
const response = await client.query(query, variables, context).toPromise()
|
||||||
return response
|
return response
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetchData: ', error.message)
|
LoggerInstance.error('Error fetchData: ', error.message)
|
||||||
throw Error(error.message)
|
|
||||||
}
|
}
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchDataForMultipleChains(
|
export async function fetchDataForMultipleChains(
|
||||||
@ -237,21 +241,20 @@ export async function fetchDataForMultipleChains(
|
|||||||
chainIds: number[]
|
chainIds: number[]
|
||||||
): Promise<any[]> {
|
): Promise<any[]> {
|
||||||
let datas: any[] = []
|
let datas: any[] = []
|
||||||
for (const chainId of chainIds) {
|
try {
|
||||||
const context: OperationContext = {
|
for (const chainId of chainIds) {
|
||||||
url: `${getSubgraphUri(
|
// console.log('fetch chainID', chainId)
|
||||||
chainId
|
const context: OperationContext = getQueryContext(chainId)
|
||||||
)}/subgraphs/name/oceanprotocol/ocean-subgraph`,
|
|
||||||
requestPolicy: 'network-only'
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const response = await fetchData(query, variables, context)
|
const response = await fetchData(query, variables, context)
|
||||||
datas = datas.concat(response.data)
|
// console.log('fetch response', response)
|
||||||
} catch (error) {
|
if (!response || response.error) continue
|
||||||
console.error('Error fetchData: ', error.message)
|
datas = datas.concat(response?.data)
|
||||||
|
// console.log('fetch datas', datas)
|
||||||
}
|
}
|
||||||
|
return datas
|
||||||
|
} catch (error) {
|
||||||
|
LoggerInstance.error('Error fetchDataForMultipleChains: ', error.message)
|
||||||
}
|
}
|
||||||
return datas
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getOpcFees(chainId: number) {
|
export async function getOpcFees(chainId: number) {
|
||||||
@ -268,7 +271,7 @@ export async function getOpcFees(chainId: number) {
|
|||||||
)
|
)
|
||||||
opcFees = response?.data?.opc
|
opcFees = response?.data?.opc
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetchData: ', error.message)
|
LoggerInstance.error('Error getOpcFees: ', error.message)
|
||||||
throw Error(error.message)
|
throw Error(error.message)
|
||||||
}
|
}
|
||||||
return opcFees
|
return opcFees
|
||||||
@ -320,6 +323,7 @@ export async function getHighestLiquidityDatatokens(
|
|||||||
): Promise<string[]> {
|
): Promise<string[]> {
|
||||||
const dtList: string[] = []
|
const dtList: string[] = []
|
||||||
let highestLiquidityAssets: HighestLiquidityAssetsPool[] = []
|
let highestLiquidityAssets: HighestLiquidityAssetsPool[] = []
|
||||||
|
|
||||||
for (const chain of chainIds) {
|
for (const chain of chainIds) {
|
||||||
const queryContext = getQueryContext(Number(chain))
|
const queryContext = getQueryContext(Number(chain))
|
||||||
const fetchedPools: OperationResult<HighestLiquidityGraphAssets, any> =
|
const fetchedPools: OperationResult<HighestLiquidityGraphAssets, any> =
|
||||||
@ -339,22 +343,11 @@ export async function getHighestLiquidityDatatokens(
|
|||||||
return dtList
|
return dtList
|
||||||
}
|
}
|
||||||
|
|
||||||
export function calculateUserLiquidity(poolShare: PoolShare): number {
|
export async function getAccountTVLInOwnAssets(
|
||||||
const ocean =
|
|
||||||
(poolShare.shares / poolShare.pool.totalShares) *
|
|
||||||
poolShare.pool.baseTokenLiquidity
|
|
||||||
const datatokens =
|
|
||||||
(poolShare.shares / poolShare.pool.totalShares) *
|
|
||||||
poolShare.pool.datatokenLiquidity
|
|
||||||
const totalLiquidity = ocean + datatokens * poolShare.pool.spotPrice
|
|
||||||
return totalLiquidity
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getAccountLiquidityInOwnAssets(
|
|
||||||
accountId: string,
|
accountId: string,
|
||||||
chainIds: number[],
|
chainIds: number[],
|
||||||
pools: string[]
|
pools: string[]
|
||||||
): Promise<UserLiquidity> {
|
): Promise<string> {
|
||||||
const queryVariables = {
|
const queryVariables = {
|
||||||
user: accountId.toLowerCase(),
|
user: accountId.toLowerCase(),
|
||||||
pools: pools
|
pools: pools
|
||||||
@ -364,22 +357,22 @@ export async function getAccountLiquidityInOwnAssets(
|
|||||||
queryVariables,
|
queryVariables,
|
||||||
chainIds
|
chainIds
|
||||||
)
|
)
|
||||||
let totalLiquidity = 0
|
let tvl = new Decimal(0)
|
||||||
let totalOceanLiquidity = 0
|
// console.log('resss', results)
|
||||||
|
|
||||||
for (const result of results) {
|
for (const result of results) {
|
||||||
|
// console.log('result.poolShares', result.poolShares)
|
||||||
for (const poolShare of result.poolShares) {
|
for (const poolShare of result.poolShares) {
|
||||||
const userShare = poolShare.shares / poolShare.pool.totalShares
|
const poolUserTvl = calculateUserTVL(
|
||||||
const userBalance = userShare * poolShare.pool.baseTokenLiquidity
|
poolShare.shares,
|
||||||
totalOceanLiquidity += userBalance
|
poolShare.pool.totalShares,
|
||||||
const poolLiquidity = calculateUserLiquidity(poolShare)
|
poolShare.pool.baseTokenLiquidity
|
||||||
totalLiquidity += poolLiquidity
|
)
|
||||||
|
tvl = tvl.add(new Decimal(poolUserTvl))
|
||||||
|
// console.log('result.poolShares', tvl.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {
|
return tvl.toDecimalPlaces(MAX_DECIMALS).toString()
|
||||||
price: totalLiquidity.toString(),
|
|
||||||
oceanBalance: totalOceanLiquidity.toString()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getPoolSharesData(
|
export async function getPoolSharesData(
|
||||||
@ -388,17 +381,21 @@ export async function getPoolSharesData(
|
|||||||
): Promise<PoolShare[]> {
|
): Promise<PoolShare[]> {
|
||||||
const variables = { user: accountId?.toLowerCase() }
|
const variables = { user: accountId?.toLowerCase() }
|
||||||
const data: PoolShare[] = []
|
const data: PoolShare[] = []
|
||||||
const result = await fetchDataForMultipleChains(
|
try {
|
||||||
userPoolSharesQuery,
|
const result = await fetchDataForMultipleChains(
|
||||||
variables,
|
userPoolSharesQuery,
|
||||||
chainIds
|
variables,
|
||||||
)
|
chainIds
|
||||||
for (let i = 0; i < result.length; i++) {
|
)
|
||||||
result[i].poolShares.forEach((poolShare: PoolShare) => {
|
for (let i = 0; i < result.length; i++) {
|
||||||
data.push(poolShare)
|
result[i].poolShares.forEach((poolShare: PoolShare) => {
|
||||||
})
|
data.push(poolShare)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
} catch (error) {
|
||||||
|
LoggerInstance.error('Error getPoolSharesData: ', error.message)
|
||||||
}
|
}
|
||||||
return data
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getUserTokenOrders(
|
export async function getUserTokenOrders(
|
||||||
@ -422,7 +419,7 @@ export async function getUserTokenOrders(
|
|||||||
|
|
||||||
return data
|
return data
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
LoggerInstance.error(error.message)
|
LoggerInstance.error('Error getUserTokenOrders', error.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -445,7 +442,7 @@ export async function getUserSales(
|
|||||||
}
|
}
|
||||||
return salesSum
|
return salesSum
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
LoggerInstance.log(error.message)
|
LoggerInstance.error('Error getUserSales', error.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,11 @@ export default function AssetComputeSelection({
|
|||||||
{asset.symbol} | {asset.did}
|
{asset.symbol} | {asset.did}
|
||||||
</Dotdotdot>
|
</Dotdotdot>
|
||||||
</div>
|
</div>
|
||||||
<PriceUnit price={asset.price} small className={styles.price} />
|
<PriceUnit
|
||||||
|
price={asset.price}
|
||||||
|
size="small"
|
||||||
|
className={styles.price}
|
||||||
|
/>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
))
|
))
|
||||||
|
@ -51,7 +51,7 @@ export default function AssetTeaser({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<footer className={styles.foot}>
|
<footer className={styles.foot}>
|
||||||
<Price accessDetails={asset.accessDetails} small />
|
<Price accessDetails={asset.accessDetails} size="small" />
|
||||||
<NetworkName networkId={asset.chainId} className={styles.network} />
|
<NetworkName networkId={asset.chainId} className={styles.network} />
|
||||||
</footer>
|
</footer>
|
||||||
</a>
|
</a>
|
||||||
|
@ -110,7 +110,7 @@ export default function AssetSelection({
|
|||||||
<PriceUnit
|
<PriceUnit
|
||||||
price={asset.price}
|
price={asset.price}
|
||||||
type={asset.price === '0' ? 'free' : undefined}
|
type={asset.price === '0' ? 'free' : undefined}
|
||||||
small
|
size="small"
|
||||||
className={styles.price}
|
className={styles.price}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -5,11 +5,10 @@ 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/subgraph/TransactionHistory'
|
import { TransactionHistory_poolTransactions as TransactionHistoryPoolTransactions } from '../../../@types/subgraph/TransactionHistory'
|
||||||
import web3 from 'web3'
|
|
||||||
import { fetchDataForMultipleChains } from '@utils/subgraph'
|
import { fetchDataForMultipleChains } from '@utils/subgraph'
|
||||||
import { useSiteMetadata } from '@hooks/useSiteMetadata'
|
import { useSiteMetadata } from '@hooks/useSiteMetadata'
|
||||||
import NetworkName from '@shared/NetworkName'
|
import NetworkName from '@shared/NetworkName'
|
||||||
import { retrieveDDOListByDIDs } from '@utils/aquarius'
|
import { getAssetsFromDtList } from '@utils/aquarius'
|
||||||
import { CancelToken } from 'axios'
|
import { CancelToken } from 'axios'
|
||||||
import Title from './Title'
|
import Title from './Title'
|
||||||
import styles from './index.module.css'
|
import styles from './index.module.css'
|
||||||
@ -128,13 +127,14 @@ export default function PoolTransactions({
|
|||||||
minimal?: boolean
|
minimal?: boolean
|
||||||
accountId: string
|
accountId: string
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const [transactions, setTransactions] = useState<PoolTransaction[]>()
|
|
||||||
const [isLoading, setIsLoading] = useState<boolean>(false)
|
|
||||||
const { chainIds } = useUserPreferences()
|
const { chainIds } = useUserPreferences()
|
||||||
const { appConfig } = useSiteMetadata()
|
const { appConfig } = useSiteMetadata()
|
||||||
|
const cancelToken = useCancelToken()
|
||||||
|
|
||||||
|
const [transactions, setTransactions] = useState<PoolTransaction[]>()
|
||||||
|
const [isLoading, setIsLoading] = useState<boolean>(false)
|
||||||
const [dataFetchInterval, setDataFetchInterval] = useState<NodeJS.Timeout>()
|
const [dataFetchInterval, setDataFetchInterval] = useState<NodeJS.Timeout>()
|
||||||
const [data, setData] = useState<PoolTransaction[]>()
|
const [data, setData] = useState<PoolTransaction[]>()
|
||||||
const cancelToken = useCancelToken()
|
|
||||||
|
|
||||||
const getPoolTransactionData = useCallback(async () => {
|
const getPoolTransactionData = useCallback(async () => {
|
||||||
const variables = {
|
const variables = {
|
||||||
@ -165,24 +165,18 @@ export default function PoolTransactions({
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
const poolTransactions: PoolTransaction[] = []
|
const poolTransactions: PoolTransaction[] = []
|
||||||
const didList: string[] = []
|
const dtList: string[] = []
|
||||||
|
|
||||||
for (let i = 0; i < data.length; i++) {
|
for (let i = 0; i < data.length; i++) {
|
||||||
const { address } = data[i].datatoken
|
dtList.push(data[i]?.datatoken?.address)
|
||||||
const did = web3.utils
|
|
||||||
.toChecksumAddress(address)
|
|
||||||
.replace('0x', 'did:op:')
|
|
||||||
didList.push(did)
|
|
||||||
}
|
}
|
||||||
if (didList.length === 0) {
|
|
||||||
|
if (dtList.length === 0) {
|
||||||
setIsLoading(false)
|
setIsLoading(false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const ddoList = await retrieveDDOListByDIDs(
|
const ddoList = await getAssetsFromDtList(dtList, chainIds, cancelToken)
|
||||||
didList,
|
|
||||||
chainIds,
|
|
||||||
cancelToken
|
|
||||||
)
|
|
||||||
for (let i = 0; i < data.length; i++) {
|
for (let i = 0; i < data.length; i++) {
|
||||||
poolTransactions.push({
|
poolTransactions.push({
|
||||||
...data[i],
|
...data[i],
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-weight: var(--font-weight-bold);
|
font-weight: var(--font-weight-bold);
|
||||||
font-family: var(--font-family-base);
|
font-family: var(--font-family-base);
|
||||||
font-size: var(--font-size-large);
|
|
||||||
color: var(--font-color-text);
|
color: var(--font-color-text);
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
}
|
}
|
||||||
@ -17,6 +17,10 @@
|
|||||||
font-size: var(--font-size-base);
|
font-size: var(--font-size-base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.price.large {
|
||||||
|
font-size: var(--font-size-large);
|
||||||
|
}
|
||||||
|
|
||||||
.price.small {
|
.price.small {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: var(--font-size-base);
|
font-size: var(--font-size-base);
|
||||||
@ -26,6 +30,15 @@
|
|||||||
font-size: var(--font-size-small);
|
font-size: var(--font-size-small);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.price.mini {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: var(--font-size-small);
|
||||||
|
}
|
||||||
|
|
||||||
|
.price.mini .symbol {
|
||||||
|
font-size: var(--font-size-mini);
|
||||||
|
}
|
||||||
|
|
||||||
.price .badge {
|
.price .badge {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
margin-left: calc(var(--spacer) / 6);
|
margin-left: calc(var(--spacer) / 6);
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
import React, { ReactElement } from 'react'
|
import React, { ReactElement } from 'react'
|
||||||
import { formatCurrency } from '@coingecko/cryptoformat'
|
import { formatCurrency } from '@coingecko/cryptoformat'
|
||||||
import classNames from 'classnames/bind'
|
|
||||||
import Conversion from './Conversion'
|
import Conversion from './Conversion'
|
||||||
import styles from './PriceUnit.module.css'
|
import styles from './PriceUnit.module.css'
|
||||||
import { useUserPreferences } from '@context/UserPreferences'
|
import { useUserPreferences } from '@context/UserPreferences'
|
||||||
import Badge from '@shared/atoms/Badge'
|
import Badge from '@shared/atoms/Badge'
|
||||||
|
|
||||||
const cx = classNames.bind(styles)
|
|
||||||
|
|
||||||
export function formatPrice(price: string, locale: string): string {
|
export function formatPrice(price: string, locale: string): string {
|
||||||
return formatCurrency(Number(price), '', locale, false, {
|
return formatCurrency(Number(price), '', locale, false, {
|
||||||
// Not exactly clear what `significant figures` are for this library,
|
// Not exactly clear what `significant figures` are for this library,
|
||||||
@ -20,7 +17,7 @@ export function formatPrice(price: string, locale: string): string {
|
|||||||
export default function PriceUnit({
|
export default function PriceUnit({
|
||||||
price,
|
price,
|
||||||
className,
|
className,
|
||||||
small,
|
size = 'small',
|
||||||
conversion,
|
conversion,
|
||||||
symbol,
|
symbol,
|
||||||
type
|
type
|
||||||
@ -28,20 +25,14 @@ export default function PriceUnit({
|
|||||||
price: string
|
price: string
|
||||||
type?: string
|
type?: string
|
||||||
className?: string
|
className?: string
|
||||||
small?: boolean
|
size?: 'small' | 'mini' | 'large'
|
||||||
conversion?: boolean
|
conversion?: boolean
|
||||||
symbol?: string
|
symbol?: string
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const { locale } = useUserPreferences()
|
const { locale } = useUserPreferences()
|
||||||
|
|
||||||
const styleClasses = cx({
|
|
||||||
price: true,
|
|
||||||
small: small,
|
|
||||||
[className]: className
|
|
||||||
})
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styleClasses}>
|
<div className={`${styles.price} ${styles[size]} ${className}`}>
|
||||||
{type && type === 'free' ? (
|
{type && type === 'free' ? (
|
||||||
<div> Free </div>
|
<div> Free </div>
|
||||||
) : (
|
) : (
|
||||||
|
@ -9,21 +9,21 @@ export default function Price({
|
|||||||
accessDetails,
|
accessDetails,
|
||||||
orderPriceAndFees,
|
orderPriceAndFees,
|
||||||
className,
|
className,
|
||||||
small,
|
size,
|
||||||
conversion
|
conversion
|
||||||
}: {
|
}: {
|
||||||
accessDetails: AccessDetails
|
accessDetails: AccessDetails
|
||||||
orderPriceAndFees?: OrderPriceAndFees
|
orderPriceAndFees?: OrderPriceAndFees
|
||||||
className?: string
|
className?: string
|
||||||
small?: boolean
|
|
||||||
conversion?: boolean
|
conversion?: boolean
|
||||||
|
size?: 'small' | 'mini' | 'large'
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
return accessDetails?.price || accessDetails?.type === 'free' ? (
|
return accessDetails?.price || accessDetails?.type === 'free' ? (
|
||||||
<PriceUnit
|
<PriceUnit
|
||||||
price={`${orderPriceAndFees?.price || accessDetails?.price}`}
|
price={`${orderPriceAndFees?.price || accessDetails?.price}`}
|
||||||
symbol={accessDetails.baseToken?.symbol}
|
symbol={accessDetails.baseToken?.symbol}
|
||||||
className={className}
|
className={className}
|
||||||
small={small}
|
size={size}
|
||||||
conversion={conversion}
|
conversion={conversion}
|
||||||
type={accessDetails.type}
|
type={accessDetails.type}
|
||||||
/>
|
/>
|
||||||
|
@ -39,7 +39,7 @@ function Row({
|
|||||||
<PriceUnit
|
<PriceUnit
|
||||||
price={hasPreviousOrder || hasDatatoken ? '0' : `${price}`}
|
price={hasPreviousOrder || hasDatatoken ? '0' : `${price}`}
|
||||||
symbol={symbol}
|
symbol={symbol}
|
||||||
small
|
size="small"
|
||||||
className={styles.price}
|
className={styles.price}
|
||||||
/>
|
/>
|
||||||
<span className={styles.timeout}>
|
<span className={styles.timeout}>
|
||||||
@ -68,7 +68,8 @@ export default function PriceOutput({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.priceComponent}>
|
<div className={styles.priceComponent}>
|
||||||
You will pay <PriceUnit price={`${totalPrice}`} symbol={symbol} small />
|
You will pay{' '}
|
||||||
|
<PriceUnit price={`${totalPrice}`} symbol={symbol} size="small" />
|
||||||
<Tooltip
|
<Tooltip
|
||||||
content={
|
content={
|
||||||
<div className={styles.calculation}>
|
<div className={styles.calculation}>
|
||||||
|
@ -389,7 +389,7 @@ export default function Compute({
|
|||||||
<>
|
<>
|
||||||
<div className={styles.info}>
|
<div className={styles.info}>
|
||||||
<FileIcon file={file} isLoading={fileIsLoading} small />
|
<FileIcon file={file} isLoading={fileIsLoading} small />
|
||||||
<Price accessDetails={accessDetails} conversion />
|
<Price accessDetails={accessDetails} conversion size="large" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{ddo.metadata.type === 'algorithm' ? (
|
{ddo.metadata.type === 'algorithm' ? (
|
||||||
|
@ -258,6 +258,7 @@ export default function Download({
|
|||||||
accessDetails={asset.accessDetails}
|
accessDetails={asset.accessDetails}
|
||||||
orderPriceAndFees={orderPriceAndFees}
|
orderPriceAndFees={orderPriceAndFees}
|
||||||
conversion
|
conversion
|
||||||
|
size="large"
|
||||||
/>
|
/>
|
||||||
{!isInPurgatory && <PurchaseButton />}
|
{!isInPurgatory && <PurchaseButton />}
|
||||||
</div>
|
</div>
|
||||||
|
@ -34,3 +34,7 @@
|
|||||||
.noIcon {
|
.noIcon {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.token.mini {
|
||||||
|
font-size: var(--font-size-mini);
|
||||||
|
}
|
||||||
|
@ -6,20 +6,22 @@ import Logo from '@shared/atoms/Logo'
|
|||||||
export default function Token({
|
export default function Token({
|
||||||
symbol,
|
symbol,
|
||||||
balance,
|
balance,
|
||||||
noIcon
|
noIcon,
|
||||||
|
size
|
||||||
}: {
|
}: {
|
||||||
symbol: string
|
symbol: string
|
||||||
balance: string
|
balance: string
|
||||||
noIcon?: boolean
|
noIcon?: boolean
|
||||||
|
size?: 'small' | 'mini'
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
return (
|
return (
|
||||||
<div className={styles.token}>
|
<div className={`${styles.token} ${size ? styles[size] : ''}`}>
|
||||||
<figure
|
<figure
|
||||||
className={`${styles.icon} ${symbol} ${noIcon ? styles.noIcon : ''}`}
|
className={`${styles.icon} ${symbol} ${noIcon ? styles.noIcon : ''}`}
|
||||||
>
|
>
|
||||||
<Logo noWordmark />
|
<Logo noWordmark />
|
||||||
</figure>
|
</figure>
|
||||||
<PriceUnit price={balance} symbol={symbol} small />
|
<PriceUnit price={balance} symbol={symbol} size={size} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -12,31 +12,38 @@ export default function TokenList({
|
|||||||
datatokenValue,
|
datatokenValue,
|
||||||
datatokenSymbol,
|
datatokenSymbol,
|
||||||
conversion,
|
conversion,
|
||||||
highlight
|
highlight,
|
||||||
|
size = 'small'
|
||||||
}: {
|
}: {
|
||||||
title: string | ReactNode
|
title?: string | ReactNode
|
||||||
children?: ReactNode
|
children?: ReactNode
|
||||||
baseTokenValue: string
|
baseTokenValue: string
|
||||||
baseTokenSymbol: string
|
baseTokenSymbol: string
|
||||||
datatokenValue?: string
|
datatokenValue?: string
|
||||||
datatokenSymbol?: string
|
datatokenSymbol?: string
|
||||||
conversion: Decimal
|
conversion?: Decimal
|
||||||
highlight?: boolean
|
highlight?: boolean
|
||||||
|
size?: 'small' | 'mini'
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
return (
|
return (
|
||||||
<div className={`${styles.tokenlist} ${highlight ? styles.highlight : ''}`}>
|
<div className={`${styles.tokenlist} ${highlight ? styles.highlight : ''}`}>
|
||||||
<h3 className={styles.title}>{title}</h3>
|
{title && <h3 className={styles.title}>{title}</h3>}
|
||||||
<div className={styles.tokens}>
|
<div className={styles.tokens}>
|
||||||
<Token symbol={baseTokenSymbol} balance={baseTokenValue} />
|
<Token symbol={baseTokenSymbol} balance={baseTokenValue} size={size} />
|
||||||
{datatokenValue && (
|
|
||||||
<Token symbol={datatokenSymbol} balance={datatokenValue} />
|
{conversion?.greaterThan(0) && (
|
||||||
)}
|
|
||||||
{conversion.greaterThan(0) && (
|
|
||||||
<Conversion
|
<Conversion
|
||||||
price={conversion.toString()}
|
price={conversion.toString()}
|
||||||
className={styles.totalLiquidity}
|
className={styles.totalLiquidity}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{datatokenValue && (
|
||||||
|
<Token
|
||||||
|
symbol={datatokenSymbol}
|
||||||
|
balance={datatokenValue}
|
||||||
|
size={size}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -16,6 +16,7 @@ import PoolTransactions from '@shared/PoolTransactions'
|
|||||||
import Decimal from 'decimal.js'
|
import Decimal from 'decimal.js'
|
||||||
import content from '../../../../../content/price.json'
|
import content from '../../../../../content/price.json'
|
||||||
import { usePool } from '@context/Pool'
|
import { usePool } from '@context/Pool'
|
||||||
|
import Token from './Token'
|
||||||
|
|
||||||
export default function Pool(): ReactElement {
|
export default function Pool(): ReactElement {
|
||||||
const { accountId } = useWeb3()
|
const { accountId } = useWeb3()
|
||||||
@ -65,10 +66,16 @@ export default function Pool(): ReactElement {
|
|||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<div className={styles.dataToken}>
|
<div className={styles.dataToken}>
|
||||||
<PriceUnit price="1" symbol={poolInfo?.datatokenSymbol} /> ={' '}
|
<PriceUnit
|
||||||
|
price="1"
|
||||||
|
symbol={poolInfo?.datatokenSymbol}
|
||||||
|
size="large"
|
||||||
|
/>{' '}
|
||||||
|
={' '}
|
||||||
<PriceUnit
|
<PriceUnit
|
||||||
price={`${poolData?.spotPrice}`}
|
price={`${poolData?.spotPrice}`}
|
||||||
symbol={poolInfo?.baseTokenSymbol}
|
symbol={poolInfo?.baseTokenSymbol}
|
||||||
|
size="large"
|
||||||
/>
|
/>
|
||||||
<Tooltip content={content.pool.tooltips.price} />
|
<Tooltip content={content.pool.tooltips.price} />
|
||||||
<div className={styles.dataTokenLinks}>
|
<div className={styles.dataTokenLinks}>
|
||||||
@ -90,7 +97,6 @@ export default function Pool(): ReactElement {
|
|||||||
</ExplorerLink>
|
</ExplorerLink>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<TokenList
|
<TokenList
|
||||||
title={
|
title={
|
||||||
<>
|
<>
|
||||||
@ -113,11 +119,10 @@ export default function Pool(): ReactElement {
|
|||||||
conversion={poolInfoUser?.liquidity}
|
conversion={poolInfoUser?.liquidity}
|
||||||
highlight
|
highlight
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TokenList
|
<TokenList
|
||||||
title={
|
title={
|
||||||
<>
|
<>
|
||||||
Owner Liquidity
|
Owner Value Locked
|
||||||
<span className={styles.titleInfo}>
|
<span className={styles.titleInfo}>
|
||||||
{poolInfoOwner?.poolShare}% of pool
|
{poolInfoOwner?.poolShare}% of pool
|
||||||
</span>
|
</span>
|
||||||
@ -127,7 +132,6 @@ export default function Pool(): ReactElement {
|
|||||||
baseTokenSymbol={poolInfo?.baseTokenSymbol}
|
baseTokenSymbol={poolInfo?.baseTokenSymbol}
|
||||||
conversion={poolInfoOwner?.liquidity}
|
conversion={poolInfoOwner?.liquidity}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TokenList
|
<TokenList
|
||||||
title={
|
title={
|
||||||
<>
|
<>
|
||||||
@ -143,21 +147,41 @@ export default function Pool(): ReactElement {
|
|||||||
<Graph poolSnapshots={poolSnapshots} />
|
<Graph poolSnapshots={poolSnapshots} />
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
baseTokenValue={`${poolInfo?.totalLiquidityInOcean}`}
|
||||||
|
baseTokenSymbol={poolInfo?.baseTokenSymbol}
|
||||||
|
conversion={poolInfo?.totalLiquidityInOcean}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TokenList
|
||||||
|
size="mini"
|
||||||
baseTokenValue={`${poolData?.baseTokenLiquidity}`}
|
baseTokenValue={`${poolData?.baseTokenLiquidity}`}
|
||||||
baseTokenSymbol={poolInfo?.baseTokenSymbol}
|
baseTokenSymbol={poolInfo?.baseTokenSymbol}
|
||||||
datatokenValue={`${poolData?.datatokenLiquidity}`}
|
datatokenValue={`${poolData?.datatokenLiquidity}`}
|
||||||
datatokenSymbol={poolInfo?.datatokenSymbol}
|
datatokenSymbol={poolInfo?.datatokenSymbol}
|
||||||
conversion={poolInfo?.totalLiquidityInOcean}
|
|
||||||
>
|
>
|
||||||
{/* <Token symbol="% pool fee" balance={poolInfo?.poolFee} noIcon />
|
<Token
|
||||||
<Token symbol="% market fee" balance={poolInfo?.marketFee} noIcon />
|
symbol="% pool fee"
|
||||||
<Token symbol="% OPF fee" balance={poolInfo?.opfFee} noIcon /> */}
|
balance={poolInfo?.liquidityProviderSwapFee}
|
||||||
|
noIcon
|
||||||
|
size="mini"
|
||||||
|
/>
|
||||||
|
<Token
|
||||||
|
symbol="% market fee"
|
||||||
|
balance={poolInfo?.publishMarketSwapFee}
|
||||||
|
noIcon
|
||||||
|
size="mini"
|
||||||
|
/>
|
||||||
|
<Token
|
||||||
|
symbol="% OPF fee"
|
||||||
|
balance={poolInfo?.opcFee}
|
||||||
|
noIcon
|
||||||
|
size="mini"
|
||||||
|
/>
|
||||||
</TokenList>
|
</TokenList>
|
||||||
|
|
||||||
<div className={styles.update}>
|
<div className={styles.update}>
|
||||||
Fetching every {refreshInterval / 1000} sec.
|
Fetching every {refreshInterval / 1000} sec.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={stylesActions.actions}>
|
<div className={stylesActions.actions}>
|
||||||
<Button
|
<Button
|
||||||
style="primary"
|
style="primary"
|
||||||
@ -178,7 +202,6 @@ export default function Pool(): ReactElement {
|
|||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{accountId && (
|
{accountId && (
|
||||||
<AssetActionHistoryTable title="Your Pool Transactions">
|
<AssetActionHistoryTable title="Your Pool Transactions">
|
||||||
<PoolTransactions
|
<PoolTransactions
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
import { isValidNumber } from '@utils/numbers'
|
|
||||||
import Decimal from 'decimal.js'
|
|
||||||
|
|
||||||
Decimal.set({ toExpNeg: -18, precision: 18, rounding: 1 })
|
|
||||||
|
|
||||||
export async function getMaxPercentRemove(
|
|
||||||
poolAddress: string,
|
|
||||||
poolTokens: string
|
|
||||||
): Promise<string> {
|
|
||||||
// const amountMaxOcean = await ocean.pool.getOceanMaxRemoveLiquidity(
|
|
||||||
// poolAddress
|
|
||||||
// )
|
|
||||||
|
|
||||||
// const amountMaxPoolShares =
|
|
||||||
// await ocean.pool.getPoolSharesRequiredToRemoveOcean(
|
|
||||||
// poolAddress,
|
|
||||||
// amountMaxOcean
|
|
||||||
// )
|
|
||||||
|
|
||||||
// let amountMaxPercent =
|
|
||||||
// isValidNumber(amountMaxPoolShares) && isValidNumber(poolTokens)
|
|
||||||
// ? new Decimal(amountMaxPoolShares)
|
|
||||||
// .dividedBy(new Decimal(poolTokens))
|
|
||||||
// .mul(100)
|
|
||||||
// .floor()
|
|
||||||
// .toString()
|
|
||||||
// : '0'
|
|
||||||
|
|
||||||
// if (Number(amountMaxPercent) > 100) {
|
|
||||||
// amountMaxPercent = '100'
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return amountMaxPercent
|
|
||||||
return '0'
|
|
||||||
}
|
|
@ -14,7 +14,7 @@ function UserLiquidityLine({
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<span>{title}</span>
|
<span>{title}</span>
|
||||||
<PriceUnit price={amount} symbol={symbol} small />
|
<PriceUnit price={amount} symbol={symbol} size="small" />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ export default function MarketStatsTooltip({
|
|||||||
<PriceUnit
|
<PriceUnit
|
||||||
price={totalOceanLiquidity?.[chainId] || '0'}
|
price={totalOceanLiquidity?.[chainId] || '0'}
|
||||||
symbol="OCEAN"
|
symbol="OCEAN"
|
||||||
small
|
size="small"
|
||||||
/>
|
/>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
|
@ -21,8 +21,12 @@ export default function MarketStatsTotal({
|
|||||||
/>{' '}
|
/>{' '}
|
||||||
<abbr title="Total Value Locked">TVL</abbr> across{' '}
|
<abbr title="Total Value Locked">TVL</abbr> across{' '}
|
||||||
<strong>{total.pools}</strong> asset pools that contain{' '}
|
<strong>{total.pools}</strong> asset pools that contain{' '}
|
||||||
<PriceUnit price={`${total.totalOceanLiquidity}`} symbol="OCEAN" small />,
|
<PriceUnit
|
||||||
plus datatokens for each pool.
|
price={`${total.totalOceanLiquidity}`}
|
||||||
|
symbol="OCEAN"
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
, plus datatokens for each pool.
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ const columns = [
|
|||||||
{
|
{
|
||||||
name: 'Price',
|
name: 'Price',
|
||||||
selector: function getAssetRow(row: AssetExtended) {
|
selector: function getAssetRow(row: AssetExtended) {
|
||||||
return <Price accessDetails={row.accessDetails} small />
|
return <Price accessDetails={row.accessDetails} size="small" />
|
||||||
},
|
},
|
||||||
right: true
|
right: true
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,10 @@ function SectionQueryResult({
|
|||||||
const [loading, setLoading] = useState<boolean>()
|
const [loading, setLoading] = useState<boolean>()
|
||||||
const isMounted = useIsMounted()
|
const isMounted = useIsMounted()
|
||||||
const newCancelToken = useCancelToken()
|
const newCancelToken = useCancelToken()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!query) return
|
||||||
|
|
||||||
async function init() {
|
async function init() {
|
||||||
if (chainIds.length === 0) {
|
if (chainIds.length === 0) {
|
||||||
const result: PagedAssets = {
|
const result: PagedAssets = {
|
||||||
@ -91,11 +94,13 @@ function SectionQueryResult({
|
|||||||
return (
|
return (
|
||||||
<section className={styles.section}>
|
<section className={styles.section}>
|
||||||
<h3>{title}</h3>
|
<h3>{title}</h3>
|
||||||
|
|
||||||
<AssetList
|
<AssetList
|
||||||
assets={result?.results}
|
assets={result?.results}
|
||||||
showPagination={false}
|
showPagination={false}
|
||||||
isLoading={loading}
|
isLoading={loading || !query}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{action && action}
|
{action && action}
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
@ -130,28 +135,24 @@ export default function HomePage(): ReactElement {
|
|||||||
<Bookmarks />
|
<Bookmarks />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{queryAndDids && (
|
<SectionQueryResult
|
||||||
<SectionQueryResult
|
title="Highest Liquidity"
|
||||||
title="Highest Liquidity"
|
query={queryAndDids?.[0]}
|
||||||
query={queryAndDids[0]}
|
queryData={queryAndDids?.[1]}
|
||||||
queryData={queryAndDids[1]}
|
/>
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{queryLatest && (
|
<SectionQueryResult
|
||||||
<SectionQueryResult
|
title="Recently Published"
|
||||||
title="Recently Published"
|
query={queryLatest}
|
||||||
query={queryLatest}
|
action={
|
||||||
action={
|
<Button
|
||||||
<Button
|
style="text"
|
||||||
style="text"
|
to="/search?sort=metadata.created&sortOrder=desc"
|
||||||
to="/search?sort=metadata.created&sortOrder=desc"
|
>
|
||||||
>
|
All data sets and algorithms →
|
||||||
All data sets and algorithms →
|
</Button>
|
||||||
</Button>
|
}
|
||||||
}
|
/>
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ import React, { ReactElement } from 'react'
|
|||||||
import { useUserPreferences } from '@context/UserPreferences'
|
import { useUserPreferences } from '@context/UserPreferences'
|
||||||
import ExplorerLink from '@shared/ExplorerLink'
|
import ExplorerLink from '@shared/ExplorerLink'
|
||||||
import NetworkName from '@shared/NetworkName'
|
import NetworkName from '@shared/NetworkName'
|
||||||
import jellyfish from '@oceanprotocol/art/creatures/jellyfish/jellyfish-grid.svg'
|
import Jellyfish from '@oceanprotocol/art/creatures/jellyfish/jellyfish-grid.svg'
|
||||||
import Copy from '@shared/atoms/Copy'
|
import Copy from '@shared/atoms/Copy'
|
||||||
import Blockies from '@shared/atoms/Blockies'
|
import Blockies from '@shared/atoms/Blockies'
|
||||||
import styles from './Account.module.css'
|
import styles from './Account.module.css'
|
||||||
@ -29,12 +29,7 @@ export default function Account({
|
|||||||
) : accountId ? (
|
) : accountId ? (
|
||||||
<Blockies accountId={accountId} className={styles.image} />
|
<Blockies accountId={accountId} className={styles.image} />
|
||||||
) : (
|
) : (
|
||||||
<img
|
<Jellyfish className={styles.image} />
|
||||||
src={jellyfish}
|
|
||||||
className={styles.image}
|
|
||||||
width="96"
|
|
||||||
height="96"
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
|
@ -1,28 +1,32 @@
|
|||||||
import { LoggerInstance } from '@oceanprotocol/lib'
|
import { LoggerInstance } from '@oceanprotocol/lib'
|
||||||
import React, { useEffect, useState, ReactElement } from 'react'
|
import React, { useEffect, useState, ReactElement } from 'react'
|
||||||
import { useUserPreferences } from '@context/UserPreferences'
|
import { useUserPreferences } from '@context/UserPreferences'
|
||||||
import {
|
import { getAccountTVLInOwnAssets, UserLiquidity } from '@utils/subgraph'
|
||||||
getAccountLiquidityInOwnAssets,
|
|
||||||
UserLiquidity,
|
|
||||||
calculateUserLiquidity
|
|
||||||
} from '@utils/subgraph'
|
|
||||||
import Conversion from '@shared/Price/Conversion'
|
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/subgraph/PoolShares'
|
import { PoolShares_poolShares as PoolShare } from '../../../@types/subgraph/PoolShares'
|
||||||
import { getAccessDetailsForAssets } from '@utils/accessDetailsAndPricing'
|
import { getAccessDetailsForAssets } from '@utils/accessDetailsAndPricing'
|
||||||
|
import { calculateUserTVL } from '@utils/pool'
|
||||||
|
import Decimal from 'decimal.js'
|
||||||
|
import { MAX_DECIMALS } from '@utils/constants'
|
||||||
|
|
||||||
async function getPoolSharesLiquidity(
|
async function getPoolSharesLiquidity(
|
||||||
poolShares: PoolShare[]
|
poolShares: PoolShare[]
|
||||||
): Promise<number> {
|
): Promise<string> {
|
||||||
let totalLiquidity = 0
|
let tvl = new Decimal(0)
|
||||||
|
|
||||||
for (const poolShare of poolShares) {
|
for (const poolShare of poolShares) {
|
||||||
const poolLiquidity = calculateUserLiquidity(poolShare)
|
const poolUserTvl = calculateUserTVL(
|
||||||
totalLiquidity += poolLiquidity
|
poolShare.shares,
|
||||||
|
poolShare.pool.totalShares,
|
||||||
|
poolShare.pool.baseTokenLiquidity
|
||||||
|
)
|
||||||
|
tvl = tvl.add(new Decimal(poolUserTvl))
|
||||||
}
|
}
|
||||||
|
|
||||||
return totalLiquidity
|
return tvl.toDecimalPlaces(MAX_DECIMALS).toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Stats({
|
export default function Stats({
|
||||||
@ -33,13 +37,13 @@ export default function Stats({
|
|||||||
const { chainIds } = useUserPreferences()
|
const { chainIds } = useUserPreferences()
|
||||||
const { poolShares, assets, assetsTotal, sales } = useProfile()
|
const { poolShares, assets, assetsTotal, sales } = useProfile()
|
||||||
|
|
||||||
const [publisherLiquidity, setPublisherLiquidity] = useState<UserLiquidity>()
|
const [publisherTvl, setPublisherTvl] = useState('0')
|
||||||
const [totalLiquidity, setTotalLiquidity] = useState(0)
|
const [totalTvl, setTotalTvl] = useState('0')
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!accountId || chainIds.length === 0) {
|
if (!accountId || chainIds.length === 0) {
|
||||||
setPublisherLiquidity({ price: '0', oceanBalance: '0' })
|
setPublisherTvl('0')
|
||||||
setTotalLiquidity(0)
|
setTotalTvl('0')
|
||||||
}
|
}
|
||||||
}, [accountId, chainIds])
|
}, [accountId, chainIds])
|
||||||
|
|
||||||
@ -57,12 +61,12 @@ export default function Stats({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const userLiquidity = await getAccountLiquidityInOwnAssets(
|
const userTvl = await getAccountTVLInOwnAssets(
|
||||||
accountId,
|
accountId,
|
||||||
chainIds,
|
chainIds,
|
||||||
accountPoolAdresses
|
accountPoolAdresses
|
||||||
)
|
)
|
||||||
setPublisherLiquidity(userLiquidity)
|
setPublisherTvl(userTvl)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
LoggerInstance.error(error.message)
|
LoggerInstance.error(error.message)
|
||||||
}
|
}
|
||||||
@ -75,10 +79,10 @@ export default function Stats({
|
|||||||
|
|
||||||
async function getTotalLiquidity() {
|
async function getTotalLiquidity() {
|
||||||
try {
|
try {
|
||||||
const totalLiquidity = await getPoolSharesLiquidity(poolShares)
|
const totalTvl = await getPoolSharesLiquidity(poolShares)
|
||||||
setTotalLiquidity(totalLiquidity)
|
setTotalTvl(totalTvl)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching pool shares: ', error.message)
|
LoggerInstance.error('Error fetching pool shares: ', error.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getTotalLiquidity()
|
getTotalLiquidity()
|
||||||
@ -87,14 +91,12 @@ export default function Stats({
|
|||||||
return (
|
return (
|
||||||
<div className={styles.stats}>
|
<div className={styles.stats}>
|
||||||
<NumberUnit
|
<NumberUnit
|
||||||
label="Liquidity in Own Assets"
|
label="TVL in Own Assets"
|
||||||
value={
|
value={<Conversion price={publisherTvl} hideApproximateSymbol />}
|
||||||
<Conversion price={publisherLiquidity?.price} hideApproximateSymbol />
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<NumberUnit
|
<NumberUnit
|
||||||
label="Total Liquidity"
|
label="TVL"
|
||||||
value={<Conversion price={`${totalLiquidity}`} hideApproximateSymbol />}
|
value={<Conversion price={totalTvl} hideApproximateSymbol />}
|
||||||
/>
|
/>
|
||||||
<NumberUnit label={`Sale${sales === 1 ? '' : 's'}`} value={sales} />
|
<NumberUnit label={`Sale${sales === 1 ? '' : 's'}`} value={sales} />
|
||||||
<NumberUnit label="Published" value={assetsTotal} />
|
<NumberUnit label="Published" value={assetsTotal} />
|
||||||
|
@ -1,60 +0,0 @@
|
|||||||
.totalLiquidity {
|
|
||||||
margin-bottom: 0;
|
|
||||||
font-weight: var(--font-weight-base) !important;
|
|
||||||
font-size: var(--font-size-small);
|
|
||||||
padding-left: var(--font-size-base);
|
|
||||||
}
|
|
||||||
|
|
||||||
.totalLiquidity strong {
|
|
||||||
font-size: var(--font-size-base);
|
|
||||||
color: var(--font-color-text);
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.poolSharesTable [role='gridcell'] {
|
|
||||||
align-items: flex-start;
|
|
||||||
margin: calc(var(--spacer) / 2) 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.poolSharesTable [class*='AssetListTitle-module--title'] {
|
|
||||||
line-height: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.poolSharesTable [class*='Token-module--token'] div {
|
|
||||||
color: var(--color-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 30rem) {
|
|
||||||
.poolSharesTable [class*='AssetListTitle-module--title'] {
|
|
||||||
line-height: 0 !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.userLiquidity {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-end;
|
|
||||||
}
|
|
||||||
|
|
||||||
.userLiquidity [class*='Conversion-module--'] {
|
|
||||||
margin-bottom: calc(var(--spacer) / 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
.userLiquidity [class*='Conversion-module--'] strong {
|
|
||||||
font-size: var(--font-size-base);
|
|
||||||
}
|
|
||||||
|
|
||||||
.userLiquidity [class*='Token-module--token'] {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-end;
|
|
||||||
margin-bottom: calc(var(--spacer) / 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
.userLiquidity [class*='Token-module--token'] div {
|
|
||||||
font-size: var(--font-size-small);
|
|
||||||
}
|
|
||||||
|
|
||||||
.userLiquidity [class*='Token-module--icon'] {
|
|
||||||
display: none;
|
|
||||||
}
|
|
@ -1,229 +0,0 @@
|
|||||||
import React, { ReactElement, useCallback, useEffect, useState } from 'react'
|
|
||||||
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 } from '../../../@types/subgraph/PoolShares'
|
|
||||||
import web3 from 'web3'
|
|
||||||
import Token from '../../Asset/AssetActions/Pool/Token'
|
|
||||||
import { calculateUserLiquidity } from '@utils/subgraph'
|
|
||||||
import NetworkName from '@shared/NetworkName'
|
|
||||||
import { retrieveDDOListByDIDs } from '@utils/aquarius'
|
|
||||||
import { CancelToken } from 'axios'
|
|
||||||
import { isValidNumber } from '@utils/numbers'
|
|
||||||
import Decimal from 'decimal.js'
|
|
||||||
import { useProfile } from '@context/Profile'
|
|
||||||
import { useCancelToken } from '@hooks/useCancelToken'
|
|
||||||
import { useIsMounted } from '@hooks/useIsMounted'
|
|
||||||
import { useUserPreferences } from '@context/UserPreferences'
|
|
||||||
import { Asset } from '@oceanprotocol/lib'
|
|
||||||
|
|
||||||
Decimal.set({ toExpNeg: -18, precision: 18, rounding: 1 })
|
|
||||||
|
|
||||||
const REFETCH_INTERVAL = 20000
|
|
||||||
|
|
||||||
interface AssetPoolShare {
|
|
||||||
userLiquidity: number
|
|
||||||
poolShare: PoolShare
|
|
||||||
networkId: number
|
|
||||||
createTime: number
|
|
||||||
asset: Asset
|
|
||||||
}
|
|
||||||
|
|
||||||
function Liquidity({ row, type }: { row: AssetPoolShare; type: string }) {
|
|
||||||
let price = ``
|
|
||||||
let oceanTokenBalance = ''
|
|
||||||
let dataTokenBalance = ''
|
|
||||||
if (type === 'user') {
|
|
||||||
price = `${row.userLiquidity}`
|
|
||||||
const userShare = row.poolShare.shares / row.poolShare.pool.totalShares
|
|
||||||
oceanTokenBalance = (
|
|
||||||
userShare * row.poolShare.pool.baseTokenLiquidity
|
|
||||||
).toString()
|
|
||||||
dataTokenBalance = (
|
|
||||||
userShare * row.poolShare.pool.datatokenLiquidity
|
|
||||||
).toString()
|
|
||||||
}
|
|
||||||
if (type === 'pool') {
|
|
||||||
price =
|
|
||||||
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.pool.baseTokenLiquidity.toString()
|
|
||||||
dataTokenBalance = row.poolShare.pool.datatokenLiquidity.toString()
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div className={styles.userLiquidity}>
|
|
||||||
<Conversion
|
|
||||||
price={price}
|
|
||||||
className={styles.totalLiquidity}
|
|
||||||
hideApproximateSymbol
|
|
||||||
/>
|
|
||||||
<Token
|
|
||||||
symbol={row.poolShare.pool.baseToken.symbol}
|
|
||||||
balance={oceanTokenBalance}
|
|
||||||
noIcon
|
|
||||||
/>
|
|
||||||
<Token
|
|
||||||
symbol={row.poolShare.pool.datatoken.symbol}
|
|
||||||
balance={dataTokenBalance}
|
|
||||||
noIcon
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const columns = [
|
|
||||||
{
|
|
||||||
name: 'Data Set',
|
|
||||||
selector: function getAssetRow(row: AssetPoolShare) {
|
|
||||||
return <AssetTitle asset={row.asset} />
|
|
||||||
},
|
|
||||||
grow: 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Network',
|
|
||||||
selector: function getNetwork(row: AssetPoolShare) {
|
|
||||||
return <NetworkName networkId={row.networkId} />
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Datatoken',
|
|
||||||
selector: function getSymbol(row: AssetPoolShare) {
|
|
||||||
return <>{row.poolShare.pool.datatoken.symbol}</>
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Liquidity',
|
|
||||||
selector: function getAssetRow(row: AssetPoolShare) {
|
|
||||||
return <Liquidity row={row} type="user" />
|
|
||||||
},
|
|
||||||
right: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Pool Liquidity',
|
|
||||||
selector: function getAssetRow(row: AssetPoolShare) {
|
|
||||||
return <Liquidity row={row} type="pool" />
|
|
||||||
},
|
|
||||||
right: true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
async function getPoolSharesAssets(
|
|
||||||
data: PoolShare[],
|
|
||||||
chainIds: number[],
|
|
||||||
cancelToken: CancelToken
|
|
||||||
) {
|
|
||||||
if (data.length < 1) return
|
|
||||||
|
|
||||||
const assetList: AssetPoolShare[] = []
|
|
||||||
const didList: string[] = []
|
|
||||||
|
|
||||||
for (let i = 0; i < data.length; i++) {
|
|
||||||
const did = web3.utils
|
|
||||||
.toChecksumAddress(data[i].pool.datatoken.address)
|
|
||||||
.replace('0x', 'did:op:')
|
|
||||||
didList.push(did)
|
|
||||||
}
|
|
||||||
const ddoList = await retrieveDDOListByDIDs(didList, chainIds, cancelToken)
|
|
||||||
|
|
||||||
for (let i = 0; i < data.length; i++) {
|
|
||||||
const userLiquidity = calculateUserLiquidity(data[i])
|
|
||||||
assetList.push({
|
|
||||||
poolShare: data[i],
|
|
||||||
userLiquidity: userLiquidity,
|
|
||||||
networkId: ddoList[i].chainId,
|
|
||||||
createTime: data[i].pool.createdTimestamp,
|
|
||||||
asset: ddoList[i]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
const assets = assetList.sort((a, b) => b.createTime - a.createTime)
|
|
||||||
return assets
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function PoolShares({
|
|
||||||
accountId
|
|
||||||
}: {
|
|
||||||
accountId: string
|
|
||||||
}): ReactElement {
|
|
||||||
const { poolShares, isPoolSharesLoading } = useProfile()
|
|
||||||
const [assets, setAssets] = useState<AssetPoolShare[]>()
|
|
||||||
const [loading, setLoading] = useState<boolean>(false)
|
|
||||||
const [dataFetchInterval, setDataFetchInterval] = useState<NodeJS.Timeout>()
|
|
||||||
const { chainIds } = useUserPreferences()
|
|
||||||
const newCancelToken = useCancelToken()
|
|
||||||
const isMounted = useIsMounted()
|
|
||||||
|
|
||||||
const fetchPoolSharesAssets = useCallback(
|
|
||||||
async (
|
|
||||||
chainIds: number[],
|
|
||||||
poolShares: PoolShare[],
|
|
||||||
cancelToken: CancelToken
|
|
||||||
) => {
|
|
||||||
try {
|
|
||||||
const assets = await getPoolSharesAssets(
|
|
||||||
poolShares,
|
|
||||||
chainIds,
|
|
||||||
cancelToken
|
|
||||||
)
|
|
||||||
setAssets(assets)
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error fetching pool shares: ', error.message)
|
|
||||||
} finally {
|
|
||||||
setLoading(false)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[]
|
|
||||||
)
|
|
||||||
// do not add chainIds,dataFetchInterval to effect dep
|
|
||||||
useEffect(() => {
|
|
||||||
const cancelToken = newCancelToken()
|
|
||||||
async function init() {
|
|
||||||
setLoading(true)
|
|
||||||
|
|
||||||
if (!poolShares || isPoolSharesLoading || !chainIds || !isMounted())
|
|
||||||
return
|
|
||||||
await fetchPoolSharesAssets(chainIds, poolShares, cancelToken)
|
|
||||||
setLoading(false)
|
|
||||||
|
|
||||||
if (dataFetchInterval) return
|
|
||||||
|
|
||||||
const interval = setInterval(async () => {
|
|
||||||
await fetchPoolSharesAssets(chainIds, poolShares, cancelToken)
|
|
||||||
}, REFETCH_INTERVAL)
|
|
||||||
setDataFetchInterval(interval)
|
|
||||||
}
|
|
||||||
init()
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
clearInterval(dataFetchInterval)
|
|
||||||
}
|
|
||||||
}, [
|
|
||||||
fetchPoolSharesAssets,
|
|
||||||
isPoolSharesLoading,
|
|
||||||
newCancelToken,
|
|
||||||
poolShares,
|
|
||||||
isMounted
|
|
||||||
])
|
|
||||||
|
|
||||||
return accountId ? (
|
|
||||||
<Table
|
|
||||||
columns={columns}
|
|
||||||
className={styles.poolSharesTable}
|
|
||||||
data={assets}
|
|
||||||
pagination
|
|
||||||
paginationPerPage={5}
|
|
||||||
isLoading={loading}
|
|
||||||
sortField="userLiquidity"
|
|
||||||
sortAsc={false}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<div>Please connect your Web3 wallet.</div>
|
|
||||||
)
|
|
||||||
}
|
|
@ -0,0 +1,37 @@
|
|||||||
|
.totalLiquidity {
|
||||||
|
margin-bottom: 0;
|
||||||
|
font-weight: var(--font-weight-base) !important;
|
||||||
|
font-size: var(--font-size-small);
|
||||||
|
padding-left: var(--font-size-base);
|
||||||
|
}
|
||||||
|
|
||||||
|
.totalLiquidity strong {
|
||||||
|
font-size: var(--font-size-base);
|
||||||
|
color: var(--font-color-text);
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.userLiquidity {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.userLiquidity [class*='Conversion_conversion'] {
|
||||||
|
margin-bottom: calc(var(--spacer) / 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.userLiquidity [class*='Conversion_conversion'] strong {
|
||||||
|
font-size: var(--font-size-base);
|
||||||
|
}
|
||||||
|
|
||||||
|
.userLiquidity [class*='Token_token'] {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-bottom: calc(var(--spacer) / 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.userLiquidity [class*='Token_token'] div {
|
||||||
|
font-size: var(--font-size-small);
|
||||||
|
}
|
59
src/components/Profile/History/PoolShares/Liquidity.tsx
Normal file
59
src/components/Profile/History/PoolShares/Liquidity.tsx
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import Conversion from '@shared/Price/Conversion'
|
||||||
|
import styles from './Liquidity.module.css'
|
||||||
|
import Token from '../../../Asset/AssetActions/Pool/Token'
|
||||||
|
import { isValidNumber } from '@utils/numbers'
|
||||||
|
import Decimal from 'decimal.js'
|
||||||
|
import { AssetPoolShare } from './index'
|
||||||
|
import { calculateUserTVL } from '@utils/pool'
|
||||||
|
|
||||||
|
export function Liquidity({
|
||||||
|
row,
|
||||||
|
type
|
||||||
|
}: {
|
||||||
|
row: AssetPoolShare
|
||||||
|
type: string
|
||||||
|
}) {
|
||||||
|
let price = '0'
|
||||||
|
let liquidity = '0'
|
||||||
|
|
||||||
|
if (type === 'user') {
|
||||||
|
price = new Decimal(row.userLiquidity).mul(2).toString()
|
||||||
|
|
||||||
|
// Liquidity in base token, calculated from pool share tokens.
|
||||||
|
liquidity = calculateUserTVL(
|
||||||
|
row.poolShare.shares,
|
||||||
|
row.poolShare.pool.totalShares,
|
||||||
|
row.poolShare.pool.baseTokenLiquidity
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (type === 'pool') {
|
||||||
|
price =
|
||||||
|
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'
|
||||||
|
|
||||||
|
liquidity = new Decimal(row.poolShare.pool.baseTokenLiquidity)
|
||||||
|
.mul(2)
|
||||||
|
.toString()
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className={styles.userLiquidity}>
|
||||||
|
<Conversion
|
||||||
|
price={price}
|
||||||
|
className={styles.totalLiquidity}
|
||||||
|
hideApproximateSymbol
|
||||||
|
/>
|
||||||
|
<Token
|
||||||
|
symbol={row.poolShare.pool.baseToken.symbol}
|
||||||
|
balance={liquidity}
|
||||||
|
noIcon
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
49
src/components/Profile/History/PoolShares/_utils.ts
Normal file
49
src/components/Profile/History/PoolShares/_utils.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import { getAssetsFromDtList } from '@utils/aquarius'
|
||||||
|
import { calculateUserLiquidity } from '@utils/pool'
|
||||||
|
import { CancelToken } from 'axios'
|
||||||
|
import { PoolShares_poolShares as PoolShare } from '../../../../@types/subgraph/PoolShares'
|
||||||
|
import { AssetPoolShare } from '.'
|
||||||
|
import { Asset } from '@oceanprotocol/lib'
|
||||||
|
|
||||||
|
function getAsset(items: Asset[], datatoken: string): Asset {
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
if (
|
||||||
|
items[i].datatokens[0].address.toLowerCase() === datatoken.toLowerCase()
|
||||||
|
)
|
||||||
|
return items[i]
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getAssetsFromPoolShares(
|
||||||
|
data: PoolShare[],
|
||||||
|
chainIds: number[],
|
||||||
|
cancelToken: CancelToken
|
||||||
|
) {
|
||||||
|
if (data.length < 1) return []
|
||||||
|
|
||||||
|
const assetList: AssetPoolShare[] = []
|
||||||
|
const dtList: string[] = []
|
||||||
|
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
dtList.push(data[i].pool.datatoken.address)
|
||||||
|
}
|
||||||
|
const ddoList = await getAssetsFromDtList(dtList, chainIds, cancelToken)
|
||||||
|
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
const userLiquidity = calculateUserLiquidity(
|
||||||
|
data[i].shares,
|
||||||
|
data[i].pool.totalShares,
|
||||||
|
data[i].pool.baseTokenLiquidity
|
||||||
|
)
|
||||||
|
console.log(data[i].pool.datatoken.address, userLiquidity)
|
||||||
|
assetList.push({
|
||||||
|
poolShare: data[i],
|
||||||
|
userLiquidity,
|
||||||
|
networkId: getAsset(ddoList, data[i].pool.datatoken.address).chainId,
|
||||||
|
createTime: data[i].pool.createdTimestamp,
|
||||||
|
asset: getAsset(ddoList, data[i].pool.datatoken.address)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return assetList
|
||||||
|
}
|
18
src/components/Profile/History/PoolShares/index.module.css
Normal file
18
src/components/Profile/History/PoolShares/index.module.css
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
.poolSharesTable [role='gridcell'] {
|
||||||
|
align-items: flex-start;
|
||||||
|
margin: calc(var(--spacer) / 2) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.poolSharesTable [class*='AssetListTitle_title'] {
|
||||||
|
line-height: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.poolSharesTable [class*='Token_token'] div {
|
||||||
|
color: var(--color-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 30rem) {
|
||||||
|
.poolSharesTable [class*='AssetListTitle_title'] {
|
||||||
|
line-height: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
116
src/components/Profile/History/PoolShares/index.tsx
Normal file
116
src/components/Profile/History/PoolShares/index.tsx
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
import React, { ReactElement, useCallback, useEffect, useState } from 'react'
|
||||||
|
import Table from '@shared/atoms/Table'
|
||||||
|
import styles from './index.module.css'
|
||||||
|
import AssetTitle from '@shared/AssetList/AssetListTitle'
|
||||||
|
import { PoolShares_poolShares as PoolShare } from '../../../../@types/subgraph/PoolShares'
|
||||||
|
import NetworkName from '@shared/NetworkName'
|
||||||
|
import Decimal from 'decimal.js'
|
||||||
|
import { useProfile } from '@context/Profile'
|
||||||
|
import { useCancelToken } from '@hooks/useCancelToken'
|
||||||
|
import { useIsMounted } from '@hooks/useIsMounted'
|
||||||
|
import { useUserPreferences } from '@context/UserPreferences'
|
||||||
|
import { Asset, LoggerInstance } from '@oceanprotocol/lib'
|
||||||
|
import { Liquidity } from './Liquidity'
|
||||||
|
import { getAssetsFromPoolShares } from './_utils'
|
||||||
|
|
||||||
|
Decimal.set({ toExpNeg: -18, precision: 18, rounding: 1 })
|
||||||
|
|
||||||
|
export interface AssetPoolShare {
|
||||||
|
userLiquidity: string
|
||||||
|
poolShare: PoolShare
|
||||||
|
networkId: number
|
||||||
|
createTime: number
|
||||||
|
asset: Asset
|
||||||
|
}
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
name: 'Data Set',
|
||||||
|
selector: function getAssetRow(row: AssetPoolShare) {
|
||||||
|
return <AssetTitle asset={row.asset} />
|
||||||
|
},
|
||||||
|
grow: 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Network',
|
||||||
|
selector: function getNetwork(row: AssetPoolShare) {
|
||||||
|
return <NetworkName networkId={row.networkId} />
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Your Value Locked',
|
||||||
|
selector: function getAssetRow(row: AssetPoolShare) {
|
||||||
|
return <Liquidity row={row} type="user" />
|
||||||
|
},
|
||||||
|
right: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Total Value Locked',
|
||||||
|
selector: function getAssetRow(row: AssetPoolShare) {
|
||||||
|
return <Liquidity row={row} type="pool" />
|
||||||
|
},
|
||||||
|
right: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
export default function PoolShares({
|
||||||
|
accountId
|
||||||
|
}: {
|
||||||
|
accountId: string
|
||||||
|
}): ReactElement {
|
||||||
|
const { poolShares } = useProfile()
|
||||||
|
const { chainIds } = useUserPreferences()
|
||||||
|
const newCancelToken = useCancelToken()
|
||||||
|
const isMounted = useIsMounted()
|
||||||
|
|
||||||
|
const [assets, setAssets] = useState<AssetPoolShare[]>()
|
||||||
|
const [loading, setLoading] = useState<boolean>(false)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Helper: fetch assets from pool shares data
|
||||||
|
//
|
||||||
|
const fetchPoolSharesAssets = useCallback(async () => {
|
||||||
|
if (!poolShares || !chainIds) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
const assets = await getAssetsFromPoolShares(
|
||||||
|
poolShares,
|
||||||
|
chainIds,
|
||||||
|
newCancelToken()
|
||||||
|
)
|
||||||
|
setAssets(assets)
|
||||||
|
} catch (error) {
|
||||||
|
LoggerInstance.error('Error fetching pool shares: ', error.message)
|
||||||
|
} finally {
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
// We do not need to react to `chainIds` changes here, cause changing them
|
||||||
|
// triggers change of `poolShares` from `useProfile()` already.
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [poolShares, newCancelToken])
|
||||||
|
|
||||||
|
//
|
||||||
|
// 1. Kick off data fetching
|
||||||
|
//
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isMounted()) return
|
||||||
|
|
||||||
|
setLoading(true)
|
||||||
|
fetchPoolSharesAssets()
|
||||||
|
}, [fetchPoolSharesAssets, isMounted])
|
||||||
|
|
||||||
|
return accountId ? (
|
||||||
|
<Table
|
||||||
|
columns={columns}
|
||||||
|
className={styles.poolSharesTable}
|
||||||
|
data={assets}
|
||||||
|
pagination
|
||||||
|
paginationPerPage={5}
|
||||||
|
isLoading={loading}
|
||||||
|
sortField="userLiquidity"
|
||||||
|
sortAsc={false}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div>Please connect your Web3 wallet.</div>
|
||||||
|
)
|
||||||
|
}
|
@ -49,7 +49,7 @@ export default function Price({
|
|||||||
Expected first price:{' '}
|
Expected first price:{' '}
|
||||||
<PriceUnit
|
<PriceUnit
|
||||||
price={Number(firstPrice) > 0 ? firstPrice : '-'}
|
price={Number(firstPrice) > 0 ? firstPrice : '-'}
|
||||||
small
|
size="small"
|
||||||
conversion
|
conversion
|
||||||
/>
|
/>
|
||||||
</aside>
|
</aside>
|
||||||
|
Loading…
Reference in New Issue
Block a user