diff --git a/components/trade-form/index.tsx b/components/trade-form/index.tsx index 751c12e81..b35a3776c 100644 --- a/components/trade-form/index.tsx +++ b/components/trade-form/index.tsx @@ -122,8 +122,6 @@ const Inner = ({ marketId: getMarketIdOf(tradeItem.assetId), }); - const { data: constants } = useChainConstants(); - const { poolBaseBalance, baseWeight, @@ -257,18 +255,25 @@ const Inner = ({ const changeByPercentage = useCallback( (percentage: Decimal) => { - if (tradeItemState == null) { + const [balanceIn, weightIn, balanceOut, weightOut] = [ + poolBaseBalance, + baseWeight, + poolAssetBalance, + assetWeight, + ]; + + if ( + tradeItemState == null || + balanceIn == null || + weightIn == null || + balanceOut == null || + weightOut == null + ) { return; } - if (tradeItem.action === "buy") { - const amountOut = maxAssetAmountDecimal.mul(percentage); - const [balanceIn, weightIn, balanceOut, weightOut] = [ - poolBaseBalance, - baseWeight, - poolAssetBalance, - assetWeight, - ]; + if (tradeItem.action === "buy" && balanceIn) { + const amountOut = maxAssetAmountDecimal.mul(percentage); const amountIn = calcInGivenOut( balanceIn, @@ -277,6 +282,7 @@ const Inner = ({ weightOut, amountOut.mul(ZTG), tradeItemState.swapFee, + market?.creatorFee ?? 0, ); setValue( @@ -287,13 +293,6 @@ const Inner = ({ } else if (tradeItem.action === "sell") { const amountOut = maxBaseAmountDecimal.mul(percentage); - const [balanceIn, weightIn, balanceOut, weightOut] = [ - poolBaseBalance, - baseWeight, - poolAssetBalance, - assetWeight, - ]; - const amountIn = calcInGivenOut( balanceOut, weightOut, @@ -301,6 +300,7 @@ const Inner = ({ weightIn, amountOut.mul(ZTG), tradeItemState.swapFee, + market?.creatorFee ?? 0, ); setValue("baseAmount", amountOut.toFixed(4, Decimal.ROUND_DOWN)); @@ -320,7 +320,20 @@ const Inner = ({ const changeByAssetAmount = useCallback( (assetAmount: Decimal) => { - if (tradeItemState == null) { + const [balanceIn, weightIn, balanceOut, weightOut] = [ + poolBaseBalance, + baseWeight, + poolAssetBalance, + assetWeight, + ]; + if ( + tradeItemState == null || + balanceIn == null || + weightIn == null || + balanceOut == null || + weightOut == null || + swapFee == null + ) { return; } @@ -329,12 +342,6 @@ const Inner = ({ : new Decimal(0); if (tradeItem.action === "buy") { - const [balanceIn, weightIn, balanceOut, weightOut] = [ - poolBaseBalance, - baseWeight, - poolAssetBalance, - assetWeight, - ]; const amountIn = calcInGivenOut( balanceIn, weightIn, @@ -342,6 +349,7 @@ const Inner = ({ weightOut, assetAmount.mul(ZTG), swapFee, + market?.creatorFee ?? 0, ); setValue( @@ -350,13 +358,6 @@ const Inner = ({ ); setPercentageDisplay(percentage.toString()); } else if (tradeItem.action === "sell") { - const [balanceIn, weightIn, balanceOut, weightOut] = [ - poolAssetBalance, - assetWeight, - poolBaseBalance, - baseWeight, - ]; - const amountOut = calcOutGivenIn( balanceIn, weightIn, @@ -364,6 +365,7 @@ const Inner = ({ weightOut, assetAmount.mul(ZTG), swapFee, + market?.creatorFee ?? 0, ); setValue( "baseAmount", @@ -412,6 +414,7 @@ const Inner = ({ weightOut, baseAmount.mul(ZTG), swapFee, + market?.creatorFee ?? 0, ); setValue( "assetAmount", @@ -433,6 +436,7 @@ const Inner = ({ weightOut, baseAmount.mul(ZTG), swapFee, + market?.creatorFee ?? 0, ); setValue( diff --git a/lib/hooks/queries/useTradeItemState.ts b/lib/hooks/queries/useTradeItemState.ts index 0d4045d85..a9cb08b2e 100644 --- a/lib/hooks/queries/useTradeItemState.ts +++ b/lib/hooks/queries/useTradeItemState.ts @@ -23,7 +23,6 @@ export const tradeItemStateRootQueryKey = "trade-item-state"; export const useTradeItemState = (item: TradeItem) => { const [sdk, id] = useSdkv2(); const wallet = useWallet(); - const signer = wallet.activeAccount ? wallet.activeAccount : null; const slippage = 1; const marketId = getMarketIdOf(item.assetId); diff --git a/lib/hooks/trade.tsx b/lib/hooks/trade.tsx index 923069496..2c4a552d5 100644 --- a/lib/hooks/trade.tsx +++ b/lib/hooks/trade.tsx @@ -36,7 +36,6 @@ export const useTradeItem = () => { export const useTradeMaxBaseAmount = (item: TradeItem): Decimal => { const { data: itemState } = useTradeItemState(item); - if (!itemState) { return new Decimal(0); } @@ -50,6 +49,7 @@ export const useTradeMaxBaseAmount = (item: TradeItem): Decimal => { swapFee, traderAssetBalance, traderBaseBalance, + market, } = itemState; let maxAmountBase: Decimal = new Decimal(0); @@ -66,6 +66,7 @@ export const useTradeMaxBaseAmount = (item: TradeItem): Decimal => { assetWeight, tradeablePoolAssetBalance, swapFee, + market.creatorFee ?? 0, ); return maxAmountBase.gt(traderBaseBalance) ? traderBaseBalance @@ -83,6 +84,7 @@ export const useTradeMaxBaseAmount = (item: TradeItem): Decimal => { baseWeight, maxAssetIn, swapFee, + market.creatorFee ?? 0, ); return maxAmountBase; } @@ -107,6 +109,7 @@ export const useTradeMaxAssetAmount = (item: TradeItem): Decimal => { tradeablePoolAssetBalance, swapFee, traderBaseBalance, + market, } = itemState; let maxAmountAsset: Decimal = new Decimal(0); @@ -119,6 +122,7 @@ export const useTradeMaxAssetAmount = (item: TradeItem): Decimal => { assetWeight, maxBaseAmount, swapFee, + market.creatorFee ?? 0, ); } if (item.action === "sell") { @@ -129,6 +133,7 @@ export const useTradeMaxAssetAmount = (item: TradeItem): Decimal => { baseWeight, maxBaseAmount, swapFee, + market.creatorFee ?? 0, ); } @@ -166,6 +171,7 @@ export const useTradeTransaction = ( slippage, baseAssetId, assetId, + market, } = itemState; let transaction: @@ -186,6 +192,7 @@ export const useTradeTransaction = ( assetWeight, amountDecimal, swapFee, + market.creatorFee ?? 0, ).mul(new Decimal(1 - slippage / 100)); if (!minAmountOut.isNaN() && minAmountOut.greaterThanOrEqualTo(0)) { @@ -206,6 +213,7 @@ export const useTradeTransaction = ( assetWeight, amountDecimal, swapFee, + market.creatorFee ?? 0, ).mul(new Decimal(slippage / 100 + 1)); if (!maxAmountIn.isNaN() && maxAmountIn.greaterThanOrEqualTo(0)) { @@ -234,6 +242,7 @@ export const useTradeTransaction = ( baseWeight, amountDecimal, swapFee, + market.creatorFee ?? 0, ).mul(new Decimal(slippage / 100 + 1)); if (!maxAmountIn.isNaN() && maxAmountIn.greaterThanOrEqualTo(0)) { @@ -254,6 +263,7 @@ export const useTradeTransaction = ( baseWeight, amountDecimal, swapFee, + market.creatorFee ?? 0, ).mul(new Decimal(1 - slippage / 100)); if (!minAmountOut.isNaN() && minAmountOut.greaterThanOrEqualTo(0)) { diff --git a/lib/math.spec.ts b/lib/math.spec.ts index 0582a4aee..a73bdce7c 100644 --- a/lib/math.spec.ts +++ b/lib/math.spec.ts @@ -16,30 +16,50 @@ describe("math", () => { }); describe("calcOutGivenIn", () => { - test("should calculate correctly", () => { - const out = calcOutGivenIn(50, 50, 50, 50, 25, 0); + describe("without creator fees", () => { + test("should calculate correctly", () => { + const out = calcOutGivenIn(50, 50, 50, 50, 25, 0, 0); - expect(out.toFixed(1)).toEqual("16.7"); + expect(out.toFixed(1)).toEqual("16.7"); + }); + + test("should calculate correctly with fees", () => { + const out = calcOutGivenIn(50, 50, 50, 50, 25, 0.1, 0); + + expect(out.toFixed(1)).toEqual("15.5"); + }); }); - test("should calculate correctly with fees", () => { - const out = calcOutGivenIn(50, 50, 50, 50, 25, 0.1); + describe("with creator fees", () => { + test("should calculate correctly", () => { + const out = calcOutGivenIn(50, 50, 50, 50, 25, 0.01, 0.01); - expect(out.toFixed(1)).toEqual("15.5"); + expect(out.toFixed(1)).toEqual("16.4"); + }); }); }); describe("calcInGivenOut", () => { - test("should calculate correctly", () => { - const amountIn = calcInGivenOut(50, 50, 50, 50, 10, 0); + describe("without creator fees", () => { + test("should calculate correctly", () => { + const amountIn = calcInGivenOut(50, 50, 50, 50, 10, 0, 0); + + expect(amountIn.toFixed(1)).toEqual("12.5"); + }); + + test("should calculate correctly with fees", () => { + const amountIn = calcInGivenOut(50, 50, 50, 50, 10, 0.05, 0); - expect(amountIn.toFixed(1)).toEqual("12.5"); + expect(amountIn.toFixed(1)).toEqual("13.2"); + }); }); - test("should calculate correctly with fees", () => { - const amountIn = calcInGivenOut(50, 50, 50, 50, 10, 0.05); + describe("with creator fees", () => { + test("should calculate correctly", () => { + const amountIn = calcInGivenOut(50, 50, 50, 50, 10, 0.01, 0.01); - expect(amountIn.toFixed(1)).toEqual("13.2"); + expect(amountIn.toFixed(1)).toEqual("12.8"); + }); }); }); }); diff --git a/lib/math.ts b/lib/math.ts index 73c1169e6..b81865699 100644 --- a/lib/math.ts +++ b/lib/math.ts @@ -16,18 +16,20 @@ export const calcSpotPrice = ( }; export const calcOutGivenIn = ( - tokenBalanceIn, // amount of 'in' asset in the pool - tokenWeightIn, // weight of 'in' asset on the pool - tokenBalanceOut, // amount of 'out' asset in the pool - tokenWeightOut, // weight of 'out' asset on the pool - tokenAmountIn, // amount in for the swap - swapFee, + tokenBalanceIn: Decimal | string | number, // amount of 'in' asset in the pool + tokenWeightIn: Decimal | string | number, // weight of 'in' asset on the pool + tokenBalanceOut: Decimal | string | number, // amount of 'out' asset in the pool + tokenWeightOut: Decimal | string | number, // weight of 'out' asset on the pool + tokenAmountIn: Decimal | string | number, // amount in for the swap + swapFee: Decimal | string | number, // 0.01 is 1% + creatorFee: Decimal | string | number, // 0.01 is 1% ) => { + const totalFee = new Decimal(swapFee).plus(creatorFee); const weightRatio = new Decimal(tokenWeightIn).div( new Decimal(tokenWeightOut), ); const adjustedIn = new Decimal(tokenAmountIn).times( - new Decimal(1).minus(new Decimal(swapFee)), + new Decimal(1).minus(new Decimal(totalFee)), ); const y = new Decimal(tokenBalanceIn).div( new Decimal(tokenBalanceIn).plus(adjustedIn), @@ -39,13 +41,15 @@ export const calcOutGivenIn = ( }; export const calcInGivenOut = ( - tokenBalanceIn, - tokenWeightIn, - tokenBalanceOut, - tokenWeightOut, - tokenAmountOut, - swapFee, + tokenBalanceIn: Decimal | string | number, + tokenWeightIn: Decimal | string | number, + tokenBalanceOut: Decimal | string | number, + tokenWeightOut: Decimal | string | number, + tokenAmountOut: Decimal | string | number, + swapFee: Decimal | string | number, // 0.01 is 1% + creatorFee: Decimal | string | number, // 0.01 is 1% ) => { + const totalFee = new Decimal(swapFee).plus(creatorFee); const weightRatio = new Decimal(tokenWeightOut).div( new Decimal(tokenWeightIn), ); @@ -54,6 +58,6 @@ export const calcInGivenOut = ( const foo = y.pow(weightRatio).minus(new Decimal(1)); const tokenAmountIn = new Decimal(tokenBalanceIn) .times(foo) - .div(new Decimal(1).minus(new Decimal(swapFee))); + .div(new Decimal(1).minus(new Decimal(totalFee))); return tokenAmountIn; };