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 './AssetListTitle' import styles from './PoolTransactions.module.css' import { useUserPreferences } from '../../providers/UserPreferences' import { Ocean } from '@oceanprotocol/lib' import { formatPrice } from '../atoms/Price/PriceUnit' import { gql, useQuery } from '@apollo/client' import { TransactionHistory, TransactionHistory_poolTransactions as TransactionHistoryPoolTransactions } from '../../@types/apollo/TransactionHistory' import web3 from 'web3' const txHistoryQueryByPool = gql` query TransactionHistoryByPool($user: String, $pool: String) { poolTransactions( orderBy: timestamp orderDirection: desc where: { userAddress: $user, poolAddress: $pool } first: 1000 ) { tx event timestamp poolAddress { datatokenAddress } tokens { value type tokenAddress } } } ` const txHistoryQuery = gql` query TransactionHistory($user: String) { poolTransactions( orderBy: timestamp orderDirection: desc where: { userAddress: $user } first: 1000 ) { tx event timestamp poolAddress { datatokenAddress } tokens { value type tokenAddress } } } ` async function getSymbol(ocean: Ocean, tokenAddress: string) { const symbol = ocean.pool.oceanAddress.toLowerCase() === tokenAddress.toLowerCase() ? 'OCEAN' : await ocean.datatokens.getSymbol(tokenAddress) return symbol } async function getTitle( ocean: Ocean, row: TransactionHistoryPoolTransactions, locale: string ) { let title = '' switch (row.event) { case 'swap': { const inToken = row.tokens.filter((x) => x.type === 'in')[0] const inTokenSymbol = await getSymbol(ocean, inToken.tokenAddress) const outToken = row.tokens.filter((x) => x.type === 'out')[0] const outTokenSymbol = await getSymbol(ocean, outToken.tokenAddress) title += `Swap ${formatPrice( Math.abs(inToken.value).toString(), locale )}${inTokenSymbol} for ${formatPrice( Math.abs(outToken.value).toString(), locale )}${outTokenSymbol}` break } case 'setup': { const firstToken = row.tokens.filter( (x) => x.tokenAddress.toLowerCase() === ocean.pool.oceanAddress.toLowerCase() )[0] const firstTokenSymbol = await getSymbol(ocean, firstToken.tokenAddress) const secondToken = row.tokens.filter( (x) => x.tokenAddress.toLowerCase() !== ocean.pool.oceanAddress.toLowerCase() )[0] const secondTokenSymbol = await getSymbol(ocean, secondToken.tokenAddress) title += `Create pool with ${formatPrice( Math.abs(firstToken.value).toString(), locale )}${firstTokenSymbol} and ${formatPrice( Math.abs(secondToken.value).toString(), locale )}${secondTokenSymbol}` break } case 'join': case 'exit': { for (let i = 0; i < row.tokens.length; i++) { const tokenSymbol = await getSymbol(ocean, row.tokens[i].tokenAddress) if (i > 0) title += '\n' title += `${row.event === 'join' ? 'Add' : 'Remove'} ${formatPrice( Math.abs(row.tokens[i].value).toString(), locale )}${tokenSymbol}` } break } } return title } function Title({ row }: { row: TransactionHistoryPoolTransactions }) { const { ocean, networkId } = useOcean() const [title, setTitle] = useState() const { locale } = useUserPreferences() useEffect(() => { if (!ocean || !locale || !row) return async function init() { const title = await getTitle(ocean, row, locale) setTitle(title) } init() }, [ocean, row, locale]) return title ? ( {title} ) : null } const columns = [ { name: 'Title', selector: function getTitleRow(row: TransactionHistoryPoolTransactions) { return } }, { name: 'Data Set', selector: function getAssetRow(row: TransactionHistoryPoolTransactions) { const did = web3.utils .toChecksumAddress(row.poolAddress.datatokenAddress) .replace('0x', 'did:op:') return <AssetTitle did={did} /> } }, { name: 'Time', selector: function getTimeRow(row: TransactionHistoryPoolTransactions) { return ( <Time className={styles.time} date={row.timestamp.toString()} relative isUnix /> ) }, maxWidth: '10rem' } ] // hack! if we use a function to omit one field this will display a strange refresh to the enduser for each row const columnsMinimal = [columns[0], columns[2]] export default function PoolTransactions({ poolAddress, minimal }: { poolAddress?: string minimal?: boolean }): ReactElement { const { accountId } = useOcean() const [logs, setLogs] = useState<TransactionHistoryPoolTransactions[]>() const { data, loading } = useQuery<TransactionHistory>( poolAddress ? txHistoryQueryByPool : txHistoryQuery, { variables: { user: accountId?.toLowerCase(), pool: poolAddress?.toLowerCase() }, pollInterval: 20000 } ) useEffect(() => { if (!data) return setLogs(data.poolTransactions) }, [data, loading]) return ( <Table columns={minimal ? columnsMinimal : columns} data={logs} isLoading={loading} noTableHead={minimal} dense={minimal} pagination={minimal ? logs?.length >= 4 : logs?.length >= 9} paginationPerPage={minimal ? 5 : 10} emptyMessage="Your pool transactions will show up here" /> ) }