Skip to content

Commit

Permalink
Merge pull request #756 from subspace/748-display-withdrawals-on-stak…
Browse files Browse the repository at this point in the history
…ing-when-on-rpc

Display withdrawals on staking when on rpc
  • Loading branch information
marc-aurele-besner authored Jul 22, 2024
2 parents 5b656ab + 7b955b1 commit 42379ef
Show file tree
Hide file tree
Showing 10 changed files with 243 additions and 63 deletions.
18 changes: 10 additions & 8 deletions explorer/src/components/Staking/OperatorNominatorTable.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { SortingState } from '@tanstack/react-table'
import { SortedTable } from 'components/common/SortedTable'
import { PAGE_SIZE } from 'constants/general'
import { BIGINT_ZERO, PAGE_SIZE, SHARES_CALCULATION_MULTIPLIER } from 'constants/general'
import { INTERNAL_ROUTES, Routes } from 'constants/routes'
import {
NominatorOrderByInput,
Expand Down Expand Up @@ -147,20 +147,22 @@ export const OperatorNominatorTable: FC<Props> = ({ operator }) => {
(d) => d.account === row.original.account.id && d.operatorId.toString() === operatorId,
)
const sharesValue =
op && BigInt(op.currentTotalShares) > BigInt(0)
? (BigInt(op.currentTotalStake) * BigInt(1000)) / BigInt(op.currentTotalShares)
: BigInt(0)
op && BigInt(op.currentTotalShares) > BIGINT_ZERO
? (BigInt(op.currentTotalStake) * SHARES_CALCULATION_MULTIPLIER) /
BigInt(op.currentTotalShares)
: BIGINT_ZERO
return (
<div>
{deposit && deposit.shares !== '0' && (
{deposit && deposit.shares > BIGINT_ZERO && (
<>
{`Staked: ${bigNumberToNumber(((BigInt(deposit.shares) * BigInt(sharesValue)) / BigInt(1000)).toString())} ${selectedChain.token.symbol}`}
{`Staked: ${bigNumberToNumber((deposit.shares * sharesValue) / SHARES_CALCULATION_MULTIPLIER)} ${selectedChain.token.symbol}`}
<br />
</>
)}
{deposit &&
deposit.pending.amount !== '0' &&
`Pending: ${bigNumberToNumber((BigInt(deposit.pending.amount) + BigInt(deposit.pending.storageFeeDeposit)).toString())} ${selectedChain.token.symbol}`}
deposit.pending !== null &&
deposit.pending.amount > BIGINT_ZERO &&
`Pending: ${bigNumberToNumber(deposit.pending.amount + deposit.pending.storageFeeDeposit)} ${selectedChain.token.symbol}`}
</div>
)
},
Expand Down
171 changes: 145 additions & 26 deletions explorer/src/components/Staking/OperatorsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { SortingState } from '@tanstack/react-table'
import { DebouncedInput } from 'components/common/DebouncedInput'
import { SortedTable } from 'components/common/SortedTable'
import { Spinner } from 'components/common/Spinner'
import { Chains, PAGE_SIZE } from 'constants/'
import { BIGINT_ZERO, Chains, PAGE_SIZE, SHARES_CALCULATION_MULTIPLIER } from 'constants/'
import { INTERNAL_ROUTES, Routes } from 'constants/routes'
import {
OperatorOrderByInput,
Expand Down Expand Up @@ -55,7 +55,7 @@ export const OperatorsList: FC = () => {
})
const { subspaceAccount } = useWallet()
const { operatorId } = useParams<{ operatorId?: string }>()
const { operators: rpcOperators, nominatorCount, deposits } = useConsensusStates()
const { operators: rpcOperators, nominatorCount, deposits, withdrawals } = useConsensusStates()
const { domains } = useDomainsStates()
const { loadData: loadDomainsData } = useDomainsData()
const { loadData: loadConsensusData } = useConsensusData()
Expand Down Expand Up @@ -90,6 +90,11 @@ export const OperatorsList: FC = () => {
const { selectedChain, selectedDomain } = useDomains()
const apolloClient = useApolloClient()

const myWithdrawals = useMemo(
() => withdrawals.filter((w) => w.account === subspaceAccount),
[withdrawals, subspaceAccount],
)

const columns = useMemo(() => {
const cols = [
{
Expand Down Expand Up @@ -202,32 +207,34 @@ export const OperatorsList: FC = () => {
>) => {
const opDeposits = deposits.filter((d) => d.operatorId.toString() === row.original.id)
const depositShares = opDeposits.reduce(
(acc, deposit) => acc + BigInt(deposit.shares),
BigInt(0),
(acc, deposit) => acc + deposit.shares,
BIGINT_ZERO,
)
const pendingAmount = opDeposits.reduce(
(acc, deposit) => acc + BigInt(deposit.pending.amount),
BigInt(0),
(acc, deposit) => (deposit.pending !== null ? acc + deposit.pending.amount : acc),
BIGINT_ZERO,
)
const pendingStorageFee = opDeposits.reduce(
(acc, deposit) => acc + BigInt(deposit.pending.storageFeeDeposit),
BigInt(0),
(acc, deposit) =>
deposit.pending !== null ? acc + deposit.pending.storageFeeDeposit : acc,
BIGINT_ZERO,
)
const op = rpcOperators.find((o) => o.id === row.original.id)
const sharesValue =
op && BigInt(op.currentTotalShares) > BigInt(0)
? (BigInt(op.currentTotalStake) * BigInt(1000)) / BigInt(op.currentTotalShares)
: BigInt(0)
op && BigInt(op.currentTotalShares) > BIGINT_ZERO
? (BigInt(op.currentTotalStake) * SHARES_CALCULATION_MULTIPLIER) /
BigInt(op.currentTotalShares)
: BIGINT_ZERO
return (
<div>
{depositShares > BigInt(0) && (
{depositShares > BIGINT_ZERO && (
<>
{`Staked: ${bigNumberToNumber(((depositShares * sharesValue) / BigInt(1000)).toString())} ${selectedChain.token.symbol}`}
{`Staked: ${bigNumberToNumber((depositShares * sharesValue) / SHARES_CALCULATION_MULTIPLIER)} ${selectedChain.token.symbol}`}
<br />
</>
)}
{pendingAmount > BigInt(0) &&
`Pending; ${bigNumberToNumber((pendingAmount + pendingStorageFee).toString())} ${selectedChain.token.symbol}`}
{pendingAmount > BIGINT_ZERO &&
`Pending; ${bigNumberToNumber(pendingAmount + pendingStorageFee)} ${selectedChain.token.symbol}`}
</div>
)
},
Expand Down Expand Up @@ -290,20 +297,22 @@ export const OperatorsList: FC = () => {
)
const op = rpcOperators.find((o) => o.id === row.original.id)
const sharesValue =
op && BigInt(op.currentTotalShares) > BigInt(0)
? (BigInt(op.currentTotalStake) * BigInt(1000)) / BigInt(op.currentTotalShares)
: BigInt(0)
op && BigInt(op.currentTotalShares) > BIGINT_ZERO
? (BigInt(op.currentTotalStake) * SHARES_CALCULATION_MULTIPLIER) /
BigInt(op.currentTotalShares)
: BIGINT_ZERO
return (
<div>
{deposit && deposit.shares !== '0' && (
{deposit && deposit.shares > BIGINT_ZERO && (
<>
{`Staked: ${bigNumberToNumber(((BigInt(deposit.shares) * sharesValue) / BigInt(1000)).toString())} ${selectedChain.token.symbol}`}
{`Staked: ${bigNumberToNumber((deposit.shares * sharesValue) / SHARES_CALCULATION_MULTIPLIER)} ${selectedChain.token.symbol}`}
<br />
</>
)}
{deposit &&
deposit.pending.amount !== '0' &&
`Pending: ${bigNumberToNumber((BigInt(deposit.pending.amount) + BigInt(deposit.pending.storageFeeDeposit)).toString())} ${selectedChain.token.symbol}`}
deposit.pending !== null &&
deposit.pending.amount > BIGINT_ZERO &&
`Pending: ${bigNumberToNumber(deposit.pending.amount + deposit.pending.storageFeeDeposit)} ${selectedChain.token.symbol}`}
</div>
)
},
Expand All @@ -319,16 +328,17 @@ export const OperatorsList: FC = () => {
OperatorsConnectionQuery['operatorsConnection']['edges'][0]['node'] | Operators
>) => {
const isOperator = row.original.operatorOwner === subspaceAccount
const deposit = deposits.find(
(d) => d.account === subspaceAccount && d.operatorId.toString() === row.original.id,
)
const nominator =
(!useRpcData &&
(
row.original as OperatorsConnectionQuery['operatorsConnection']['edges'][0]['node']
).nominators.find(
(nominator) => nominator.id === `${row.original.id}-${subspaceAccount}`,
)) ||
deposits.find(
(d) => d.account === subspaceAccount && d.operatorId.toString() === row.original.id,
)
deposit
const excludeActions = []
if (!isOperator)
excludeActions.push(OperatorActionType.Deregister, OperatorActionType.UnlockFunds)
Expand All @@ -353,7 +363,7 @@ export const OperatorsList: FC = () => {
handleAction={handleAction}
row={row as ActionsDropdownRow}
excludeActions={excludeActions}
nominatorMaxShares={nominator ? BigInt(nominator.shares) : BigInt(0)}
nominatorMaxShares={nominator ? BigInt(nominator.shares) : BIGINT_ZERO}
/>
)
},
Expand Down Expand Up @@ -509,6 +519,115 @@ export const OperatorsList: FC = () => {
</div>
</div>
<DataSourceBanner />
{myWithdrawals.length > 0 && (
<div className='mt-5 flex flex-col gap-2'>
<div className='text-base font-medium text-grayDark dark:text-white'>My Withdrawals</div>
<div className='flex w-full flex-col sm:mt-0'>
<div className='my-6 rounded'>
<SortedTable
data={myWithdrawals}
columns={[
{
accessorKey: 'operatorId',
header: 'Operator Id',
enableSorting: false,
cell: ({ row }) => <div>{row.original.operatorId}</div>,
},
{
accessorKey: 'withdrawalInShares.shares',
header: 'Withdrawal Amount',
enableSorting: false,
cell: ({ row }) => {
const op = rpcOperators.find(
(o) => o.id === row.original.operatorId.toString(),
)
const sharesValue =
op && BigInt(op.currentTotalShares) > BIGINT_ZERO
? (BigInt(op.currentTotalStake) * SHARES_CALCULATION_MULTIPLIER) /
BigInt(op.currentTotalShares)
: BIGINT_ZERO
const withdrawAmount = bigNumberToNumber(
(row.original.withdrawalInShares.shares * sharesValue) /
SHARES_CALCULATION_MULTIPLIER,
)
return (
<div>
<Tooltip
text={`Shares: ${row.original.withdrawalInShares.shares.toString()} - Share value: ${sharesValue} - Total: ${withdrawAmount}`}
>
{withdrawAmount} {selectedChain.token.symbol}
</Tooltip>
</div>
)
},
},
{
accessorKey: 'withdrawalInShares.storageFeeRefund',
header: 'Withdrawal Storage Fee Refund',
enableSorting: false,
cell: ({ row }) => {
const op = rpcOperators.find(
(o) => o.id === row.original.operatorId.toString(),
)
const sharesValue =
op && BigInt(op.currentTotalShares) > BIGINT_ZERO
? (BigInt(op.currentTotalStake) * SHARES_CALCULATION_MULTIPLIER) /
BigInt(op.currentTotalShares)
: BIGINT_ZERO
const withdrawAmount = bigNumberToNumber(
(row.original.withdrawalInShares.storageFeeRefund * sharesValue) /
SHARES_CALCULATION_MULTIPLIER,
)
return (
<div>
<Tooltip
text={`Shares: ${row.original.withdrawalInShares.storageFeeRefund.toString()} - Share value: ${sharesValue} - Total: ${withdrawAmount}`}
>
{withdrawAmount} {selectedChain.token.symbol}
</Tooltip>
</div>
)
},
},
{
accessorKey: 'withdrawalInShares.unlockAtConfirmedDomainBlockNumber',
header: 'Withdrawal at Domain Block Number',
enableSorting: false,
cell: ({ row }) => {
return (
<div>
{row.original.withdrawalInShares.unlockAtConfirmedDomainBlockNumber.toString()}
</div>
)
},
},
{
accessorKey: 'totalWithdrawalAmount',
header: 'Total Withdrawal Amount',
enableSorting: false,
cell: ({ row }) => <div>{row.original.totalWithdrawalAmount.toString()}</div>,
},
{
accessorKey: 'withdrawals',
header: 'Withdrawals',
enableSorting: false,
cell: ({ row }) => <div>{row.original.withdrawals.length}</div>,
},
]}
showNavigation={false}
sorting={sorting}
onSortingChange={setSorting}
pagination={pagination}
pageCount={pageCount}
onPaginationChange={setPagination}
filename='operators-my-withdrawals-list'
pageSizeOptions={[10]}
fullDataDownloader={fullDataDownloader}
/>
</div>
</div>
</div>
)}
<div className='mt-5 flex w-full flex-col sm:mt-0'>
<div className='my-6 rounded' ref={ref}>
{operatorsConnection ? (
Expand Down
4 changes: 4 additions & 0 deletions explorer/src/constants/general.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,7 @@ export const searchTypes: SearchType[] = [
]

export const SUBSPACE_ACC_PREFIX = 2254

export const BIGINT_ZERO = BigInt(0)

export const SHARES_CALCULATION_MULTIPLIER = BigInt(1000000000000)
4 changes: 4 additions & 0 deletions explorer/src/states/consensus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
SuccessfulBundle,
Withdrawal,
} from 'types/consensus'
import { bigIntDeserializer, bigIntSerializer } from 'utils/number'
import { create } from 'zustand'
import { createJSONStorage, persist } from 'zustand/middleware'

Expand Down Expand Up @@ -118,7 +119,10 @@ export const useConsensusStates = create<ConsensusState>()(
}),
{
name: 'consensus-storage',
version: 2,
storage: createJSONStorage(() => localStorage),
serialize: (state) => JSON.stringify(state, bigIntSerializer),
deserialize: (str) => JSON.parse(str, bigIntDeserializer),
},
),
)
5 changes: 4 additions & 1 deletion explorer/src/states/domains.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Domain } from 'types/domain'
import { bigIntDeserializer, bigIntSerializer } from 'utils/number'
import { create } from 'zustand'
import { createJSONStorage, persist } from 'zustand/middleware'

Expand Down Expand Up @@ -28,8 +29,10 @@ export const useDomainsStates = create<DomainsState>()(
}),
{
name: 'domains-storage',
version: 2,
version: 3,
storage: createJSONStorage(() => localStorage),
serialize: (state) => JSON.stringify(state, bigIntSerializer),
deserialize: (str) => JSON.parse(str, bigIntDeserializer),
},
),
)
10 changes: 7 additions & 3 deletions explorer/src/states/transactions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { TransactionStatus } from 'constants/transaction'
import type { Transaction, TransactionWithMetadata } from 'types/transaction'
import { bigIntDeserializer, bigIntSerializer } from 'utils/number'
import { create } from 'zustand'
import { createJSONStorage, persist } from 'zustand/middleware'

Expand Down Expand Up @@ -35,9 +36,9 @@ export const useTransactionsStates = create<TransactionsState>()(
})),
getNextNonceForAccount: (address: string) => {
const lastNonce = get()
.pendingTransactions.filter(t => t.ownerAccount.address === address)
.reduce((maxNonce, tx) => Math.max(maxNonce, tx.nonce), -1);
return lastNonce + 1;
.pendingTransactions.filter((t) => t.ownerAccount.address === address)
.reduce((maxNonce, tx) => Math.max(maxNonce, tx.nonce), -1)
return lastNonce + 1
},
removePendingTransactions: (transaction: Transaction) =>
set((state) => ({
Expand Down Expand Up @@ -78,7 +79,10 @@ export const useTransactionsStates = create<TransactionsState>()(
}),
{
name: 'transactions-storage',
version: 2,
storage: createJSONStorage(() => localStorage),
serialize: (state) => JSON.stringify(state, bigIntSerializer),
deserialize: (str) => JSON.parse(str, bigIntDeserializer),
},
),
)
5 changes: 4 additions & 1 deletion explorer/src/states/view.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { bigIntDeserializer, bigIntSerializer } from 'utils/number'
import { create } from 'zustand'
import { createJSONStorage, persist } from 'zustand/middleware'

Expand Down Expand Up @@ -27,8 +28,10 @@ export const useViewStates = create<ViewStatesAndFn>()(
}),
{
name: 'view-storage',
version: 1,
version: 2,
storage: createJSONStorage(() => localStorage),
serialize: (state) => JSON.stringify(state, bigIntSerializer),
deserialize: (str) => JSON.parse(str, bigIntDeserializer),
},
),
)
Loading

0 comments on commit 42379ef

Please sign in to comment.