From 23f3c776f5f41080a92997d3abc7bc2f3700f0ed Mon Sep 17 00:00:00 2001 From: jinoosss Date: Mon, 13 Nov 2023 04:04:39 +0900 Subject: [PATCH] [GSW-463] feat: Calculate the Price Range of Liquidity --- .../LiquidityEnterAmounts.tsx | 9 +- .../PoolSelectionGraph.stories.tsx | 1846 +---------------- .../PoolSelectionGraph.tsx | 279 +-- .../common/select-fee-tier/SelectFeeTier.tsx | 6 +- .../SelectPriceRangeCustom.styles.ts | 36 + .../SelectPriceRangeCustom.tsx | 312 ++- .../SelectPriceRangeCutomController.tsx | 10 +- .../select-price-range/SelectPriceRange.tsx | 21 + .../EarnAddConfirmPriceRangeInfo.stories.tsx | 3 +- .../EarnAddConfirmPriceRangeInfo.tsx | 19 +- .../EarnAddConfirm.stories.tsx | 3 +- .../earn-add-confirm/EarnAddConfirm.tsx | 3 +- .../earn-add-liquidity/EarnAddLiquidity.tsx | 16 +- packages/web/src/constants/swap.constant.ts | 2 +- .../EarnAddLiquidityContainer.tsx | 189 +- .../web/src/hooks/common/use-background.tsx | 5 +- packages/web/src/hooks/pool/use-pool.tsx | 49 +- .../web/src/hooks/pool/use-select-pool.tsx | 274 +++ .../use-earn-add-liquidity-confirm-modal.tsx | 73 +- packages/web/src/hooks/wallet/use-wallet.ts | 30 +- .../models/pool/mapper/pool-info-mapper.ts | 48 +- .../web/src/models/pool/pool-info-model.ts | 20 +- .../GnoswapServiceProvider.tsx | 46 +- .../repositories/pool/pool-repository-impl.ts | 65 +- .../repositories/pool/pool-repository-mock.ts | 4 + .../src/repositories/pool/pool-repository.ts | 3 + .../pool/request/add-liquidity-request.ts | 14 + .../pool/response/pool-info-response.ts | 18 +- packages/web/src/utils/swap-utils.ts | 11 +- 29 files changed, 1182 insertions(+), 2232 deletions(-) create mode 100644 packages/web/src/hooks/pool/use-select-pool.tsx create mode 100644 packages/web/src/repositories/pool/request/add-liquidity-request.ts diff --git a/packages/web/src/components/common/liquidity-enter-amounts/LiquidityEnterAmounts.tsx b/packages/web/src/components/common/liquidity-enter-amounts/LiquidityEnterAmounts.tsx index f04ccc1d8..af821f569 100644 --- a/packages/web/src/components/common/liquidity-enter-amounts/LiquidityEnterAmounts.tsx +++ b/packages/web/src/components/common/liquidity-enter-amounts/LiquidityEnterAmounts.tsx @@ -10,6 +10,8 @@ interface LiquidityEnterAmountsProps { tokenBInput: TokenAmountInputModel; changeTokenA: (token: TokenModel) => void; changeTokenB: (token: TokenModel) => void; + changeTokenAAmount: (amount: string) => void; + changeTokenBAmount: (amount: string) => void; } const LiquidityEnterAmounts: React.FC = ({ @@ -17,12 +19,13 @@ const LiquidityEnterAmounts: React.FC = ({ tokenBInput, changeTokenA, changeTokenB, + changeTokenAAmount, + changeTokenBAmount, }) => { - return ( - - + +
diff --git a/packages/web/src/components/common/pool-selection-graph/PoolSelectionGraph.stories.tsx b/packages/web/src/components/common/pool-selection-graph/PoolSelectionGraph.stories.tsx index 32e9f8d01..792c569e9 100644 --- a/packages/web/src/components/common/pool-selection-graph/PoolSelectionGraph.stories.tsx +++ b/packages/web/src/components/common/pool-selection-graph/PoolSelectionGraph.stories.tsx @@ -1,1837 +1,9 @@ -import React, { useEffect, useState, useRef } from "react"; -import PoolSelectionGraph, { type PoolSelectionGraphProps } from "./PoolSelectionGraph"; -import { ComponentStory, Meta, StoryObj } from "@storybook/react"; +import React, { useEffect, useState } from "react"; +import PoolSelectionGraph from "./PoolSelectionGraph"; +import { ComponentStory, Meta } from "@storybook/react"; import POOLS from "@repositories/pool/mock/pools.json"; import { tickToPrice } from "@utils/swap-utils"; - -const test = [ - { - "binId": 1, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 3, - "lowerTick": 4, - "originalLowerTick": 4, - "reserveA": 706712.8892504529, - "reserveB": 1193758.2264479052, - "cumulativeTokenAPerShare": 1070.708822547057, - "cumulativeTokenBPerShare": 1071.4874367179784, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 1846025.1041936176, - "timestamp": 1699233815, - "annualizedFeeGrowth": 0.08498393581540704 - }, - { - "binId": 5, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -4, - "originalLowerTick": -4, - "reserveA": 13945.262023390807, - "reserveB": 0, - "cumulativeTokenAPerShare": 716.7770059394281, - "cumulativeTokenBPerShare": 717.2639011401274, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 13556.583223601854, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.00575550925925926 - }, - { - "binId": 6, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -3, - "originalLowerTick": -3, - "reserveA": 22813.866943515444, - "reserveB": 0, - "cumulativeTokenAPerShare": 721.8200760136953, - "cumulativeTokenBPerShare": 722.1670784083564, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 22173.655247320337, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.00575550925925926 - }, - { - "binId": 7, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -2, - "originalLowerTick": -2, - "reserveA": 37464.65069303584, - "reserveB": 0, - "cumulativeTokenAPerShare": 729.5159123282365, - "cumulativeTokenBPerShare": 729.7203527466146, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 36402.41107788155, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.00575550925925926 - }, - { - "binId": 8, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -1, - "originalLowerTick": -1, - "reserveA": 89771.95482678543, - "reserveB": 0, - "cumulativeTokenAPerShare": 798.4596815088286, - "cumulativeTokenBPerShare": 797.521715775281, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 85532.87699987474, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.010934668216306585 - }, - { - "binId": 9, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 0, - "originalLowerTick": 0, - "reserveA": 155838.53563751673, - "reserveB": 0, - "cumulativeTokenAPerShare": 913.2714900355272, - "cumulativeTokenBPerShare": 912.1600016744314, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 150334.68355653159, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.014721984495616632 - }, - { - "binId": 10, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 1, - "originalLowerTick": 1, - "reserveA": 73282.62392635278, - "reserveB": 0, - "cumulativeTokenAPerShare": 992.1791604897556, - "cumulativeTokenBPerShare": 990.8594072833087, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 70466.3060404752, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.016302757538062273 - }, - { - "binId": 26, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -5, - "originalLowerTick": -5, - "reserveA": 4467.583938441541, - "reserveB": 0, - "cumulativeTokenAPerShare": 717.5472114571389, - "cumulativeTokenBPerShare": 718.1789214655598, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 4342.934585985483, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.00575550925925926 - }, - { - "binId": 27, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 2, - "originalLowerTick": 2, - "reserveA": 57865.770779943894, - "reserveB": 0, - "cumulativeTokenAPerShare": 1030.5800264565232, - "cumulativeTokenBPerShare": 1029.0451453347935, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 55549.204174081904, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.04710726670481152 - }, - { - "binId": 28, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 3, - "originalLowerTick": 3, - "reserveA": 35113.358378134384, - "reserveB": 0, - "cumulativeTokenAPerShare": 1007.1105644817275, - "cumulativeTokenBPerShare": 1005.3859616828165, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 33731.570177738344, - "timestamp": 1699221275, - "annualizedFeeGrowth": 0.0841605026382442 - }, - { - "binId": 29, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 4, - "originalLowerTick": 4, - "reserveA": 7918.014590787251, - "reserveB": 13374.872877883863, - "cumulativeTokenAPerShare": 996.2901938590836, - "cumulativeTokenBPerShare": 995.027687477932, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 20471.329914966384, - "timestamp": 1699233815, - "annualizedFeeGrowth": 0.1021039263915912 - }, - { - "binId": 40, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 5, - "originalLowerTick": 5, - "reserveA": 0, - "reserveB": 11428.069308246346, - "cumulativeTokenAPerShare": 973.0349401439623, - "cumulativeTokenBPerShare": 971.9849067499306, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 11000.385102714357, - "timestamp": 1699206299, - "annualizedFeeGrowth": 0.04498293834082653 - }, - { - "binId": 92, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 2, - "lowerTick": -8, - "originalLowerTick": -8, - "reserveA": 56.46594153637028, - "reserveB": 0, - "cumulativeTokenAPerShare": 704.5117437797314, - "cumulativeTokenBPerShare": 704.3809696624211, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 54.999944, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.005755509259259258 - }, - { - "binId": 147, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 1, - "lowerTick": 4, - "originalLowerTick": 4, - "reserveA": 2715.726222039534, - "reserveB": 4587.323321325579, - "cumulativeTokenAPerShare": 941.9901859271693, - "cumulativeTokenBPerShare": 942.322655780659, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 7041.9237363884395, - "timestamp": 1699233815, - "annualizedFeeGrowth": 0.1000376603009731 - }, - { - "binId": 317, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -11, - "originalLowerTick": -11, - "reserveA": 77.16719247786641, - "reserveB": 0, - "cumulativeTokenAPerShare": 526.9230325526293, - "cumulativeTokenBPerShare": 528.0198036747414, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 75.57433425629291, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.005755509259259263 - }, - { - "binId": 318, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -10, - "originalLowerTick": -10, - "reserveA": 126.22321502726892, - "reserveB": 0, - "cumulativeTokenAPerShare": 539.8689764650783, - "cumulativeTokenBPerShare": 540.8847667040528, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 123.55509918976466, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.005755509259259261 - }, - { - "binId": 319, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -9, - "originalLowerTick": -9, - "reserveA": 215.50293295889045, - "reserveB": 0, - "cumulativeTokenAPerShare": 549.3089816827655, - "cumulativeTokenBPerShare": 550.2323018952485, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 210.86967525421676, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.00575550925925926 - }, - { - "binId": 320, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -8, - "originalLowerTick": -8, - "reserveA": 353.5067820557563, - "reserveB": 0, - "cumulativeTokenAPerShare": 568.7848902453738, - "cumulativeTokenBPerShare": 569.6269531769881, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 345.6429987255599, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.00575550925925926 - }, - { - "binId": 321, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -7, - "originalLowerTick": -7, - "reserveA": 583.2566017704041, - "reserveB": 0, - "cumulativeTokenAPerShare": 586.8434461890743, - "cumulativeTokenBPerShare": 587.5952002133256, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 569.8795159670073, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.00575550925925926 - }, - { - "binId": 322, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -6, - "originalLowerTick": -6, - "reserveA": 2800.892037074582, - "reserveB": 0, - "cumulativeTokenAPerShare": 577.7591805189553, - "cumulativeTokenBPerShare": 578.3836850261574, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 2737.625073871, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.00575550925925926 - }, - { - "binId": 323, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -16, - "originalLowerTick": -16, - "reserveA": 1.6592670135219414, - "reserveB": 0, - "cumulativeTokenAPerShare": 489.1382529875325, - "cumulativeTokenBPerShare": 490.6467132334712, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 1.627425867237734, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.005755509259259314 - }, - { - "binId": 324, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -15, - "originalLowerTick": -15, - "reserveA": 1.6598271427322362, - "reserveB": 0, - "cumulativeTokenAPerShare": 497.76756913525327, - "cumulativeTokenBPerShare": 499.2031218977299, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 1.6274242903448781, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.005755509259259258 - }, - { - "binId": 325, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -14, - "originalLowerTick": -14, - "reserveA": 1.6601502347491581, - "reserveB": 0, - "cumulativeTokenAPerShare": 502.7370581555517, - "cumulativeTokenBPerShare": 504.0860498327076, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 1.6274238988115568, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.0057555092592594765 - }, - { - "binId": 326, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -13, - "originalLowerTick": -13, - "reserveA": 1.660240039297983, - "reserveB": 0, - "cumulativeTokenAPerShare": 505.43087370066115, - "cumulativeTokenBPerShare": 506.6858012317236, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 1.6273400479942635, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.005755509259259444 - }, - { - "binId": 327, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -12, - "originalLowerTick": -12, - "reserveA": 47.427214388060435, - "reserveB": 0, - "cumulativeTokenAPerShare": 511.11808620007105, - "cumulativeTokenBPerShare": 512.2846107657545, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 46.47701414242052, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.00575550925925926 - }, - { - "binId": 1187, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -32, - "originalLowerTick": -32, - "reserveA": 0.0463435701307749, - "reserveB": 0, - "cumulativeTokenAPerShare": 258.2990923039097, - "cumulativeTokenBPerShare": 259.92622969058493, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.04586965124997149, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.00575550925926569 - }, - { - "binId": 1188, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -31, - "originalLowerTick": -31, - "reserveA": 0.04634676303862378, - "reserveB": 0, - "cumulativeTokenAPerShare": 260.0456338709438, - "cumulativeTokenBPerShare": 261.6314259405612, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.04586963981492271, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.00575550925926257 - }, - { - "binId": 1189, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -30, - "originalLowerTick": -30, - "reserveA": 0.04635650980135836, - "reserveB": 0, - "cumulativeTokenAPerShare": 265.37478799429744, - "cumulativeTokenBPerShare": 266.93964328274524, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.04586960916010256, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.00575550925926161 - }, - { - "binId": 1190, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -29, - "originalLowerTick": -29, - "reserveA": 0.04635840938417238, - "reserveB": 0, - "cumulativeTokenAPerShare": 266.41481818186253, - "cumulativeTokenBPerShare": 267.9322836789809, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.0458696005860837, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.00015731765745788354 - }, - { - "binId": 1191, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -28, - "originalLowerTick": -28, - "reserveA": 0.04636002244483275, - "reserveB": 0, - "cumulativeTokenAPerShare": 267.41388707336097, - "cumulativeTokenBPerShare": 268.88326265411223, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.04586938293834845, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.0057555092592642375 - }, - { - "binId": 1192, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -27, - "originalLowerTick": -27, - "reserveA": 0.046364143652935313, - "reserveB": 0, - "cumulativeTokenAPerShare": 269.7114929665209, - "cumulativeTokenBPerShare": 271.1392106824499, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.04586928965289385, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.005755509259265558 - }, - { - "binId": 1193, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 23, - "originalLowerTick": 23, - "reserveA": 0, - "reserveB": 0.9909989177259614, - "cumulativeTokenAPerShare": 642.3354951003428, - "cumulativeTokenBPerShare": 639.3365775587359, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.9662878388905187, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.009090072781343392 - }, - { - "binId": 1194, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 24, - "originalLowerTick": 24, - "reserveA": 0, - "reserveB": 0.9908769506357206, - "cumulativeTokenAPerShare": 639.2520276279813, - "cumulativeTokenBPerShare": 636.1402912004418, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.9662893731771254, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.00909007278134344 - }, - { - "binId": 1195, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 25, - "originalLowerTick": 25, - "reserveA": 0, - "reserveB": 0.9907509043666082, - "cumulativeTokenAPerShare": 636.0938716957864, - "cumulativeTokenBPerShare": 632.8708720174664, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.9662896851913185, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.009090072781343495 - }, - { - "binId": 1196, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 26, - "originalLowerTick": 26, - "reserveA": 0, - "reserveB": 0.9906868132777966, - "cumulativeTokenAPerShare": 634.5481486494297, - "cumulativeTokenBPerShare": 631.2067825136984, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.9662899082639463, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.008684381499237066 - }, - { - "binId": 1197, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 27, - "originalLowerTick": 27, - "reserveA": 0, - "reserveB": 0.9905881522584051, - "cumulativeTokenAPerShare": 632.0815016584576, - "cumulativeTokenBPerShare": 628.6273564111834, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.966290919253447, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.008628032938265376 - }, - { - "binId": 1198, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 28, - "originalLowerTick": 28, - "reserveA": 0, - "reserveB": 0.9905151847838304, - "cumulativeTokenAPerShare": 630.309302897399, - "cumulativeTokenBPerShare": 626.7394732130988, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.9662909205287823, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.00776697353121794 - }, - { - "binId": 1199, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 29, - "originalLowerTick": 29, - "reserveA": 0, - "reserveB": 0.990515184900952, - "cumulativeTokenAPerShare": 630.435371104055, - "cumulativeTokenBPerShare": 626.7394732558304, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.9662909205287661, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.007766973531217892 - }, - { - "binId": 1200, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 30, - "originalLowerTick": 30, - "reserveA": 0, - "reserveB": 0.9905151847838304, - "cumulativeTokenAPerShare": 630.5614644396373, - "cumulativeTokenBPerShare": 626.7394732130989, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.9662909205287823, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.007766973531217889 - }, - { - "binId": 1201, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 31, - "originalLowerTick": 31, - "reserveA": 0, - "reserveB": 0.9905151847857459, - "cumulativeTokenAPerShare": 630.6875830384323, - "cumulativeTokenBPerShare": 626.7394732133895, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.966290920528782, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.00776697353118329 - }, - { - "binId": 1202, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 32, - "originalLowerTick": 32, - "reserveA": 0, - "reserveB": 0.8954890732129996, - "cumulativeTokenAPerShare": 630.8137494002756, - "cumulativeTokenBPerShare": 626.7394956061801, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.8735887169185576, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.006182278919417847 - }, - { - "binId": 1276, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 6, - "originalLowerTick": 6, - "reserveA": 0, - "reserveB": 6813.231767403327, - "cumulativeTokenAPerShare": 679.9301146757575, - "cumulativeTokenBPerShare": 679.0604063350629, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 6633.063536441259, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.012346911331836616 - }, - { - "binId": 1457, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 8, - "originalLowerTick": 8, - "reserveA": 0, - "reserveB": 0.0205072013221458, - "cumulativeTokenAPerShare": 10.01901729604251, - "cumulativeTokenBPerShare": 10.002200330038727, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.020499, - "timestamp": 1694794943, - "annualizedFeeGrowth": 0 - }, - { - "binId": 1458, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 9, - "originalLowerTick": 9, - "reserveA": 0, - "reserveB": 0.020507201322168586, - "cumulativeTokenAPerShare": 10.021021199691889, - "cumulativeTokenBPerShare": 10.002200330038725, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.020499, - "timestamp": 1694794943, - "annualizedFeeGrowth": 0 - }, - { - "binId": 1459, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 10, - "originalLowerTick": 10, - "reserveA": 0, - "reserveB": 0.02050720132216859, - "cumulativeTokenAPerShare": 10.02302550414204, - "cumulativeTokenBPerShare": 10.002200330038727, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.020499, - "timestamp": 1694794943, - "annualizedFeeGrowth": 0 - }, - { - "binId": 1460, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 11, - "originalLowerTick": 11, - "reserveA": 0, - "reserveB": 0.0205072013221458, - "cumulativeTokenAPerShare": 10.025030209473124, - "cumulativeTokenBPerShare": 10.002200330038727, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.020499, - "timestamp": 1694794943, - "annualizedFeeGrowth": 0 - }, - { - "binId": 1461, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 12, - "originalLowerTick": 12, - "reserveA": 0, - "reserveB": 0.020507201322168586, - "cumulativeTokenAPerShare": 10.02703531576532, - "cumulativeTokenBPerShare": 10.002200330038725, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.020499, - "timestamp": 1694794943, - "annualizedFeeGrowth": 0 - }, - { - "binId": 1462, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 13, - "originalLowerTick": 13, - "reserveA": 0, - "reserveB": 0.020507201322168586, - "cumulativeTokenAPerShare": 10.029040823098825, - "cumulativeTokenBPerShare": 10.002200330038727, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.020499, - "timestamp": 1694794943, - "annualizedFeeGrowth": 0 - }, - { - "binId": 1463, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 14, - "originalLowerTick": 14, - "reserveA": 0, - "reserveB": 0.020507201322145785, - "cumulativeTokenAPerShare": 10.031046731553854, - "cumulativeTokenBPerShare": 10.002200330038727, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.020499, - "timestamp": 1694794943, - "annualizedFeeGrowth": 0 - }, - { - "binId": 1464, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 15, - "originalLowerTick": 15, - "reserveA": 0, - "reserveB": 0.02050720132216859, - "cumulativeTokenAPerShare": 10.033053041210632, - "cumulativeTokenBPerShare": 10.002200330038727, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.020499, - "timestamp": 1694794943, - "annualizedFeeGrowth": 0 - }, - { - "binId": 1465, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 16, - "originalLowerTick": 16, - "reserveA": 0, - "reserveB": 0.020507198707935364, - "cumulativeTokenAPerShare": 10.031860841664033, - "cumulativeTokenBPerShare": 9.999012212028196, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.020499, - "timestamp": 1694794943, - "annualizedFeeGrowth": 0 - }, - { - "binId": 1466, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 17, - "originalLowerTick": 17, - "reserveA": 0, - "reserveB": 0.02050638104231858, - "cumulativeTokenAPerShare": 9.033179499359571, - "cumulativeTokenBPerShare": 9.001800246026404, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.020499, - "timestamp": 1694794943, - "annualizedFeeGrowth": 0 - }, - { - "binId": 1467, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 18, - "originalLowerTick": 18, - "reserveA": 0, - "reserveB": 0.020506381042295768, - "cumulativeTokenAPerShare": 9.034986225591238, - "cumulativeTokenBPerShare": 9.001800246026404, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.020499, - "timestamp": 1694794943, - "annualizedFeeGrowth": 0 - }, - { - "binId": 1468, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 19, - "originalLowerTick": 19, - "reserveA": 0, - "reserveB": 0.02050638104231858, - "cumulativeTokenAPerShare": 9.036793313186218, - "cumulativeTokenBPerShare": 9.001800246026404, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.020499, - "timestamp": 1694794943, - "annualizedFeeGrowth": 0 - }, - { - "binId": 1469, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 20, - "originalLowerTick": 20, - "reserveA": 0, - "reserveB": 0.02050638104231858, - "cumulativeTokenAPerShare": 9.038600762216788, - "cumulativeTokenBPerShare": 9.001800246026404, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.020499, - "timestamp": 1694794943, - "annualizedFeeGrowth": 0 - }, - { - "binId": 1470, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 21, - "originalLowerTick": 21, - "reserveA": 0, - "reserveB": 0.02050638104229576, - "cumulativeTokenAPerShare": 9.040408572755238, - "cumulativeTokenBPerShare": 9.001800246026404, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.020499, - "timestamp": 1694794943, - "annualizedFeeGrowth": 0 - }, - { - "binId": 1471, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 22, - "originalLowerTick": 22, - "reserveA": 0, - "reserveB": 0.02050638104231858, - "cumulativeTokenAPerShare": 9.042216744873874, - "cumulativeTokenBPerShare": 9.001800246026404, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.020499, - "timestamp": 1694794943, - "annualizedFeeGrowth": 0 - }, - { - "binId": 1472, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 33, - "originalLowerTick": 33, - "reserveA": 0, - "reserveB": 0.03148397637545181, - "cumulativeTokenAPerShare": 562.9138098446691, - "cumulativeTokenBPerShare": 559.1662650252136, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.030795197798522824, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.007735275166424647 - }, - { - "binId": 1473, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -17, - "originalLowerTick": -17, - "reserveA": 0.000123004920147605, - "reserveB": 0, - "cumulativeTokenAPerShare": 1.0000400012000406, - "cumulativeTokenBPerShare": 1.0033253519671381, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000123, - "timestamp": 1694770403, - "annualizedFeeGrowth": 0 - }, - { - "binId": 1474, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -18, - "originalLowerTick": -18, - "reserveA": 0.000123004920147605, - "reserveB": 0, - "cumulativeTokenAPerShare": 1.0000400012000406, - "cumulativeTokenBPerShare": 1.0035260270707886, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000123, - "timestamp": 1694770403, - "annualizedFeeGrowth": 0 - }, - { - "binId": 1475, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -19, - "originalLowerTick": -19, - "reserveA": 0.000123004920147605, - "reserveB": 0, - "cumulativeTokenAPerShare": 1.0000400012000406, - "cumulativeTokenBPerShare": 1.0037267423114633, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000123, - "timestamp": 1694770403, - "annualizedFeeGrowth": 0 - }, - { - "binId": 1476, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -20, - "originalLowerTick": -20, - "reserveA": 0.000123004920147605, - "reserveB": 0, - "cumulativeTokenAPerShare": 1.0000400012000406, - "cumulativeTokenBPerShare": 1.003927497697195, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000123, - "timestamp": 1694770403, - "annualizedFeeGrowth": 0 - }, - { - "binId": 1477, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -21, - "originalLowerTick": -21, - "reserveA": 0.000123004920147605, - "reserveB": 0, - "cumulativeTokenAPerShare": 1.0000400012000406, - "cumulativeTokenBPerShare": 1.004128293236008, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000123, - "timestamp": 1694770403, - "annualizedFeeGrowth": 0 - }, - { - "binId": 1478, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -22, - "originalLowerTick": -22, - "reserveA": 0.00012300492014746914, - "reserveB": 0, - "cumulativeTokenAPerShare": 1.0000400012000488, - "cumulativeTokenBPerShare": 1.004329128935943, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000123, - "timestamp": 1694770403, - "annualizedFeeGrowth": 0 - }, - { - "binId": 1479, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -23, - "originalLowerTick": -23, - "reserveA": 0.000123004920147605, - "reserveB": 0, - "cumulativeTokenAPerShare": 1.0000400012000406, - "cumulativeTokenBPerShare": 1.0045300048050163, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000123, - "timestamp": 1694770403, - "annualizedFeeGrowth": 0 - }, - { - "binId": 1480, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -24, - "originalLowerTick": -24, - "reserveA": 0.000123004920147605, - "reserveB": 0, - "cumulativeTokenAPerShare": 1.0000400012000406, - "cumulativeTokenBPerShare": 1.0047309208512765, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000123, - "timestamp": 1694770403, - "annualizedFeeGrowth": 0 - }, - { - "binId": 1481, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -25, - "originalLowerTick": -25, - "reserveA": 0.000123004920147605, - "reserveB": 0, - "cumulativeTokenAPerShare": 1.0000400012000406, - "cumulativeTokenBPerShare": 1.004931877082756, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000123, - "timestamp": 1694770403, - "annualizedFeeGrowth": 0 - }, - { - "binId": 1482, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -26, - "originalLowerTick": -26, - "reserveA": 0.00012300492014746806, - "reserveB": 0, - "cumulativeTokenAPerShare": 1.0000400012000406, - "cumulativeTokenBPerShare": 1.0051328735074878, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000123, - "timestamp": 1694770403, - "annualizedFeeGrowth": 0 - }, - { - "binId": 2265, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 2, - "lowerTick": 0, - "originalLowerTick": 0, - "reserveA": 1165.6424430826492, - "reserveB": 0, - "cumulativeTokenAPerShare": 158.30169180904724, - "cumulativeTokenBPerShare": 157.26992159732026, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 1158.216468, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.014721984495616632 - }, - { - "binId": 2519, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 10, - "originalLowerTick": 10, - "reserveA": 0, - "reserveB": 0.000013023942259603, - "cumulativeTokenAPerShare": 46.13913206656431, - "cumulativeTokenBPerShare": 46.04326725430354, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000013, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.012314687812829172 - }, - { - "binId": 2520, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 11, - "originalLowerTick": 11, - "reserveA": 0, - "reserveB": 0.000013023942259591525, - "cumulativeTokenAPerShare": 46.14836035437215, - "cumulativeTokenBPerShare": 46.04326725430715, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000013, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.012314687812910664 - }, - { - "binId": 2521, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 12, - "originalLowerTick": 12, - "reserveA": 0, - "reserveB": 0.000013023939032973, - "cumulativeTokenAPerShare": 46.151369662626195, - "cumulativeTokenBPerShare": 46.03706245382777, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000013, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.012309736748139547 - }, - { - "binId": 2522, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 13, - "originalLowerTick": 13, - "reserveA": 0, - "reserveB": 0.000013022900375473998, - "cumulativeTokenAPerShare": 44.157802421819, - "cumulativeTokenBPerShare": 44.03962390302123, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000013, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.01056892222591231 - }, - { - "binId": 2523, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 14, - "originalLowerTick": 14, - "reserveA": 0, - "reserveB": 0.000013022900375088519, - "cumulativeTokenAPerShare": 44.166633712654836, - "cumulativeTokenBPerShare": 44.039623193911275, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000013, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.0105689220590736 - }, - { - "binId": 2524, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 15, - "originalLowerTick": 15, - "reserveA": 0, - "reserveB": 0.00001302237946467, - "cumulativeTokenAPerShare": 43.17061659896523, - "cumulativeTokenBPerShare": 43.03786233567677, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000013, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.009963171657693339 - }, - { - "binId": 2525, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 16, - "originalLowerTick": 16, - "reserveA": 0, - "reserveB": 0.000013022379464671, - "cumulativeTokenAPerShare": 43.17925115400161, - "cumulativeTokenBPerShare": 43.037862335686924, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000013, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.009963171657658844 - }, - { - "binId": 2526, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 17, - "originalLowerTick": 17, - "reserveA": 0, - "reserveB": 0.000013022376322679998, - "cumulativeTokenAPerShare": 43.18182372407074, - "cumulativeTokenBPerShare": 43.031820288169364, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000013, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.009958506902450632 - }, - { - "binId": 2527, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 18, - "originalLowerTick": 18, - "reserveA": 0, - "reserveB": 0.000013021858574681514, - "cumulativeTokenAPerShare": 42.19111100799577, - "cumulativeTokenBPerShare": 42.03614083839577, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000013, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.009059970316406115 - }, - { - "binId": 2528, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 19, - "originalLowerTick": 19, - "reserveA": 0, - "reserveB": 0.000013021858574695, - "cumulativeTokenAPerShare": 42.199549652106924, - "cumulativeTokenBPerShare": 42.03614083839438, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000013, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.009059970318713828 - }, - { - "binId": 2529, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 20, - "originalLowerTick": 20, - "reserveA": 0, - "reserveB": 0.000013021858574699998, - "cumulativeTokenAPerShare": 42.20798998403354, - "cumulativeTokenBPerShare": 42.036140838395156, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000013, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.009059970323311335 - }, - { - "binId": 2530, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 21, - "originalLowerTick": 21, - "reserveA": 0, - "reserveB": 0.000013021858574686513, - "cumulativeTokenAPerShare": 42.216432004112384, - "cumulativeTokenBPerShare": 42.03614083839715, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000013, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.009059970323450833 - }, - { - "binId": 2531, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 22, - "originalLowerTick": 22, - "reserveA": 0, - "reserveB": 0.000013021858574698, - "cumulativeTokenAPerShare": 42.224875712675306, - "cumulativeTokenBPerShare": 42.03614083839477, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000013, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.009059970318484493 - }, - { - "binId": 2532, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 34, - "originalLowerTick": 34, - "reserveA": 0, - "reserveB": 0.000013019775223164, - "cumulativeTokenAPerShare": 38.292188453356076, - "cumulativeTokenBPerShare": 38.029655517835074, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000013, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.007453397166951762 - }, - { - "binId": 2533, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 35, - "originalLowerTick": 35, - "reserveA": 0, - "reserveB": 0.000013019775223157002, - "cumulativeTokenAPerShare": 38.29984727396138, - "cumulativeTokenBPerShare": 38.02965551782723, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000013, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.007453397163837512 - }, - { - "binId": 2534, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 36, - "originalLowerTick": 36, - "reserveA": 0, - "reserveB": 0.000013019768042874491, - "cumulativeTokenAPerShare": 38.29359769947823, - "cumulativeTokenBPerShare": 38.01584785343465, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000013, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.007443246416021819 - }, - { - "binId": 2535, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -17, - "originalLowerTick": -17, - "reserveA": 0.000014008962957492, - "reserveB": 0, - "cumulativeTokenAPerShare": 16.005441251434856, - "cumulativeTokenBPerShare": 16.058022636808715, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000014, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.005755509260693049 - }, - { - "binId": 2536, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -18, - "originalLowerTick": -18, - "reserveA": 0.000014008962957489, - "reserveB": 0, - "cumulativeTokenAPerShare": 16.00544125143357, - "cumulativeTokenBPerShare": 16.061234401915073, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000014, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.00575550928123471 - }, - { - "binId": 2537, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -19, - "originalLowerTick": -19, - "reserveA": 0.000014008962957490001, - "reserveB": 0, - "cumulativeTokenAPerShare": 16.005441251433716, - "cumulativeTokenBPerShare": 16.06444680940786, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000014, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.005755509281234399 - }, - { - "binId": 2538, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -20, - "originalLowerTick": -20, - "reserveA": 0.000014008962957488, - "reserveB": 0, - "cumulativeTokenAPerShare": 16.0054412514335, - "cumulativeTokenBPerShare": 16.067659859414, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000014, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.005755509260694761 - }, - { - "binId": 2539, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -21, - "originalLowerTick": -21, - "reserveA": 0.000014008962957487001, - "reserveB": 0, - "cumulativeTokenAPerShare": 16.005441251432284, - "cumulativeTokenBPerShare": 16.070873552061357, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000014, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.0057555092606951345 - }, - { - "binId": 2540, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -22, - "originalLowerTick": -22, - "reserveA": 0.000014008962957472413, - "reserveB": 0, - "cumulativeTokenAPerShare": 16.005441251433215, - "cumulativeTokenBPerShare": 16.07408788748143, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000014, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.005755509260694722 - }, - { - "binId": 2541, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -23, - "originalLowerTick": -23, - "reserveA": 0.000014008962957484, - "reserveB": 0, - "cumulativeTokenAPerShare": 16.005441251430927, - "cumulativeTokenBPerShare": 16.07730286579764, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000014, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.005755509260696192 - }, - { - "binId": 2542, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -24, - "originalLowerTick": -24, - "reserveA": 0.000014008600294993, - "reserveB": 0, - "cumulativeTokenAPerShare": 15.357827211606201, - "cumulativeTokenBPerShare": 15.42984371462987, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000014, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.00575550925720525 - }, - { - "binId": 2543, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -25, - "originalLowerTick": -25, - "reserveA": 0.000014008402604574999, - "reserveB": 0, - "cumulativeTokenAPerShare": 15.004801040185857, - "cumulativeTokenBPerShare": 15.078199728482858, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000014, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.005755509259766168 - }, - { - "binId": 2544, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": -26, - "originalLowerTick": -26, - "reserveA": 0.000014008402604559407, - "reserveB": 0, - "cumulativeTokenAPerShare": 15.004801040184857, - "cumulativeTokenBPerShare": 15.081215519209714, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 0.000014, - "timestamp": 1699215827, - "annualizedFeeGrowth": 0.005755509280307726 - }, - { - "binId": 2588, - "poolId": "0xd0b2f5018b5d22759724af6d4281ac0b13266360", - "kind": 0, - "lowerTick": 7, - "originalLowerTick": 7, - "reserveA": 0, - "reserveB": 17.940621721095518, - "cumulativeTokenAPerShare": 7.011488925175008, - "cumulativeTokenBPerShare": 7.001120123210753, - "mergeCumulativeTokenAPerShare": 0, - "mergeCumulativeTokenBPerShare": 0, - "mergeBinBalance": 0, - "mergeId": null, - "mergedAtTimestamp": null, - "totalSupply": 17.935599, - "timestamp": 1699160627, - "annualizedFeeGrowth": 0.006153749786658708 - } -]; - const pool = POOLS.pools[0]; export default { @@ -1844,17 +16,21 @@ const buttonStyles = { height: "20px", margin: "5px 2px", backgroundColor: "#b5cfeb" -} +}; const Template: ComponentStory = args => { const [minPrice, setMinPrice] = useState(null); const [maxPrice, setMaxPrice] = useState(null); const [focusTick, setFocusTick] = useState(tickToPrice(18)); const [zoomLevel, setZoomLevel] = useState(3); - const [selectedFullRange, setSelectedFullRange] = useState(false); + const [selectedFullRange] = useState(false); const width = 600; const height = 400; + useEffect(() => { + console.log(pool); + }, []); + function zoomIn() { if (zoomLevel < 5) { setZoomLevel(zoomLevel + 1); @@ -1892,9 +68,7 @@ const Template: ComponentStory = args => { setMinPrice={setMinPrice} setMaxPrice={setMaxPrice} zoomLevel={zoomLevel} - focusTick={focusTick} selectedFullRange={selectedFullRange} - setSelectedFullRange={setSelectedFullRange} /> ); @@ -1902,7 +76,5 @@ const Template: ComponentStory = args => { export const Default = Template.bind({}); Default.args = { - bins: pool.bins, - currentTick: 18, // zoomLevel: 0 }; \ No newline at end of file diff --git a/packages/web/src/components/common/pool-selection-graph/PoolSelectionGraph.tsx b/packages/web/src/components/common/pool-selection-graph/PoolSelectionGraph.tsx index bbefcdf77..fd8a23011 100644 --- a/packages/web/src/components/common/pool-selection-graph/PoolSelectionGraph.tsx +++ b/packages/web/src/components/common/pool-selection-graph/PoolSelectionGraph.tsx @@ -1,31 +1,7 @@ import React, { useEffect, useRef } from "react"; import { PoolSelectionGraphWrapper } from "./PoolSelectionGraph.styles"; import * as d3 from "d3"; -import { PoolBinModel } from "@models/pool/pool-bin-model"; -import { tickToPrice } from "@utils/swap-utils"; -import BigNumber from "bignumber.js"; - -export interface PoolSelectionGraphProps { - bins: PoolBinModel[]; - currentTick: number | null; - zoomLevel: number; - displayLabels?: number; - minPrice: number | null; - maxPrice: number | null; - setMinPrice: (tick: number | null) => void; - setMaxPrice: (tick: number | null) => void; - selectedFullRange: boolean; - setSelectedFullRange: (selected: boolean) => void; - focusTick: number | null; - width: number; - height: number; - margin?: { - left: number; - right: number; - top: number; - bottom: number; - }, -} +import { numberToFormat } from "@utils/string-utils"; function makeBadge( refer: d3.Selection, @@ -123,9 +99,35 @@ function changeLine( .html(rateStr); } +export interface PoolSelectionGraphProps { + scaleX: d3.ScaleLinear; + scaleY: d3.ScaleLinear; + liquidityOfTickPoints: [number, number][]; + currentPrice: number | null; + zoomLevel: number; + displayLabels?: number; + minPrice: number | null; + maxPrice: number | null; + setMinPrice: (tick: number | null) => void; + setMaxPrice: (tick: number | null) => void; + selectedFullRange: boolean; + setFullRange: (fullRange: boolean) => void; + focusPosition: number | null; + width: number; + height: number; + margin?: { + left: number; + right: number; + top: number; + bottom: number; + }, +} + const PoolSelectionGraph: React.FC = ({ - bins, - currentTick = null, + scaleX, + scaleY, + liquidityOfTickPoints, + currentPrice = null, displayLabels = 8, width, height, @@ -134,8 +136,8 @@ const PoolSelectionGraph: React.FC = ({ setMinPrice, setMaxPrice, selectedFullRange, - setSelectedFullRange, - focusTick, + setFullRange, + focusPosition, zoomLevel, margin = { left: 0, @@ -150,67 +152,70 @@ const PoolSelectionGraph: React.FC = ({ const tooltipRef = useRef(null); const labelHeight = displayLabels > 0 ? 20 : 0; - const paddingHeight = 20; + const paddingHeight = 0; const boundsWidth = width - margin.right - margin.left; const boundsHeight = height - margin.top - margin.bottom - labelHeight - paddingHeight; - const tickAmount = 10000; - const [, maxX] = d3.extent(bins.map(bin => bin.currentTick)); - const maxXTick = tickToPrice(maxX ?? 1) * 10000; - const binRange = maxXTick / tickAmount; - const currentPrice = tickToPrice(currentTick || 0); + const getRange = () => { + return scaleX.domain(); + }; + + const getBinWidth = () => { + return width / 20; + }; const resolvedBins = () => { - const sortedBins = bins.sort((b1, b2) => b1.currentTick - b2.currentTick) - .map(bin => ({ ...bin, currentPrice: tickToPrice(bin.currentTick) })); - console.log(sortedBins); - return Array.from( - { length: tickAmount }, - (_, index) => { - const startPrice = binRange * index; - const endPrice = startPrice + binRange; - return sortedBins.filter( - bin => - bin.currentPrice < endPrice && - bin.currentPrice >= startPrice) - .reduce((a, b) => a + b.totalSupply, 0); - }, - ); + const binWidth = getBinWidth(); + const startXPosition = (scaleX.invert(0) % binWidth) * -1; + + return Array.from({ length: 22 }, (_, index) => { + const x = startXPosition + (binWidth * index); + const y = liquidityOfTickPoints.find((point, pIndex) => { + const pointPosition = scaleX(point[0]); + if (liquidityOfTickPoints.length <= pIndex + 1) { + return x >= pointPosition; + } + const nextPointPosition = scaleX(liquidityOfTickPoints[pIndex + 1][0]); + if (nextPointPosition > x && x >= pointPosition) { + return true; + } + return false; + })?.[1] || 0; + + return { + x, + y, + width: binWidth + }; + }); }; /** D3 Variables */ - const defaultScaleX = d3 - .scaleLinear() - .domain([-maxXTick, maxXTick]) - .range([margin.left, boundsWidth]); + const defaultScaleX = scaleX.copy(); - const scaleX = defaultScaleX.copy(); const xAxis = d3 .axisBottom(scaleX) + .tickFormat(tick => numberToFormat(`${tick}`, 4)) .tickArguments([displayLabels]); - const [, max] = d3.extent(resolvedBins()); - - const scaleY = d3 - .scaleLinear() - .domain([0, max || 0]) - .range([boundsHeight, 0]); const binData = () => { - function fillByBin(num: number, index: number) { - if (num === 0) { + const currentPricePosition = currentPrice ? scaleX(currentPrice) : null; + function fillByBin(bin: { x: number, y: number, width: number }) { + if (bin.y === 0) { return "#4c4c4c"; } - if (currentTick && index * binRange < tickToPrice(currentTick)) { + const centerX = bin.x + (bin.width / 2); + if (currentPricePosition && centerX < currentPricePosition) { return "url(#gradient-bar-green)"; } return "url(#gradient-bar-red)"; } - return resolvedBins().map((bin, index) => { - const x = scaleX(index * binRange); - const y = bin < 100 ? boundsHeight - 5 : scaleY(bin); - const fill = fillByBin(bin, index); - const width = scaleX(binRange) - scaleX(0) > 2 ? scaleX(binRange) - scaleX(0) - 2 : scaleX(binRange) - scaleX(0); + return resolvedBins().map((bin) => { + const x = bin.x + 1; + const y = scaleY(bin.y); + const fill = fillByBin(bin); + const width = bin.width - 1; const height = boundsHeight - y; return { @@ -232,16 +237,19 @@ const PoolSelectionGraph: React.FC = ({ .on("start brush end", onBrush); function onBrush(event: d3.D3BrushEvent) { - if (event.selection !== null) { - if (Array.isArray(event.selection)) { - if (typeof event.selection[0] !== "number" || typeof event.selection[1] !== "number") { - return; - } + try { + if (!event?.type || !brushRef.current) { + return; + } - if (!brushRef.current) { - return; - } + if (event.selection === null || !Array.isArray(event.selection)) { + return; + } + if (typeof event.selection[0] !== "number" || typeof event.selection[1] !== "number") { + return; + } + if (event.type === "brush") { if (event.selection[0] === event.selection[1]) { setMinPrice(null); setMaxPrice(null); @@ -250,21 +258,31 @@ const PoolSelectionGraph: React.FC = ({ selectionElement.select("#end").remove(); return; } - - const minPricePosition = event.selection[0]; - const minPrice = scaleX.invert(minPricePosition); - const maxPricePosition = event.selection[1]; - const maxPrice = scaleX.invert(maxPricePosition); - - setSelectedFullRange(false); - - if (event.type === "drag" || event.type === "end") { - setMinPrice(BigNumber(minPrice.toPrecision(12)).toNumber()); - setMaxPrice(BigNumber(maxPrice.toPrecision(12)).toNumber()); + } else { + if (event.mode) { + setFullRange(false); } - initBrushGradient(currentPrice, minPrice, maxPrice); } - } + if (event.type === "end") { + if (event.selection[0] === event.selection[1]) { + setMinPrice(null); + setMaxPrice(null); + const selectionElement = d3.select(brushRef.current); + selectionElement.select("#start").remove(); + selectionElement.select("#end").remove(); + return; + } + } + + const zeroPosition = scaleX(0); + const minPricePosition = event.selection[0] > zeroPosition ? event.selection[0] : zeroPosition; + const minPrice = scaleX.invert(minPricePosition); + const maxPricePosition = event.selection[1] > zeroPosition ? event.selection[1] : zeroPosition; + const maxPrice = scaleX.invert(maxPricePosition); + setMinPrice(minPrice); + setMaxPrice(maxPrice); + initBrushGradient(currentPrice, minPrice, maxPrice); + } catch { } } function initBrushGradient(currentPrice: number | null, minPrice: number | null, maxPrice: number | null) { @@ -324,23 +342,20 @@ const PoolSelectionGraph: React.FC = ({ const minPriceRate = currentPrice === 0 ? 0 : (minPrice - currentPrice) / currentPrice * 100; changeLine(selectionElement, "start", scaleX(minPrice), minPriceRate, isRightStartLine); - const isRightEndLine = scaleX(maxPrice) + 75 < boundsWidth; - const maxPriceRate = currentPrice === 0 ? 0 : (maxPrice - currentPrice) / currentPrice * 100; - changeLine(selectionElement, "end", scaleX(maxPrice), maxPriceRate, isRightEndLine); + if (selectedFullRange) { + const endLineElement = selectionElement.select("#end"); + endLineElement.remove(); + } else { + const isRightEndLine = scaleX(maxPrice) + 75 < boundsWidth; + const maxPriceRate = currentPrice === 0 ? 0 : (maxPrice - currentPrice) / currentPrice * 100; + changeLine(selectionElement, "end", scaleX(maxPrice), maxPriceRate, isRightEndLine); + } } /** Zoom */ const zoom: d3.ZoomBehavior = d3 .zoom() - .scaleExtent([-maxXTick, maxXTick]) - .translateExtent([ - [0, 0], - [boundsWidth, boundsHeight] - ]) - .extent([ - [0, 0], - [boundsWidth, boundsHeight] - ]) + .scaleExtent([0.01, 2 ** 20]) .on("zoom", onZoom); function onZoom(event: d3.D3ZoomEvent) { @@ -352,8 +367,14 @@ const PoolSelectionGraph: React.FC = ({ function initZoom() { const svgElement = d3.select(svgRef.current); - const scaleRate = BigNumber(2).pow(zoomLevel * 3).toNumber(); - zoom.scaleTo(svgElement, scaleRate, [scaleX(focusTick || 0), 0]); + const scaleRate = 2 ** (zoomLevel - 10); + zoom.scaleTo(svgElement, scaleRate, [0, 0]); + const [x1, x2] = getRange(); + zoom.translateTo( + svgElement, + scaleX((x1 + x2) / 2), + 0 + ); brush.extent([ [scaleX(0), 0], @@ -386,7 +407,8 @@ const PoolSelectionGraph: React.FC = ({ } // Create a line of current tick. - if (currentTick) { + const currentPricePosition = currentPrice ? scaleX(currentPrice) : null; + if (currentPricePosition) { if (d3.select(svgRef.current).select("#current-price").empty()) { d3.select(svgRef.current) .append("line") @@ -394,8 +416,8 @@ const PoolSelectionGraph: React.FC = ({ } d3.select(svgRef.current) .select("#current-price") - .attr("x1", scaleX(tickToPrice(currentTick))) - .attr("x2", scaleX(tickToPrice(currentTick))) + .attr("x1", currentPricePosition) + .attr("x2", currentPricePosition) .attr("y1", boundsHeight + paddingHeight) .attr("y2", 0) .attr("stroke-dasharray", 4) @@ -406,40 +428,43 @@ const PoolSelectionGraph: React.FC = ({ } function interactChart() { - if (focusTick) { - const svgElement = d3.select(svgRef.current); - zoom.translateTo( - svgElement, - scaleX(focusTick), - 0 - ); - } initZoom(); - updateChart(); - if (brushRef.current && minPrice && maxPrice) { + if (brushRef.current) { try { - initBrushGradient(currentPrice, minPrice, maxPrice); - brush.move( - d3.select(brushRef.current), - [scaleX(minPrice), scaleX(maxPrice)] - ); + const brushElement = d3.select(brushRef.current); + if (minPrice && maxPrice) { + initBrushGradient(currentPrice, minPrice, maxPrice); + brush.move( + brushElement, + [scaleX(minPrice), scaleX(maxPrice)] + ); + } else { + brush.clear(brushElement); + brushElement.selectChildren().remove(); + } } catch { } } } useEffect(() => { interactChart(); - }, [zoomLevel, focusTick, minPrice, maxPrice, currentTick]); + updateChart(); + }, [zoomLevel, focusPosition, minPrice, maxPrice, currentPrice, selectedFullRange]); useEffect(() => { - if (selectedFullRange && brushRef.current) { - brush.move( + if (selectedFullRange && brushRef.current && scaleX && brush?.move) { + const x1 = scaleX(0); + const minPrice = 0; + const maxPrice = scaleX.invert(width); + setMinPrice(minPrice); + setMaxPrice(maxPrice); + brush?.move( d3.select(brushRef.current), - [scaleX(0), maxXTick] + [x1, width] ); } - }, [selectedFullRange]); + }, [selectedFullRange, zoomLevel]); useEffect(() => { const svgElement = d3.select(svgRef.current) diff --git a/packages/web/src/components/common/select-fee-tier/SelectFeeTier.tsx b/packages/web/src/components/common/select-fee-tier/SelectFeeTier.tsx index 5b581e97d..0bf24a94c 100644 --- a/packages/web/src/components/common/select-fee-tier/SelectFeeTier.tsx +++ b/packages/web/src/components/common/select-fee-tier/SelectFeeTier.tsx @@ -31,7 +31,7 @@ const SelectFeeTier: React.FC = ({ selected={feeTier === item} feeTier={item} pools={pools} - liquidityRange={feetierOfLiquidityMap[SwapFeeTierInfoMap[item].fee] || null} + liquidityRange={feetierOfLiquidityMap[SwapFeeTierInfoMap[item].fee]} onClick={() => onClickFeeTierItem(item)} /> ))} @@ -43,7 +43,7 @@ interface SelectFeeTierItemProps { selected: boolean; feeTier: SwapFeeTierType; pools: PoolModel[]; - liquidityRange: number | null; + liquidityRange: number | undefined | null; onClick: () => void; } @@ -58,7 +58,7 @@ const SelectFeeTierItem: React.FC = ({ }, [feeTier]); const rangeStr = useMemo(() => { - if (liquidityRange === null) { + if (liquidityRange === null || liquidityRange === undefined) { return "Not created"; } return `${liquidityRange}% Select`; diff --git a/packages/web/src/components/common/select-price-range-custom/SelectPriceRangeCustom.styles.ts b/packages/web/src/components/common/select-price-range-custom/SelectPriceRangeCustom.styles.ts index 0e4466fd1..05ccefdff 100644 --- a/packages/web/src/components/common/select-price-range-custom/SelectPriceRangeCustom.styles.ts +++ b/packages/web/src/components/common/select-price-range-custom/SelectPriceRangeCustom.styles.ts @@ -12,6 +12,34 @@ export const SelectPriceRangeCustomWrapper = styled.div` border-radius: 8px; margin-top: 8px; + .starting-price-wrapper { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 8px; + align-self: stretch; + + .sub-title { + color: ${({ theme }) => theme.color.text05}; + ${fonts.p4} + line-height: 22px; + } + + .starting-price-input { + display: flex; + padding: 16px; + flex-direction: column; + align-items: flex-start; + gap: 8px; + align-self: stretch; + text-align: right; + border-radius: 8px; + border: 1px solid ${({ theme }) => theme.color.border02}; + background: ${({ theme }) => theme.color.backgroundOpacity}; + ${fonts.body10} + } + } + .option-wrapper { display: flex; width: 100%; @@ -41,6 +69,14 @@ export const SelectPriceRangeCustomWrapper = styled.div` } } + .loading-wrapper { + display: flex; + width: 100%; + height: 220px; + justify-content: center; + align-items: center; + } + .current-price-wrapper { display: flex; flex-direction: column; diff --git a/packages/web/src/components/common/select-price-range-custom/SelectPriceRangeCustom.tsx b/packages/web/src/components/common/select-price-range-custom/SelectPriceRangeCustom.tsx index 36d488040..21ed3399d 100644 --- a/packages/web/src/components/common/select-price-range-custom/SelectPriceRangeCustom.tsx +++ b/packages/web/src/components/common/select-price-range-custom/SelectPriceRangeCustom.tsx @@ -1,157 +1,261 @@ -import React, { useCallback, useMemo, useState } from "react"; +import React, { useCallback, useEffect, useMemo, useState } from "react"; import IconRefresh from "../icons/IconRefresh"; import IconSwap from "../icons/IconSwap"; import SelectPriceRangeCutomController from "../select-price-range-cutom-controller/SelectPriceRangeCutomController"; import SelectTab from "../select-tab/SelectTab"; import { SelectPriceRangeCustomWrapper } from "./SelectPriceRangeCustom.styles"; -import { TokenInfo } from "@models/token/token-info"; -import { PoolTick } from "@containers/earn-add-liquidity-container/EarnAddLiquidityContainer"; -import BigNumber from "bignumber.js"; +import PoolSelectionGraph from "../pool-selection-graph/PoolSelectionGraph"; +import { TokenModel } from "@models/token/token-model"; +import { SelectPool } from "@hooks/pool/use-select-pool"; +import * as d3 from "d3"; +import { numberToFormat } from "@utils/string-utils"; +import { PriceRangeType } from "@constants/option.constant"; +import { toNumberFormat } from "@utils/number-utils"; +import LoadingSpinner from "../loading-spinner/LoadingSpinner"; export interface SelectPriceRangeCustomProps { - tokenA: TokenInfo | undefined; - tokenB: TokenInfo | undefined; - currentTick?: PoolTick; - ticks: PoolTick[]; + tokenA: TokenModel; + tokenB: TokenModel; + priceRangeType: PriceRangeType | null; + selectPool: SelectPool; + changeStartingPrice: (price: string) => void; } const SelectPriceRangeCustom: React.FC = ({ tokenA, tokenB, - currentTick, - ticks, + priceRangeType, + selectPool, + changeStartingPrice }) => { - const [minTick, setMinTick] = useState(); - const [maxTick, setMaxTick] = useState(); + const GRAPH_WIDTH = 388; + const GRAPH_HEIGHT = 160; + const [startingPriceValue, setStartingPriceValue] = useState(""); - const token0Symbol = useMemo(() => { - return tokenA?.symbol || ""; - }, [tokenA]); + function getPriceRange() { + const currentPrice = selectPool.currentPrice || 1; + if (selectPool.liquidityOfTickPoints.length === 0) { + const priceGap = currentPrice * 0.5; + return [currentPrice - priceGap, currentPrice + priceGap]; + } + const [minX, maxX] = d3.extent(selectPool.liquidityOfTickPoints.map(point => point[0])); + + const minPriceGap = (typeof selectPool.currentPrice === "number" && typeof minX === "number") ? Math.abs(selectPool.currentPrice - minX) : 0; + const maxPriceGap = (typeof selectPool.currentPrice === "number" && typeof maxX === "number") ? Math.abs(selectPool.currentPrice - maxX) : 0; + const priceGap = Math.min(maxPriceGap, minPriceGap); + return [currentPrice - priceGap, currentPrice + priceGap]; + } + + function getHeightRange() { + const [, maxY] = d3.extent(selectPool.liquidityOfTickPoints.map(point => point[1])); + return [0, maxY || 0]; + } + + /** D3 Variables */ + const defaultScaleX = d3 + .scaleLinear() + .domain(getPriceRange()) + .range([0, GRAPH_WIDTH]); + + const scaleX = defaultScaleX.copy(); + + const scaleY = d3 + .scaleLinear() + .domain(getHeightRange()) + .range([GRAPH_HEIGHT, 0]); + + const availSelect = Array.isArray(selectPool.liquidityOfTickPoints) && selectPool.renderState === "DONE"; - const token1Symbol = useMemo(() => { - return tokenB?.symbol || ""; - }, [tokenB]); + const comparedTokenA = selectPool.compareToken?.symbol !== tokenB.symbol; - const tabItems = useMemo(() => { - return [token0Symbol, token1Symbol]; - }, [token0Symbol, token1Symbol]); + const currentTokenA = useMemo(() => { + return comparedTokenA ? tokenA : tokenB; + }, [comparedTokenA, tokenA, tokenB]); - const currentPriceInfo = useMemo(() => { - if (!currentTick) { + const currentTokenB = useMemo(() => { + return comparedTokenA ? tokenB : tokenA; + }, [comparedTokenA, tokenA, tokenB]); + + const currentPriceStr = useMemo(() => { + if (!selectPool.currentPrice) { return "-"; } - const currentPrice = BigNumber(currentTick.price).toFixed(4); - return `${currentPrice} ${token0Symbol} per ${token1Symbol}`; - }, [currentTick, token0Symbol, token1Symbol]); - - const findPreviousTick = useCallback((tick: PoolTick) => { - const tickIndex = ticks.findIndex(item => item.tick === tick.tick); - if (tickIndex < 0) { - return undefined; - } - if (tickIndex < 1) { - return ticks[0]; - } - return ticks[tickIndex - 1]; - }, [ticks]); + const currentPrice = toNumberFormat(selectPool.currentPrice, 4); + return `${currentPrice} ${currentTokenA.symbol} per ${currentTokenB.symbol}`; + }, [currentTokenA.symbol, currentTokenB.symbol, selectPool.currentPrice]); - const findNextTick = useCallback((tick: PoolTick) => { - const tickIndex = ticks.findIndex(item => item.tick === tick.tick); - if (tickIndex < 0) { - return undefined; + const minPriceStr = useMemo(() => { + return numberToFormat(`${selectPool.minPrice || 0}`, 4); + }, [selectPool.minPrice]); + + const maxPriceStr = useMemo(() => { + if (selectPool.selectedFullRange) { + return "∞"; } - if (tickIndex >= ticks.length - 1) { - return ticks[ticks.length - 1]; + return numberToFormat(`${selectPool.maxPrice || 0}`, 4); + }, [selectPool.maxPrice, selectPool.selectedFullRange]); + + const onClickTabItem = useCallback((symbol: string) => { + const compareToken = tokenA.symbol === symbol ? tokenA : tokenB; + selectPool.setCompareToken(compareToken); + }, [selectPool, tokenA, tokenB]); + + const selectFullRange = useCallback(() => { + selectPool.setFullRange(true); + }, [selectPool]); + + function initPriceRange() { + if (selectPool.currentPrice && selectPool.feeTier && priceRangeType) { + let minRate = 0.5; + let maxRate = 1.5; + if (priceRangeType === "Active") { + if (selectPool.feeTier === "FEE_100") { + minRate = 0.995; + maxRate = 1.005; + } else { + minRate = 0.9; + maxRate = 1.1; + } + } else if (priceRangeType === "Passive") { + if (selectPool.feeTier === "FEE_100") { + minRate = 0.99; + maxRate = 0.01; + } else { + minRate = 0.5; + maxRate = 2; + } + } + selectPool.setMinPosition(selectPool.currentPrice * minRate); + selectPool.setMaxPosition(selectPool.currentPrice * maxRate); } - return ticks[tickIndex + 1]; - }, [ticks]); + } + + function resetRange() { + selectPool.resetRange(); + scaleX.domain(defaultScaleX.domain()); + initPriceRange(); + } - const onClickTabItem = useCallback(() => { - return; + const onChangeStartingPrice = useCallback((event: React.ChangeEvent) => { + const value = event.target.value; + setStartingPriceValue(value); }, []); - const decreaseMinPrice = useCallback(() => { - if (!minTick) { - return; - } - const tick = findPreviousTick(minTick); - setMinTick(tick); - return; - }, [findPreviousTick, minTick]); - - const increaseMinPrice = useCallback(() => { - if (!minTick) { - return; - } - const tick = findNextTick(minTick); - setMinTick(tick); - return; - }, [findNextTick, minTick]); - - const decreaseMaxPrice = useCallback(() => { - if (!maxTick) { - return; - } - const tick = findPreviousTick(maxTick); - setMaxTick(tick); - return; - }, [findPreviousTick, maxTick]); - - const increaseMaxPrice = useCallback(() => { - if (!maxTick) { - return; + const updateStartingPrice = useCallback(() => { + changeStartingPrice(startingPriceValue); + }, [startingPriceValue]); + + useEffect(() => { + selectPool.setCompareToken(tokenA); + }, []); + + useEffect(() => { + resetRange(); + }, [selectPool.currentPrice, selectPool.feeTier, priceRangeType, selectPool.liquidityOfTickPoints]); + + useEffect(() => { + defaultScaleX.domain(getPriceRange()); + scaleX.domain(defaultScaleX.domain()); + }, [selectPool.liquidityOfTickPoints]); + + useEffect(() => { + if (selectPool.currentPrice) { + selectPool.setFocusPosition(scaleX(selectPool.currentPrice)); } - const tick = findNextTick(maxTick); - setMaxTick(tick); - return; - }, [findNextTick, maxTick]); + }, [selectPool.currentPrice]); + + if (selectPool.renderState === "NONE") { + return <>; + } return ( + { + selectPool.isCreate && ( +
+ Starting Price + +
+ ) + }
- - - + + - + +
-
- Current Price - {currentPriceInfo} -
-
- {/* TBD: SelectLiquidityGraph */} -
+ { + selectPool.renderState === "LOADING" && ( +
+ +
+ ) + } + { + availSelect && ( + <> +
+ Current Price + {currentPriceStr} +
+
+ +
+ + ) + }
-
+
Reset Range
-
+
Full Price Range
diff --git a/packages/web/src/components/common/select-price-range-cutom-controller/SelectPriceRangeCutomController.tsx b/packages/web/src/components/common/select-price-range-cutom-controller/SelectPriceRangeCutomController.tsx index 8b323f0ba..0d754d522 100644 --- a/packages/web/src/components/common/select-price-range-cutom-controller/SelectPriceRangeCutomController.tsx +++ b/packages/web/src/components/common/select-price-range-cutom-controller/SelectPriceRangeCutomController.tsx @@ -1,6 +1,5 @@ import React, { useCallback, useMemo } from "react"; import { SelectPriceRangeCutomControllerWrapper } from "./SelectPriceRangeCutomController.styles"; -import BigNumber from "bignumber.js"; export interface SelectPriceRangeCutomControllerProps { title: string; @@ -24,13 +23,6 @@ const SelectPriceRangeCutomController: React.FC { - if (!current) { - return "-"; - } - return BigNumber(current).toFixed(4); - }, [current]); - const onClickDecrease = useCallback(() => { decrease(); }, [decrease]); @@ -47,7 +39,7 @@ const SelectPriceRangeCutomController: React.FC-
- {currentPriceStr} + {current}
+ diff --git a/packages/web/src/components/common/select-price-range/SelectPriceRange.tsx b/packages/web/src/components/common/select-price-range/SelectPriceRange.tsx index 08d4f94c2..91f75d1bf 100644 --- a/packages/web/src/components/common/select-price-range/SelectPriceRange.tsx +++ b/packages/web/src/components/common/select-price-range/SelectPriceRange.tsx @@ -5,18 +5,30 @@ import IconStrokeArrowRight from "@components/common/icons/IconStrokeArrowRight" import Tooltip from "@components/common/tooltip/Tooltip"; import { SelectPriceRangeItemWrapper, SelectPriceRangeWrapper } from "./SelectPriceRange.styles"; import { AddLiquidityPriceRage } from "@containers/earn-add-liquidity-container/EarnAddLiquidityContainer"; +import SelectPriceRangeCustom from "../select-price-range-custom/SelectPriceRangeCustom"; +import { TokenModel } from "@models/token/token-model"; +import { SelectPool } from "@hooks/pool/use-select-pool"; interface SelectPriceRangeProps { + tokenA: TokenModel | null; + tokenB: TokenModel | null; priceRanges: AddLiquidityPriceRage[]; priceRange: AddLiquidityPriceRage | null; changePriceRange: (priceRange: AddLiquidityPriceRage) => void; + changeStartingPrice: (price: string) => void; + selectPool: SelectPool } const SelectPriceRange: React.FC = ({ + tokenA, + tokenB, priceRanges, priceRange, changePriceRange, + changeStartingPrice, + selectPool }) => { + const selectedTokenPair = tokenA !== null && tokenB !== null; return ( @@ -31,6 +43,15 @@ const SelectPriceRange: React.FC = ({ /> ))}
+ {selectedTokenPair && ( + + )} ); }; diff --git a/packages/web/src/components/earn-add/earn-add-confirm-price-range-info/EarnAddConfirmPriceRangeInfo.stories.tsx b/packages/web/src/components/earn-add/earn-add-confirm-price-range-info/EarnAddConfirmPriceRangeInfo.stories.tsx index e92b5b3b7..065123fdf 100644 --- a/packages/web/src/components/earn-add/earn-add-confirm-price-range-info/EarnAddConfirmPriceRangeInfo.stories.tsx +++ b/packages/web/src/components/earn-add/earn-add-confirm-price-range-info/EarnAddConfirmPriceRangeInfo.stories.tsx @@ -8,9 +8,8 @@ export default { const priceRangeInfo = { minPrice: "123", - minPriceLable: "GNOS per ETH", maxPrice: "123", - maxPriceLable: "GNOS per ETH", + priceLabel: "GNOS per ETH", currentPrice: "11 ETH per GNOT", feeBoost: "x10.23", estimatedAPR: "N/A", diff --git a/packages/web/src/components/earn-add/earn-add-confirm-price-range-info/EarnAddConfirmPriceRangeInfo.tsx b/packages/web/src/components/earn-add/earn-add-confirm-price-range-info/EarnAddConfirmPriceRangeInfo.tsx index 49b801db8..e3ad1918a 100644 --- a/packages/web/src/components/earn-add/earn-add-confirm-price-range-info/EarnAddConfirmPriceRangeInfo.tsx +++ b/packages/web/src/components/earn-add/earn-add-confirm-price-range-info/EarnAddConfirmPriceRangeInfo.tsx @@ -1,12 +1,12 @@ -import React from "react"; +import React, { useMemo } from "react"; import { EarnAddConfirmPriceRangeInfoSection, EarnAddConfirmPriceRangeInfoWrapper } from "./EarnAddConfirmPriceRangeInfo.styles"; +import { numberToFormat } from "@utils/string-utils"; export interface EarnAddConfirmPriceRangeInfoProps { currentPrice: string; minPrice: string; - minPriceLable: string; maxPrice: string; - maxPriceLable: string; + priceLabel: string; feeBoost: string; estimatedAPR: string; } @@ -14,12 +14,15 @@ export interface EarnAddConfirmPriceRangeInfoProps { const EarnAddConfirmPriceRangeInfo: React.FC = ({ currentPrice, minPrice, - minPriceLable, maxPrice, - maxPriceLable, + priceLabel, feeBoost, estimatedAPR, }) => { + const currentPriceStr = useMemo(() => { + return `${numberToFormat(currentPrice, 4)} ${priceLabel}`; + }, [currentPrice, priceLabel]); + return (

Price Range

@@ -28,19 +31,19 @@ const EarnAddConfirmPriceRangeInfo: React.FC Min Price {minPrice} - {minPriceLable} + {priceLabel} Max Price {maxPrice} - {maxPriceLable} + {priceLabel}
Current Price: - {currentPrice} + {currentPriceStr}
Fee Boost: diff --git a/packages/web/src/components/earn-add/earn-add-confirm/EarnAddConfirm.stories.tsx b/packages/web/src/components/earn-add/earn-add-confirm/EarnAddConfirm.stories.tsx index 23ef5753c..f4b42bce1 100644 --- a/packages/web/src/components/earn-add/earn-add-confirm/EarnAddConfirm.stories.tsx +++ b/packages/web/src/components/earn-add/earn-add-confirm/EarnAddConfirm.stories.tsx @@ -52,9 +52,8 @@ const amountInfo = { const priceRangeInfo = { minPrice: "123", - minPriceLable: "GNOS per ETH", maxPrice: "123", - maxPriceLable: "GNOS per ETH", + priceLabel: "GNOS per ETH", currentPrice: "11 ETH per GNOT", feeBoost: "x10.23", estimatedAPR: "N/A", diff --git a/packages/web/src/components/earn-add/earn-add-confirm/EarnAddConfirm.tsx b/packages/web/src/components/earn-add/earn-add-confirm/EarnAddConfirm.tsx index bad3ed9b9..d08b9a109 100644 --- a/packages/web/src/components/earn-add/earn-add-confirm/EarnAddConfirm.tsx +++ b/packages/web/src/components/earn-add/earn-add-confirm/EarnAddConfirm.tsx @@ -24,9 +24,8 @@ export interface EarnAddConfirmProps { priceRangeInfo: { currentPrice: string; minPrice: string; - minPriceLable: string; maxPrice: string; - maxPriceLable: string; + priceLabel: string; feeBoost: string; estimatedAPR: string; }; diff --git a/packages/web/src/components/earn-add/earn-add-liquidity/EarnAddLiquidity.tsx b/packages/web/src/components/earn-add/earn-add-liquidity/EarnAddLiquidity.tsx index e8d30bdc8..6da04103f 100644 --- a/packages/web/src/components/earn-add/earn-add-liquidity/EarnAddLiquidity.tsx +++ b/packages/web/src/components/earn-add/earn-add-liquidity/EarnAddLiquidity.tsx @@ -14,6 +14,7 @@ import { PoolModel } from "@models/pool/pool-model"; import SelectPriceRange from "@components/common/select-price-range/SelectPriceRange"; import SelectPriceRangeSummary from "@components/common/select-price-range-summary/SelectPriceRangeSummary"; import { TokenModel } from "@models/token/token-model"; +import { SelectPool } from "@hooks/pool/use-select-pool"; interface EarnAddLiquidityProps { mode: AddLiquidityType; @@ -23,6 +24,8 @@ interface EarnAddLiquidityProps { changeTokenB: (token: TokenModel) => void; tokenAInput: TokenAmountInputModel; tokenBInput: TokenAmountInputModel; + changeTokenAAmount: (amount: string) => void; + changeTokenBAmount: (amount: string) => void; feetierOfLiquidityMap: { [key in string]: number }; feeTiers: SwapFeeTierType[]; feeTier: SwapFeeTierType | null; @@ -36,6 +39,8 @@ interface EarnAddLiquidityProps { currentTick: PoolTick | null; submitType: AddLiquiditySubmitType; submit: () => void; + selectPool: SelectPool; + changeStartingPrice: (price: string) => void; } const EarnAddLiquidity: React.FC = ({ @@ -45,6 +50,8 @@ const EarnAddLiquidity: React.FC = ({ changeTokenB, tokenAInput, tokenBInput, + changeTokenAAmount, + changeTokenBAmount, feetierOfLiquidityMap, feeTiers, feeTier, @@ -56,6 +63,8 @@ const EarnAddLiquidity: React.FC = ({ changePriceRange, submitType, submit, + selectPool, + changeStartingPrice }) => { const [openedSelectPair, setOpenedSelectPair] = useState(true); const [openedFeeTier, setOpenedFeeTier] = useState(true); @@ -190,12 +199,15 @@ const EarnAddLiquidity: React.FC = ({ /> )}
- {openedPriceRange && ( )} @@ -214,6 +226,8 @@ const EarnAddLiquidity: React.FC = ({ tokenBInput={tokenBInput} changeTokenA={changeTokenA} changeTokenB={changeTokenB} + changeTokenAAmount={changeTokenAAmount} + changeTokenBAmount={changeTokenBAmount} />
diff --git a/packages/web/src/constants/swap.constant.ts b/packages/web/src/constants/swap.constant.ts index 382dbfb81..3fbe45f55 100644 --- a/packages/web/src/constants/swap.constant.ts +++ b/packages/web/src/constants/swap.constant.ts @@ -5,4 +5,4 @@ export const MAX_PRICE_X96 = export const MIN_TICK = -887272 as const; export const MAX_TICK = 887272 as const; -export const X96 = 7.9228163e28 as const; +export const X96 = "79228162514264337593543950337" as const; diff --git a/packages/web/src/containers/earn-add-liquidity-container/EarnAddLiquidityContainer.tsx b/packages/web/src/containers/earn-add-liquidity-container/EarnAddLiquidityContainer.tsx index 900328d45..d6d60500e 100644 --- a/packages/web/src/containers/earn-add-liquidity-container/EarnAddLiquidityContainer.tsx +++ b/packages/web/src/containers/earn-add-liquidity-container/EarnAddLiquidityContainer.tsx @@ -3,6 +3,7 @@ import EarnAddLiquidity from "@components/earn-add/earn-add-liquidity/EarnAddLiq import { AddLiquiditySubmitType, PriceRangeType, + SwapFeeTierInfoMap, SwapFeeTierType, } from "@constants/option.constant"; import { useTokenAmountInput } from "@hooks/token/use-token-amount-input"; @@ -16,15 +17,11 @@ import { useAtom } from "jotai"; import { SwapState } from "@states/index"; import { useRouter } from "next/router"; import { usePool } from "@hooks/pool/use-pool"; +import { useSelectPool } from "@hooks/pool/use-select-pool"; +import { priceToNearTick, tickToPrice } from "@utils/swap-utils"; export interface AddLiquidityPriceRage { type: PriceRangeType; - range: { - minTick: number; - minPrice: string; - maxTick: number; - maxPrice: string; - }; apr?: string; } @@ -47,29 +44,22 @@ export const SWAP_FEE_TIERS: SwapFeeTierType[] = [ "FEE_10000", ]; -const TEMP_CUSTOM_PRICE_RANGE: AddLiquidityPriceRage = { - type: "Custom", - range: { - minTick: 6600, - maxTick: 10200, - minPrice: "1.2840093675402746", - maxPrice: "2.1169206358924533", - }, - apr: "0", -}; +const PRICE_RANGES: AddLiquidityPriceRage[] = [ + { type: "Active" }, + { type: "Passive" }, + { type: "Custom" } +]; const EarnAddLiquidityContainer: React.FC = () => { const [swapValue, setSwapValue] = useAtom(SwapState.swap); const { tokenA = null, tokenB = null, type = "EXACT_IN" } = swapValue; const { query } = useRouter(); - const [startPrice] = useState("130621891405341611593710811006"); const tokenAAmountInput = useTokenAmountInput(tokenA); const tokenBAmountInput = useTokenAmountInput(tokenB); + const [exactType, setExactType] = useState<"EXACT_IN" | "EXACT_OUT">("EXACT_IN"); const [swapFeeTier, setSwapFeeTier] = useState(null); - const [priceRanges] = useState([ - TEMP_CUSTOM_PRICE_RANGE, - ]); + const [priceRanges] = useState(PRICE_RANGES); const [priceRange, setPriceRange] = useState( null ); @@ -83,36 +73,70 @@ const EarnAddLiquidityContainer: React.FC = () => { } = useWallet(); const { slippage } = useSlippage(); const { updateTokenPrices } = useTokenData(); - const { pools, feetierOfLiquidityMap, createPool } = usePool({ tokenA, tokenB }); + const { pools, feetierOfLiquidityMap, createPool, addLiquidity } = usePool({ tokenA, tokenB }); + const [createOption, setCreateOption] = useState<{ startPrice: number | null, isCreate: boolean } | null>(null); + const selectPool = useSelectPool({ tokenA, tokenB, feeTier: swapFeeTier, isCreate: createOption?.isCreate, startPrice: createOption?.startPrice }); const { openModal: openConfirmModal } = useEarnAddLiquidityConfirmModal({ tokenA, tokenB, tokenAAmountInput, tokenBAmountInput, - currentPrice: startPrice, - priceRange, + selectPool, slippage, swapFeeTier, - createPool + createPool, + addLiquidity, }); - useEffect(() => { - console.log(feetierOfLiquidityMap); - }, [feetierOfLiquidityMap]); - useEffect(() => { if (query?.feeTier) { setSwapFeeTier(query?.feeTier as SwapFeeTierType); } }, [query]); + function calculateDeposiRatio(minPrice: number, maxPrice: number, currentPrice: number) { + const minPriceGap = currentPrice - minPrice; + const maxPriceGap = maxPrice - currentPrice; + const totalPriceGap = maxPrice - minPrice; + + + if (maxPriceGap < 0) { + return { + tokenARatio: 100, + tokenBRatio: 0, + }; + } + if (minPriceGap < 0) { + return { + tokenARatio: 100, + tokenBRatio: 0, + }; + } + const tokenARatio = (minPriceGap / totalPriceGap) * 100; + const tokenBRatio = 100 - tokenARatio; + return { + tokenARatio, + tokenBRatio, + }; + } + const priceRangeSummary: PriceRangeSummary = useMemo(() => { + let depositRatio = "-"; + if (selectPool.minPrice && selectPool.maxPrice && selectPool.currentPrice) { + const { tokenARatio, tokenBRatio } = calculateDeposiRatio(selectPool.minPrice, selectPool.maxPrice, selectPool.currentPrice); + const tokenARatioStr = BigNumber(tokenARatio).toFixed(1); + const tokenBRatioStr = BigNumber(tokenBRatio).toFixed(1); + const tokenASymbol = tokenA?.symbol === selectPool.compareToken?.symbol ? tokenA?.symbol : tokenB?.symbol; + const tokenBSymbol = tokenA?.symbol === selectPool.compareToken?.symbol ? tokenB?.symbol : tokenA?.symbol; + depositRatio = `${tokenARatioStr}% ${tokenASymbol} / ${tokenBRatioStr}% ${tokenBSymbol}`; + } + return { - depositRatio: "-", + depositRatio, feeBoost: "-", estimatedApr: "-", }; - }, []); + }, [selectPool.currentPrice, selectPool.maxPrice, selectPool.minPrice, tokenA?.symbol, tokenB?.symbol]); const submitType: AddLiquiditySubmitType = useMemo(() => { if (!connectedWallet) { @@ -155,8 +179,18 @@ const EarnAddLiquidityContainer: React.FC = () => { }, []); const selectSwapFeeTier = useCallback((swapFeeTier: SwapFeeTierType) => { + const fee = SwapFeeTierInfoMap[swapFeeTier].fee; + if (feetierOfLiquidityMap[fee] === undefined) { + setCreateOption({ + isCreate: true, + startPrice: null + }); + } else { + setCreateOption(null); + } + setPriceRange(priceRanges.find(range => range.type === "Active") || null); setSwapFeeTier(swapFeeTier); - }, []); + }, [feetierOfLiquidityMap]); const changePriceRange = useCallback((priceRange: AddLiquidityPriceRage) => { setPriceRange(priceRange); @@ -178,6 +212,87 @@ const EarnAddLiquidityContainer: React.FC = () => { })); }, [type]); + const changeStartingPrice = useCallback((price: string) => { + if (price === "") { + setCreateOption({ + isCreate: true, + startPrice: null + }); + return; + } + const priceNum = BigNumber(price).toNumber(); + if (Number.isNaN(priceNum)) { + setCreateOption({ + isCreate: true, + startPrice: null + }); + return; + } + const tick = priceToNearTick(priceNum, selectPool.tickSpacing); + const nearStartPrice = tickToPrice(tick); + setCreateOption({ + isCreate: true, + startPrice: nearStartPrice + }); + }, [selectPool.tickSpacing]); + + const updateTokenBAmountByTokenA = useCallback((amount: string) => { + if (!BigNumber(amount).isNaN()) { + if (!selectPool.currentPrice) { + return; + } + const ordered = tokenA?.symbol === selectPool.compareToken?.symbol; + const currentPrice = ordered ? selectPool.currentPrice : 1 / selectPool.currentPrice; + if (!selectPool.minPrice || !selectPool.maxPrice) { + tokenBAmountInput.changeAmount(BigNumber(amount).multipliedBy(currentPrice).toFixed(0)); + } else { + const { tokenARatio, tokenBRatio } = calculateDeposiRatio(selectPool.minPrice, selectPool.maxPrice, selectPool.currentPrice); + if (tokenARatio === 0 || tokenBRatio === 0) { + const isZero = ordered ? tokenBRatio === 0 : tokenARatio === 0; + isZero && tokenBAmountInput.changeAmount("0"); + return; + } + const ratio = ordered ? tokenBRatio / tokenARatio : tokenARatio / tokenBRatio; + tokenBAmountInput.changeAmount(BigNumber(amount).multipliedBy(currentPrice * ratio).toFixed(0)); + } + } + }, [selectPool.compareToken?.symbol, selectPool.currentPrice, selectPool.maxPrice, selectPool.minPrice, tokenA?.symbol, tokenBAmountInput]); + + const updateTokenAAmountByTokenB = useCallback((amount: string) => { + if (!BigNumber(amount).isNaN()) { + if (!selectPool.currentPrice) { + return; + } + const ordered = tokenB?.symbol === selectPool.compareToken?.symbol; + const currentPrice = ordered ? selectPool.currentPrice : 1 / selectPool.currentPrice; + if (!selectPool.minPrice || !selectPool.maxPrice) { + tokenAAmountInput.changeAmount(BigNumber(amount).multipliedBy(currentPrice).toFixed(0)); + } else { + const { tokenARatio, tokenBRatio } = calculateDeposiRatio(selectPool.minPrice, selectPool.maxPrice, selectPool.currentPrice); + if (tokenARatio === 0 || tokenBRatio === 0) { + const isZero = ordered ? tokenARatio === 0 : tokenBRatio === 0; + isZero && tokenAAmountInput.changeAmount("0"); + return; + } + const ratio = ordered ? tokenBRatio / tokenARatio : tokenARatio / tokenBRatio; + tokenAAmountInput.changeAmount(BigNumber(amount).multipliedBy(currentPrice * ratio).toFixed(0)); + } + } + }, [selectPool.compareToken?.symbol, selectPool.currentPrice, selectPool.maxPrice, selectPool.minPrice, tokenAAmountInput, tokenB?.symbol]); + + + const changeTokenAAmount = useCallback((amount: string) => { + tokenAAmountInput.changeAmount(amount); + setExactType("EXACT_IN"); + updateTokenBAmountByTokenA(amount); + }, [tokenAAmountInput, updateTokenBAmountByTokenA]); + + const changeTokenBAmount = useCallback((amount: string) => { + tokenBAmountInput.changeAmount(amount); + setExactType("EXACT_OUT"); + updateTokenAAmountByTokenB(amount); + }, [tokenBAmountInput, updateTokenAAmountByTokenB]); + const submit = useCallback(() => { if (submitType === "CONNECT_WALLET") { connectAdenaClient(); @@ -205,6 +320,14 @@ const EarnAddLiquidityContainer: React.FC = () => { switchNetwork, ]); + useEffect(() => { + if (exactType === "EXACT_IN") { + updateTokenBAmountByTokenA(tokenAAmountInput.amount); + } else { + updateTokenAAmountByTokenB(tokenBAmountInput.amount); + } + }, [selectPool.currentPrice, selectPool.minPrice, selectPool.maxPosition]); + return ( { tokenBInput={tokenBAmountInput} changeTokenA={changeTokenA} changeTokenB={changeTokenB} + changeTokenAAmount={changeTokenAAmount} + changeTokenBAmount={changeTokenBAmount} feeTiers={SWAP_FEE_TIERS} feetierOfLiquidityMap={feetierOfLiquidityMap} feeTier={swapFeeTier} @@ -227,6 +352,8 @@ const EarnAddLiquidityContainer: React.FC = () => { currentTick={null} submitType={submitType} submit={submit} + selectPool={selectPool} + changeStartingPrice={changeStartingPrice} /> ); }; diff --git a/packages/web/src/hooks/common/use-background.tsx b/packages/web/src/hooks/common/use-background.tsx index c0e704bc5..a940d395f 100644 --- a/packages/web/src/hooks/common/use-background.tsx +++ b/packages/web/src/hooks/common/use-background.tsx @@ -2,15 +2,16 @@ import { useEffect } from "react"; import { useWallet } from "@hooks/wallet/use-wallet"; import { useAtom } from "jotai"; import { WalletState } from "@states/index"; +import { useRouter } from "next/router"; export const useBackground = () => { - + const router = useRouter(); const [walletClient] = useAtom(WalletState.client); const { initSession, connectAccount, updateWalletEvents } = useWallet(); useEffect(() => { initSession(); - }, []); + }, [router.route]); useEffect(() => { if (walletClient) { diff --git a/packages/web/src/hooks/pool/use-pool.tsx b/packages/web/src/hooks/pool/use-pool.tsx index 299d3b912..3e64829f5 100644 --- a/packages/web/src/hooks/pool/use-pool.tsx +++ b/packages/web/src/hooks/pool/use-pool.tsx @@ -1,5 +1,4 @@ import { SwapFeeTierType } from "@constants/option.constant"; -import { AddLiquidityPriceRage } from "@containers/earn-add-liquidity-container/EarnAddLiquidityContainer"; import { useGnoswapContext } from "@hooks/common/use-gnoswap-context"; import { useWallet } from "@hooks/wallet/use-wallet"; import { PoolModel } from "@models/pool/pool-model"; @@ -40,14 +39,16 @@ export const usePool = ({ tokenBAmount, swapFeeTier, startPrice, - priceRange, + minTick, + maxTick, slippage, }: { tokenAAmount: string; tokenBAmount: string; swapFeeTier: SwapFeeTierType; startPrice: string; - priceRange: AddLiquidityPriceRage; + minTick: number; + maxTick: number; slippage: number; }) => { if (!tokenA || !tokenB || !account) { @@ -60,8 +61,43 @@ export const usePool = ({ tokenBAmount, feeTier: swapFeeTier, startPrice, - minTick: priceRange.range.minTick, - maxTick: priceRange.range.maxTick, + minTick, + maxTick, + slippage, + caller: account.address + }).catch(e => { + console.error(e); + return null; + }); + return hash; + }, [account, poolRepository, tokenA, tokenB]); + + const addLiquidity = useCallback(async ({ + tokenAAmount, + tokenBAmount, + swapFeeTier, + minTick, + maxTick, + slippage, + }: { + tokenAAmount: string; + tokenBAmount: string; + swapFeeTier: SwapFeeTierType; + minTick: number; + maxTick: number; + slippage: number; + }) => { + if (!tokenA || !tokenB || !account) { + return null; + } + const hash = await poolRepository.addLiquidity({ + tokenA, + tokenB, + tokenAAmount, + tokenBAmount, + feeTier: swapFeeTier, + minTick, + maxTick, slippage, caller: account.address }).catch(e => { @@ -95,6 +131,7 @@ export const usePool = ({ return { pools: currentPools, feetierOfLiquidityMap, - createPool + createPool, + addLiquidity, }; }; \ No newline at end of file diff --git a/packages/web/src/hooks/pool/use-select-pool.tsx b/packages/web/src/hooks/pool/use-select-pool.tsx new file mode 100644 index 000000000..45f87da7e --- /dev/null +++ b/packages/web/src/hooks/pool/use-select-pool.tsx @@ -0,0 +1,274 @@ +import { SwapFeeTierInfoMap, SwapFeeTierType } from "@constants/option.constant"; +import { TokenModel } from "@models/token/token-model"; +import { useCallback, useEffect, useMemo, useState } from "react"; +import { useGnoswapContext } from "@hooks/common/use-gnoswap-context"; +import { PoolInfoModel } from "@models/pool/pool-info-model"; +import { priceToNearTick, tickToPrice } from "@utils/swap-utils"; +import { MAX_TICK, MIN_TICK } from "@constants/swap.constant"; + +type RenderState = "NONE" | "CREATE" | "LOADING" | "DONE"; + +interface Props { + tokenA: TokenModel | null; + tokenB: TokenModel | null; + feeTier: SwapFeeTierType | null; + isCreate?: boolean; + startPrice?: number | null, +} + +export interface SelectPool { + isCreate: boolean; + renderState: RenderState; + startPrice?: number | null; + feeTier: SwapFeeTierType | null; + tickSpacing: number; + minPosition: number | null; + setMinPosition: (position: number | null) => void; + maxPosition: number | null; + setMaxPosition: (position: number | null) => void; + compareToken: TokenModel | null; + setCompareToken: (token: TokenModel | null) => void; + currentPrice: number | null; + minPrice: number | null; + maxPrice: number | null; + depositRatio: number | null; + feeBoost: number | null; + estimatedAPR: number | null; + increaseMinTick: () => void; + decreaseMinTick: () => void; + increaseMaxTick: () => void; + decreaseMaxTick: () => void; + selectedFullRange: boolean; + setFullRange: (fullRange: boolean) => void; + resetRange: () => void; + focusPosition: number; + setFocusPosition: (position: number) => void; + zoomLevel: number; + zoomIn: () => void; + zoomOut: () => void; + liquidityOfTickPoints: [number, number][]; +} + + +export const useSelectPool = ({ + tokenA, + tokenB, + feeTier, + isCreate = false, + startPrice, +}: Props) => { + const [fullRange, setFullRange] = useState(false); + const [focusPosition, setFocusPosition] = useState(0); + const [zoomLevel, setZoomLevel] = useState(10); + const { poolRepository } = useGnoswapContext(); + const [minPosition, setMinPosition] = useState(null); + const [maxPosition, setMaxPosition] = useState(null); + const [compareToken, setCompareToken] = useState(tokenA); + const [poolInfo, setPoolInfo] = useState(null); + + const renderState: RenderState = useMemo(() => { + if (!tokenA || !tokenB || !feeTier) { + return "NONE"; + } + if (isCreate && startPrice === null) { + return "CREATE"; + } + if (!poolInfo) { + return "LOADING"; + } + return "DONE"; + }, [feeTier, isCreate, poolInfo, startPrice, tokenA, tokenB]); + + const liquidityOfTickPoints: [number, number][] = useMemo(() => { + if (!poolInfo || poolInfo.ticks.length === 0) { + return [] as [number, number][]; + } + const result: [number, number][] = poolInfo.ticks.sort((t1, t2) => t1 - t2) + .map(tick => { + const height = poolInfo.positions + .filter(p => p.tickLower <= tick && p.tickUpper > tick) + .reduce((acc, cur) => acc + cur.liquidityOfTick, 0); + const tickPrice = tickToPrice(tick); + return [tickPrice, height]; + }); + return [[0, 0], ...result]; + }, [poolInfo]); + + const price = useMemo(() => { + if (!poolInfo) { + return 0; + } + return poolInfo.price; + }, [poolInfo]); + + const minPrice = useMemo(() => { + return minPosition; + }, [minPosition]); + + const maxPrice = useMemo(() => { + return maxPosition; + }, [maxPosition]); + + const depositRatio = useMemo(() => { + return 10; + }, []); + + const feeBoost = useMemo(() => { + return null; + }, []); + + const estimatedAPR = useMemo(() => { + return null; + }, []); + + const tickSpacing = useMemo(() => poolInfo?.tickSpacing || 2, [poolInfo?.tickSpacing]); + + const increaseMinTick = useCallback(() => { + if (!poolInfo || !minPrice) { + return; + } + const tickSpacing = poolInfo.tickSpacing; + const nearTick = priceToNearTick(minPrice, tickSpacing); + if (nearTick < MAX_TICK - tickSpacing) { + setMinPosition(tickToPrice(nearTick + tickSpacing)); + } + }, [minPrice, poolInfo]); + + const decreaseMinTick = useCallback(() => { + if (!poolInfo || !minPrice) { + return; + } + const tickSpacing = poolInfo.tickSpacing; + const nearTick = priceToNearTick(minPrice, tickSpacing); + if (nearTick > MIN_TICK + tickSpacing) { + setMinPosition(tickToPrice(nearTick - tickSpacing)); + } + }, [minPrice, poolInfo]); + + const increaseMaxTick = useCallback(() => { + if (!poolInfo || !maxPrice) { + return; + } + const tickSpacing = poolInfo.tickSpacing; + const nearTick = priceToNearTick(maxPrice, tickSpacing); + if (nearTick < MAX_TICK - tickSpacing) { + setMaxPosition(tickToPrice(nearTick + tickSpacing)); + } + }, [maxPrice, poolInfo]); + + const decreaseMaxTick = useCallback(() => { + if (!poolInfo || !maxPrice) { + return; + } + const tickSpacing = poolInfo.tickSpacing; + const nearTick = priceToNearTick(maxPrice, tickSpacing); + if (nearTick > MIN_TICK + tickSpacing) { + setMaxPosition(tickToPrice(nearTick - tickSpacing)); + } + }, [maxPrice, poolInfo]); + + const resetRange = useCallback(() => { + setZoomLevel(10); + setFullRange(false); + setMinPosition(null); + setMaxPosition(null); + }, []); + + const zoomIn = useCallback(() => { + if (zoomLevel > 1) { + setZoomLevel(zoomLevel - 1); + } + }, [zoomLevel]); + + const zoomOut = useCallback(() => { + if (zoomLevel < 20) { + setZoomLevel(zoomLevel + 1); + } + }, [zoomLevel]); + + useEffect(() => { + if (!tokenA || !tokenB || !feeTier) { + return; + } + setPoolInfo(null); + + if (isCreate) { + if (!startPrice) { + setPoolInfo(null); + return; + } + const poolInfo: PoolInfoModel = { + poolPath: "", + tokenABalance: 0, + tokenBBalance: 0, + tickSpacing: SwapFeeTierInfoMap[feeTier].tickSpacing, + maxLiquidityPerTick: 0, + price: startPrice, + sqrtPriceX96: 0, + tick: 0, + feeProtocol: 0, + feeGrowthGlobal0X128: 0, + feeGrowthGlobal1X128: 0, + tokenAProtocolFee: 0, + tokenBProtocolFee: 0, + liquidity: 0, + ticks: [], + tickBitmaps: [], + positions: [] + }; + setPoolInfo(poolInfo); + } else { + const tokenPair = [tokenA.symbol.toLowerCase(), tokenB.symbol.toLowerCase()].sort(); + const poolPath = `${tokenPair.join("_")}_${SwapFeeTierInfoMap[feeTier].fee}`; + const reverse = [tokenA?.path, tokenB?.path].sort().findIndex(path => path === compareToken?.path) === 1; + + poolRepository.getPoolInfoByPoolPath(poolPath).then(poolInfo => { + const changedPoolInfo = reverse === false ? poolInfo : { + ...poolInfo, + price: 1 / poolInfo.price, + ticks: poolInfo.ticks.map(tick => tick * -1), + positions: poolInfo.positions.map(position => ({ + ...position, + tickLower: position.tickUpper * -1, + tickUpper: position.tickLower * -1, + })) + }; + setPoolInfo(changedPoolInfo); + }).catch(() => null); + } + }, [poolRepository, feeTier, tokenA, tokenB, compareToken, isCreate, startPrice]); + + + + return { + renderState, + feeTier, + tickSpacing, + minPosition, + setMinPosition, + maxPosition, + setMaxPosition, + compareToken, + setCompareToken, + currentPrice: price, + minPrice, + maxPrice, + depositRatio, + feeBoost, + estimatedAPR, + increaseMinTick, + decreaseMinTick, + increaseMaxTick, + decreaseMaxTick, + selectedFullRange: fullRange, + setFullRange, + resetRange, + focusPosition, + setFocusPosition, + zoomLevel, + zoomIn, + zoomOut, + liquidityOfTickPoints, + isCreate + }; +}; \ No newline at end of file diff --git a/packages/web/src/hooks/token/use-earn-add-liquidity-confirm-modal.tsx b/packages/web/src/hooks/token/use-earn-add-liquidity-confirm-modal.tsx index 1dc24bc8e..bb3ea4e7d 100644 --- a/packages/web/src/hooks/token/use-earn-add-liquidity-confirm-modal.tsx +++ b/packages/web/src/hooks/token/use-earn-add-liquidity-confirm-modal.tsx @@ -1,21 +1,21 @@ import EarnAddConfirm from "@components/earn-add/earn-add-confirm/EarnAddConfirm"; import { SwapFeeTierInfoMap, SwapFeeTierType } from "@constants/option.constant"; -import { AddLiquidityPriceRage } from "@containers/earn-add-liquidity-container/EarnAddLiquidityContainer"; import useNavigate from "@hooks/common/use-navigate"; import { TokenModel } from "@models/token/token-model"; import { CommonState } from "@states/index"; import { useAtom } from "jotai"; import { useCallback, useMemo } from "react"; import { TokenAmountInputModel } from "./use-token-amount-input"; -import { getCurrentPriceByRaw } from "@utils/swap-utils"; +import { priceToNearTick } from "@utils/swap-utils"; +import { SelectPool } from "@hooks/pool/use-select-pool"; +import { numberToFormat } from "@utils/string-utils"; export interface EarnAddLiquidityConfirmModalProps { tokenA: TokenModel | null; tokenB: TokenModel | null; tokenAAmountInput: TokenAmountInputModel; tokenBAmountInput: TokenAmountInputModel; - currentPrice: string; - priceRange: AddLiquidityPriceRage | null; + selectPool: SelectPool; slippage: number; swapFeeTier: SwapFeeTierType | null; createPool: ( @@ -24,7 +24,18 @@ export interface EarnAddLiquidityConfirmModalProps { tokenBAmount: string; swapFeeTier: SwapFeeTierType; startPrice: string; - priceRange: AddLiquidityPriceRage; + minTick: number; + maxTick: number; + slippage: number; + } + ) => Promise; + addLiquidity: ( + params: { + tokenAAmount: string; + tokenBAmount: string; + swapFeeTier: SwapFeeTierType; + minTick: number; + maxTick: number; slippage: number; } ) => Promise; @@ -38,11 +49,11 @@ export const useEarnAddLiquidityConfirmModal = ({ tokenB, tokenAAmountInput, tokenBAmountInput, - priceRange, - currentPrice, + selectPool, slippage, swapFeeTier, createPool, + addLiquidity, }: EarnAddLiquidityConfirmModalProps): SelectTokenModalModel => { const [, setOpenedModal] = useAtom(CommonState.openedModal); const [, setModalContent] = useAtom(CommonState.modalContent); @@ -67,21 +78,29 @@ export const useEarnAddLiquidityConfirmModal = ({ }; }, [swapFeeTier, tokenA, tokenAAmountInput, tokenBAmountInput, tokenB]); + const priceLabel = useMemo(() => { + if (!selectPool.compareToken || !tokenA || !tokenB) { + return "-"; + } + const tokenASymbol = selectPool.compareToken?.symbol === tokenA?.symbol ? tokenA?.symbol : tokenB?.symbol; + const tokenBSymbol = selectPool.compareToken?.symbol === tokenA?.symbol ? tokenB?.symbol : tokenA?.symbol; + return `${tokenASymbol} per ${tokenBSymbol}`; + }, [selectPool.compareToken, tokenA, tokenB]); + const priceRangeInfo = useMemo(() => { - if (!priceRange) { + if (!selectPool) { return null; } return { - currentPrice: getCurrentPriceByRaw(currentPrice).toFixed(), - minPrice: `${priceRange.range.minTick}`, - minPriceLable: priceRange.range.minPrice, - maxPrice: `${priceRange.range.maxTick}`, - maxPriceLable: priceRange.range.maxPrice, + currentPrice: `${selectPool.currentPrice}`, + minPrice: numberToFormat(`${selectPool.minPrice || 0}`, 4), + maxPrice: numberToFormat(`${selectPool.minPrice || 0}`, 4), + priceLabel, feeBoost: "-", estimatedAPR: "N/A", }; - }, [currentPrice, priceRange]); + }, [priceLabel, selectPool]); const feeInfo = useMemo(() => { return { @@ -111,18 +130,34 @@ export const useEarnAddLiquidityConfirmModal = ({ }, [close, navigator]); const confirm = useCallback(() => { - if (!tokenA || !tokenB || !priceRange || !swapFeeTier) { + if (!tokenA || !tokenB || !swapFeeTier || !selectPool.minPrice || !selectPool.maxPrice) { + return; + } + const minTick = priceToNearTick(selectPool.minPrice, selectPool.tickSpacing); + const maxTick = priceToNearTick(selectPool.maxPrice, selectPool.tickSpacing); + + if (selectPool.isCreate) { + createPool({ + tokenAAmount: tokenAAmountInput.amount, + tokenBAmount: tokenBAmountInput.amount, + minTick, + maxTick, + slippage, + startPrice: `${selectPool.startPrice || 1}`, + swapFeeTier, + }).then(result => result && moveEarn()); return; } - createPool({ + + addLiquidity({ tokenAAmount: tokenAAmountInput.amount, tokenBAmount: tokenBAmountInput.amount, - priceRange, + minTick, + maxTick, slippage, - startPrice: currentPrice, swapFeeTier, }).then(result => result && moveEarn()); - }, [createPool, currentPrice, moveEarn, priceRange, slippage, swapFeeTier, tokenA, tokenAAmountInput.amount, tokenB, tokenBAmountInput.amount]); + }, [selectPool.isCreate, selectPool.maxPrice, selectPool.minPrice, selectPool.startPrice, selectPool.tickSpacing, slippage, swapFeeTier, tokenA, tokenAAmountInput.amount, tokenB, tokenBAmountInput.amount]); const openModal = useCallback(() => { if (!amountInfo || !priceRangeInfo) { diff --git a/packages/web/src/hooks/wallet/use-wallet.ts b/packages/web/src/hooks/wallet/use-wallet.ts index 9f0b62829..1bccca69b 100644 --- a/packages/web/src/hooks/wallet/use-wallet.ts +++ b/packages/web/src/hooks/wallet/use-wallet.ts @@ -44,30 +44,27 @@ export const useWallet = () => { function initSession() { const connectedBySession = accountRepository.isConnectedWalletBySession(); - if (connectedBySession) { + if (connectedBySession && walletClient === null) { connectAdenaClient(); } } - const switchNetwork = useCallback( - async () => { - const res = await accountRepository.switchNetwork(CHAIN_ID); - if (res.code === 0) { - const account = await accountRepository.getAccount(); - setWalletAccount(account); - accountRepository.setConnectedWallet(true); - } - }, - [accountRepository, setWalletAccount] - ); - - const connectAdenaClient = useCallback(() => { + function connectAdenaClient() { const adena = AdenaClient.createAdenaClient(); if (adena !== null) { adena.initAdena(); } setWalletClient(adena); - }, [setWalletClient]); + } + + const switchNetwork = async () => { + const res = await accountRepository.switchNetwork(CHAIN_ID); + if (res.code === 0) { + const account = await accountRepository.getAccount(); + setWalletAccount(account); + accountRepository.setConnectedWallet(true); + } + }; const connectAccount = useCallback(async () => { const established = await accountRepository @@ -109,12 +106,11 @@ export const useWallet = () => { } const isSwitchNetwork = useMemo(() => { - if (!walletAccount) return true; const network = NetworkData.find( network => network.chainId === walletAccount.chainId, ); - + return network ? false : true; }, [walletAccount]); diff --git a/packages/web/src/models/pool/mapper/pool-info-mapper.ts b/packages/web/src/models/pool/mapper/pool-info-mapper.ts index 04887bd7d..fd0a11afd 100644 --- a/packages/web/src/models/pool/mapper/pool-info-mapper.ts +++ b/packages/web/src/models/pool/mapper/pool-info-mapper.ts @@ -7,27 +7,43 @@ export class PoolInfoMapper { if (!response) { throw new Error("mapper error"); } - const sqrtPriceX96 = response.response.data.sqrt_price_x96; + const data = response.response.data; + const sqrtPriceX96 = data.sqrt_price_x96; const price = rawByX96(sqrtPriceX96); + const tickSpacing = data.tick_spacing; return { - poolPath: response.response.data.pool_path, - tokenABalance: response.response.data.token0_balance, - tokenBBalance: response.response.data.token1_balance, - tickSpacing: response.response.data.tick_spacing, - maxLiquidityPerTick: response.response.data.max_liquidity_per_tick, + poolPath: data.pool_path, + tokenABalance: data.token0_balance, + tokenBBalance: data.token1_balance, + tickSpacing, + maxLiquidityPerTick: data.max_liquidity_per_tick, price, sqrtPriceX96, - tick: response.response.data.tick, - feeProtocol: response.response.data.fee_protocol, - feeGrowthGlobal0X128: response.response.data.fee_growth_global0_x128, - feeGrowthGlobal1X128: response.response.data.fee_growth_global1_x128, - tokenAProtocolFee: response.response.data.token0_protocol_fee, - tokenBProtocolFee: response.response.data.token1_protocol_fee, - liquidity: response.response.data.liquidity, - ticks: response.response.data.ticks, - tickBitmaps: response.response.data.tick_bitmaps, - positions: [] as any, + tick: data.tick, + feeProtocol: data.fee_protocol, + feeGrowthGlobal0X128: data.fee_growth_global0_x128, + feeGrowthGlobal1X128: data.fee_growth_global1_x128, + tokenAProtocolFee: data.token0_protocol_fee, + tokenBProtocolFee: data.token1_protocol_fee, + liquidity: data.liquidity, + ticks: data.ticks, + tickBitmaps: data.tick_bitmaps, + positions: data.positions.map(p => { + const tickLower = p.tick_lower; + const tickUpper = p.tick_upper; + const liquidityOfTick = + p.liquidity / (1 + (tickUpper - tickLower) / tickSpacing); + return { + owner: p.owner, + tokenAOwed: p.token0_owed, + tokenBOwed: p.token1_owed, + tickLower, + tickUpper, + liquidityOfTick, + liquidity: p.liquidity, + }; + }), }; } } diff --git a/packages/web/src/models/pool/pool-info-model.ts b/packages/web/src/models/pool/pool-info-model.ts index fbf5214c4..ea1744ac4 100644 --- a/packages/web/src/models/pool/pool-info-model.ts +++ b/packages/web/src/models/pool/pool-info-model.ts @@ -31,19 +31,19 @@ export interface PoolInfoModel { tickBitmaps: number[]; - positions: [ - { - owner: string; + positions: { + owner: string; - tickLower: number; + tokenAOwed: number; - tickUpper: number; + tokenBOwed: number; - liquidity: number; + tickLower: number; - tokenAOwed: number; + tickUpper: number; - tokenBOwed: number; - }, - ]; + liquidityOfTick: number; + + liquidity: number; + }[]; } diff --git a/packages/web/src/providers/gnoswap-service-provider/GnoswapServiceProvider.tsx b/packages/web/src/providers/gnoswap-service-provider/GnoswapServiceProvider.tsx index 720c938db..e0fc72fb0 100644 --- a/packages/web/src/providers/gnoswap-service-provider/GnoswapServiceProvider.tsx +++ b/packages/web/src/providers/gnoswap-service-provider/GnoswapServiceProvider.tsx @@ -8,7 +8,7 @@ import { StakingRepository, StakingRepositoryMock } from "@repositories/staking" import { SwapRepository } from "@repositories/swap"; import { TokenRepository } from "@repositories/token"; import { TokenRepositoryImpl } from "@repositories/token/token-repository-impl"; -import { createContext, useEffect, useMemo, useState } from "react"; +import { createContext, useLayoutEffect, useMemo, useState } from "react"; import { useAtom } from "jotai"; import { CommonState, WalletState } from "@states/index"; import { GnoProvider, GnoWSProvider } from "@gnolang/gno-js-client"; @@ -44,22 +44,6 @@ const GnoswapServiceProvider: React.FC = ({ const [rpcProvider, setRPCProvider] = useState(null); - useEffect(() => { - if (window) { - setLocalStorageClient(WebStorageClient.createLocalStorageClient()); - setSessionStorageClient(WebStorageClient.createSessionStorageClient()); - } - }, []); - - useEffect(() => { - const defaultChainId = process.env.NEXT_PUBLIC_DEFAULT_CHAIN_ID || ""; - const currentNetwork = network || ChainNetworkInfos.find(info => info.chainId === defaultChainId); - if (currentNetwork) { - const provider = new GnoWSProvider(currentNetwork.wsUrl, 5 * 1000); - provider.waitForOpenConnection().then(() => setRPCProvider(provider)); - } - }, [network]); - const accountRepository = useMemo(() => { return new AccountRepositoryImpl(walletClient, networkClient, localStorageClient, sessionStorageClient); }, [walletClient, networkClient, localStorageClient, sessionStorageClient]); @@ -84,6 +68,34 @@ const GnoswapServiceProvider: React.FC = ({ return new TokenRepositoryImpl(networkClient, localStorageClient); }, [localStorageClient, networkClient]); + async function initNetwork() { + const defaultChainId = process.env.NEXT_PUBLIC_DEFAULT_CHAIN_ID || ""; + const currentNetwork = network || ChainNetworkInfos.find(info => info.chainId === defaultChainId); + if (currentNetwork) { + try { + const provider = new GnoWSProvider(currentNetwork.wsUrl, 5 * 1000); + await provider.waitForOpenConnection(); + setRPCProvider(provider); + return true; + } catch (error) { + console.log(error); + } + } + setRPCProvider(null); + return false; + } + + useLayoutEffect(() => { + if (window) { + setLocalStorageClient(WebStorageClient.createLocalStorageClient()); + setSessionStorageClient(WebStorageClient.createSessionStorageClient()); + } + }, []); + + useLayoutEffect(() => { + initNetwork(); + }, [network]); + return ( => { + if (this.walletClient === null) { + throw new CommonError("FAILED_INITIALIZE_WALLET"); + } + const { + tokenA, + tokenB, + feeTier, + tokenAAmount, + tokenBAmount, + minTick, + maxTick, + slippage, + caller, + } = request; + const gasFee = 1; + const gasWanted = 2000000; + const result = await this.walletClient.sendTransaction({ + messages: [ + PoolRepositoryImpl.makeApproveTokenMessage( + tokenA, + tokenAAmount, + caller, + ), + PoolRepositoryImpl.makeApproveTokenMessage( + tokenB, + tokenBAmount, + caller, + ), + PoolRepositoryImpl.makeAddLiquidityMessage( + tokenA, + tokenB, + feeTier, + minTick, + maxTick, + tokenAAmount, + tokenBAmount, + slippage, + caller, + ), + ], + gasFee, + gasWanted, + }); + const response = result.data as SendTransactionSuccessResponse; + if (!response.hash) { + throw new Error(`${result}`); + } + return response.hash; + }; + private static makeCreatePoolMessage( tokenA: TokenModel, tokenB: TokenModel, @@ -156,12 +211,15 @@ export class PoolRepositoryImpl implements PoolRepository { const tokenAPath = tokenA.symbol.toLowerCase(); const tokenBPath = tokenB.symbol.toLowerCase(); const fee = `${SwapFeeTierInfoMap[feeTier].fee}`; + const currentTick = priceToNearTick(BigNumber(startPrice).toNumber(), SwapFeeTierInfoMap[feeTier].tickSpacing); + const currentPriceX96 = BigNumber(tickToPrice(currentTick)).multipliedBy(X96).toFixed(0); + return { caller, send: "", pkg_path: POOL_PATH, func: "CreatePool", - args: [tokenAPath, tokenBPath, fee, startPrice], + args: [tokenAPath, tokenBPath, fee, currentPriceX96], }; } @@ -196,6 +254,7 @@ export class PoolRepositoryImpl implements PoolRepository { const tokenAPath = tokenA.symbol.toLowerCase(); const tokenBPath = tokenB.symbol.toLowerCase(); const fee = `${SwapFeeTierInfoMap[feeTier].fee}`; + const slippageRatio = 0; const deadline = "7282571140"; return { caller, @@ -210,8 +269,8 @@ export class PoolRepositoryImpl implements PoolRepository { `${maxTick}`, tokenAAmount, tokenBAmount, - "0", - "0", + BigNumber(tokenAAmount).multipliedBy(slippageRatio).toFixed(0), + BigNumber(tokenBAmount).multipliedBy(slippageRatio).toFixed(0), deadline, ], }; diff --git a/packages/web/src/repositories/pool/pool-repository-mock.ts b/packages/web/src/repositories/pool/pool-repository-mock.ts index 70b6909c5..71dcecdc1 100644 --- a/packages/web/src/repositories/pool/pool-repository-mock.ts +++ b/packages/web/src/repositories/pool/pool-repository-mock.ts @@ -21,4 +21,8 @@ export class PoolRepositoryMock implements PoolRepository { createPool = async (): Promise => { return "hash"; }; + + addLiquidity = async (): Promise => { + return "hash"; + }; } diff --git a/packages/web/src/repositories/pool/pool-repository.ts b/packages/web/src/repositories/pool/pool-repository.ts index 6b65da72b..efb699b05 100644 --- a/packages/web/src/repositories/pool/pool-repository.ts +++ b/packages/web/src/repositories/pool/pool-repository.ts @@ -1,6 +1,7 @@ import { PoolInfoModel } from "@models/pool/pool-info-model"; import { CreatePoolRequest } from "./request/create-pool-request"; import { PoolDetailResponse, PoolListResponse } from "./response"; +import { AddLiquidityRequest } from "./request/add-liquidity-request"; export interface PoolRepository { getPools: () => Promise; @@ -10,4 +11,6 @@ export interface PoolRepository { getPoolDetailByPoolId: (poolId: string) => Promise; createPool: (request: CreatePoolRequest) => Promise; + + addLiquidity: (request: AddLiquidityRequest) => Promise; } diff --git a/packages/web/src/repositories/pool/request/add-liquidity-request.ts b/packages/web/src/repositories/pool/request/add-liquidity-request.ts new file mode 100644 index 000000000..4ccf48d25 --- /dev/null +++ b/packages/web/src/repositories/pool/request/add-liquidity-request.ts @@ -0,0 +1,14 @@ +import { SwapFeeTierType } from "@constants/option.constant"; +import { TokenModel } from "@models/token/token-model"; + +export interface AddLiquidityRequest { + tokenA: TokenModel; + tokenB: TokenModel; + feeTier: SwapFeeTierType; + tokenAAmount: string; + tokenBAmount: string; + minTick: number; + maxTick: number; + slippage: number; + caller: string; +} diff --git a/packages/web/src/repositories/pool/response/pool-info-response.ts b/packages/web/src/repositories/pool/response/pool-info-response.ts index 9553a86b7..f98c93a8c 100644 --- a/packages/web/src/repositories/pool/response/pool-info-response.ts +++ b/packages/web/src/repositories/pool/response/pool-info-response.ts @@ -20,16 +20,14 @@ export interface PoolInfoResponse { liquidity: number; ticks: number[]; tick_bitmaps: number[]; - positions: [ - { - owner: string; - tick_lower: number; - tick_upper: number; - liquidity: number; - token0_owed: number; - token1_owed: number; - }, - ]; + positions: { + owner: string; + tick_lower: number; + tick_upper: number; + liquidity: number; + token0_owed: number; + token1_owed: number; + }[]; }; }; } diff --git a/packages/web/src/utils/swap-utils.ts b/packages/web/src/utils/swap-utils.ts index fa4334d4b..745380424 100644 --- a/packages/web/src/utils/swap-utils.ts +++ b/packages/web/src/utils/swap-utils.ts @@ -6,7 +6,7 @@ import { MAX_TICK, MIN_TICK, X96 } from "@constants/swap.constant"; import BigNumber from "bignumber.js"; export function getCurrentPriceByRaw(raw: string) { - return BigNumber(raw).dividedBy(2 ** 96); + return BigNumber(raw).dividedBy(X96); } export function makeSwapFeeTier(value: string | number): SwapFeeTierType { @@ -24,6 +24,9 @@ export function tickToPrice(tick: number) { } export function priceToTick(price: number) { + if (price === 0) { + return MIN_TICK; + } const logPrice = Math.log(price ** 2); const log10001 = Math.log(1.0001); return Math.round(BigNumber(logPrice).dividedBy(log10001).toNumber()); @@ -35,7 +38,11 @@ export function priceToNearTick(price: number, tickSpacing: number) { const sign = Math.sign(tickRaw); if (sign < 0) { - return tickRaw - (tickSpacing - mod); + const tick = tickRaw + mod; + if (tick - tickSpacing < MIN_TICK) { + return tick; + } + return tick - tickSpacing; } return tickRaw - mod; }