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

added inputs for LP Bonus computations #4

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
115 changes: 88 additions & 27 deletions src/app/calculator/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { useData } from '@/app/context/datacontext';
import { useState } from 'react';
import InfoIcon from '@/icons/info'

export default function Calculator() {
const {
Expand All @@ -21,32 +22,45 @@ export default function Calculator() {
initialBamkPrice = Number(magicEdenBamkData.floorUnitPrice.formatted);
}

const [myNusd, setMyNusd] = useState('2000');
const [totalNusd, setTotalNusd] = useState(initialTotalNusd);
const [bamkPrice, setBamkPrice] = useState(initialBamkPrice);
const [walletNusd, setMyNusd] = useState<number>(2000);
const [poolNusd, setPoolNusd] = useState<number>(0);
const [liquidityPoolPercent, setLiquidityPoolPercent] = useState<number>(0);
const [totalNusd, setTotalNusd] = useState<number>(initialTotalNusd);
const [bamkPrice, setBamkPrice] = useState<number>(initialBamkPrice);

const handleMyNusdChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
// Sanitize leading zeros
const sanitizedValue = value.replace(/^0+(?=\d)/, '');
setMyNusd(sanitizedValue);
const value = e.target.value.replace(/^0+/, '');
setMyNusd(value === '' ? 0 : Number(value));
};

const handlePoolNusdChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value.replace(/^0+/, '');
setPoolNusd(value === '' ? 0 : Number(value));
};

const handleLPPercentChange = (e: React.ChangeEvent<HTMLInputElement>) => {
let value = e.target.value.replace(/^0+/, '');
let numericValue = value === '' ? 0 : Number(value);
if (numericValue > 100) {
numericValue = 100;
}
setLiquidityPoolPercent(numericValue);
};

const handleTotalNusdChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
// Sanitize leading zeros
const sanitizedValue = value.replace(/^0+(?=\d)/, '');
setTotalNusd(Number(sanitizedValue));
const value = e.target.value.replace(/^0+/, '');
setTotalNusd(value === '' ? 0 : Number(value));
};

const handleBamkPriceChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
// Sanitize leading zeros
const sanitizedValue = value.replace(/^0+(?=\d)/, '');
setBamkPrice(Number(sanitizedValue));
const value = e.target.value.replace(/^0+/, '');
setBamkPrice(value === '' ? 0 : Number(value));
};

const bamkPerDay = ((Number(myNusd) || 0) / totalNusd) * (31250 * 144);
const bamkLiquidityBonus = 5000 * 144;
const liquidityPoolBonus = (Number(liquidityPoolPercent) / 100) * bamkLiquidityBonus;

const bamkPerDay = ((Number(walletNusd) + Number(poolNusd) || 0) / Number(totalNusd)) * (31250 * 144) + liquidityPoolBonus;

