diff --git a/components/StakeTransactions/index.tsx b/components/StakeTransactions/index.tsx
index 264c48c8..1b4dd409 100644
--- a/components/StakeTransactions/index.tsx
+++ b/components/StakeTransactions/index.tsx
@@ -2,11 +2,6 @@ import { Box, Card, Flex, Heading, Text } from "@livepeer/design-system";
import { formatLPT } from "@utils/numberFormatters";
import { formatAddress } from "@utils/web3";
import { UnbondingLock } from "apollo";
-import {
- useCurrentRoundData,
- useSubgraphDegraded,
- useUnbondingLocksData,
-} from "hooks";
import { useMemo } from "react";
import { parseEther } from "viem";
@@ -18,54 +13,20 @@ import WithdrawStake from "../WithdrawStake";
const Index = ({ delegator, transcoders, currentRound, isMyAccount }) => {
const isBonded = !!delegator.delegate;
- // TEMPORARY, with the subgraph outage: locks created after indexing stopped
- // are missing here, so an unbond looks like it never happened. Append the
- // ones above the subgraph's highest known id, read from the chain. The round
- // comes from the chain too, or a stale one leaves a matured lock stuck in
- // "Pending" with no withdraw button. Remove once indexing has recovered.
- const degraded = useSubgraphDegraded();
-
- const nextLockId = useMemo(
- () =>
- delegator.unbondingLocks.reduce(
- (next: number, lock: UnbondingLock) =>
- Math.max(next, lock.unbondingLockId + 1),
- 0
- ),
- [delegator.unbondingLocks]
- );
- const missing = useUnbondingLocksData(
- degraded && isMyAccount ? delegator.id : null,
- nextLockId
- );
-
- const locks = useMemo(
- () =>
- missing?.locks.length
- ? [...delegator.unbondingLocks, ...missing.locks]
- : delegator.unbondingLocks,
- [delegator.unbondingLocks, missing]
- );
-
- const onchainRound = useCurrentRoundData();
- const roundId = Number(onchainRound?.id ?? currentRound.id);
-
- const pendingStakeTransactions = useMemo(
- () =>
- locks.filter(
- (item: UnbondingLock) =>
- item.withdrawRound && +item.withdrawRound > roundId
- ),
- [locks, roundId]
- );
- const completedStakeTransactions = useMemo(
- () =>
- locks.filter(
- (item: UnbondingLock) =>
- item.withdrawRound && +item.withdrawRound <= roundId
- ),
- [locks, roundId]
- );
+ const pendingStakeTransactions = useMemo(() => {
+ const roundId = parseInt(currentRound.id, 10);
+ return delegator.unbondingLocks.filter(
+ (item: UnbondingLock) =>
+ item.withdrawRound && +item.withdrawRound > roundId
+ );
+ }, [delegator.unbondingLocks, currentRound.id]);
+ const completedStakeTransactions = useMemo(() => {
+ const roundId = parseInt(currentRound.id, 10);
+ return delegator.unbondingLocks.filter(
+ (item: UnbondingLock) =>
+ item.withdrawRound && +item.withdrawRound <= roundId
+ );
+ }, [delegator.unbondingLocks, currentRound.id]);
return (
@@ -114,7 +75,8 @@ const Index = ({ delegator, transcoders, currentRound, isMyAccount }) => {
Tokens will be available for withdrawal in approximately{" "}
- {+lock.withdrawRound - roundId} days.
+ {+lock.withdrawRound - parseInt(currentRound.id, 10)}{" "}
+ days.
{
return data ?? null;
};
-export const useUnbondingLocksData = (
- address: string | undefined | null,
- from: number
-) => {
- // `from` skips the ids the subgraph already has. See /api/unbonding-locks.
- const { data } = useSWR(
- address ? `/unbonding-locks/${address.toLowerCase()}?from=${from}` : null
- );
-
- return data ?? null;
-};
-
export const useL1DelegatorData = (address: string | undefined | null) => {
const { data } = useSWR(
address ? `/l1-delegator/${address.toLowerCase()}` : null
diff --git a/lib/api/types/get-unbonding-locks.ts b/lib/api/types/get-unbonding-locks.ts
deleted file mode 100644
index d5d9cf38..00000000
--- a/lib/api/types/get-unbonding-locks.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-export type UnbondingLockInfo = {
- id: string;
- unbondingLockId: number;
- amount: string;
- withdrawRound: string;
- /**
- * The contract does not record which orchestrator a lock was unbonded from,
- * so this is the delegator's current delegate.
- */
- delegate: { id: string };
-};
-
-export type UnbondingLocks = {
- locks: UnbondingLockInfo[];
-};
diff --git a/pages/api/unbonding-locks/[address].tsx b/pages/api/unbonding-locks/[address].tsx
deleted file mode 100644
index b00ae040..00000000
--- a/pages/api/unbonding-locks/[address].tsx
+++ /dev/null
@@ -1,102 +0,0 @@
-import { getCacheControlHeader } from "@lib/api";
-import { bondingManager } from "@lib/api/abis/main/BondingManager";
-import { getBondingManagerAddress } from "@lib/api/contracts";
-import { badRequest, internalError, methodNotAllowed } from "@lib/api/errors";
-import { UnbondingLocks } from "@lib/api/types/get-unbonding-locks";
-import { l2PublicClient } from "@lib/chains";
-import { NextApiRequest, NextApiResponse } from "next";
-import { formatEther, isAddress } from "viem";
-
-/** Lock ids read per request, so a caller cannot ask for an unbounded scan. */
-const MAX_SCAN = 200;
-
-/**
- * TEMPORARY stopgap, paired with the subgraph outage: returns the delegator's
- * unbonding locks from `from` onwards, so the UI can show locks created after
- * the subgraph stopped indexing. Everything the subgraph already knows keeps
- * coming from the subgraph.
- *
- * Remove this route along with its caller once indexing has recovered.
- */
-const handler = async (
- req: NextApiRequest,
- res: NextApiResponse
-) => {
- try {
- const method = req.method;
-
- if (method === "GET") {
- res.setHeader("Cache-Control", getCacheControlHeader("revalidate"));
-
- const { address, from } = req.query;
-
- if (!!address && !Array.isArray(address) && isAddress(address)) {
- const bondingManagerAddress = await getBondingManagerAddress();
-
- const contract = {
- address: bondingManagerAddress,
- abi: bondingManager,
- } as const;
-
- // [bondedAmount, fees, delegateAddress, delegatedAmount, startRound,
- // lastClaimRound, nextUnbondingLockId]
- const delegator = await l2PublicClient.readContract({
- ...contract,
- functionName: "getDelegator",
- args: [address],
- });
- const delegateAddress = delegator[2];
- const end = Number(delegator[6]);
-
- // Ids are sequential and never reused, so anything the subgraph has not
- // seen sits above its highest known id. Always cover the newest ids,
- // whatever `from` asks for, and never read more than MAX_SCAN of them.
- const requested = Number(Array.isArray(from) ? from[0] : from);
- const start = Math.max(
- 0,
- Number.isInteger(requested) ? requested : 0,
- end - MAX_SCAN
- );
-
- const results = await l2PublicClient.multicall({
- allowFailure: false,
- contracts: Array.from(
- { length: Math.max(0, end - start) },
- (_, i) => ({
- ...contract,
- functionName: "getDelegatorUnbondingLock" as const,
- args: [address, BigInt(start + i)] as const,
- })
- ),
- });
-
- // Withdrawing and rebonding both delete the lock, so a non-zero amount
- // is what makes one open.
- const locks = results
- .map(([amount, withdrawRound], i) => ({
- amount,
- withdrawRound,
- id: start + i,
- }))
- .filter(({ amount }) => amount > 0n)
- .map(({ amount, withdrawRound, id }) => ({
- id: `${address.toLowerCase()}-${id}`,
- unbondingLockId: id,
- amount: formatEther(amount),
- withdrawRound: withdrawRound.toString(),
- delegate: { id: delegateAddress.toLowerCase() },
- }));
-
- return res.status(200).json({ locks });
- } else {
- return badRequest(res, "Invalid address format");
- }
- }
-
- return methodNotAllowed(res, method ?? "unknown", ["GET"]);
- } catch (err) {
- return internalError(res, err);
- }
-};
-
-export default handler;