mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
merge v4 into v4-c2d and fixed conflicts
This commit is contained in:
commit
4eb41bba2c
946
package-lock.json
generated
946
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -21,7 +21,7 @@
|
||||
"@coingecko/cryptoformat": "^0.4.4",
|
||||
"@loadable/component": "^5.15.2",
|
||||
"@oceanprotocol/art": "^3.2.0",
|
||||
"@oceanprotocol/lib": "^1.0.0-next.24",
|
||||
"@oceanprotocol/lib": "^1.0.0-next.25",
|
||||
"@oceanprotocol/typographies": "^0.1.0",
|
||||
"@portis/web3": "^4.0.6",
|
||||
"@tippyjs/react": "^4.2.6",
|
||||
|
@ -172,7 +172,6 @@ function PoolProvider({ children }: { children: ReactNode }): ReactElement {
|
||||
.mul(100)
|
||||
.toFixed(2)
|
||||
: '0'
|
||||
|
||||
const newPoolOwnerInfo = {
|
||||
liquidity,
|
||||
poolShares: ownerPoolShares,
|
||||
|
@ -154,7 +154,11 @@ function ProfileProvider({
|
||||
await fetchPoolShares(accountId, chainIds, isEthAddress)
|
||||
|
||||
if (poolSharesInterval) return
|
||||
|
||||
const interval = setInterval(async () => {
|
||||
LoggerInstance.log(
|
||||
`[profile] Re-fetching pool shares after ${refreshInterval / 1000}s.`
|
||||
)
|
||||
await fetchPoolShares(accountId, chainIds, isEthAddress)
|
||||
}, refreshInterval)
|
||||
setPoolSharesInterval(interval)
|
||||
|
@ -8,7 +8,7 @@ import {
|
||||
TokensPriceQuery,
|
||||
TokensPriceQuery_tokens as TokensPrice
|
||||
} from '../@types/subgraph/TokensPriceQuery'
|
||||
import { Asset, ProviderInstance } from '@oceanprotocol/lib'
|
||||
import { Asset, LoggerInstance, ProviderInstance } from '@oceanprotocol/lib'
|
||||
import { AssetExtended } from 'src/@types/AssetExtended'
|
||||
import { calculateBuyPrice } from './pool'
|
||||
import { getFixedBuyPrice } from './fixedRateExchange'
|
||||
@ -233,29 +233,27 @@ export async function getOrderPriceAndFees(
|
||||
computeEnv: string = null,
|
||||
computeValidUntil: number = null
|
||||
): 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()
|
||||
|
||||
// fetch publish market order fee
|
||||
orderPriceAndFee.publisherMarketOrderFee =
|
||||
asset.accessDetails.publisherMarketOrderFee
|
||||
// fetch consume market order fee
|
||||
orderPriceAndFee.consumeMarketOrderFee = appConfig.consumeMarketOrderFee
|
||||
const orderPriceAndFee = {
|
||||
price: '0',
|
||||
publisherMarketOrderFee:
|
||||
asset?.accessDetails?.publisherMarketOrderFee || '0',
|
||||
publisherMarketPoolSwapFee: '0',
|
||||
publisherMarketFixedSwapFee: '0',
|
||||
consumeMarketOrderFee: appConfig.consumeMarketOrderFee || '0',
|
||||
consumeMarketPoolSwapFee: '0',
|
||||
consumeMarketFixedSwapFee: '0',
|
||||
providerFee: {
|
||||
providerFeeAmount: '0'
|
||||
},
|
||||
opcFee: '0'
|
||||
} as OrderPriceAndFees
|
||||
|
||||
// fetch provider fee
|
||||
|
||||
const initializeData = await ProviderInstance.initialize(
|
||||
asset.id,
|
||||
asset?.id,
|
||||
asset.services[0].id,
|
||||
0,
|
||||
accountId,
|
||||
@ -268,9 +266,12 @@ export async function getOrderPriceAndFees(
|
||||
orderPriceAndFee.providerFee = initializeData.providerFee
|
||||
|
||||
// fetch price and swap fees
|
||||
switch (accessDetails.type) {
|
||||
switch (asset?.accessDetails?.type) {
|
||||
case 'dynamic': {
|
||||
const poolPrice = await calculateBuyPrice(accessDetails, asset.chainId)
|
||||
const poolPrice = await calculateBuyPrice(
|
||||
asset?.accessDetails,
|
||||
asset?.chainId
|
||||
)
|
||||
orderPriceAndFee.price = poolPrice.tokenAmount
|
||||
orderPriceAndFee.liquidityProviderSwapFee =
|
||||
poolPrice.liquidityProviderSwapFeeAmount
|
||||
@ -281,7 +282,7 @@ export async function getOrderPriceAndFees(
|
||||
break
|
||||
}
|
||||
case 'fixed': {
|
||||
const fixed = await getFixedBuyPrice(accessDetails, asset.chainId)
|
||||
const fixed = await getFixedBuyPrice(asset?.accessDetails, asset?.chainId)
|
||||
orderPriceAndFee.price = fixed.baseTokenAmount
|
||||
orderPriceAndFee.opcFee = fixed.oceanFeeAmount
|
||||
orderPriceAndFee.publisherMarketFixedSwapFee = fixed.marketFeeAmount
|
||||
@ -304,9 +305,9 @@ export async function getOrderPriceAndFees(
|
||||
/**
|
||||
* @param {number} chain
|
||||
* @param {string} datatokenAddress
|
||||
* @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 {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 {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 {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>}
|
||||
*/
|
||||
export async function getAccessDetails(
|
||||
@ -315,22 +316,26 @@ export async function getAccessDetails(
|
||||
timeout?: number,
|
||||
account = ''
|
||||
): Promise<AccessDetails> {
|
||||
const queryContext = getQueryContext(Number(chainId))
|
||||
const tokenQueryResult: OperationResult<
|
||||
TokenPriceQuery,
|
||||
{ datatokenId: string; account: string }
|
||||
> = await fetchData(
|
||||
TokenPriceQuery,
|
||||
{
|
||||
datatokenId: datatokenAddress.toLowerCase(),
|
||||
account: account?.toLowerCase()
|
||||
},
|
||||
queryContext
|
||||
)
|
||||
try {
|
||||
const queryContext = getQueryContext(Number(chainId))
|
||||
const tokenQueryResult: OperationResult<
|
||||
TokenPriceQuery,
|
||||
{ datatokenId: string; account: string }
|
||||
> = await fetchData(
|
||||
TokenPriceQuery,
|
||||
{
|
||||
datatokenId: datatokenAddress.toLowerCase(),
|
||||
account: account?.toLowerCase()
|
||||
},
|
||||
queryContext
|
||||
)
|
||||
|
||||
const tokenPrice: TokenPrice = tokenQueryResult.data.token
|
||||
const accessDetails = getAccessDetailsFromTokenPrice(tokenPrice, timeout)
|
||||
return accessDetails
|
||||
const tokenPrice: TokenPrice = tokenQueryResult.data.token
|
||||
const accessDetails = getAccessDetailsFromTokenPrice(tokenPrice, timeout)
|
||||
return accessDetails
|
||||
} catch (error) {
|
||||
LoggerInstance.error('Error getting access details: ', error.message)
|
||||
}
|
||||
}
|
||||
|
||||
export async function getAccessDetailsForAssets(
|
||||
@ -340,43 +345,48 @@ export async function getAccessDetailsForAssets(
|
||||
const assetsExtended: AssetExtended[] = assets
|
||||
const chainAssetLists: { [key: number]: string[] } = {}
|
||||
|
||||
for (const asset of assets) {
|
||||
if (chainAssetLists[asset.chainId]) {
|
||||
chainAssetLists[asset.chainId].push(
|
||||
asset.services[0].datatokenAddress.toLowerCase()
|
||||
)
|
||||
} else {
|
||||
chainAssetLists[asset.chainId] = []
|
||||
chainAssetLists[asset.chainId].push(
|
||||
asset.services[0].datatokenAddress.toLowerCase()
|
||||
)
|
||||
try {
|
||||
for (const asset of assets) {
|
||||
if (chainAssetLists[asset.chainId]) {
|
||||
chainAssetLists[asset.chainId].push(
|
||||
asset.services[0].datatokenAddress.toLowerCase()
|
||||
)
|
||||
} else {
|
||||
chainAssetLists[asset.chainId] = []
|
||||
chainAssetLists[asset.chainId].push(
|
||||
asset.services[0].datatokenAddress.toLowerCase()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const chainKey in chainAssetLists) {
|
||||
const queryContext = getQueryContext(Number(chainKey))
|
||||
const tokenQueryResult: OperationResult<
|
||||
TokensPriceQuery,
|
||||
{ datatokenIds: [string]; account: string }
|
||||
> = await fetchData(
|
||||
TokensPriceQuery,
|
||||
{
|
||||
datatokenIds: chainAssetLists[chainKey],
|
||||
account: account?.toLowerCase()
|
||||
},
|
||||
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
|
||||
for (const chainKey in chainAssetLists) {
|
||||
const queryContext = getQueryContext(Number(chainKey))
|
||||
const tokenQueryResult: OperationResult<
|
||||
TokensPriceQuery,
|
||||
{ datatokenIds: [string]; account: string }
|
||||
> = await fetchData(
|
||||
TokensPriceQuery,
|
||||
{
|
||||
datatokenIds: chainAssetLists[chainKey],
|
||||
account: account?.toLowerCase()
|
||||
},
|
||||
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
|
||||
)
|
||||
|
||||
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(
|
||||
didList: string[],
|
||||
chainIds: number[],
|
||||
|
@ -16,9 +16,6 @@ export function getOceanConfig(network: string | number): Config {
|
||||
? undefined
|
||||
: process.env.NEXT_PUBLIC_INFURA_PROJECT_ID
|
||||
) as Config
|
||||
// TODO: remove hack once address is fixed
|
||||
if (network === 'rinkeby' || network === 4)
|
||||
config.oceanTokenAddress = '0x8967bcf84170c91b0d24d4302c2376283b0b3a07'
|
||||
return config as Config
|
||||
}
|
||||
|
||||
@ -30,7 +27,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://subgraphv4.rinkeby.oceanprotocol.com'
|
||||
subgraphUri: 'https://v4.subgraph.rinkeby.oceanprotocol.com'
|
||||
} as Config
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,8 @@ import { getDummyWeb3 } from './web3'
|
||||
import { TransactionReceipt } from 'web3-eth'
|
||||
import Decimal from 'decimal.js'
|
||||
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
|
||||
* @param {AccessDetails} accessDetails
|
||||
@ -73,3 +74,40 @@ export async function buyDtFromPool(
|
||||
|
||||
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_poolShares as PoolShare
|
||||
} from '../@types/subgraph/PoolShares'
|
||||
import {
|
||||
OrdersData_orders as OrdersData,
|
||||
OrdersData_orders_datatoken as OrdersDatatoken
|
||||
} from '../@types/subgraph/OrdersData'
|
||||
import { OrdersData_orders as OrdersData } from '../@types/subgraph/OrdersData'
|
||||
import { UserSalesQuery as UsersSalesList } from '../@types/subgraph/UserSalesQuery'
|
||||
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 {
|
||||
price: string
|
||||
@ -164,7 +164,7 @@ const UserTokenOrders = gql`
|
||||
`
|
||||
|
||||
const UserSalesQuery = gql`
|
||||
query UserSalesQuery($user: String!) {
|
||||
query UserSalesQuery($user: ID!) {
|
||||
users(where: { id: $user }) {
|
||||
id
|
||||
totalSales
|
||||
@ -177,7 +177,7 @@ const TopSalesQuery = gql`
|
||||
query TopSalesQuery {
|
||||
users(
|
||||
first: 20
|
||||
orderBy: tokensOwned
|
||||
orderBy: sharesOwned
|
||||
orderDirection: desc
|
||||
where: { tokenBalancesOwned_not: "0" }
|
||||
) {
|
||||
@ -206,14 +206,17 @@ export function getSubgraphUri(chainId: number): string {
|
||||
}
|
||||
|
||||
export function getQueryContext(chainId: number): OperationContext {
|
||||
const queryContext: OperationContext = {
|
||||
url: `${getSubgraphUri(
|
||||
Number(chainId)
|
||||
)}/subgraphs/name/oceanprotocol/ocean-subgraph`,
|
||||
requestPolicy: 'cache-and-network'
|
||||
try {
|
||||
const queryContext: OperationContext = {
|
||||
url: `${getSubgraphUri(
|
||||
Number(chainId)
|
||||
)}/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(
|
||||
@ -223,12 +226,13 @@ export async function fetchData(
|
||||
): Promise<any> {
|
||||
try {
|
||||
const client = getUrqlClientInstance()
|
||||
|
||||
const response = await client.query(query, variables, context).toPromise()
|
||||
return response
|
||||
} catch (error) {
|
||||
console.error('Error fetchData: ', error.message)
|
||||
throw Error(error.message)
|
||||
LoggerInstance.error('Error fetchData: ', error.message)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export async function fetchDataForMultipleChains(
|
||||
@ -237,21 +241,20 @@ export async function fetchDataForMultipleChains(
|
||||
chainIds: number[]
|
||||
): Promise<any[]> {
|
||||
let datas: any[] = []
|
||||
for (const chainId of chainIds) {
|
||||
const context: OperationContext = {
|
||||
url: `${getSubgraphUri(
|
||||
chainId
|
||||
)}/subgraphs/name/oceanprotocol/ocean-subgraph`,
|
||||
requestPolicy: 'network-only'
|
||||
}
|
||||
try {
|
||||
try {
|
||||
for (const chainId of chainIds) {
|
||||
// console.log('fetch chainID', chainId)
|
||||
const context: OperationContext = getQueryContext(chainId)
|
||||
const response = await fetchData(query, variables, context)
|
||||
datas = datas.concat(response.data)
|
||||
} catch (error) {
|
||||
console.error('Error fetchData: ', error.message)
|
||||
// console.log('fetch response', response)
|
||||
if (!response || response.error) continue
|
||||
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) {
|
||||
@ -268,7 +271,7 @@ export async function getOpcFees(chainId: number) {
|
||||
)
|
||||
opcFees = response?.data?.opc
|
||||
} catch (error) {
|
||||
console.error('Error fetchData: ', error.message)
|
||||
LoggerInstance.error('Error getOpcFees: ', error.message)
|
||||
throw Error(error.message)
|
||||
}
|
||||
return opcFees
|
||||
@ -320,6 +323,7 @@ export async function getHighestLiquidityDatatokens(
|
||||
): Promise<string[]> {
|
||||
const dtList: string[] = []
|
||||
let highestLiquidityAssets: HighestLiquidityAssetsPool[] = []
|
||||
|
||||
for (const chain of chainIds) {
|
||||
const queryContext = getQueryContext(Number(chain))
|
||||
const fetchedPools: OperationResult<HighestLiquidityGraphAssets, any> =
|
||||
@ -339,22 +343,11 @@ export async function getHighestLiquidityDatatokens(
|
||||
return dtList
|
||||
}
|
||||
|
||||
export function calculateUserLiquidity(poolShare: PoolShare): number {
|
||||
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(
|
||||
export async function getAccountTVLInOwnAssets(
|
||||
accountId: string,
|
||||
chainIds: number[],
|
||||
pools: string[]
|
||||
): Promise<UserLiquidity> {
|
||||
): Promise<string> {
|
||||
const queryVariables = {
|
||||
user: accountId.toLowerCase(),
|
||||
pools: pools
|
||||
@ -364,22 +357,22 @@ export async function getAccountLiquidityInOwnAssets(
|
||||
queryVariables,
|
||||
chainIds
|
||||
)
|
||||
let totalLiquidity = 0
|
||||
let totalOceanLiquidity = 0
|
||||
let tvl = new Decimal(0)
|
||||
// console.log('resss', results)
|
||||
|
||||
for (const result of results) {
|
||||
// console.log('result.poolShares', result.poolShares)
|
||||
for (const poolShare of result.poolShares) {
|
||||
const userShare = poolShare.shares / poolShare.pool.totalShares
|
||||
const userBalance = userShare * poolShare.pool.baseTokenLiquidity
|
||||
totalOceanLiquidity += userBalance
|
||||
const poolLiquidity = calculateUserLiquidity(poolShare)
|
||||
totalLiquidity += poolLiquidity
|
||||
const poolUserTvl = calculateUserTVL(
|
||||
poolShare.shares,
|
||||
poolShare.pool.totalShares,
|
||||
poolShare.pool.baseTokenLiquidity
|
||||
)
|
||||
tvl = tvl.add(new Decimal(poolUserTvl))
|
||||
// console.log('result.poolShares', tvl.toString())
|
||||
}
|
||||
}
|
||||
return {
|
||||
price: totalLiquidity.toString(),
|
||||
oceanBalance: totalOceanLiquidity.toString()
|
||||
}
|
||||
return tvl.toDecimalPlaces(MAX_DECIMALS).toString()
|
||||
}
|
||||
|
||||
export async function getPoolSharesData(
|
||||
@ -388,17 +381,21 @@ export async function getPoolSharesData(
|
||||
): Promise<PoolShare[]> {
|
||||
const variables = { user: accountId?.toLowerCase() }
|
||||
const data: PoolShare[] = []
|
||||
const result = await fetchDataForMultipleChains(
|
||||
userPoolSharesQuery,
|
||||
variables,
|
||||
chainIds
|
||||
)
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
result[i].poolShares.forEach((poolShare: PoolShare) => {
|
||||
data.push(poolShare)
|
||||
})
|
||||
try {
|
||||
const result = await fetchDataForMultipleChains(
|
||||
userPoolSharesQuery,
|
||||
variables,
|
||||
chainIds
|
||||
)
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
result[i].poolShares.forEach((poolShare: PoolShare) => {
|
||||
data.push(poolShare)
|
||||
})
|
||||
}
|
||||
return data
|
||||
} catch (error) {
|
||||
LoggerInstance.error('Error getPoolSharesData: ', error.message)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
export async function getUserTokenOrders(
|
||||
@ -422,7 +419,7 @@ export async function getUserTokenOrders(
|
||||
|
||||
return data
|
||||
} catch (error) {
|
||||
LoggerInstance.error(error.message)
|
||||
LoggerInstance.error('Error getUserTokenOrders', error.message)
|
||||
}
|
||||
}
|
||||
|
||||
@ -445,7 +442,7 @@ export async function getUserSales(
|
||||
}
|
||||
return salesSum
|
||||
} catch (error) {
|
||||
LoggerInstance.log(error.message)
|
||||
LoggerInstance.error('Error getUserSales', error.message)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,11 @@ export default function AssetComputeSelection({
|
||||
{asset.symbol} | {asset.did}
|
||||
</Dotdotdot>
|
||||
</div>
|
||||
<PriceUnit price={asset.price} small className={styles.price} />
|
||||
<PriceUnit
|
||||
price={asset.price}
|
||||
size="small"
|
||||
className={styles.price}
|
||||
/>
|
||||
</a>
|
||||
</Link>
|
||||
))
|
||||
|
@ -51,7 +51,7 @@ export default function AssetTeaser({
|
||||
</div>
|
||||
|
||||
<footer className={styles.foot}>
|
||||
<Price accessDetails={asset.accessDetails} small />
|
||||
<Price accessDetails={asset.accessDetails} size="small" />
|
||||
<NetworkName networkId={asset.chainId} className={styles.network} />
|
||||
</footer>
|
||||
</a>
|
||||
|
@ -110,7 +110,7 @@ export default function AssetSelection({
|
||||
<PriceUnit
|
||||
price={asset.price}
|
||||
type={asset.price === '0' ? 'free' : undefined}
|
||||
small
|
||||
size="small"
|
||||
className={styles.price}
|
||||
/>
|
||||
</div>
|
||||
|
@ -5,11 +5,10 @@ import AssetTitle from '@shared/AssetList/AssetListTitle'
|
||||
import { useUserPreferences } from '@context/UserPreferences'
|
||||
import { gql } from 'urql'
|
||||
import { TransactionHistory_poolTransactions as TransactionHistoryPoolTransactions } from '../../../@types/subgraph/TransactionHistory'
|
||||
import web3 from 'web3'
|
||||
import { fetchDataForMultipleChains } from '@utils/subgraph'
|
||||
import { useSiteMetadata } from '@hooks/useSiteMetadata'
|
||||
import NetworkName from '@shared/NetworkName'
|
||||
import { retrieveDDOListByDIDs } from '@utils/aquarius'
|
||||
import { getAssetsFromDtList } from '@utils/aquarius'
|
||||
import { CancelToken } from 'axios'
|
||||
import Title from './Title'
|
||||
import styles from './index.module.css'
|
||||
@ -128,13 +127,14 @@ export default function PoolTransactions({
|
||||
minimal?: boolean
|
||||
accountId: string
|
||||
}): ReactElement {
|
||||
const [transactions, setTransactions] = useState<PoolTransaction[]>()
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false)
|
||||
const { chainIds } = useUserPreferences()
|
||||
const { appConfig } = useSiteMetadata()
|
||||
const cancelToken = useCancelToken()
|
||||
|
||||
const [transactions, setTransactions] = useState<PoolTransaction[]>()
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false)
|
||||
const [dataFetchInterval, setDataFetchInterval] = useState<NodeJS.Timeout>()
|
||||
const [data, setData] = useState<PoolTransaction[]>()
|
||||
const cancelToken = useCancelToken()
|
||||
|
||||
const getPoolTransactionData = useCallback(async () => {
|
||||
const variables = {
|
||||
@ -165,24 +165,18 @@ export default function PoolTransactions({
|
||||
return
|
||||
}
|
||||
const poolTransactions: PoolTransaction[] = []
|
||||
const didList: string[] = []
|
||||
const dtList: string[] = []
|
||||
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const { address } = data[i].datatoken
|
||||
const did = web3.utils
|
||||
.toChecksumAddress(address)
|
||||
.replace('0x', 'did:op:')
|
||||
didList.push(did)
|
||||
dtList.push(data[i]?.datatoken?.address)
|
||||
}
|
||||
if (didList.length === 0) {
|
||||
|
||||
if (dtList.length === 0) {
|
||||
setIsLoading(false)
|
||||
return
|
||||
}
|
||||
const ddoList = await retrieveDDOListByDIDs(
|
||||
didList,
|
||||
chainIds,
|
||||
cancelToken
|
||||
)
|
||||
const ddoList = await getAssetsFromDtList(dtList, chainIds, cancelToken)
|
||||
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
poolTransactions.push({
|
||||
...data[i],
|
||||
|
@ -2,7 +2,7 @@
|
||||
display: inline-block;
|
||||
font-weight: var(--font-weight-bold);
|
||||
font-family: var(--font-family-base);
|
||||
font-size: var(--font-size-large);
|
||||
|
||||
color: var(--font-color-text);
|
||||
line-height: 1.2;
|
||||
}
|
||||
@ -17,6 +17,10 @@
|
||||
font-size: var(--font-size-base);
|
||||
}
|
||||
|
||||
.price.large {
|
||||
font-size: var(--font-size-large);
|
||||
}
|
||||
|
||||
.price.small {
|
||||
display: inline-block;
|
||||
font-size: var(--font-size-base);
|
||||
@ -26,6 +30,15 @@
|
||||
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 {
|
||||
vertical-align: middle;
|
||||
margin-left: calc(var(--spacer) / 6);
|
||||
|
@ -1,13 +1,10 @@
|
||||
import React, { ReactElement } from 'react'
|
||||
import { formatCurrency } from '@coingecko/cryptoformat'
|
||||
import classNames from 'classnames/bind'
|
||||
import Conversion from './Conversion'
|
||||
import styles from './PriceUnit.module.css'
|
||||
import { useUserPreferences } from '@context/UserPreferences'
|
||||
import Badge from '@shared/atoms/Badge'
|
||||
|
||||
const cx = classNames.bind(styles)
|
||||
|
||||
export function formatPrice(price: string, locale: string): string {
|
||||
return formatCurrency(Number(price), '', locale, false, {
|
||||
// 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({
|
||||
price,
|
||||
className,
|
||||
small,
|
||||
size = 'small',
|
||||
conversion,
|
||||
symbol,
|
||||
type
|
||||
@ -28,20 +25,14 @@ export default function PriceUnit({
|
||||
price: string
|
||||
type?: string
|
||||
className?: string
|
||||
small?: boolean
|
||||
size?: 'small' | 'mini' | 'large'
|
||||
conversion?: boolean
|
||||
symbol?: string
|
||||
}): ReactElement {
|
||||
const { locale } = useUserPreferences()
|
||||
|
||||
const styleClasses = cx({
|
||||
price: true,
|
||||
small: small,
|
||||
[className]: className
|
||||
})
|
||||
|
||||
return (
|
||||
<div className={styleClasses}>
|
||||
<div className={`${styles.price} ${styles[size]} ${className}`}>
|
||||
{type && type === 'free' ? (
|
||||
<div> Free </div>
|
||||
) : (
|
||||
|
@ -9,21 +9,21 @@ export default function Price({
|
||||
accessDetails,
|
||||
orderPriceAndFees,
|
||||
className,
|
||||
small,
|
||||
size,
|
||||
conversion
|
||||
}: {
|
||||
accessDetails: AccessDetails
|
||||
orderPriceAndFees?: OrderPriceAndFees
|
||||
className?: string
|
||||
small?: boolean
|
||||
conversion?: boolean
|
||||
size?: 'small' | 'mini' | 'large'
|
||||
}): ReactElement {
|
||||
return accessDetails?.price || accessDetails?.type === 'free' ? (
|
||||
<PriceUnit
|
||||
price={`${orderPriceAndFees?.price || accessDetails?.price}`}
|
||||
symbol={accessDetails.baseToken?.symbol}
|
||||
className={className}
|
||||
small={small}
|
||||
size={size}
|
||||
conversion={conversion}
|
||||
type={accessDetails.type}
|
||||
/>
|
||||
|
@ -16,7 +16,7 @@ export default function Blockies({
|
||||
|
||||
return (
|
||||
<img
|
||||
className={`${styles.blockies} ${className || ''}`}
|
||||
className={`${className || ''} ${styles.blockies} `}
|
||||
src={blockies}
|
||||
alt="Blockies"
|
||||
aria-hidden="true"
|
||||
|
@ -39,7 +39,7 @@ function Row({
|
||||
<PriceUnit
|
||||
price={hasPreviousOrder || hasDatatoken ? '0' : `${price}`}
|
||||
symbol={symbol}
|
||||
small
|
||||
size="small"
|
||||
className={styles.price}
|
||||
/>
|
||||
<span className={styles.timeout}>
|
||||
@ -68,7 +68,8 @@ export default function PriceOutput({
|
||||
|
||||
return (
|
||||
<div className={styles.priceComponent}>
|
||||
You will pay <PriceUnit price={`${totalPrice}`} symbol={symbol} small />
|
||||
You will pay{' '}
|
||||
<PriceUnit price={`${totalPrice}`} symbol={symbol} size="small" />
|
||||
<Tooltip
|
||||
content={
|
||||
<div className={styles.calculation}>
|
||||
|
@ -258,13 +258,19 @@ export default function Download({
|
||||
accessDetails={asset.accessDetails}
|
||||
orderPriceAndFees={orderPriceAndFees}
|
||||
conversion
|
||||
size="large"
|
||||
/>
|
||||
{!isInPurgatory && <PurchaseButton />}
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.collect}>
|
||||
{asset.nft.owner === accountId && <CollectTokensButton />}
|
||||
</div>
|
||||
|
||||
{asset?.accessDetails?.datatoken?.name !== '' &&
|
||||
asset?.nft.owner === accountId && (
|
||||
<div className={styles.collect}>
|
||||
<CollectTokensButton />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{asset?.metadata?.type === 'algorithm' && (
|
||||
<AlgorithmDatasetsListForCompute
|
||||
algorithmDid={asset.id}
|
||||
|
@ -34,3 +34,7 @@
|
||||
.noIcon {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.token.mini {
|
||||
font-size: var(--font-size-mini);
|
||||
}
|
||||
|
@ -6,20 +6,22 @@ import Logo from '@shared/atoms/Logo'
|
||||
export default function Token({
|
||||
symbol,
|
||||
balance,
|
||||
noIcon
|
||||
noIcon,
|
||||
size
|
||||
}: {
|
||||
symbol: string
|
||||
balance: string
|
||||
noIcon?: boolean
|
||||
size?: 'small' | 'mini'
|
||||
}): ReactElement {
|
||||
return (
|
||||
<div className={styles.token}>
|
||||
<div className={`${styles.token} ${size ? styles[size] : ''}`}>
|
||||
<figure
|
||||
className={`${styles.icon} ${symbol} ${noIcon ? styles.noIcon : ''}`}
|
||||
>
|
||||
<Logo noWordmark />
|
||||
</figure>
|
||||
<PriceUnit price={balance} symbol={symbol} small />
|
||||
<PriceUnit price={balance} symbol={symbol} size={size} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -12,31 +12,38 @@ export default function TokenList({
|
||||
datatokenValue,
|
||||
datatokenSymbol,
|
||||
conversion,
|
||||
highlight
|
||||
highlight,
|
||||
size = 'small'
|
||||
}: {
|
||||
title: string | ReactNode
|
||||
title?: string | ReactNode
|
||||
children?: ReactNode
|
||||
baseTokenValue: string
|
||||
baseTokenSymbol: string
|
||||
datatokenValue?: string
|
||||
datatokenSymbol?: string
|
||||
conversion: Decimal
|
||||
conversion?: Decimal
|
||||
highlight?: boolean
|
||||
size?: 'small' | 'mini'
|
||||
}): ReactElement {
|
||||
return (
|
||||
<div className={`${styles.tokenlist} ${highlight ? styles.highlight : ''}`}>
|
||||
<h3 className={styles.title}>{title}</h3>
|
||||
{title && <h3 className={styles.title}>{title}</h3>}
|
||||
<div className={styles.tokens}>
|
||||
<Token symbol={baseTokenSymbol} balance={baseTokenValue} />
|
||||
{datatokenValue && (
|
||||
<Token symbol={datatokenSymbol} balance={datatokenValue} />
|
||||
)}
|
||||
{conversion.greaterThan(0) && (
|
||||
<Token symbol={baseTokenSymbol} balance={baseTokenValue} size={size} />
|
||||
|
||||
{conversion?.greaterThan(0) && (
|
||||
<Conversion
|
||||
price={conversion.toString()}
|
||||
className={styles.totalLiquidity}
|
||||
/>
|
||||
)}
|
||||
{datatokenValue && (
|
||||
<Token
|
||||
symbol={datatokenSymbol}
|
||||
balance={datatokenValue}
|
||||
size={size}
|
||||
/>
|
||||
)}
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -16,6 +16,7 @@ import PoolTransactions from '@shared/PoolTransactions'
|
||||
import Decimal from 'decimal.js'
|
||||
import content from '../../../../../content/price.json'
|
||||
import { usePool } from '@context/Pool'
|
||||
import Token from './Token'
|
||||
|
||||
export default function Pool(): ReactElement {
|
||||
const { accountId } = useWeb3()
|
||||
@ -65,10 +66,16 @@ export default function Pool(): ReactElement {
|
||||
) : (
|
||||
<>
|
||||
<div className={styles.dataToken}>
|
||||
<PriceUnit price="1" symbol={poolInfo?.datatokenSymbol} /> ={' '}
|
||||
<PriceUnit
|
||||
price="1"
|
||||
symbol={poolInfo?.datatokenSymbol}
|
||||
size="large"
|
||||
/>{' '}
|
||||
={' '}
|
||||
<PriceUnit
|
||||
price={`${poolData?.spotPrice}`}
|
||||
symbol={poolInfo?.baseTokenSymbol}
|
||||
size="large"
|
||||
/>
|
||||
<Tooltip content={content.pool.tooltips.price} />
|
||||
<div className={styles.dataTokenLinks}>
|
||||
@ -90,7 +97,6 @@ export default function Pool(): ReactElement {
|
||||
</ExplorerLink>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<TokenList
|
||||
title={
|
||||
<>
|
||||
@ -113,11 +119,10 @@ export default function Pool(): ReactElement {
|
||||
conversion={poolInfoUser?.liquidity}
|
||||
highlight
|
||||
/>
|
||||
|
||||
<TokenList
|
||||
title={
|
||||
<>
|
||||
Owner Liquidity
|
||||
Owner Value Locked
|
||||
<span className={styles.titleInfo}>
|
||||
{poolInfoOwner?.poolShare}% of pool
|
||||
</span>
|
||||
@ -127,7 +132,6 @@ export default function Pool(): ReactElement {
|
||||
baseTokenSymbol={poolInfo?.baseTokenSymbol}
|
||||
conversion={poolInfoOwner?.liquidity}
|
||||
/>
|
||||
|
||||
<TokenList
|
||||
title={
|
||||
<>
|
||||
@ -143,21 +147,41 @@ export default function Pool(): ReactElement {
|
||||
<Graph poolSnapshots={poolSnapshots} />
|
||||
</>
|
||||
}
|
||||
baseTokenValue={`${poolInfo?.totalLiquidityInOcean}`}
|
||||
baseTokenSymbol={poolInfo?.baseTokenSymbol}
|
||||
conversion={poolInfo?.totalLiquidityInOcean}
|
||||
/>
|
||||
|
||||
<TokenList
|
||||
size="mini"
|
||||
baseTokenValue={`${poolData?.baseTokenLiquidity}`}
|
||||
baseTokenSymbol={poolInfo?.baseTokenSymbol}
|
||||
datatokenValue={`${poolData?.datatokenLiquidity}`}
|
||||
datatokenSymbol={poolInfo?.datatokenSymbol}
|
||||
conversion={poolInfo?.totalLiquidityInOcean}
|
||||
>
|
||||
{/* <Token symbol="% pool fee" balance={poolInfo?.poolFee} noIcon />
|
||||
<Token symbol="% market fee" balance={poolInfo?.marketFee} noIcon />
|
||||
<Token symbol="% OPF fee" balance={poolInfo?.opfFee} noIcon /> */}
|
||||
<Token
|
||||
symbol="% pool fee"
|
||||
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>
|
||||
|
||||
<div className={styles.update}>
|
||||
Fetching every {refreshInterval / 1000} sec.
|
||||
</div>
|
||||
|
||||
<div className={stylesActions.actions}>
|
||||
<Button
|
||||
style="primary"
|
||||
@ -178,7 +202,6 @@ export default function Pool(): ReactElement {
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{accountId && (
|
||||
<AssetActionHistoryTable title="Your Pool Transactions">
|
||||
<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 (
|
||||
<div>
|
||||
<span>{title}</span>
|
||||
<PriceUnit price={amount} symbol={symbol} small />
|
||||
<PriceUnit price={amount} symbol={symbol} size="small" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -161,12 +161,12 @@ export default function AssetActions({
|
||||
{
|
||||
title: 'Pool',
|
||||
content: <Pool />,
|
||||
disabled: !asset?.accessDetails.datatoken
|
||||
disabled: asset?.accessDetails.datatoken.name === ''
|
||||
},
|
||||
{
|
||||
title: 'Trade',
|
||||
content: <Trade />,
|
||||
disabled: !asset?.accessDetails.datatoken
|
||||
disabled: asset?.accessDetails.datatoken.name === ''
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -34,7 +34,7 @@ export default function MarketStatsTooltip({
|
||||
<PriceUnit
|
||||
price={totalOceanLiquidity?.[chainId] || '0'}
|
||||
symbol="OCEAN"
|
||||
small
|
||||
size="small"
|
||||
/>
|
||||
</li>
|
||||
))}
|
||||
|
@ -21,8 +21,12 @@ export default function MarketStatsTotal({
|
||||
/>{' '}
|
||||
<abbr title="Total Value Locked">TVL</abbr> across{' '}
|
||||
<strong>{total.pools}</strong> asset pools that contain{' '}
|
||||
<PriceUnit price={`${total.totalOceanLiquidity}`} symbol="OCEAN" small />,
|
||||
plus datatokens for each pool.
|
||||
<PriceUnit
|
||||
price={`${total.totalOceanLiquidity}`}
|
||||
symbol="OCEAN"
|
||||
size="small"
|
||||
/>
|
||||
, plus datatokens for each pool.
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ const columns = [
|
||||
{
|
||||
name: 'Price',
|
||||
selector: function getAssetRow(row: AssetExtended) {
|
||||
return <Price accessDetails={row.accessDetails} small />
|
||||
return <Price accessDetails={row.accessDetails} size="small" />
|
||||
},
|
||||
right: true
|
||||
}
|
||||
|
@ -56,7 +56,10 @@ function SectionQueryResult({
|
||||
const [loading, setLoading] = useState<boolean>()
|
||||
const isMounted = useIsMounted()
|
||||
const newCancelToken = useCancelToken()
|
||||
|
||||
useEffect(() => {
|
||||
if (!query) return
|
||||
|
||||
async function init() {
|
||||
if (chainIds.length === 0) {
|
||||
const result: PagedAssets = {
|
||||
@ -91,11 +94,13 @@ function SectionQueryResult({
|
||||
return (
|
||||
<section className={styles.section}>
|
||||
<h3>{title}</h3>
|
||||
|
||||
<AssetList
|
||||
assets={result?.results}
|
||||
showPagination={false}
|
||||
isLoading={loading}
|
||||
isLoading={loading || !query}
|
||||
/>
|
||||
|
||||
{action && action}
|
||||
</section>
|
||||
)
|
||||
@ -130,28 +135,24 @@ export default function HomePage(): ReactElement {
|
||||
<Bookmarks />
|
||||
</section>
|
||||
|
||||
{queryAndDids && (
|
||||
<SectionQueryResult
|
||||
title="Highest Liquidity"
|
||||
query={queryAndDids[0]}
|
||||
queryData={queryAndDids[1]}
|
||||
/>
|
||||
)}
|
||||
<SectionQueryResult
|
||||
title="Highest Liquidity"
|
||||
query={queryAndDids?.[0]}
|
||||
queryData={queryAndDids?.[1]}
|
||||
/>
|
||||
|
||||
{queryLatest && (
|
||||
<SectionQueryResult
|
||||
title="Recently Published"
|
||||
query={queryLatest}
|
||||
action={
|
||||
<Button
|
||||
style="text"
|
||||
to="/search?sort=metadata.created&sortOrder=desc"
|
||||
>
|
||||
All data sets and algorithms →
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<SectionQueryResult
|
||||
title="Recently Published"
|
||||
query={queryLatest}
|
||||
action={
|
||||
<Button
|
||||
style="text"
|
||||
to="/search?sort=metadata.created&sortOrder=desc"
|
||||
>
|
||||
All data sets and algorithms →
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -16,10 +16,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* Sledgehammer !important cause Next.js reordering of styles is clashing with
|
||||
our Blockies implementation.
|
||||
See https://github.com/oceanprotocol/market/issues/1143 */
|
||||
.imageWrap,
|
||||
.image {
|
||||
width: 96px;
|
||||
height: 96px;
|
||||
width: 96px !important;
|
||||
height: 96px !important;
|
||||
}
|
||||
|
||||
.imageWrap {
|
||||
|
@ -2,7 +2,7 @@ import React, { ReactElement } from 'react'
|
||||
import { useUserPreferences } from '@context/UserPreferences'
|
||||
import ExplorerLink from '@shared/ExplorerLink'
|
||||
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 Blockies from '@shared/atoms/Blockies'
|
||||
import styles from './Account.module.css'
|
||||
@ -29,12 +29,7 @@ export default function Account({
|
||||
) : accountId ? (
|
||||
<Blockies accountId={accountId} className={styles.image} />
|
||||
) : (
|
||||
<img
|
||||
src={jellyfish}
|
||||
className={styles.image}
|
||||
width="96"
|
||||
height="96"
|
||||
/>
|
||||
<Jellyfish className={styles.image} />
|
||||
)}
|
||||
</figure>
|
||||
|
||||
|
@ -1,28 +1,32 @@
|
||||
import { LoggerInstance } from '@oceanprotocol/lib'
|
||||
import React, { useEffect, useState, ReactElement } from 'react'
|
||||
import { useUserPreferences } from '@context/UserPreferences'
|
||||
import {
|
||||
getAccountLiquidityInOwnAssets,
|
||||
UserLiquidity,
|
||||
calculateUserLiquidity
|
||||
} from '@utils/subgraph'
|
||||
import { getAccountTVLInOwnAssets, UserLiquidity } from '@utils/subgraph'
|
||||
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/subgraph/PoolShares'
|
||||
import { getAccessDetailsForAssets } from '@utils/accessDetailsAndPricing'
|
||||
import { calculateUserTVL } from '@utils/pool'
|
||||
import Decimal from 'decimal.js'
|
||||
import { MAX_DECIMALS } from '@utils/constants'
|
||||
|
||||
async function getPoolSharesLiquidity(
|
||||
poolShares: PoolShare[]
|
||||
): Promise<number> {
|
||||
let totalLiquidity = 0
|
||||
): Promise<string> {
|
||||
let tvl = new Decimal(0)
|
||||
|
||||
for (const poolShare of poolShares) {
|
||||
const poolLiquidity = calculateUserLiquidity(poolShare)
|
||||
totalLiquidity += poolLiquidity
|
||||
const poolUserTvl = calculateUserTVL(
|
||||
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({
|
||||
@ -33,13 +37,13 @@ export default function Stats({
|
||||
const { chainIds } = useUserPreferences()
|
||||
const { poolShares, assets, assetsTotal, sales } = useProfile()
|
||||
|
||||
const [publisherLiquidity, setPublisherLiquidity] = useState<UserLiquidity>()
|
||||
const [totalLiquidity, setTotalLiquidity] = useState(0)
|
||||
const [publisherTvl, setPublisherTvl] = useState('0')
|
||||
const [totalTvl, setTotalTvl] = useState('0')
|
||||
|
||||
useEffect(() => {
|
||||
if (!accountId || chainIds.length === 0) {
|
||||
setPublisherLiquidity({ price: '0', oceanBalance: '0' })
|
||||
setTotalLiquidity(0)
|
||||
setPublisherTvl('0')
|
||||
setTotalTvl('0')
|
||||
}
|
||||
}, [accountId, chainIds])
|
||||
|
||||
@ -57,12 +61,12 @@ export default function Stats({
|
||||
)
|
||||
}
|
||||
}
|
||||
const userLiquidity = await getAccountLiquidityInOwnAssets(
|
||||
const userTvl = await getAccountTVLInOwnAssets(
|
||||
accountId,
|
||||
chainIds,
|
||||
accountPoolAdresses
|
||||
)
|
||||
setPublisherLiquidity(userLiquidity)
|
||||
setPublisherTvl(userTvl)
|
||||
} catch (error) {
|
||||
LoggerInstance.error(error.message)
|
||||
}
|
||||
@ -75,10 +79,10 @@ export default function Stats({
|
||||
|
||||
async function getTotalLiquidity() {
|
||||
try {
|
||||
const totalLiquidity = await getPoolSharesLiquidity(poolShares)
|
||||
setTotalLiquidity(totalLiquidity)
|
||||
const totalTvl = await getPoolSharesLiquidity(poolShares)
|
||||
setTotalTvl(totalTvl)
|
||||
} catch (error) {
|
||||
console.error('Error fetching pool shares: ', error.message)
|
||||
LoggerInstance.error('Error fetching pool shares: ', error.message)
|
||||
}
|
||||
}
|
||||
getTotalLiquidity()
|
||||
@ -87,14 +91,12 @@ export default function Stats({
|
||||
return (
|
||||
<div className={styles.stats}>
|
||||
<NumberUnit
|
||||
label="Liquidity in Own Assets"
|
||||
value={
|
||||
<Conversion price={publisherLiquidity?.price} hideApproximateSymbol />
|
||||
}
|
||||
label="TVL in Own Assets"
|
||||
value={<Conversion price={publisherTvl} hideApproximateSymbol />}
|
||||
/>
|
||||
<NumberUnit
|
||||
label="Total Liquidity"
|
||||
value={<Conversion price={`${totalLiquidity}`} hideApproximateSymbol />}
|
||||
label="TVL"
|
||||
value={<Conversion price={totalTvl} hideApproximateSymbol />}
|
||||
/>
|
||||
<NumberUnit label={`Sale${sales === 1 ? '' : 's'}`} value={sales} />
|
||||
<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:{' '}
|
||||
<PriceUnit
|
||||
price={Number(firstPrice) > 0 ? firstPrice : '-'}
|
||||
small
|
||||
size="small"
|
||||
conversion
|
||||
/>
|
||||
</aside>
|
||||
|
@ -260,6 +260,12 @@ export async function createTokensAndPricing(
|
||||
)
|
||||
LoggerInstance.log('[publish] pool.approve tx', txApprove, nftFactory)
|
||||
|
||||
if (!txApprove) {
|
||||
throw new Error(
|
||||
'MetaMask Approve TX Signature: User denied transaction signature'
|
||||
)
|
||||
}
|
||||
|
||||
const result = await nftFactory.createNftErc20WithPool(
|
||||
accountId,
|
||||
nftCreateData,
|
||||
|
Loading…
Reference in New Issue
Block a user