Skip to content

Commit 894848d

Browse files
committed
Merge branch 'main' into 310-showcase-orchestrator-voting-activity-in-the-ui
2 parents ea087fc + fa98eca commit 894848d

File tree

38 files changed

+606
-237
lines changed

38 files changed

+606
-237
lines changed

components/Approve/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { livepeerToken } from "@lib/api/abis/main/LivepeerToken";
2-
import { useHandleTransaction } from "hooks";
32
import {
43
useBondingManagerAddress,
54
useLivepeerTokenAddress,
65
} from "hooks/useContracts";
6+
import { useHandleTransaction } from "hooks/useHandleTransaction";
77
import { useSimulateContract, useWriteContract } from "wagmi";
88

99
import { MAXIMUM_VALUE_UINT256 } from "../../lib/utils";

components/Claim/index.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
1-
import { LAYOUT_MAX_WIDTH } from "@layouts/main";
1+
import { LAYOUT_MAX_WIDTH } from "@layouts/constants";
22
import { l2Migrator } from "@lib/api/abis/bridge/L2Migrator";
33
import { getL2MigratorAddress } from "@lib/api/contracts";
44
import { Box, Button, Container, Flex, Text } from "@livepeer/design-system";
55
import { ArrowTopRightIcon } from "@modulz/radix-icons";
66
import { constants, ethers } from "ethers";
7-
import {
8-
useAccountAddress,
9-
useHandleTransaction,
10-
useL1DelegatorData,
11-
} from "hooks";
7+
import { useAccountAddress, useL1DelegatorData } from "hooks";
8+
import { useHandleTransaction } from "hooks/useHandleTransaction";
129
import { CHAIN_INFO, DEFAULT_CHAIN_ID } from "lib/chains";
1310
import { useEffect, useState } from "react";
1411
import { Hex } from "viem";

components/DelegatingView/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ import { AccountQueryResult, OrchestratorsSortedQueryResult } from "apollo";
88
import {
99
useAccountAddress,
1010
useEnsData,
11-
useHandleTransaction,
1211
usePendingFeesAndStakeData,
1312
} from "hooks";
1413
import { useBondingManagerAddress } from "hooks/useContracts";
14+
import { useHandleTransaction } from "hooks/useHandleTransaction";
1515
import Link from "next/link";
1616
import { useRouter } from "next/router";
1717
import numbro from "numbro";

components/DelegatingWidget/Delegate.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import { bondingManager } from "@lib/api/abis/main/BondingManager";
22
import { livepeerToken } from "@lib/api/abis/main/LivepeerToken";
33
import { MAXIMUM_VALUE_UINT256 } from "@lib/utils";
44
import { Box, Button } from "@livepeer/design-system";
5-
import { useHandleTransaction } from "hooks";
65
import {
76
useBondingManagerAddress,
87
useLivepeerTokenAddress,
98
} from "hooks/useContracts";
9+
import { useHandleTransaction } from "hooks/useHandleTransaction";
1010
import { useMemo, useState } from "react";
1111
import { parseEther } from "viem";
1212
import { useSimulateContract, useWriteContract } from "wagmi";

