Skip to content

Commit

Permalink
Reset allocations before staking / unstaking (#691)
Browse files Browse the repository at this point in the history
  • Loading branch information
bpierre authored Jan 14, 2025
1 parent 2c8a046 commit 6ba0538
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 11 deletions.
12 changes: 10 additions & 2 deletions frontend/app/src/services/TransactionFlow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,16 @@ export type FlowStepDeclaration<FlowRequest extends BaseFlowRequest = BaseFlowRe

export type FlowDeclaration<FlowRequest extends BaseFlowRequest> = {
title: ReactNode;
Summary: ComponentType<{ request: FlowRequest; steps: FlowStep[] | null }>;
Details: ComponentType<{ request: FlowRequest; steps: FlowStep[] | null }>;
Summary: ComponentType<{
account: Address | null;
request: FlowRequest;
steps: FlowStep[] | null;
}>;
Details: ComponentType<{
account: Address | null;
request: FlowRequest;
steps: FlowStep[] | null;
}>;
steps: Record<string, FlowStepDeclaration<FlowRequest>>;
getSteps: (params: FlowParams<FlowRequest>) => Promise<string[]>;
parseRequest: (request: unknown) => FlowRequest | null;
Expand Down
18 changes: 11 additions & 7 deletions frontend/app/src/tx-flows/allocateVotingPower.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Amount } from "@/src/comps/Amount/Amount";
import { getUserStates, useInitiatives } from "@/src/liquity-governance";
import { TransactionDetailsRow } from "@/src/screens/TransactionsScreen/TransactionsScreen";
import { TransactionStatus } from "@/src/screens/TransactionsScreen/TransactionStatus";
import { useGovernanceUser } from "@/src/subgraph-hooks";
import { GovernanceUserAllocated, graphQuery } from "@/src/subgraph-queries";
import { vVoteAllocations } from "@/src/valibot-utils";
import { css } from "@/styled-system/css";
Expand Down Expand Up @@ -132,8 +133,10 @@ export const allocateVotingPower: FlowDeclaration<AllocateVotingPowerRequest> =
);
},

