Skip to content

Commit

Permalink
/contracts: multiple troves fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
bpierre committed Apr 13, 2024
1 parent a57d0c5 commit 0c817a6
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 96 deletions.
111 changes: 75 additions & 36 deletions frontend/src/app/contracts/ContractBorrowerOperations.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import type { Address } from "@/src/types";
import type { Dnum } from "dnum";

import { BorrowerOperations } from "@/src/abi/BorrowerOperations";
import { FormField } from "@/src/comps/FormField/FormField";
import { TextInput } from "@/src/comps/Input/TextInput";
import { CONTRACT_BORROWER_OPERATIONS } from "@/src/env";
import { ADDRESS_ZERO } from "@/src/eth-utils";
import { parseInputAddress, parseInputPercentage, parseInputValue } from "@/src/form-utils";
import { parseInputInt, parseInputPercentage, parseInputValue } from "@/src/form-utils";
import { getTroveId } from "@/src/liquity-utils";
import * as dn from "dnum";
import { useState } from "react";
import { useAccount, useWriteContract } from "wagmi";
Expand All @@ -28,33 +27,38 @@ export function ContractBorrowerOperations() {
);
}

type FormValue<T> = [fieldValue: string, parsedValue: T];

function OpenTrove() {
const account = useAccount();
const { writeContract } = useWriteContract();

const [formValues, setFormValues] = useState<{
maxFeePercentage: [string, Dnum];
boldAmount: [string, Dnum];
upperHint: [string, Address];
lowerHint: [string, Address];
annualInterestRate: [string, Dnum];
ethValue: [string, Dnum];
ownerIndex: FormValue<bigint>;
maxFeePercentage: FormValue<Dnum>;
boldAmount: FormValue<Dnum>;
upperHint: FormValue<Dnum>;
lowerHint: FormValue<Dnum>;
annualInterestRate: FormValue<Dnum>;
ethAmount: FormValue<Dnum>;
}>(() => ({
ownerIndex: ["", 0n],
maxFeePercentage: ["", dn.from(0, 18)],
boldAmount: ["", dn.from(0, 18)],
upperHint: ["", ADDRESS_ZERO],
lowerHint: ["", ADDRESS_ZERO],
upperHint: ["", dn.from(0, 18)],
lowerHint: ["", dn.from(0, 18)],
annualInterestRate: ["", dn.from(0, 18)],
ethValue: ["", dn.from(0, 18)],
ethAmount: ["", dn.from(0, 18)],
}));

const formProps = Object.fromEntries([
["ownerIndex", parseInputInt] as const,
["maxFeePercentage", parseInputValue] as const,
["boldAmount", parseInputValue] as const,
["upperHint", parseInputAddress] as const,
["lowerHint", parseInputAddress] as const,
["upperHint", parseInputValue] as const,
["lowerHint", parseInputValue] as const,
["annualInterestRate", parseInputPercentage] as const,
["ethValue", parseInputValue] as const,
["ethAmount", parseInputValue] as const,
].map(([name, valueParser]) => [name, {
onChange: (value: string) => {
const parsedValue = valueParser(value);
Expand All @@ -75,26 +79,28 @@ function OpenTrove() {
address: CONTRACT_BORROWER_OPERATIONS,
functionName: "openTrove",
args: [
account.address,
formValues.ownerIndex[1],
formValues.maxFeePercentage[1][0],
formValues.ethAmount[1][0],
formValues.boldAmount[1][0],
formValues.upperHint[1],
formValues.lowerHint[1],
formValues.upperHint[1][0],
formValues.lowerHint[1][0],
formValues.annualInterestRate[1][0],
],
value: formValues.ethValue[1][0],
});
}
};

const onFillExample = () => {
const address = account.address ?? ADDRESS_ZERO;
setFormValues({
ownerIndex: ["0", 0n],
maxFeePercentage: ["100", [100n * 10n ** 16n, 18]],
boldAmount: ["1800", [1800n * 10n ** 18n, 18]],
upperHint: [address, address],
lowerHint: [address, address],
upperHint: ["0", [0n, 18]],
lowerHint: ["0", [0n, 18]],
annualInterestRate: ["5", [5n * 10n ** 16n, 18]],
ethValue: ["20", [20n * 10n ** 18n, 18]],
ethAmount: ["20", [20n * 10n ** 18n, 18]],
});
};

Expand All @@ -104,9 +110,15 @@ function OpenTrove() {
onSubmit={onSubmit}
title="Open Trove"
>
<FormField label="Owner Index">
<TextInput {...formProps.ownerIndex} />
</FormField>
<FormField label="Max Fee Percentage">
<TextInput {...formProps.maxFeePercentage} />
</FormField>
<FormField label="ETH Amount">
<TextInput {...formProps.ethAmount} />
</FormField>
<FormField label="BOLD Amount">
<TextInput {...formProps.boldAmount} />
</FormField>
Expand All @@ -119,30 +131,57 @@ function OpenTrove() {
<FormField label="Annual Interest Rate">
<TextInput {...formProps.annualInterestRate} />
</FormField>
<FormField label="Collateral (value)">
<TextInput {...formProps.ethValue} />
</FormField>
</ContractAction>
);
}

function CloseTrove() {
const account = useAccount();
const { writeContract } = useWriteContract();

const [formValues, setFormValues] = useState<{
ownerIndex: FormValue<bigint>;
}>(() => ({
ownerIndex: ["", 0n],
}));

const formProps = Object.fromEntries([
["ownerIndex", parseInputInt] as const,
].map(([name, valueParser]) => [name, {
onChange: (value: string) => {
const parsedValue = valueParser(value);
if (parsedValue !== null) {
setFormValues((values) => ({
...values,
[name]: [value, parsedValue],
}));
}
},
value: formValues[name][0],
}]));

const onSubmit = () => {
if (account.address) {
writeContract({
abi: BorrowerOperations,
address: CONTRACT_BORROWER_OPERATIONS,
functionName: "closeTrove",
args: [
getTroveId(account.address, formValues.ownerIndex[1]),
],
});
}
};

return (
<ContractAction
title="Close Trove"
onSubmit={() => {
if (account.address) {
writeContract({
abi: BorrowerOperations,
address: CONTRACT_BORROWER_OPERATIONS,
functionName: "closeTrove",
args: [],
});
}
}}
/>
onSubmit={onSubmit}
>
<FormField label="Owner Index">
<TextInput {...formProps.ownerIndex} />
</FormField>
</ContractAction>
);
}

Expand Down
31 changes: 15 additions & 16 deletions frontend/src/app/contracts/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { ReactNode } from "react";

import { ADDRESS_ZERO, shortenAddress } from "@/src/eth-utils";
import {
getTroveId,
useBoldBalance,
useCloseTrove,
useLiquity2Info,
Expand Down Expand Up @@ -54,7 +55,7 @@ function AccountDetails() {
const { address } = useAccount();
const balance = useBalance({ address: address ?? ADDRESS_ZERO });
const boldBalance = useBoldBalance(address ?? ADDRESS_ZERO);
const rewards = useRewards(address ?? ADDRESS_ZERO);
const rewards = useRewards(getTroveId(address ?? ADDRESS_ZERO, 0n));
return (
<Card
title="Account"
Expand All @@ -75,7 +76,7 @@ function AccountDetails() {
)
.when(
({ address, data }) => address && data.some(({ status }) => status === "error"),
() => <div>error</div>,
({ data }) => <div>error</div>,
)
.with(
{
Expand Down Expand Up @@ -122,21 +123,22 @@ function AccountDetails() {

function TroveDetails() {
const { address } = useAccount();
const troveDetails = useTroveDetails(address ?? ADDRESS_ZERO);
const troveDetails = useTroveDetails(address && getTroveId(address, 0n));

const closeTrove = useCloseTrove(address ?? ADDRESS_ZERO);
const closeTrove = useCloseTrove(getTroveId(address ?? ADDRESS_ZERO, 0n));
const openTrove = useOpenTrove(address ?? ADDRESS_ZERO, {
ownerIndex: 0n,
maxFeePercentage: 100n * 10n ** 16n, // 100%
boldAmount: 1800n * 10n ** 18n, // 1800 BOLD
upperHint: address ?? ADDRESS_ZERO,
lowerHint: address ?? ADDRESS_ZERO,
upperHint: 0n,
lowerHint: 0n,
interestRate: 5n * 10n ** 16n, // 5%
value: 20n * 10n ** 18n, // 20 ETH
ethAmount: 20n * 10n ** 18n, // 20 ETH
});

return (
<Card
title="Trove"
title="Trove #0"
action={match([troveDetails.data?.status, address])
.with(
[
Expand Down Expand Up @@ -193,20 +195,20 @@ function Liquity2Info() {
<>
<CardRow
name="Troves Count"
value={data.trovesCount}
value="?"
/>
<CardRow
name="Total Collateral"
value={dn.format(data.totalCollateral) + " ETH"}
/>
<CardRow
name="Total Debt"
value={dn.format(data.totalDebt) + " BOLD"}
value={dn.format(data.totalDebt, 2) + " BOLD"}
/>
<CardRow
name={
<>
<abbr title="Total Collateral Ratio">TCR</abbr> ($4k/ETH)
<abbr title="Total Collateral Ratio">TCR</abbr> ($200/ETH)
</>
}
value={dn.format(dn.mul(data.tcr, 100n), 2) + "%"}
Expand Down Expand Up @@ -326,13 +328,10 @@ function CardRow({
alignItems: "center",
gap: 80,
height: 32,
whiteSpace: "nowrap",
})}
>
<div
className={css({
whiteSpace: "nowrap",
})}
>
<div>
{name}
</div>
<div>{value}</div>
Expand Down
11 changes: 11 additions & 0 deletions frontend/src/form-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ export function isInputValueFloat(value: string) {
return inputValueRegex.test(value);
}

const inputIntRegex = /^[0-9]*$/;
export function isInputValueInt(value: string) {
value = value.trim();
return inputIntRegex.test(value);
}

export function parseInputValue(value: string) {
value = value.trim();

Expand All @@ -29,6 +35,11 @@ export function parseInputPercentage(value: string) {
return dn.div(parsedValue, 100);
}

export function parseInputInt(value: string) {
value = value.trim();
return isInputValueInt(value) ? BigInt(value) : null;
}

export function parseInputAddress(value: string) {
value = value.trim();
return isAddress(value) ? value : ADDRESS_ZERO;
Expand Down
Loading

0 comments on commit 0c817a6

Please sign in to comment.