Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions atp-indexer/src/api/handlers/atp/details.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ function formatDirectStakes(
return {
attesterAddress: checksumAddress(stake.attesterAddress),
operatorAddress: checksumAddress(stake.operatorAddress),
rollupAddress: checksumAddress(stake.rollupAddress),
stakedAmount: activationThreshold,
totalSlashed: totalSlashed.toString(),
txHash: stake.txHash,
Expand Down Expand Up @@ -63,6 +64,7 @@ function formatDelegations(
providerName: metadata?.providerName || `Provider ${providerId}`,
providerLogo: metadata?.providerLogoUrl || '',
operatorAddress: checksumAddress(op.attesterAddress),
rollupAddress: checksumAddress(op.rollupAddress),
stakedAmount: activationThreshold,
totalSlashed: totalSlashed.toString(),
splitContract: checksumAddress(op.splitContractAddress),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ export async function handleBeneficiaryStakingOverview(c: Context): Promise<Resp
const directStakeBreakdown = markedDirectStakes.map(stake => ({
atpAddress: checksumAddress(atpByStaker.get(stake.stakerAddress.toLowerCase()) || stake.atpAddress),
attesterAddress: checksumAddress(stake.attesterAddress),
rollupAddress: checksumAddress(stake.rollupAddress),
stakedAmount: stake.stakedAmount.toString(),
hasFailedDeposit: stake.hasFailedDeposit,
failedDepositTxHash: stake.failedDepositTxHash,
Expand All @@ -150,6 +151,7 @@ export async function handleBeneficiaryStakingOverview(c: Context): Promise<Resp
providerName: metadata?.providerName || `Provider ${providerId}`,
providerLogo: metadata?.providerLogoUrl || '',
attesterAddress: checksumAddress(delegation.attesterAddress),
rollupAddress: checksumAddress(delegation.rollupAddress),
stakedAmount: delegation.stakedAmount.toString(),
splitContract: checksumAddress(delegation.splitContractAddress),
providerTakeRate: delegation.providerTakeRate,
Expand All @@ -174,6 +176,7 @@ export async function handleBeneficiaryStakingOverview(c: Context): Promise<Resp
providerName: metadata?.providerName || `Provider ${providerId}`,
providerLogo: metadata?.providerLogoUrl || '',
attesterAddress: checksumAddress(delegation.attesterAddress),
rollupAddress: checksumAddress(delegation.rollupAddress),
stakedAmount: delegation.stakedAmount.toString(),
splitContract: checksumAddress(delegation.splitContractAddress),
providerTakeRate: delegation.providerTakeRate,
Expand All @@ -192,6 +195,7 @@ export async function handleBeneficiaryStakingOverview(c: Context): Promise<Resp
const erc20DirectStakeBreakdown = markedErc20DirectDeposits.map(dep => ({
attesterAddress: checksumAddress(dep.attesterAddress),
withdrawerAddress: checksumAddress(dep.withdrawerAddress),
rollupAddress: checksumAddress(dep.rollupAddress),
stakedAmount: dep.amount.toString(),
txHash: dep.txHash,
timestamp: Number(dep.timestamp),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ export const ATPDetailsDelegationItem = ({
const { getSplitStatus, claimAllHook } = useClaimAllContext()
const { isRewardsClaimable } = useIsRewardsClaimable()

const { status, statusLabel, isLoading: isLoadingStatus, canFinalize, actualUnlockTime, refetch: refetchStatus } = useSequencerStatus(delegation.operatorAddress as Address)
const delegationRollupAddress = delegation.rollupAddress as Address
const { status, statusLabel, isLoading: isLoadingStatus, canFinalize, actualUnlockTime, refetch: refetchStatus } = useSequencerStatus(delegation.operatorAddress as Address, delegationRollupAddress)
const { withdrawalDelayDays } = useGovernanceConfig()

const {
Expand All @@ -72,7 +73,7 @@ export const ATPDetailsDelegationItem = ({
isAtRisk,
isCritical,
isLoading: isLoadingHealth
} = useStakeHealth(delegation.operatorAddress as Address)
} = useStakeHealth(delegation.operatorAddress as Address, delegationRollupAddress)

const splitStatus = getSplitStatus(delegation.splitContract as Address)
const isInBatch = splitStatus !== 'idle'
Expand Down Expand Up @@ -487,6 +488,7 @@ export const ATPDetailsDelegationItem = ({
stakerAddress={stakerAddress}
attesterAddress={delegation.operatorAddress as Address}
rollupVersion={rollupVersion}
rollupAddress={delegationRollupAddress}
status={status}
canFinalize={canFinalize}
actualUnlockTime={actualUnlockTime}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ export const ATPDetailsDirectStakeItem = ({ stake, stakerAddress, rollupVersion,
const { date, time } = formatBlockTimestamp(stake.timestamp)
const { isRewardsClaimable } = useIsRewardsClaimable()

const { status, statusLabel, isLoading: isLoadingStatus, canFinalize, actualUnlockTime, refetch: refetchStatus } = useSequencerStatus(stake.attesterAddress as Address)
const stakeRollupAddress = stake.rollupAddress as Address
const { status, statusLabel, isLoading: isLoadingStatus, canFinalize, actualUnlockTime, refetch: refetchStatus } = useSequencerStatus(stake.attesterAddress as Address, stakeRollupAddress)
const { withdrawalDelayDays } = useGovernanceConfig()

const {
Expand All @@ -55,7 +56,7 @@ export const ATPDetailsDirectStakeItem = ({ stake, stakerAddress, rollupVersion,
isAtRisk,
isCritical,
isLoading: isLoadingHealth
} = useStakeHealth(stake.attesterAddress as Address)
} = useStakeHealth(stake.attesterAddress as Address, stakeRollupAddress)

const isUnstaked = stake.status === 'UNSTAKED'
const isInQueue = status === SequencerStatus.NONE && !stake.hasFailedDeposit && !isUnstaked
Expand Down Expand Up @@ -389,6 +390,7 @@ export const ATPDetailsDirectStakeItem = ({ stake, stakerAddress, rollupVersion,
stakerAddress={stakerAddress}
attesterAddress={stake.attesterAddress as Address}
rollupVersion={rollupVersion}
rollupAddress={stakeRollupAddress}
status={status}
canFinalize={canFinalize}
actualUnlockTime={actualUnlockTime}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ interface WithdrawalActionsProps {
stakerAddress: Address;
attesterAddress: Address;
rollupVersion: bigint;
rollupAddress: Address;
status: number | undefined;
canFinalize: boolean;
actualUnlockTime?: bigint;
Expand All @@ -94,6 +95,7 @@ export const WithdrawalActions = ({
stakerAddress,
attesterAddress,
rollupVersion,
rollupAddress,
status,
canFinalize,
actualUnlockTime,
Expand Down Expand Up @@ -186,7 +188,7 @@ export const WithdrawalActions = ({

const handleFinalizeWithdraw = async () => {
try {
await finalizeWithdraw(attesterAddress);
await finalizeWithdraw(attesterAddress, rollupAddress);
} catch (error) {
console.error("Failed to finalize withdraw:", error);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ export const WalletDelegationItem = ({
const { getSplitStatus, claimAllHook } = useClaimAllContext()
const { isRewardsClaimable } = useIsRewardsClaimable()

const { status, statusLabel, isLoading: isLoadingStatus, canFinalize, actualUnlockTime, refetch: refetchStatus } = useSequencerStatus(delegation.attesterAddress as Address)
const delegationRollupAddress = delegation.rollupAddress as Address
const { status, statusLabel, isLoading: isLoadingStatus, canFinalize, actualUnlockTime, refetch: refetchStatus } = useSequencerStatus(delegation.attesterAddress as Address, delegationRollupAddress)
const { withdrawalDelayDays } = useGovernanceConfig()

const {
Expand All @@ -57,7 +58,7 @@ export const WalletDelegationItem = ({
isAtRisk,
isCritical,
isLoading: isLoadingHealth
} = useStakeHealth(delegation.attesterAddress as Address)
} = useStakeHealth(delegation.attesterAddress as Address, delegationRollupAddress)

const splitStatus = getSplitStatus(delegation.splitContract as Address)
const isInBatch = splitStatus !== 'idle'
Expand Down Expand Up @@ -380,6 +381,7 @@ export const WalletDelegationItem = ({
<WalletWithdrawalActions
attesterAddress={delegation.attesterAddress as Address}
recipientAddress={address}
rollupAddress={delegationRollupAddress}
status={status}
canFinalize={canFinalize}
actualUnlockTime={actualUnlockTime}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ export const WalletDirectStakeItem = ({
const { symbol, decimals } = useStakingAssetTokenDetails()
const { date, time } = formatBlockTimestamp(stake.timestamp)

const { status, statusLabel, isLoading: isLoadingStatus, canFinalize, actualUnlockTime, refetch: refetchStatus } = useSequencerStatus(stake.attesterAddress as Address)
const stakeRollupAddress = stake.rollupAddress as Address
const { status, statusLabel, isLoading: isLoadingStatus, canFinalize, actualUnlockTime, refetch: refetchStatus } = useSequencerStatus(stake.attesterAddress as Address, stakeRollupAddress)
const { withdrawalDelayDays } = useGovernanceConfig()

const {
Expand All @@ -46,7 +47,7 @@ export const WalletDirectStakeItem = ({
isAtRisk,
isCritical,
isLoading: isLoadingHealth
} = useStakeHealth(stake.attesterAddress as Address)
} = useStakeHealth(stake.attesterAddress as Address, stakeRollupAddress)

const isUnstaked = stake.status === 'UNSTAKED'
const isInQueue = status === SequencerStatus.NONE && !stake.hasFailedDeposit && !isUnstaked
Expand Down Expand Up @@ -248,6 +249,7 @@ export const WalletDirectStakeItem = ({
<WalletWithdrawalActions
attesterAddress={stake.attesterAddress as Address}
recipientAddress={address}
rollupAddress={stakeRollupAddress}
status={status}
canFinalize={canFinalize}
actualUnlockTime={actualUnlockTime}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ function parseContractError(error: Error): string {
interface WalletWithdrawalActionsProps {
attesterAddress: Address
recipientAddress: Address
rollupAddress: Address
status: number | undefined
canFinalize: boolean
actualUnlockTime?: bigint
Expand All @@ -78,6 +79,7 @@ interface WalletWithdrawalActionsProps {
export const WalletWithdrawalActions = ({
attesterAddress,
recipientAddress,
rollupAddress,
status,
canFinalize,
actualUnlockTime,
Expand Down Expand Up @@ -149,15 +151,15 @@ export const WalletWithdrawalActions = ({

const handleInitiateWithdraw = async () => {
try {
await initiateWithdraw(attesterAddress, recipientAddress)
await initiateWithdraw(attesterAddress, recipientAddress, rollupAddress)
} catch (error) {
console.error("Failed to initiate withdraw:", error)
}
}

const handleFinalizeWithdraw = async () => {
try {
await finalizeWithdraw(attesterAddress)
await finalizeWithdraw(attesterAddress, rollupAddress)
} catch (error) {
console.error("Failed to finalize withdraw:", error)
}
Expand Down
2 changes: 2 additions & 0 deletions staking-dashboard/src/hooks/atp/useATPDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { stringToBigInt } from '@/utils/atpFormatters'
export interface DirectStake {
attesterAddress: string
operatorAddress: string
rollupAddress: string
stakedAmount: bigint
txHash: string
timestamp: string
Expand All @@ -21,6 +22,7 @@ export interface Delegation {
providerName?: string
providerLogo?: string
operatorAddress: string
rollupAddress: string
splitContract: string
providerTakeRate: number
providerRewardsRecipient: string
Expand Down
13 changes: 13 additions & 0 deletions staking-dashboard/src/hooks/atp/useAggregatedStakingData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
export interface DirectStakeBreakdown {
atpAddress: Address
attesterAddress: Address
rollupAddress: Address
stakedAmount: bigint
hasFailedDeposit: boolean
failedDepositTxHash: string | null
Expand All @@ -41,6 +42,7 @@ export interface DelegationBreakdown {
providerName?: string
providerLogo?: string
attesterAddress: Address
rollupAddress: Address
stakedAmount: bigint
rewards: bigint
splitContract: Address
Expand All @@ -60,6 +62,7 @@ export interface Erc20DelegationBreakdown {
providerName?: string
providerLogo?: string
attesterAddress: Address
rollupAddress: Address
stakedAmount: bigint
rewards: bigint
splitContract: Address
Expand All @@ -77,6 +80,7 @@ export interface Erc20DelegationBreakdown {
export interface Erc20DirectStakeBreakdown {
attesterAddress: Address
withdrawerAddress: Address
rollupAddress: Address
stakedAmount: bigint
hasFailedDeposit: boolean
failedDepositTxHash: string | null
Expand Down Expand Up @@ -109,6 +113,7 @@ export interface AggregatedStakingData {
interface ApiDirectStake {
atpAddress: string
attesterAddress: string
rollupAddress: string
stakedAmount: string
hasFailedDeposit: boolean
failedDepositTxHash: string | null
Expand All @@ -130,6 +135,7 @@ interface ApiDelegation {
providerName?: string
providerLogo?: string
attesterAddress: string
rollupAddress: string
stakedAmount: string
splitContract: string
providerTakeRate: number
Expand All @@ -148,6 +154,7 @@ interface ApiErc20Delegation {
providerName?: string
providerLogo?: string
attesterAddress: string
rollupAddress: string
stakedAmount: string
splitContract: string
providerTakeRate: number
Expand All @@ -164,6 +171,7 @@ interface ApiErc20Delegation {
interface ApiErc20DirectStake {
attesterAddress: string
withdrawerAddress: string
rollupAddress: string
stakedAmount: string
hasFailedDeposit: boolean
failedDepositTxHash: string | null
Expand Down Expand Up @@ -207,6 +215,7 @@ function parseDirectStake(stake: ApiDirectStake): DirectStakeBreakdown {
return {
atpAddress: stake.atpAddress as Address,
attesterAddress: stake.attesterAddress as Address,
rollupAddress: stake.rollupAddress as Address,
stakedAmount: stringToBigInt(stake.stakedAmount),
hasFailedDeposit: stake.hasFailedDeposit,
failedDepositTxHash: stake.failedDepositTxHash,
Expand Down Expand Up @@ -267,6 +276,7 @@ function parseDelegation(
providerName: delegation.providerName,
providerLogo: delegation.providerLogo,
attesterAddress: delegation.attesterAddress as Address,
rollupAddress: delegation.rollupAddress as Address,
stakedAmount: stringToBigInt(delegation.stakedAmount),
rewards: delegation.hasFailedDeposit ? 0n : userRewards,
splitContract: delegation.splitContract as Address,
Expand Down Expand Up @@ -324,6 +334,7 @@ function parseErc20Delegation(
providerName: delegation.providerName,
providerLogo: delegation.providerLogo,
attesterAddress: delegation.attesterAddress as Address,
rollupAddress: delegation.rollupAddress as Address,
stakedAmount: stringToBigInt(delegation.stakedAmount),
rewards: delegation.hasFailedDeposit ? 0n : userRewards,
splitContract: delegation.splitContract as Address,
Expand All @@ -346,6 +357,7 @@ function parseErc20DirectStake(stake: ApiErc20DirectStake): Erc20DirectStakeBrea
return {
attesterAddress: stake.attesterAddress as Address,
withdrawerAddress: stake.withdrawerAddress as Address,
rollupAddress: stake.rollupAddress as Address,
stakedAmount: stringToBigInt(stake.stakedAmount),
hasFailedDeposit: stake.hasFailedDeposit,
failedDepositTxHash: stake.failedDepositTxHash,
Expand Down Expand Up @@ -502,6 +514,7 @@ export const useAggregatedStakingData = (): AggregatedStakingData => {
.map(stake => ({
attesterAddress: stake.attesterAddress,
withdrawerAddress: stake.withdrawerAddress,
rollupAddress: contracts.rollup.address,
stakedAmount: BigInt(stake.stakedAmount),
hasFailedDeposit: false,
failedDepositTxHash: null,
Expand Down
16 changes: 12 additions & 4 deletions staking-dashboard/src/hooks/rollup/useAttesterView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,24 @@ import type { Address } from "viem"
import { contracts } from "@/contracts"

/**
* Hook to get comprehensive attester/sequencer information including status, balance, and exit details
* Hook to get comprehensive attester/sequencer information including status, balance, and exit details.
*
* `rollupAddress` is required (but may be undefined while the caller's data is still
* loading). A legacy-rollup stake queried against the current canonical rollup returns
* status=NONE and strands users in "IN QUEUE" with no finalize button — so there is
* deliberately no silent fallback to `contracts.rollup.address`.
*/
export function useAttesterView(attesterAddress: Address | undefined) {
export function useAttesterView(
attesterAddress: Address | undefined,
rollupAddress: Address | undefined,
) {
const { data, isLoading, error, refetch } = useReadContract({
address: contracts.rollup.address,
address: rollupAddress,
abi: contracts.rollup.abi,
functionName: "getAttesterView",
args: attesterAddress ? [attesterAddress] : undefined,
query: {
enabled: !!attesterAddress,
enabled: !!attesterAddress && !!rollupAddress,
},
})

Expand Down
4 changes: 2 additions & 2 deletions staking-dashboard/src/hooks/rollup/useFinalizeWithdraw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ export function useFinalizeWithdraw() {
})

return {
finalizeWithdraw: (attesterAddress: Address) => {
finalizeWithdraw: (attesterAddress: Address, rollupAddress: Address) => {
return write.writeContract({
abi: contracts.rollup.abi,
address: contracts.rollup.address,
address: rollupAddress,
functionName: "finalizeWithdraw",
args: [attesterAddress]
})
Expand Down
7 changes: 5 additions & 2 deletions staking-dashboard/src/hooks/rollup/useSequencerStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,12 @@ export function getStatusLabel(status: number | undefined): string {
* @param sequencerAddress - The address of the sequencer
* @returns Sequencer status, label, and related information
*/
export function useSequencerStatus(sequencerAddress: Address | undefined) {
export function useSequencerStatus(
sequencerAddress: Address | undefined,
rollupAddress: Address | undefined,
) {
const { status, effectiveBalance, exit, isLoading, error, refetch } =
useAttesterView(sequencerAddress);
useAttesterView(sequencerAddress, rollupAddress);

// Query the governance withdrawal to get the REAL unlock time
const { withdrawal, isLoading: isLoadingWithdrawal } = useGovernanceWithdrawal(exit?.withdrawalId);
Expand Down
Loading
Loading