Skip to content

Commit

Permalink
prepare for borrow rewards
Browse files Browse the repository at this point in the history
  • Loading branch information
0xshiba1 committed Jul 15, 2024
1 parent aa7bdae commit a2e765d
Show file tree
Hide file tree
Showing 9 changed files with 142 additions and 92 deletions.
22 changes: 12 additions & 10 deletions frontend/src/components/dashboard/AprWithRewardsBreakdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ const formatAprPercent = (
showChange: boolean,
) =>
showChange && !newValue.eq(value)
? `${formatPercent(value)}${isAprModifierInvalid ? "N/A" : formatPercent(newValue)}`
: formatPercent(value);
? `${formatPercent(value, { useAccountingSign: true })}${isAprModifierInvalid ? "N/A" : formatPercent(newValue, { useAccountingSign: true })}`
: formatPercent(value, { useAccountingSign: true });

interface AprWithRewardsBreakdownProps {
side: Side;
Expand Down Expand Up @@ -159,13 +159,11 @@ export default function AprWithRewardsBreakdown({
}));

// Total APR
const totalAprPercent = getTotalAprPercent(aprPercent, filteredRewards);
const newTotalAprPercent = newAprRewards.reduce(
(acc, reward) =>
side === Side.DEPOSIT
? acc.plus(reward.stats.aprPercent)
: acc.minus(reward.stats.aprPercent),
const totalAprPercent = getTotalAprPercent(side, aprPercent, filteredRewards);
const newTotalAprPercent = getTotalAprPercent(
side,
newAprPercent,
newAprRewards,
);

if (filteredRewards.length === 0)
Expand Down Expand Up @@ -263,8 +261,12 @@ export default function AprWithRewardsBreakdown({
key={index}
isLast={index === aprRewards.length - 1}
value={formatAprPercent(
reward.stats.aprPercent,
newAprRewards[index].stats.aprPercent,
reward.stats.aprPercent.times(
side === Side.DEPOSIT ? 1 : -1,
),
newAprRewards[index].stats.aprPercent.times(
side === Side.DEPOSIT ? 1 : -1,
),
isAprModifierInvalid,
showChange,
)}
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/components/dashboard/MarketTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,13 @@ export default function MarketTable() {
const borrowedAmountUsd = reserve.borrowedAmountUsd;
const depositAprPercent = reserve.depositAprPercent;
const totalDepositAprPercent = getTotalAprPercent(
Side.DEPOSIT,
reserve.depositAprPercent,
getFilteredRewards(data.rewardMap[coinType].deposit),
);
const borrowAprPercent = reserve.borrowAprPercent;
const totalBorrowAprPercent = getTotalAprPercent(
Side.BORROW,
reserve.borrowAprPercent,
getFilteredRewards(data.rewardMap[coinType].borrow),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import BigNumber from "bignumber.js";
import { AlertTriangle, FileClock, TrendingUp } from "lucide-react";

import { ParsedObligation } from "@suilend/sdk/parsers/obligation";
import { Side } from "@suilend/sdk/types";

import AccountBreakdown from "@/components/dashboard/account/AccountBreakdown";
import BorrowLimitTitle from "@/components/dashboard/account/BorrowLimitTitle";
Expand Down Expand Up @@ -46,6 +47,7 @@ function AccountPositionCardContent() {
// APR
const aprWeightedDepositsUsd = obligation.deposits.reduce((acc, deposit) => {
const totalAprPercent = getTotalAprPercent(
Side.DEPOSIT,
deposit.reserve.depositAprPercent,
getFilteredRewards(data.rewardMap[deposit.reserve.coinType].deposit),
);
Expand All @@ -55,6 +57,7 @@ function AccountPositionCardContent() {

const aprWeightedBorrowsUsd = obligation.borrows.reduce((acc, borrow) => {
const totalAprPercent = getTotalAprPercent(
Side.BORROW,
borrow.reserve.borrowAprPercent,
getFilteredRewards(data.rewardMap[borrow.reserve.coinType].borrow),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import {
DAY_S,
Days,
RESERVE_EVENT_SAMPLE_INTERVAL_S_MAP,
calculateRewardDepositAprPercent,
calculateRewardAprPercent,
} from "@/lib/events";
import { formatPercent } from "@/lib/format";
import {
Expand Down Expand Up @@ -68,6 +68,19 @@ function TooltipContent({ side, fields, d, viewBox, x }: TooltipContentProps) {

if (fields.every((field) => d[field] === undefined)) return null;
if (viewBox === undefined || x === undefined) return null;

const interestField = `${side}InterestAprPercent`;
const rewardFields = fields.filter((field) => field !== interestField);

const aprPercent = new BigNumber(d[interestField] as number);
const totalAprPercent = rewardFields.reduce(
(acc, field) =>
acc.plus(
new BigNumber(d[field] as number).times(side === Side.DEPOSIT ? 1 : -1),
),
new BigNumber(aprPercent),
);

return (
// Subset of TooltipContent className
<div
Expand All @@ -82,14 +95,7 @@ function TooltipContent({ side, fields, d, viewBox, x }: TooltipContentProps) {
<div className="flex w-full flex-row items-center justify-between gap-4">
<TBodySans>{capitalize(side)} APR</TBodySans>
<TBody>
{formatPercent(
new BigNumber(
fields.reduce(
(acc: number, field) => acc + (d[field] as number),
0,
),
),
)}
{formatPercent(totalAprPercent, { useAccountingSign: true })}
</TBody>
</div>

Expand All @@ -103,7 +109,14 @@ function TooltipContent({ side, fields, d, viewBox, x }: TooltipContentProps) {
isLast={index === fields.length - 1}
value={
<span style={{ color }}>
{formatPercent(new BigNumber(d[field] as number))}
{formatPercent(
!coinType
? aprPercent
: new BigNumber(d[field] as number).times(
side === Side.DEPOSIT ? 1 : -1,
),
{ useAccountingSign: true },
)}
</span>
}
>
Expand Down Expand Up @@ -401,8 +414,9 @@ export default function HistoricalAprLineChart({
const d = aprRewardReserves.reduce(
(acc, rewardReserve) => ({
...acc,
[`depositInterestAprPercent_${rewardReserve.coinType}`]: event
? calculateRewardDepositAprPercent(
[`${side}InterestAprPercent_${rewardReserve.coinType}`]: event
? calculateRewardAprPercent(
side,
event,
reserveAssetDataEventsMap?.[rewardReserve.id]?.[
days
Expand All @@ -423,7 +437,7 @@ export default function HistoricalAprLineChart({
});

return result as ChartData[];
}, [reserveAssetDataEventsMap, reserve, days, aprRewardReserves]);
}, [reserveAssetDataEventsMap, reserve, days, aprRewardReserves, side]);
const isLoading = chartData === undefined;

return (
Expand Down
144 changes: 79 additions & 65 deletions frontend/src/lib/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import BigNumber from "bignumber.js";

import { ParsedDownsampledApiReserveAssetDataEvent } from "@suilend/sdk/parsers/apiReserveAssetDataEvent";
import { ParsedReserve } from "@suilend/sdk/parsers/reserve";
import { Side } from "@suilend/sdk/types";

import {
NORMALIZED_SUI_COINTYPE,
Expand Down Expand Up @@ -72,7 +73,8 @@ type ReducedPoolReward = {
endTimeMs: number;
};

export const calculateRewardDepositAprPercent = (
export const calculateRewardAprPercent = (
side: Side,
event: ParsedDownsampledApiReserveAssetDataEvent,
rewardEvents: ParsedDownsampledApiReserveAssetDataEvent[],
reserve: ParsedReserve,
Expand All @@ -86,73 +88,81 @@ export const calculateRewardDepositAprPercent = (

const rewardCoinType = rewardEvent.coinType;

const historicalRewardsMap: Record<string, ReducedPoolReward[]> = {
[NORMALIZED_SUI_COINTYPE]: [
{
coinType: NORMALIZED_SUI_COINTYPE,
totalRewards: new BigNumber(93613.13),
startTimeMs: 1713225600000,
endTimeMs: 1713830400000,
},
{
coinType: NORMALIZED_SUI_COINTYPE,
totalRewards: new BigNumber(177579),
startTimeMs: 1713830400000, // 2024-04-23 08:00:00
endTimeMs: 1715040000000, // 2024-05-07 08:00:00
},
{
coinType: NORMALIZED_SUI_COINTYPE,
totalRewards: new BigNumber(162386.57),
startTimeMs: 1715040000000, // 2024-05-07 08:00:00
endTimeMs: 1716249600000, //2024-05-21 08:00:00
},
],
[NORMALIZED_USDC_COINTYPE]: [
{
coinType: NORMALIZED_SUI_COINTYPE,
totalRewards: new BigNumber(75915.32),
startTimeMs: 1713225600000,
endTimeMs: 1713830400000,
},
{
coinType: NORMALIZED_SUI_COINTYPE,
totalRewards: new BigNumber(168534),
startTimeMs: 1713830400000, // 2024-04-23 08:00:00
endTimeMs: 1715040000000, // 2024-05-07 08:00:00
},
{
coinType: NORMALIZED_SUI_COINTYPE,
totalRewards: new BigNumber(176679.79),
startTimeMs: 1715040000000, // 2024-05-07 08:00:00
endTimeMs: 1716249600000, //2024-05-21 08:00:00
},
],
[NORMALIZED_USDT_COINTYPE]: [
{
coinType: NORMALIZED_SUI_COINTYPE,
totalRewards: new BigNumber(64602.32),
startTimeMs: 1713225600000,
endTimeMs: 1713830400000,
},
{
coinType: NORMALIZED_SUI_COINTYPE,
totalRewards: new BigNumber(128939),
startTimeMs: 1713830400000, // 2024-04-23 08:00:00
endTimeMs: 1715040000000, // 2024-05-07 08:00:00
},
{
coinType: NORMALIZED_SUI_COINTYPE,
totalRewards: new BigNumber(116534.73),
startTimeMs: 1715040000000, // 2024-05-07 08:00:00
endTimeMs: 1716249600000, //2024-05-21 08:00:00
},
],
const historicalRewardsMap: Record<
Side,
Record<string, ReducedPoolReward[]>
> = {
[Side.DEPOSIT]: {
[NORMALIZED_SUI_COINTYPE]: [
{
coinType: NORMALIZED_SUI_COINTYPE,
totalRewards: new BigNumber(93613.13),
startTimeMs: 1713225600000,
endTimeMs: 1713830400000,
},
{
coinType: NORMALIZED_SUI_COINTYPE,
totalRewards: new BigNumber(177579),
startTimeMs: 1713830400000, // 2024-04-23 08:00:00
endTimeMs: 1715040000000, // 2024-05-07 08:00:00
},
{
coinType: NORMALIZED_SUI_COINTYPE,
totalRewards: new BigNumber(162386.57),
startTimeMs: 1715040000000, // 2024-05-07 08:00:00
endTimeMs: 1716249600000, //2024-05-21 08:00:00
},
],
[NORMALIZED_USDC_COINTYPE]: [
{
coinType: NORMALIZED_SUI_COINTYPE,
totalRewards: new BigNumber(75915.32),
startTimeMs: 1713225600000,
endTimeMs: 1713830400000,
},
{
coinType: NORMALIZED_SUI_COINTYPE,
totalRewards: new BigNumber(168534),
startTimeMs: 1713830400000, // 2024-04-23 08:00:00
endTimeMs: 1715040000000, // 2024-05-07 08:00:00
},
{
coinType: NORMALIZED_SUI_COINTYPE,
totalRewards: new BigNumber(176679.79),
startTimeMs: 1715040000000, // 2024-05-07 08:00:00
endTimeMs: 1716249600000, //2024-05-21 08:00:00
},
],
[NORMALIZED_USDT_COINTYPE]: [
{
coinType: NORMALIZED_SUI_COINTYPE,
totalRewards: new BigNumber(64602.32),
startTimeMs: 1713225600000,
endTimeMs: 1713830400000,
},
{
coinType: NORMALIZED_SUI_COINTYPE,
totalRewards: new BigNumber(128939),
startTimeMs: 1713830400000, // 2024-04-23 08:00:00
endTimeMs: 1715040000000, // 2024-05-07 08:00:00
},
{
coinType: NORMALIZED_SUI_COINTYPE,
totalRewards: new BigNumber(116534.73),
startTimeMs: 1715040000000, // 2024-05-07 08:00:00
endTimeMs: 1716249600000, //2024-05-21 08:00:00
},
],
},
[Side.BORROW]: {},
};

const allPoolRewards: ReducedPoolReward[] = [
...reserve.depositsPoolRewardManager.poolRewards,
...(side === Side.DEPOSIT
? reserve.depositsPoolRewardManager.poolRewards
: reserve.borrowsPoolRewardManager.poolRewards),
];
(historicalRewardsMap[event.coinType] ?? []).forEach((hr) => {
(historicalRewardsMap[side][event.coinType] ?? []).forEach((hr) => {
if (
allPoolRewards.find(
(pr) =>
Expand Down Expand Up @@ -185,7 +195,11 @@ export const calculateRewardDepositAprPercent = (
pr.totalRewards
.times(rewardEvent.price)
.times(new BigNumber(msPerYear).div(pr.endTimeMs - pr.startTimeMs))
.div(event.depositedAmountUsd)
.div(
side === Side.DEPOSIT
? event.depositedAmountUsd
: event.borrowedAmountUsd,
)
.times(100),
),
new BigNumber(0),
Expand Down
14 changes: 11 additions & 3 deletions frontend/src/lib/format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,14 +154,22 @@ export const formatPoints = (value: BigNumber, options?: { dp?: number }) => {
});
};

export const formatPercent = (value: BigNumber, options?: { dp?: number }) => {
export const formatPercent = (
value: BigNumber,
options?: { dp?: number; useAccountingSign?: boolean },
) => {
const dp = options?.dp ?? 2;
const useAccountingSign = options?.useAccountingSign ?? false;

return Intl.NumberFormat(undefined, {
const formattedValue = Intl.NumberFormat(undefined, {
style: "percent",
minimumFractionDigits: dp,
maximumFractionDigits: dp,
}).format(value.div(100).toNumber());
}).format(value.abs().div(100).toNumber());

return !useAccountingSign || value.gte(0)
? formattedValue
: `(${formattedValue})`;
};

export const formatDuration = (seconds: BigNumber) => {
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/lib/liquidityMining.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,10 +222,12 @@ export const getDedupedPerDayRewards = (
};

export const getTotalAprPercent = (
side: Side,
aprPercent: BigNumber,
filteredRewards: RewardSummary[],
) =>
getDedupedAprRewards(filteredRewards).reduce(
(acc, reward) => acc.plus(reward.stats.aprPercent),
(acc, reward) =>
acc.plus(reward.stats.aprPercent.times(side === Side.DEPOSIT ? 1 : -1)),
aprPercent,
);
3 changes: 3 additions & 0 deletions frontend/src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import NextLink from "next/link";

import { Droplet, Server } from "lucide-react";

import { Side } from "@suilend/sdk/types";

import DiscordIcon from "@/components/assets/DiscordIcon";
import XIcon from "@/components/assets/XIcon";
import HeaderBase from "@/components/layout/HeaderBase";
Expand Down Expand Up @@ -162,6 +164,7 @@ export default function Home() {
)
.map((reserve) => {
const totalDepositAprPercent = getTotalAprPercent(
Side.DEPOSIT,
reserve.depositAprPercent,
getFilteredRewards(
data.rewardMap[reserve.coinType].deposit,
Expand Down
Loading

0 comments on commit a2e765d

Please sign in to comment.