Details({ request }) {
Details({ request, account }) {
const initiatives = useInitiatives();
const governanceUser = useGovernanceUser(account);
const stakedLQTY = governanceUser.data?.stakedLQTY ?? 0n;
return (
<>
{Object.entries(request.voteAllocations).map(([address, vote]) => {
Expand All @@ -143,6 +146,7 @@ export const allocateVotingPower: FlowDeclaration<AllocateVotingPowerRequest> =
key={address}
initiative={initiative}
vote={vote}
stakedLQTY={stakedLQTY}
/>
);
})}
Expand All @@ -162,7 +166,7 @@ export const allocateVotingPower: FlowDeclaration<AllocateVotingPowerRequest> =
const userStates = await getUserStates(wagmiConfig, account);

const { voteAllocations } = request;
const { unallocatedLQTY } = userStates;
const { stakedLQTY } = userStates;

const initiativeAddresses = Object.keys(voteAllocations) as Address[];

Expand All @@ -172,16 +176,13 @@ export const allocateVotingPower: FlowDeclaration<AllocateVotingPowerRequest> =
vetos: new Array(initiativeAddresses.length).fill(0n) as bigint[],
};

let remainingLqty = unallocatedLQTY;

for (const [index, address] of initiativeAddresses.entries()) {
const vote = voteAllocations[address];
if (!vote) {
throw new Error("Vote not found");
}

let qty = dn.mul([unallocatedLQTY, 18], vote.value)[0];
remainingLqty -= qty;
let qty = dn.mul([stakedLQTY, 18], vote.value)[0];

if (vote?.vote === "for") {
allocationArgs.votes[index] = qty;
Expand Down Expand Up @@ -225,10 +226,13 @@ export const allocateVotingPower: FlowDeclaration<AllocateVotingPowerRequest> =
function VoteAllocation({
initiative,
vote,
stakedLQTY,
}: {
initiative: Initiative;
vote: VoteAllocation;
stakedLQTY: bigint;
}) {
const lqtyAllocation = dn.mul([stakedLQTY, 18], vote.value);
return (
<TransactionDetailsRow
label={[
Expand Down Expand Up @@ -257,7 +261,7 @@ function VoteAllocation({
alignItems: "center",
})}
>
{vote.vote === "for" ? "Support" : "Oppose"}
{vote.vote === "for" ? "Support" : "Oppose"} with <Amount value={lqtyAllocation} /> LQTY
</div>,
]}
/>
Expand Down
41 changes: 41 additions & 0 deletions frontend/app/src/tx-flows/stakeDeposit.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { FlowDeclaration } from "@/src/services/TransactionFlow";
import type { Address } from "@/src/types";

import { Amount } from "@/src/comps/Amount/Amount";
import { StakePositionSummary } from "@/src/comps/StakePositionSummary/StakePositionSummary";
Expand All @@ -8,6 +9,7 @@ import { PermissionStatus } from "@/src/screens/TransactionsScreen/PermissionSta
import { TransactionDetailsRow } from "@/src/screens/TransactionsScreen/TransactionsScreen";
import { TransactionStatus } from "@/src/screens/TransactionsScreen/TransactionStatus";
import { usePrice } from "@/src/services/Prices";
import { GovernanceUserAllocated, graphQuery } from "@/src/subgraph-queries";
import { vDnum, vPositionStake } from "@/src/valibot-utils";
import * as dn from "dnum";
import * as v from "valibot";
Expand Down Expand Up @@ -82,6 +84,33 @@ export const stakeDeposit: FlowDeclaration<StakeDepositRequest> = {
},
},

// reset allocations
resetAllocations: {
name: () => "Reset Allocations",
Status: TransactionStatus,

async commit({ account, contracts, wagmiConfig }) {
if (!account) {
throw new Error("Account address is required");
}

const allocated = await graphQuery(
GovernanceUserAllocated,
{ id: account.toLowerCase() },
);

return writeContract(wagmiConfig, {
...contracts.Governance,
functionName: "resetAllocations",
args: [(allocated.governanceUser?.allocated ?? []) as Address[], true],
});
},

async verify({ wagmiConfig }, hash) {
await verifyTransaction(wagmiConfig, hash);
},
},

// approve via permit
permitLqty: {
name: () => "Approve LQTY",
Expand Down Expand Up @@ -203,6 +232,18 @@ export const stakeDeposit: FlowDeclaration<StakeDepositRequest> = {

const steps: string[] = [];

// check if the user has any allocations
const allocated = await graphQuery(
GovernanceUserAllocated,
{ id: account.toLowerCase() },
);
if (
allocated.governanceUser
&& allocated.governanceUser.allocated.length > 0
) {
steps.push("resetAllocations");
}

// get the user proxy address
const userProxyAddress = await readContract(wagmiConfig, {
...contracts.Governance,
Expand Down
52 changes: 50 additions & 2 deletions frontend/app/src/tx-flows/unstakeDeposit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { StakePositionSummary } from "@/src/comps/StakePositionSummary/StakePosi
import { TransactionDetailsRow } from "@/src/screens/TransactionsScreen/TransactionsScreen";
import { TransactionStatus } from "@/src/screens/TransactionsScreen/TransactionStatus";
import { usePrice } from "@/src/services/Prices";
import { GovernanceUserAllocated, graphQuery } from "@/src/subgraph-queries";
import { vDnum, vPositionStake } from "@/src/valibot-utils";
import * as dn from "dnum";
import * as v from "valibot";
Expand Down Expand Up @@ -57,6 +58,33 @@ export const unstakeDeposit: FlowDeclaration<UnstakeDepositRequest> = {
},

steps: {
// reset allocations
resetAllocations: {
name: () => "Reset Allocations",
Status: TransactionStatus,

async commit({ account, contracts, wagmiConfig }) {
if (!account) {
throw new Error("Account address is required");
}

const allocated = await graphQuery(
GovernanceUserAllocated,
{ id: account.toLowerCase() },
);

return writeContract(wagmiConfig, {
...contracts.Governance,
functionName: "resetAllocations",
args: [(allocated.governanceUser?.allocated ?? []) as Address[], true],
});
},

async verify({ wagmiConfig }, hash) {
await verifyTransaction(wagmiConfig, hash);
},
},

unstakeDeposit: {
name: () => "Unstake",
Status: TransactionStatus,
Expand All @@ -76,8 +104,28 @@ export const unstakeDeposit: FlowDeclaration<UnstakeDepositRequest> = {
},
},

async getSteps() {
return ["unstakeDeposit"];
async getSteps({ account }) {
if (!account) {
throw new Error("Account address is required");
}

const steps: string[] = [];

// check if the user has any allocations
const allocated = await graphQuery(
GovernanceUserAllocated,
{ id: account.toLowerCase() },
);
if (
allocated.governanceUser
&& allocated.governanceUser.allocated.length > 0
) {
steps.push("resetAllocations");
}

steps.push("unstakeDeposit");

return steps;
},

parseRequest(request) {
Expand Down

0 comments on commit 6ba0538

Please sign in to comment.