mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
special veOCEAN number treatment (#1782)
* special veOCEAN number treatment * path fix * fix duplicate AllLocked declarations * so many duplicate declarations * bold numbers on asset teasers * update test * unify number formatting in more generic `formatNumber()` method
This commit is contained in:
parent
b99634a3b3
commit
4b4a926f89
@ -1,5 +1,20 @@
|
|||||||
|
import { formatCurrency } from '@coingecko/cryptoformat'
|
||||||
import { Decimal } from 'decimal.js'
|
import { Decimal } from 'decimal.js'
|
||||||
|
|
||||||
|
export function formatNumber(
|
||||||
|
price: number,
|
||||||
|
locale: string,
|
||||||
|
decimals?: string
|
||||||
|
): string {
|
||||||
|
return formatCurrency(price, '', locale, false, {
|
||||||
|
// Not exactly clear what `significant figures` are for this library,
|
||||||
|
// but setting this seems to give us the formatting we want.
|
||||||
|
// See https://github.com/oceanprotocol/market/issues/70
|
||||||
|
significantFigures: 4,
|
||||||
|
...(decimals && { decimalPlaces: Number(decimals) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Run decimal.js comparison
|
// Run decimal.js comparison
|
||||||
// http://mikemcl.github.io/decimal.js/#cmp
|
// http://mikemcl.github.io/decimal.js/#cmp
|
||||||
export function compareAsBN(balance: string, price: string): boolean {
|
export function compareAsBN(balance: string, price: string): boolean {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { AllLocked } from 'src/@types/subgraph/AllLocked'
|
import { AllLockedQuery } from 'src/@types/subgraph/AllLockedQuery'
|
||||||
import { OwnAllocations } from 'src/@types/subgraph/OwnAllocations'
|
import { OwnAllocationsQuery } from 'src/@types/subgraph/OwnAllocationsQuery'
|
||||||
import { NftOwnAllocation } from 'src/@types/subgraph/NftOwnAllocation'
|
import { NftOwnAllocationQuery } from 'src/@types/subgraph/NftOwnAllocationQuery'
|
||||||
import { OceanLocked } from 'src/@types/subgraph/OceanLocked'
|
import { OceanLockedQuery } from 'src/@types/subgraph/OceanLockedQuery'
|
||||||
import { gql, OperationResult } from 'urql'
|
import { gql, OperationResult } from 'urql'
|
||||||
import { fetchData, getQueryContext } from './subgraph'
|
import { fetchData, getQueryContext } from './subgraph'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
@ -12,11 +12,11 @@ import {
|
|||||||
NetworkType
|
NetworkType
|
||||||
} from '@hooks/useNetworkMetadata'
|
} from '@hooks/useNetworkMetadata'
|
||||||
import { getAssetsFromNftList } from './aquarius'
|
import { getAssetsFromNftList } from './aquarius'
|
||||||
import { chainIdsSupported } from 'app.config'
|
import { chainIdsSupported } from '../../app.config'
|
||||||
import { Asset } from '@oceanprotocol/lib'
|
import { Asset } from '@oceanprotocol/lib'
|
||||||
|
|
||||||
const AllLocked = gql`
|
const AllLocked = gql`
|
||||||
query AllLocked {
|
query AllLockedQuery {
|
||||||
veOCEANs(first: 1000) {
|
veOCEANs(first: 1000) {
|
||||||
lockedAmount
|
lockedAmount
|
||||||
}
|
}
|
||||||
@ -24,7 +24,7 @@ const AllLocked = gql`
|
|||||||
`
|
`
|
||||||
|
|
||||||
const OwnAllocations = gql`
|
const OwnAllocations = gql`
|
||||||
query OwnAllocations($address: String) {
|
query OwnAllocationsQuery($address: String) {
|
||||||
veAllocations(where: { allocationUser: $address }) {
|
veAllocations(where: { allocationUser: $address }) {
|
||||||
id
|
id
|
||||||
nftAddress
|
nftAddress
|
||||||
@ -33,7 +33,7 @@ const OwnAllocations = gql`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
const NftOwnAllocation = gql`
|
const NftOwnAllocation = gql`
|
||||||
query NftOwnAllocation($address: String, $nftAddress: String) {
|
query NftOwnAllocationQuery($address: String, $nftAddress: String) {
|
||||||
veAllocations(
|
veAllocations(
|
||||||
where: { allocationUser: $address, nftAddress: $nftAddress }
|
where: { allocationUser: $address, nftAddress: $nftAddress }
|
||||||
) {
|
) {
|
||||||
@ -42,7 +42,7 @@ const NftOwnAllocation = gql`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
const OceanLocked = gql`
|
const OceanLocked = gql`
|
||||||
query OceanLocked($address: ID!) {
|
query OceanLockedQuery($address: ID!) {
|
||||||
veOCEAN(id: $address) {
|
veOCEAN(id: $address) {
|
||||||
id
|
id
|
||||||
lockedAmount
|
lockedAmount
|
||||||
@ -87,7 +87,7 @@ export async function getNftOwnAllocation(
|
|||||||
): Promise<number> {
|
): Promise<number> {
|
||||||
const veNetworkId = getVeChainNetworkId(networkId)
|
const veNetworkId = getVeChainNetworkId(networkId)
|
||||||
const queryContext = getQueryContext(veNetworkId)
|
const queryContext = getQueryContext(veNetworkId)
|
||||||
const fetchedAllocation: OperationResult<NftOwnAllocation, any> =
|
const fetchedAllocation: OperationResult<NftOwnAllocationQuery, any> =
|
||||||
await fetchData(
|
await fetchData(
|
||||||
NftOwnAllocation,
|
NftOwnAllocation,
|
||||||
{
|
{
|
||||||
@ -115,7 +115,7 @@ export async function getTotalAllocatedAndLocked(): Promise<TotalVe> {
|
|||||||
0
|
0
|
||||||
)
|
)
|
||||||
|
|
||||||
const fetchedLocked: OperationResult<AllLocked, any> = await fetchData(
|
const fetchedLocked: OperationResult<AllLockedQuery, any> = await fetchData(
|
||||||
AllLocked,
|
AllLocked,
|
||||||
null,
|
null,
|
||||||
queryContext
|
queryContext
|
||||||
@ -136,11 +136,12 @@ export async function getLocked(
|
|||||||
const veNetworkIds = getVeChainNetworkIds(networkIds)
|
const veNetworkIds = getVeChainNetworkIds(networkIds)
|
||||||
for (let i = 0; i < veNetworkIds.length; i++) {
|
for (let i = 0; i < veNetworkIds.length; i++) {
|
||||||
const queryContext = getQueryContext(veNetworkIds[i])
|
const queryContext = getQueryContext(veNetworkIds[i])
|
||||||
const fetchedLocked: OperationResult<OceanLocked, any> = await fetchData(
|
const fetchedLocked: OperationResult<OceanLockedQuery, any> =
|
||||||
OceanLocked,
|
await fetchData(
|
||||||
{ address: userAddress.toLowerCase() },
|
OceanLocked,
|
||||||
queryContext
|
{ address: userAddress.toLowerCase() },
|
||||||
)
|
queryContext
|
||||||
|
)
|
||||||
|
|
||||||
fetchedLocked.data?.veOCEAN?.lockedAmount &&
|
fetchedLocked.data?.veOCEAN?.lockedAmount &&
|
||||||
(total += Number(fetchedLocked.data?.veOCEAN?.lockedAmount))
|
(total += Number(fetchedLocked.data?.veOCEAN?.lockedAmount))
|
||||||
@ -157,7 +158,7 @@ export async function getOwnAllocations(
|
|||||||
const veNetworkIds = getVeChainNetworkIds(networkIds)
|
const veNetworkIds = getVeChainNetworkIds(networkIds)
|
||||||
for (let i = 0; i < veNetworkIds.length; i++) {
|
for (let i = 0; i < veNetworkIds.length; i++) {
|
||||||
const queryContext = getQueryContext(veNetworkIds[i])
|
const queryContext = getQueryContext(veNetworkIds[i])
|
||||||
const fetchedAllocations: OperationResult<OwnAllocations, any> =
|
const fetchedAllocations: OperationResult<OwnAllocationsQuery, any> =
|
||||||
await fetchData(
|
await fetchData(
|
||||||
OwnAllocations,
|
OwnAllocations,
|
||||||
{ address: userAddress.toLowerCase() },
|
{ address: userAddress.toLowerCase() },
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.footer {
|
.footer {
|
||||||
margin-top: calc(var(--spacer) / 12);
|
margin-top: calc(var(--spacer) / 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
.typeLabel {
|
.typeLabel {
|
||||||
|
@ -8,8 +8,8 @@ import AssetType from '@shared/AssetType'
|
|||||||
import NetworkName from '@shared/NetworkName'
|
import NetworkName from '@shared/NetworkName'
|
||||||
import styles from './index.module.css'
|
import styles from './index.module.css'
|
||||||
import { getServiceByName } from '@utils/ddo'
|
import { getServiceByName } from '@utils/ddo'
|
||||||
import { formatPrice } from '@shared/Price/PriceUnit'
|
|
||||||
import { useUserPreferences } from '@context/UserPreferences'
|
import { useUserPreferences } from '@context/UserPreferences'
|
||||||
|
import { formatNumber } from '@utils/numbers'
|
||||||
|
|
||||||
export declare type AssetTeaserProps = {
|
export declare type AssetTeaserProps = {
|
||||||
asset: AssetExtended
|
asset: AssetExtended
|
||||||
@ -77,23 +77,37 @@ export default function AssetTeaser({
|
|||||||
<footer className={styles.footer}>
|
<footer className={styles.footer}>
|
||||||
{allocated && allocated > 0 ? (
|
{allocated && allocated > 0 ? (
|
||||||
<span className={styles.typeLabel}>
|
<span className={styles.typeLabel}>
|
||||||
{allocated < 0
|
{allocated < 0 ? (
|
||||||
? ''
|
''
|
||||||
: `${formatPrice(allocated, locale)} veOCEAN`}
|
) : (
|
||||||
|
<>
|
||||||
|
<strong>{formatNumber(allocated, locale, '0')}</strong>{' '}
|
||||||
|
veOCEAN
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</span>
|
</span>
|
||||||
) : null}
|
) : null}
|
||||||
{orders && orders > 0 ? (
|
{orders && orders > 0 ? (
|
||||||
<span className={styles.typeLabel}>
|
<span className={styles.typeLabel}>
|
||||||
{orders < 0
|
{orders < 0 ? (
|
||||||
? 'N/A'
|
'N/A'
|
||||||
: `${orders} ${orders === 1 ? 'sale' : 'sales'}`}
|
) : (
|
||||||
|
<>
|
||||||
|
<strong>{orders}</strong> {orders === 1 ? 'sale' : 'sales'}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</span>
|
</span>
|
||||||
) : null}
|
) : null}
|
||||||
{asset.views && asset.views > 0 ? (
|
{asset.views && asset.views > 0 ? (
|
||||||
<span className={styles.typeLabel}>
|
<span className={styles.typeLabel}>
|
||||||
{asset.views < 0
|
{asset.views < 0 ? (
|
||||||
? 'N/A'
|
'N/A'
|
||||||
: `${asset.views} ${asset.views === 1 ? 'view' : 'views'}`}
|
) : (
|
||||||
|
<>
|
||||||
|
<strong>{asset.views}</strong>{' '}
|
||||||
|
{asset.views === 1 ? 'view' : 'views'}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</span>
|
</span>
|
||||||
) : null}
|
) : null}
|
||||||
</footer>
|
</footer>
|
||||||
|
@ -1,17 +1,8 @@
|
|||||||
import React, { ReactElement } from 'react'
|
import React, { ReactElement } from 'react'
|
||||||
import { formatCurrency } from '@coingecko/cryptoformat'
|
|
||||||
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 { formatNumber } from '@utils/numbers'
|
||||||
export function formatPrice(price: number, locale: string): string {
|
|
||||||
return formatCurrency(price, '', locale, false, {
|
|
||||||
// Not exactly clear what `significant figures` are for this library,
|
|
||||||
// but setting this seems to give us the formatting we want.
|
|
||||||
// See https://github.com/oceanprotocol/market/issues/70
|
|
||||||
significantFigures: 4
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function PriceUnit({
|
export default function PriceUnit({
|
||||||
price,
|
price,
|
||||||
@ -19,7 +10,8 @@ export default function PriceUnit({
|
|||||||
size = 'small',
|
size = 'small',
|
||||||
conversion,
|
conversion,
|
||||||
symbol,
|
symbol,
|
||||||
type
|
type,
|
||||||
|
decimals
|
||||||
}: {
|
}: {
|
||||||
price: number
|
price: number
|
||||||
type?: string
|
type?: string
|
||||||
@ -27,6 +19,7 @@ export default function PriceUnit({
|
|||||||
size?: 'small' | 'mini' | 'large'
|
size?: 'small' | 'mini' | 'large'
|
||||||
conversion?: boolean
|
conversion?: boolean
|
||||||
symbol?: string
|
symbol?: string
|
||||||
|
decimals?: string
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const { locale } = useUserPreferences()
|
const { locale } = useUserPreferences()
|
||||||
|
|
||||||
@ -37,7 +30,7 @@ export default function PriceUnit({
|
|||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<div>
|
<div>
|
||||||
{Number.isNaN(price) ? '-' : formatPrice(price, locale)}{' '}
|
{Number.isNaN(price) ? '-' : formatNumber(price, locale, decimals)}{' '}
|
||||||
<span className={styles.symbol}>{symbol}</span>
|
<span className={styles.symbol}>{symbol}</span>
|
||||||
</div>
|
</div>
|
||||||
{conversion && <Conversion price={price} symbol={symbol} />}
|
{conversion && <Conversion price={price} symbol={symbol} />}
|
||||||
|
@ -2,7 +2,7 @@ import { useAsset } from '@context/Asset'
|
|||||||
import { useUserPreferences } from '@context/UserPreferences'
|
import { useUserPreferences } from '@context/UserPreferences'
|
||||||
import { useWeb3 } from '@context/Web3'
|
import { useWeb3 } from '@context/Web3'
|
||||||
import Tooltip from '@shared/atoms/Tooltip'
|
import Tooltip from '@shared/atoms/Tooltip'
|
||||||
import { formatPrice } from '@shared/Price/PriceUnit'
|
import { formatNumber } from '@utils/numbers'
|
||||||
import { getNftOwnAllocation } from '@utils/veAllocation'
|
import { getNftOwnAllocation } from '@utils/veAllocation'
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import styles from './index.module.css'
|
import styles from './index.module.css'
|
||||||
@ -33,8 +33,8 @@ export default function AssetStats() {
|
|||||||
{asset?.stats?.allocated && asset?.stats?.allocated > 0 ? (
|
{asset?.stats?.allocated && asset?.stats?.allocated > 0 ? (
|
||||||
<span className={styles.stat}>
|
<span className={styles.stat}>
|
||||||
<span className={styles.number}>
|
<span className={styles.number}>
|
||||||
{formatPrice(asset.stats.allocated, locale)}
|
{formatNumber(asset.stats.allocated, locale, '0')}
|
||||||
</span>
|
</span>{' '}
|
||||||
veOCEAN
|
veOCEAN
|
||||||
</span>
|
</span>
|
||||||
) : null}
|
) : null}
|
||||||
|
@ -124,8 +124,19 @@ export default function MarketStats(): ReactElement {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<PriceUnit price={total.veLocked} symbol="OCEAN" size="small" /> locked.{' '}
|
<PriceUnit
|
||||||
<PriceUnit price={total.veAllocated} symbol="veOCEAN" size="small" />{' '}
|
decimals="0"
|
||||||
|
price={total.veLocked}
|
||||||
|
symbol="OCEAN"
|
||||||
|
size="small"
|
||||||
|
/>{' '}
|
||||||
|
locked.{' '}
|
||||||
|
<PriceUnit
|
||||||
|
decimals="0"
|
||||||
|
price={total.veAllocated}
|
||||||
|
symbol="veOCEAN"
|
||||||
|
size="small"
|
||||||
|
/>{' '}
|
||||||
allocated.
|
allocated.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -32,7 +32,7 @@ describe('components/Home/MostViews', () => {
|
|||||||
)
|
)
|
||||||
queryMetadataMock.mockResolvedValue(queryMetadataBaseReturn)
|
queryMetadataMock.mockResolvedValue(queryMetadataBaseReturn)
|
||||||
render(<MostViews />)
|
render(<MostViews />)
|
||||||
await screen.findByText('666 views')
|
await screen.findByText('666')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('catches errors', async () => {
|
it('catches errors', async () => {
|
||||||
|
Loading…
Reference in New Issue
Block a user