Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate DSRHyperdriveABI, Fix Router #202

Merged
merged 6 commits into from
Jul 3, 2023
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
90 changes: 40 additions & 50 deletions apps/hyperdrive-trading/src/ui/app/App/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ReactElement, useMemo } from "react";
import { ReactElement } from "react";
import {
createBrowserRouter,
Outlet,
Expand All @@ -9,7 +9,6 @@ import { Markets } from "src/pages/Markets";
import { Trade } from "src/pages/Trade";
import { Navbar } from "src/ui/app/Navbar/Navbar";
import { useAppConfig } from "src/ui/appconfig/useAppConfig";
import { useLocalStorage } from "src/ui/base/hooks/useLocalStorage";

const LASTED_VIEWED_MARKET_KEY = "last-viewed-market";

Expand All @@ -22,65 +21,56 @@ function BaseLayout(): ReactElement {
);
}

export function App(): ReactElement {
export function App(): ReactElement | null {
const { appConfig } = useAppConfig();
if (appConfig) {
// eslint-disable-next-line no-console
console.log("appConfig", appConfig);
}

const [lastViewedMarket, setLastViewedMarket] = useLocalStorage<
string | undefined
>(LASTED_VIEWED_MARKET_KEY, undefined);
if (!appConfig) {
return null;
}

const router = useMemo(() => {
return createBrowserRouter([
{
path: "/",
element: <BaseLayout />,
children: [
{
path: "/",
element: <Markets />,
},
{
path: "markets",
element: <Markets />,
},
{
path: "/trade",
loader: () => {
if (lastViewedMarket) {
return redirect(`/trade/${lastViewedMarket}`);
}
// we fall back to the first market in the config
// this should rarely happen
return redirect(`/trade/${appConfig?.hyperdrives[0].address}`);
},
const router = createBrowserRouter([
{
path: "/",
element: <BaseLayout />,
children: [
{
path: "/",
element: <Markets />,
},
{
path: "markets",
element: <Markets />,
},
{
path: "/trade",
loader: () => {
return redirect(`/trade/${appConfig?.hyperdrives[0].address}`);
},
{
path: "/trade/:address",
element: <Trade />,
loader: ({ params }) => {
const market = appConfig?.hyperdrives.find(
(market) => market.address === params.address,
);
},
{
path: "/trade/:address",
element: <Trade />,
loader: ({ params }) => {
const market = appConfig?.hyperdrives.find(
(market) => market.address === params.address,
);

if (market) {
setLastViewedMarket(market.address);
return market;
}
if (market) {
return market;
}

// we fall back to the first market in the config
// this should rarely happen
return redirect(`/trade/${appConfig?.hyperdrives[0].address}`);
},
// we fall back to the first market in the config
// this should rarely happen
return redirect(`/trade/${appConfig?.hyperdrives[0].address}`);
},
],
},
]);
/* eslint-disable-next-line react-hooks/exhaustive-deps */
}, [appConfig]);
},
],
},
]);

return (
<div className="flex h-full flex-col overflow-auto bg-base-100">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ export function useCloseLong({
enabled = true,
}: UseCloseLongOptions): UseCloseLongResult {
const queryEnabled =
!!long && !!bondAmountIn && !!minBaseAmountOut && !!destination && enabled;
!!long &&
!!bondAmountIn &&
minBaseAmountOut !== undefined && // check undefined since 0 is valid
!!destination &&
enabled;

const { config } = usePrepareContractWrite({
abi: HyperdriveABI,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DSRHyperdriveABI } from "@hyperdrive/core";
import { HyperdriveABI } from "@hyperdrive/core";
import { QueryStatus, useQuery } from "@tanstack/react-query";
import { Address, useAccount, usePublicClient } from "wagmi";

Expand Down Expand Up @@ -37,7 +37,7 @@ export function usePreviewCloseLong({
!!hyperdriveAddress &&
!!maturityTime &&
!!bondAmountIn &&
!!minBaseAmountOut &&
minBaseAmountOut !== undefined && // check undefined since 0 is valid
!!destination &&
!!publicClient &&
!!account &&
Expand All @@ -56,7 +56,7 @@ export function usePreviewCloseLong({
? async () => {
// TODO: Refactor this to the math library instead
const { result } = await publicClient.simulateContract({
abi: DSRHyperdriveABI,
abi: HyperdriveABI,
address: hyperdriveAddress,
account,
functionName: "closeLong",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@ export function CloseLongForm({
hyperdriveAddress: long.hyperdriveAddress,
maturityTime: long.maturity,
bondAmountIn: amountAsBigInt,
minBaseAmountOut: parseUnits("0.01", baseDecimals),
minBaseAmountOut: parseUnits("0", baseDecimals),
destination: account,
});

const { closeLong, isPendingWalletAction } = useCloseLong({
long,
bondAmountIn: amountAsBigInt,
minBaseAmountOut: parseUnits("1", baseDecimals),
minBaseAmountOut: parseUnits("0", baseDecimals),
destination: account,
enabled: previewCloseLongStatus === "success",
});
Expand Down
25 changes: 9 additions & 16 deletions apps/hyperdrive-trading/src/ui/trade/OpenLongForm/OpenLongForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { ethers } from "ethers";
import { ReactElement } from "react";
import { Hyperdrive } from "src/appconfig/types";
import { parseUnits } from "src/base/parseUnits";
import { Button } from "src/ui/base/components/Button";
import { useNumericInput } from "src/ui/base/hooks/useNumericInput";
import { useOpenLong } from "src/ui/hyperdrive/hooks/useOpenLong";
import { usePreviewOpenLong } from "src/ui/hyperdrive/hooks/usePreviewOpenLong";
Expand Down Expand Up @@ -99,40 +98,34 @@ export function OpenLongForm({ market }: OpenLongFormProps): ReactElement {
{account ? (
needsApproval ? (
// Approval button
<Button
<button
disabled={!approve}
variant="Work"
size="lg"
block
className="daisy-btn-warning daisy-btn"
onClick={() => approve?.()}
>
<h5>Approve {market.baseToken.symbol}</h5>
</Button>
</button>
) : (
// Trade button
<Button
<button
disabled={
!openLong ||
openLongTransactionStatus === "loading" ||
openLongStatus === "loading"
}
variant="Emerald"
size="lg"
block
className="daisy-btn-secondary daisy-btn"
onClick={() => openLong?.()}
>
<h5>Open Long</h5>
</Button>
</button>
)
) : (
<Button
variant="Emerald"
size="lg"
block
<button
className="daisy-btn-secondary daisy-btn"
onClick={() => openConnectModal?.()}
>
<h5>Connect wallet</h5>
</Button>
</button>
)}
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@ export function OpenLongModalButton({
Open a long
</p>
<p className="font-light">
Earn fixed rate yield on your existing DAI holdings
Earn the fixed rate on your current DAI holdings
</p>
{/* Using a div styled as a button here just as a visual cue. Don't
use a real button here since the Well is interactive already, and
doing so would create invalid dom nesting of buttons. */}
<div className="daisy-btn-secondary daisy-btn-sm daisy-btn mt-2 justify-between gap-0 border-secondary normal-case">
<span className="ml-4 flex-1 text-center">Long</span>
<ChevronRightIcon className="h-3 text-right" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { useConnectModal } from "@rainbow-me/rainbowkit";
import { ConnectButton, useConnectModal } from "@rainbow-me/rainbowkit";
import { constants, ethers } from "ethers";
import { ReactElement } from "react";
import { Hyperdrive } from "src/appconfig/types";
import { convertMillisecondsToMonths } from "src/base/covertMillisecondsToMonths";
import { Button } from "src/ui/base/components/Button";
import { useNumericInput } from "src/ui/base/hooks/useNumericInput";
import { useOpenShort } from "src/ui/hyperdrive/hooks/useOpenShort";
import { usePreviewOpenShort } from "src/ui/hyperdrive/hooks/usePreviewOpenShort";
Expand All @@ -17,7 +16,7 @@ interface OpenShortPositionFormProps {
market: Hyperdrive;
}

export function OpenShortPositionForm({
export function OpenShortForm({
market,
}: OpenShortPositionFormProps): ReactElement {
const { address: account } = useAccount();
Expand Down Expand Up @@ -74,53 +73,35 @@ export function OpenShortPositionForm({

const openShortButton = () => {
if (!account) {
return (
<Button
variant="Crimson"
size="lg"
block
onClick={() => openConnectModal?.()}
>
<h5>Connect wallet</h5>
</Button>
);
return <ConnectButton />;
}

if (hasEnoughBalance === true) {
if (needsApproval) {
return (
<Button
disabled={!approve}
variant="Work"
onClick={() => approve?.()}
>
<h5>Approve {market.baseToken.symbol}</h5>
</Button>
);
} else {
return (
<Button
disabled={
!openShort ||
openShortTransactionStatus === "loading" ||
openShortSubmittedStatus === "loading"
}
variant="Crimson"
size="lg"
block
onClick={() => openShort?.()}
>
<h5>Open Short</h5>
</Button>
);
}
} else {
if (needsApproval) {
return (
<Button variant="Crimson" size="lg" block onClick={() => {}}>
<h5>Not enough {market.baseToken.symbol}</h5>
</Button>
<button
disabled={!approve}
className="daisy-btn-warning daisy-btn"
onClick={() => approve?.()}
>
Approve {market.baseToken.symbol}
</button>
);
}

return (
<button
disabled={
!hasEnoughBalance ||
!openShort ||
openShortTransactionStatus === "loading" ||
openShortSubmittedStatus === "loading"
}
className="daisy-btn-accent daisy-btn"
onClick={() => openShort?.()}
>
<h5>Open Short</h5>
</button>
);
};

const current = new Date();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { BoltIcon, ChevronRightIcon } from "@heroicons/react/24/outline";
import { ReactElement } from "react";
import { Hyperdrive } from "src/appconfig/types";
import { Modal } from "src/ui/base/components/Modal/Modal";
import { Well } from "src/ui/base/components/Well/Well";
import { OpenShortForm } from "src/ui/trade/OpenShortForm/OpenShortForm";

const OPEN_SHORT_MODAL_ID = "openShortModal";
export function OpenShortModalButton({
hyperdrive,
}: {
hyperdrive: Hyperdrive;
}): ReactElement {
return (
<Modal
modalId={OPEN_SHORT_MODAL_ID}
modalContent={<OpenShortForm market={hyperdrive} />}
>
{({ showModal }) => (
<Well interactive variant="accent" onClick={() => showModal()}>
<div className="flex w-52 flex-col gap-2 py-4 text-center">
<BoltIcon className="mb-2 h-16 text-accent" />
<p className="font-lato text-h5 font-light text-accent">
Open a short
</p>
<p className="font-light ">
Maximize your exposure to the DAI Savings Rate (DSR)
</p>
{/* Using a div styled as a button here just as a visual cue. Don't
use a real button here since the Well is interactive already, and
doing so would create invalid dom nesting of buttons. */}
<div className="daisy-btn-accent daisy-btn-sm daisy-btn mt-2 justify-between gap-0 normal-case">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be a button?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good eye, I need to add a comment here. Using a div since using button would created nested buttons in the markup. The parent element is a button (Well set to interactive), and so we just want this here as a visual cue.

<span className="ml-4 flex-1 text-center">Short</span>
<ChevronRightIcon className="h-3 text-right" />
</div>
</div>
</Well>
)}
</Modal>
);
}
Loading