if (
!magicEdenBamkData ||
Expand All @@ -70,33 +84,80 @@ export default function Calculator() {
<div className="max-w-screen-xl container flex flex-col gap-8 sm:mt-8 mx-3 md:mx-8" style={{ maxWidth: '600px' }}>
<div className="mt-3 p-4 border border-border/40 rounded-md shadow-sm bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<div className="flex flex-col mt-0">
<label htmlFor="myNusd" className="block text-sm font-medium text-zinc-50">My $NUSD</label>
<label htmlFor="myNusd" className="block text-sm font-medium text-zinc-50">
$NUSD in Wallet
<span className="tooltip">
<InfoIcon className="info-icon" width={16} height={16} />
<span className="tooltiptext">Amount freely available to spend/trade, not locked in Liquidity Pool</span>
</span>
</label>
<input
type="text"
id="myNusd"
value={myNusd}
type="number"
id="walletNusd"
value={walletNusd.toString()}
onChange={handleMyNusdChange}
className="mt-4 bg-accent flex text-sm gap-2 px-4 py-3 rounded-md items-center border border-black-300 shadow-sm focus:ring-primary focus:border-primary sm:text-sm text-white placeholder-zinc-400 appearance-none"
placeholder="0"
/>
</div>
<div className="flex flex-col mt-4">
<label htmlFor="totalNusd" className="block text-sm font-medium text-zinc-50">$NUSD TVL</label>
<label htmlFor="poolNusd" className="block text-sm font-medium text-zinc-50">
$NUSD in DotSwap LP
<span className="tooltip">
<InfoIcon className="info-icon" width={16} height={16} />
<span className="tooltiptext">Amount committed to DotSwap $NUSD/BTC Liquidity Pool</span>
</span>
</label>
<input
type="number"
id="poolNusd"
value={poolNusd.toString()}
onChange={handlePoolNusdChange}
className="mt-4 bg-accent flex text-sm gap-2 px-4 py-3 rounded-md border border-black-300 shadow-sm focus:ring-primary focus:border-primary sm:text-sm text-white placeholder-zinc-400 appearance-none"
placeholder="0"
/>
</div>
<div className="flex flex-col mt-4">
<label htmlFor="liquidityPoolPercent" className="block text-sm font-medium text-zinc-50">
Pool %
<span className="tooltip">
<InfoIcon className="info-icon" width={16} height={16} />
<span className="tooltiptext">Your percentage of the pool, number available on DotSwap</span>
</span>
</label>
<input
type="text"
type="number"
id="liquidityPoolPercent"
value={liquidityPoolPercent.toString()}
onChange={handleLPPercentChange}
max="100"
className="mt-4 bg-accent flex text-sm gap-2 px-4 py-3 rounded-md border border-black-300 shadow-sm focus:ring-primary focus:border-primary sm:text-sm text-white placeholder-zinc-400 appearance-none"
placeholder="0"
/>
</div>
<div className="flex flex-col mt-4">
<label htmlFor="totalNusd" className="block text-sm font-medium text-zinc-50">
$NUSD TVL
<span className="tooltip">
<InfoIcon className="info-icon" width={16} height={16} />
<span className="tooltiptext">Total Value Locked in $NUSD protocol.</span>
</span>
</label>
<input
type="number"
id="totalNusd"
value={totalNusd}
value={totalNusd.toString()}
onChange={handleTotalNusdChange}
className="mt-4 bg-accent flex text-sm gap-2 px-4 py-3 rounded-md items-center border border-black-300 shadow-sm focus:ring-primary focus:border-primary sm:text-sm text-white placeholder-zinc-400 appearance-none"
placeholder="0"
placeholder="1"
/>
</div>
<div className="flex flex-col mt-4">
<label htmlFor="bamkPrice" className="block text-sm font-medium text-zinc-50">BAMK Price (sats)</label>
<input
type="text"
type="number"
id="bamkPrice"
value={bamkPrice}
value={bamkPrice.toString()}
onChange={handleBamkPriceChange}
className="mt-4 bg-accent flex text-sm gap-2 px-4 py-3 rounded-md border border-black-300 shadow-sm focus:ring-primary focus:border-primary sm:text-sm text-white placeholder-zinc-400 appearance-none"
placeholder="0"
Expand All @@ -109,7 +170,7 @@ export default function Calculator() {
<div className="relative inline-flex group mt-1 w-full">
<div className="absolute transition-all duration-500 opacity-70 -inset-px rounded-xl blur-sm"></div>
<div className="relative inline-flex items-center w-full px-3 py-4 text-lg font-bold text-primary bg-primary/5 rounded-xl border border-primary">
<p className="font-bold text-primary">{bamkPerDay.toLocaleString(undefined, { maximumFractionDigits: 2 })} BAMK = {((bamkPerDay * bamkPrice)/100000000).toLocaleString(undefined, { maximumFractionDigits: 8 })} BTC = ${(btcPriceData.bitcoin.usd * (Math.floor(bamkPerDay * bamkPrice)) / 100000000).toLocaleString(undefined, { maximumFractionDigits: 2 })}</p>
<p className="font-bold text-primary">{bamkPerDay.toLocaleString(undefined, { maximumFractionDigits: 2 })} BAMK = {((bamkPerDay * Number(bamkPrice))/100000000).toLocaleString(undefined, { maximumFractionDigits: 8 })} BTC = ${(btcPriceData.bitcoin.usd * (Math.floor(bamkPerDay * Number(bamkPrice))) / 100000000).toLocaleString(undefined, { maximumFractionDigits: 2 })}</p>
<p className="font-bold text-primary"> </p>
</div>
</div>
Expand Down
36 changes: 36 additions & 0 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,39 @@
@apply bg-background text-foreground;
}
}

.tooltip {
position: relative;
display: inline-block;
cursor: pointer;
margin-left: 5px;
}

.tooltip .tooltiptext {
visibility: hidden;
width: 200px;
background-color: #292524;
border: black;
border-style: groove;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px;
position: absolute;
z-index: 1;
top: 20%;
left: 0%;
margin-left: 0;
opacity: 0;
transition: opacity 0.3s;
}

.tooltip:hover .tooltiptext,
.tooltip:focus .tooltiptext {
visibility: visible;
opacity: 1;
}

.info-icon {
vertical-align: middle;
}
27 changes: 27 additions & 0 deletions src/icons/info.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React, { FC, ReactElement, MouseEvent } from 'react';

const InfoIcon: FC<{
className?: string;
width?: number;
height?: number;
onClick?: (evt: MouseEvent) => void;
}> = (props): ReactElement => {
return (
<svg
onClick={props.onClick}
viewBox="0 0 24 24"
fill="none"
className={props.className}
width={props.width}
height={props.height}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm-1-13h2v2h-2V7zm0 4h2v7h-2v-7z"
fill="#444444"
/>
</svg>
);
};

export default InfoIcon;