components/DelegatingWidget/Footer.tsx

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,17 +78,22 @@ const Footer = ({
7878
() => getDelegatorStatus(delegator, currentRound),
7979
[currentRound, delegator]
8080
);
81-
const stake = useMemo(
81+
const stakeWei = useMemo(
8282
() =>
8383
delegatorPendingStakeAndFees?.pendingStake
84-
? +delegatorPendingStakeAndFees?.pendingStake
85-
: 0,
84+
? BigInt(delegatorPendingStakeAndFees.pendingStake)
85+
: null,
8686
[delegatorPendingStakeAndFees]
8787
);
88-
const sufficientStake = useMemo(
89-
() => delegator && amount && parseFloat(amount) <= stake,
90-
[delegator, amount, stake]
91-
);
88+
const sufficientStake = useMemo(() => {
89+
if (!delegator || !amount || stakeWei === null) return false;
90+
try {
91+
const amountWei = parseEther(amount);
92+
return amountWei <= stakeWei;
93+
} catch {
94+
return false;
95+
}
96+
}, [delegator, amount, stakeWei]);
9297
const canUndelegate = useMemo(
9398
() => isMyTranscoder && isDelegated && parseFloat(amount) > 0,
9499
[isMyTranscoder, isDelegated, amount]
@@ -116,6 +121,24 @@ const Footer = ({
116121
[newActiveSetOrder, transcoder]
117122
);
118123

124+
// Check if unbonding will deactivate the orchestrator
125+
const isOwnOrchestrator = useMemo(
126+
() =>
127+
accountAddress?.toLowerCase() === delegator?.delegate?.id?.toLowerCase(),
128+
[accountAddress, delegator?.delegate?.id]
129+
);
130+
const willDeactivate = useMemo(() => {
131+
// Wait for stake data to load before determining deactivation
132+
if (!isOwnOrchestrator || stakeWei === null || !amount) return false;
133+
try {
134+
const amountWei = parseEther(amount);
135+
// Deactivates if unbonding all stake (amount >= current stake)
136+
return amountWei > 0n && amountWei >= stakeWei;
137+
} catch {
138+
return false;
139+
}
140+
}, [isOwnOrchestrator, stakeWei, amount]);
141+
119142
if (!accountAddress) {
120143
return (
121144
<>
@@ -162,6 +185,7 @@ const Footer = ({
162185
newPosPrev={newPosPrev}
163186
newPosNext={newPosNext}
164187
disabled={!canUndelegate || delegatorStatus === "Pending"}
188+
willDeactivate={willDeactivate}
165189
/>
166190
{renderUnstakeWarnings(
167191
amount,

components/DelegatingWidget/Undelegate.tsx

Lines changed: 133 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,37 @@
11
import { bondingManager } from "@lib/api/abis/main/BondingManager";
2-
import { Button } from "@livepeer/design-system";
3-
import { useAccountAddress, useHandleTransaction } from "hooks";
2+
import {
3+
Box,
4+
Button,
5+
Dialog,
6+
DialogContent,
7+
DialogTitle,
8+
Flex,
9+
Text,
10+
} from "@livepeer/design-system";
11+
import { useAccountAddress } from "hooks";
412
import { useBondingManagerAddress } from "hooks/useContracts";
13+
import { useHandleTransaction } from "hooks/useHandleTransaction";
14+
import { useState } from "react";
515
import { parseEther } from "viem";
616
import { useSimulateContract, useWriteContract } from "wagmi";
717

8-
const Undelegate = ({ amount, newPosPrev, newPosNext, disabled }) => {
18+
interface Props {
19+
amount: string;
20+
newPosPrev: string;
21+
newPosNext: string;
22+
disabled: boolean;
23+
willDeactivate: boolean;
24+
}
25+
26+
const Undelegate = ({
27+
amount,
28+
newPosPrev,
29+
newPosNext,
30+
disabled,
31+
willDeactivate,
32+
}: Props) => {
933
const accountAddress = useAccountAddress();
34+
const [showConfirmDialog, setShowConfirmDialog] = useState(false);
1035

1136
const args = {
1237
amount: parseEther(amount ? amount.toString() : "0"),
@@ -21,12 +46,34 @@ const Undelegate = ({ amount, newPosPrev, newPosNext, disabled }) => {
2146
address: bondingManagerAddress,
2247
abi: bondingManager,
2348
functionName: "unbondWithHint",
24-
args: [BigInt(args.amount.toString()), newPosPrev, newPosNext],
49+
args: [
50+
BigInt(args.amount.toString()),
51+
newPosPrev as `0x${string}`,
52+
newPosNext as `0x${string}`,
53+
],
2554
});
2655
const { data, isPending, writeContract, error, isSuccess } =
2756
useWriteContract();
2857

29-
useHandleTransaction("unbond", data, error, isPending, isSuccess, args);
58+
useHandleTransaction("unbond", data, error, isPending, isSuccess, {
59+
...args,
60+
wasDeactivated: willDeactivate,
61+
});
62+
63+
const handleUndelegate = () => {
64+
if (willDeactivate) {
65+
setShowConfirmDialog(true);
66+
} else if (config) {
67+
writeContract(config.request);
68+
}
69+
};
70+
71+
const handleConfirmUnbond = () => {
72+
setShowConfirmDialog(false);
73+
if (config) {
74+
writeContract(config.request);
75+
}
76+
};
3077

3178
if (!accountAddress) {
3279
return null;
@@ -41,10 +88,90 @@ const Undelegate = ({ amount, newPosPrev, newPosNext, disabled }) => {
4188
css={{
4289
width: "100%",
4390
}}
44-
onClick={() => config && writeContract(config.request)}
91+
onClick={handleUndelegate}
4592
>
4693
{!amount ? "Enter an amount" : "Undelegate"}
4794
</Button>
95+
96+
<Dialog open={showConfirmDialog} onOpenChange={setShowConfirmDialog}>
97+
<DialogContent
98+
css={{ maxWidth: 390, width: "100%" }}
99+
onPointerEnterCapture={undefined}
100+
onPointerLeaveCapture={undefined}
101+
placeholder={undefined}
102+
>
103+
<DialogTitle asChild>
104+
<Text
105+
as="h2"
106+
css={{
107+
fontWeight: 600,
108+
fontSize: "$4",
109+
marginBottom: "$3",
110+
lineHeight: 1.3,
111+
}}
112+
>
113+
Unbonding all stake
114+
</Text>
115+
</DialogTitle>
116+
117+
<Text
118+
css={{
119+
marginBottom: "$4",
120+
color: "$neutral11",
121+
lineHeight: 1.5,
122+
}}
123+
>
124+
This will{" "}
125+
<Text as="span" css={{ color: "$yellow9" }}>
126+
deactivate your orchestrator
127+
</Text>{" "}
128+
and remove you from the active set. You&apos;ll stop earning rewards
129+
until you stake again.
130+
</Text>
131+
132+
<Box
133+
css={{
134+
background: "$neutral3",
135+
border: "1px solid $neutral5",
136+
borderRadius: "$2",
137+
padding: "$3",
138+
marginBottom: "$4",
139+
display: "flex",
140+
justifyContent: "space-between",
141+
alignItems: "center",
142+
}}
143+
>
144+
<Text css={{ color: "$neutral11" }}>Amount</Text>
145+
<Text
146+
css={{
147+
fontWeight: 600,
148+
fontVariantNumeric: "tabular-nums",
149+
}}
150+
>
151+
{amount} LPT
152+
</Text>
153+
</Box>
154+
155+
<Flex css={{ gap: "$2", justifyContent: "flex-end" }}>
156+
<Button
157+
size="3"
158+
ghost
159+
onClick={() => setShowConfirmDialog(false)}
160+
css={{ minWidth: "unset" }}
161+
>
162+
Cancel
163+
</Button>
164+
<Button
165+
size="3"
166+
variant="red"
167+
onClick={handleConfirmUnbond}
168+
disabled={!config}
169+
>
170+
Yes, unbond my stake
171+
</Button>
172+
</Flex>
173+
</DialogContent>
174+
</Dialog>
48175
</>
49176
);
50177
};

components/ExplorerChart/index.tsx

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ const CustomizedXAxisTick = ({ x, y, payload }) => {
5353
);
5454
};
5555

56+
export type Group = "day" | "week" | "year" | "all";
57+
5658
const ExplorerChart = ({
5759
title,
5860
tooltip,
@@ -78,8 +80,8 @@ const ExplorerChart = ({
7880
| "small-unitless"
7981
| "none";
8082
type: "bar" | "line";
81-
grouping?: "day" | "week";
82-
onToggleGrouping?: (grouping: "day" | "week") => void;
83+
grouping?: Group;
84+
onToggleGrouping?: (grouping: Group) => void;
8385
}) => {
8486
const formatDateSubtitle = useCallback(
8587
(date: number) =>
@@ -351,6 +353,31 @@ const ExplorerChart = ({
351353
</Button>
352354
</Flex>
353355
)}
356+
{type === "line" && grouping && onToggleGrouping && (
357+
<Flex
358+
css={{
359+
position: "absolute",
360+
right: 0,
361+
zIndex: 3,
362+
}}
363+
>
364+
<Button
365+
onClick={() => onToggleGrouping("year")}
366+
size="1"
367+
variant={grouping === "year" ? "primary" : "neutral"}
368+
>
369+
Y
370+
</Button>
371+
<Button
372+
onClick={() => onToggleGrouping("all")}
373+
size="1"
374+
variant={grouping === "all" ? "primary" : "neutral"}
375+
css={{ marginLeft: "$1" }}
376+
>
377+
All
378+
</Button>
379+
</Flex>
380+
)}
354381
<Box
355382
css={{
356383
paddingTop: 57,

components/HistoryView/index.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,16 @@ const Index = () => {
3838
}
3939
);
4040

41-
const events = useMemo(
42-
() => data?.transactions?.flatMap(({ events: e }) => e ?? []) ?? [],
43-
[data]
44-
);
41+
const events = useMemo(() => {
42+
// First reverse the order of the array of events per transaction to have events in descending order
43+
const reversedEvents = data?.transactions?.map((tx) => {
44+
return {
45+
...tx,
46+
events: tx.events ? tx.events.slice().reverse() : [],
47+
};
48+
});
49+
return reversedEvents?.flatMap(({ events: e }) => e ?? []) ?? [];
50+
}, [data]);
4551

4652
const lastEventTimestamp = useMemo(
4753
() =>

components/InactiveWarning/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { LAYOUT_MAX_WIDTH } from "@layouts/main";
1+
import { LAYOUT_MAX_WIDTH } from "@layouts/constants";
22
import { Box, Button, Container, Text } from "@livepeer/design-system";
33
import { useAccountInactiveQuery } from "apollo";
44
import { useAccountAddress } from "hooks";

components/QueueExecuteButton/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import { livepeerGovernor } from "@lib/api/abis/main/LivepeerGovernor";
22
import { ProposalExtended } from "@lib/api/treasury";
33
import { Button } from "@livepeer/design-system";
44
import { ethers } from "ethers";
5-
import { useAccountAddress, useHandleTransaction } from "hooks";
5+
import { useAccountAddress } from "hooks";
66
import { useLivepeerGovernorAddress } from "hooks/useContracts";
7+
import { useHandleTransaction } from "hooks/useHandleTransaction";
78
import { useMemo } from "react";
89
import { Address } from "viem";
910
import {

0 commit comments

Comments
 (0)