diff --git a/components/marketplace/buy-fractional-order-form.tsx b/components/marketplace/buy-fractional-order-form.tsx index 75b9da72..f6f84384 100644 --- a/components/marketplace/buy-fractional-order-form.tsx +++ b/components/marketplace/buy-fractional-order-form.tsx @@ -19,12 +19,15 @@ import { getCurrencyByAddress, getPricePerPercent, getPricePerUnit, - getTotalPriceFromPercentage, } from "@/marketplace/utils"; import z from "zod"; import { zodResolver } from "@hookform/resolvers/zod"; import { parseUnits } from "viem"; import { calculateBigIntPercentage } from "@/lib/calculateBigIntPercentage"; +import { + DEFAULT_NUM_FRACTIONS, + DEFAULT_NUM_FRACTIONS_DECIMALS, +} from "@/configs/hypercerts"; const formSchema = z .object({ @@ -83,13 +86,17 @@ export const BuyFractionalOrderForm = ({ const getUnitsToBuy = (percentageAmount: string) => { try { const hypercertUnits = BigInt(hypercert.units || 0); - const percentageAsBigInt = BigInt(Number(percentageAmount) * 100); + const percentageAsBigInt = parseUnits( + percentageAmount, + DEFAULT_NUM_FRACTIONS_DECIMALS, + ); const unitsToBuy = - (hypercertUnits * percentageAsBigInt) / BigInt(100 * 100); - return unitsToBuy.toString(); + (hypercertUnits * percentageAsBigInt) / + (BigInt(100) * DEFAULT_NUM_FRACTIONS); + return unitsToBuy < BigInt(0) ? BigInt(0) : unitsToBuy; } catch (e) { console.error(e); - return "0"; + return BigInt(0); } }; @@ -153,12 +160,15 @@ export const BuyFractionalOrderForm = ({ const percentageAmount = form.watch("percentageAmount"); const pricePerPercent = form.watch("pricePerPercent"); + const unitsToBuy = getUnitsToBuy(percentageAmount); + const pricePerUnit = getPricePerUnit( + pricePerPercent, + BigInt(hypercert.units || 0), + ); + const totalPrice = formatPrice( order.chainId, - getTotalPriceFromPercentage( - BigInt(pricePerPercent), - Number(percentageAmount), - ), + unitsToBuy * pricePerUnit, currency.address, true, ); @@ -169,10 +179,7 @@ export const BuyFractionalOrderForm = ({ currency.address, ); - const unitsToBuy = - BigInt(getUnitsToBuy(percentageAmount)) > BigInt(0) - ? getUnitsToBuy(percentageAmount) - : "0"; + const disabled = !form.formState.isValid || unitsToBuy === BigInt(0); return (
@@ -189,7 +196,7 @@ export const BuyFractionalOrderForm = ({
You will buy{" "} - {unitsToBuy} + {unitsToBuy.toString()} {" "} units , for a total of {totalPrice}. (min:{" "} {minPercentageAmount}%, max: {maxPercentageAmount}%) @@ -238,6 +245,7 @@ export const BuyFractionalOrderForm = ({ variant={"outline"} type="button" onClick={form.handleSubmit(onSubmit)} + disabled={disabled} > Execute order diff --git a/configs/hypercerts.ts b/configs/hypercerts.ts index 9f2eb0db..a95edecf 100644 --- a/configs/hypercerts.ts +++ b/configs/hypercerts.ts @@ -8,6 +8,10 @@ const HYPERCERT_API_URL = export const HYPERCERTS_API_URL_REST = `${HYPERCERT_API_URL}/v1`; export const HYPERCERTS_API_URL_GRAPH = `${HYPERCERT_API_URL}/v1/graphql`; -export const DEFAULT_NUM_FRACTIONS = parseUnits("1", 8); +export const DEFAULT_NUM_FRACTIONS_DECIMALS = 8; +export const DEFAULT_NUM_FRACTIONS = parseUnits( + "1", + DEFAULT_NUM_FRACTIONS_DECIMALS, +); export const DEFAULT_DISPLAY_CURRENCY = "usd"; diff --git a/marketplace/hooks.tsx b/marketplace/hooks.tsx index 0c1a207d..0219bbb8 100644 --- a/marketplace/hooks.tsx +++ b/marketplace/hooks.tsx @@ -414,7 +414,7 @@ export const useBuyFractionalMakerAsk = () => { totalUnitsInHypercert, }: { order: MarketplaceOrder; - unitAmount: string; + unitAmount: bigint; pricePerUnit: string; hypercertName?: string | null; totalUnitsInHypercert?: bigint; @@ -473,7 +473,7 @@ export const useBuyFractionalMakerAsk = () => { takerOrder = hypercertExchangeClient.createFractionalSaleTakerBid( order, address, - unitAmount, + unitAmount.toString(), pricePerUnit, ); } catch (e) { @@ -492,7 +492,7 @@ export const useBuyFractionalMakerAsk = () => { ); } - const totalPrice = BigInt(order.price) * BigInt(unitAmount); + const totalPrice = BigInt(order.price) * unitAmount; try { await setStep("ERC20"); if (currency.address !== zeroAddress) { @@ -566,11 +566,7 @@ export const useBuyFractionalMakerAsk = () => { Congratulations, you successfully bought{" "} - {calculateBigIntPercentage( - BigInt(unitAmount), - totalUnitsInHypercert, - )} - % + {calculateBigIntPercentage(unitAmount, totalUnitsInHypercert)}% {" "} of {hypercertName}. diff --git a/marketplace/utils.ts b/marketplace/utils.ts index be0f7d69..dd65d08f 100644 --- a/marketplace/utils.ts +++ b/marketplace/utils.ts @@ -144,19 +144,3 @@ export const isTokenDividableBy = ( (parseUnits(denominator || "1", currency.decimals) || BigInt(1)); return remainder === BigInt(0); }; - -export const getTotalPriceFromPercentage = ( - pricePerPercent: bigint, - percentageAmount: number, -) => { - if (percentageAmount < 0 || percentageAmount > 100) { - throw new Error("Percentage amount must be between 0 and 100"); - } - - const precision = 10 ** 16; - - return ( - (pricePerPercent * BigInt(Math.round(percentageAmount * precision))) / - BigInt(precision) - ); -}; diff --git a/test/marketplace/utils.test.ts b/test/marketplace/utils.test.ts index 545df969..280ba11b 100644 --- a/test/marketplace/utils.test.ts +++ b/test/marketplace/utils.test.ts @@ -1,10 +1,6 @@ import { describe, it, expect } from "vitest"; -import { - getPricePerPercent, - getPricePerUnit, - getTotalPriceFromPercentage, -} from "@/marketplace/utils"; +import { getPricePerPercent, getPricePerUnit } from "@/marketplace/utils"; import { currenciesByNetwork } from "@hypercerts-org/marketplace-sdk"; import { sepolia } from "viem/chains"; @@ -42,23 +38,4 @@ describe("utils", () => { // expect(getMinimumPrice("1", chainId, usdc.address)).to.eq(1n); }); }); - - describe("getTotalPriceFromPercentage", () => { - it("should return the total price from percentage", () => { - expect(getTotalPriceFromPercentage(BigInt(1), 100)).to.eq(BigInt(100)); - expect(() => getTotalPriceFromPercentage(BigInt(1), 200)).toThrowError(); - - expect(getTotalPriceFromPercentage(BigInt(1), 10)).to.eq(BigInt(10)); - expect(getTotalPriceFromPercentage(BigInt(100), 0.1)).to.eq(BigInt(10)); - expect(getTotalPriceFromPercentage(BigInt(10 ** 6), 0.00001)).to.eq( - BigInt(10), - ); - expect( - getTotalPriceFromPercentage(BigInt(10 ** 12), 0.00000000001), - ).to.eq(BigInt(10)); - expect( - getTotalPriceFromPercentage(BigInt(10 ** 16), 0.000000000000001), - ).to.eq(BigInt(10)); - }); - }); });