mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
User pool transactions on asset details (#193)
* refactored pool transactions component, output pool transactions on asset details * styling * remove sticky around asset actions * hasAddedLiquidity simplification * owner from useMetadata * refactor, styling, number formatting * refactor * toggle pattern
This commit is contained in:
parent
a5b7c66331
commit
be8307f34d
@ -25,10 +25,12 @@ const confettiConfig = {
|
|||||||
|
|
||||||
export default function SuccessConfetti({
|
export default function SuccessConfetti({
|
||||||
success,
|
success,
|
||||||
action
|
action,
|
||||||
|
className
|
||||||
}: {
|
}: {
|
||||||
success: string
|
success: string
|
||||||
action?: ReactNode
|
action?: ReactNode
|
||||||
|
className?: string
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
// Have some confetti upon success
|
// Have some confetti upon success
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -41,11 +43,11 @@ export default function SuccessConfetti({
|
|||||||
}, [success])
|
}, [success])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className={className || null}>
|
||||||
<Alert text={success} state="success" />
|
<Alert text={success} state="success" />
|
||||||
<span className={styles.action} data-confetti>
|
<span className={styles.action} data-confetti>
|
||||||
{action}
|
{action}
|
||||||
</span>
|
</span>
|
||||||
</>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
.table [role='row'] {
|
.table [role='row'] {
|
||||||
color: var(--font-color-text);
|
color: var(--font-color-text);
|
||||||
font-size: var(--font-size-small);
|
font-size: var(--font-size-small);
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table [class~='rdt_TableCol'] {
|
.table [class~='rdt_TableCol'] {
|
||||||
@ -26,6 +27,7 @@
|
|||||||
font-size: var(--font-size-small);
|
font-size: var(--font-size-small);
|
||||||
color: var(--color-secondary);
|
color: var(--color-secondary);
|
||||||
background: none;
|
background: none;
|
||||||
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table + div [class*='rdt_Pagination'] svg {
|
.table + div [class*='rdt_Pagination'] svg {
|
||||||
|
@ -17,6 +17,8 @@ export default function Table({
|
|||||||
columns,
|
columns,
|
||||||
isLoading,
|
isLoading,
|
||||||
emptyMessage,
|
emptyMessage,
|
||||||
|
pagination,
|
||||||
|
paginationPerPage,
|
||||||
...props
|
...props
|
||||||
}: TableProps): ReactElement {
|
}: TableProps): ReactElement {
|
||||||
return (
|
return (
|
||||||
@ -25,8 +27,8 @@ export default function Table({
|
|||||||
data={data}
|
data={data}
|
||||||
className={styles.table}
|
className={styles.table}
|
||||||
noHeader
|
noHeader
|
||||||
pagination={data?.length >= 9}
|
pagination={pagination || data?.length >= 9}
|
||||||
paginationPerPage={10}
|
paginationPerPage={paginationPerPage || 10}
|
||||||
paginationComponentOptions={{ noRowsPerPage: true }}
|
paginationComponentOptions={{ noRowsPerPage: true }}
|
||||||
noDataComponent={<Empty message={emptyMessage} />}
|
noDataComponent={<Empty message={emptyMessage} />}
|
||||||
progressPending={isLoading}
|
progressPending={isLoading}
|
||||||
|
@ -4,11 +4,13 @@ import { format, formatDistance } from 'date-fns'
|
|||||||
export default function Time({
|
export default function Time({
|
||||||
date,
|
date,
|
||||||
relative,
|
relative,
|
||||||
isUnix
|
isUnix,
|
||||||
|
className
|
||||||
}: {
|
}: {
|
||||||
date: string
|
date: string
|
||||||
relative?: boolean
|
relative?: boolean
|
||||||
isUnix?: boolean
|
isUnix?: boolean
|
||||||
|
className?: string
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const dateNew = isUnix ? new Date(Number(date) * 1000) : new Date(date)
|
const dateNew = isUnix ? new Date(Number(date) * 1000) : new Date(date)
|
||||||
const dateIso = dateNew.toISOString()
|
const dateIso = dateNew.toISOString()
|
||||||
@ -19,6 +21,7 @@ export default function Time({
|
|||||||
<time
|
<time
|
||||||
title={relative ? format(dateNew, 'MMMM d, yyyy') : undefined}
|
title={relative ? format(dateNew, 'MMMM d, yyyy') : undefined}
|
||||||
dateTime={dateIso}
|
dateTime={dateIso}
|
||||||
|
className={className || undefined}
|
||||||
>
|
>
|
||||||
{relative
|
{relative
|
||||||
? formatDistance(dateNew, Date.now(), { addSuffix: true })
|
? formatDistance(dateNew, Date.now(), { addSuffix: true })
|
||||||
|
3
src/components/molecules/PoolTransactions.module.css
Normal file
3
src/components/molecules/PoolTransactions.module.css
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.time {
|
||||||
|
color: var(--color-secondary);
|
||||||
|
}
|
127
src/components/molecules/PoolTransactions.tsx
Normal file
127
src/components/molecules/PoolTransactions.tsx
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
import { PoolTransaction } from '@oceanprotocol/lib/dist/node/balancer/OceanPool'
|
||||||
|
import { useOcean } from '@oceanprotocol/react'
|
||||||
|
import React, { ReactElement, useEffect, useState } from 'react'
|
||||||
|
import EtherscanLink from '../atoms/EtherscanLink'
|
||||||
|
import Time from '../atoms/Time'
|
||||||
|
import Table from '../atoms/Table'
|
||||||
|
import AssetTitle from './AssetTitle'
|
||||||
|
import styles from './PoolTransactions.module.css'
|
||||||
|
import { formatCurrency } from '@coingecko/cryptoformat'
|
||||||
|
import { useUserPreferences } from '../../providers/UserPreferences'
|
||||||
|
|
||||||
|
function formatNumber(number: number, locale: string) {
|
||||||
|
return formatCurrency(number, '', locale, false, {
|
||||||
|
significantFigures: 4
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function Title({ row }: { row: PoolTransaction }) {
|
||||||
|
const { ocean, networkId } = useOcean()
|
||||||
|
const [dtSymbol, setDtSymbol] = useState<string>()
|
||||||
|
const { locale } = useUserPreferences()
|
||||||
|
|
||||||
|
const title = row.tokenAmountIn
|
||||||
|
? `Add ${formatNumber(Number(row.tokenAmountIn), locale)} ${
|
||||||
|
dtSymbol || 'OCEAN'
|
||||||
|
}`
|
||||||
|
: `Remove ${formatNumber(Number(row.tokenAmountOut), locale)} ${
|
||||||
|
dtSymbol || 'OCEAN'
|
||||||
|
}`
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!ocean) return
|
||||||
|
|
||||||
|
async function getSymbol() {
|
||||||
|
const symbol = await ocean.datatokens.getSymbol(
|
||||||
|
row.tokenIn || row.tokenOut
|
||||||
|
)
|
||||||
|
setDtSymbol(symbol)
|
||||||
|
}
|
||||||
|
getSymbol()
|
||||||
|
}, [ocean, row])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<EtherscanLink networkId={networkId} path={`/tx/${row.transactionHash}`}>
|
||||||
|
{title}
|
||||||
|
</EtherscanLink>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getColumns(minimal?: boolean) {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
name: 'Title',
|
||||||
|
selector: function getTitleRow(row: PoolTransaction) {
|
||||||
|
return <Title row={row} />
|
||||||
|
},
|
||||||
|
minWidth: '14rem',
|
||||||
|
grow: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Data Set',
|
||||||
|
selector: function getAssetRow(row: PoolTransaction) {
|
||||||
|
const did = row.dtAddress.replace('0x', 'did:op:')
|
||||||
|
return <AssetTitle did={did} />
|
||||||
|
},
|
||||||
|
omit: minimal
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Time',
|
||||||
|
selector: function getTimeRow(row: PoolTransaction) {
|
||||||
|
return (
|
||||||
|
<Time
|
||||||
|
className={styles.time}
|
||||||
|
date={row.timestamp.toString()}
|
||||||
|
relative
|
||||||
|
isUnix
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function PoolTransactions({
|
||||||
|
poolAddress,
|
||||||
|
minimal
|
||||||
|
}: {
|
||||||
|
poolAddress?: string
|
||||||
|
minimal?: boolean
|
||||||
|
}): ReactElement {
|
||||||
|
const { ocean, accountId } = useOcean()
|
||||||
|
const [logs, setLogs] = useState<PoolTransaction[]>()
|
||||||
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function getLogs() {
|
||||||
|
if (!ocean || !accountId) return
|
||||||
|
|
||||||
|
setIsLoading(true)
|
||||||
|
const logs = poolAddress
|
||||||
|
? await ocean.pool.getPoolLogs(poolAddress, 0, accountId)
|
||||||
|
: await ocean.pool.getAllPoolLogs(accountId)
|
||||||
|
// sort logs by date, newest first
|
||||||
|
const logsSorted = logs.sort((a, b) => {
|
||||||
|
if (a.timestamp > b.timestamp) return -1
|
||||||
|
if (a.timestamp < b.timestamp) return 1
|
||||||
|
return 0
|
||||||
|
})
|
||||||
|
setLogs(logsSorted)
|
||||||
|
setIsLoading(false)
|
||||||
|
}
|
||||||
|
getLogs()
|
||||||
|
}, [ocean, accountId, poolAddress])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Table
|
||||||
|
columns={getColumns(minimal)}
|
||||||
|
data={logs}
|
||||||
|
isLoading={isLoading}
|
||||||
|
noTableHead={minimal}
|
||||||
|
dense={minimal}
|
||||||
|
pagination={minimal ? logs?.length >= 4 : logs?.length >= 9}
|
||||||
|
paginationPerPage={minimal ? 5 : 10}
|
||||||
|
emptyMessage="Your pool transactions will show up here"
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
@ -11,7 +11,7 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.actions + div {
|
.success {
|
||||||
margin-top: calc(var(--spacer) / 2);
|
margin-top: calc(var(--spacer) / 2);
|
||||||
margin-bottom: calc(var(--spacer) / 2);
|
margin-bottom: calc(var(--spacer) / 2);
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,7 @@ export default function Actions({
|
|||||||
</div>
|
</div>
|
||||||
{txId && (
|
{txId && (
|
||||||
<SuccessConfetti
|
<SuccessConfetti
|
||||||
|
className={styles.success}
|
||||||
success={successMessage}
|
success={successMessage}
|
||||||
action={
|
action={
|
||||||
<EtherscanLink networkId={networkId} path={`/tx/${txId}`}>
|
<EtherscanLink networkId={networkId} path={`/tx/${txId}`}>
|
||||||
|
@ -33,9 +33,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-size: var(--font-size-base);
|
composes: title from './index.module.css';
|
||||||
margin-bottom: calc(var(--spacer) / 3);
|
|
||||||
color: var(--color-secondary);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.totalLiquidity {
|
.totalLiquidity {
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
.transactions {
|
||||||
|
composes: container from './index.module.css';
|
||||||
|
border-top: 1px solid var(--border-color);
|
||||||
|
margin-top: calc(var(--spacer) / 1.5);
|
||||||
|
padding: calc(var(--spacer) / 1.5);
|
||||||
|
background: var(--background-highlight);
|
||||||
|
margin-bottom: -2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transactions [class*='rdt_Pagination'] {
|
||||||
|
margin-bottom: -1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
composes: title from './index.module.css';
|
||||||
|
margin-bottom: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title:hover .toggle {
|
||||||
|
color: var(--color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.title + div {
|
||||||
|
margin-top: calc(var(--spacer) / 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle {
|
||||||
|
color: var(--color-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle svg {
|
||||||
|
display: inline-block;
|
||||||
|
width: var(--font-size-mini);
|
||||||
|
height: var(--font-size-mini);
|
||||||
|
fill: currentColor;
|
||||||
|
transition: 0.2s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.open .toggle svg {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
37
src/components/organisms/AssetActions/Pool/Transactions.tsx
Normal file
37
src/components/organisms/AssetActions/Pool/Transactions.tsx
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import React, { ReactElement, useState } from 'react'
|
||||||
|
import Button from '../../../atoms/Button'
|
||||||
|
import PoolTransactions from '../../../molecules/PoolTransactions'
|
||||||
|
import styles from './Transactions.module.css'
|
||||||
|
import { ReactComponent as Caret } from '../../../../images/caret.svg'
|
||||||
|
|
||||||
|
export default function Transactions({
|
||||||
|
poolAddress
|
||||||
|
}: {
|
||||||
|
poolAddress: string
|
||||||
|
}): ReactElement {
|
||||||
|
const [open, setOpen] = useState(false)
|
||||||
|
|
||||||
|
function handleClick() {
|
||||||
|
setOpen(!open)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={`${styles.transactions} ${open === true ? styles.open : ''}`}
|
||||||
|
>
|
||||||
|
{/* TODO: onClick on h3 is nasty but we're in a hurry */}
|
||||||
|
<h3 className={styles.title} onClick={handleClick}>
|
||||||
|
Your Pool Transactions{' '}
|
||||||
|
<Button
|
||||||
|
style="text"
|
||||||
|
size="small"
|
||||||
|
onClick={handleClick}
|
||||||
|
className={styles.toggle}
|
||||||
|
>
|
||||||
|
{open ? 'Hide' : 'Show'} <Caret />
|
||||||
|
</Button>
|
||||||
|
</h3>
|
||||||
|
{open === true && <PoolTransactions poolAddress={poolAddress} minimal />}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
@ -1,10 +1,14 @@
|
|||||||
.dataToken {
|
.container {
|
||||||
padding-bottom: calc(var(--spacer) / 1.5);
|
|
||||||
font-size: var(--font-size-large);
|
|
||||||
margin-left: -2rem;
|
margin-left: -2rem;
|
||||||
margin-right: -2rem;
|
margin-right: -2rem;
|
||||||
padding-left: calc(var(--spacer) / 1.5);
|
padding-left: calc(var(--spacer) / 1.5);
|
||||||
padding-right: calc(var(--spacer) / 1.5);
|
padding-right: calc(var(--spacer) / 1.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dataToken {
|
||||||
|
composes: container;
|
||||||
|
padding-bottom: calc(var(--spacer) / 1.5);
|
||||||
|
font-size: var(--font-size-large);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
@ -21,13 +25,18 @@
|
|||||||
margin-right: calc(var(--spacer) / 3);
|
margin-right: calc(var(--spacer) / 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: var(--font-size-base);
|
||||||
|
margin-bottom: calc(var(--spacer) / 3);
|
||||||
|
color: var(--color-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
.update {
|
.update {
|
||||||
|
composes: container;
|
||||||
font-size: var(--font-size-mini);
|
font-size: var(--font-size-mini);
|
||||||
color: var(--color-secondary);
|
color: var(--color-secondary);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border-top: 1px solid var(--border-color);
|
border-top: 1px solid var(--border-color);
|
||||||
margin-left: -2rem;
|
|
||||||
margin-right: -2rem;
|
|
||||||
padding-top: calc(var(--spacer) / 4);
|
padding-top: calc(var(--spacer) / 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,8 @@ import EtherscanLink from '../../../atoms/EtherscanLink'
|
|||||||
import Token from './Token'
|
import Token from './Token'
|
||||||
import TokenList from './TokenList'
|
import TokenList from './TokenList'
|
||||||
import { graphql, useStaticQuery } from 'gatsby'
|
import { graphql, useStaticQuery } from 'gatsby'
|
||||||
|
import PoolTransactions from '../../../molecules/PoolTransactions'
|
||||||
|
import Transactions from './Transactions'
|
||||||
|
|
||||||
export interface Balance {
|
export interface Balance {
|
||||||
ocean: number
|
ocean: number
|
||||||
@ -44,7 +46,7 @@ export default function Pool({ ddo }: { ddo: DDO }): ReactElement {
|
|||||||
const content = data.content.edges[0].node.childContentJson.pool
|
const content = data.content.edges[0].node.childContentJson.pool
|
||||||
|
|
||||||
const { ocean, accountId, networkId } = useOcean()
|
const { ocean, accountId, networkId } = useOcean()
|
||||||
const { price, refreshPrice } = useMetadata(ddo)
|
const { price, refreshPrice, owner } = useMetadata(ddo)
|
||||||
const { dtSymbol } = usePricing(ddo)
|
const { dtSymbol } = usePricing(ddo)
|
||||||
|
|
||||||
const [poolTokens, setPoolTokens] = useState<string>()
|
const [poolTokens, setPoolTokens] = useState<string>()
|
||||||
@ -71,16 +73,12 @@ export default function Pool({ ddo }: { ddo: DDO }): ReactElement {
|
|||||||
const [refreshPool, setRefreshPool] = useState(false)
|
const [refreshPool, setRefreshPool] = useState(false)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const hasAddedLiquidity =
|
|
||||||
userLiquidity && (userLiquidity.ocean > 0 || userLiquidity.datatoken > 0)
|
|
||||||
setHasAddedLiquidity(hasAddedLiquidity)
|
|
||||||
|
|
||||||
const poolShare =
|
const poolShare =
|
||||||
price?.ocean &&
|
price?.ocean &&
|
||||||
price?.datatoken &&
|
price?.datatoken &&
|
||||||
userLiquidity &&
|
((Number(poolTokens) / Number(totalPoolTokens)) * 100).toFixed(5)
|
||||||
((Number(poolTokens) / Number(totalPoolTokens)) * 100).toFixed(2)
|
|
||||||
setPoolShare(poolShare)
|
setPoolShare(poolShare)
|
||||||
|
setHasAddedLiquidity(Number(poolShare) > 0)
|
||||||
|
|
||||||
const totalUserLiquidityInOcean =
|
const totalUserLiquidityInOcean =
|
||||||
userLiquidity?.ocean + userLiquidity?.datatoken * price?.value
|
userLiquidity?.ocean + userLiquidity?.datatoken * price?.value
|
||||||
@ -129,15 +127,13 @@ export default function Pool({ ddo }: { ddo: DDO }): ReactElement {
|
|||||||
//
|
//
|
||||||
// Get everything the creator put into the pool
|
// Get everything the creator put into the pool
|
||||||
//
|
//
|
||||||
|
|
||||||
const creatorPoolTokens = await ocean.pool.sharesBalance(
|
const creatorPoolTokens = await ocean.pool.sharesBalance(
|
||||||
ddo.publicKey[0].owner,
|
owner,
|
||||||
price.address
|
price.address
|
||||||
)
|
)
|
||||||
setCreatorPoolTokens(creatorPoolTokens)
|
setCreatorPoolTokens(creatorPoolTokens)
|
||||||
|
|
||||||
// calculate creator's provided liquidity based on pool tokens
|
// Calculate creator's provided liquidity based on pool tokens
|
||||||
|
|
||||||
const creatorOceanBalance =
|
const creatorOceanBalance =
|
||||||
(Number(creatorPoolTokens) / Number(totalPoolTokens)) * price.ocean
|
(Number(creatorPoolTokens) / Number(totalPoolTokens)) * price.ocean
|
||||||
|
|
||||||
@ -287,6 +283,8 @@ export default function Pool({ ddo }: { ddo: DDO }): ReactElement {
|
|||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{accountId && <Transactions poolAddress={price?.address} />}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
@ -20,9 +20,7 @@
|
|||||||
grid-template-columns: 1.5fr 1fr;
|
grid-template-columns: 1.5fr 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sticky {
|
.actions {
|
||||||
position: sticky;
|
|
||||||
top: calc(var(--spacer) / 2);
|
|
||||||
margin-top: var(--spacer);
|
margin-top: var(--spacer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,10 +106,8 @@ export default function AssetContent({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div className={styles.actions}>
|
||||||
<div className={styles.sticky}>
|
<AssetActions ddo={ddo} />
|
||||||
<AssetActions ddo={ddo} />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
)
|
)
|
||||||
|
@ -1,81 +0,0 @@
|
|||||||
import { PoolTransaction } from '@oceanprotocol/lib/dist/node/balancer/OceanPool'
|
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
|
||||||
import React, { ReactElement, useEffect, useState } from 'react'
|
|
||||||
import EtherscanLink from '../../atoms/EtherscanLink'
|
|
||||||
import Time from '../../atoms/Time'
|
|
||||||
import Table from '../../atoms/Table'
|
|
||||||
import AssetTitle from '../../molecules/AssetTitle'
|
|
||||||
|
|
||||||
function Title({ row }: { row: PoolTransaction }) {
|
|
||||||
const { ocean, networkId } = useOcean()
|
|
||||||
const [dtSymbol, setDtSymbol] = useState<string>()
|
|
||||||
|
|
||||||
const title = row.tokenAmountIn
|
|
||||||
? `Add ${row.tokenAmountIn} ${dtSymbol || 'OCEAN'}`
|
|
||||||
: `Remove ${row.tokenAmountOut} ${dtSymbol || 'OCEAN'}`
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!ocean) return
|
|
||||||
|
|
||||||
async function getSymbol() {
|
|
||||||
const symbol = await ocean.datatokens.getSymbol(
|
|
||||||
row.tokenIn || row.tokenOut
|
|
||||||
)
|
|
||||||
setDtSymbol(symbol)
|
|
||||||
}
|
|
||||||
getSymbol()
|
|
||||||
}, [ocean, row])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<EtherscanLink networkId={networkId} path={`/tx/${row.transactionHash}`}>
|
|
||||||
{title}
|
|
||||||
</EtherscanLink>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const columns = [
|
|
||||||
{
|
|
||||||
name: 'Title',
|
|
||||||
selector: function getTitleRow(row: PoolTransaction) {
|
|
||||||
return <Title row={row} />
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Data Set',
|
|
||||||
selector: function getAssetRow(row: PoolTransaction) {
|
|
||||||
const did = row.dtAddress.replace('0x', 'did:op:')
|
|
||||||
return <AssetTitle did={did} />
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Time',
|
|
||||||
selector: function getTimeRow(row: PoolTransaction) {
|
|
||||||
return <Time date={row.timestamp.toString()} relative isUnix />
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
export default function PoolTransactions(): ReactElement {
|
|
||||||
const { ocean, accountId } = useOcean()
|
|
||||||
const [logs, setLogs] = useState<PoolTransaction[]>()
|
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
async function getLogs() {
|
|
||||||
if (!ocean || !accountId) return
|
|
||||||
setIsLoading(true)
|
|
||||||
const logs = await ocean.pool.getAllPoolLogs(accountId)
|
|
||||||
// sort logs by date, newest first
|
|
||||||
const logsSorted = logs.sort((a, b) => {
|
|
||||||
if (a.timestamp > b.timestamp) return -1
|
|
||||||
if (a.timestamp < b.timestamp) return 1
|
|
||||||
return 0
|
|
||||||
})
|
|
||||||
setLogs(logsSorted)
|
|
||||||
setIsLoading(false)
|
|
||||||
}
|
|
||||||
getLogs()
|
|
||||||
}, [ocean, accountId])
|
|
||||||
|
|
||||||
return <Table columns={columns} data={logs} isLoading={isLoading} />
|
|
||||||
}
|
|
@ -2,7 +2,7 @@ import React, { ReactElement, ReactNode } from 'react'
|
|||||||
import ComputeJobs from './ComputeJobs'
|
import ComputeJobs from './ComputeJobs'
|
||||||
import styles from './index.module.css'
|
import styles from './index.module.css'
|
||||||
import PoolShares from './PoolShares'
|
import PoolShares from './PoolShares'
|
||||||
import PoolTransactions from './PoolTransactions'
|
import PoolTransactions from '../../molecules/PoolTransactions'
|
||||||
import PublishedList from './PublishedList'
|
import PublishedList from './PublishedList'
|
||||||
|
|
||||||
const sections = [
|
const sections = [
|
||||||
|
Loading…
x
Reference in New Issue
Block a user