diff --git a/packages/dev-frontend/src/components/Bonds/BondsTable.tsx b/packages/dev-frontend/src/components/Bonds/BondsTable.tsx
index aaf0e5e09..95cdb02a0 100644
--- a/packages/dev-frontend/src/components/Bonds/BondsTable.tsx
+++ b/packages/dev-frontend/src/components/Bonds/BondsTable.tsx
@@ -6,6 +6,8 @@ import * as lexicon from "./lexicon";
import { Empty } from "./views/idle/Empty";
import { Link } from "../Link";
import { useBondView } from "./context/BondViewContext";
+import { Decimal } from "@liquity/lib-base";
+import { InfiniteEstimate } from "./views/InfiniteEstimation";
const {
BONDS,
@@ -34,6 +36,8 @@ const formatDays = (days: number) =>
? "Now"
: parseFloat(days.toFixed(1)) < 1
? `${days.toFixed(1)} days`
+ : days > 10000
+ ? Decimal.INFINITY.toString()
: `${days.toFixed(0)} days`;
const Line = (columns: number) =>
@@ -107,17 +111,23 @@ export const BondsTable: React.FC = () => {
{Line(5)}
{pendingBonds.map((bond, idx) => {
- const breakEvenDays =
- (bond.breakEvenTime.getTime() - Date.now()) / 1000 / 60 / 60 / 24;
- const rebondDays = (bond.rebondTime.getTime() - Date.now()) / 1000 / 60 / 60 / 24;
+ const breakEvenDays = formatDays(
+ (bond.breakEvenTime.getTime() - Date.now()) / 1000 / 60 / 60 / 24
+ );
+ const rebondDays = formatDays(
+ (bond.rebondTime.getTime() - Date.now()) / 1000 / 60 / 60 / 24
+ );
return (
{bond.deposit.shorten()} LUSD
{bond.accrued.shorten()} bLUSD
{bond.marketValue.shorten()} LUSD
- {formatDays(breakEvenDays)}
- {formatDays(rebondDays)}
-
+
+
+
+
+
+
{Line(5)}
);
diff --git a/packages/dev-frontend/src/components/Bonds/context/api.ts b/packages/dev-frontend/src/components/Bonds/context/api.ts
index e01b550cb..27f899114 100644
--- a/packages/dev-frontend/src/components/Bonds/context/api.ts
+++ b/packages/dev-frontend/src/components/Bonds/context/api.ts
@@ -574,7 +574,7 @@ const getProtocolInfo = async (
rebondPeriodInDays
} = _getProtocolInfo(marketPrice, floorPrice, claimBondFee, alphaAccrualFactor);
- const simulatedMarketPrice = hasMarketPremium ? marketPrice : floorPrice.mul(1.1);
+ const simulatedMarketPrice = marketPrice;
const controllerTargetAge = Decimal.from(
(await chickenBondManager.targetAverageAgeSeconds()).toString()
diff --git a/packages/dev-frontend/src/components/Bonds/lexicon.ts b/packages/dev-frontend/src/components/Bonds/lexicon.ts
index f0855817d..38f2687d1 100644
--- a/packages/dev-frontend/src/components/Bonds/lexicon.ts
+++ b/packages/dev-frontend/src/components/Bonds/lexicon.ts
@@ -224,3 +224,8 @@ export const TREASURY_PERMANENT = {
export const ESTIMATES_ONLY_NOTICE = {
description: "These metrics are estimations based on the current bLUSD market price"
};
+
+export const INFINITE_ESTIMATION = {
+ description:
+ "The market price premium is currently too low to make bonding profitable. Bonds will be profitable again if the premium returns."
+};
diff --git a/packages/dev-frontend/src/components/Bonds/views/InfiniteEstimation.tsx b/packages/dev-frontend/src/components/Bonds/views/InfiniteEstimation.tsx
new file mode 100644
index 000000000..03f671f57
--- /dev/null
+++ b/packages/dev-frontend/src/components/Bonds/views/InfiniteEstimation.tsx
@@ -0,0 +1,23 @@
+import { Decimal, Decimalish } from "@liquity/lib-base";
+import { InfoIcon } from "../../InfoIcon";
+import { Card } from "theme-ui";
+import * as l from "../lexicon";
+
+type InfiniteEstimateProps = {
+ estimate: Decimalish;
+};
+
+export const InfiniteEstimate: React.FC = ({ estimate, children }) => {
+ if (estimate.toString() !== Decimal.INFINITY.toString()) return <>{children ?? estimate}>;
+
+ return (
+ <>
+ {Decimal.INFINITY.toString()}
+ {l.INFINITE_ESTIMATION.description}}
+ />
+
+ >
+ );
+};
diff --git a/packages/dev-frontend/src/components/Bonds/views/actioning/Actioning.tsx b/packages/dev-frontend/src/components/Bonds/views/actioning/Actioning.tsx
index 99a544599..a9830d9a9 100644
--- a/packages/dev-frontend/src/components/Bonds/views/actioning/Actioning.tsx
+++ b/packages/dev-frontend/src/components/Bonds/views/actioning/Actioning.tsx
@@ -12,6 +12,7 @@ import { Warning } from "../../../Warning";
import { ReactModal } from "../../../ReactModal";
import { percentify } from "../../utils";
import { Decimal } from "@liquity/lib-base";
+import { InfiniteEstimate } from "../InfiniteEstimation";
export const Actioning: React.FC = () => {
const { dispatchEvent, view, selectedBond: bond } = useBondView();
@@ -49,7 +50,11 @@ export const Actioning: React.FC = () => {
label: (
<>
- {`${bond.breakEvenAccrual.prettify(2)} bLUSD`}
+
+
+ {bond.breakEvenAccrual.prettify(2)} bLUSD
+
+
>
)
},
@@ -58,7 +63,11 @@ export const Actioning: React.FC = () => {
label: (
<>
- {`${bond.rebondAccrual.prettify(2)} bLUSD`}
+
+
+ {bond.rebondAccrual.prettify(2)} bLUSD
+
+
>
)
},
diff --git a/packages/dev-frontend/src/components/Bonds/views/creating/Details.tsx b/packages/dev-frontend/src/components/Bonds/views/creating/Details.tsx
index c47d08f5a..68d802725 100644
--- a/packages/dev-frontend/src/components/Bonds/views/creating/Details.tsx
+++ b/packages/dev-frontend/src/components/Bonds/views/creating/Details.tsx
@@ -6,7 +6,7 @@ import { EditableRow } from "../../../Trove/Editor";
import { Record } from "../../Record";
import { InfoIcon } from "../../../InfoIcon";
import { useBondView } from "../../context/BondViewContext";
-import { HorizontalTimeline, Label, SubLabel } from "../../../HorizontalTimeline";
+import { HorizontalTimeline, Label, SubLabel, UNKNOWN_DATE } from "../../../HorizontalTimeline";
import { EXAMPLE_NFT } from "../../context/BondViewProvider";
import * as l from "../../lexicon";
import { useWizard } from "../../../Wizard/Context";
@@ -25,6 +25,7 @@ import {
import { HorizontalSlider } from "../../../HorizontalSlider";
import { ErrorDescription } from "../../../ErrorDescription";
import { Amount } from "../../../ActionDescription";
+import { InfiniteEstimate } from "../InfiniteEstimation";
type DetailsProps = { onBack?: () => void };
@@ -70,6 +71,7 @@ export const Details: React.FC = ({ onBack }) => {
if (protocolInfo === undefined || simulatedProtocolInfo === undefined || lusdBalance === undefined)
return null;
+ const hasMarketPremium = simulatedProtocolInfo.hasMarketPremium;
const depositMinusClaimBondFee = Decimal.ONE.sub(protocolInfo.claimBondFee).mul(deposit);
const rebondReturn = getReturn(
depositMinusClaimBondFee.mul(simulatedProtocolInfo.rebondAccrualFactor),
@@ -77,7 +79,7 @@ export const Details: React.FC = ({ onBack }) => {
simulatedProtocolInfo.simulatedMarketPrice
);
const rebondRoi = rebondReturn / toFloat(deposit) || 0;
- const marketPriceMin = protocolInfo.floorPrice.add(0.015).prettify(2); // Add 0.015 to prevent market_price=floor_price infinity issues
+ const marketPriceMin = protocolInfo.floorPrice.mul(1.025).prettify(2); // Enough to display what happens below the 3% chicken in fee
const marketPriceMax = Decimal.max(
protocolInfo.marketPrice.mul(1.1),
protocolInfo.floorPrice.mul(1.5)
@@ -102,19 +104,31 @@ export const Details: React.FC = ({ onBack }) => {
protocolInfo.claimBondFee
);
- const breakEvenTime = getRebondOrBreakEvenTimeWithControllerAdjustment(
- Decimal.ZERO,
- simulatedProtocolInfo.controllerTargetAge,
- simulatedProtocolInfo.averageBondAge,
- Decimal.from(breakEvenDays)
- );
+ const breakEvenTime = breakEvenDays.eq(Decimal.INFINITY)
+ ? UNKNOWN_DATE
+ : getRebondOrBreakEvenTimeWithControllerAdjustment(
+ Decimal.ZERO,
+ simulatedProtocolInfo.controllerTargetAge,
+ simulatedProtocolInfo.averageBondAge,
+ breakEvenDays
+ );
- const rebondTime = getRebondOrBreakEvenTimeWithControllerAdjustment(
- Decimal.ZERO,
- simulatedProtocolInfo.controllerTargetAge,
- simulatedProtocolInfo.averageBondAge,
- Decimal.from(rebondDays)
- );
+ const rebondTime = rebondDays.eq(Decimal.INFINITY)
+ ? UNKNOWN_DATE
+ : getRebondOrBreakEvenTimeWithControllerAdjustment(
+ Decimal.ZERO,
+ simulatedProtocolInfo.controllerTargetAge,
+ simulatedProtocolInfo.averageBondAge,
+ rebondDays
+ );
+
+ const breakEvenAccrual = hasMarketPremium
+ ? depositMinusClaimBondFee.mul(simulatedProtocolInfo.breakEvenAccrualFactor)
+ : Decimal.INFINITY;
+
+ const rebondAccrual = hasMarketPremium
+ ? depositMinusClaimBondFee.mul(simulatedProtocolInfo.rebondAccrualFactor)
+ : Decimal.INFINITY;
return (
<>
@@ -169,9 +183,11 @@ export const Details: React.FC = ({ onBack }) => {
label: (
<>
- {`${depositMinusClaimBondFee
- .mul(simulatedProtocolInfo.breakEvenAccrualFactor)
- .prettify(2)} bLUSD`}
+
+
+ {breakEvenAccrual.prettify(2)} bLUSD
+
+
>
)
},
@@ -182,9 +198,11 @@ export const Details: React.FC = ({ onBack }) => {
- {`${depositMinusClaimBondFee
- .mul(simulatedProtocolInfo.rebondAccrualFactor)
- .prettify(2)} bLUSD`}
+
+
+ {rebondAccrual.prettify(2)} bLUSD
+
+
>
)
}
@@ -207,21 +225,25 @@ export const Details: React.FC = ({ onBack }) => {
@@ -235,11 +257,18 @@ export const Details: React.FC = ({ onBack }) => {
max={marketPriceMax}
type="LUSD"
onSliderChange={value => setSimulatedMarketPrice(value)}
- onReset={() => setSimulatedMarketPrice(protocolInfo.marketPrice)}
+ onReset={() => resetSimulatedMarketPrice()}
/>
{statuses.CREATE === "FAILED" && Failed to create bond. Please try again.}
+ {!protocolInfo.hasMarketPremium && (
+
+ When the market price is less than 3% above the floor price, it's not profitable to bond.
+ Buying bLUSD from the market currently generates a higher return than bonding.
+
+ )}
+
{!isDepositEnough && The minimum bond amount is 100 LUSD.}
{doesDepositExceedBalance && (
diff --git a/packages/dev-frontend/src/components/Bonds/views/idle/Bond.tsx b/packages/dev-frontend/src/components/Bonds/views/idle/Bond.tsx
index 794f9d5bd..cb1559a97 100644
--- a/packages/dev-frontend/src/components/Bonds/views/idle/Bond.tsx
+++ b/packages/dev-frontend/src/components/Bonds/views/idle/Bond.tsx
@@ -7,6 +7,7 @@ import { Label, SubLabel } from "../../../HorizontalTimeline";
import * as l from "../../lexicon";
import { statuses, useBondView } from "../../context/BondViewContext";
import { useBondAddresses } from "../../context/BondAddressesContext";
+import { InfiniteEstimate } from "../InfiniteEstimation";
const getBondEvents = (bond: BondType): EventType[] => {
const events = [
@@ -14,9 +15,7 @@ const getBondEvents = (bond: BondType): EventType[] => {
date: new Date(bond.startTime),
label: (
<>
-
+
{`0.00 bLUSD`}
>
)
@@ -55,7 +54,11 @@ const getBondEvents = (bond: BondType): EventType[] => {
label: (
<>
- {`${bond?.breakEvenAccrual?.prettify(2) ?? "?"} bLUSD`}
+
+
+ {bond?.breakEvenAccrual?.prettify(2) ?? "?"} bLUSD
+
+
>
)
});
@@ -65,7 +68,11 @@ const getBondEvents = (bond: BondType): EventType[] => {
label: (
<>
- {`${bond?.rebondAccrual?.prettify(2) ?? "?"} bLUSD`}
+
+
+ {bond?.rebondAccrual?.prettify(2) ?? "?"} bLUSD
+
+
>
)
});