From 2f925f46b11eb89d94b9ad0d2d4f82ca59d73ed0 Mon Sep 17 00:00:00 2001 From: quangdz1704 Date: Mon, 5 Aug 2024 18:43:29 +0700 Subject: [PATCH 01/19] feat: stats --- codegen.ts | 2 +- package.json | 5 + .../Pool-V3/components/PoolList/index.tsx | 7 - .../Pool-V3/components/PositionItem/index.tsx | 52 +-- .../Pool-V3/components/PositionList/index.tsx | 336 +++++++++++++++- .../EmptyPlaceholder/EmptyPlaceholder.tsx | 29 ++ .../Statistics/EmptyPlaceholder/style.tsx | 25 ++ .../Statistics/Liquidity/Liquidity.tsx | 133 +++++++ .../components/Statistics/Liquidity/style.ts | 102 +++++ .../PaginationList/PaginationList.tsx | 28 ++ .../Statistics/PaginationList/style.tsx | 76 ++++ .../Statistics/PoolList/PoolList.tsx | 113 ++++++ .../components/Statistics/PoolList/style.ts | 30 ++ .../Statistics/PoolListItem/PoolListItem.tsx | 241 ++++++++++++ .../Statistics/PoolListItem/style.ts | 112 ++++++ .../TokenListItem/TokenListItem.tsx | 188 +++++++++ .../Statistics/TokenListItem/style.ts | 84 ++++ .../Statistics/TokensList/TokensList.tsx | 127 ++++++ .../components/Statistics/TokensList/style.ts | 28 ++ .../components/Statistics/Volume/Volume.tsx | 128 ++++++ .../components/Statistics/Volume/style.ts | 82 ++++ .../Statistics/WrappedStats/WrappedStats.tsx | 146 +++++++ .../Statistics/WrappedStats/mockStats.ts | 196 ++++++++++ .../Statistics/WrappedStats/styles.ts | 48 +++ .../Statistics/hooks/useGetStatistic.ts | 363 ++++++++++++++++++ .../components/Statistics/theme/index.ts | 223 +++++++++++ .../components/Statistics/theme/types.ts | 19 + .../Statistics/volumeBar/VolumeBar.tsx | 76 ++++ .../components/Statistics/volumeBar/style.ts | 52 +++ src/pages/Pool-V3/helpers/format.tsx | 8 + src/pages/Pool-V3/helpers/helper.ts | 15 +- src/pages/Pool-V3/index.module.scss | 4 + src/pages/Pool-V3/index.tsx | 16 +- yarn.lock | 295 +++++++++++++- 34 files changed, 3334 insertions(+), 55 deletions(-) create mode 100644 src/pages/Pool-V3/components/Statistics/EmptyPlaceholder/EmptyPlaceholder.tsx create mode 100644 src/pages/Pool-V3/components/Statistics/EmptyPlaceholder/style.tsx create mode 100644 src/pages/Pool-V3/components/Statistics/Liquidity/Liquidity.tsx create mode 100644 src/pages/Pool-V3/components/Statistics/Liquidity/style.ts create mode 100644 src/pages/Pool-V3/components/Statistics/PaginationList/PaginationList.tsx create mode 100644 src/pages/Pool-V3/components/Statistics/PaginationList/style.tsx create mode 100644 src/pages/Pool-V3/components/Statistics/PoolList/PoolList.tsx create mode 100644 src/pages/Pool-V3/components/Statistics/PoolList/style.ts create mode 100644 src/pages/Pool-V3/components/Statistics/PoolListItem/PoolListItem.tsx create mode 100644 src/pages/Pool-V3/components/Statistics/PoolListItem/style.ts create mode 100644 src/pages/Pool-V3/components/Statistics/TokenListItem/TokenListItem.tsx create mode 100644 src/pages/Pool-V3/components/Statistics/TokenListItem/style.ts create mode 100644 src/pages/Pool-V3/components/Statistics/TokensList/TokensList.tsx create mode 100644 src/pages/Pool-V3/components/Statistics/TokensList/style.ts create mode 100644 src/pages/Pool-V3/components/Statistics/Volume/Volume.tsx create mode 100644 src/pages/Pool-V3/components/Statistics/Volume/style.ts create mode 100644 src/pages/Pool-V3/components/Statistics/WrappedStats/WrappedStats.tsx create mode 100644 src/pages/Pool-V3/components/Statistics/WrappedStats/mockStats.ts create mode 100644 src/pages/Pool-V3/components/Statistics/WrappedStats/styles.ts create mode 100644 src/pages/Pool-V3/components/Statistics/hooks/useGetStatistic.ts create mode 100644 src/pages/Pool-V3/components/Statistics/theme/index.ts create mode 100644 src/pages/Pool-V3/components/Statistics/theme/types.ts create mode 100644 src/pages/Pool-V3/components/Statistics/volumeBar/VolumeBar.tsx create mode 100644 src/pages/Pool-V3/components/Statistics/volumeBar/style.ts diff --git a/codegen.ts b/codegen.ts index 1f7ef70f7..e5b83fef7 100644 --- a/codegen.ts +++ b/codegen.ts @@ -1,7 +1,7 @@ import { CodegenConfig } from '@graphql-codegen/cli'; // https://subql-staging.orai.io/ -export const endpoint_gql = `http://10.10.20.72:3000/`; +export const endpoint_gql = `https//staging-ammv3-indexer.oraidex.io/`; const config: CodegenConfig = { schema: endpoint_gql, documents: ['src/**/*.tsx'], diff --git a/package.json b/package.json index eba66bed7..421f9a2ca 100644 --- a/package.json +++ b/package.json @@ -12,9 +12,13 @@ "@cosmjs/stargate": "^0.31.0", "@cosmjs/tendermint-rpc": "^0.31.0", "@duckdb/duckdb-wasm": "1.28.0", + "@emotion/react": "^11.13.0", + "@emotion/styled": "^11.13.0", "@injectivelabs/sdk-ts": "1.12.1", "@leapwallet/cosmos-snap-provider": "0.1.25", "@lucky-canvas/react": "^0.1.13", + "@mui/icons-material": "^5.16.6", + "@mui/material": "^5.16.6", "@nivo/bar": "^0.87.0", "@nivo/line": "^0.86.0", "@oraichain/common-contracts-sdk": "^1.0.31", @@ -58,6 +62,7 @@ "redux-persist": "^6.0.0", "serialize-error": "8.0.0", "tronweb": "^5.1.0", + "tss-react": "^4.9.12", "urql": "^4.1.0" }, "devDependencies": { diff --git a/src/pages/Pool-V3/components/PoolList/index.tsx b/src/pages/Pool-V3/components/PoolList/index.tsx index 87629a568..391c6ad01 100644 --- a/src/pages/Pool-V3/components/PoolList/index.tsx +++ b/src/pages/Pool-V3/components/PoolList/index.tsx @@ -231,13 +231,6 @@ const PoolList = () => { // const tokenY = allTokens[poolsDataObject[address].tokenY.toString()]; //@ts-ignore const lastSnapshot = snapshots[snapshots.length - 1]; - // console.log('token: ', tokenX.coingeckoId, tokenY.coingeckoId, lastSnapshot, lastTimestamp); - // tokensDataObject[(tokenX.contractAddress || tokenX.denom).toString()].volume24 += - // lastSnapshot.timestamp === lastTimestamp ? lastSnapshot.volumeX.usdValue24 : 0; - // tokensDataObject[(tokenX.contractAddress || tokenX.denom).toString()].volume24 += - // lastSnapshot.timestamp === lastTimestamp ? lastSnapshot.volumeY.usdValue24 : 0; - // tokensDataObject[(tokenX.contractAddress || tokenX.denom).toString()].tvl += lastSnapshot.liquidityX.usdValue24; - // tokensDataObject[(tokenX.contractAddress || tokenX.denom).toString()].tvl += lastSnapshot.liquidityY.usdValue24; poolsData.push({ volume24: lastSnapshot.timestamp === lastTimestamp diff --git a/src/pages/Pool-V3/components/PositionItem/index.tsx b/src/pages/Pool-V3/components/PositionItem/index.tsx index 4827a657e..ae8ef45b0 100644 --- a/src/pages/Pool-V3/components/PositionItem/index.tsx +++ b/src/pages/Pool-V3/components/PositionItem/index.tsx @@ -34,7 +34,7 @@ import { getCosmWasmClient } from 'libs/cosmjs'; import { useCoinGeckoPrices } from 'hooks/useCoingecko'; import { oraichainTokens } from 'config/bridgeTokens'; import { oraichainTokensWithIcon } from 'config/chainInfos'; -import { toDisplay, parseAssetInfo, TokenItemType, BigDecimal } from '@oraichain/oraidex-common'; +import { toDisplay, parseAssetInfo, TokenItemType, BigDecimal, CW20_DECIMALS } from '@oraichain/oraidex-common'; import { Tick } from '@oraichain/oraidex-contracts-sdk/build/OraiswapV3.types'; const shorterPrefixConfig: PrefixConfig = { @@ -58,7 +58,9 @@ const PositionItem = ({ position, setStatusRemove }) => { totalEarn, totalEarnIncentiveUsd = 0, tokenXUsd = 0, - tokenYUsd = 0 + tokenYUsd = 0, + tokenYDecimal, + tokenXDecimal } = position || {}; const { earnX = 0, earnY = 0, earnIncentive = null } = totalEarn || {}; @@ -171,7 +173,6 @@ const PositionItem = ({ position, setStatusRemove }) => { const totalIncentiveUsd = Object.entries(incentives).reduce((acc: number, [tokenAddress, amount]) => { const token = oraichainTokens.find((e) => [e.contractAddress, e.denom].includes(tokenAddress)); - console.log('first', [tokenAddress, amount, token]); const usd = toDisplay(amount.toString()) * cachePrices[token.coinGeckoId]; acc = new BigDecimal(acc || 0).add(usd).toNumber(); @@ -179,8 +180,6 @@ const PositionItem = ({ position, setStatusRemove }) => { return acc; }, 0); - console.log('totalIncentiveUsd', totalIncentiveUsd); - return [x_claim, y_claim, x_usd, y_usd, totalIncentiveUsd]; } @@ -303,8 +302,8 @@ const PositionItem = ({ position, setStatusRemove }) => { {!principalAmountX || !principalAmountY ? '--' : formatDisplayUsdt( - new BigDecimal(toDisplay(principalAmountX || 0) * tokenXUsd) - .add(toDisplay(principalAmountY || 0) * tokenYUsd) + new BigDecimal(toDisplay((principalAmountX || 0).toString(), tokenXDecimal) * tokenXUsd) + .add(toDisplay((principalAmountY || 0).toString(), tokenYDecimal) * tokenYUsd) .toNumber(), 6, 6 @@ -314,14 +313,18 @@ const PositionItem = ({ position, setStatusRemove }) => { {!principalAmountX ? '--' - : numberWithCommas(toDisplay(principalAmountX || 0), undefined, { maximumFractionDigits: 6 })}{' '} + : numberWithCommas(toDisplay(principalAmountX || 0, tokenXDecimal), undefined, { + maximumFractionDigits: 6 + })}{' '} {position?.tokenX.name} {!principalAmountY ? '--' - : numberWithCommas(toDisplay(principalAmountY || 0), undefined, { maximumFractionDigits: 6 })}{' '} + : numberWithCommas(toDisplay(principalAmountY || 0, tokenYDecimal), undefined, { + maximumFractionDigits: 6 + })}{' '} {position?.tokenY.name} @@ -385,25 +388,27 @@ const PositionItem = ({ position, setStatusRemove }) => {

Total Reward Earned

- {!earnX || !earnY - ? '--' - : formatDisplayUsdt( - new BigDecimal(toDisplay(earnX || 0) * tokenXUsd) - .add(toDisplay(earnY || 0) * tokenYUsd) - .add(totalEarnIncentiveUsd) - .toNumber(), - 6, - 6 - )} + {formatDisplayUsdt( + new BigDecimal(toDisplay((earnX || 0).toString(), tokenXDecimal) * tokenXUsd) + .add(toDisplay((earnY || 0).toString(), tokenYDecimal) * tokenYUsd) + .add(totalEarnIncentiveUsd) + .toNumber(), + 6, + 6 + )} - {!earnX ? '--' : numberWithCommas(toDisplay(earnX), undefined, { maximumFractionDigits: 6 })}{' '} + {numberWithCommas(toDisplay((earnX || 0).toString(), tokenXDecimal), undefined, { + maximumFractionDigits: 6 + })}{' '} {position?.tokenX.name} - {!earnY ? '--' : numberWithCommas(toDisplay(earnY), undefined, { maximumFractionDigits: 6 })}{' '} + {numberWithCommas(toDisplay((earnY || 0).toString(), tokenYDecimal), undefined, { + maximumFractionDigits: 6 + })}{' '} {position?.tokenY.name}
@@ -418,7 +423,10 @@ const PositionItem = ({ position, setStatusRemove }) => { {theme === 'light' ? : } - {!amount || !Number(amount) ? '--' : toDisplay(amount.toString())} {token?.name} + {!amount || !Number(amount) + ? '--' + : toDisplay(amount.toString(), token.decimals || CW20_DECIMALS)}{' '} + {token?.name} ); diff --git a/src/pages/Pool-V3/components/PositionList/index.tsx b/src/pages/Pool-V3/components/PositionList/index.tsx index b3c569be6..3795dc3e8 100644 --- a/src/pages/Pool-V3/components/PositionList/index.tsx +++ b/src/pages/Pool-V3/components/PositionList/index.tsx @@ -13,9 +13,8 @@ import { gql, request, GraphQLClient } from 'graphql-request'; export const getFeeClaimData = async (address: string) => { try { - return []; // https://subql-staging.orai.io/ - const endpoint = `http://10.10.20.72:3000/`; + const endpoint = `https://staging-ammv3-indexer.oraidex.io/`; const client = new GraphQLClient(endpoint); const document = gql` @@ -29,7 +28,8 @@ export const getFeeClaimData = async (address: string) => { principalAmountY fees { nodes { - amountUSD + amountXInUSD + amountYInUSD amountX amountY claimFeeIncentiveTokens { @@ -53,11 +53,12 @@ export const getFeeClaimData = async (address: string) => { } `; - const result = await client.request(document); + // return MOCK_DATA; - console.log('result', result); + const result = await client.request(document); const data = result.query.positions.nodes; + return data || []; } catch (error) { console.log('error', error); @@ -134,3 +135,328 @@ const PositionList = () => { }; export default PositionList; + +export const MOCK_DATA = [ + { + id: 'orai-orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh-3000000000-100-84', + poolId: 'orai-orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh-3000000000-100', + principalAmountX: '500000', + principalAmountY: '1126302', + fees: { + nodes: [ + { + amountXInUSD: null, + amountYInUSD: null, + amountX: '0', + amountY: '0', + claimFeeIncentiveTokens: { + nodes: [ + { + id: '0A8B981EC18080CA491EB23E18A571439B0902FA222D18F5D3B17EAADDC2DCF4-claimFee-orai-orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh-3000000000-100-84-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', + tokenId: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', + token: { + id: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', + denom: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', + name: 'ORAIX', + logo: 'https://i.ibb.co/VmMJtf7/oraix.png' + }, + rewardAmount: '1661' + } + ] + } + }, + { + amountXInUSD: null, + amountYInUSD: null, + amountX: '312', + amountY: '0', + claimFeeIncentiveTokens: { + nodes: [ + { + id: '446866EC0563851CF86AAF935601DD1F3E74DBC780820C8BF0B243DDD3EE3891-claimFee-orai-orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh-3000000000-100-84-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', + tokenId: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', + token: { + id: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', + denom: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', + name: 'ORAIX', + logo: 'https://i.ibb.co/VmMJtf7/oraix.png' + }, + rewardAmount: '398576' + } + ] + } + }, + { + amountXInUSD: null, + amountYInUSD: null, + amountX: '33', + amountY: '0', + claimFeeIncentiveTokens: { + nodes: [ + { + id: 'D5FB1C6E77640D4CD6EDC313BA043866D6A5C535282929861523F4B4C345C3AB-claimFee-orai-orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh-3000000000-100-84-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', + tokenId: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', + token: { + id: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', + denom: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', + name: 'ORAIX', + logo: 'https://i.ibb.co/VmMJtf7/oraix.png' + }, + rewardAmount: '164764' + } + ] + } + } + ] + } + }, + { + id: 'orai-orai15un8msx3n5zf9ahlxmfeqd2kwa5wm0nrpxer304m9nd5q6qq0g6sku5pdd-3000000000-100-154', + poolId: 'orai-orai15un8msx3n5zf9ahlxmfeqd2kwa5wm0nrpxer304m9nd5q6qq0g6sku5pdd-3000000000-100', + principalAmountX: '100000', + principalAmountY: '532732', + fees: { + nodes: [ + { + amountXInUSD: null, + amountYInUSD: null, + amountX: '0', + amountY: '0', + claimFeeIncentiveTokens: { + nodes: [ + { + id: '0E4913310390F391E21C47BE68F24F907DF9845F82466EC25AC00A3073F71D9B-claimFee-orai-orai15un8msx3n5zf9ahlxmfeqd2kwa5wm0nrpxer304m9nd5q6qq0g6sku5pdd-3000000000-100-154-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', + tokenId: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', + token: { + id: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', + denom: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', + name: 'ORAIX', + logo: 'https://i.ibb.co/VmMJtf7/oraix.png' + }, + rewardAmount: '7777' + } + ] + } + } + ] + } + }, + { + id: 'orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh-orai1hn8w33cqvysun2aujk5sv33tku4pgcxhhnsxmvnkfvdxagcx0p8qa4l98q-3000000000-100-17', + poolId: + 'orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh-orai1hn8w33cqvysun2aujk5sv33tku4pgcxhhnsxmvnkfvdxagcx0p8qa4l98q-3000000000-100', + principalAmountX: '387330', + principalAmountY: '1143314', + fees: { + nodes: [] + } + }, + { + id: 'orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100-160', + poolId: 'orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100', + principalAmountX: '100000', + principalAmountY: '539684344', + fees: { + nodes: [] + } + }, + { + id: 'orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh-orai15un8msx3n5zf9ahlxmfeqd2kwa5wm0nrpxer304m9nd5q6qq0g6sku5pdd-500000000-10-52', + poolId: + 'orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh-orai15un8msx3n5zf9ahlxmfeqd2kwa5wm0nrpxer304m9nd5q6qq0g6sku5pdd-500000000-10', + principalAmountX: '70374', + principalAmountY: '119972', + fees: { + nodes: [] + } + }, + { + id: 'orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100-98', + poolId: 'orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100', + principalAmountX: '93072', + principalAmountY: '105354416', + fees: { + nodes: [ + { + amountXInUSD: null, + amountYInUSD: null, + amountX: '169', + amountY: '0', + claimFeeIncentiveTokens: { + nodes: [ + { + id: '73D98E5910363AA2DD25AFCA680E405AF84EDF757E3B8E0B8F12AD833FD97A8B-claimFee-orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100-98-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', + tokenId: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', + token: { + id: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', + denom: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', + name: 'ORAIX', + logo: 'https://i.ibb.co/VmMJtf7/oraix.png' + }, + rewardAmount: '240408' + } + ] + } + }, + { + amountXInUSD: null, + amountYInUSD: null, + amountX: '0', + amountY: '0', + claimFeeIncentiveTokens: { + nodes: [] + } + } + ] + } + }, + { + id: 'orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh-orai15un8msx3n5zf9ahlxmfeqd2kwa5wm0nrpxer304m9nd5q6qq0g6sku5pdd-500000000-10-70', + poolId: + 'orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh-orai15un8msx3n5zf9ahlxmfeqd2kwa5wm0nrpxer304m9nd5q6qq0g6sku5pdd-500000000-10', + principalAmountX: '1982821', + principalAmountY: '2241197', + fees: { + nodes: [ + { + amountXInUSD: null, + amountYInUSD: null, + amountX: '0', + amountY: '6', + claimFeeIncentiveTokens: { + nodes: [] + } + } + ] + } + }, + { + id: 'factory/orai1wuvhex9xqs3r539mvc6mtm7n20fcj3qr2m0y9khx6n5vtlngfzes3k0rq9/ton-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100-153', + poolId: + 'factory/orai1wuvhex9xqs3r539mvc6mtm7n20fcj3qr2m0y9khx6n5vtlngfzes3k0rq9/ton-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100', + principalAmountX: '1000000000', + principalAmountY: '1543494902', + fees: { + nodes: [ + { + amountXInUSD: null, + amountYInUSD: null, + amountX: '2450494', + amountY: '0', + claimFeeIncentiveTokens: { + nodes: [] + } + } + ] + } + }, + { + id: 'orai-orai15un8msx3n5zf9ahlxmfeqd2kwa5wm0nrpxer304m9nd5q6qq0g6sku5pdd-3000000000-100-156', + poolId: 'orai-orai15un8msx3n5zf9ahlxmfeqd2kwa5wm0nrpxer304m9nd5q6qq0g6sku5pdd-3000000000-100', + principalAmountX: '1000000', + principalAmountY: '4345107', + fees: { + nodes: [] + } + }, + { + id: 'orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-100000000-1-81', + poolId: 'orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-100000000-1', + principalAmountX: '10000', + principalAmountY: '26756', + fees: { + nodes: [] + } + }, + { + id: 'orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-100000000-1-90', + poolId: 'orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-100000000-1', + principalAmountX: '100', + principalAmountY: '146', + fees: { + nodes: [] + } + }, + { + id: 'orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100-88', + poolId: 'orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100', + principalAmountX: '100', + principalAmountY: '113198', + fees: { + nodes: [ + { + amountXInUSD: null, + amountYInUSD: null, + amountX: '0', + amountY: '0', + claimFeeIncentiveTokens: { + nodes: [ + { + id: '97F86751A2C900A988ABC482CA50687C4F31AF6BF0B76E200B4640EF66C2FD86-claimFee-orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100-88-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', + tokenId: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', + token: { + id: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', + denom: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', + name: 'ORAIX', + logo: 'https://i.ibb.co/VmMJtf7/oraix.png' + }, + rewardAmount: '40' + } + ] + } + } + ] + } + }, + { + id: 'orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh-orai1hn8w33cqvysun2aujk5sv33tku4pgcxhhnsxmvnkfvdxagcx0p8qa4l98q-3000000000-100-18', + poolId: + 'orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh-orai1hn8w33cqvysun2aujk5sv33tku4pgcxhhnsxmvnkfvdxagcx0p8qa4l98q-3000000000-100', + principalAmountX: '387325', + principalAmountY: '1143314', + fees: { + nodes: [] + } + }, + { + id: 'orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100-91', + poolId: 'orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100', + principalAmountX: '1', + principalAmountY: '11560', + fees: { + nodes: [ + { + amountXInUSD: null, + amountYInUSD: null, + amountX: '0', + amountY: '0', + claimFeeIncentiveTokens: { + nodes: [ + { + id: 'E8DAFABA05274A0A736B704AE2E681A9F823783B6CB2E275F1B071DFC89371E3-claimFee-orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100-91-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', + tokenId: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', + token: { + id: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', + denom: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', + name: 'ORAIX', + logo: 'https://i.ibb.co/VmMJtf7/oraix.png' + }, + rewardAmount: '6' + } + ] + } + } + ] + } + }, + { + id: 'factory/orai1wuvhex9xqs3r539mvc6mtm7n20fcj3qr2m0y9khx6n5vtlngfzes3k0rq9/ton-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100-152', + poolId: + 'factory/orai1wuvhex9xqs3r539mvc6mtm7n20fcj3qr2m0y9khx6n5vtlngfzes3k0rq9/ton-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100', + principalAmountX: '10000000', + principalAmountY: '15434950', + fees: { + nodes: [] + } + } +]; diff --git a/src/pages/Pool-V3/components/Statistics/EmptyPlaceholder/EmptyPlaceholder.tsx b/src/pages/Pool-V3/components/Statistics/EmptyPlaceholder/EmptyPlaceholder.tsx new file mode 100644 index 000000000..50a33ff09 --- /dev/null +++ b/src/pages/Pool-V3/components/Statistics/EmptyPlaceholder/EmptyPlaceholder.tsx @@ -0,0 +1,29 @@ +import { Grid, Typography } from '@mui/material'; +import empty from 'assets/images/NoDataPool.svg'; +import classNames from 'classnames'; +import React from 'react'; +import { useStyles } from './style'; + +export interface IEmptyPlaceholder { + desc: string; + className?: string; + style?: React.CSSProperties; +} + +export const EmptyPlaceholder: React.FC = ({ desc, className, style }) => { + const { classes } = useStyles(); + + return ( + + empty data + It's empty here... + {desc} + + ); +}; diff --git a/src/pages/Pool-V3/components/Statistics/EmptyPlaceholder/style.tsx b/src/pages/Pool-V3/components/Statistics/EmptyPlaceholder/style.tsx new file mode 100644 index 000000000..c52daf9b9 --- /dev/null +++ b/src/pages/Pool-V3/components/Statistics/EmptyPlaceholder/style.tsx @@ -0,0 +1,25 @@ +import { colors, typography } from '../theme'; +import { makeStyles } from 'tss-react/mui'; + +export const useStyles = makeStyles()(() => ({ + wrapper: { + width: 300 + }, + image: { + width: 160, + height: 180 + }, + title: { + ...typography.heading2, + marginBlock: 24, + color: colors.oraidex.textGrey, + opacity: 0.7 + }, + desc: { + color: colors.oraidex.textGrey, + opacity: 0.7, + ...typography.heading4, + fontWeight: 400, + textAlign: 'center' + } +})); diff --git a/src/pages/Pool-V3/components/Statistics/Liquidity/Liquidity.tsx b/src/pages/Pool-V3/components/Statistics/Liquidity/Liquidity.tsx new file mode 100644 index 000000000..9f4dd64a1 --- /dev/null +++ b/src/pages/Pool-V3/components/Statistics/Liquidity/Liquidity.tsx @@ -0,0 +1,133 @@ +import React from 'react'; +import { ResponsiveLine } from '@nivo/line'; +import { linearGradientDef } from '@nivo/core'; +import classNames from 'classnames'; +import { colors } from '../theme'; +import { useStyles } from './style'; +import { TimeData } from '../hooks/useGetStatistic'; +import { Grid, Typography } from '@mui/material'; +import { formatNumbers, showPrefix } from 'pages/Pool-V3/helpers/helper'; + +interface LiquidityInterface { + liquidityPercent: number; + liquidityVolume: number; + data: TimeData[]; + className?: string; +} + +const Liquidity: React.FC = ({ liquidityPercent, liquidityVolume, data, className }) => { + const { classes } = useStyles(); + + const isLower = liquidityPercent < 0; + + return ( + + + Liquidity + + + ${formatNumbers()(liquidityVolume.toString())} + {showPrefix(liquidityVolume)} + + + + + {liquidityPercent < 0 ? liquidityPercent.toFixed(2) : `+${liquidityPercent.toFixed(2)}`}% + + + + + + + ({ + x: new Date(timestamp).toLocaleDateString('en-GB'), + y: value + })) + } + ]} + margin={{ top: 24, bottom: 24, left: 24, right: 24 }} + xScale={{ + type: 'time', + format: '%d/%m/%Y', + precision: 'day', + useUTC: false + }} + axisBottom={{ + tickSize: 0, + tickPadding: 10, + tickRotation: 0, + tickValues: data.length >= 24 ? 'every 4 days' : data.length >= 8 ? 'every 2 days' : 'every day', + format: '%d/%m' + }} + legends={[]} + axisTop={null} + axisRight={null} + axisLeft={null} + curve={'monotoneX'} + role="aplication" + enableGridX={false} + enableGridY={false} + enablePoints={false} + enableArea={true} + isInteractive + useMesh + animate + colors={colors.oraidex.green} + theme={{ + axis: { + ticks: { + line: { stroke: colors.oraidex.component }, + text: { fill: '#A9B6BF' } + } + }, + crosshair: { + line: { + stroke: colors.oraidex.lightGrey, + strokeWidth: 1, + strokeDasharray: 'solid' + } + } + }} + lineWidth={1} + defs={[ + linearGradientDef('gradient', [ + { offset: 0, color: 'inherit' }, + { offset: 50, color: 'inherit' }, + { offset: 100, color: 'inherit', opacity: 0 } + ]) + ]} + fill={[{ match: '*', id: 'gradient' }]} + crosshairType="bottom" + tooltip={({ point }) => { + const date = point.data.x as Date; + const day = date.getDate(); + const month = date.getMonth() + 1; + + return ( + + {`${day < 10 ? '0' : ''}${day}/${ + month < 10 ? '0' : '' + }${month}`} + ${(point.data.y as number).toFixed(2)} + + ); + }} + /> + + + ); +}; + +export default Liquidity; diff --git a/src/pages/Pool-V3/components/Statistics/Liquidity/style.ts b/src/pages/Pool-V3/components/Statistics/Liquidity/style.ts new file mode 100644 index 000000000..8f56d4613 --- /dev/null +++ b/src/pages/Pool-V3/components/Statistics/Liquidity/style.ts @@ -0,0 +1,102 @@ +import { typography, colors } from '../theme'; +import { makeStyles } from 'tss-react/mui'; + +export const useStyles = makeStyles()(() => ({ + container: { + backgroundColor: colors.oraidex.component, + color: 'white', + borderRadius: 24, + paddingBlock: 24, + boxSizing: 'border-box' + }, + liquidityContainer: { + dispaly: 'flex', + flexDirection: 'column', + alignItems: 'flex-start', + fontWeight: 'normal', + marginLeft: 24 + }, + + liquidityHeader: { + color: colors.oraidex.textGrey, + ...typography.body2 + }, + + volumeLiquidityHeader: { + ...typography.heading1, + letterSpacing: '-0.03em', + marginTop: 5 + }, + + barContainer: { + height: 200, + display: 'flex' + }, + + volumePercentHeader: { + display: 'flex', + alignItems: 'center' + }, + volumeStatusContainer: { + marginLeft: 10, + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + minWidth: 'auto' + }, + volumeStatusColor: { + height: 30, + minWidth: 'auto', + padding: '5px 15px 5px 15px', + borderRadius: 6 + }, + + volumeStatusHeader: { + ...typography.body1, + filter: 'brightness(1.2)' + }, + volumeLow: { + color: colors.oraidex.Error + }, + + backgroundVolumeLow: { + backgroundColor: 'rgba(251,85,95,0.2)' + }, + + backgroundVolumeUp: { + backgroundColor: 'rgba(46, 224, 149,0.2)' + }, + + volumeUp: { + color: colors.oraidex.green + }, + + LineKeys: { + marginLeft: 10, + display: 'flex', + width: '100%' + }, + + keyPTag: { + width: '100%', + color: colors.oraidex.textGrey, + ...typography.caption4 + }, + tooltip: { + background: colors.oraidex.component, + border: `1px solid ${colors.oraidex.lightGrey}`, + borderRadius: 5, + width: 100, + padding: 5 + }, + tooltipDate: { + ...typography.caption4, + color: colors.white.main, + textAlign: 'center' + }, + tooltipValue: { + ...typography.caption3, + color: colors.oraidex.green, + textAlign: 'center' + } +})); diff --git a/src/pages/Pool-V3/components/Statistics/PaginationList/PaginationList.tsx b/src/pages/Pool-V3/components/Statistics/PaginationList/PaginationList.tsx new file mode 100644 index 000000000..438d485e3 --- /dev/null +++ b/src/pages/Pool-V3/components/Statistics/PaginationList/PaginationList.tsx @@ -0,0 +1,28 @@ +import { Pagination, useMediaQuery } from '@mui/material'; +import { theme } from '../theme'; +import { useStyles } from './style'; + +export interface IPaginationList { + pages: number; + defaultPage: number; + handleChangePage: (page: number) => void; + variant: string; +} + +export const PaginationList: React.FC = ({ pages, defaultPage, handleChangePage, variant }) => { + const { classes } = useStyles(); + const position = useMediaQuery(theme.breakpoints.down('sm')); + const matches = useMediaQuery(theme.breakpoints.down('xs')); + + return ( +
+ handleChangePage(page)} + siblingCount={matches ? 0 : 1} + /> +
+ ); +}; diff --git a/src/pages/Pool-V3/components/Statistics/PaginationList/style.tsx b/src/pages/Pool-V3/components/Statistics/PaginationList/style.tsx new file mode 100644 index 000000000..424ea458a --- /dev/null +++ b/src/pages/Pool-V3/components/Statistics/PaginationList/style.tsx @@ -0,0 +1,76 @@ +import { Theme } from '@mui/material/styles/createTheme'; +import { colors, typography } from '../theme'; +import { makeStyles } from 'tss-react/mui'; + +export const useStyles = makeStyles()((theme: Theme) => ({ + root: { + width: 1122, + display: 'flex', + [theme.breakpoints.down('md')]: { + width: '100%' + }, + '& .MuiPagination-ul': { + flexWrap: 'nowrap', + margin: '10px 0 10px' + }, + + '& .MuiPaginationItem-icon': { + color: colors.black.full + }, + + '& .MuiPaginationItem-page': { + ...typography.heading4, + + color: colors.oraidex.light, + '&:hover': { + color: colors.oraidex.lightGrey + } + }, + + '& .MuiPaginationItem-page:hover': { + color: colors.oraidex.textGrey + }, + + '& .MuiPaginationItem-ellipsis': { + color: colors.oraidex.light + }, + + '& .Mui-selected': { + color: colors.oraidex.greenLinearGradient + }, + '& .Mui-selected:hover': { + color: `${colors.oraidex.green} !important` + }, + + '& .MuiPaginationItem-page.Mui-selected': { + backgroundColor: 'transparent', + '&:hover': { + color: colors.oraidex.greenLinearGradient + } + }, + '& li:first-of-type button': { + backgroundColor: colors.oraidex.greenLinearGradient, + minWidth: 40, + minHeight: 40, + opacity: 0.8 + }, + '& li:first-of-type button:hover': { + opacity: 1 + }, + + '& li:last-child button': { + backgroundColor: colors.oraidex.greenLinearGradient, + minWidth: 40, + minHeight: 40, + opacity: 0.8 + }, + + '& li:last-child button:hover': { + opacity: 1 + }, + + '& svg': { + transform: 'scale(2.2)' + } + } +})); diff --git a/src/pages/Pool-V3/components/Statistics/PoolList/PoolList.tsx b/src/pages/Pool-V3/components/Statistics/PoolList/PoolList.tsx new file mode 100644 index 000000000..bb6aa2cfd --- /dev/null +++ b/src/pages/Pool-V3/components/Statistics/PoolList/PoolList.tsx @@ -0,0 +1,113 @@ +import React, { useMemo, useEffect, FunctionComponent } from 'react'; + +import PoolListItem, { SortType } from '../PoolListItem/PoolListItem'; +import { useStyles } from './style'; +import { Grid } from '@mui/material'; +import { PaginationList } from '../PaginationList/PaginationList'; + +interface PoolListInterface { + data: Array<{ + symbolFrom: string; + symbolTo: string; + iconFrom: FunctionComponent< + React.SVGProps & { + title?: string; + } + >; + iconTo: FunctionComponent< + React.SVGProps & { + title?: string; + } + >; + volume: number; + TVL: number; + fee: number; + // apy: number + // apyData: { + // fees: number + // accumulatedFarmsAvg: number + // accumulatedFarmsSingleTick: number + // } + }>; +} + +const PoolList: React.FC = ({ data }) => { + const { classes } = useStyles(); + const [page, setPage] = React.useState(1); + const [sortType, setSortType] = React.useState(SortType.VOLUME_DESC); + + const sortedData = useMemo(() => { + switch (sortType) { + case SortType.NAME_ASC: + return data.sort((a, b) => `${a.symbolFrom}/${a.symbolTo}`.localeCompare(`${b.symbolFrom}/${b.symbolTo}`)); + case SortType.NAME_DESC: + return data.sort((a, b) => `${b.symbolFrom}/${b.symbolTo}`.localeCompare(`${a.symbolFrom}/${a.symbolTo}`)); + case SortType.FEE_ASC: + return data.sort((a, b) => a.fee - b.fee); + case SortType.FEE_DESC: + return data.sort((a, b) => b.fee - a.fee); + case SortType.VOLUME_ASC: + return data.sort((a, b) => (a.volume === b.volume ? a.TVL - b.TVL : a.volume - b.volume)); + case SortType.VOLUME_DESC: + return data.sort((a, b) => (a.volume === b.volume ? b.TVL - a.TVL : b.volume - a.volume)); + case SortType.TVL_ASC: + return data.sort((a, b) => (a.TVL === b.TVL ? a.volume - b.volume : a.TVL - b.TVL)); + case SortType.TVL_DESC: + return data.sort((a, b) => (a.TVL === b.TVL ? b.volume - a.volume : b.TVL - a.TVL)); + // case SortType.APY_ASC: + // return data.sort((a, b) => a.apy - b.apy) + // case SortType.APY_DESC: + // return data.sort((a, b) => b.apy - a.apy) + } + }, [data, sortType]); + + useEffect(() => { + setPage(1); + }, [data]); + + const handleChangePagination = (currentPage: number) => setPage(currentPage); + + const paginator = (currentPage: number) => { + const page = currentPage || 1; + const perPage = 10; + const offest = (page - 1) * perPage; + + return sortedData.slice(offest).slice(0, perPage); + }; + + const pages = Math.ceil(data.length / 10); + + return ( + +
+
+ + {paginator(page).map((element, index) => ( + + ))} +
+
+ {pages > 1 ? ( + + + + ) : null} +
+ ); +}; + +export default PoolList; diff --git a/src/pages/Pool-V3/components/Statistics/PoolList/style.ts b/src/pages/Pool-V3/components/Statistics/PoolList/style.ts new file mode 100644 index 000000000..0d4a4d301 --- /dev/null +++ b/src/pages/Pool-V3/components/Statistics/PoolList/style.ts @@ -0,0 +1,30 @@ +import { colors, theme } from '../theme'; +import { makeStyles } from 'tss-react/mui'; + +export const useStyles = makeStyles()(() => ({ + container: { + padding: '0 24px', + borderRadius: '24px', + backgroundColor: `${colors.oraidex.component} !important` + }, + pagination: { + width: '100%', + padding: '20px 0 10px 0', + + '& div': { + width: '100%' + } + }, + listWrapper: { + width: '100%', + + [theme.breakpoints.down('md')]: { + overflowX: 'scroll' + } + }, + inner: { + [theme.breakpoints.down('md')]: { + minWidth: 576 + } + } +})); diff --git a/src/pages/Pool-V3/components/Statistics/PoolListItem/PoolListItem.tsx b/src/pages/Pool-V3/components/Statistics/PoolListItem/PoolListItem.tsx new file mode 100644 index 000000000..106df6859 --- /dev/null +++ b/src/pages/Pool-V3/components/Statistics/PoolListItem/PoolListItem.tsx @@ -0,0 +1,241 @@ +import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown'; +import ArrowDropUpIcon from '@mui/icons-material/ArrowDropUp'; +import { Box, Grid, Typography, useMediaQuery } from '@mui/material'; +import { formatNumbers, PERCENTAGE_SCALE, showPrefix } from 'pages/Pool-V3/helpers/helper'; +import React, { FunctionComponent } from 'react'; +import { printBigint } from '../../PriceRangePlot/utils'; +import { theme } from '../theme'; +import { useStyles } from './style'; + +export enum SortType { + NAME_ASC, + NAME_DESC, + FEE_ASC, + FEE_DESC, + VOLUME_ASC, + VOLUME_DESC, + TVL_ASC, + TVL_DESC + // APY_ASC, + // APY_DESC +} + +interface IProps { + TVL?: number; + volume?: number; + fee?: number; + displayType: string; + symbolFrom?: string; + symbolTo?: string; + IconFrom?: FunctionComponent< + React.SVGProps & { + title?: string; + } + >; + IconTo?: FunctionComponent< + React.SVGProps & { + title?: string; + } + >; + tokenIndex?: number; + sortType?: SortType; + onSort?: (type: SortType) => void; + hideBottomLine?: boolean; + // apy?: number + // apyData?: { + // fees: number + // accumulatedFarmsAvg: number + // accumulatedFarmsSingleTick: number + // } +} + +const PoolListItem: React.FC = ({ + fee = 0, + volume = 0, + TVL = 0, + displayType, + symbolFrom, + symbolTo, + IconFrom, + IconTo, + tokenIndex, + sortType, + onSort, + hideBottomLine = false + // apy = 0, + // apyData = { + // fees: 0, + // accumulatedFarmsAvg: 0, + // accumulatedFarmsSingleTick: 0 + // } +}) => { + const { classes } = useStyles(); + + const isXs = useMediaQuery(theme.breakpoints.down('xs')); + + return ( + + {displayType === 'token' ? ( + + {!isXs ? {tokenIndex} : null} + + {!isXs && ( + + {/* Token from + Token to */} + + + + )} + + + {symbolFrom}/{symbolTo} + + + + {/* {!isXs ? ( + + {`${apy > 1000 ? '>1000' : apy.toFixed(2)}%`} + + Pool APY + + Pool fees: {`${apyData.fees > 1000 ? '>1000' : apyData.fees.toFixed(2)}%`} + {apyData.accumulatedFarmsAvg > 0 ? ( + <> +
+ All farms rewards with single tick position:{' '} + {`${ + apyData.accumulatedFarmsSingleTick > 1000 + ? '>1000' + : apyData.accumulatedFarmsSingleTick.toFixed(2) + }%`} +
+ (All farms rewards with average position:{' '} + {`${ + apyData.accumulatedFarmsAvg > 1000 + ? '>1000' + : apyData.accumulatedFarmsAvg.toFixed(2) + }%`} + ) + + ) : null} +
+ + } + placement='bottom' + classes={{ + tooltip: classes.liquidityTooltip + }}> + i +
+
+ ) : null} */} + {+printBigint(BigInt(fee), PERCENTAGE_SCALE - 2)}% + {`$${formatNumbers()(volume.toString())}${showPrefix(volume)}`} + {`$${formatNumbers()(TVL.toString())}${showPrefix(TVL)}`} +
+ ) : ( + + {!isXs && ( + + No + + )} + { + if (sortType === SortType.NAME_ASC) { + onSort?.(SortType.NAME_DESC); + } else { + onSort?.(SortType.NAME_ASC); + } + }} + > + Name + {sortType === SortType.NAME_ASC ? ( + + ) : sortType === SortType.NAME_DESC ? ( + + ) : null} + + {/* {!isXs ? ( + { + if (sortType === SortType.APY_DESC) { + onSort?.(SortType.APY_ASC) + } else { + onSort?.(SortType.APY_DESC) + } + }}> + APY + {sortType === SortType.APY_ASC ? ( + + ) : sortType === SortType.APY_DESC ? ( + + ) : null} + + ) : null} */} + { + if (sortType === SortType.FEE_ASC) { + onSort?.(SortType.FEE_DESC); + } else { + onSort?.(SortType.FEE_ASC); + } + }} + > + Fee + {sortType === SortType.FEE_ASC ? ( + + ) : sortType === SortType.FEE_DESC ? ( + + ) : null} + + { + if (sortType === SortType.VOLUME_DESC) { + onSort?.(SortType.VOLUME_ASC); + } else { + onSort?.(SortType.VOLUME_DESC); + } + }} + > + Volume 24H + {sortType === SortType.VOLUME_ASC ? ( + + ) : sortType === SortType.VOLUME_DESC ? ( + + ) : null} + + { + if (sortType === SortType.TVL_DESC) { + onSort?.(SortType.TVL_ASC); + } else { + onSort?.(SortType.TVL_DESC); + } + }} + > + TVL + {sortType === SortType.TVL_ASC ? ( + + ) : sortType === SortType.TVL_DESC ? ( + + ) : null} + + + )} +
+ ); +}; + +export default PoolListItem; diff --git a/src/pages/Pool-V3/components/Statistics/PoolListItem/style.ts b/src/pages/Pool-V3/components/Statistics/PoolListItem/style.ts new file mode 100644 index 000000000..cf339d9b5 --- /dev/null +++ b/src/pages/Pool-V3/components/Statistics/PoolListItem/style.ts @@ -0,0 +1,112 @@ +import { colors, theme, typography } from '../theme'; +import { makeStyles } from 'tss-react/mui'; + +export const useStyles = makeStyles()(() => ({ + container: { + color: colors.white.main, + display: 'grid', + gridTemplateColumns: '5% 45% 15% 20% auto', + padding: '18px 0', + + backgroundColor: colors.oraidex.component, + borderBottom: `1px solid ${colors.oraidex.light}`, + whiteSpace: 'nowrap', + '& p': { + ...typography.heading4, + display: 'flex', + justifyContent: 'start', + alignItems: 'center' + }, + + [theme.breakpoints.down('sm')]: { + '& p': { + ...typography.caption1 + } + }, + + [theme.breakpoints.down('xs')]: { + gridTemplateColumns: '28% 15% 30% 25%' + } + }, + + imageContainer: { + display: 'flex', + alignItems: 'center', + '& svg': { + minWidth: 28, + maxWidth: 28, + height: 28, + marginRight: 3, + borderRadius: '50%' + } + }, + + iconsWrapper: { + height: 28 + }, + + header: { + '& p': { + color: colors.oraidex.textGrey, + ...typography.heading4, + fontWeight: 400, + + [theme.breakpoints.down('sm')]: { + ...typography.caption2 + } + } + }, + + symbolsContainer: { + marginLeft: 10, + paddingRight: 5, + + '& p': { + overflow: 'hidden', + whiteSpace: 'nowrap', + textOverflow: 'ellipsis', + display: 'block' + }, + + [theme.breakpoints.down('xs')]: { + marginLeft: 0 + } + }, + icon: { + [theme.breakpoints.down('sm')]: { + marginLeft: -4 + } + }, + activeLiquidityIcon: { + marginLeft: 5, + height: 14, + width: 14, + border: '1px solid #FFFFFF', + color: colors.oraidex.text, + borderRadius: '50%', + fontSize: 10, + lineHeight: '10px', + fontWeight: 400, + textAlign: 'center', + boxSizing: 'border-box', + paddingTop: 1, + cursor: 'pointer' + }, + liquidityTooltip: { + background: colors.oraidex.component, + boxShadow: '0px 4px 18px rgba(0, 0, 0, 0.35)', + borderRadius: 20, + padding: 16, + maxWidth: 350, + boxSizing: 'border-box' + }, + liquidityTitle: { + color: colors.oraidex.text, + ...typography.heading4, + marginBottom: 8 + }, + liquidityDesc: { + color: colors.oraidex.text, + ...typography.caption1 + } +})); diff --git a/src/pages/Pool-V3/components/Statistics/TokenListItem/TokenListItem.tsx b/src/pages/Pool-V3/components/Statistics/TokenListItem/TokenListItem.tsx new file mode 100644 index 000000000..81f1434a3 --- /dev/null +++ b/src/pages/Pool-V3/components/Statistics/TokenListItem/TokenListItem.tsx @@ -0,0 +1,188 @@ +import React, { FunctionComponent } from 'react'; +import { colors, theme } from '../theme'; +import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown'; +import ArrowDropUpIcon from '@mui/icons-material/ArrowDropUp'; +import { useStyles } from './style'; +import { Grid, Typography, useMediaQuery } from '@mui/material'; +import { formatNumbers, showPrefix } from 'pages/Pool-V3/helpers/helper'; + +export enum SortType { + NAME_ASC, + NAME_DESC, + PRICE_ASC, + PRICE_DESC, + CHANGE_ASC, + CHANGE_DESC, + VOLUME_ASC, + VOLUME_DESC, + TVL_ASC, + TVL_DESC +} + +interface IProps { + displayType: string; + itemNumber?: number; + Icon?: FunctionComponent< + React.SVGProps & { + title?: string; + } + >; + name?: string; + symbol?: string; + price?: number; + priceChange?: number; + volume?: number; + TVL?: number; + sortType?: SortType; + onSort?: (type: SortType) => void; + hideBottomLine?: boolean; +} + +const TokenListItem: React.FC = ({ + displayType, + itemNumber = 0, + Icon, + symbol, + price = 0, + priceChange = 0, + volume = 0, + TVL = 0, + sortType, + onSort, + hideBottomLine = false +}) => { + const { classes } = useStyles(); + const isNegative = priceChange < 0; + + const isXDown = useMediaQuery(theme.breakpoints.down('sm')); + const hideName = useMediaQuery(theme.breakpoints.down('xs')); + + return ( + + {displayType === 'tokens' ? ( + + {!hideName && {itemNumber}} + + {/* {!isXDown && Token icon} */} + {!isXDown && } + + {symbol} + {/* {!hideName && {` (${symbol})`}} */} + + + {`~$${formatNumbers()(price.toString())}${showPrefix(price)}`} + {/* {!hideName && ( + + {isNegative ? `${priceChange.toFixed(2)}%` : `+${priceChange.toFixed(2)}%`} + + )} */} + {`$${formatNumbers()(volume.toString())}${showPrefix(volume)}`} + {`$${formatNumbers()(TVL.toString())}${showPrefix(TVL)}`} + + ) : ( + + {!hideName && ( + + No + + )} + { + if (sortType === SortType.NAME_ASC) { + onSort?.(SortType.NAME_DESC); + } else { + onSort?.(SortType.NAME_ASC); + } + }} + > + Name + {sortType === SortType.NAME_ASC ? ( + + ) : sortType === SortType.NAME_DESC ? ( + + ) : null} + + { + if (sortType === SortType.PRICE_ASC) { + onSort?.(SortType.PRICE_DESC); + } else { + onSort?.(SortType.PRICE_ASC); + } + }} + > + Price + {sortType === SortType.PRICE_ASC ? ( + + ) : sortType === SortType.PRICE_DESC ? ( + + ) : null} + + {/* {!hideName && ( + { + if (sortType === SortType.CHANGE_ASC) { + onSort?.(SortType.CHANGE_DESC) + } else { + onSort?.(SortType.CHANGE_ASC) + } + }}> + Price change + {sortType === SortType.CHANGE_ASC ? ( + + ) : sortType === SortType.CHANGE_DESC ? ( + + ) : null} + + )} */} + { + if (sortType === SortType.VOLUME_DESC) { + onSort?.(SortType.VOLUME_ASC); + } else { + onSort?.(SortType.VOLUME_DESC); + } + }} + > + Volume 24H + {sortType === SortType.VOLUME_ASC ? ( + + ) : sortType === SortType.VOLUME_DESC ? ( + + ) : null} + + { + if (sortType === SortType.TVL_DESC) { + onSort?.(SortType.TVL_ASC); + } else { + onSort?.(SortType.TVL_DESC); + } + }} + > + TVL + {sortType === SortType.TVL_ASC ? ( + + ) : sortType === SortType.TVL_DESC ? ( + + ) : null} + + + )} + + ); +}; +export default TokenListItem; diff --git a/src/pages/Pool-V3/components/Statistics/TokenListItem/style.ts b/src/pages/Pool-V3/components/Statistics/TokenListItem/style.ts new file mode 100644 index 000000000..c33793f36 --- /dev/null +++ b/src/pages/Pool-V3/components/Statistics/TokenListItem/style.ts @@ -0,0 +1,84 @@ +import { Theme } from '@mui/material'; +import { typography, colors } from '../theme'; +import { makeStyles } from 'tss-react/mui'; + +export const useStyles = makeStyles()((theme: Theme) => ({ + container: { + display: 'grid', + gridTemplateColumns: '5% 45% 15% 20% auto', + // gridTemplateColumns: 'repeat(5, 1fr)', + padding: '18px 0 ', + backgroundColor: colors.oraidex.component, + borderBottom: `1px solid ${colors.oraidex.light}`, + whiteSpace: 'nowrap', + + [theme.breakpoints.down('sm')]: { + gridTemplateColumns: '5% 35% 15% 17.5% 16.5% 15%', + '& p': { + ...typography.caption2 + } + }, + + [theme.breakpoints.down('xs')]: { + gridTemplateColumns: '28% 15% 30% 25%' + } + }, + + tokenList: { + color: colors.white.main, + '& p': { + ...typography.heading4 + }, + + [theme.breakpoints.down('sm')]: { + '& p': { + ...typography.caption1 + } + } + }, + + header: { + '& p': { + ...typography.heading4, + fontWeight: 400, + display: 'flex', + justifyContent: 'start', + alignItems: 'center' + }, + [theme.breakpoints.down('sm')]: { + '& p': { + ...typography.caption2 + } + } + }, + + tokenName: { + display: 'flex', + alignItems: 'center', + paddingRight: 5, + + '& p': { + overflow: 'hidden', + whiteSpace: 'nowrap', + textOverflow: 'ellipsis' + }, + + '& svg': { + minWidth: 28, + maxWidth: 28, + height: 28, + marginRight: 8, + borderRadius: '50%' + } + }, + + tokenSymbol: { + color: colors.oraidex.textGrey, + fontWeight: 400 + }, + icon: { + [theme.breakpoints.down('sm')]: { + marginLeft: -4 + } + } +})); diff --git a/src/pages/Pool-V3/components/Statistics/TokensList/TokensList.tsx b/src/pages/Pool-V3/components/Statistics/TokensList/TokensList.tsx new file mode 100644 index 000000000..11bc86dde --- /dev/null +++ b/src/pages/Pool-V3/components/Statistics/TokensList/TokensList.tsx @@ -0,0 +1,127 @@ +import TokenListItem, { SortType } from '../TokenListItem/TokenListItem'; +import React, { FunctionComponent, useEffect, useMemo, useState } from 'react'; +import { theme } from '../theme'; +import useStyles from './style'; +import { Grid, useMediaQuery } from '@mui/material'; +import { PaginationList } from '../PaginationList/PaginationList'; + +export interface ITokensListData { + icon: FunctionComponent< + React.SVGProps & { + title?: string; + } + >; + name: string; + symbol: string; + price: number; + priceChange: number; + volume: number; + TVL: number; +} + +export interface ITokensList { + data: ITokensListData[]; +} + +const TokensList: React.FC = ({ data }) => { + const { classes } = useStyles(); + const [page, setPage] = useState(1); + const [sortType, setSortType] = React.useState(SortType.VOLUME_DESC); + + const isXsDown = useMediaQuery(theme.breakpoints.down('xs')); + + const sortedData = useMemo(() => { + switch (sortType) { + case SortType.NAME_ASC: + return data.sort((a, b) => + isXsDown + ? a.symbol.localeCompare(b.symbol) + : `${a.name} (${a.symbol})`.localeCompare(`${b.name} (${b.symbol})`) + ); + case SortType.NAME_DESC: + return data.sort((a, b) => + isXsDown + ? b.symbol.localeCompare(a.symbol) + : `${b.name} (${b.symbol})`.localeCompare(`${a.name} (${a.symbol})`) + ); + case SortType.PRICE_ASC: + return data.sort((a, b) => a.price - b.price); + case SortType.PRICE_DESC: + return data.sort((a, b) => b.price - a.price); + case SortType.CHANGE_ASC: + return data.sort((a, b) => a.priceChange - b.priceChange); + case SortType.CHANGE_DESC: + return data.sort((a, b) => b.priceChange - a.priceChange); + case SortType.VOLUME_ASC: + return data.sort((a, b) => (a.volume === b.volume ? a.TVL - b.TVL : a.volume - b.volume)); + case SortType.VOLUME_DESC: + return data.sort((a, b) => (a.volume === b.volume ? b.TVL - a.TVL : b.volume - a.volume)); + case SortType.TVL_ASC: + return data.sort((a, b) => (a.TVL === b.TVL ? a.volume - b.volume : a.TVL - b.TVL)); + case SortType.TVL_DESC: + return data.sort((a, b) => (a.TVL === b.TVL ? b.volume - a.volume : b.TVL - a.TVL)); + } + }, [data, sortType, isXsDown]); + + useEffect(() => { + setPage(1); + }, [data]); + + const handleChangePagination = (page: number): void => { + setPage(page); + }; + function paginator(currentPage: number) { + const page = currentPage || 1; + const perPage = 10; + const offset = (page - 1) * perPage; + const paginatedItems = sortedData.slice(offset).slice(0, 10); + const totalPages = Math.ceil(data.length / perPage); + + return { + page: page, + totalPages: totalPages, + data: paginatedItems + }; + } + + const pages = Math.ceil(data.length / 10); + + return ( + +
+
+ + {paginator(page).data.map((token, index) => { + return ( + + ); + })} +
+
+ {pages > 1 ? ( + + + + ) : null} +
+ ); +}; + +export default TokensList; diff --git a/src/pages/Pool-V3/components/Statistics/TokensList/style.ts b/src/pages/Pool-V3/components/Statistics/TokensList/style.ts new file mode 100644 index 000000000..1f6789bb7 --- /dev/null +++ b/src/pages/Pool-V3/components/Statistics/TokensList/style.ts @@ -0,0 +1,28 @@ +import { colors, theme } from '../theme'; +import { makeStyles } from 'tss-react/mui'; + +export const useStyles = makeStyles()(() => ({ + container: { + padding: '0 24px', + borderRadius: '24px', + backgroundColor: colors.oraidex.component + }, + pagination: { + width: '100%', + display: 'flex', + justifyContent: 'center', + marginBlock: 10 + }, + listWrapper: { + [theme.breakpoints.down('md')]: { + overflowX: 'scroll' + } + }, + inner: { + [theme.breakpoints.down('md')]: { + minWidth: 576 + } + } +})); + +export default useStyles; diff --git a/src/pages/Pool-V3/components/Statistics/Volume/Volume.tsx b/src/pages/Pool-V3/components/Statistics/Volume/Volume.tsx new file mode 100644 index 000000000..6000b4fe4 --- /dev/null +++ b/src/pages/Pool-V3/components/Statistics/Volume/Volume.tsx @@ -0,0 +1,128 @@ +import React from 'react'; +import { ResponsiveBar } from '@nivo/bar'; +import classNames from 'classnames'; +import { colors, theme } from '../theme'; +import { linearGradientDef } from '@nivo/core'; +import { useStyles } from './style'; +import { TimeData } from '../hooks/useGetStatistic'; +import { Grid, Typography, useMediaQuery } from '@mui/material'; +import { Box } from '@mui/system'; +import { formatNumbers, showPrefix } from 'pages/Pool-V3/helpers/helper'; + +interface StatsInterface { + percentVolume: number; + volume: number; + data: TimeData[]; + className?: string; +} + +const Volume: React.FC = ({ percentVolume, volume, data, className }) => { + const { classes } = useStyles(); + + const isXsDown = useMediaQuery(theme.breakpoints.down('xs')); + + const Theme = { + axis: { + fontSize: '14px', + tickColor: 'transparent', + ticks: { line: { stroke: colors.oraidex.component }, text: { fill: '#A9B6BF' } }, + legend: { text: { stroke: 'transparent' } } + }, + grid: { line: { stroke: 'transparent' } } + }; + + const isLower = percentVolume < 0; + + return ( + + + Volume +
+ + ${formatNumbers()(volume.toString())} + {showPrefix(volume)} + + + + + {percentVolume == Infinity + ? `+9999` + : percentVolume < 0 + ? percentVolume.toFixed(2) + : `+${percentVolume.toFixed(2)}`} + % + + + +
+
+
+ } + keys={['value']} + indexBy="timestamp" + axisBottom={{ + tickSize: 0, + tickPadding: 10, + tickRotation: 0, + format: (time) => { + const date = new Date(time); + const day = date.getDate(); + const month = date.getMonth() + 1; + + const dayMod = + Math.floor(time / (1000 * 60 * 60 * 24)) % (data.length >= 24 ? 4 : data.length >= 8 ? 2 : 1); + + return newDayMod(dayMod, day, month); + } + }} + theme={Theme} + groupMode="grouped" + enableLabel={false} + enableGridY={false} + innerPadding={isXsDown ? 1 : 2} + isInteractive + padding={0.03} + indexScale={{ type: 'band', round: true }} + defs={[ + linearGradientDef('gradient', [ + { offset: 0, color: '#EF84F5' }, + { offset: 100, color: '#9C3EBD', opacity: 0.7 } + ]) + ]} + fill={[{ match: '*', id: 'gradient' }]} + colors={colors.oraidex.pink} + tooltip={({ data }) => { + const date = new Date(data.timestamp); + const day = date.getDate(); + const month = date.getMonth() + 1; + + return ( + + {`${day < 10 ? '0' : ''}${day}/${ + month < 10 ? '0' : '' + }${month}`} + ${data.value.toFixed(2)} + + ); + }} + /> +
+
+ ); +}; + +export default Volume; + +function newDayMod(dayMod: number, day: number, month: number): any { + return dayMod === 0 ? `${day < 10 ? '0' : ''}${day}/${month < 10 ? '0' : ''}${month}` : ''; +} diff --git a/src/pages/Pool-V3/components/Statistics/Volume/style.ts b/src/pages/Pool-V3/components/Statistics/Volume/style.ts new file mode 100644 index 000000000..2b211ce25 --- /dev/null +++ b/src/pages/Pool-V3/components/Statistics/Volume/style.ts @@ -0,0 +1,82 @@ +import { typography, colors } from '../theme'; +import { makeStyles } from 'tss-react/mui'; + +export const useStyles = makeStyles()(() => ({ + container: { + backgroundColor: colors.oraidex.component, + borderRadius: 24, + padding: 24, + boxSizing: 'border-box' + }, + volumeContainer: { + display: 'flex', + flexDirection: 'column', + alignItems: 'flex-start', + fontWeight: 'normal' + }, + volumeHeader: { + color: colors.oraidex.textGrey, + ...typography.body2 + }, + volumePercentContainer: { + display: 'flex', + alignItems: 'center' + }, + volumePercentHeader: { + ...typography.heading1, + letterSpacing: '-0.03em', + color: colors.white.main, + marginTop: 5 + }, + volumeStatusContainer: { + marginLeft: 10, + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + minWidth: 'auto' + }, + volumeStatusColor: { + height: 30, + minWidth: 'auto', + padding: '5px 15px 5px 15px', + borderRadius: 6 + }, + + volumeStatusHeader: { + ...typography.body1, + filter: 'brightness(1.2)' + }, + barContainer: { + height: 200, + display: 'flex' + }, + volumeLow: { + color: colors.oraidex.Error + }, + backgroundVolumeLow: { + backgroundColor: 'rgba(251,85,95,0.2)' + }, + backgroundVolumeUp: { + backgroundColor: 'rgba(46, 224, 149,0.2)' + }, + volumeUp: { + color: colors.oraidex.green + }, + tooltip: { + background: colors.oraidex.component, + border: `1px solid ${colors.oraidex.lightGrey}`, + borderRadius: 5, + width: 100, + padding: 5 + }, + tooltipDate: { + ...typography.caption4, + color: colors.white.main, + textAlign: 'center' + }, + tooltipValue: { + ...typography.caption3, + color: colors.oraidex.pink, + textAlign: 'center' + } +})); diff --git a/src/pages/Pool-V3/components/Statistics/WrappedStats/WrappedStats.tsx b/src/pages/Pool-V3/components/Statistics/WrappedStats/WrappedStats.tsx new file mode 100644 index 000000000..38a81aa63 --- /dev/null +++ b/src/pages/Pool-V3/components/Statistics/WrappedStats/WrappedStats.tsx @@ -0,0 +1,146 @@ +import React, { useEffect, useState } from 'react'; +import loader from 'assets/gif/loading.gif'; +import useStyles from './styles'; +import { Grid, Typography } from '@mui/material'; +import { EmptyPlaceholder } from '../EmptyPlaceholder/EmptyPlaceholder'; + +import Volume from '../Volume/Volume'; +import Liquidity from '../Liquidity/Liquidity'; +import VolumeBar from '../volumeBar/VolumeBar'; +import TokensList from '../TokensList/TokensList'; +import PoolList from '../PoolList/PoolList'; +import useGetStatistic from '../hooks/useGetStatistic'; +import LoadingBox from 'components/LoadingBox'; + +export const WrappedStats: React.FC = () => { + const { classes } = useStyles(); + const [isLoadingStats, setLoading] = useState(false); + const [stats, setStats] = useState({ + volume24: { + value: 0, + change: 0 + }, + tvl24: { + value: 0, + change: 0 + }, + fees24: { + value: 0, + change: 0 + }, + tokensData: [], + poolsData: [], + volumePlot: [], + liquidityPlot: [] + }); + const { getStats } = useGetStatistic(); + + const { + volume24: volume24h, + tvl24: tvl24h, + fees24: fees24h, + tokensData, + poolsData, + volumePlot: volumePlotData, + liquidityPlot: liquidityPlotData + } = stats; + + useEffect(() => { + (async () => { + setLoading(true); + const data = await getStats(); + + if (data) { + setStats(data); + } + setLoading(false); + })(); + }, []); + + // isLoadingStats ? ( + // Loading + // ) : + return ( + + + {!isLoadingStats && liquidityPlotData.length === 0 ? ( + + + + ) : ( + !isLoadingStats && ( + <> + Overview + + + + + + + + Top tokens + + ({ + icon: tokenData.Icon, + name: tokenData.tokenInfo.name, + symbol: tokenData.tokenInfo.name, + price: tokenData.price, + priceChange: tokenData.priceChange, + volume: tokenData.volume24, + TVL: tokenData.tvl + }))} + /> + + Top pools + ({ + symbolFrom: poolData.tokenXinfo.name, + symbolTo: poolData.tokenYinfo.name, + iconFrom: poolData.FromTokenIcon, + iconTo: poolData.ToTokenIcon, + volume: poolData.volume24, + TVL: poolData.tvl, + fee: poolData.fee, + apy: poolData.apy + // apyData: { + // fees: poolData.apy, + // accumulatedFarmsSingleTick: 0, + // accumulatedFarmsAvg: 0 + // }, + // apy: + // poolData.apy + (accumulatedSingleTickAPY?.[poolData.poolAddress.toString()] ?? 0), + // apyData: { + // fees: poolData.apy, + // accumulatedFarmsSingleTick: + // accumulatedSingleTickAPY?.[poolData.poolAddress.toString()] ?? 0, + // accumulatedFarmsAvg: accumulatedAverageAPY?.[poolData.poolAddress.toString()] ?? 0 + // } + }))} + /> + + ) + )} + + + ); +}; + +export default WrappedStats; diff --git a/src/pages/Pool-V3/components/Statistics/WrappedStats/mockStats.ts b/src/pages/Pool-V3/components/Statistics/WrappedStats/mockStats.ts new file mode 100644 index 000000000..b00056f6f --- /dev/null +++ b/src/pages/Pool-V3/components/Statistics/WrappedStats/mockStats.ts @@ -0,0 +1,196 @@ +export const poolsList = Array(40) + .fill({}) + .map(() => { + const randomVolume = Math.random() * 1000000000 + const randomTVL = Math.random() * 500000000 + const randomFee = +(Math.random() * 500).toFixed(2) + const randomApy = Math.random() * 5000000000 + const randomVolume24 = Math.random() * 1000 + const randomTvl24 = Math.random() * 100000 + const randomApyDataFees = Math.random() * 100 + const randomAccumulatedFarmsAvg = Math.random() * 1000 + const randomAccumulatedFarmsSingleTick = Math.random() * 2000 + + return { + symbolFrom: 'BCT', + symbolTo: 'USDT', + iconFrom: + 'https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/So11111111111111111111111111111111111111112/logo.png', + iconTo: + 'https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB/logo.svg', + volume: randomVolume, + TVL: randomTVL, + fee: randomFee, + apy: randomApy, + apyData: { + fees: randomApyDataFees, + accumulatedFarmsAvg: randomAccumulatedFarmsAvg, + accumulatedFarmsSingleTick: randomAccumulatedFarmsSingleTick + }, + tokenXDetails: { + address: '5Dvb5E8zKU4E9c7YxfNL5VC8YQj4VAFUTCGYY9ayFLnnY3UA', + chainId: 101, + decimals: 6, + name: 'UST (Portal)', + symbol: 'UST', + logoURI: + 'https://raw.githubusercontent.com/wormhole-foundation/wormhole-token-list/main/assets/UST_wh.png', + tags: ['wormhole', 'old-registry'], + extensions: { coingeckoId: 'terrausd-wormhole' }, + coingeckoId: 'terrausd-wormhole' + }, + tokenYDetails: { + address: '5Dvb5E8zKU4E9c7YxfNL5VC8YQj4VAFUTCGYY9ayFLnnY3UA', + chainId: 101, + decimals: 6, + name: 'USD Coin', + symbol: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v/logo.png', + tags: ['old-registry', 'solana-fm'], + extensions: { coingeckoId: 'usd-coin' }, + coingeckoId: 'usd-coin' + }, + volume24: randomVolume24, + tvl: randomTvl24 + } + }) + +export const tokensList = [ + { + icon: 'https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/So11111111111111111111111111111111111111112/logo.png', + name: 'Wrapped SOL', + symbol: 'SOL', + price: 123.321321452, + priceChange: 0.123, + volume: 421323423.23, + tvl: 32065.79898800001, + tokenDetails: { + address: '5Dvb5E8zKU4E9c7YxfNL5VC8YQj4VAFUTCGYY9ayFLnnY3UA', + chainId: 101, + decimals: 6, + name: 'USD Coin', + symbol: 'USDC', + logoURI: + 'https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v/logo.png', + tags: ['old-registry', 'solana-fm'], + extensions: { coingeckoId: 'usd-coin' }, + coingeckoId: 'usd-coin' + }, + volume24: 841.2384 + }, + { + icon: 'https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB/logo.svg', + name: 'USDT', + symbol: 'USDT', + price: 1.321452, + priceChange: 2, + volume: 421323423.23, + tvl: 234413532.43, + tokenDetails: { + address: '5Dvb5E8zKU4E9c7YxfNL5VC8YQj4VAFUTCGYY9ayFLnnY3UA', + chainId: 101, + decimals: 9, + name: 'Wrapped SOL', + symbol: 'SOL', + logoURI: + 'https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/So11111111111111111111111111111111111111112/logo.png', + tags: ['old-registry'], + extensions: { coingeckoId: 'wrapped-solana' }, + coingeckoId: 'wrapped-solana' + }, + volume24: 21.2384 + }, + { + icon: 'https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v/logo.png', + name: 'USD Coin', + symbol: 'USDC', + price: 1.0, + priceChange: 0.83, + volume: 421323423.23, + tvl: 234413532.43, + tokenDetails: { + address: '5Dvb5E8zKU4E9c7YxfNL5VC8YQj4VAFUTCGYY9ayFLnnY3UA', + chainId: 101, + decimals: 9, + name: 'Wrapped SOL', + symbol: 'SOL', + logoURI: + 'https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/So11111111111111111111111111111111111111112/logo.png', + tags: ['old-registry'], + extensions: { coingeckoId: 'wrapped-solana' }, + coingeckoId: 'wrapped-solana' + }, + volume24: 8241.2384 + } +] + +export const volume24h = { value: 4022333.4231874547, change: -52.239195549272985 } + +export const tvl24h = { value: 279204.3080979749, change: -3.604507854550285 } + +export const fees24h = { value: 599.544959417, change: -47.79969743772543 } + +export const volumePlotData = [ + { timestamp: 1716552000000, value: 4512625.608953071 }, + { timestamp: 1716638400000, value: 2696192.124473429 }, + { timestamp: 1716724800000, value: 1659467.054644387 }, + { timestamp: 1716811200000, value: 2478284.0069509996 }, + { timestamp: 1716897600000, value: 4066913.005100426 }, + { timestamp: 1717070400000, value: 8535283.141011314 }, + { timestamp: 1717156800000, value: 3057580.304299723 }, + { timestamp: 1717243200000, value: 3438682.6270488105 }, + { timestamp: 1717329600000, value: 2405098.563568 }, + { timestamp: 1717416000000, value: 3010963.8025822206 }, + { timestamp: 1717502400000, value: 3361458.9228925616 }, + { timestamp: 1717588800000, value: 4530301.107894169 }, + { timestamp: 1717675200000, value: 4650692.700283449 }, + { timestamp: 1717761600000, value: 6302225.768652554 }, + { timestamp: 1717848000000, value: 7763069.118376541 }, + { timestamp: 1717934400000, value: 3534570.8735763766 }, + { timestamp: 1718020800000, value: 3844000.33935 }, + { timestamp: 1718107200000, value: 4168392.436431511 }, + { timestamp: 1718193600000, value: 4212258.790136831 }, + { timestamp: 1718280000000, value: 4115531.3857006463 }, + { timestamp: 1718366400000, value: 2844247.1688079913 }, + { timestamp: 1718452800000, value: 3571590.550698615 }, + { timestamp: 1718539200000, value: 1919774.698571 }, + { timestamp: 1718625600000, value: 3474827.407744309 }, + { timestamp: 1718712000000, value: 6270210.212383572 }, + { timestamp: 1718798400000, value: 8944805.2201305 }, + { timestamp: 1718884800000, value: 8421829.300084637 }, + { timestamp: 1718971200000, value: 4022333.4231874547 } +] + +export const liquidityPlotData = [ + { timestamp: 1716552000000, value: 283814.9853831609 }, + { timestamp: 1716638400000, value: 296563.856253402 }, + { timestamp: 1716724800000, value: 279605.94078915595 }, + { timestamp: 1716811200000, value: 286414.33889901394 }, + { timestamp: 1716897600000, value: 289328.01251464605 }, + { timestamp: 1717070400000, value: 291109.37093950785 }, + { timestamp: 1717156800000, value: 299144.8861490599 }, + { timestamp: 1717243200000, value: 286275.867182114 }, + { timestamp: 1717329600000, value: 269892.904872398 }, + { timestamp: 1717416000000, value: 267545.83903459297 }, + { timestamp: 1717502400000, value: 263298.0398656629 }, + { timestamp: 1717588800000, value: 267228.09554199304 }, + { timestamp: 1717675200000, value: 264501.37196904595 }, + { timestamp: 1717761600000, value: 265863.77726675477 }, + { timestamp: 1717848000000, value: 402046.74954411597 }, + { timestamp: 1717934400000, value: 414647.28326416895 }, + { timestamp: 1718020800000, value: 412864.8249698 }, + { timestamp: 1718107200000, value: 425187.23476959986 }, + { timestamp: 1718193600000, value: 427589.885517467 }, + { timestamp: 1718280000000, value: 433799.8806224759 }, + { timestamp: 1718366400000, value: 463301.1012211619 }, + { timestamp: 1718452800000, value: 469062.1202646391 }, + { timestamp: 1718539200000, value: 460250.9162467961 }, + { timestamp: 1718625600000, value: 449104.74350912473 }, + { timestamp: 1718712000000, value: 427811.60435006284 }, + { timestamp: 1718798400000, value: 287254.4826316768 }, + { timestamp: 1718884800000, value: 289644.56935049174 }, + { timestamp: 1718971200000, value: 279204.3080979749 } +] + +export const isLoadingStats = false diff --git a/src/pages/Pool-V3/components/Statistics/WrappedStats/styles.ts b/src/pages/Pool-V3/components/Statistics/WrappedStats/styles.ts new file mode 100644 index 000000000..0e66fa21e --- /dev/null +++ b/src/pages/Pool-V3/components/Statistics/WrappedStats/styles.ts @@ -0,0 +1,48 @@ +import { Theme } from '@mui/material'; +import { typography, colors } from '../theme'; +import { makeStyles } from 'tss-react/mui'; + +export const useStyles = makeStyles()((theme: Theme) => ({ + wrapper: { + minHeight: '100%' + }, + subheader: { + ...typography.heading4, + color: colors.white.main, + marginBottom: 16 + }, + plotsRow: { + marginBottom: 24, + flexDirection: 'row', + + [theme.breakpoints.down('sm')]: { + flexDirection: 'column' + } + }, + row: { + marginBottom: 16 + }, + loading: { + width: 150, + height: 150, + margin: 'auto' + }, + plot: { + width: '100%', + + '&:first-child': { + marginRight: 24 + }, + + [theme.breakpoints.down('sm')]: { + width: '100%', + + '&:first-child': { + marginRight: 0, + marginBottom: 24 + } + } + } +})); + +export default useStyles; diff --git a/src/pages/Pool-V3/components/Statistics/hooks/useGetStatistic.ts b/src/pages/Pool-V3/components/Statistics/hooks/useGetStatistic.ts new file mode 100644 index 000000000..9d25b2554 --- /dev/null +++ b/src/pages/Pool-V3/components/Statistics/hooks/useGetStatistic.ts @@ -0,0 +1,363 @@ +import { TokenItemType } from '@oraichain/oraidex-common'; +import { oraichainTokensWithIcon } from 'config/chainInfos'; +import { useCoinGeckoPrices } from 'hooks/useCoingecko'; +import SingletonOraiswapV3, { poolKeyToString } from 'libs/contractSingleton'; +import axios from 'rest/request'; +import { extractAddress, TokenDataOnChain } from '../../PriceRangePlot/utils'; +import { getIconPoolData, getTokenInfo } from 'pages/Pool-V3/helpers/format'; + +export interface PoolWithStringKey extends PoolStructure { + poolKey: string; +} + +export interface TimeData { + timestamp: number; + value: number; +} + +export interface TokenStatsData { + address: string; + price: number; + priceChange: number; + volume24: number; + tvl: number; +} + +export interface PoolStatsData { + poolAddress: string; + tokenX: string; + tokenY: string; + fee: number; + volume24: number; + tvl: number; + apy: number; +} + +export interface PoolStructure { + tokenX: string; + tokenY: string; + fee: bigint; +} +export interface SnapshotValueData { + tokenBNFromBeginning: string; + usdValue24: number; +} + +export interface PoolSnapshot { + timestamp: number; + volumeX: SnapshotValueData; + volumeY: SnapshotValueData; + liquidityX: SnapshotValueData; + liquidityY: SnapshotValueData; + feeX: SnapshotValueData; + feeY: SnapshotValueData; +} + +export interface TokenPriceData { + price: number; +} + +export interface Token { + symbol: string; + address: string; + decimals: number; + name: string; + logoURI: string; + balance?: bigint; + coingeckoId?: string; + isUnknown?: boolean; +} + +export const getNetworkStats = async (): Promise> => { + const { data } = await axios.get>(`https://api.oraidex.io/v1/pool-v3/status`); + + return data; +}; + +export const formatTokenList = (): Record => { + return oraichainTokensWithIcon.reduce((acc, cur) => { + const key = extractAddress(cur); + + acc[key] = { + ...cur, + symbol: cur.name, + address: key, + decimals: cur.decimals, + name: cur.name + }; + + return acc; + }, {}); +}; + +export const getPoolsFromAddresses = async (): Promise => { + const pools = await SingletonOraiswapV3.getPools(); + + const poolWithStringKey: PoolWithStringKey[] = pools.map((pool) => { + return { + tokenX: pool.pool_key.token_x, + tokenY: pool.pool_key.token_y, + fee: BigInt(pool.pool_key.fee_tier.fee), + poolKey: poolKeyToString(pool.pool_key) + }; + }); + + return poolWithStringKey; +}; + +export const getTokenDataByAddresses = async (tokens: string[], address?: string): Promise> => { + const tokenInfos: TokenDataOnChain[] = await SingletonOraiswapV3.getTokensInfo(tokens, address); + + const newTokens: Record = {}; + tokenInfos.forEach((token) => { + newTokens[token.address] = { + symbol: token.symbol ? (token.symbol as string) : 'UNKNOWN', + address: token.address, + name: token.name ? (token.name as string) : '', + decimals: token.decimals, + balance: token.balance, + logoURI: '/unknownToken.svg', + isUnknown: true + }; + }); + return newTokens; +}; + +const useGetStatistic = () => { + const { data: prices } = useCoinGeckoPrices(); + + const getStats = async () => { + try { + // get pool data snapshoted + const data = await getNetworkStats(); + + // get all pool data aggregated + const allPoolsData = await getPoolsFromAddresses(); // (Object.keys(data)); + + // transform aggregated pool data to object: poolKey in string -> poolData + const poolsDataObject: Record = {}; + allPoolsData.forEach((pool) => { + poolsDataObject[pool.poolKey.toString()] = pool; + }); + + // get all tokens we have + const allTokens = formatTokenList(); + + // prepare price for each tokens + const preparedTokens: Record> = {}; + Object.entries(allTokens).forEach(([key, val]) => { + if (typeof val.coinGeckoId !== 'undefined') { + preparedTokens[key] = val as Required; + } + }); + + const volume24 = { + value: 0, + change: 0 + }; + const tvl24 = { + value: 0, + change: 0 + }; + const fees24 = { + value: 0, + change: 0 + }; + + const tokensDataObject: Record = {}; + let poolsData: PoolStatsData[] = []; + + const volumeForTimestamps: Record = {}; + const liquidityForTimestamps: Record = {}; + const feesForTimestamps: Record = {}; + + const lastTimestamp = Math.max( + ...Object.values(data) + .filter((snaps) => snaps.length > 0) + .map((snaps) => +snaps[snaps.length - 1].timestamp) + ); + + Object.entries(data).forEach(([address, snapshots]) => { + if (!poolsDataObject[address]) { + return; + } + + const tokenXId = allTokens?.[poolsDataObject[address].tokenX.toString()]?.coinGeckoId ?? ''; + + const tokenYId = preparedTokens?.[poolsDataObject[address].tokenY.toString()]?.coinGeckoId ?? ''; + + if (!tokensDataObject[poolsDataObject[address].tokenX.toString()]) { + tokensDataObject[poolsDataObject[address].tokenX.toString()] = { + address: poolsDataObject[address].tokenX, + price: prices?.[tokenXId] ?? 0, + volume24: 0, + tvl: 0, + priceChange: 0 + }; + } + + if (!tokensDataObject[poolsDataObject[address].tokenY.toString()]) { + tokensDataObject[poolsDataObject[address].tokenY.toString()] = { + address: poolsDataObject[address].tokenY, + price: prices?.[tokenYId] ?? 0, + volume24: 0, + tvl: 0, + priceChange: 0 + }; + } + + if (!snapshots.length) { + poolsData.push({ + volume24: 0, + tvl: 0, + tokenX: poolsDataObject[address].tokenX, + tokenY: poolsDataObject[address].tokenY, + // TODO: hard code decimals + fee: Number(poolsDataObject[address].fee), + apy: 0, // TODO: calculate apy + poolAddress: address + }); + return; + } + + const tokenX = allTokens[poolsDataObject[address].tokenX.toString()]; + const tokenY = allTokens[poolsDataObject[address].tokenY.toString()]; + + const lastSnapshot = snapshots[snapshots.length - 1]; + + tokensDataObject[tokenX.address.toString()].volume24 += + lastSnapshot.timestamp === lastTimestamp ? lastSnapshot.volumeX.usdValue24 : 0; + tokensDataObject[tokenY.address.toString()].volume24 += + lastSnapshot.timestamp === lastTimestamp ? lastSnapshot.volumeY.usdValue24 : 0; + tokensDataObject[tokenX.address.toString()].tvl += lastSnapshot.liquidityX.usdValue24; + tokensDataObject[tokenY.address.toString()].tvl += lastSnapshot.liquidityY.usdValue24; + + poolsData.push({ + volume24: + lastSnapshot.timestamp === lastTimestamp + ? lastSnapshot.volumeX.usdValue24 + lastSnapshot.volumeY.usdValue24 + : 0, + tvl: + lastSnapshot.timestamp === lastTimestamp + ? lastSnapshot.liquidityX.usdValue24 + lastSnapshot.liquidityY.usdValue24 + : 0, + tokenX: poolsDataObject[address].tokenX, + tokenY: poolsDataObject[address].tokenY, + fee: Number(poolsDataObject[address].fee), + apy: 0, // TODO: calculate apy + poolAddress: address + }); + + snapshots.slice(-30).forEach((snapshot) => { + const timestamp = snapshot.timestamp.toString(); + + if (!volumeForTimestamps[timestamp]) { + volumeForTimestamps[timestamp] = 0; + } + + if (!liquidityForTimestamps[timestamp]) { + liquidityForTimestamps[timestamp] = 0; + } + + if (!feesForTimestamps[timestamp]) { + feesForTimestamps[timestamp] = 0; + } + + volumeForTimestamps[timestamp] += snapshot.volumeX.usdValue24 + snapshot.volumeY.usdValue24; + liquidityForTimestamps[timestamp] += snapshot.liquidityX.usdValue24 + snapshot.liquidityY.usdValue24; + feesForTimestamps[timestamp] += snapshot.feeX.usdValue24 + snapshot.feeY.usdValue24; + }); + }); + + const volumePlot: TimeData[] = Object.entries(volumeForTimestamps) + .map(([timestamp, value]) => ({ + timestamp: +timestamp, + value + })) + .sort((a, b) => a.timestamp - b.timestamp); + const liquidityPlot: TimeData[] = Object.entries(liquidityForTimestamps) + .map(([timestamp, value]) => ({ + timestamp: +timestamp, + value + })) + .sort((a, b) => a.timestamp - b.timestamp); + const feePlot: TimeData[] = Object.entries(feesForTimestamps) + .map(([timestamp, value]) => ({ + timestamp: +timestamp, + value + })) + .sort((a, b) => a.timestamp - b.timestamp); + + const tiersToOmit = [0.001, 0.003]; + + poolsData = poolsData.filter((pool) => !tiersToOmit.includes(pool.fee)); + + volume24.value = volumePlot.length ? volumePlot[volumePlot.length - 1].value : 0; + tvl24.value = liquidityPlot.length ? liquidityPlot[liquidityPlot.length - 1].value : 0; + fees24.value = feePlot.length ? feePlot[feePlot.length - 1].value : 0; + + const prevVolume24 = volumePlot.length > 1 ? volumePlot[volumePlot.length - 2].value : 0; + const prevTvl24 = liquidityPlot.length > 1 ? liquidityPlot[liquidityPlot.length - 2].value : 0; + const prevFees24 = feePlot.length > 1 ? feePlot[feePlot.length - 2].value : 0; + + volume24.change = ((volume24.value - prevVolume24) / prevVolume24) * 100; + tvl24.change = ((tvl24.value - prevTvl24) / prevTvl24) * 100; + fees24.change = ((fees24.value - prevFees24) / prevFees24) * 100; + + const fmtPoolData = poolsData.map((p) => { + const iconsData = getIconPoolData(p.tokenX, p.tokenY, false); + + return { + ...iconsData, + ...p + }; + }); + + const fmtTokenData = Object.values(tokensDataObject).map((tk) => { + const iconsData = getTokenInfo(tk.address, false); + + return { + ...iconsData, + ...tk + }; + }); + + return { + volume24, + tvl24, + fees24, + tokensData: fmtTokenData, + poolsData: fmtPoolData, + volumePlot, + liquidityPlot + }; + } catch (error) { + console.log(error); + + return { + volume24: { + value: 0, + change: 0 + }, + tvl24: { + value: 0, + change: 0 + }, + fees24: { + value: 0, + change: 0 + }, + tokensData: [], + poolsData: [], + volumePlot: [], + liquidityPlot: [] + }; + } + }; + + return { + getStats + }; +}; + +export default useGetStatistic; diff --git a/src/pages/Pool-V3/components/Statistics/theme/index.ts b/src/pages/Pool-V3/components/Statistics/theme/index.ts new file mode 100644 index 000000000..3f032b952 --- /dev/null +++ b/src/pages/Pool-V3/components/Statistics/theme/index.ts @@ -0,0 +1,223 @@ +// theme.ts +import { createTheme } from '@mui/material/styles'; + +export const colors = { + black: { + full: '#000000', + background: '#1B1C2A', // v2.0 + light: '#090B1B', + kinda: '#1A1A1A', + greyish: '#081323', + cinder: '#0E0C12', // v2.0 background color + controls: '#44424E', // v2.0 controls background color + header: '#1A1D28', // v2.0 header + card: '#28242E' // v2.0 card color + }, + blue: { + accent: '#072E5A', + subtle: 'rgba(7,46,90,0.1)', + deepAccent: 'rgba(7,46,90,0.5)', + base: '#0B2545', + light: '#66AFF5', + neon: '#08F7FE', + astel: '#48ADF1', + bastille: '#1E1A23', + charade: '#272735', // v2.0 component + deep: '#4B5983' + }, + green: { + main: '#00F9BB', + // button: '#40BFA0', + button: '#aee67f', + hover: 'rgba(0,249,187,0.15)', + pastel: '#8AF7E4', + snackbar: '#4BB724', + shine: '#AEE57E' + }, + white: { + main: '#FFFFFF' + }, + red: { + main: '#EB5757', + error: '#C52727', + neon: '#FF2079', + pinkish: '#FE53BB', + snackbar: '#DE3232' + }, + yellow: { + neon: '#F5D300' + }, + navy: { + // colors with suffix "2" on figma + background: '#0C0D2C', + dark: '#0E0E2A', + component: '#1D1D49', + navBar: 'rgba(249, 249, 251, 0.76)', + navButton: '#3A3A85', + grey: '#A3A8CE', + lightGrey: '#DADCF1', + veryLightGrey: '#FBFBFB', + button: '#655ED4', + info: '#6261A3', + darkGrey: '#292956', + tooltip: '#5B54CE', + '5756B3': '#5756B3', + '807ADC': '#807ADC' + }, + oraidex: { + neutralText: '#979995', + neutralTextLight: '#EFEFEF', + border: '#595B57', + warning: '#EFD063', + pink: '#EF84F5', + violet: '#9C3EBD', + green: '#2EE09A', + dark: '#040B22', + newDark: '#232521', + component: '#181a17', + componentBcg: '#232521', + light: '#494949', + lightHover: '#A9B6BF', + black: '#232521', + textGrey: '#A9B6BF', + lightGrey: '#A9B6BF', + text: '#F7F7F7', + Error: '#FB555F', + greenLinearGradient: '#aee67f', + greenLinearGradientOpacity: '#aee67f', + pinkLinearGradient: 'linear-gradient(180deg, #EF84F5 0%, #9C3EBD 100%)', + pinkLinearGradientOpacity: 'linear-gradient(180deg, rgba(239, 132, 245, 0.8) 0%, rgba(156, 62, 189, 0.8) 100%)', + yellow: '#EFD063', + blue: '#43BBFF' + } +}; + +export const typography = { + heading1: { + fontSize: 32, + lineHeight: '36px', + fontWeight: 700 + }, + heading2: { + fontSize: 28, + lineHeight: '32px', + fontWeight: 700 + }, + heading3: { + fontSize: 24, + lineHeight: '28px', + fontWeight: 700 + }, + heading4: { + fontSize: 14, + lineHeight: '20px', + fontWeight: 400 + }, + heading5: { + fontSize: 18, + lineHeight: 1.5, + fontWeight: 500 + }, + body1: { + fontSize: 16, + lineHeight: '20px', + fontWeight: 500 + }, + body2: { + fontSize: 16, + lineHeight: '20px', + fontWeight: 400 + }, + body3: { + fontSize: 20, + lineHeight: '24px', + fontWeight: 400 + }, + body4: { + fontSize: 13, + lineHeight: 1.5, + fontWeight: 400 + }, + caption1: { + fontSize: 14, + lineHeight: '17px', + fontWeight: 700 + }, + caption2: { + fontSize: 14, + lineHeight: '17px', + fontWeight: 400 + }, + caption3: { + fontSize: 12, + lineHeight: '15px', + fontWeight: 700 + }, + caption4: { + fontSize: 12, + lineHeight: '16px', + fontWeight: 400 + }, + tiny1: { + fontSize: 10, + lineHeight: '13px', + fontWeight: 700 + }, + tiny2: { + fontSize: 10, + lineHeight: '13px', + fontWeight: 400 + } +}; + +// Create a theme instance. +export const theme = createTheme({ + palette: { + primary: { + main: colors.navy.button, // v2.0 + contrastText: colors.navy.veryLightGrey // v2.0 + }, + secondary: { + main: colors.green.button, + contrastText: colors.navy.background + }, + text: { + primary: '#FFFFFF', + secondary: '#595B57' + }, + error: { + main: '#E15757' + } + }, + typography: { + fontWeightRegular: 500, + h1: typography.heading1, + h2: typography.heading2, + h3: typography.heading3, + h4: typography.heading4, + body1: typography.body1, + body2: typography.body2, + body3: typography.body3, + caption: typography.caption1 + }, + breakpoints: { + values: { + xs: 0, + sm: 600, + md: 960, + lg: 1280, + xl: 1920 + } + } + // overrides: { + // MuiInputBase: { + // input: { + // MozAppearance: "textfield", + // "&::-webkit-clear-button, &::-webkit-outer-spin-button, &::-webkit-inner-spin-button": + // { + // display: "none", + // }, + // }, + // }, + // }, +}); diff --git a/src/pages/Pool-V3/components/Statistics/theme/types.ts b/src/pages/Pool-V3/components/Statistics/theme/types.ts new file mode 100644 index 000000000..4d5109ef9 --- /dev/null +++ b/src/pages/Pool-V3/components/Statistics/theme/types.ts @@ -0,0 +1,19 @@ +import '@mui/material/styles' + +declare module '@mui/material/styles' { + interface TypographyVariants { + body3: React.CSSProperties + } + + // allow configuration using `createTheme` + interface TypographyVariantsOptions { + body3?: React.CSSProperties + } +} + +// Update the TypographyProps interface if you plan to use the variant in the Typography component +declare module '@mui/material/Typography' { + interface TypographyPropsVariantOverrides { + body3: true + } +} diff --git a/src/pages/Pool-V3/components/Statistics/volumeBar/VolumeBar.tsx b/src/pages/Pool-V3/components/Statistics/volumeBar/VolumeBar.tsx new file mode 100644 index 000000000..e0ca9d4b8 --- /dev/null +++ b/src/pages/Pool-V3/components/Statistics/volumeBar/VolumeBar.tsx @@ -0,0 +1,76 @@ +import React from 'react'; +import classNames from 'classnames'; +import { theme } from '../theme'; +import { useStyles } from './style'; +import { Box, Grid, Typography, useMediaQuery } from '@mui/material'; +import { formatNumbers, showPrefix } from 'pages/Pool-V3/helpers/helper'; + +interface Iprops { + percentVolume: number; + volume: number; + tvlVolume: number; + percentTvl: number; + feesVolume: number; + percentFees: number; +} + +const VolumeBar: React.FC = ({ percentVolume, volume, tvlVolume, percentTvl, feesVolume, percentFees }) => { + const { classes } = useStyles(); + + const isXDown = useMediaQuery(theme.breakpoints.down('xs')); + + return ( + + + Volume 24H: + + ${formatNumbers()(volume.toString())} + {showPrefix(volume)} + + {!isXDown && ( + + {percentVolume === Infinity + ? '(+9999%)' + : percentVolume < 0 + ? `(${percentVolume.toFixed(2)}%)` + : `(+${percentVolume.toFixed(2)}%)`} + + )} + + + TVL 24H: + + ${formatNumbers()(tvlVolume.toString())} + {showPrefix(tvlVolume)} + + {!isXDown && ( + + {percentTvl < 0 ? `(${percentTvl.toFixed(2)}%)` : `(+${percentTvl.toFixed(2)}%)`} + + )} + + + Fees 24H: + + ${formatNumbers()(feesVolume.toString())} + {showPrefix(feesVolume)} + + {!isXDown && ( + + {percentFees === Infinity + ? '(+9999%)' + : percentFees < 0 + ? `(${percentFees.toFixed(2)}%)` + : `(+${percentFees.toFixed(2)}%)`} + + )} + + + ); +}; + +export default VolumeBar; diff --git a/src/pages/Pool-V3/components/Statistics/volumeBar/style.ts b/src/pages/Pool-V3/components/Statistics/volumeBar/style.ts new file mode 100644 index 000000000..4535cf5d1 --- /dev/null +++ b/src/pages/Pool-V3/components/Statistics/volumeBar/style.ts @@ -0,0 +1,52 @@ +import { colors, typography, theme } from '../theme'; +import { makeStyles } from 'tss-react/mui'; + +export const useStyles = makeStyles()(() => ({ + container: { + width: '100%', + backgroundColor: colors.oraidex.component, + borderRadius: 22, + padding: 20, + display: 'flex', + whiteSpace: 'nowrap', + justifyContent: 'space-between' + }, + + tokenName: { + display: 'flex', + whiteSpace: 'nowrap', + + [theme.breakpoints.down('sm')]: { + '& p': { + ...typography.caption2 + } + }, + + [theme.breakpoints.down('xs')]: { + '& p': { + ...typography.caption4 + } + } + }, + + tokenHeader: { + ...typography.heading4, + color: colors.oraidex.textGrey + }, + + tokenContent: { + ...typography.heading4, + color: colors.white.main, + padding: '0 0 0 5px' + }, + + tokenLow: { + color: colors.oraidex.Error, + fontWeight: 400 + }, + + tokenUp: { + color: colors.oraidex.green, + fontWeight: 400 + } +})); diff --git a/src/pages/Pool-V3/helpers/format.tsx b/src/pages/Pool-V3/helpers/format.tsx index 91ac54527..7b3b4dc62 100644 --- a/src/pages/Pool-V3/helpers/format.tsx +++ b/src/pages/Pool-V3/helpers/format.tsx @@ -23,6 +23,14 @@ export type PoolWithTokenInfo = PoolWithPoolKey & { poolKey: string; }; +export const getTokenInfo = (address, isLight) => { + let Icon = DefaultIcon; + const tokenInfo = oraichainTokensWithIcon.find((token) => [token.denom, token.contractAddress].includes(address)); + + if (tokenInfo) Icon = isLight ? tokenInfo.IconLight : tokenInfo.Icon; + return { Icon, tokenInfo }; +}; + export const getIconPoolData = (tokenX, tokenY, isLight) => { let [FromTokenIcon, ToTokenIcon] = [DefaultIcon, DefaultIcon]; const tokenXinfo = oraichainTokensWithIcon.find((token) => [token.denom, token.contractAddress].includes(tokenX)); diff --git a/src/pages/Pool-V3/helpers/helper.ts b/src/pages/Pool-V3/helpers/helper.ts index 71d9f8890..ffd266bb6 100644 --- a/src/pages/Pool-V3/helpers/helper.ts +++ b/src/pages/Pool-V3/helpers/helper.ts @@ -1,4 +1,4 @@ -import { BigDecimal, toDisplay, TokenItemType } from '@oraichain/oraidex-common'; +import { BigDecimal, toDisplay, TokenItemType, CW20_DECIMALS } from '@oraichain/oraidex-common'; import { reduce } from 'lodash'; import { Coin } from '@cosmjs/proto-signing'; import { PoolKey } from '@oraichain/oraidex-contracts-sdk/build/OraiswapV3.types'; @@ -502,7 +502,7 @@ export const convertPosition = ({ }) => { const fmtFeeClaim = formatClaimFeeData(feeClaimData); - return positions + const fmtData = positions .map((position: Position & { poolData: { pool: Pool }; ind: number; token_id: number }) => { const [tokenX, tokenY] = [position?.pool_key.token_x, position?.pool_key.token_y]; let { @@ -586,13 +586,17 @@ export const convertPosition = ({ token: TokenItemType; }; - const usd = toDisplay(amount) * (cachePrices[token?.coinGeckoId] || 0); + const usd = + toDisplay(amount.toString(), token.decimals || CW20_DECIMALS) * Number(cachePrices[token?.coinGeckoId] || 0); acc = new BigDecimal(acc || 0).add(usd).toNumber(); return acc; }, 0); + const tokenYDecimal = tokenYinfo.decimals || CW20_DECIMALS; + const tokenXDecimal = tokenXinfo.decimals || CW20_DECIMALS; + return { ...position, poolData: { @@ -605,6 +609,10 @@ export const convertPosition = ({ tokenYName: tokenYinfo.name, tokenXIcon: tokenXIcon, tokenYIcon: tokenYIcon, + tokenYinfo, + tokenXinfo, + tokenYDecimal, + tokenXDecimal, fee: +printBigint(BigInt(position.pool_key.fee_tier.fee), PERCENTAGE_SCALE - 2), min, max, @@ -627,4 +635,5 @@ export const convertPosition = ({ }; }) .filter(Boolean); + return fmtData; }; diff --git a/src/pages/Pool-V3/index.module.scss b/src/pages/Pool-V3/index.module.scss index 2763041dd..b82a501d8 100644 --- a/src/pages/Pool-V3/index.module.scss +++ b/src/pages/Pool-V3/index.module.scss @@ -87,5 +87,9 @@ .content { width: 100%; + + &.light.stats { + filter: invert(1); + } } } diff --git a/src/pages/Pool-V3/index.tsx b/src/pages/Pool-V3/index.tsx index 66de0783c..13318b5c2 100644 --- a/src/pages/Pool-V3/index.tsx +++ b/src/pages/Pool-V3/index.tsx @@ -5,26 +5,30 @@ import PoolList from './components/PoolList'; import PositionList from './components/PositionList'; import styles from './index.module.scss'; import { Link } from 'react-router-dom'; +import WrappedStats from './components/Statistics/WrappedStats/WrappedStats'; +import useTheme from 'hooks/useTheme'; export enum PoolV3PageType { POOL = 'pools', POSITION = 'positions', - SWAP = 'swap' + STAT = 'stats' } -const listTab = [PoolV3PageType.POOL, PoolV3PageType.POSITION]; +const listTab = [PoolV3PageType.POOL, PoolV3PageType.POSITION, PoolV3PageType.STAT]; const listTabRender = [ { id: PoolV3PageType.POOL, value: 'Pools' }, - { id: PoolV3PageType.POSITION, value: 'Your Liquidity Positions' } + { id: PoolV3PageType.POSITION, value: 'Your Liquidity Positions' }, + { id: PoolV3PageType.STAT, value: 'Stats' } ]; const PageContent = { [PoolV3PageType.POOL]: PoolList, - [PoolV3PageType.POSITION]: PositionList - // [PoolV3PageType.SWAP]: PositionList + [PoolV3PageType.POSITION]: PositionList, + [PoolV3PageType.STAT]: WrappedStats }; const PoolV3 = () => { + const theme = useTheme(); const navigate = useNavigate(); let [searchParams, setSearchParams] = useSearchParams(); const type = searchParams.get('type') as PoolV3PageType; @@ -59,7 +63,7 @@ const PoolV3 = () => { */} -
{Content && }
+
{Content && }
); }; diff --git a/yarn.lock b/yarn.lock index 43f45df26..a4a88fcdd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -383,7 +383,7 @@ dependencies: "@babel/types" "^7.22.15" -"@babel/helper-module-imports@^7.24.7": +"@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.24.7": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz#f2f980392de5b84c3328fc71d38bd81bbb83042b" integrity sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA== @@ -1657,6 +1657,13 @@ dependencies: regenerator-runtime "^0.14.0" +"@babel/runtime@^7.18.3", "@babel/runtime@^7.23.9", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.0.tgz#3af9a91c1b739c569d5d80cc917280919c544ecb" + integrity sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw== + dependencies: + regenerator-runtime "^0.14.0" + "@babel/template@^7.18.10", "@babel/template@^7.20.7", "@babel/template@^7.25.0": version "7.25.0" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.25.0.tgz#e733dc3134b4fede528c15bc95e89cb98c52592a" @@ -2373,6 +2380,113 @@ dependencies: apache-arrow "^13.0.0" +"@emotion/babel-plugin@^11.12.0": + version "11.12.0" + resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz#7b43debb250c313101b3f885eba634f1d723fcc2" + integrity sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw== + dependencies: + "@babel/helper-module-imports" "^7.16.7" + "@babel/runtime" "^7.18.3" + "@emotion/hash" "^0.9.2" + "@emotion/memoize" "^0.9.0" + "@emotion/serialize" "^1.2.0" + babel-plugin-macros "^3.1.0" + convert-source-map "^1.5.0" + escape-string-regexp "^4.0.0" + find-root "^1.1.0" + source-map "^0.5.7" + stylis "4.2.0" + +"@emotion/cache@*", "@emotion/cache@^11.11.0", "@emotion/cache@^11.13.0": + version "11.13.1" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.13.1.tgz#fecfc54d51810beebf05bf2a161271a1a91895d7" + integrity sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw== + dependencies: + "@emotion/memoize" "^0.9.0" + "@emotion/sheet" "^1.4.0" + "@emotion/utils" "^1.4.0" + "@emotion/weak-memoize" "^0.4.0" + stylis "4.2.0" + +"@emotion/hash@^0.9.2": + version "0.9.2" + resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.2.tgz#ff9221b9f58b4dfe61e619a7788734bd63f6898b" + integrity sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g== + +"@emotion/is-prop-valid@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.3.0.tgz#bd84ba972195e8a2d42462387581560ef780e4e2" + integrity sha512-SHetuSLvJDzuNbOdtPVbq6yMMMlLoW5Q94uDqJZqy50gcmAjxFkVqmzqSGEFq9gT2iMuIeKV1PXVWmvUhuZLlQ== + dependencies: + "@emotion/memoize" "^0.9.0" + +"@emotion/memoize@^0.9.0": + version "0.9.0" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.9.0.tgz#745969d649977776b43fc7648c556aaa462b4102" + integrity sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ== + +"@emotion/react@^11.13.0": + version "11.13.0" + resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.13.0.tgz#a9ebf827b98220255e5760dac89fa2d38ca7b43d" + integrity sha512-WkL+bw1REC2VNV1goQyfxjx1GYJkcc23CRQkXX+vZNLINyfI7o+uUn/rTGPt/xJ3bJHd5GcljgnxHf4wRw5VWQ== + dependencies: + "@babel/runtime" "^7.18.3" + "@emotion/babel-plugin" "^11.12.0" + "@emotion/cache" "^11.13.0" + "@emotion/serialize" "^1.3.0" + "@emotion/use-insertion-effect-with-fallbacks" "^1.1.0" + "@emotion/utils" "^1.4.0" + "@emotion/weak-memoize" "^0.4.0" + hoist-non-react-statics "^3.3.1" + +"@emotion/serialize@*", "@emotion/serialize@^1.2.0", "@emotion/serialize@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.3.0.tgz#e07cadfc967a4e7816e0c3ffaff4c6ce05cb598d" + integrity sha512-jACuBa9SlYajnpIVXB+XOXnfJHyckDfe6fOpORIM6yhBDlqGuExvDdZYHDQGoDf3bZXGv7tNr+LpLjJqiEQ6EA== + dependencies: + "@emotion/hash" "^0.9.2" + "@emotion/memoize" "^0.9.0" + "@emotion/unitless" "^0.9.0" + "@emotion/utils" "^1.4.0" + csstype "^3.0.2" + +"@emotion/sheet@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.4.0.tgz#c9299c34d248bc26e82563735f78953d2efca83c" + integrity sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg== + +"@emotion/styled@^11.13.0": + version "11.13.0" + resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.13.0.tgz#633fd700db701472c7a5dbef54d6f9834e9fb190" + integrity sha512-tkzkY7nQhW/zC4hztlwucpT8QEZ6eUzpXDRhww/Eej4tFfO0FxQYWRyg/c5CCXa4d/f174kqeXYjuQRnhzf6dA== + dependencies: + "@babel/runtime" "^7.18.3" + "@emotion/babel-plugin" "^11.12.0" + "@emotion/is-prop-valid" "^1.3.0" + "@emotion/serialize" "^1.3.0" + "@emotion/use-insertion-effect-with-fallbacks" "^1.1.0" + "@emotion/utils" "^1.4.0" + +"@emotion/unitless@^0.9.0": + version "0.9.0" + resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.9.0.tgz#8e5548f072bd67b8271877e51c0f95c76a66cbe2" + integrity sha512-TP6GgNZtmtFaFcsOgExdnfxLLpRDla4Q66tnenA9CktvVSdNKDvMVuUah4QvWPIpNjrWsGg3qeGo9a43QooGZQ== + +"@emotion/use-insertion-effect-with-fallbacks@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz#1a818a0b2c481efba0cf34e5ab1e0cb2dcb9dfaf" + integrity sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw== + +"@emotion/utils@*", "@emotion/utils@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.4.0.tgz#262f1d02aaedb2ec91c83a0955dd47822ad5fbdd" + integrity sha512-spEnrA1b6hDR/C68lC2M7m6ALPUHZC0lIY7jAS/B/9DuuO1ZP04eov8SMv/6fwRd8pzmsn2AuJEznRREWlQrlQ== + +"@emotion/weak-memoize@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz#5e13fac887f08c44f76b0ccaf3370eb00fec9bb6" + integrity sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg== + "@esbuild/linux-loong64@0.14.54": version "0.14.54" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.14.54.tgz#de2a4be678bd4d0d1ffbb86e6de779cde5999028" @@ -3881,6 +3995,86 @@ tweetnacl "^1.0.3" tweetnacl-util "^0.15.1" +"@mui/core-downloads-tracker@^5.16.6": + version "5.16.6" + resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.6.tgz#f029e12ffda8eb79838cc85897f03a628010037c" + integrity sha512-kytg6LheUG42V8H/o/Ptz3olSO5kUXW9zF0ox18VnblX6bO2yif1FPItgc3ey1t5ansb1+gbe7SatntqusQupg== + +"@mui/icons-material@^5.16.6": + version "5.16.6" + resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.16.6.tgz#7067ddba693bec22f77592cb9cd516e2f1c1fd6e" + integrity sha512-ceNGjoXheH9wbIFa1JHmSc9QVjJUvh18KvHrR4/FkJCSi9HXJ+9ee1kUhCOEFfuxNF8UB6WWVrIUOUgRd70t0A== + dependencies: + "@babel/runtime" "^7.23.9" + +"@mui/material@^5.16.6": + version "5.16.6" + resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.16.6.tgz#c7d695f4a9a473052dc086e64471d0435b7e4a52" + integrity sha512-0LUIKBOIjiFfzzFNxXZBRAyr9UQfmTAFzbt6ziOU2FDXhorNN2o3N9/32mNJbCA8zJo2FqFU6d3dtoqUDyIEfA== + dependencies: + "@babel/runtime" "^7.23.9" + "@mui/core-downloads-tracker" "^5.16.6" + "@mui/system" "^5.16.6" + "@mui/types" "^7.2.15" + "@mui/utils" "^5.16.6" + "@popperjs/core" "^2.11.8" + "@types/react-transition-group" "^4.4.10" + clsx "^2.1.0" + csstype "^3.1.3" + prop-types "^15.8.1" + react-is "^18.3.1" + react-transition-group "^4.4.5" + +"@mui/private-theming@^5.16.6": + version "5.16.6" + resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.16.6.tgz#547671e7ae3f86b68d1289a0b90af04dfcc1c8c9" + integrity sha512-rAk+Rh8Clg7Cd7shZhyt2HGTTE5wYKNSJ5sspf28Fqm/PZ69Er9o6KX25g03/FG2dfpg5GCwZh/xOojiTfm3hw== + dependencies: + "@babel/runtime" "^7.23.9" + "@mui/utils" "^5.16.6" + prop-types "^15.8.1" + +"@mui/styled-engine@^5.16.6": + version "5.16.6" + resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.16.6.tgz#60110c106dd482dfdb7e2aa94fd6490a0a3f8852" + integrity sha512-zaThmS67ZmtHSWToTiHslbI8jwrmITcN93LQaR2lKArbvS7Z3iLkwRoiikNWutx9MBs8Q6okKvbZq1RQYB3v7g== + dependencies: + "@babel/runtime" "^7.23.9" + "@emotion/cache" "^11.11.0" + csstype "^3.1.3" + prop-types "^15.8.1" + +"@mui/system@^5.16.6": + version "5.16.6" + resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.16.6.tgz#2dabe63d2e45816ce611c40d6e3f79b9c2ccbcd7" + integrity sha512-5xgyJjBIMPw8HIaZpfbGAaFYPwImQn7Nyh+wwKWhvkoIeDosQ1ZMVrbTclefi7G8hNmqhip04duYwYpbBFnBgw== + dependencies: + "@babel/runtime" "^7.23.9" + "@mui/private-theming" "^5.16.6" + "@mui/styled-engine" "^5.16.6" + "@mui/types" "^7.2.15" + "@mui/utils" "^5.16.6" + clsx "^2.1.0" + csstype "^3.1.3" + prop-types "^15.8.1" + +"@mui/types@^7.2.15": + version "7.2.15" + resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.15.tgz#dadd232fe9a70be0d526630675dff3b110f30b53" + integrity sha512-nbo7yPhtKJkdf9kcVOF8JZHPZTmqXjJ/tI0bdWgHg5tp9AnIN4Y7f7wm9T+0SyGYJk76+GYZ8Q5XaTYAsUHN0Q== + +"@mui/utils@^5.16.6": + version "5.16.6" + resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.16.6.tgz#905875bbc58d3dcc24531c3314a6807aba22a711" + integrity sha512-tWiQqlhxAt3KENNiSRL+DIn9H5xNVK6Jjf70x3PnfQPz1MPBdh7yyIcAyVBT9xiw7hP3SomRhPR7hzBMBCjqEA== + dependencies: + "@babel/runtime" "^7.23.9" + "@mui/types" "^7.2.15" + "@types/prop-types" "^15.7.12" + clsx "^2.1.1" + prop-types "^15.8.1" + react-is "^18.3.1" + "@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": version "5.1.1-v1" resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz#dbf733a965ca47b1973177dc0bb6c889edcfb129" @@ -4487,7 +4681,7 @@ "@pnpm/network.ca-file" "^1.0.1" config-chain "^1.1.11" -"@popperjs/core@^2.9.0": +"@popperjs/core@^2.11.8", "@popperjs/core@^2.9.0": version "2.11.8" resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f" integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A== @@ -5626,7 +5820,7 @@ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.11.tgz#2596fb352ee96a1379c657734d4b913a613ad563" integrity sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng== -"@types/prop-types@^15.7.2": +"@types/prop-types@^15.7.12", "@types/prop-types@^15.7.2": version "15.7.12" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.12.tgz#12bb1e2be27293c1406acb6af1c3f3a1481d98c6" integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q== @@ -5684,6 +5878,13 @@ "@types/history" "^4.7.11" "@types/react" "*" +"@types/react-transition-group@^4.4.10": + version "4.4.10" + resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.10.tgz#6ee71127bdab1f18f11ad8fb3322c6da27c327ac" + integrity sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q== + dependencies: + "@types/react" "*" + "@types/react@*", "@types/react@^18.0.34": version "18.2.46" resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.46.tgz#f04d6c528f8f136ea66333bc66abcae46e2680df" @@ -8062,6 +8263,11 @@ clsx@^1.1.1: resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== +clsx@^2.1.0, clsx@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999" + integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -8317,7 +8523,7 @@ content-type@^1.0.4, content-type@~1.0.4, content-type@~1.0.5: resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== -convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: +convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.9.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== @@ -8764,7 +8970,7 @@ cssstyle@^2.3.0: dependencies: cssom "~0.3.6" -csstype@^3.0.2, csstype@^3.1.2: +csstype@^3.0.2, csstype@^3.1.2, csstype@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== @@ -9231,6 +9437,14 @@ dom-converter@^0.2.0: dependencies: utila "~0.4" +dom-helpers@^5.0.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902" + integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA== + dependencies: + "@babel/runtime" "^7.8.7" + csstype "^3.0.2" + dom-serializer@0: version "0.2.2" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" @@ -10689,6 +10903,11 @@ find-replace@^3.0.0: dependencies: array-back "^3.0.1" +find-root@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" + integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== + find-up@5.0.0, find-up@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" @@ -11560,7 +11779,7 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: +hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== @@ -15752,7 +15971,7 @@ prompts@^2.0.1, prompts@^2.4.2: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@^15.7.2, prop-types@^15.8.1: +prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -16163,6 +16382,11 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== +react-is@^18.3.1: + version "18.3.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" + integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== + react-lifecycles-compat@^3.0.0, react-lifecycles-compat@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" @@ -16279,6 +16503,16 @@ react-toastify@^8.2.0: dependencies: clsx "^1.1.1" +react-transition-group@^4.4.5: + version "4.4.5" + resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1" + integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g== + dependencies: + "@babel/runtime" "^7.5.5" + dom-helpers "^5.0.1" + loose-envify "^1.4.0" + prop-types "^15.6.2" + react-universal-interface@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/react-universal-interface/-/react-universal-interface-0.6.2.tgz#5e8d438a01729a4dbbcbeeceb0b86be146fe2b3b" @@ -17413,7 +17647,7 @@ source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, sourc resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -source-map@^0.5.6: +source-map@^0.5.6, source-map@^0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== @@ -17646,7 +17880,7 @@ string-natural-compare@^3.0.1: resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -17664,6 +17898,15 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" +string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -17743,7 +17986,7 @@ stringify-object@^3.3.0: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -17764,6 +18007,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -17821,6 +18071,11 @@ stylehacks@^5.1.1: browserslist "^4.21.4" postcss-selector-parser "^6.0.4" +stylis@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51" + integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw== + stylis@^4.3.0: version "4.3.1" resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.3.1.tgz#ed8a9ebf9f76fe1e12d462f5cc3c4c980b23a7eb" @@ -18426,6 +18681,15 @@ tslib@^2.0.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.5.0, tslib@^2.6.3, tslib@~2.6 resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== +tss-react@^4.9.12: + version "4.9.12" + resolved "https://registry.yarnpkg.com/tss-react/-/tss-react-4.9.12.tgz#beaae5459cae2dd966af4c97f6dc6dd6655e183d" + integrity sha512-bsREJF9opq8OEZKibw7Awao2g16ZSlsBavmIxzKVF7EMcJ1d0Uc/Z2lJEKlZwYoct6g1C0dxd5XI+RwPhTrlUA== + dependencies: + "@emotion/cache" "*" + "@emotion/serialize" "*" + "@emotion/utils" "*" + tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" @@ -19517,7 +19781,7 @@ workbox-window@6.6.1: "@types/trusted-types" "^2.0.2" workbox-core "6.6.1" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -19544,6 +19808,15 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 7ebb444913c425d659dff35c422f31714af5a567 Mon Sep 17 00:00:00 2001 From: quangdz1704 Date: Mon, 5 Aug 2024 18:50:20 +0700 Subject: [PATCH 02/19] fix: modbile mode --- src/pages/Pool-V3/index.module.scss | 5 +++++ src/pages/Pool-V3/index.tsx | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/pages/Pool-V3/index.module.scss b/src/pages/Pool-V3/index.module.scss index b82a501d8..df3ac9039 100644 --- a/src/pages/Pool-V3/index.module.scss +++ b/src/pages/Pool-V3/index.module.scss @@ -42,6 +42,7 @@ line-height: 150%; /* 24px */ .item { + white-space: nowrap; display: flex; padding: 12px 24px; justify-content: center; @@ -51,6 +52,10 @@ border-radius: var(--Dimension-Corner-Radius-button, 99px); + @include small-mobile { + padding: 12px 18px; + } + &.active { @include theme { color: theme-get('colors-neutral-text-body-on-row'); diff --git a/src/pages/Pool-V3/index.tsx b/src/pages/Pool-V3/index.tsx index 13318b5c2..4f571573a 100644 --- a/src/pages/Pool-V3/index.tsx +++ b/src/pages/Pool-V3/index.tsx @@ -7,6 +7,7 @@ import styles from './index.module.scss'; import { Link } from 'react-router-dom'; import WrappedStats from './components/Statistics/WrappedStats/WrappedStats'; import useTheme from 'hooks/useTheme'; +import { isMobile } from '@walletconnect/browser-utils'; export enum PoolV3PageType { POOL = 'pools', @@ -32,6 +33,7 @@ const PoolV3 = () => { const navigate = useNavigate(); let [searchParams, setSearchParams] = useSearchParams(); const type = searchParams.get('type') as PoolV3PageType; + const mobileMode = isMobile(); useEffect(() => { if (!listTab.includes(type)) { @@ -40,6 +42,7 @@ const PoolV3 = () => { }, [type]); const Content = PageContent[type || PoolV3PageType.POOL]; + console.log('isMobile()', mobileMode); return (
@@ -52,7 +55,7 @@ const PoolV3 = () => { key={e.id} className={classNames(styles.item, { [styles.active]: type === e.id })} > - {e.value} + {!mobileMode ? e.value : e.value === 'Your Liquidity Positions' ? 'Your Positions' : e.value} ); })} From e232aca426d3face8cb9ece380c9e9c3905e51bc Mon Sep 17 00:00:00 2001 From: quangdz1704 Date: Tue, 6 Aug 2024 11:46:26 +0700 Subject: [PATCH 03/19] chore: rm clo --- src/pages/Pool-V3/components/PositionItem/index.tsx | 7 +++++-- src/pages/Pool-V3/helpers/helper.ts | 1 - src/pages/Pool-V3/index.tsx | 1 - 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/pages/Pool-V3/components/PositionItem/index.tsx b/src/pages/Pool-V3/components/PositionItem/index.tsx index ae8ef45b0..daae00a62 100644 --- a/src/pages/Pool-V3/components/PositionItem/index.tsx +++ b/src/pages/Pool-V3/components/PositionItem/index.tsx @@ -302,8 +302,11 @@ const PositionItem = ({ position, setStatusRemove }) => { {!principalAmountX || !principalAmountY ? '--' : formatDisplayUsdt( - new BigDecimal(toDisplay((principalAmountX || 0).toString(), tokenXDecimal) * tokenXUsd) - .add(toDisplay((principalAmountY || 0).toString(), tokenYDecimal) * tokenYUsd) + new BigDecimal(toDisplay((principalAmountX || 0).toString(), tokenXDecimal)) + .mul(tokenXUsd) + .add( + new BigDecimal(toDisplay((principalAmountY || 0).toString(), tokenYDecimal)).mul(tokenYUsd) + ) .toNumber(), 6, 6 diff --git a/src/pages/Pool-V3/helpers/helper.ts b/src/pages/Pool-V3/helpers/helper.ts index ffd266bb6..511eb3641 100644 --- a/src/pages/Pool-V3/helpers/helper.ts +++ b/src/pages/Pool-V3/helpers/helper.ts @@ -479,7 +479,6 @@ export const formatClaimFeeData = (feeClaimData: PositionsNode[]) => { return acc; }, {}); - console.log('fmtFeeClaimData', fmtFeeClaimData); return fmtFeeClaimData; }; diff --git a/src/pages/Pool-V3/index.tsx b/src/pages/Pool-V3/index.tsx index 4f571573a..8d0d897d3 100644 --- a/src/pages/Pool-V3/index.tsx +++ b/src/pages/Pool-V3/index.tsx @@ -42,7 +42,6 @@ const PoolV3 = () => { }, [type]); const Content = PageContent[type || PoolV3PageType.POOL]; - console.log('isMobile()', mobileMode); return (
From 79da67977652db79f4e05bf84e388c54b96c0027 Mon Sep 17 00:00:00 2001 From: trungbach Date: Thu, 8 Aug 2024 14:13:30 +0700 Subject: [PATCH 04/19] update: add graphql client --- src/config/networks.ts | 5 +- src/helper/constants.ts | 3 + .../Pool-V3/components/PoolDetail/index.tsx | 37 +++++----- .../Pool-V3/components/PositionList/index.tsx | 70 ++----------------- .../Statistics/WrappedStats/WrappedStats.tsx | 20 +++--- src/pages/Pool-V3/index.tsx | 43 +++++------- src/rest/graphClient.ts | 49 +++++++++++++ 7 files changed, 106 insertions(+), 121 deletions(-) create mode 100644 src/rest/graphClient.ts diff --git a/src/config/networks.ts b/src/config/networks.ts index 5e6add1d4..13461095d 100644 --- a/src/config/networks.ts +++ b/src/config/networks.ts @@ -16,7 +16,7 @@ import { AMM_V3_CONTRACT } from '@oraichain/oraidex-common'; -export const network: CustomChainInfo & NetworkConfig & { pool_v3: string } = { +export const network: CustomChainInfo & NetworkConfig & { pool_v3: string; indexer_v3: string } = { ...oraichainNetwork, prefix: oraichainNetwork.bech32Config.bech32PrefixAccAddr, denom: 'orai', @@ -34,5 +34,6 @@ export const network: CustomChainInfo & NetworkConfig & { pool_v3: string } = { staking_oraix: CW20_STAKING_CONTRACT, multicall: MULTICALL_CONTRACT, explorer: 'https://scan.orai.io', - pool_v3: AMM_V3_CONTRACT + pool_v3: AMM_V3_CONTRACT, + indexer_v3: 'https://staging-ammv3-indexer.oraidex.io/' }; diff --git a/src/helper/constants.ts b/src/helper/constants.ts index 3f44766d8..2f69884a9 100644 --- a/src/helper/constants.ts +++ b/src/helper/constants.ts @@ -1,3 +1,5 @@ +import { network } from 'config/networks'; + export const leapSnapId = 'npm:@leapwallet/metamask-cosmos-snap'; export const leapWalletType = 'leapSnap'; @@ -8,3 +10,4 @@ export const bitcoinLcd = 'https://btc.lcd.orai.io'; export const MIN_DEPOSIT_BTC = 600; export const MIN_WITHDRAW_BTC = 600; +export const INDEXER_V3_URL = network.indexer_v3 ?? 'https://staging-ammv3-indexer.oraidex.io/'; diff --git a/src/pages/Pool-V3/components/PoolDetail/index.tsx b/src/pages/Pool-V3/components/PoolDetail/index.tsx index fa6752d7e..e0d111b52 100644 --- a/src/pages/Pool-V3/components/PoolDetail/index.tsx +++ b/src/pages/Pool-V3/components/PoolDetail/index.tsx @@ -1,31 +1,26 @@ -import styles from './index.module.scss'; -import { ReactComponent as BackIcon } from 'assets/icons/back.svg'; +import { toDisplay } from '@oraichain/oraidex-common'; import { ReactComponent as AddIcon } from 'assets/icons/Add.svg'; +import { ReactComponent as BackIcon } from 'assets/icons/back.svg'; import { ReactComponent as BootsIconDark } from 'assets/icons/boost-icon-dark.svg'; import { ReactComponent as BootsIcon } from 'assets/icons/boost-icon.svg'; -import { Button } from 'components/Button'; -import { useNavigate, useParams } from 'react-router-dom'; +import { ReactComponent as NoDataDark } from 'assets/images/NoDataPool.svg'; +import { ReactComponent as NoData } from 'assets/images/NoDataPoolLight.svg'; import classNames from 'classnames'; -import { formatDisplayUsdt } from 'pages/Pools/helpers'; -import useTheme from 'hooks/useTheme'; -import { useEffect, useState } from 'react'; +import { Button } from 'components/Button'; +import LoadingBox from 'components/LoadingBox'; import { formatNumberKMB, numberWithCommas } from 'helper/format'; -import PositionItem from '../PositionItem'; -import SingletonOraiswapV3, { - fetchPoolAprInfo, - PoolAprInfo, - poolKeyToString, - stringToPoolKey -} from 'libs/contractSingleton'; -import { toDisplay } from '@oraichain/oraidex-common'; -import { formatPoolData, getIconPoolData, PoolWithTokenInfo } from 'pages/Pool-V3/helpers/format'; import { useCoinGeckoPrices } from 'hooks/useCoingecko'; -import { convertPosition } from 'pages/Pool-V3/helpers/helper'; import useConfigReducer from 'hooks/useConfigReducer'; -import LoadingBox from 'components/LoadingBox'; -import { ReactComponent as NoDataDark } from 'assets/images/NoDataPool.svg'; -import { ReactComponent as NoData } from 'assets/images/NoDataPoolLight.svg'; -import { getFeeClaimData } from '../PositionList'; +import useTheme from 'hooks/useTheme'; +import SingletonOraiswapV3, { fetchPoolAprInfo, poolKeyToString, stringToPoolKey } from 'libs/contractSingleton'; +import { formatPoolData, getIconPoolData, PoolWithTokenInfo } from 'pages/Pool-V3/helpers/format'; +import { convertPosition } from 'pages/Pool-V3/helpers/helper'; +import { formatDisplayUsdt } from 'pages/Pools/helpers'; +import { useEffect, useState } from 'react'; +import { useNavigate, useParams } from 'react-router-dom'; +import { getFeeClaimData } from 'rest/graphClient'; +import PositionItem from '../PositionItem'; +import styles from './index.module.scss'; const PoolV3Detail = () => { const [address] = useConfigReducer('address'); diff --git a/src/pages/Pool-V3/components/PositionList/index.tsx b/src/pages/Pool-V3/components/PositionList/index.tsx index 3795dc3e8..592876ddd 100644 --- a/src/pages/Pool-V3/components/PositionList/index.tsx +++ b/src/pages/Pool-V3/components/PositionList/index.tsx @@ -1,70 +1,14 @@ -import { useState } from 'react'; -import styles from './index.module.scss'; -import PositionItem from '../PositionItem'; import { ReactComponent as NoDataDark } from 'assets/images/NoDataPool.svg'; import { ReactComponent as NoData } from 'assets/images/NoDataPoolLight.svg'; -import useTheme from 'hooks/useTheme'; -import { useEffect } from 'react'; +import LoadingBox from 'components/LoadingBox'; import useConfigReducer from 'hooks/useConfigReducer'; -import { convertPosition } from 'pages/Pool-V3/helpers/helper'; +import useTheme from 'hooks/useTheme'; import SingletonOraiswapV3 from 'libs/contractSingleton'; -import LoadingBox from 'components/LoadingBox'; -import { gql, request, GraphQLClient } from 'graphql-request'; - -export const getFeeClaimData = async (address: string) => { - try { - // https://subql-staging.orai.io/ - const endpoint = `https://staging-ammv3-indexer.oraidex.io/`; - const client = new GraphQLClient(endpoint); - - const document = gql` - { - query { - positions(filter: { ownerId: { equalTo: "${address}" } }) { - nodes { - id - poolId - principalAmountX - principalAmountY - fees { - nodes { - amountXInUSD - amountYInUSD - amountX - amountY - claimFeeIncentiveTokens { - nodes { - id - tokenId - token { - id - denom - name - logo - } - rewardAmount - } - } - } - } - } - } - } - } - `; - - // return MOCK_DATA; - - const result = await client.request(document); - - const data = result.query.positions.nodes; - - return data || []; - } catch (error) { - console.log('error', error); - return []; - } -}; +import { convertPosition } from 'pages/Pool-V3/helpers/helper'; +import { useEffect, useState } from 'react'; +import { getFeeClaimData } from 'rest/graphClient'; +import PositionItem from '../PositionItem'; +import styles from './index.module.scss'; const PositionList = () => { const theme = useTheme(); diff --git a/src/pages/Pool-V3/components/Statistics/WrappedStats/WrappedStats.tsx b/src/pages/Pool-V3/components/Statistics/WrappedStats/WrappedStats.tsx index 38a81aa63..ce8293aef 100644 --- a/src/pages/Pool-V3/components/Statistics/WrappedStats/WrappedStats.tsx +++ b/src/pages/Pool-V3/components/Statistics/WrappedStats/WrappedStats.tsx @@ -1,20 +1,18 @@ -import React, { useEffect, useState } from 'react'; -import loader from 'assets/gif/loading.gif'; -import useStyles from './styles'; import { Grid, Typography } from '@mui/material'; +import React, { useEffect, useState } from 'react'; import { EmptyPlaceholder } from '../EmptyPlaceholder/EmptyPlaceholder'; - -import Volume from '../Volume/Volume'; +import useStyles from './styles'; +import LoadingBox from 'components/LoadingBox'; import Liquidity from '../Liquidity/Liquidity'; -import VolumeBar from '../volumeBar/VolumeBar'; -import TokensList from '../TokensList/TokensList'; import PoolList from '../PoolList/PoolList'; +import TokensList from '../TokensList/TokensList'; +import Volume from '../Volume/Volume'; import useGetStatistic from '../hooks/useGetStatistic'; -import LoadingBox from 'components/LoadingBox'; +import VolumeBar from '../volumeBar/VolumeBar'; export const WrappedStats: React.FC = () => { const { classes } = useStyles(); - const [isLoadingStats, setLoading] = useState(false); + const [isLoadingStats, setIsLoadingStats] = useState(false); const [stats, setStats] = useState({ volume24: { value: 0, @@ -47,13 +45,13 @@ export const WrappedStats: React.FC = () => { useEffect(() => { (async () => { - setLoading(true); + setIsLoadingStats(true); const data = await getStats(); if (data) { setStats(data); } - setLoading(false); + setIsLoadingStats(false); })(); }, []); diff --git a/src/pages/Pool-V3/index.tsx b/src/pages/Pool-V3/index.tsx index 8d0d897d3..a568a2a7e 100644 --- a/src/pages/Pool-V3/index.tsx +++ b/src/pages/Pool-V3/index.tsx @@ -1,13 +1,12 @@ +import { isMobile } from '@walletconnect/browser-utils'; import classNames from 'classnames'; -import { useEffect } from 'react'; -import { useNavigate, useParams, useSearchParams } from 'react-router-dom'; +import useTheme from 'hooks/useTheme'; +import React, { useEffect } from 'react'; +import { Link, useNavigate, useSearchParams } from 'react-router-dom'; import PoolList from './components/PoolList'; import PositionList from './components/PositionList'; -import styles from './index.module.scss'; -import { Link } from 'react-router-dom'; import WrappedStats from './components/Statistics/WrappedStats/WrappedStats'; -import useTheme from 'hooks/useTheme'; -import { isMobile } from '@walletconnect/browser-utils'; +import styles from './index.module.scss'; export enum PoolV3PageType { POOL = 'pools', @@ -15,23 +14,23 @@ export enum PoolV3PageType { STAT = 'stats' } -const listTab = [PoolV3PageType.POOL, PoolV3PageType.POSITION, PoolV3PageType.STAT]; -const listTabRender = [ - { id: PoolV3PageType.POOL, value: 'Pools' }, - { id: PoolV3PageType.POSITION, value: 'Your Liquidity Positions' }, - { id: PoolV3PageType.STAT, value: 'Stats' } -]; - -const PageContent = { - [PoolV3PageType.POOL]: PoolList, - [PoolV3PageType.POSITION]: PositionList, - [PoolV3PageType.STAT]: WrappedStats +type TabRender = { + id: PoolV3PageType; + value: string; + content: React.FC; }; +const listTab = Object.values(PoolV3PageType); +const listTabRender: TabRender[] = [ + { id: PoolV3PageType.POOL, value: 'Pools', content: PoolList }, + { id: PoolV3PageType.POSITION, value: 'Your Liquidity Positions', content: PositionList }, + { id: PoolV3PageType.STAT, value: 'Stats', content: WrappedStats } +]; + const PoolV3 = () => { const theme = useTheme(); const navigate = useNavigate(); - let [searchParams, setSearchParams] = useSearchParams(); + let [searchParams] = useSearchParams(); const type = searchParams.get('type') as PoolV3PageType; const mobileMode = isMobile(); @@ -39,9 +38,10 @@ const PoolV3 = () => { if (!listTab.includes(type)) { navigate(`/pools-v3?type=${PoolV3PageType.POOL}`); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [type]); - const Content = PageContent[type || PoolV3PageType.POOL]; + const Content = listTabRender.find((tab) => tab.id === type)?.content ?? PoolList; return (
@@ -59,12 +59,7 @@ const PoolV3 = () => { ); })}
- - {/* - Swap - */}
-
{Content && }
); diff --git a/src/rest/graphClient.ts b/src/rest/graphClient.ts new file mode 100644 index 000000000..46e342173 --- /dev/null +++ b/src/rest/graphClient.ts @@ -0,0 +1,49 @@ +import { gql, GraphQLClient } from 'graphql-request'; +import { INDEXER_V3_URL } from 'helper/constants'; + +export const graphqlClient = new GraphQLClient(INDEXER_V3_URL); + +export const getFeeClaimData = async (address: string) => { + try { + const document = gql` + { + query { + positions(filter: { ownerId: { equalTo: "${address}" } }) { + nodes { + id + poolId + principalAmountX + principalAmountY + fees { + nodes { + amountXInUSD + amountYInUSD + amountX + amountY + claimFeeIncentiveTokens { + nodes { + id + tokenId + token { + id + denom + name + logo + } + rewardAmount + } + } + } + } + } + } + } + } + `; + const result = await graphqlClient.request(document); + return result.query.positions.nodes || []; + } catch (error) { + console.log('error', error); + return []; + } +}; From b05ec67c1005e7f99e103023fba024cc5b59d5cc Mon Sep 17 00:00:00 2001 From: vuonghuuhung Date: Thu, 8 Aug 2024 14:16:31 +0700 Subject: [PATCH 05/19] refactor singleton --- package.json | 3 +- src/index.tsx | 41 +- src/layouts/App.tsx | 13 + src/libs/contractSingleton.ts | 293 +--- .../components/CreatePosition/index.tsx | 2 +- .../components/NewPositionNoPool/index.tsx | 2 +- .../Pool-V3/components/PoolDetail/index.tsx | 1 + .../Pool-V3/components/PositionItem/index.tsx | 3 +- .../components/PriceRangePlot/utils.ts | 65 +- .../Pool-V3/components/TokenForm/index.tsx | 2 +- src/pages/Pool-V3/helpers/helper.ts | 15 +- src/pages/Pool-V3/hooks/useAddLiquidity.ts | 3 +- .../Pool-V3/packages/sdk/OraiswapV3.client.ts | 1203 -------------- .../Pool-V3/packages/sdk/OraiswapV3.types.ts | 431 ----- src/pages/Pool-V3/packages/sdk/index.ts | 2 - .../packages/wasm/oraiswap_v3_wasm.d.ts | 646 -------- .../Pool-V3/packages/wasm/oraiswap_v3_wasm.js | 1391 ----------------- .../packages/wasm/oraiswap_v3_wasm_bg.wasm | Bin 171580 -> 0 bytes .../wasm/oraiswap_v3_wasm_bg.wasm.d.ts | 71 - src/pages/Pool-V3/packages/wasm/package.json | 24 - yarn.lock | 22 +- 21 files changed, 136 insertions(+), 4097 deletions(-) delete mode 100644 src/pages/Pool-V3/packages/sdk/OraiswapV3.client.ts delete mode 100644 src/pages/Pool-V3/packages/sdk/OraiswapV3.types.ts delete mode 100644 src/pages/Pool-V3/packages/sdk/index.ts delete mode 100644 src/pages/Pool-V3/packages/wasm/oraiswap_v3_wasm.d.ts delete mode 100644 src/pages/Pool-V3/packages/wasm/oraiswap_v3_wasm.js delete mode 100644 src/pages/Pool-V3/packages/wasm/oraiswap_v3_wasm_bg.wasm delete mode 100644 src/pages/Pool-V3/packages/wasm/oraiswap_v3_wasm_bg.wasm.d.ts delete mode 100644 src/pages/Pool-V3/packages/wasm/package.json diff --git a/package.json b/package.json index eba66bed7..efded4038 100644 --- a/package.json +++ b/package.json @@ -95,7 +95,8 @@ "stream-http": "^3.2.0", "ts-jest": "^29.1.1", "typed-scss-modules": "^7.1.4", - "typescript": "^5.1.6" + "typescript": "^5.1.6", + "oraiswap-v3-test": "0.1.5-beta10" }, "scripts": { "analyze": "source-map-explorer 'build/static/js/*.js'", diff --git a/src/index.tsx b/src/index.tsx index 3e93d5530..2df38b090 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -19,8 +19,6 @@ import { persistor, store } from 'store/configure'; import './index.scss'; import App from './layouts/App'; import ScrollToTop from './layouts/ScrollToTop'; -import loadWasm from 'pages/Pool-V3/packages/wasm/oraiswap_v3_wasm'; -import { Client, cacheExchange, fetchExchange, Provider as UrqlProvider } from 'urql'; // const client = new Client({ // url: 'http://10.10.20.72:3000/', @@ -96,41 +94,4 @@ const initApp = async () => { } }; -export interface WasmInfo { - imports: { - from: string; - names: string[]; - }[]; - exports: string[]; -} - -export async function parseWasm(wasmFilePath: string): Promise { - try { - const wasmBinary = await fetch(wasmFilePath) - .then((res) => res.arrayBuffer()) - .then((buf) => buf); - - console.log('wasmBinary', wasmBinary); - // const wasmBinary = await fs.promises.readFile(wasmFilePath); - const wasmModule = await WebAssembly.compile(wasmBinary); - const imports = Object.entries( - WebAssembly.Module.imports(wasmModule).reduce( - (result, item) => ({ - ...result, - [item.module]: [...(result[item.module] || []), item.name] - }), - {} as Record - ) - ).map(([from, names]) => ({ from, names })); - - const exports = WebAssembly.Module.exports(wasmModule).map((item) => item.name); - - return { imports, exports }; - } catch (e) { - throw new Error(`Failed to parse WASM file: ${e.message}`); - } -} - -loadWasm().then(() => { - initApp(); -}); +initApp(); diff --git a/src/layouts/App.tsx b/src/layouts/App.tsx index 263e88b43..15098dce8 100644 --- a/src/layouts/App.tsx +++ b/src/layouts/App.tsx @@ -26,6 +26,8 @@ import './index.scss'; import Menu from './Menu'; import { NoticeBanner } from './NoticeBanner'; import Sidebar from './Sidebar'; +import SingletonOraiswapV3 from 'libs/contractSingleton'; +import { getCosmWasmClient } from 'libs/cosmjs'; const App = () => { const [address, setOraiAddress] = useConfigReducer('address'); @@ -58,6 +60,17 @@ const App = () => { } }, [walletByNetworks, window.tronWeb, window.tronLink, ethOwallet]); + useEffect(() => { + const loadSingleton = async () => { + if (address) { + const cosmWasmClient = await getCosmWasmClient({ chainId: network.chainId }); + SingletonOraiswapV3.load(cosmWasmClient.client, address); + } + }; + + loadSingleton(); + }, [address]); + //Public API that will echo messages sent to it back to the client const { sendJsonMessage, lastJsonMessage } = useWebSocket( `wss://${new URL(network.rpc).host}/websocket`, // only get rpc.orai.io diff --git a/src/libs/contractSingleton.ts b/src/libs/contractSingleton.ts index 18013e284..cfa823cfb 100644 --- a/src/libs/contractSingleton.ts +++ b/src/libs/contractSingleton.ts @@ -9,29 +9,27 @@ import { calculateSqrtPrice, getChunkSize, getLiquidityTicksLimit, - getMaxTickmapQuerySize -} from '../pages/Pool-V3/packages/wasm'; -// import { -// CHUNK_SIZE, -// LIQUIDITY_TICKS_LIMIT, -// MAX_TICKMAP_QUERY_SIZE, -// TokenDataOnChain, -// getCoingeckoTokenPriceV2, -// parse, -// poolKeyToString -// // parse -// } from '@store/consts/utils'; + getMaxTickmapQuerySize, + OraiswapV3Handler +} from 'oraiswap-v3-test'; import { network } from 'config/networks'; -import { AssetInfo, OraiswapTokenClient, OraiswapTokenQueryClient } from '@oraichain/oraidex-contracts-sdk'; +import { + AssetInfo, + OraiswapTokenClient, + OraiswapTokenQueryClient, + OraiswapV3Client, + OraiswapV3QueryClient +} from '@oraichain/oraidex-contracts-sdk'; import { ArrayOfAsset, + ArrayOfPosition, ArrayOfTupleOfUint16AndUint64, FeeTier, PoolWithPoolKey, - Position + Position, + Tick } from '@oraichain/oraidex-contracts-sdk/build/OraiswapV3.types'; import { CoinGeckoPrices } from 'hooks/useCoingecko'; -import { ArrayOfPosition, Pool, Tick } from 'pages/Pool-V3/packages/sdk/OraiswapV3.types'; import { TokenDataOnChain } from 'pages/Pool-V3/components/PriceRangePlot/utils'; import Axios from 'axios'; import { throttleAdapterEnhancer, retryAdapterEnhancer } from 'axios-extensions'; @@ -39,9 +37,7 @@ import { AXIOS_TIMEOUT, AXIOS_THROTTLE_THRESHOLD, toDisplay } from '@oraichain/o import { CoinGeckoId } from '@oraichain/oraidex-common'; import { extractAddress, extractDenom } from 'pages/Pool-V3/components/PriceRangePlot/utils'; import { oraichainTokens } from 'config/bridgeTokens'; -import { OraiswapV3Client, OraiswapV3QueryClient } from 'pages/Pool-V3/packages/sdk'; import { calculateTokenAmounts } from 'pages/Pool-V3/helpers/helper'; -// import { defaultState } from '@store/reducers/connection'; export const ALL_FEE_TIERS_DATA: FeeTier[] = [ { fee: 100000000, tick_spacing: 1 }, @@ -106,24 +102,9 @@ const isObject = (value: any): boolean => { return typeof value === 'object' && value !== null; }; -// export let CHUNK_SIZE = getChunkSize(); -// export let LIQUIDITY_TICKS_LIMIT = getLiquidityTicksLimit(); -// export let MAX_TICKMAP_QUERY_SIZE = getMaxTickmapQuerySize(); - -export const loadChunkSize = () => { - const chunkSize = getChunkSize(); - return chunkSize; -}; - -export const loadLiquidityTicksLimit = () => { - const liquidityTicksLimit = getLiquidityTicksLimit(); - return liquidityTicksLimit; -}; - -export const loadMaxTickmapQuerySize = () => { - const maxTickmapQuerySize = getMaxTickmapQuerySize(); - return maxTickmapQuerySize; -}; +export const CHUNK_SIZE = getChunkSize(); +export const LIQUIDITY_TICKS_LIMIT = getLiquidityTicksLimit(); +export const MAX_TICKMAP_QUERY_SIZE = getMaxTickmapQuerySize(); export const poolKeyToString = (poolKey: PoolKey): string => { return poolKey.token_x + '-' + poolKey.token_y + '-' + poolKey.fee_tier.fee + '-' + poolKey.fee_tier.tick_spacing; @@ -193,50 +174,48 @@ export interface PositionInfo { createdAt: string; } +// this should be moved to redux export default class SingletonOraiswapV3 { - private static _tokens: { [key: string]: OraiswapTokenClient } = {}; - private static _nativeTokens: { [key: string]: string } = {}; private static _dex: OraiswapV3Client; - private static _dexQuerier: OraiswapV3QueryClient; - - private constructor() {} + private static _cosmwasmClient: CosmWasmClient; + private static _handler: OraiswapV3Handler; + private static _sender: string; public static get dex() { return this._dex; } - public static get dexQuerier() { - return this._dexQuerier; - } - - public static get tokens() { - return this._tokens; - } - - public static get nativeTokens() { - return this._nativeTokens; - } + private constructor() {} public static async load(signingClient: SigningCosmWasmClient, sender: string) { - if (!this.dex) { + if (!this._cosmwasmClient) { + this._cosmwasmClient = await CosmWasmClient.connect(network.rpc); + } + if (!this._dex) { this._dex = new OraiswapV3Client(signingClient, sender, defaultState.dexAddress); } - const client = await CosmWasmClient.connect(network.rpc); - this._dexQuerier = new OraiswapV3QueryClient(client, defaultState.dexAddress); + if (this._sender !== sender) { + this._sender = sender; + this._dex = new OraiswapV3Client(signingClient, sender, defaultState.dexAddress); + } + this.loadHandler(); } - public static async loadCw20(sender: string, contractAddress: string) { - this._tokens[contractAddress] = new OraiswapTokenClient(this._dex.client, sender, contractAddress); + public static async loadCosmwasmClient() { + if (!this._cosmwasmClient) { + this._cosmwasmClient = await CosmWasmClient.connect(network.rpc);; + } } - public static async loadNative(tokenDenom: string) { - this._nativeTokens[tokenDenom] = tokenDenom; + public static async loadHandler() { + await this.loadCosmwasmClient(); + if (!this._handler) { + this._handler = new OraiswapV3Handler(this._cosmwasmClient); + } } public static async queryBalance(address: string, tokenDenom: string = 'orai') { - if (!address) return '0'; - const client = await CosmWasmClient.connect(network.rpc); - const { amount } = await client.getBalance(address, tokenDenom); + const { amount } = await this._cosmwasmClient.getBalance(address, tokenDenom); return amount; } @@ -246,20 +225,11 @@ export default class SingletonOraiswapV3 { upperTick: number, xToY: boolean ): Promise { - const client = await CosmWasmClient.connect(network.rpc); - const queryClient = new OraiswapV3QueryClient(client, defaultState.dexAddress); - - const tickmaps = await queryClient.tickMap({ - lowerTickIndex: lowerTick, - upperTickIndex: upperTick, - xToY, - poolKey - }); + const tickmaps = await this._handler.tickMap(poolKey, lowerTick, upperTick, xToY); return tickmaps; } public static async getTokensInfo(tokens: string[], address?: string): Promise { - const client = await CosmWasmClient.connect(network.rpc); return await Promise.all( tokens.map(async (token) => { if (token.includes('ibc') || token == 'orai') { @@ -273,7 +243,7 @@ export default class SingletonOraiswapV3 { }; } - const queryClient = new OraiswapTokenQueryClient(client, token); + const queryClient = new OraiswapTokenQueryClient(this._cosmwasmClient, token); const balance = address ? await queryClient.balance({ address: address }) : { balance: '0' }; const tokenInfo = await queryClient.tokenInfo(); const symbol = tokenInfo.symbol; @@ -292,49 +262,31 @@ export default class SingletonOraiswapV3 { } public static async getPools(): Promise { - const client = await CosmWasmClient.connect(network.rpc); - const queryClient = new OraiswapV3QueryClient(client, defaultState.dexAddress); - return await queryClient.pools({}); + await this.loadHandler(); + return await this._handler.getPools(); } - public static async getIncentivesPosition(position, ownerId: string): Promise { - const client = await CosmWasmClient.connect(network.rpc); - const queryClient = new OraiswapV3QueryClient(client, defaultState.dexAddress); - return await queryClient.positionIncentives({ index: position.id, ownerId }); + public static async getIncentivesPosition(positionIndex: number, ownerId: string): Promise { + console.log({ positionIndex, ownerId }); + return await this._handler.positionIncentives(positionIndex, ownerId); } - public static async getTicks(index, key): Promise { - const client = await CosmWasmClient.connect(network.rpc); - const queryClient = new OraiswapV3QueryClient(client, defaultState.dexAddress); - return await queryClient.tick({ index, key }); + public static async getTicks(tickIndex: number, poolKey: PoolKey): Promise { + return await this._handler.getTick(poolKey, tickIndex); } public static async getPool(poolKey: PoolKey): Promise { try { - const client = await CosmWasmClient.connect(network.rpc); - const queryClient = new OraiswapV3QueryClient(client, defaultState.dexAddress); - const pool = await queryClient.pool({ - feeTier: poolKey.fee_tier, - token0: poolKey.token_x, - token1: poolKey.token_y - }); - return { - pool: pool, - pool_key: poolKey - }; + await this.loadHandler(); + const pool = await this._handler.getPool(poolKey); + return pool; } catch (error) { return null; } } - public static async getAllPosition(address: string, limit?: number, offset?: number): Promise { - const client = await CosmWasmClient.connect(network.rpc); - const queryClient = new OraiswapV3QueryClient(client, defaultState.dexAddress); - const position = await queryClient.positions({ - ownerId: address, - limit, - offset - }); + public static async getAllPosition(address: string): Promise { + const position = await this._handler.getPositions(address); return position; } @@ -347,12 +299,11 @@ export default class SingletonOraiswapV3 { const promises = []; const tickSpacing = poolKey.fee_tier.tick_spacing; assert(tickSpacing <= 100); - - assert(loadMaxTickmapQuerySize() > 3); - assert(loadChunkSize() * 2 > tickSpacing); + assert(MAX_TICKMAP_QUERY_SIZE > 3); + assert(CHUNK_SIZE * 2 > tickSpacing); // move back 1 chunk since the range is inclusive // then move back additional 2 chunks to ensure that adding tickspacing won't exceed the query limit - const jump = (loadMaxTickmapQuerySize() - 3) * loadChunkSize(); + const jump = (MAX_TICKMAP_QUERY_SIZE - 3) * CHUNK_SIZE; while (lowerTick <= maxTick) { let nextTick = lowerTick + jump; @@ -400,12 +351,7 @@ export default class SingletonOraiswapV3 { } } - const client = await CosmWasmClient.connect(network.rpc); - const querier = new OraiswapV3QueryClient(client, defaultState.dexAddress); - const liquidityTicks = await querier.liquidityTicks({ - poolKey, - tickIndexes: ticks - }); + const liquidityTicks = await this._handler.liquidityTicks(poolKey, ticks); const convertedLiquidityTicks: LiquidityTick[] = liquidityTicks.map((tickData: any) => { return { index: tickData.index, @@ -418,30 +364,22 @@ export default class SingletonOraiswapV3 { } public static approveToken = async (token: string, amount: bigint, address: string) => { - const tokenClient = new OraiswapTokenClient(this.dex.client, address, token); + const tokenClient = new OraiswapTokenClient(this._dex.client, address, token); return await tokenClient.increaseAllowance({ amount: amount.toString(), - spender: this.dex.contractAddress + spender: this._dex.contractAddress }); }; public static getLiquidityByPool = async (pool: PoolWithPoolKey, prices: CoinGeckoPrices): Promise => { - const allPosition = await SingletonOraiswapV3.queryPosition(); - const poolKey = pool.pool_key; - const poolData = pool.pool; const tokenX = oraichainTokens.find((token) => extractAddress(token) === poolKey.token_x); const tokenY = oraichainTokens.find((token) => extractAddress(token) === poolKey.token_y); - let tvlX = 0n; - let tvlY = 0n; - allPosition.forEach((position) => { - if (position.poolId === poolKeyToString(poolKey)) { - tvlX += BigInt(position.principalAmountX); - tvlY += BigInt(position.principalAmountY); - } - }); + const res = await this._handler.getPairLiquidityValues(pool); + const tvlX = res.liquidityX; + const tvlY = res.liquidityY; const xUsd = (prices[tokenX.coinGeckoId] * Number(tvlX)) / 10 ** tokenX.decimals; const yUsd = (prices[tokenY.coinGeckoId] * Number(tvlY)) / 10 ** tokenY.decimals; @@ -480,9 +418,7 @@ export default class SingletonOraiswapV3 { poolList[poolKeyToString(pool.pool_key)] = pool; }); - const client = await CosmWasmClient.connect(network.rpc); - const queryClient = new OraiswapV3QueryClient(client, defaultState.dexAddress); - const allPosition = await queryClient.allPosition({}); + const allPosition = await this._handler.allPositions(); for (const position of allPosition) { const positionData = position; @@ -513,22 +449,15 @@ export default class SingletonOraiswapV3 { prices: CoinGeckoPrices ): Promise> => { const poolLiquidities: Record = {}; - const allPosition = await SingletonOraiswapV3.queryPosition(); for (const pool of pools) { const poolKey = pool.pool_key; - const poolData = pool.pool; const tokenX = oraichainTokens.find((token) => extractAddress(token) === poolKey.token_x); const tokenY = oraichainTokens.find((token) => extractAddress(token) === poolKey.token_y); - let tvlX = 0n; - let tvlY = 0n; - allPosition.forEach((position) => { - if (position.poolId === poolKeyToString(poolKey)) { - tvlX += BigInt(position.principalAmountX); - tvlY += BigInt(position.principalAmountY); - } - }); + const res = await this._handler.getPairLiquidityValues(pool); + const tvlX = res.liquidityX; + const tvlY = res.liquidityY; const tvlLockedUSD = (prices[tokenX.coinGeckoId] * Number(tvlX)) / 10 ** tokenX.decimals + @@ -541,93 +470,7 @@ export default class SingletonOraiswapV3 { }; public static getTotalLiquidityValue = async (): Promise => { - const pools = await this._dexQuerier.pools({}); // get pools from state - - const totalLiquidity = await Promise.all( - pools.map(async (pool) => { - const tickmap = await this.getFullTickmap(pool.pool_key); - - const liquidityTicks = await this.getAllLiquidityTicks(pool.pool_key, tickmap); - - // console.log({ liquidityTicks }); - - const tickIndexes: number[] = []; - for (const [chunkIndex, chunk] of tickmap.bitmap.entries()) { - for (let bit = 0; bit < loadChunkSize(); bit++) { - const checkedBit = chunk & (1n << BigInt(bit)); - if (checkedBit) { - const tickIndex = positionToTick(Number(chunkIndex), bit, pool.pool_key.fee_tier.tick_spacing); - tickIndexes.push(tickIndex); - } - } - } - - const tickArray: VirtualRange[] = []; - - for (let i = 0; i < tickIndexes.length - 1; i++) { - tickArray.push({ - lowerTick: tickIndexes[i], - upperTick: tickIndexes[i + 1] - }); - } - - const posTest: PositionTest[] = calculateLiquidityForRanges(liquidityTicks, tickArray); - - const res = await calculateLiquidityForPair(posTest, BigInt(pool.pool.sqrt_price)); - - return [ - { address: pool.pool_key.token_x, balance: res.liquidityX }, - { address: pool.pool_key.token_y, balance: res.liquidityY } - ]; - }) - ); - - const flattenArray = totalLiquidity.flat(1); - - // get all tokens and remove duplicate - const tokens = flattenArray - .map((item) => item.address) - .filter((value, index, self) => self.indexOf(value) === index); - - // get token info - const tokenInfos = await Promise.all( - tokens.map(async (token) => { - if (oraichainTokens.filter((item) => extractAddress(item) === token).length > 0) { - const info = oraichainTokens.filter((item) => extractAddress(item) === token)[0]; - return { - info, - price: { - price: 0 - } - }; - // return { info, price: await getCoingeckoTokenPriceV2(info.coingeckoId) }; - } - }) - ); - - // console.log({ tokenInfos }); - - const tokenWithLiquidities = tokens.map((token) => { - const liquidity = flattenArray - .filter((item) => item.address === token) - .reduce((acc, item) => acc + item.balance, 0n); - return { address: token, balance: liquidity }; - }); - - // tokenWithUSDValue - const tokenWithUSDValue = tokenWithLiquidities.map((token) => { - const tokenInfo = tokenInfos.filter((item) => extractAddress(item.info) === token.address)[0]; - return { - address: token.address, - usdValue: (Number(token.balance) / 10 ** 6) * tokenInfo.price.price - }; - }); - - // console.log({ tokenWithUSDValue }); - - const totalValue = tokenWithUSDValue.reduce((acc, item) => acc + item.usdValue, 0); - - return totalValue; + return 1; }; } diff --git a/src/pages/Pool-V3/components/CreatePosition/index.tsx b/src/pages/Pool-V3/components/CreatePosition/index.tsx index f585da14b..c877f8b34 100644 --- a/src/pages/Pool-V3/components/CreatePosition/index.tsx +++ b/src/pages/Pool-V3/components/CreatePosition/index.tsx @@ -23,7 +23,7 @@ import { getMaxTick, getMinTick, Price -} from 'pages/Pool-V3/packages/wasm/oraiswap_v3_wasm'; +} from 'oraiswap-v3-test'; import { useEffect, useMemo, useRef, useState } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; import NewPositionNoPool from '../NewPositionNoPool'; diff --git a/src/pages/Pool-V3/components/NewPositionNoPool/index.tsx b/src/pages/Pool-V3/components/NewPositionNoPool/index.tsx index d1d2830fb..7a5896340 100644 --- a/src/pages/Pool-V3/components/NewPositionNoPool/index.tsx +++ b/src/pages/Pool-V3/components/NewPositionNoPool/index.tsx @@ -8,7 +8,7 @@ import { ReactComponent as PlusIcon } from 'assets/icons/plus.svg'; import { ReactComponent as MinusIcon } from 'assets/icons/minus.svg'; import { ReactComponent as WarningIcon } from 'assets/icons/warning-fill-ic.svg'; import classNames from 'classnames'; -import { getMaxTick, getMinTick, Price } from 'pages/Pool-V3/packages/wasm/oraiswap_v3_wasm'; +import { getMaxTick, getMinTick, Price } from 'oraiswap-v3-test'; import { useEffect, useMemo, useRef, useState } from 'react'; import { calcPrice, diff --git a/src/pages/Pool-V3/components/PoolDetail/index.tsx b/src/pages/Pool-V3/components/PoolDetail/index.tsx index fa6752d7e..f78bc5796 100644 --- a/src/pages/Pool-V3/components/PoolDetail/index.tsx +++ b/src/pages/Pool-V3/components/PoolDetail/index.tsx @@ -67,6 +67,7 @@ const PoolV3Detail = () => { (async () => { try { const poolKey = stringToPoolKey(poolId); + console.log('poolKey', poolKey); const pool = await SingletonOraiswapV3.getPool(poolKey); const isLight = theme === 'light'; const fmtPool = formatPoolData(pool, isLight); diff --git a/src/pages/Pool-V3/components/PositionItem/index.tsx b/src/pages/Pool-V3/components/PositionItem/index.tsx index 4827a657e..6a27339ff 100644 --- a/src/pages/Pool-V3/components/PositionItem/index.tsx +++ b/src/pages/Pool-V3/components/PositionItem/index.tsx @@ -114,10 +114,11 @@ const PositionItem = ({ position, setStatusRemove }) => { if (!openCollapse) return; (async () => { const { pool_key, lower_tick_index, upper_tick_index } = position; + console.log('position', position); const [lowerTickData, upperTickData, incentives] = await Promise.all([ SingletonOraiswapV3.getTicks(lower_tick_index, pool_key), SingletonOraiswapV3.getTicks(upper_tick_index, pool_key), - SingletonOraiswapV3.getIncentivesPosition(position, address) + SingletonOraiswapV3.getIncentivesPosition(position.id, address) ]); const tokenIncentive = incentives.reduce((acc, cur) => { diff --git a/src/pages/Pool-V3/components/PriceRangePlot/utils.ts b/src/pages/Pool-V3/components/PriceRangePlot/utils.ts index 38e28e834..97df7ff15 100644 --- a/src/pages/Pool-V3/components/PriceRangePlot/utils.ts +++ b/src/pages/Pool-V3/components/PriceRangePlot/utils.ts @@ -9,24 +9,18 @@ import { LiquidityTick, Tick, Liquidity, -// getPriceScale -} from 'pages/Pool-V3/packages/wasm/oraiswap_v3_wasm.js'; + getPriceScale +} from 'oraiswap-v3-test'; import { TokenItemType } from '@oraichain/oraidex-common'; -import SingletonOraiswapV3, {Token} from 'libs/contractSingleton'; +import SingletonOraiswapV3, { Token } from 'libs/contractSingleton'; import { PlotTickData } from './PriceRangePlot'; -export const PRICE_SCALE = 24; +export const PRICE_SCALE = getPriceScale(); export const CONCENTRATION_FACTOR = 1.00001526069123; -export const getTickAtSqrtPriceDelta = ( - tickSpacing: number, - minimumRange: number, - concentration: number -) => { +export const getTickAtSqrtPriceDelta = (tickSpacing: number, minimumRange: number, concentration: number) => { const base = Math.pow(1.0001, -(tickSpacing / 4)); - const logArg = - (1 - 1 / (concentration * CONCENTRATION_FACTOR)) / - Math.pow(1.0001, (-tickSpacing * minimumRange) / 4); + const logArg = (1 - 1 / (concentration * CONCENTRATION_FACTOR)) / Math.pow(1.0001, (-tickSpacing * minimumRange) / 4); return Math.ceil(Math.log(logArg) / Math.log(base) / 2); }; @@ -136,7 +130,7 @@ export const calcPrice = (amountTickIndex: number, isXtoY: boolean, xDecimal: nu }; export const calcYPerXPriceByTickIndex = (tickIndex: number, xDecimal: number, yDecimal: number): number => { - const sqrt = +printBigint(calculateSqrtPrice(tickIndex), PRICE_SCALE); + const sqrt = +printBigint(calculateSqrtPrice(tickIndex), Number(PRICE_SCALE)); const proportion = sqrt * sqrt; @@ -244,7 +238,7 @@ export const trimLeadingZeros = (amount: string): string => { } const reversedDec = Array.from(amountParts[1]).reverse(); - const firstNonZero = reversedDec.findIndex(char => char !== '0'); + const firstNonZero = reversedDec.findIndex((char) => char !== '0'); if (firstNonZero === -1) { return amountParts[0]; @@ -257,11 +251,11 @@ export const trimLeadingZeros = (amount: string): string => { export const extractDenom = (tokenInfo: TokenItemType) => { return tokenInfo.contractAddress ? tokenInfo.contractAddress : tokenInfo.denom; -} +}; export const extractAddress = (tokenInfo: TokenItemType) => { return tokenInfo.contractAddress ? tokenInfo.contractAddress : tokenInfo.denom; -} +}; export enum PositionTokenBlock { None, @@ -338,12 +332,10 @@ export interface LiquidityBreakpoint { index: bigint; } -export const calculateLiquidityBreakpoints = ( - ticks: (Tick | LiquidityTick)[] -): LiquidityBreakpoint[] => { +export const calculateLiquidityBreakpoints = (ticks: (Tick | LiquidityTick)[]): LiquidityBreakpoint[] => { let currentLiquidity = 0n; - return ticks.map(tick => { + return ticks.map((tick) => { currentLiquidity = currentLiquidity + BigInt(tick.liquidity_change) * (tick.sign ? 1n : -1n); return { liquidity: currentLiquidity, @@ -446,14 +438,11 @@ export type TokenDataOnChain = { balance: bigint; }; -export const getTokenDataByAddresses = async ( - tokens: string[], - address?: string -): Promise> => { +export const getTokenDataByAddresses = async (tokens: string[], address?: string): Promise> => { const tokenInfos: TokenDataOnChain[] = await SingletonOraiswapV3.getTokensInfo(tokens, address); const newTokens: Record = {}; - tokenInfos.forEach(token => { + tokenInfos.forEach((token) => { newTokens[token.address] = { symbol: token.symbol ? (token.symbol as string) : 'UNKNOWN', address: token.address, @@ -474,33 +463,15 @@ export async function handleGetCurrentPlotTicks({ poolKey, isXtoY, xDecimal, yDe const rawTicks = await SingletonOraiswapV3.getAllLiquidityTicks(poolKey, allTickmaps); console.log('rawTicks', rawTicks); if (rawTicks.length === 0) { - const data = createPlaceholderLiquidityPlot( - isXtoY, - 0, - poolKey.fee_tier.tick_spacing, - xDecimal, - yDecimal - ); + const data = createPlaceholderLiquidityPlot(isXtoY, 0, poolKey.fee_tier.tick_spacing, xDecimal, yDecimal); return data; } - const ticksData = createLiquidityPlot( - rawTicks, - poolKey.fee_tier.tick_spacing, - isXtoY, - xDecimal, - yDecimal - ); + const ticksData = createLiquidityPlot(rawTicks, poolKey.fee_tier.tick_spacing, isXtoY, xDecimal, yDecimal); return ticksData; } catch (error) { console.log(error); - const data = createPlaceholderLiquidityPlot( - isXtoY, - 10, - poolKey.fee_tier.tick_spacing, - xDecimal, - yDecimal - ); + const data = createPlaceholderLiquidityPlot(isXtoY, 10, poolKey.fee_tier.tick_spacing, xDecimal, yDecimal); return data; } -} \ No newline at end of file +} diff --git a/src/pages/Pool-V3/components/TokenForm/index.tsx b/src/pages/Pool-V3/components/TokenForm/index.tsx index 9d5e1aea8..afed7704f 100644 --- a/src/pages/Pool-V3/components/TokenForm/index.tsx +++ b/src/pages/Pool-V3/components/TokenForm/index.tsx @@ -13,7 +13,7 @@ import useTheme from 'hooks/useTheme'; import { ALL_FEE_TIERS_DATA } from 'libs/contractSingleton'; import { InitPositionData } from 'pages/Pool-V3/helpers/helper'; import useAddLiquidity from 'pages/Pool-V3/hooks/useAddLiquidity'; -import { calculateSqrtPrice, newPoolKey } from 'pages/Pool-V3/packages/wasm/oraiswap_v3_wasm'; +import { calculateSqrtPrice, newPoolKey } from 'oraiswap-v3-test'; import { Dispatch, SetStateAction, useEffect, useMemo, useState } from 'react'; import NumberFormat from 'react-number-format'; import { useSelector } from 'react-redux'; diff --git a/src/pages/Pool-V3/helpers/helper.ts b/src/pages/Pool-V3/helpers/helper.ts index 71d9f8890..f62d6f166 100644 --- a/src/pages/Pool-V3/helpers/helper.ts +++ b/src/pages/Pool-V3/helpers/helper.ts @@ -1,5 +1,4 @@ import { BigDecimal, toDisplay, TokenItemType } from '@oraichain/oraidex-common'; -import { reduce } from 'lodash'; import { Coin } from '@cosmjs/proto-signing'; import { PoolKey } from '@oraichain/oraidex-contracts-sdk/build/OraiswapV3.types'; import { oraichainTokens } from 'config/bridgeTokens'; @@ -17,16 +16,14 @@ import { getSqrtPriceDenominator, getTickAtSqrtPrice, calculateFee as wasmCalculateFee -} from '../packages/wasm/oraiswap_v3_wasm'; +} from 'oraiswap-v3-test'; import { getIconPoolData } from './format'; import { network } from 'config/networks'; -import { SwapHop } from '../packages/sdk/OraiswapV3.types'; import { CoinGeckoPrices } from 'hooks/useCoingecko'; import { CoinGeckoId } from '@oraichain/oraidex-common/build/network'; -import { ClaimFee, Position as PositionsNode } from 'gql/graphql'; +import { Position as PositionsNode } from 'gql/graphql'; import { oraichainTokensWithIcon } from 'config/chainInfos'; -// export const PERCENTAGE_SCALE = Number(getPercentageScale()); export interface InitPositionData { poolKeyData: PoolKey; lowerTick: number; @@ -143,7 +140,7 @@ export const TokenList = oraichainTokens.reduce((acc, cur) => { export const addressTickerMap: { [key: string]: string } = TokenList; export const calcYPerXPriceByTickIndex = (tickIndex: number, xDecimal: number, yDecimal: number): number => { - const sqrt = +printBigint(calculateSqrtPrice(tickIndex), PRICE_SCALE); + const sqrt = +printBigint(calculateSqrtPrice(tickIndex), Number(PRICE_SCALE)); const proportion = sqrt * sqrt; @@ -151,7 +148,7 @@ export const calcYPerXPriceByTickIndex = (tickIndex: number, xDecimal: number, y }; export const calcYPerXPriceBySqrtPrice = (sqrtPrice: bigint, xDecimal: number, yDecimal: number): number => { - const sqrt = +printBigint(sqrtPrice, PRICE_SCALE); + const sqrt = +printBigint(sqrtPrice, Number(PRICE_SCALE)); const proportion = sqrt * sqrt; @@ -248,7 +245,7 @@ const newtonIteration = (n: bigint, x0: bigint): bigint => { const sqrt = (value: bigint): bigint => { if (value < 0n) { - throw 'square root of negative numbers is not supported'; + throw Error('square root of negative numbers is not supported'); } if (value < 2n) { @@ -438,7 +435,7 @@ export const createPositionWithNativeTx = async ( export const formatClaimFeeData = (feeClaimData: PositionsNode[]) => { const fmtFeeClaimData = feeClaimData.reduce((acc, cur) => { - const { principalAmountX, principalAmountY, poolId, id, fees } = cur || {}; + const { principalAmountX, principalAmountY, id, fees } = cur || {}; const totalEarn = (fees.nodes || []).reduce( (total, fee) => { diff --git a/src/pages/Pool-V3/hooks/useAddLiquidity.ts b/src/pages/Pool-V3/hooks/useAddLiquidity.ts index c10f7e189..f08b5040a 100644 --- a/src/pages/Pool-V3/hooks/useAddLiquidity.ts +++ b/src/pages/Pool-V3/hooks/useAddLiquidity.ts @@ -1,7 +1,6 @@ import SingletonOraiswapV3 from 'libs/contractSingleton'; import { approveListToken, - approveToken, calculateTokenAmountsWithSlippage, createPoolTx, createPositionTx, @@ -11,7 +10,7 @@ import { isNativeToken } from '../helpers/helper'; -import { newPoolKey } from '../packages/wasm/oraiswap_v3_wasm'; +import { newPoolKey } from 'oraiswap-v3-test'; import { getCosmWasmClient } from 'libs/cosmjs'; import { network } from 'config/networks'; diff --git a/src/pages/Pool-V3/packages/sdk/OraiswapV3.client.ts b/src/pages/Pool-V3/packages/sdk/OraiswapV3.client.ts deleted file mode 100644 index 5992663de..000000000 --- a/src/pages/Pool-V3/packages/sdk/OraiswapV3.client.ts +++ /dev/null @@ -1,1203 +0,0 @@ -/** -* This file was automatically generated by @oraichain/ts-codegen@0.35.9. -* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, -* and run the @oraichain/ts-codegen generate command to regenerate this file. -*/ - -import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from "@cosmjs/cosmwasm-stargate"; -import { Coin, StdFee } from "@cosmjs/amino"; -import {Percentage, InstantiateMsg, ExecuteMsg, Addr, Liquidity, SqrtPrice, TokenAmount, Binary, Expiration, Timestamp, Uint64, AssetInfo, PoolKey, FeeTier, SwapHop, NftExtensionMsg, QueryMsg, MigrateMsg, FeeGrowth, AllNftInfoResponse, OwnerOfResponse, Approval, NftInfoResponse, Position, PositionIncentives, ArrayOfPosition, TokensResponse, ApprovedForAllResponse, Boolean, ArrayOfFeeTier, ArrayOfLiquidityTick, LiquidityTick, Uint32, NumTokensResponse, Pool, IncentiveRecord, ArrayOfPoolWithPoolKey, PoolWithPoolKey, Uint128, ArrayOfAsset, Asset, ArrayOfPositionTick, PositionTick, QuoteResult, Tick, TickIncentive, ArrayOfTupleOfUint16AndUint64} from "./OraiswapV3.types"; -export interface OraiswapV3ReadOnlyInterface { - contractAddress: string; - admin: () => Promise; - protocolFee: () => Promise; - position: ({ - index, - ownerId - }: { - index: number; - ownerId: Addr; - }) => Promise; - positions: ({ - limit, - offset, - ownerId - }: { - limit?: number; - offset?: number; - ownerId: Addr; - }) => Promise; - allPosition: ({ - limit, - startAfter - }: { - limit?: number; - startAfter?: Binary; - }) => Promise; - feeTierExist: ({ - feeTier - }: { - feeTier: FeeTier; - }) => Promise; - pool: ({ - feeTier, - token0, - token1 - }: { - feeTier: FeeTier; - token0: string; - token1: string; - }) => Promise; - pools: ({ - limit, - startAfter - }: { - limit?: number; - startAfter?: PoolKey; - }) => Promise; - tick: ({ - index, - key - }: { - index: number; - key: PoolKey; - }) => Promise; - isTickInitialized: ({ - index, - key - }: { - index: number; - key: PoolKey; - }) => Promise; - feeTiers: () => Promise; - positionTicks: ({ - offset, - owner - }: { - offset: number; - owner: Addr; - }) => Promise; - userPositionAmount: ({ - owner - }: { - owner: Addr; - }) => Promise; - tickMap: ({ - lowerTickIndex, - poolKey, - upperTickIndex, - xToY - }: { - lowerTickIndex: number; - poolKey: PoolKey; - upperTickIndex: number; - xToY: boolean; - }) => Promise; - liquidityTicks: ({ - poolKey, - tickIndexes - }: { - poolKey: PoolKey; - tickIndexes: number[]; - }) => Promise; - liquidityTicksAmount: ({ - lowerTick, - poolKey, - upperTick - }: { - lowerTick: number; - poolKey: PoolKey; - upperTick: number; - }) => Promise; - poolsForPair: ({ - token0, - token1 - }: { - token0: string; - token1: string; - }) => Promise; - quote: ({ - amount, - byAmountIn, - poolKey, - sqrtPriceLimit, - xToY - }: { - amount: TokenAmount; - byAmountIn: boolean; - poolKey: PoolKey; - sqrtPriceLimit: SqrtPrice; - xToY: boolean; - }) => Promise; - quoteRoute: ({ - amountIn, - swaps - }: { - amountIn: TokenAmount; - swaps: SwapHop[]; - }) => Promise; - numTokens: () => Promise; - ownerOf: ({ - includeExpired, - tokenId - }: { - includeExpired?: boolean; - tokenId: number; - }) => Promise; - approvedForAll: ({ - includeExpired, - limit, - owner, - startAfter - }: { - includeExpired?: boolean; - limit?: number; - owner: Addr; - startAfter?: Addr; - }) => Promise; - nftInfo: ({ - tokenId - }: { - tokenId: number; - }) => Promise; - allNftInfo: ({ - includeExpired, - tokenId - }: { - includeExpired?: boolean; - tokenId: number; - }) => Promise; - tokens: ({ - limit, - owner, - startAfter - }: { - limit?: number; - owner: Addr; - startAfter?: number; - }) => Promise; - allTokens: ({ - limit, - startAfter - }: { - limit?: number; - startAfter?: number; - }) => Promise; - positionIncentives: ({ - index, - ownerId - }: { - index: number; - ownerId: Addr; - }) => Promise; - poolsByPoolKeys: ({ - poolKeys - }: { - poolKeys: PoolKey[]; - }) => Promise; -} -export class OraiswapV3QueryClient implements OraiswapV3ReadOnlyInterface { - client: CosmWasmClient; - contractAddress: string; - - constructor(client: CosmWasmClient, contractAddress: string) { - this.client = client; - this.contractAddress = contractAddress; - this.admin = this.admin.bind(this); - this.protocolFee = this.protocolFee.bind(this); - this.position = this.position.bind(this); - this.positions = this.positions.bind(this); - this.allPosition = this.allPosition.bind(this); - this.feeTierExist = this.feeTierExist.bind(this); - this.pool = this.pool.bind(this); - this.pools = this.pools.bind(this); - this.tick = this.tick.bind(this); - this.isTickInitialized = this.isTickInitialized.bind(this); - this.feeTiers = this.feeTiers.bind(this); - this.positionTicks = this.positionTicks.bind(this); - this.userPositionAmount = this.userPositionAmount.bind(this); - this.tickMap = this.tickMap.bind(this); - this.liquidityTicks = this.liquidityTicks.bind(this); - this.liquidityTicksAmount = this.liquidityTicksAmount.bind(this); - this.poolsForPair = this.poolsForPair.bind(this); - this.quote = this.quote.bind(this); - this.quoteRoute = this.quoteRoute.bind(this); - this.numTokens = this.numTokens.bind(this); - this.ownerOf = this.ownerOf.bind(this); - this.approvedForAll = this.approvedForAll.bind(this); - this.nftInfo = this.nftInfo.bind(this); - this.allNftInfo = this.allNftInfo.bind(this); - this.tokens = this.tokens.bind(this); - this.allTokens = this.allTokens.bind(this); - this.positionIncentives = this.positionIncentives.bind(this); - this.poolsByPoolKeys = this.poolsByPoolKeys.bind(this); - } - - admin = async (): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - admin: {} - }); - }; - protocolFee = async (): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - protocol_fee: {} - }); - }; - position = async ({ - index, - ownerId - }: { - index: number; - ownerId: Addr; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - position: { - index, - owner_id: ownerId - } - }); - }; - positions = async ({ - limit, - offset, - ownerId - }: { - limit?: number; - offset?: number; - ownerId: Addr; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - positions: { - limit, - offset, - owner_id: ownerId - } - }); - }; - allPosition = async ({ - limit, - startAfter - }: { - limit?: number; - startAfter?: Binary; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - all_position: { - limit, - start_after: startAfter - } - }); - }; - feeTierExist = async ({ - feeTier - }: { - feeTier: FeeTier; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - fee_tier_exist: { - fee_tier: feeTier - } - }); - }; - pool = async ({ - feeTier, - token0, - token1 - }: { - feeTier: FeeTier; - token0: string; - token1: string; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - pool: { - fee_tier: feeTier, - token_0: token0, - token_1: token1 - } - }); - }; - pools = async ({ - limit, - startAfter - }: { - limit?: number; - startAfter?: PoolKey; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - pools: { - limit, - start_after: startAfter - } - }); - }; - tick = async ({ - index, - key - }: { - index: number; - key: PoolKey; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - tick: { - index, - key - } - }); - }; - isTickInitialized = async ({ - index, - key - }: { - index: number; - key: PoolKey; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - is_tick_initialized: { - index, - key - } - }); - }; - feeTiers = async (): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - fee_tiers: {} - }); - }; - positionTicks = async ({ - offset, - owner - }: { - offset: number; - owner: Addr; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - position_ticks: { - offset, - owner - } - }); - }; - userPositionAmount = async ({ - owner - }: { - owner: Addr; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - user_position_amount: { - owner - } - }); - }; - tickMap = async ({ - lowerTickIndex, - poolKey, - upperTickIndex, - xToY - }: { - lowerTickIndex: number; - poolKey: PoolKey; - upperTickIndex: number; - xToY: boolean; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - tick_map: { - lower_tick_index: lowerTickIndex, - pool_key: poolKey, - upper_tick_index: upperTickIndex, - x_to_y: xToY - } - }); - }; - liquidityTicks = async ({ - poolKey, - tickIndexes - }: { - poolKey: PoolKey; - tickIndexes: number[]; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - liquidity_ticks: { - pool_key: poolKey, - tick_indexes: tickIndexes - } - }); - }; - liquidityTicksAmount = async ({ - lowerTick, - poolKey, - upperTick - }: { - lowerTick: number; - poolKey: PoolKey; - upperTick: number; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - liquidity_ticks_amount: { - lower_tick: lowerTick, - pool_key: poolKey, - upper_tick: upperTick - } - }); - }; - poolsForPair = async ({ - token0, - token1 - }: { - token0: string; - token1: string; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - pools_for_pair: { - token_0: token0, - token_1: token1 - } - }); - }; - quote = async ({ - amount, - byAmountIn, - poolKey, - sqrtPriceLimit, - xToY - }: { - amount: TokenAmount; - byAmountIn: boolean; - poolKey: PoolKey; - sqrtPriceLimit: SqrtPrice; - xToY: boolean; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - quote: { - amount, - by_amount_in: byAmountIn, - pool_key: poolKey, - sqrt_price_limit: sqrtPriceLimit, - x_to_y: xToY - } - }); - }; - quoteRoute = async ({ - amountIn, - swaps - }: { - amountIn: TokenAmount; - swaps: SwapHop[]; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - quote_route: { - amount_in: amountIn, - swaps - } - }); - }; - numTokens = async (): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - num_tokens: {} - }); - }; - ownerOf = async ({ - includeExpired, - tokenId - }: { - includeExpired?: boolean; - tokenId: number; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - owner_of: { - include_expired: includeExpired, - token_id: tokenId - } - }); - }; - approvedForAll = async ({ - includeExpired, - limit, - owner, - startAfter - }: { - includeExpired?: boolean; - limit?: number; - owner: Addr; - startAfter?: Addr; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - approved_for_all: { - include_expired: includeExpired, - limit, - owner, - start_after: startAfter - } - }); - }; - nftInfo = async ({ - tokenId - }: { - tokenId: number; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - nft_info: { - token_id: tokenId - } - }); - }; - allNftInfo = async ({ - includeExpired, - tokenId - }: { - includeExpired?: boolean; - tokenId: number; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - all_nft_info: { - include_expired: includeExpired, - token_id: tokenId - } - }); - }; - tokens = async ({ - limit, - owner, - startAfter - }: { - limit?: number; - owner: Addr; - startAfter?: number; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - tokens: { - limit, - owner, - start_after: startAfter - } - }); - }; - allTokens = async ({ - limit, - startAfter - }: { - limit?: number; - startAfter?: number; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - all_tokens: { - limit, - start_after: startAfter - } - }); - }; - positionIncentives = async ({ - index, - ownerId - }: { - index: number; - ownerId: Addr; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - position_incentives: { - index, - owner_id: ownerId - } - }); - }; - poolsByPoolKeys = async ({ - poolKeys - }: { - poolKeys: PoolKey[]; - }): Promise => { - return this.client.queryContractSmart(this.contractAddress, { - pools_by_pool_keys: { - pool_keys: poolKeys - } - }); - }; -} -export interface OraiswapV3Interface extends OraiswapV3ReadOnlyInterface { - contractAddress: string; - sender: string; - changeAdmin: ({ - newAdmin - }: { - newAdmin: Addr; - }, _fee?: number | StdFee | "auto", _memo?: string, _funds?: Coin[]) => Promise; - withdrawProtocolFee: ({ - poolKey - }: { - poolKey: PoolKey; - }, _fee?: number | StdFee | "auto", _memo?: string, _funds?: Coin[]) => Promise; - changeProtocolFee: ({ - protocolFee - }: { - protocolFee: Percentage; - }, _fee?: number | StdFee | "auto", _memo?: string, _funds?: Coin[]) => Promise; - changeFeeReceiver: ({ - feeReceiver, - poolKey - }: { - feeReceiver: Addr; - poolKey: PoolKey; - }, _fee?: number | StdFee | "auto", _memo?: string, _funds?: Coin[]) => Promise; - createPosition: ({ - liquidityDelta, - lowerTick, - poolKey, - slippageLimitLower, - slippageLimitUpper, - upperTick - }: { - liquidityDelta: Liquidity; - lowerTick: number; - poolKey: PoolKey; - slippageLimitLower: SqrtPrice; - slippageLimitUpper: SqrtPrice; - upperTick: number; - }, _fee?: number | StdFee | "auto", _memo?: string, _funds?: Coin[]) => Promise; - swap: ({ - amount, - byAmountIn, - poolKey, - sqrtPriceLimit, - xToY - }: { - amount: TokenAmount; - byAmountIn: boolean; - poolKey: PoolKey; - sqrtPriceLimit: SqrtPrice; - xToY: boolean; - }, _fee?: number | StdFee | "auto", _memo?: string, _funds?: Coin[]) => Promise; - swapRoute: ({ - amountIn, - expectedAmountOut, - slippage, - swaps - }: { - amountIn: TokenAmount; - expectedAmountOut: TokenAmount; - slippage: Percentage; - swaps: SwapHop[]; - }, _fee?: number | StdFee | "auto", _memo?: string, _funds?: Coin[]) => Promise; - transferPosition: ({ - index, - receiver - }: { - index: number; - receiver: string; - }, _fee?: number | StdFee | "auto", _memo?: string, _funds?: Coin[]) => Promise; - claimFee: ({ - index - }: { - index: number; - }, _fee?: number | StdFee | "auto", _memo?: string, _funds?: Coin[]) => Promise; - removePosition: ({ - index - }: { - index: number; - }, _fee?: number | StdFee | "auto", _memo?: string, _funds?: Coin[]) => Promise; - createPool: ({ - feeTier, - initSqrtPrice, - initTick, - token0, - token1 - }: { - feeTier: FeeTier; - initSqrtPrice: SqrtPrice; - initTick: number; - token0: string; - token1: string; - }, _fee?: number | StdFee | "auto", _memo?: string, _funds?: Coin[]) => Promise; - addFeeTier: ({ - feeTier - }: { - feeTier: FeeTier; - }, _fee?: number | StdFee | "auto", _memo?: string, _funds?: Coin[]) => Promise; - removeFeeTier: ({ - feeTier - }: { - feeTier: FeeTier; - }, _fee?: number | StdFee | "auto", _memo?: string, _funds?: Coin[]) => Promise; - transferNft: ({ - recipient, - tokenId - }: { - recipient: Addr; - tokenId: number; - }, _fee?: number | StdFee | "auto", _memo?: string, _funds?: Coin[]) => Promise; - mint: ({ - extension - }: { - extension: NftExtensionMsg; - }, _fee?: number | StdFee | "auto", _memo?: string, _funds?: Coin[]) => Promise; - burn: ({ - tokenId - }: { - tokenId: number; - }, _fee?: number | StdFee | "auto", _memo?: string, _funds?: Coin[]) => Promise; - sendNft: ({ - contract, - msg, - tokenId - }: { - contract: Addr; - msg?: Binary; - tokenId: number; - }, _fee?: number | StdFee | "auto", _memo?: string, _funds?: Coin[]) => Promise; - approve: ({ - expires, - spender, - tokenId - }: { - expires?: Expiration; - spender: Addr; - tokenId: number; - }, _fee?: number | StdFee | "auto", _memo?: string, _funds?: Coin[]) => Promise; - revoke: ({ - spender, - tokenId - }: { - spender: Addr; - tokenId: number; - }, _fee?: number | StdFee | "auto", _memo?: string, _funds?: Coin[]) => Promise; - approveAll: ({ - expires, - operator - }: { - expires?: Expiration; - operator: Addr; - }, _fee?: number | StdFee | "auto", _memo?: string, _funds?: Coin[]) => Promise; - revokeAll: ({ - operator - }: { - operator: Addr; - }, _fee?: number | StdFee | "auto", _memo?: string, _funds?: Coin[]) => Promise; - createIncentive: ({ - poolKey, - rewardPerSec, - rewardToken, - startTimestamp, - totalReward - }: { - poolKey: PoolKey; - rewardPerSec: TokenAmount; - rewardToken: AssetInfo; - startTimestamp?: number; - totalReward?: TokenAmount; - }, _fee?: number | StdFee | "auto", _memo?: string, _funds?: Coin[]) => Promise; - updateIncentive: ({ - incentiveId, - poolKey, - remainingReward, - rewardPerSec, - startTimestamp - }: { - incentiveId: number; - poolKey: PoolKey; - remainingReward?: TokenAmount; - rewardPerSec?: TokenAmount; - startTimestamp?: number; - }, _fee?: number | StdFee | "auto", _memo?: string, _funds?: Coin[]) => Promise; - claimIncentive: ({ - index - }: { - index: number; - }, _fee?: number | StdFee | "auto", _memo?: string, _funds?: Coin[]) => Promise; -} -export class OraiswapV3Client extends OraiswapV3QueryClient implements OraiswapV3Interface { - client: SigningCosmWasmClient; - sender: string; - contractAddress: string; - - constructor(client: SigningCosmWasmClient, sender: string, contractAddress: string) { - super(client, contractAddress); - this.client = client; - this.sender = sender; - this.contractAddress = contractAddress; - this.changeAdmin = this.changeAdmin.bind(this); - this.withdrawProtocolFee = this.withdrawProtocolFee.bind(this); - this.changeProtocolFee = this.changeProtocolFee.bind(this); - this.changeFeeReceiver = this.changeFeeReceiver.bind(this); - this.createPosition = this.createPosition.bind(this); - this.swap = this.swap.bind(this); - this.swapRoute = this.swapRoute.bind(this); - this.transferPosition = this.transferPosition.bind(this); - this.claimFee = this.claimFee.bind(this); - this.removePosition = this.removePosition.bind(this); - this.createPool = this.createPool.bind(this); - this.addFeeTier = this.addFeeTier.bind(this); - this.removeFeeTier = this.removeFeeTier.bind(this); - this.transferNft = this.transferNft.bind(this); - this.mint = this.mint.bind(this); - this.burn = this.burn.bind(this); - this.sendNft = this.sendNft.bind(this); - this.approve = this.approve.bind(this); - this.revoke = this.revoke.bind(this); - this.approveAll = this.approveAll.bind(this); - this.revokeAll = this.revokeAll.bind(this); - this.createIncentive = this.createIncentive.bind(this); - this.updateIncentive = this.updateIncentive.bind(this); - this.claimIncentive = this.claimIncentive.bind(this); - } - - changeAdmin = async ({ - newAdmin - }: { - newAdmin: Addr; - }, _fee: number | StdFee | "auto" = "auto", _memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - change_admin: { - new_admin: newAdmin - } - }, _fee, _memo, _funds); - }; - withdrawProtocolFee = async ({ - poolKey - }: { - poolKey: PoolKey; - }, _fee: number | StdFee | "auto" = "auto", _memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - withdraw_protocol_fee: { - pool_key: poolKey - } - }, _fee, _memo, _funds); - }; - changeProtocolFee = async ({ - protocolFee - }: { - protocolFee: Percentage; - }, _fee: number | StdFee | "auto" = "auto", _memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - change_protocol_fee: { - protocol_fee: protocolFee - } - }, _fee, _memo, _funds); - }; - changeFeeReceiver = async ({ - feeReceiver, - poolKey - }: { - feeReceiver: Addr; - poolKey: PoolKey; - }, _fee: number | StdFee | "auto" = "auto", _memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - change_fee_receiver: { - fee_receiver: feeReceiver, - pool_key: poolKey - } - }, _fee, _memo, _funds); - }; - createPosition = async ({ - liquidityDelta, - lowerTick, - poolKey, - slippageLimitLower, - slippageLimitUpper, - upperTick - }: { - liquidityDelta: Liquidity; - lowerTick: number; - poolKey: PoolKey; - slippageLimitLower: SqrtPrice; - slippageLimitUpper: SqrtPrice; - upperTick: number; - }, _fee: number | StdFee | "auto" = "auto", _memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - create_position: { - liquidity_delta: liquidityDelta, - lower_tick: lowerTick, - pool_key: poolKey, - slippage_limit_lower: slippageLimitLower, - slippage_limit_upper: slippageLimitUpper, - upper_tick: upperTick - } - }, _fee, _memo, _funds); - }; - swap = async ({ - amount, - byAmountIn, - poolKey, - sqrtPriceLimit, - xToY - }: { - amount: TokenAmount; - byAmountIn: boolean; - poolKey: PoolKey; - sqrtPriceLimit: SqrtPrice; - xToY: boolean; - }, _fee: number | StdFee | "auto" = "auto", _memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - swap: { - amount, - by_amount_in: byAmountIn, - pool_key: poolKey, - sqrt_price_limit: sqrtPriceLimit, - x_to_y: xToY - } - }, _fee, _memo, _funds); - }; - swapRoute = async ({ - amountIn, - expectedAmountOut, - slippage, - swaps - }: { - amountIn: TokenAmount; - expectedAmountOut: TokenAmount; - slippage: Percentage; - swaps: SwapHop[]; - }, _fee: number | StdFee | "auto" = "auto", _memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - swap_route: { - amount_in: amountIn, - expected_amount_out: expectedAmountOut, - slippage, - swaps - } - }, _fee, _memo, _funds); - }; - transferPosition = async ({ - index, - receiver - }: { - index: number; - receiver: string; - }, _fee: number | StdFee | "auto" = "auto", _memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - transfer_position: { - index, - receiver - } - }, _fee, _memo, _funds); - }; - claimFee = async ({ - index - }: { - index: number; - }, _fee: number | StdFee | "auto" = "auto", _memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - claim_fee: { - index - } - }, _fee, _memo, _funds); - }; - removePosition = async ({ - index - }: { - index: number; - }, _fee: number | StdFee | "auto" = "auto", _memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - remove_position: { - index - } - }, _fee, _memo, _funds); - }; - createPool = async ({ - feeTier, - initSqrtPrice, - initTick, - token0, - token1 - }: { - feeTier: FeeTier; - initSqrtPrice: SqrtPrice; - initTick: number; - token0: string; - token1: string; - }, _fee: number | StdFee | "auto" = "auto", _memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - create_pool: { - fee_tier: feeTier, - init_sqrt_price: initSqrtPrice, - init_tick: initTick, - token_0: token0, - token_1: token1 - } - }, _fee, _memo, _funds); - }; - addFeeTier = async ({ - feeTier - }: { - feeTier: FeeTier; - }, _fee: number | StdFee | "auto" = "auto", _memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - add_fee_tier: { - fee_tier: feeTier - } - }, _fee, _memo, _funds); - }; - removeFeeTier = async ({ - feeTier - }: { - feeTier: FeeTier; - }, _fee: number | StdFee | "auto" = "auto", _memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - remove_fee_tier: { - fee_tier: feeTier - } - }, _fee, _memo, _funds); - }; - transferNft = async ({ - recipient, - tokenId - }: { - recipient: Addr; - tokenId: number; - }, _fee: number | StdFee | "auto" = "auto", _memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - transfer_nft: { - recipient, - token_id: tokenId - } - }, _fee, _memo, _funds); - }; - mint = async ({ - extension - }: { - extension: NftExtensionMsg; - }, _fee: number | StdFee | "auto" = "auto", _memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - mint: { - extension - } - }, _fee, _memo, _funds); - }; - burn = async ({ - tokenId - }: { - tokenId: number; - }, _fee: number | StdFee | "auto" = "auto", _memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - burn: { - token_id: tokenId - } - }, _fee, _memo, _funds); - }; - sendNft = async ({ - contract, - msg, - tokenId - }: { - contract: Addr; - msg?: Binary; - tokenId: number; - }, _fee: number | StdFee | "auto" = "auto", _memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - send_nft: { - contract, - msg, - token_id: tokenId - } - }, _fee, _memo, _funds); - }; - approve = async ({ - expires, - spender, - tokenId - }: { - expires?: Expiration; - spender: Addr; - tokenId: number; - }, _fee: number | StdFee | "auto" = "auto", _memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - approve: { - expires, - spender, - token_id: tokenId - } - }, _fee, _memo, _funds); - }; - revoke = async ({ - spender, - tokenId - }: { - spender: Addr; - tokenId: number; - }, _fee: number | StdFee | "auto" = "auto", _memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - revoke: { - spender, - token_id: tokenId - } - }, _fee, _memo, _funds); - }; - approveAll = async ({ - expires, - operator - }: { - expires?: Expiration; - operator: Addr; - }, _fee: number | StdFee | "auto" = "auto", _memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - approve_all: { - expires, - operator - } - }, _fee, _memo, _funds); - }; - revokeAll = async ({ - operator - }: { - operator: Addr; - }, _fee: number | StdFee | "auto" = "auto", _memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - revoke_all: { - operator - } - }, _fee, _memo, _funds); - }; - createIncentive = async ({ - poolKey, - rewardPerSec, - rewardToken, - startTimestamp, - totalReward - }: { - poolKey: PoolKey; - rewardPerSec: TokenAmount; - rewardToken: AssetInfo; - startTimestamp?: number; - totalReward?: TokenAmount; - }, _fee: number | StdFee | "auto" = "auto", _memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - create_incentive: { - pool_key: poolKey, - reward_per_sec: rewardPerSec, - reward_token: rewardToken, - start_timestamp: startTimestamp, - total_reward: totalReward - } - }, _fee, _memo, _funds); - }; - updateIncentive = async ({ - incentiveId, - poolKey, - remainingReward, - rewardPerSec, - startTimestamp - }: { - incentiveId: number; - poolKey: PoolKey; - remainingReward?: TokenAmount; - rewardPerSec?: TokenAmount; - startTimestamp?: number; - }, _fee: number | StdFee | "auto" = "auto", _memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - update_incentive: { - incentive_id: incentiveId, - pool_key: poolKey, - remaining_reward: remainingReward, - reward_per_sec: rewardPerSec, - start_timestamp: startTimestamp - } - }, _fee, _memo, _funds); - }; - claimIncentive = async ({ - index - }: { - index: number; - }, _fee: number | StdFee | "auto" = "auto", _memo?: string, _funds?: Coin[]): Promise => { - return await this.client.execute(this.sender, this.contractAddress, { - claim_incentive: { - index - } - }, _fee, _memo, _funds); - }; -} \ No newline at end of file diff --git a/src/pages/Pool-V3/packages/sdk/OraiswapV3.types.ts b/src/pages/Pool-V3/packages/sdk/OraiswapV3.types.ts deleted file mode 100644 index db0d1b94a..000000000 --- a/src/pages/Pool-V3/packages/sdk/OraiswapV3.types.ts +++ /dev/null @@ -1,431 +0,0 @@ -export type Percentage = number; -export interface InstantiateMsg { - protocol_fee: Percentage; -} -export type ExecuteMsg = { - change_admin: { - new_admin: Addr; - }; -} | { - withdraw_protocol_fee: { - pool_key: PoolKey; - }; -} | { - change_protocol_fee: { - protocol_fee: Percentage; - }; -} | { - change_fee_receiver: { - fee_receiver: Addr; - pool_key: PoolKey; - }; -} | { - create_position: { - liquidity_delta: Liquidity; - lower_tick: number; - pool_key: PoolKey; - slippage_limit_lower: SqrtPrice; - slippage_limit_upper: SqrtPrice; - upper_tick: number; - }; -} | { - swap: { - amount: TokenAmount; - by_amount_in: boolean; - pool_key: PoolKey; - sqrt_price_limit: SqrtPrice; - x_to_y: boolean; - }; -} | { - swap_route: { - amount_in: TokenAmount; - expected_amount_out: TokenAmount; - slippage: Percentage; - swaps: SwapHop[]; - }; -} | { - transfer_position: { - index: number; - receiver: string; - }; -} | { - claim_fee: { - index: number; - }; -} | { - remove_position: { - index: number; - }; -} | { - create_pool: { - fee_tier: FeeTier; - init_sqrt_price: SqrtPrice; - init_tick: number; - token_0: string; - token_1: string; - }; -} | { - add_fee_tier: { - fee_tier: FeeTier; - }; -} | { - remove_fee_tier: { - fee_tier: FeeTier; - }; -} | { - transfer_nft: { - recipient: Addr; - token_id: number; - }; -} | { - mint: { - extension: NftExtensionMsg; - }; -} | { - burn: { - token_id: number; - }; -} | { - send_nft: { - contract: Addr; - msg?: Binary | null; - token_id: number; - }; -} | { - approve: { - expires?: Expiration | null; - spender: Addr; - token_id: number; - }; -} | { - revoke: { - spender: Addr; - token_id: number; - }; -} | { - approve_all: { - expires?: Expiration | null; - operator: Addr; - }; -} | { - revoke_all: { - operator: Addr; - }; -} | { - create_incentive: { - pool_key: PoolKey; - reward_per_sec: TokenAmount; - reward_token: AssetInfo; - start_timestamp?: number | null; - total_reward?: TokenAmount | null; - }; -} | { - update_incentive: { - incentive_id: number; - pool_key: PoolKey; - remaining_reward?: TokenAmount | null; - reward_per_sec?: TokenAmount | null; - start_timestamp?: number | null; - }; -} | { - claim_incentive: { - index: number; - }; -}; -export type Addr = string; -export type Liquidity = string; -export type SqrtPrice = string; -export type TokenAmount = string; -export type Binary = string; -export type Expiration = { - at_height: number; -} | { - at_time: Timestamp; -} | { - never: {}; -}; -export type Timestamp = Uint64; -export type Uint64 = string; -export type AssetInfo = { - token: { - contract_addr: Addr; - }; -} | { - native_token: { - denom: string; - }; -}; -export interface PoolKey { - fee_tier: FeeTier; - token_x: string; - token_y: string; -} -export interface FeeTier { - fee: Percentage; - tick_spacing: number; -} -export interface SwapHop { - pool_key: PoolKey; - x_to_y: boolean; -} -export interface NftExtensionMsg { - liquidity_delta: Liquidity; - lower_tick: number; - pool_key: PoolKey; - slippage_limit_lower: SqrtPrice; - slippage_limit_upper: SqrtPrice; - upper_tick: number; -} -export type QueryMsg = { - admin: {}; -} | { - protocol_fee: {}; -} | { - position: { - index: number; - owner_id: Addr; - }; -} | { - positions: { - limit?: number | null; - offset?: number | null; - owner_id: Addr; - }; -} | { - all_position: { - limit?: number | null; - start_after?: Binary | null; - }; -} | { - fee_tier_exist: { - fee_tier: FeeTier; - }; -} | { - pool: { - fee_tier: FeeTier; - token_0: string; - token_1: string; - }; -} | { - pools: { - limit?: number | null; - start_after?: PoolKey | null; - }; -} | { - tick: { - index: number; - key: PoolKey; - }; -} | { - is_tick_initialized: { - index: number; - key: PoolKey; - }; -} | { - fee_tiers: {}; -} | { - position_ticks: { - offset: number; - owner: Addr; - }; -} | { - user_position_amount: { - owner: Addr; - }; -} | { - tick_map: { - lower_tick_index: number; - pool_key: PoolKey; - upper_tick_index: number; - x_to_y: boolean; - }; -} | { - liquidity_ticks: { - pool_key: PoolKey; - tick_indexes: number[]; - }; -} | { - liquidity_ticks_amount: { - lower_tick: number; - pool_key: PoolKey; - upper_tick: number; - }; -} | { - pools_for_pair: { - token_0: string; - token_1: string; - }; -} | { - quote: { - amount: TokenAmount; - by_amount_in: boolean; - pool_key: PoolKey; - sqrt_price_limit: SqrtPrice; - x_to_y: boolean; - }; -} | { - quote_route: { - amount_in: TokenAmount; - swaps: SwapHop[]; - }; -} | { - num_tokens: {}; -} | { - owner_of: { - include_expired?: boolean | null; - token_id: number; - }; -} | { - approved_for_all: { - include_expired?: boolean | null; - limit?: number | null; - owner: Addr; - start_after?: Addr | null; - }; -} | { - nft_info: { - token_id: number; - }; -} | { - all_nft_info: { - include_expired?: boolean | null; - token_id: number; - }; -} | { - tokens: { - limit?: number | null; - owner: Addr; - start_after?: number | null; - }; -} | { - all_tokens: { - limit?: number | null; - start_after?: number | null; - }; -} | { - position_incentives: { - index: number; - owner_id: Addr; - }; -} | { - pools_by_pool_keys: { - pool_keys: PoolKey[]; - }; -}; -export interface MigrateMsg {} -export type FeeGrowth = string; -export interface AllNftInfoResponse { - access: OwnerOfResponse; - info: NftInfoResponse; -} -export interface OwnerOfResponse { - approvals: Approval[]; - owner: Addr; -} -export interface Approval { - expires: Expiration; - spender: Addr; -} -export interface NftInfoResponse { - extension: Position; -} -export interface Position { - approvals?: Approval[]; - fee_growth_inside_x: FeeGrowth; - fee_growth_inside_y: FeeGrowth; - incentives?: PositionIncentives[]; - last_block_number: number; - liquidity: Liquidity; - lower_tick_index: number; - pool_key: PoolKey; - token_id?: number; - tokens_owed_x: TokenAmount; - tokens_owed_y: TokenAmount; - upper_tick_index: number; -} -export interface PositionIncentives { - incentive_growth_inside: FeeGrowth; - incentive_id: number; - pending_rewards: TokenAmount; -} -export type ArrayOfPosition = Position[]; -export interface TokensResponse { - tokens: number[]; -} -export interface ApprovedForAllResponse { - operators: Approval[]; -} -export type Boolean = boolean; -export type ArrayOfFeeTier = FeeTier[]; -export type ArrayOfLiquidityTick = LiquidityTick[]; -export interface LiquidityTick { - index: number; - liquidity_change: Liquidity; - sign: boolean; -} -export type Uint32 = number; -export interface NumTokensResponse { - count: number; -} -export interface Pool { - current_tick_index: number; - fee_growth_global_x: FeeGrowth; - fee_growth_global_y: FeeGrowth; - fee_protocol_token_x: TokenAmount; - fee_protocol_token_y: TokenAmount; - fee_receiver: string; - incentives?: IncentiveRecord[]; - last_timestamp: number; - liquidity: Liquidity; - sqrt_price: SqrtPrice; - start_timestamp: number; -} -export interface IncentiveRecord { - id: number; - incentive_growth_global: FeeGrowth; - last_updated: number; - remaining: TokenAmount; - reward_per_sec: TokenAmount; - reward_token: AssetInfo; - start_timestamp: number; -} -export type ArrayOfPoolWithPoolKey = PoolWithPoolKey[]; -export interface PoolWithPoolKey { - pool: Pool; - pool_key: PoolKey; -} -export type Uint128 = string; -export type ArrayOfAsset = Asset[]; -export interface Asset { - amount: Uint128; - info: AssetInfo; -} -export type ArrayOfPositionTick = PositionTick[]; -export interface PositionTick { - fee_growth_outside_x: FeeGrowth; - fee_growth_outside_y: FeeGrowth; - index: number; - seconds_outside: number; -} -export interface QuoteResult { - amount_in: TokenAmount; - amount_out: TokenAmount; - target_sqrt_price: SqrtPrice; - ticks: Tick[]; -} -export interface Tick { - fee_growth_outside_x: FeeGrowth; - fee_growth_outside_y: FeeGrowth; - incentives?: TickIncentive[]; - index: number; - liquidity_change: Liquidity; - liquidity_gross: Liquidity; - seconds_outside: number; - sign: boolean; - sqrt_price: SqrtPrice; -} -export interface TickIncentive { - incentive_growth_outside: FeeGrowth; - incentive_id: number; -} -export type ArrayOfTupleOfUint16AndUint64 = [number, number][]; \ No newline at end of file diff --git a/src/pages/Pool-V3/packages/sdk/index.ts b/src/pages/Pool-V3/packages/sdk/index.ts deleted file mode 100644 index eaeabd373..000000000 --- a/src/pages/Pool-V3/packages/sdk/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * as OraiswapV3Types from './OraiswapV3.types'; -export * from './OraiswapV3.client'; \ No newline at end of file diff --git a/src/pages/Pool-V3/packages/wasm/oraiswap_v3_wasm.d.ts b/src/pages/Pool-V3/packages/wasm/oraiswap_v3_wasm.d.ts deleted file mode 100644 index b57135354..000000000 --- a/src/pages/Pool-V3/packages/wasm/oraiswap_v3_wasm.d.ts +++ /dev/null @@ -1,646 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -/** -* @param {SqrtPrice} current_sqrt_price -* @param {SqrtPrice} target_sqrt_price -* @param {Liquidity} liquidity -* @param {TokenAmount} amount -* @param {boolean} by_amount_in -* @param {Percentage} fee -* @returns {SwapResult} -*/ -export function computeSwapStep(current_sqrt_price: SqrtPrice, target_sqrt_price: SqrtPrice, liquidity: Liquidity, amount: TokenAmount, by_amount_in: boolean, fee: Percentage): SwapResult; -/** -* @param {SqrtPrice} sqrt_price_a -* @param {SqrtPrice} sqrt_price_b -* @param {Liquidity} liquidity -* @param {boolean} rounding_up -* @returns {TokenAmount} -*/ -export function getDeltaX(sqrt_price_a: SqrtPrice, sqrt_price_b: SqrtPrice, liquidity: Liquidity, rounding_up: boolean): TokenAmount; -/** -* @param {SqrtPrice} sqrt_price_a -* @param {SqrtPrice} sqrt_price_b -* @param {Liquidity} liquidity -* @param {boolean} rounding_up -* @returns {TokenAmount} -*/ -export function getDeltaY(sqrt_price_a: SqrtPrice, sqrt_price_b: SqrtPrice, liquidity: Liquidity, rounding_up: boolean): TokenAmount; -/** -* @param {SqrtPrice} starting_sqrt_price -* @param {Liquidity} liquidity -* @param {TokenAmount} amount -* @param {boolean} x_to_y -* @returns {SqrtPrice} -*/ -export function getNextSqrtPriceFromInput(starting_sqrt_price: SqrtPrice, liquidity: Liquidity, amount: TokenAmount, x_to_y: boolean): SqrtPrice; -/** -* @param {SqrtPrice} starting_sqrt_price -* @param {Liquidity} liquidity -* @param {TokenAmount} amount -* @param {boolean} x_to_y -* @returns {SqrtPrice} -*/ -export function getNextSqrtPriceFromOutput(starting_sqrt_price: SqrtPrice, liquidity: Liquidity, amount: TokenAmount, x_to_y: boolean): SqrtPrice; -/** -* @param {SqrtPrice} starting_sqrt_price -* @param {Liquidity} liquidity -* @param {TokenAmount} x -* @param {boolean} add_x -* @returns {SqrtPrice} -*/ -export function getNextSqrtPriceXUp(starting_sqrt_price: SqrtPrice, liquidity: Liquidity, x: TokenAmount, add_x: boolean): SqrtPrice; -/** -* @param {SqrtPrice} starting_sqrt_price -* @param {Liquidity} liquidity -* @param {TokenAmount} y -* @param {boolean} add_y -* @returns {SqrtPrice} -*/ -export function getNextSqrtPriceYDown(starting_sqrt_price: SqrtPrice, liquidity: Liquidity, y: TokenAmount, add_y: boolean): SqrtPrice; -/** -* @param {number} current_tick_index -* @param {SqrtPrice} current_sqrt_price -* @param {Liquidity} liquidity_delta -* @param {boolean} liquidity_sign -* @param {number} upper_tick -* @param {number} lower_tick -* @returns {AmountDeltaResult} -*/ -export function calculateAmountDelta(current_tick_index: number, current_sqrt_price: SqrtPrice, liquidity_delta: Liquidity, liquidity_sign: boolean, upper_tick: number, lower_tick: number): AmountDeltaResult; -/** -* @param {TokenAmount} amount -* @param {SqrtPrice} starting_sqrt_price -* @param {Liquidity} liquidity -* @param {Percentage} fee -* @param {boolean} by_amount_in -* @param {boolean} x_to_y -* @returns {boolean} -*/ -export function isEnoughAmountToChangePrice(amount: TokenAmount, starting_sqrt_price: SqrtPrice, liquidity: Liquidity, fee: Percentage, by_amount_in: boolean, x_to_y: boolean): boolean; -/** -* @param {number} tick_spacing -* @returns {Liquidity} -*/ -export function calculateMaxLiquidityPerTick(tick_spacing: number): Liquidity; -/** -* @param {number} tick_lower -* @param {number} tick_upper -* @param {number} tick_spacing -*/ -export function checkTicks(tick_lower: number, tick_upper: number, tick_spacing: number): void; -/** -* @param {number} tick_index -* @param {number} tick_spacing -*/ -export function checkTick(tick_index: number, tick_spacing: number): void; -/** -* @param {TokenAmount} expected_amount_out -* @param {Percentage} slippage -* @returns {TokenAmount} -*/ -export function calculateMinAmountOut(expected_amount_out: TokenAmount, slippage: Percentage): TokenAmount; -/** -* @param {number} tick -* @param {number} tick_spacing -* @returns {PositionResult} -*/ -export function tickToPositionJs(tick: number, tick_spacing: number): PositionResult; -/** -* @param {number} chunk -* @param {number} bit -* @param {number} tick_spacing -* @returns {number} -*/ -export function positionToTick(chunk: number, bit: number, tick_spacing: number): number; -/** -* @returns {bigint} -*/ -export function getGlobalMaxSqrtPrice(): bigint; -/** -* @returns {bigint} -*/ -export function getGlobalMinSqrtPrice(): bigint; -/** -* @returns {number} -*/ -export function getTickSearchRange(): number; -/** -* @param {number} tick_spacing -* @returns {number} -*/ -export function getMaxChunk(tick_spacing: number): number; -/** -* @returns {number} -*/ -export function getChunkSize(): number; -/** -* @returns {number} -*/ -export function getMaxTickCross(): number; -/** -* @returns {number} -*/ -export function getMaxTickmapQuerySize(): number; -/** -* @returns {number} -*/ -export function getLiquidityTicksLimit(): number; -/** -* @returns {number} -*/ -export function getMaxPoolKeysReturned(): number; -/** -* @returns {number} -*/ -export function getMaxPoolPairsReturned(): number; -/** -* @param {number} lower_tick_index -* @param {FeeGrowth} lower_tick_fee_growth_outside_x -* @param {FeeGrowth} lower_tick_fee_growth_outside_y -* @param {number} upper_tick_index -* @param {FeeGrowth} upper_tick_fee_growth_outside_x -* @param {FeeGrowth} upper_tick_fee_growth_outside_y -* @param {number} pool_current_tick_index -* @param {FeeGrowth} pool_fee_growth_global_x -* @param {FeeGrowth} pool_fee_growth_global_y -* @param {FeeGrowth} position_fee_growth_inside_x -* @param {FeeGrowth} position_fee_growth_inside_y -* @param {Liquidity} position_liquidity -* @returns {TokenAmounts} -*/ -export function calculateFee(lower_tick_index: number, lower_tick_fee_growth_outside_x: FeeGrowth, lower_tick_fee_growth_outside_y: FeeGrowth, upper_tick_index: number, upper_tick_fee_growth_outside_x: FeeGrowth, upper_tick_fee_growth_outside_y: FeeGrowth, pool_current_tick_index: number, pool_fee_growth_global_x: FeeGrowth, pool_fee_growth_global_y: FeeGrowth, position_fee_growth_inside_x: FeeGrowth, position_fee_growth_inside_y: FeeGrowth, position_liquidity: Liquidity): TokenAmounts; -/** -* @param {string} token_candidate -* @param {string} token_to_compare -* @returns {boolean} -*/ -export function isTokenX(token_candidate: string, token_to_compare: string): boolean; -/** -* @param {number} tick_index -* @param {number} tick_spacing -* @param {SqrtPrice} sqrt_price -* @returns {boolean} -*/ -export function checkTickToSqrtPriceRelationship(tick_index: number, tick_spacing: number, sqrt_price: SqrtPrice): boolean; -/** -* @param {number} accurate_tick -* @param {number} tick_spacing -* @returns {number} -*/ -export function alignTickToSpacing(accurate_tick: number, tick_spacing: number): number; -/** -* @param {SqrtPrice} sqrt_price -* @param {number} tick_spacing -* @returns {number} -*/ -export function getTickAtSqrtPrice(sqrt_price: SqrtPrice, tick_spacing: number): number; -/** -* @param {TokenAmount} x -* @param {number} lower_tick -* @param {number} upper_tick -* @param {SqrtPrice} current_sqrt_price -* @param {boolean} rounding_up -* @returns {SingleTokenLiquidity} -*/ -export function getLiquidityByX(x: TokenAmount, lower_tick: number, upper_tick: number, current_sqrt_price: SqrtPrice, rounding_up: boolean): SingleTokenLiquidity; -/** -* @param {TokenAmount} y -* @param {number} lower_tick -* @param {number} upper_tick -* @param {SqrtPrice} current_sqrt_price -* @param {boolean} rounding_up -* @returns {SingleTokenLiquidity} -*/ -export function getLiquidityByY(y: TokenAmount, lower_tick: number, upper_tick: number, current_sqrt_price: SqrtPrice, rounding_up: boolean): SingleTokenLiquidity; -/** -* @param {Percentage} fee -* @param {number} tick_spacing -* @returns {FeeTier} -*/ -export function newFeeTier(fee: Percentage, tick_spacing: number): FeeTier; -/** -* @param {string} token_0 -* @param {string} token_1 -* @param {FeeTier} fee_tier -* @returns {PoolKey} -*/ -export function newPoolKey(token_0: string, token_1: string, fee_tier: FeeTier): PoolKey; -/** -* @param {Tickmap} tickmap -* @param {FeeTier} fee_tier -* @param {Pool} pool -* @param {LiquidityTickVec} ticks -* @param {boolean} x_to_y -* @param {TokenAmount} amount -* @param {boolean} by_amount_in -* @param {SqrtPrice} sqrt_price_limit -* @returns {CalculateSwapResult} -*/ -export function simulateSwap(tickmap: Tickmap, fee_tier: FeeTier, pool: Pool, ticks: LiquidityTickVec, x_to_y: boolean, amount: TokenAmount, by_amount_in: boolean, sqrt_price_limit: SqrtPrice): CalculateSwapResult; -/** -* @returns {bigint} -*/ -export function getFeeGrowthScale(): bigint; -/** -* @returns {bigint} -*/ -export function getFeeGrowthDenominator(): bigint; -/** -* @param {bigint} integer -* @param {number | undefined} [scale] -* @returns {bigint} -*/ -export function toFeeGrowth(integer: bigint, scale?: number): bigint; -/** -* @returns {bigint} -*/ -export function getFixedPointScale(): bigint; -/** -* @returns {bigint} -*/ -export function getFixedPointDenominator(): bigint; -/** -* @param {bigint} integer -* @param {number | undefined} [scale] -* @returns {bigint} -*/ -export function toFixedPoint(integer: bigint, scale?: number): bigint; -/** -* @returns {bigint} -*/ -export function getLiquidityScale(): bigint; -/** -* @returns {bigint} -*/ -export function getLiquidityDenominator(): bigint; -/** -* @param {bigint} integer -* @param {number | undefined} [scale] -* @returns {bigint} -*/ -export function toLiquidity(integer: bigint, scale?: number): bigint; -/** -* @returns {bigint} -*/ -export function getPercentageScale(): bigint; -/** -* @returns {bigint} -*/ -export function getPercentageDenominator(): bigint; -/** -* @param {bigint} integer -* @param {number | undefined} [scale] -* @returns {bigint} -*/ -export function toPercentage(integer: bigint, scale?: number): bigint; -/** -* @returns {bigint} -*/ -export function getPriceScale(): bigint; -/** -* @returns {bigint} -*/ -export function getPriceDenominator(): bigint; -/** -* @param {bigint} integer -* @param {number | undefined} [scale] -* @returns {bigint} -*/ -export function toPrice(integer: bigint, scale?: number): bigint; -/** -* @returns {bigint} -*/ -export function getSecondsPerLiquidityScale(): bigint; -/** -* @returns {bigint} -*/ -export function getSecondsPerLiquidityDenominator(): bigint; -/** -* @param {bigint} integer -* @param {number | undefined} [scale] -* @returns {bigint} -*/ -export function toSecondsPerLiquidity(integer: bigint, scale?: number): bigint; -/** -* @returns {bigint} -*/ -export function getSqrtPriceScale(): bigint; -/** -* @returns {bigint} -*/ -export function getSqrtPriceDenominator(): bigint; -/** -* @param {bigint} integer -* @param {number | undefined} [scale] -* @returns {bigint} -*/ -export function toSqrtPrice(integer: bigint, scale?: number): bigint; -/** -* @param {number} tick_index -* @returns {SqrtPrice} -*/ -export function calculateSqrtPrice(tick_index: number): SqrtPrice; -/** -* @param {number} tick_spacing -* @returns {number} -*/ -export function getMaxTick(tick_spacing: number): number; -/** -* @param {number} tick_spacing -* @returns {number} -*/ -export function getMinTick(tick_spacing: number): number; -/** -* @param {number} tick_spacing -* @returns {SqrtPrice} -*/ -export function getMaxSqrtPrice(tick_spacing: number): SqrtPrice; -/** -* @param {number} tick_spacing -* @returns {SqrtPrice} -*/ -export function getMinSqrtPrice(tick_spacing: number): SqrtPrice; -/** -* @returns {bigint} -*/ -export function getTokenAmountScale(): bigint; -/** -* @returns {bigint} -*/ -export function getTokenAmountDenominator(): bigint; -/** -* @param {bigint} integer -* @param {number | undefined} [scale] -* @returns {bigint} -*/ -export function toTokenAmount(integer: bigint, scale?: number): bigint; -/** -*/ -export enum SwapError { - NotAdmin = 0, - NotFeeReceiver = 1, - PoolAlreadyExist = 2, - PoolNotFound = 3, - TickAlreadyExist = 4, - InvalidTickIndexOrTickSpacing = 5, - PositionNotFound = 6, - TickNotFound = 7, - FeeTierNotFound = 8, - PoolKeyNotFound = 9, - AmountIsZero = 10, - WrongLimit = 11, - PriceLimitReached = 12, - NoGainSwap = 13, - InvalidTickSpacing = 14, - FeeTierAlreadyExist = 15, - PoolKeyAlreadyExist = 16, - UnauthorizedFeeReceiver = 17, - ZeroLiquidity = 18, - TransferError = 19, - TokensAreSame = 20, - AmountUnderMinimumAmountOut = 21, - InvalidFee = 22, - NotEmptyTickDeinitialization = 23, - InvalidInitTick = 24, - InvalidInitSqrtPrice = 25, - TickLimitReached = 26, - NoRouteFound = 27, - MaxTicksCrossed = 28, - StateOutdated = 29, - InsufficientLiquidity = 30, -} -export interface AmountDeltaResult { - x: TokenAmount; - y: TokenAmount; - update_liquidity: boolean; -} - -export interface SwapResult { - next_sqrt_price: SqrtPrice; - amount_in: TokenAmount; - amount_out: TokenAmount; - fee_amount: TokenAmount; -} - -export interface Tickmap { - bitmap: Map; -} - -export interface PositionResult { - chunk: number; - bit: number; -} - -export interface SwapHop { - pool_key: PoolKey; - x_to_y: boolean; -} - -export interface QuoteResult { - amount_in: TokenAmount; - amount_out: TokenAmount; - target_sqrt_price: SqrtPrice; - ticks: Tick[]; -} - -export interface TokenAmounts { - x: TokenAmount; - y: TokenAmount; -} - -export interface SingleTokenLiquidity { - l: Liquidity; - amount: TokenAmount; -} - -export interface Config { - admin: string; - protocol_fee: Percentage; -} - -export interface FeeTier { - fee: Percentage; - tick_spacing: number; -} - -export interface Pool { - liquidity: Liquidity; - sqrt_price: SqrtPrice; - current_tick_index: number; - fee_growth_global_x: FeeGrowth; - fee_growth_global_y: FeeGrowth; - fee_protocol_token_x: TokenAmount; - fee_protocol_token_y: TokenAmount; - start_timestamp: number; - last_timestamp: number; - fee_receiver: string; -} - -export interface PoolKey { - token_x: string; - token_y: string; - fee_tier: FeeTier; -} - -export interface Position { - pool_key: PoolKey; - liquidity: Liquidity; - lower_tick_index: number; - upper_tick_index: number; - fee_growth_inside_x: FeeGrowth; - fee_growth_inside_y: FeeGrowth; - last_block_number: number; - tokens_owed_x: TokenAmount; - tokens_owed_y: TokenAmount; -} - -export interface Tick { - index: number; - sign: boolean; - liquidity_change: Liquidity; - liquidity_gross: Liquidity; - sqrt_price: SqrtPrice; - fee_growth_outside_x: FeeGrowth; - fee_growth_outside_y: FeeGrowth; - seconds_outside: number; -} - -export interface PositionTick { - index: number; - fee_growth_outside_x: FeeGrowth; - fee_growth_outside_y: FeeGrowth; - seconds_outside: number; -} - -export interface LiquidityTick { - index: number; - liquidity_change: Liquidity; - sign: boolean; -} - -export type LiquidityTickVec = LiquidityTick[]; - -export type FeeGrowth = bigint; - -export type FixedPoint = bigint; - -export type Liquidity = bigint; - -export type Percentage = number; - -export type Price = bigint; - -export type SecondsPerLiquidity = bigint; - -export type SqrtPrice = bigint; - -export type TokenAmount = bigint; - -export interface CalculateSwapResult { - amount_in: TokenAmount; - amount_out: TokenAmount; - fee: TokenAmount; - start_sqrt_price: SqrtPrice; - target_sqrt_price: SqrtPrice; - crossed_ticks: LiquidityTick[]; - global_insufficient_liquidity: boolean; - state_outdated: boolean; - max_ticks_crossed: boolean; -} - - -export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; - -export interface InitOutput { - readonly memory: WebAssembly.Memory; - readonly computeSwapStep: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void; - readonly getDeltaX: (a: number, b: number, c: number, d: number, e: number) => void; - readonly getDeltaY: (a: number, b: number, c: number, d: number, e: number) => void; - readonly getNextSqrtPriceFromInput: (a: number, b: number, c: number, d: number, e: number) => void; - readonly getNextSqrtPriceFromOutput: (a: number, b: number, c: number, d: number, e: number) => void; - readonly getNextSqrtPriceXUp: (a: number, b: number, c: number, d: number, e: number) => void; - readonly getNextSqrtPriceYDown: (a: number, b: number, c: number, d: number, e: number) => void; - readonly calculateAmountDelta: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void; - readonly isEnoughAmountToChangePrice: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void; - readonly calculateMaxLiquidityPerTick: (a: number) => number; - readonly checkTicks: (a: number, b: number, c: number, d: number) => void; - readonly checkTick: (a: number, b: number, c: number) => void; - readonly calculateMinAmountOut: (a: number, b: number) => number; - readonly tickToPositionJs: (a: number, b: number, c: number) => void; - readonly positionToTick: (a: number, b: number, c: number) => number; - readonly getGlobalMaxSqrtPrice: () => number; - readonly getGlobalMinSqrtPrice: () => number; - readonly getTickSearchRange: () => number; - readonly getMaxChunk: (a: number) => number; - readonly getChunkSize: () => number; - readonly getMaxTickCross: () => number; - readonly getMaxTickmapQuerySize: () => number; - readonly getLiquidityTicksLimit: () => number; - readonly getMaxPoolKeysReturned: () => number; - readonly getMaxPoolPairsReturned: () => number; - readonly calculateFee: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number) => void; - readonly isTokenX: (a: number, b: number, c: number, d: number, e: number) => void; - readonly checkTickToSqrtPriceRelationship: (a: number, b: number, c: number, d: number) => void; - readonly alignTickToSpacing: (a: number, b: number) => number; - readonly getTickAtSqrtPrice: (a: number, b: number, c: number) => void; - readonly getLiquidityByX: (a: number, b: number, c: number, d: number, e: number, f: number) => void; - readonly getLiquidityByY: (a: number, b: number, c: number, d: number, e: number, f: number) => void; - readonly newFeeTier: (a: number, b: number, c: number) => void; - readonly newPoolKey: (a: number, b: number, c: number, d: number, e: number, f: number) => void; - readonly simulateSwap: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => void; - readonly getFeeGrowthScale: () => number; - readonly getFeeGrowthDenominator: () => number; - readonly toFeeGrowth: (a: number, b: number) => number; - readonly getFixedPointScale: () => number; - readonly getFixedPointDenominator: () => number; - readonly toFixedPoint: (a: number, b: number) => number; - readonly getLiquidityScale: () => number; - readonly getLiquidityDenominator: () => number; - readonly toLiquidity: (a: number, b: number) => number; - readonly getPercentageDenominator: () => number; - readonly toPercentage: (a: number, b: number) => number; - readonly getPriceScale: () => number; - readonly getPriceDenominator: () => number; - readonly toPrice: (a: number, b: number) => number; - readonly toSecondsPerLiquidity: (a: number, b: number) => number; - readonly toSqrtPrice: (a: number, b: number) => number; - readonly calculateSqrtPrice: (a: number, b: number) => void; - readonly getMaxTick: (a: number) => number; - readonly getMinTick: (a: number) => number; - readonly getMaxSqrtPrice: (a: number) => number; - readonly getMinSqrtPrice: (a: number) => number; - readonly getTokenAmountScale: () => number; - readonly getTokenAmountDenominator: () => number; - readonly toTokenAmount: (a: number, b: number) => number; - readonly getSecondsPerLiquidityDenominator: () => number; - readonly getSqrtPriceDenominator: () => number; - readonly getPercentageScale: () => number; - readonly getSecondsPerLiquidityScale: () => number; - readonly getSqrtPriceScale: () => number; - readonly __wbindgen_malloc: (a: number, b: number) => number; - readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; - readonly __wbindgen_add_to_stack_pointer: (a: number) => number; - readonly __wbindgen_exn_store: (a: number) => void; -} - -export type SyncInitInput = BufferSource | WebAssembly.Module; -/** -* Instantiates the given `module`, which can either be bytes or -* a precompiled `WebAssembly.Module`. -* -* @param {SyncInitInput} module -* -* @returns {InitOutput} -*/ -export function initSync(module: SyncInitInput): InitOutput; - -/** -* If `module_or_path` is {RequestInfo} or {URL}, makes a request and -* for everything else, calls `WebAssembly.instantiate` directly. -* -* @param {InitInput | Promise} module_or_path -* -* @returns {Promise} -*/ -export default function __wbg_init (module_or_path?: InitInput | Promise): Promise; diff --git a/src/pages/Pool-V3/packages/wasm/oraiswap_v3_wasm.js b/src/pages/Pool-V3/packages/wasm/oraiswap_v3_wasm.js deleted file mode 100644 index d3774fdda..000000000 --- a/src/pages/Pool-V3/packages/wasm/oraiswap_v3_wasm.js +++ /dev/null @@ -1,1391 +0,0 @@ -/* eslint-disable no-undef */ -let wasm; - -const heap = new Array(128).fill(undefined); - -heap.push(undefined, null, true, false); - -function getObject(idx) { return heap[idx]; } - -let heap_next = heap.length; - -function dropObject(idx) { - if (idx < 132) return; - heap[idx] = heap_next; - heap_next = idx; -} - -function takeObject(idx) { - const ret = getObject(idx); - dropObject(idx); - return ret; -} - -const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } ); - -if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); }; - -let cachedUint8Memory0 = null; - -function getUint8Memory0() { - if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) { - cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer); - } - return cachedUint8Memory0; -} - -function getStringFromWasm0(ptr, len) { - ptr = ptr >>> 0; - return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len)); -} - -function addHeapObject(obj) { - if (heap_next === heap.length) heap.push(heap.length + 1); - const idx = heap_next; - heap_next = heap[idx]; - - heap[idx] = obj; - return idx; -} - -function isLikeNone(x) { - return x === undefined || x === null; -} - -let cachedFloat64Memory0 = null; - -function getFloat64Memory0() { - if (cachedFloat64Memory0 === null || cachedFloat64Memory0.byteLength === 0) { - cachedFloat64Memory0 = new Float64Array(wasm.memory.buffer); - } - return cachedFloat64Memory0; -} - -let cachedInt32Memory0 = null; - -function getInt32Memory0() { - if (cachedInt32Memory0 === null || cachedInt32Memory0.byteLength === 0) { - cachedInt32Memory0 = new Int32Array(wasm.memory.buffer); - } - return cachedInt32Memory0; -} - -let WASM_VECTOR_LEN = 0; - -const cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } ); - -const encodeString = (typeof cachedTextEncoder.encodeInto === 'function' - ? function (arg, view) { - return cachedTextEncoder.encodeInto(arg, view); -} - : function (arg, view) { - const buf = cachedTextEncoder.encode(arg); - view.set(buf); - return { - read: arg.length, - written: buf.length - }; -}); - -function passStringToWasm0(arg, malloc, realloc) { - - if (realloc === undefined) { - const buf = cachedTextEncoder.encode(arg); - const ptr = malloc(buf.length, 1) >>> 0; - getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf); - WASM_VECTOR_LEN = buf.length; - return ptr; - } - - let len = arg.length; - let ptr = malloc(len, 1) >>> 0; - - const mem = getUint8Memory0(); - - let offset = 0; - - for (; offset < len; offset++) { - const code = arg.charCodeAt(offset); - if (code > 0x7F) break; - mem[ptr + offset] = code; - } - - if (offset !== len) { - if (offset !== 0) { - arg = arg.slice(offset); - } - ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0; - const view = getUint8Memory0().subarray(ptr + offset, ptr + len); - const ret = encodeString(arg, view); - - offset += ret.written; - ptr = realloc(ptr, len, offset, 1) >>> 0; - } - - WASM_VECTOR_LEN = offset; - return ptr; -} - -let cachedBigInt64Memory0 = null; - -function getBigInt64Memory0() { - if (cachedBigInt64Memory0 === null || cachedBigInt64Memory0.byteLength === 0) { - cachedBigInt64Memory0 = new BigInt64Array(wasm.memory.buffer); - } - return cachedBigInt64Memory0; -} - -function debugString(val) { - // primitive types - const type = typeof val; - if (type == 'number' || type == 'boolean' || val == null) { - return `${val}`; - } - if (type == 'string') { - return `"${val}"`; - } - if (type == 'symbol') { - const description = val.description; - if (description == null) { - return 'Symbol'; - } else { - return `Symbol(${description})`; - } - } - if (type == 'function') { - const name = val.name; - if (typeof name == 'string' && name.length > 0) { - return `Function(${name})`; - } else { - return 'Function'; - } - } - // objects - if (Array.isArray(val)) { - const length = val.length; - let debug = '['; - if (length > 0) { - debug += debugString(val[0]); - } - for(let i = 1; i < length; i++) { - debug += ', ' + debugString(val[i]); - } - debug += ']'; - return debug; - } - // Test for built-in - const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val)); - let className; - if (builtInMatches.length > 1) { - className = builtInMatches[1]; - } else { - // Failed to match the standard '[object ClassName]' - return toString.call(val); - } - if (className == 'Object') { - // we're a user defined class or Object - // JSON.stringify avoids problems with cycles, and is generally much - // easier than looping through ownProperties of `val`. - try { - return 'Object(' + JSON.stringify(val) + ')'; - } catch (_) { - return 'Object'; - } - } - // errors - if (val instanceof Error) { - return `${val.name}: ${val.message}\n${val.stack}`; - } - // TODO we could test for more things here, like `Set`s and `Map`s. - return className; -} -/** -* @param {SqrtPrice} current_sqrt_price -* @param {SqrtPrice} target_sqrt_price -* @param {Liquidity} liquidity -* @param {TokenAmount} amount -* @param {boolean} by_amount_in -* @param {Percentage} fee -* @returns {SwapResult} -*/ -export function computeSwapStep(current_sqrt_price, target_sqrt_price, liquidity, amount, by_amount_in, fee) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.computeSwapStep(retptr, addHeapObject(current_sqrt_price), addHeapObject(target_sqrt_price), addHeapObject(liquidity), addHeapObject(amount), by_amount_in, addHeapObject(fee)); - var r0 = getInt32Memory0()[retptr / 4 + 0]; - var r1 = getInt32Memory0()[retptr / 4 + 1]; - var r2 = getInt32Memory0()[retptr / 4 + 2]; - if (r2) { - throw takeObject(r1); - } - return takeObject(r0); - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } -} - -/** -* @param {SqrtPrice} sqrt_price_a -* @param {SqrtPrice} sqrt_price_b -* @param {Liquidity} liquidity -* @param {boolean} rounding_up -* @returns {TokenAmount} -*/ -export function getDeltaX(sqrt_price_a, sqrt_price_b, liquidity, rounding_up) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.getDeltaX(retptr, addHeapObject(sqrt_price_a), addHeapObject(sqrt_price_b), addHeapObject(liquidity), rounding_up); - var r0 = getInt32Memory0()[retptr / 4 + 0]; - var r1 = getInt32Memory0()[retptr / 4 + 1]; - var r2 = getInt32Memory0()[retptr / 4 + 2]; - if (r2) { - throw takeObject(r1); - } - return takeObject(r0); - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } -} - -/** -* @param {SqrtPrice} sqrt_price_a -* @param {SqrtPrice} sqrt_price_b -* @param {Liquidity} liquidity -* @param {boolean} rounding_up -* @returns {TokenAmount} -*/ -export function getDeltaY(sqrt_price_a, sqrt_price_b, liquidity, rounding_up) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.getDeltaY(retptr, addHeapObject(sqrt_price_a), addHeapObject(sqrt_price_b), addHeapObject(liquidity), rounding_up); - var r0 = getInt32Memory0()[retptr / 4 + 0]; - var r1 = getInt32Memory0()[retptr / 4 + 1]; - var r2 = getInt32Memory0()[retptr / 4 + 2]; - if (r2) { - throw takeObject(r1); - } - return takeObject(r0); - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } -} - -/** -* @param {SqrtPrice} starting_sqrt_price -* @param {Liquidity} liquidity -* @param {TokenAmount} amount -* @param {boolean} x_to_y -* @returns {SqrtPrice} -*/ -export function getNextSqrtPriceFromInput(starting_sqrt_price, liquidity, amount, x_to_y) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.getNextSqrtPriceFromInput(retptr, addHeapObject(starting_sqrt_price), addHeapObject(liquidity), addHeapObject(amount), x_to_y); - var r0 = getInt32Memory0()[retptr / 4 + 0]; - var r1 = getInt32Memory0()[retptr / 4 + 1]; - var r2 = getInt32Memory0()[retptr / 4 + 2]; - if (r2) { - throw takeObject(r1); - } - return takeObject(r0); - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } -} - -/** -* @param {SqrtPrice} starting_sqrt_price -* @param {Liquidity} liquidity -* @param {TokenAmount} amount -* @param {boolean} x_to_y -* @returns {SqrtPrice} -*/ -export function getNextSqrtPriceFromOutput(starting_sqrt_price, liquidity, amount, x_to_y) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.getNextSqrtPriceFromOutput(retptr, addHeapObject(starting_sqrt_price), addHeapObject(liquidity), addHeapObject(amount), x_to_y); - var r0 = getInt32Memory0()[retptr / 4 + 0]; - var r1 = getInt32Memory0()[retptr / 4 + 1]; - var r2 = getInt32Memory0()[retptr / 4 + 2]; - if (r2) { - throw takeObject(r1); - } - return takeObject(r0); - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } -} - -/** -* @param {SqrtPrice} starting_sqrt_price -* @param {Liquidity} liquidity -* @param {TokenAmount} x -* @param {boolean} add_x -* @returns {SqrtPrice} -*/ -export function getNextSqrtPriceXUp(starting_sqrt_price, liquidity, x, add_x) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.getNextSqrtPriceXUp(retptr, addHeapObject(starting_sqrt_price), addHeapObject(liquidity), addHeapObject(x), add_x); - var r0 = getInt32Memory0()[retptr / 4 + 0]; - var r1 = getInt32Memory0()[retptr / 4 + 1]; - var r2 = getInt32Memory0()[retptr / 4 + 2]; - if (r2) { - throw takeObject(r1); - } - return takeObject(r0); - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } -} - -/** -* @param {SqrtPrice} starting_sqrt_price -* @param {Liquidity} liquidity -* @param {TokenAmount} y -* @param {boolean} add_y -* @returns {SqrtPrice} -*/ -export function getNextSqrtPriceYDown(starting_sqrt_price, liquidity, y, add_y) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.getNextSqrtPriceYDown(retptr, addHeapObject(starting_sqrt_price), addHeapObject(liquidity), addHeapObject(y), add_y); - var r0 = getInt32Memory0()[retptr / 4 + 0]; - var r1 = getInt32Memory0()[retptr / 4 + 1]; - var r2 = getInt32Memory0()[retptr / 4 + 2]; - if (r2) { - throw takeObject(r1); - } - return takeObject(r0); - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } -} - -/** -* @param {number} current_tick_index -* @param {SqrtPrice} current_sqrt_price -* @param {Liquidity} liquidity_delta -* @param {boolean} liquidity_sign -* @param {number} upper_tick -* @param {number} lower_tick -* @returns {AmountDeltaResult} -*/ -export function calculateAmountDelta(current_tick_index, current_sqrt_price, liquidity_delta, liquidity_sign, upper_tick, lower_tick) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.calculateAmountDelta(retptr, current_tick_index, addHeapObject(current_sqrt_price), addHeapObject(liquidity_delta), liquidity_sign, upper_tick, lower_tick); - var r0 = getInt32Memory0()[retptr / 4 + 0]; - var r1 = getInt32Memory0()[retptr / 4 + 1]; - var r2 = getInt32Memory0()[retptr / 4 + 2]; - if (r2) { - throw takeObject(r1); - } - return takeObject(r0); - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } -} - -/** -* @param {TokenAmount} amount -* @param {SqrtPrice} starting_sqrt_price -* @param {Liquidity} liquidity -* @param {Percentage} fee -* @param {boolean} by_amount_in -* @param {boolean} x_to_y -* @returns {boolean} -*/ -export function isEnoughAmountToChangePrice(amount, starting_sqrt_price, liquidity, fee, by_amount_in, x_to_y) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.isEnoughAmountToChangePrice(retptr, addHeapObject(amount), addHeapObject(starting_sqrt_price), addHeapObject(liquidity), addHeapObject(fee), by_amount_in, x_to_y); - var r0 = getInt32Memory0()[retptr / 4 + 0]; - var r1 = getInt32Memory0()[retptr / 4 + 1]; - var r2 = getInt32Memory0()[retptr / 4 + 2]; - if (r2) { - throw takeObject(r1); - } - return r0 !== 0; - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } -} - -/** -* @param {number} tick_spacing -* @returns {Liquidity} -*/ -export function calculateMaxLiquidityPerTick(tick_spacing) { - const ret = wasm.calculateMaxLiquidityPerTick(tick_spacing); - return takeObject(ret); -} - -/** -* @param {number} tick_lower -* @param {number} tick_upper -* @param {number} tick_spacing -*/ -export function checkTicks(tick_lower, tick_upper, tick_spacing) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.checkTicks(retptr, tick_lower, tick_upper, tick_spacing); - var r0 = getInt32Memory0()[retptr / 4 + 0]; - var r1 = getInt32Memory0()[retptr / 4 + 1]; - if (r1) { - throw takeObject(r0); - } - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } -} - -/** -* @param {number} tick_index -* @param {number} tick_spacing -*/ -export function checkTick(tick_index, tick_spacing) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.checkTick(retptr, tick_index, tick_spacing); - var r0 = getInt32Memory0()[retptr / 4 + 0]; - var r1 = getInt32Memory0()[retptr / 4 + 1]; - if (r1) { - throw takeObject(r0); - } - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } -} - -/** -* @param {TokenAmount} expected_amount_out -* @param {Percentage} slippage -* @returns {TokenAmount} -*/ -export function calculateMinAmountOut(expected_amount_out, slippage) { - const ret = wasm.calculateMinAmountOut(addHeapObject(expected_amount_out), addHeapObject(slippage)); - return takeObject(ret); -} - -/** -* @param {number} tick -* @param {number} tick_spacing -* @returns {PositionResult} -*/ -export function tickToPositionJs(tick, tick_spacing) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.tickToPositionJs(retptr, tick, tick_spacing); - var r0 = getInt32Memory0()[retptr / 4 + 0]; - var r1 = getInt32Memory0()[retptr / 4 + 1]; - var r2 = getInt32Memory0()[retptr / 4 + 2]; - if (r2) { - throw takeObject(r1); - } - return takeObject(r0); - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } -} - -/** -* @param {number} chunk -* @param {number} bit -* @param {number} tick_spacing -* @returns {number} -*/ -export function positionToTick(chunk, bit, tick_spacing) { - const ret = wasm.positionToTick(chunk, bit, tick_spacing); - return ret; -} - -/** -* @returns {bigint} -*/ -export function getGlobalMaxSqrtPrice() { - const ret = wasm.getGlobalMaxSqrtPrice(); - return takeObject(ret); -} - -/** -* @returns {bigint} -*/ -export function getGlobalMinSqrtPrice() { - const ret = wasm.getGlobalMinSqrtPrice(); - return takeObject(ret); -} - -/** -* @returns {number} -*/ -export function getTickSearchRange() { - const ret = wasm.getTickSearchRange(); - return ret; -} - -/** -* @param {number} tick_spacing -* @returns {number} -*/ -export function getMaxChunk(tick_spacing) { - const ret = wasm.getMaxChunk(tick_spacing); - return ret; -} - -/** -* @returns {number} -*/ -export function getChunkSize() { - const ret = wasm.getChunkSize(); - return ret; -} - -/** -* @returns {number} -*/ -export function getMaxTickCross() { - const ret = wasm.getMaxTickCross(); - return ret; -} - -/** -* @returns {number} -*/ -export function getMaxTickmapQuerySize() { - const ret = wasm.getMaxTickmapQuerySize(); - return ret >>> 0; -} - -/** -* @returns {number} -*/ -export function getLiquidityTicksLimit() { - const ret = wasm.getLiquidityTicksLimit(); - return ret >>> 0; -} - -/** -* @returns {number} -*/ -export function getMaxPoolKeysReturned() { - const ret = wasm.getMaxPoolKeysReturned(); - return ret; -} - -/** -* @returns {number} -*/ -export function getMaxPoolPairsReturned() { - const ret = wasm.getMaxPoolPairsReturned(); - return ret >>> 0; -} - -/** -* @param {number} lower_tick_index -* @param {FeeGrowth} lower_tick_fee_growth_outside_x -* @param {FeeGrowth} lower_tick_fee_growth_outside_y -* @param {number} upper_tick_index -* @param {FeeGrowth} upper_tick_fee_growth_outside_x -* @param {FeeGrowth} upper_tick_fee_growth_outside_y -* @param {number} pool_current_tick_index -* @param {FeeGrowth} pool_fee_growth_global_x -* @param {FeeGrowth} pool_fee_growth_global_y -* @param {FeeGrowth} position_fee_growth_inside_x -* @param {FeeGrowth} position_fee_growth_inside_y -* @param {Liquidity} position_liquidity -* @returns {TokenAmounts} -*/ -export function calculateFee(lower_tick_index, lower_tick_fee_growth_outside_x, lower_tick_fee_growth_outside_y, upper_tick_index, upper_tick_fee_growth_outside_x, upper_tick_fee_growth_outside_y, pool_current_tick_index, pool_fee_growth_global_x, pool_fee_growth_global_y, position_fee_growth_inside_x, position_fee_growth_inside_y, position_liquidity) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.calculateFee(retptr, lower_tick_index, addHeapObject(lower_tick_fee_growth_outside_x), addHeapObject(lower_tick_fee_growth_outside_y), upper_tick_index, addHeapObject(upper_tick_fee_growth_outside_x), addHeapObject(upper_tick_fee_growth_outside_y), pool_current_tick_index, addHeapObject(pool_fee_growth_global_x), addHeapObject(pool_fee_growth_global_y), addHeapObject(position_fee_growth_inside_x), addHeapObject(position_fee_growth_inside_y), addHeapObject(position_liquidity)); - var r0 = getInt32Memory0()[retptr / 4 + 0]; - var r1 = getInt32Memory0()[retptr / 4 + 1]; - var r2 = getInt32Memory0()[retptr / 4 + 2]; - if (r2) { - throw takeObject(r1); - } - return takeObject(r0); - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } -} - -/** -* @param {string} token_candidate -* @param {string} token_to_compare -* @returns {boolean} -*/ -export function isTokenX(token_candidate, token_to_compare) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - const ptr0 = passStringToWasm0(token_candidate, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - const len0 = WASM_VECTOR_LEN; - const ptr1 = passStringToWasm0(token_to_compare, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - const len1 = WASM_VECTOR_LEN; - wasm.isTokenX(retptr, ptr0, len0, ptr1, len1); - var r0 = getInt32Memory0()[retptr / 4 + 0]; - var r1 = getInt32Memory0()[retptr / 4 + 1]; - var r2 = getInt32Memory0()[retptr / 4 + 2]; - if (r2) { - throw takeObject(r1); - } - return r0 !== 0; - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } -} - -/** -* @param {number} tick_index -* @param {number} tick_spacing -* @param {SqrtPrice} sqrt_price -* @returns {boolean} -*/ -export function checkTickToSqrtPriceRelationship(tick_index, tick_spacing, sqrt_price) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.checkTickToSqrtPriceRelationship(retptr, tick_index, tick_spacing, addHeapObject(sqrt_price)); - var r0 = getInt32Memory0()[retptr / 4 + 0]; - var r1 = getInt32Memory0()[retptr / 4 + 1]; - var r2 = getInt32Memory0()[retptr / 4 + 2]; - if (r2) { - throw takeObject(r1); - } - return r0 !== 0; - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } -} - -/** -* @param {number} accurate_tick -* @param {number} tick_spacing -* @returns {number} -*/ -export function alignTickToSpacing(accurate_tick, tick_spacing) { - const ret = wasm.alignTickToSpacing(accurate_tick, tick_spacing); - return ret; -} - -/** -* @param {SqrtPrice} sqrt_price -* @param {number} tick_spacing -* @returns {number} -*/ -export function getTickAtSqrtPrice(sqrt_price, tick_spacing) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.getTickAtSqrtPrice(retptr, addHeapObject(sqrt_price), tick_spacing); - var r0 = getInt32Memory0()[retptr / 4 + 0]; - var r1 = getInt32Memory0()[retptr / 4 + 1]; - var r2 = getInt32Memory0()[retptr / 4 + 2]; - if (r2) { - throw takeObject(r1); - } - return r0; - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } -} - -/** -* @param {TokenAmount} x -* @param {number} lower_tick -* @param {number} upper_tick -* @param {SqrtPrice} current_sqrt_price -* @param {boolean} rounding_up -* @returns {SingleTokenLiquidity} -*/ -export function getLiquidityByX(x, lower_tick, upper_tick, current_sqrt_price, rounding_up) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.getLiquidityByX(retptr, addHeapObject(x), lower_tick, upper_tick, addHeapObject(current_sqrt_price), rounding_up); - var r0 = getInt32Memory0()[retptr / 4 + 0]; - var r1 = getInt32Memory0()[retptr / 4 + 1]; - var r2 = getInt32Memory0()[retptr / 4 + 2]; - if (r2) { - throw takeObject(r1); - } - return takeObject(r0); - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } -} - -/** -* @param {TokenAmount} y -* @param {number} lower_tick -* @param {number} upper_tick -* @param {SqrtPrice} current_sqrt_price -* @param {boolean} rounding_up -* @returns {SingleTokenLiquidity} -*/ -export function getLiquidityByY(y, lower_tick, upper_tick, current_sqrt_price, rounding_up) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.getLiquidityByY(retptr, addHeapObject(y), lower_tick, upper_tick, addHeapObject(current_sqrt_price), rounding_up); - var r0 = getInt32Memory0()[retptr / 4 + 0]; - var r1 = getInt32Memory0()[retptr / 4 + 1]; - var r2 = getInt32Memory0()[retptr / 4 + 2]; - if (r2) { - throw takeObject(r1); - } - return takeObject(r0); - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } -} - -/** -* @param {Percentage} fee -* @param {number} tick_spacing -* @returns {FeeTier} -*/ -export function newFeeTier(fee, tick_spacing) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.newFeeTier(retptr, addHeapObject(fee), tick_spacing); - var r0 = getInt32Memory0()[retptr / 4 + 0]; - var r1 = getInt32Memory0()[retptr / 4 + 1]; - var r2 = getInt32Memory0()[retptr / 4 + 2]; - if (r2) { - throw takeObject(r1); - } - return takeObject(r0); - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } -} - -/** -* @param {string} token_0 -* @param {string} token_1 -* @param {FeeTier} fee_tier -* @returns {PoolKey} -*/ -export function newPoolKey(token_0, token_1, fee_tier) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - const ptr0 = passStringToWasm0(token_0, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - const len0 = WASM_VECTOR_LEN; - const ptr1 = passStringToWasm0(token_1, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - const len1 = WASM_VECTOR_LEN; - wasm.newPoolKey(retptr, ptr0, len0, ptr1, len1, addHeapObject(fee_tier)); - var r0 = getInt32Memory0()[retptr / 4 + 0]; - var r1 = getInt32Memory0()[retptr / 4 + 1]; - var r2 = getInt32Memory0()[retptr / 4 + 2]; - if (r2) { - throw takeObject(r1); - } - return takeObject(r0); - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } -} - -/** -* @param {Tickmap} tickmap -* @param {FeeTier} fee_tier -* @param {Pool} pool -* @param {LiquidityTickVec} ticks -* @param {boolean} x_to_y -* @param {TokenAmount} amount -* @param {boolean} by_amount_in -* @param {SqrtPrice} sqrt_price_limit -* @returns {CalculateSwapResult} -*/ -export function simulateSwap(tickmap, fee_tier, pool, ticks, x_to_y, amount, by_amount_in, sqrt_price_limit) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.simulateSwap(retptr, addHeapObject(tickmap), addHeapObject(fee_tier), addHeapObject(pool), addHeapObject(ticks), x_to_y, addHeapObject(amount), by_amount_in, addHeapObject(sqrt_price_limit)); - var r0 = getInt32Memory0()[retptr / 4 + 0]; - var r1 = getInt32Memory0()[retptr / 4 + 1]; - var r2 = getInt32Memory0()[retptr / 4 + 2]; - if (r2) { - throw takeObject(r1); - } - return takeObject(r0); - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } -} - -/** -* @returns {bigint} -*/ -export function getFeeGrowthScale() { - const ret = wasm.getFeeGrowthScale(); - return takeObject(ret); -} - -/** -* @returns {bigint} -*/ -export function getFeeGrowthDenominator() { - const ret = wasm.getFeeGrowthDenominator(); - return takeObject(ret); -} - -/** -* @param {bigint} integer -* @param {number | undefined} [scale] -* @returns {bigint} -*/ -export function toFeeGrowth(integer, scale) { - const ret = wasm.toFeeGrowth(integer, isLikeNone(scale) ? 0xFFFFFF : scale); - return takeObject(ret); -} - -/** -* @returns {bigint} -*/ -export function getFixedPointScale() { - const ret = wasm.getFixedPointScale(); - return takeObject(ret); -} - -/** -* @returns {bigint} -*/ -export function getFixedPointDenominator() { - const ret = wasm.getFixedPointDenominator(); - return takeObject(ret); -} - -/** -* @param {bigint} integer -* @param {number | undefined} [scale] -* @returns {bigint} -*/ -export function toFixedPoint(integer, scale) { - const ret = wasm.toFixedPoint(integer, isLikeNone(scale) ? 0xFFFFFF : scale); - return takeObject(ret); -} - -/** -* @returns {bigint} -*/ -export function getLiquidityScale() { - const ret = wasm.getLiquidityScale(); - return takeObject(ret); -} - -/** -* @returns {bigint} -*/ -export function getLiquidityDenominator() { - const ret = wasm.getLiquidityDenominator(); - return takeObject(ret); -} - -/** -* @param {bigint} integer -* @param {number | undefined} [scale] -* @returns {bigint} -*/ -export function toLiquidity(integer, scale) { - const ret = wasm.toLiquidity(integer, isLikeNone(scale) ? 0xFFFFFF : scale); - return takeObject(ret); -} - -/** -* @returns {bigint} -*/ -export function getPercentageScale() { - const ret = wasm.getFixedPointScale(); - return takeObject(ret); -} - -/** -* @returns {bigint} -*/ -export function getPercentageDenominator() { - const ret = wasm.getPercentageDenominator(); - return takeObject(ret); -} - -/** -* @param {bigint} integer -* @param {number | undefined} [scale] -* @returns {bigint} -*/ -export function toPercentage(integer, scale) { - const ret = wasm.toPercentage(integer, isLikeNone(scale) ? 0xFFFFFF : scale); - return takeObject(ret); -} - -/** -* @returns {bigint} -*/ -export function getPriceScale() { - const ret = wasm.getPriceScale(); - return takeObject(ret); -} - -/** -* @returns {bigint} -*/ -export function getPriceDenominator() { - const ret = wasm.getPriceDenominator(); - return takeObject(ret); -} - -/** -* @param {bigint} integer -* @param {number | undefined} [scale] -* @returns {bigint} -*/ -export function toPrice(integer, scale) { - const ret = wasm.toPrice(integer, isLikeNone(scale) ? 0xFFFFFF : scale); - return takeObject(ret); -} - -/** -* @returns {bigint} -*/ -export function getSecondsPerLiquidityScale() { - const ret = wasm.getPriceScale(); - return takeObject(ret); -} - -/** -* @returns {bigint} -*/ -export function getSecondsPerLiquidityDenominator() { - const ret = wasm.getPriceDenominator(); - return takeObject(ret); -} - -/** -* @param {bigint} integer -* @param {number | undefined} [scale] -* @returns {bigint} -*/ -export function toSecondsPerLiquidity(integer, scale) { - const ret = wasm.toSecondsPerLiquidity(integer, isLikeNone(scale) ? 0xFFFFFF : scale); - return takeObject(ret); -} - -/** -* @returns {bigint} -*/ -export function getSqrtPriceScale() { - const ret = wasm.getPriceScale(); - return takeObject(ret); -} - -/** -* @returns {bigint} -*/ -export function getSqrtPriceDenominator() { - const ret = wasm.getPriceDenominator(); - return takeObject(ret); -} - -/** -* @param {bigint} integer -* @param {number | undefined} [scale] -* @returns {bigint} -*/ -export function toSqrtPrice(integer, scale) { - const ret = wasm.toSqrtPrice(integer, isLikeNone(scale) ? 0xFFFFFF : scale); - return takeObject(ret); -} - -/** -* @param {number} tick_index -* @returns {SqrtPrice} -*/ -export function calculateSqrtPrice(tick_index) { - try { - const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); - wasm.calculateSqrtPrice(retptr, tick_index); - var r0 = getInt32Memory0()[retptr / 4 + 0]; - var r1 = getInt32Memory0()[retptr / 4 + 1]; - var r2 = getInt32Memory0()[retptr / 4 + 2]; - if (r2) { - throw takeObject(r1); - } - return takeObject(r0); - } finally { - wasm.__wbindgen_add_to_stack_pointer(16); - } -} - -/** -* @param {number} tick_spacing -* @returns {number} -*/ -export function getMaxTick(tick_spacing) { - const ret = wasm.getMaxTick(tick_spacing); - return ret; -} - -/** -* @param {number} tick_spacing -* @returns {number} -*/ -export function getMinTick(tick_spacing) { - const ret = wasm.getMinTick(tick_spacing); - return ret; -} - -/** -* @param {number} tick_spacing -* @returns {SqrtPrice} -*/ -export function getMaxSqrtPrice(tick_spacing) { - const ret = wasm.getMaxSqrtPrice(tick_spacing); - return takeObject(ret); -} - -/** -* @param {number} tick_spacing -* @returns {SqrtPrice} -*/ -export function getMinSqrtPrice(tick_spacing) { - const ret = wasm.getMinSqrtPrice(tick_spacing); - return takeObject(ret); -} - -/** -* @returns {bigint} -*/ -export function getTokenAmountScale() { - const ret = wasm.getTokenAmountScale(); - return takeObject(ret); -} - -/** -* @returns {bigint} -*/ -export function getTokenAmountDenominator() { - const ret = wasm.getTokenAmountDenominator(); - return takeObject(ret); -} - -/** -* @param {bigint} integer -* @param {number | undefined} [scale] -* @returns {bigint} -*/ -export function toTokenAmount(integer, scale) { - const ret = wasm.toTokenAmount(integer, isLikeNone(scale) ? 0xFFFFFF : scale); - return takeObject(ret); -} - -function handleError(f, args) { - try { - return f.apply(this, args); - } catch (e) { - wasm.__wbindgen_exn_store(addHeapObject(e)); - } -} -/** -*/ -export const SwapError = Object.freeze({ NotAdmin:0,"0":"NotAdmin",NotFeeReceiver:1,"1":"NotFeeReceiver",PoolAlreadyExist:2,"2":"PoolAlreadyExist",PoolNotFound:3,"3":"PoolNotFound",TickAlreadyExist:4,"4":"TickAlreadyExist",InvalidTickIndexOrTickSpacing:5,"5":"InvalidTickIndexOrTickSpacing",PositionNotFound:6,"6":"PositionNotFound",TickNotFound:7,"7":"TickNotFound",FeeTierNotFound:8,"8":"FeeTierNotFound",PoolKeyNotFound:9,"9":"PoolKeyNotFound",AmountIsZero:10,"10":"AmountIsZero",WrongLimit:11,"11":"WrongLimit",PriceLimitReached:12,"12":"PriceLimitReached",NoGainSwap:13,"13":"NoGainSwap",InvalidTickSpacing:14,"14":"InvalidTickSpacing",FeeTierAlreadyExist:15,"15":"FeeTierAlreadyExist",PoolKeyAlreadyExist:16,"16":"PoolKeyAlreadyExist",UnauthorizedFeeReceiver:17,"17":"UnauthorizedFeeReceiver",ZeroLiquidity:18,"18":"ZeroLiquidity",TransferError:19,"19":"TransferError",TokensAreSame:20,"20":"TokensAreSame",AmountUnderMinimumAmountOut:21,"21":"AmountUnderMinimumAmountOut",InvalidFee:22,"22":"InvalidFee",NotEmptyTickDeinitialization:23,"23":"NotEmptyTickDeinitialization",InvalidInitTick:24,"24":"InvalidInitTick",InvalidInitSqrtPrice:25,"25":"InvalidInitSqrtPrice",TickLimitReached:26,"26":"TickLimitReached",NoRouteFound:27,"27":"NoRouteFound",MaxTicksCrossed:28,"28":"MaxTicksCrossed",StateOutdated:29,"29":"StateOutdated",InsufficientLiquidity:30,"30":"InsufficientLiquidity", }); - -async function __wbg_load(module, imports) { - if (typeof Response === 'function' && module instanceof Response) { - if (typeof WebAssembly.instantiateStreaming === 'function') { - try { - return await WebAssembly.instantiateStreaming(module, imports); - - } catch (e) { - if (module.headers.get('Content-Type') != 'application/wasm') { - console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e); - - } else { - throw e; - } - } - } - - const bytes = await module.arrayBuffer(); - return await WebAssembly.instantiate(bytes, imports); - - } else { - const instance = await WebAssembly.instantiate(module, imports); - - if (instance instanceof WebAssembly.Instance) { - return { instance, module }; - - } else { - return instance; - } - } -} - -function __wbg_get_imports() { - const imports = {}; - imports.wbg = {}; - imports.wbg.__wbindgen_object_drop_ref = function(arg0) { - takeObject(arg0); - }; - imports.wbg.__wbindgen_error_new = function(arg0, arg1) { - const ret = new Error(getStringFromWasm0(arg0, arg1)); - return addHeapObject(ret); - }; - imports.wbg.__wbindgen_is_bigint = function(arg0) { - const ret = typeof(getObject(arg0)) === 'bigint'; - return ret; - }; - imports.wbg.__wbindgen_bigint_from_u64 = function(arg0) { - const ret = BigInt.asUintN(64, arg0); - return addHeapObject(ret); - }; - imports.wbg.__wbindgen_jsval_eq = function(arg0, arg1) { - const ret = getObject(arg0) === getObject(arg1); - return ret; - }; - imports.wbg.__wbindgen_shr = function(arg0, arg1) { - const ret = getObject(arg0) >> getObject(arg1); - return addHeapObject(ret); - }; - imports.wbg.__wbindgen_is_object = function(arg0) { - const val = getObject(arg0); - const ret = typeof(val) === 'object' && val !== null; - return ret; - }; - imports.wbg.__wbindgen_is_undefined = function(arg0) { - const ret = getObject(arg0) === undefined; - return ret; - }; - imports.wbg.__wbindgen_in = function(arg0, arg1) { - const ret = getObject(arg0) in getObject(arg1); - return ret; - }; - imports.wbg.__wbindgen_boolean_get = function(arg0) { - const v = getObject(arg0); - const ret = typeof(v) === 'boolean' ? (v ? 1 : 0) : 2; - return ret; - }; - imports.wbg.__wbindgen_object_clone_ref = function(arg0) { - const ret = getObject(arg0); - return addHeapObject(ret); - }; - imports.wbg.__wbindgen_bigint_from_u128 = function(arg0, arg1) { - const ret = BigInt.asUintN(64, arg0) << BigInt(64) | BigInt.asUintN(64, arg1); - return addHeapObject(ret); - }; - imports.wbg.__wbindgen_number_new = function(arg0) { - const ret = arg0; - return addHeapObject(ret); - }; - imports.wbg.__wbindgen_number_get = function(arg0, arg1) { - const obj = getObject(arg1); - const ret = typeof(obj) === 'number' ? obj : undefined; - getFloat64Memory0()[arg0 / 8 + 1] = isLikeNone(ret) ? 0 : ret; - getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret); - }; - imports.wbg.__wbindgen_string_get = function(arg0, arg1) { - const obj = getObject(arg1); - const ret = typeof(obj) === 'string' ? obj : undefined; - var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - var len1 = WASM_VECTOR_LEN; - getInt32Memory0()[arg0 / 4 + 1] = len1; - getInt32Memory0()[arg0 / 4 + 0] = ptr1; - }; - imports.wbg.__wbindgen_jsval_loose_eq = function(arg0, arg1) { - const ret = getObject(arg0) == getObject(arg1); - return ret; - }; - imports.wbg.__wbg_String_88810dfeb4021902 = function(arg0, arg1) { - const ret = String(getObject(arg1)); - const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - const len1 = WASM_VECTOR_LEN; - getInt32Memory0()[arg0 / 4 + 1] = len1; - getInt32Memory0()[arg0 / 4 + 0] = ptr1; - }; - imports.wbg.__wbindgen_string_new = function(arg0, arg1) { - const ret = getStringFromWasm0(arg0, arg1); - return addHeapObject(ret); - }; - imports.wbg.__wbg_getwithrefkey_5e6d9547403deab8 = function(arg0, arg1) { - const ret = getObject(arg0)[getObject(arg1)]; - return addHeapObject(ret); - }; - imports.wbg.__wbg_set_841ac57cff3d672b = function(arg0, arg1, arg2) { - getObject(arg0)[takeObject(arg1)] = takeObject(arg2); - }; - imports.wbg.__wbg_get_bd8e338fbd5f5cc8 = function(arg0, arg1) { - const ret = getObject(arg0)[arg1 >>> 0]; - return addHeapObject(ret); - }; - imports.wbg.__wbg_length_cd7af8117672b8b8 = function(arg0) { - const ret = getObject(arg0).length; - return ret; - }; - imports.wbg.__wbg_new_16b304a2cfa7ff4a = function() { - const ret = new Array(); - return addHeapObject(ret); - }; - imports.wbg.__wbg_BigInt_42b692c18e1ac6d6 = function(arg0) { - const ret = BigInt(getObject(arg0)); - return addHeapObject(ret); - }; - imports.wbg.__wbindgen_is_function = function(arg0) { - const ret = typeof(getObject(arg0)) === 'function'; - return ret; - }; - imports.wbg.__wbg_next_40fc327bfc8770e6 = function(arg0) { - const ret = getObject(arg0).next; - return addHeapObject(ret); - }; - imports.wbg.__wbg_next_196c84450b364254 = function() { return handleError(function (arg0) { - const ret = getObject(arg0).next(); - return addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_done_298b57d23c0fc80c = function(arg0) { - const ret = getObject(arg0).done; - return ret; - }; - imports.wbg.__wbg_value_d93c65011f51a456 = function(arg0) { - const ret = getObject(arg0).value; - return addHeapObject(ret); - }; - imports.wbg.__wbg_iterator_2cee6dadfd956dfa = function() { - const ret = Symbol.iterator; - return addHeapObject(ret); - }; - imports.wbg.__wbg_get_e3c254076557e348 = function() { return handleError(function (arg0, arg1) { - const ret = Reflect.get(getObject(arg0), getObject(arg1)); - return addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_call_27c0f87801dedf93 = function() { return handleError(function (arg0, arg1) { - const ret = getObject(arg0).call(getObject(arg1)); - return addHeapObject(ret); - }, arguments) }; - imports.wbg.__wbg_new_72fb9a18b5ae2624 = function() { - const ret = new Object(); - return addHeapObject(ret); - }; - imports.wbg.__wbg_set_d4638f722068f043 = function(arg0, arg1, arg2) { - getObject(arg0)[arg1 >>> 0] = takeObject(arg2); - }; - imports.wbg.__wbg_isArray_2ab64d95e09ea0ae = function(arg0) { - const ret = Array.isArray(getObject(arg0)); - return ret; - }; - imports.wbg.__wbg_instanceof_ArrayBuffer_836825be07d4c9d2 = function(arg0) { - let result; - try { - result = getObject(arg0) instanceof ArrayBuffer; - } catch (_) { - result = false; - } - const ret = result; - return ret; - }; - imports.wbg.__wbg_isSafeInteger_f7b04ef02296c4d2 = function(arg0) { - const ret = Number.isSafeInteger(getObject(arg0)); - return ret; - }; - imports.wbg.__wbg_entries_95cc2c823b285a09 = function(arg0) { - const ret = Object.entries(getObject(arg0)); - return addHeapObject(ret); - }; - imports.wbg.__wbg_buffer_12d079cc21e14bdb = function(arg0) { - const ret = getObject(arg0).buffer; - return addHeapObject(ret); - }; - imports.wbg.__wbg_new_63b92bc8671ed464 = function(arg0) { - const ret = new Uint8Array(getObject(arg0)); - return addHeapObject(ret); - }; - imports.wbg.__wbg_set_a47bac70306a19a7 = function(arg0, arg1, arg2) { - getObject(arg0).set(getObject(arg1), arg2 >>> 0); - }; - imports.wbg.__wbg_length_c20a40f15020d68a = function(arg0) { - const ret = getObject(arg0).length; - return ret; - }; - imports.wbg.__wbg_instanceof_Uint8Array_2b3bbecd033d19f6 = function(arg0) { - let result; - try { - result = getObject(arg0) instanceof Uint8Array; - } catch (_) { - result = false; - } - const ret = result; - return ret; - }; - imports.wbg.__wbindgen_bigint_get_as_i64 = function(arg0, arg1) { - const v = getObject(arg1); - const ret = typeof(v) === 'bigint' ? v : undefined; - getBigInt64Memory0()[arg0 / 8 + 1] = isLikeNone(ret) ? BigInt(0) : ret; - getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret); - }; - imports.wbg.__wbindgen_debug_string = function(arg0, arg1) { - const ret = debugString(getObject(arg1)); - const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); - const len1 = WASM_VECTOR_LEN; - getInt32Memory0()[arg0 / 4 + 1] = len1; - getInt32Memory0()[arg0 / 4 + 0] = ptr1; - }; - imports.wbg.__wbindgen_throw = function(arg0, arg1) { - throw new Error(getStringFromWasm0(arg0, arg1)); - }; - imports.wbg.__wbindgen_memory = function() { - const ret = wasm.memory; - return addHeapObject(ret); - }; - - return imports; -} - -function __wbg_init_memory(imports, maybe_memory) { - -} - -function __wbg_finalize_init(instance, module) { - wasm = instance.exports; - __wbg_init.__wbindgen_wasm_module = module; - cachedBigInt64Memory0 = null; - cachedFloat64Memory0 = null; - cachedInt32Memory0 = null; - cachedUint8Memory0 = null; - - - return wasm; -} - -function initSync(module) { - if (wasm !== undefined) return wasm; - - const imports = __wbg_get_imports(); - - __wbg_init_memory(imports); - - if (!(module instanceof WebAssembly.Module)) { - module = new WebAssembly.Module(module); - } - - const instance = new WebAssembly.Instance(module, imports); - - return __wbg_finalize_init(instance, module); -} - -async function __wbg_init(input) { - if (wasm !== undefined) return wasm; - - if (typeof input === 'undefined') { - input = new URL('oraiswap_v3_wasm_bg.wasm', import.meta.url); - } - const imports = __wbg_get_imports(); - - if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) { - input = fetch(input); - } - - __wbg_init_memory(imports); - - const { instance, module } = await __wbg_load(await input, imports); - - return __wbg_finalize_init(instance, module); -} - -export { initSync } -export default __wbg_init; diff --git a/src/pages/Pool-V3/packages/wasm/oraiswap_v3_wasm_bg.wasm b/src/pages/Pool-V3/packages/wasm/oraiswap_v3_wasm_bg.wasm deleted file mode 100644 index 5ea25f558ce222c5f0d0277890ebb343d424f3c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 171580 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 diff --git a/src/pages/Pool-V3/packages/wasm/oraiswap_v3_wasm_bg.wasm.d.ts b/src/pages/Pool-V3/packages/wasm/oraiswap_v3_wasm_bg.wasm.d.ts deleted file mode 100644 index 75ff0fce6..000000000 --- a/src/pages/Pool-V3/packages/wasm/oraiswap_v3_wasm_bg.wasm.d.ts +++ /dev/null @@ -1,71 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -export const memory: WebAssembly.Memory; -export function computeSwapStep(a: number, b: number, c: number, d: number, e: number, f: number, g: number): void; -export function getDeltaX(a: number, b: number, c: number, d: number, e: number): void; -export function getDeltaY(a: number, b: number, c: number, d: number, e: number): void; -export function getNextSqrtPriceFromInput(a: number, b: number, c: number, d: number, e: number): void; -export function getNextSqrtPriceFromOutput(a: number, b: number, c: number, d: number, e: number): void; -export function getNextSqrtPriceXUp(a: number, b: number, c: number, d: number, e: number): void; -export function getNextSqrtPriceYDown(a: number, b: number, c: number, d: number, e: number): void; -export function calculateAmountDelta(a: number, b: number, c: number, d: number, e: number, f: number, g: number): void; -export function isEnoughAmountToChangePrice(a: number, b: number, c: number, d: number, e: number, f: number, g: number): void; -export function calculateMaxLiquidityPerTick(a: number): number; -export function checkTicks(a: number, b: number, c: number, d: number): void; -export function checkTick(a: number, b: number, c: number): void; -export function calculateMinAmountOut(a: number, b: number): number; -export function tickToPositionJs(a: number, b: number, c: number): void; -export function positionToTick(a: number, b: number, c: number): number; -export function getGlobalMaxSqrtPrice(): number; -export function getGlobalMinSqrtPrice(): number; -export function getTickSearchRange(): number; -export function getMaxChunk(a: number): number; -export function getChunkSize(): number; -export function getMaxTickCross(): number; -export function getMaxTickmapQuerySize(): number; -export function getLiquidityTicksLimit(): number; -export function getMaxPoolKeysReturned(): number; -export function getMaxPoolPairsReturned(): number; -export function calculateFee(a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number): void; -export function isTokenX(a: number, b: number, c: number, d: number, e: number): void; -export function checkTickToSqrtPriceRelationship(a: number, b: number, c: number, d: number): void; -export function alignTickToSpacing(a: number, b: number): number; -export function getTickAtSqrtPrice(a: number, b: number, c: number): void; -export function getLiquidityByX(a: number, b: number, c: number, d: number, e: number, f: number): void; -export function getLiquidityByY(a: number, b: number, c: number, d: number, e: number, f: number): void; -export function newFeeTier(a: number, b: number, c: number): void; -export function newPoolKey(a: number, b: number, c: number, d: number, e: number, f: number): void; -export function simulateSwap(a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number): void; -export function getFeeGrowthScale(): number; -export function getFeeGrowthDenominator(): number; -export function toFeeGrowth(a: number, b: number): number; -export function getFixedPointScale(): number; -export function getFixedPointDenominator(): number; -export function toFixedPoint(a: number, b: number): number; -export function getLiquidityScale(): number; -export function getLiquidityDenominator(): number; -export function toLiquidity(a: number, b: number): number; -export function getPercentageDenominator(): number; -export function toPercentage(a: number, b: number): number; -export function getPriceScale(): number; -export function getPriceDenominator(): number; -export function toPrice(a: number, b: number): number; -export function toSecondsPerLiquidity(a: number, b: number): number; -export function toSqrtPrice(a: number, b: number): number; -export function calculateSqrtPrice(a: number, b: number): void; -export function getMaxTick(a: number): number; -export function getMinTick(a: number): number; -export function getMaxSqrtPrice(a: number): number; -export function getMinSqrtPrice(a: number): number; -export function getTokenAmountScale(): number; -export function getTokenAmountDenominator(): number; -export function toTokenAmount(a: number, b: number): number; -export function getSecondsPerLiquidityDenominator(): number; -export function getSqrtPriceDenominator(): number; -export function getPercentageScale(): number; -export function getSecondsPerLiquidityScale(): number; -export function getSqrtPriceScale(): number; -export function __wbindgen_malloc(a: number, b: number): number; -export function __wbindgen_realloc(a: number, b: number, c: number, d: number): number; -export function __wbindgen_add_to_stack_pointer(a: number): number; -export function __wbindgen_exn_store(a: number): void; diff --git a/src/pages/Pool-V3/packages/wasm/package.json b/src/pages/Pool-V3/packages/wasm/package.json deleted file mode 100644 index dd0342782..000000000 --- a/src/pages/Pool-V3/packages/wasm/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "oraiswap-v3-wasm", - "type": "module", - "collaborators": [ - "Oraichain Labs" - ], - "version": "0.1.0", - "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/oraichain/oraiswap-v3.git" - }, - "files": [ - "oraiswap_v3_wasm_bg.wasm", - "oraiswap_v3_wasm.js", - "oraiswap_v3_wasm.d.ts" - ], - "main": "oraiswap_v3_wasm.js", - "homepage": "https://orai.io", - "types": "oraiswap_v3_wasm.d.ts", - "sideEffects": [ - "./snippets/*" - ] -} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 43f45df26..d1bbdf377 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4360,7 +4360,7 @@ react-use "^17.4.0" react-use-websocket "^4.5.0" -"@oraichain/oraidex-common@^1.0.91": +"@oraichain/oraidex-common@^1.0.91", "@oraichain/oraidex-common@latest": version "1.1.2" resolved "https://registry.yarnpkg.com/@oraichain/oraidex-common/-/oraidex-common-1.1.2.tgz#4ff2dfe226a2bd417f6e59e24f66b211328bb282" integrity sha512-U+XAHnwoghiC73j+i9z2TKNM/zgaOqLYJdek9CfVLhzke3p8lpFArpwiBp1S3eU+IXhYfqfHL2Ej2Y1s7bfeXg== @@ -4397,6 +4397,11 @@ resolved "https://registry.yarnpkg.com/@oraichain/oraidex-contracts-sdk/-/oraidex-contracts-sdk-1.0.47.tgz#2e9df9900d38ebf3741f98f02b531a9671554726" integrity sha512-VkMYwyo6vG8En/GICZ+J8YfSuRJpBIK6ppEifuvbeGLUmiLrlA1TsMdqs2rIa1UJQNvEVO3mXodiSXr4V2IDLg== +"@oraichain/oraidex-contracts-sdk@^1.0.48": + version "1.0.48" + resolved "https://registry.yarnpkg.com/@oraichain/oraidex-contracts-sdk/-/oraidex-contracts-sdk-1.0.48.tgz#5abe789c5fea1e809a9395f12249e838e2c9c6be" + integrity sha512-NFJfDwjLBXlAg+F5aIUs/20r3s3n6xw80ivelMBr16y5IIvGNqiSKYZQ5YOHvMaXnwyBcpf89HLd4p0OIXc5Mg== + "@oraichain/oraidex-universal-swap@1.0.96": version "1.0.96" resolved "https://registry.yarnpkg.com/@oraichain/oraidex-universal-swap/-/oraidex-universal-swap-1.0.96.tgz#d4c6c3da7f22d4f63706cf2780dfbf686850de10" @@ -4409,6 +4414,11 @@ tronweb "5.3.2" ts-protoc-gen "^0.15.0" +"@oraichain/oraiswap-v3-wasm@^0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@oraichain/oraiswap-v3-wasm/-/oraiswap-v3-wasm-0.1.0.tgz#aff12c614635ad2c4343ef62d8497e41d52408f4" + integrity sha512-87YMqhBVgVJoX5BM+AeGc13I0dTR/hIHg6sIh+j9M/T0OecaCZR4O3h+CiaBKrK9Eej0gccv9zI02FwjAggAfw== + "@oraichain/wasm-json-toolkit@^1.0.24": version "1.0.24" resolved "https://registry.yarnpkg.com/@oraichain/wasm-json-toolkit/-/wasm-json-toolkit-1.0.24.tgz#e9a431560e8e946fbb7ec257e5f13d9320ffd23a" @@ -14687,6 +14697,16 @@ ora@^5.4.1: strip-ansi "^6.0.0" wcwidth "^1.0.1" +oraiswap-v3-test@0.1.5-beta10: + version "0.1.5-beta10" + resolved "https://registry.yarnpkg.com/oraiswap-v3-test/-/oraiswap-v3-test-0.1.5-beta10.tgz#512d90264724013433b148deaf5cb13cc0985aed" + integrity sha512-tqQWb2XazwbwGGQQSGPFGxKyttDgGitx21DUq43qa8TsbM1iN35lbxETSU7bQmbZrwwUKT7iDFtkmhUptQBcww== + dependencies: + "@cosmjs/cosmwasm-stargate" "^0.31.0" + "@oraichain/oraidex-common" latest + "@oraichain/oraidex-contracts-sdk" "^1.0.48" + "@oraichain/oraiswap-v3-wasm" "^0.1.0" + os-browserify@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" From 2752cad14246100318a2d6e54cc3e2326f92da3b Mon Sep 17 00:00:00 2001 From: trungbach Date: Thu, 8 Aug 2024 14:18:48 +0700 Subject: [PATCH 06/19] update: add graphql client --- src/helper/constants.ts | 3 --- src/rest/graphClient.ts | 3 ++- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/helper/constants.ts b/src/helper/constants.ts index 2f69884a9..3f44766d8 100644 --- a/src/helper/constants.ts +++ b/src/helper/constants.ts @@ -1,5 +1,3 @@ -import { network } from 'config/networks'; - export const leapSnapId = 'npm:@leapwallet/metamask-cosmos-snap'; export const leapWalletType = 'leapSnap'; @@ -10,4 +8,3 @@ export const bitcoinLcd = 'https://btc.lcd.orai.io'; export const MIN_DEPOSIT_BTC = 600; export const MIN_WITHDRAW_BTC = 600; -export const INDEXER_V3_URL = network.indexer_v3 ?? 'https://staging-ammv3-indexer.oraidex.io/'; diff --git a/src/rest/graphClient.ts b/src/rest/graphClient.ts index 46e342173..e9139ad80 100644 --- a/src/rest/graphClient.ts +++ b/src/rest/graphClient.ts @@ -1,6 +1,7 @@ +import { network } from 'config/networks'; import { gql, GraphQLClient } from 'graphql-request'; -import { INDEXER_V3_URL } from 'helper/constants'; +export const INDEXER_V3_URL = network.indexer_v3 ?? 'https://staging-ammv3-indexer.oraidex.io/'; export const graphqlClient = new GraphQLClient(INDEXER_V3_URL); export const getFeeClaimData = async (address: string) => { From dc94f176f4f2c4ffd102ffb991dc6f8ab764ceb4 Mon Sep 17 00:00:00 2001 From: trungbach Date: Thu, 8 Aug 2024 17:40:08 +0700 Subject: [PATCH 07/19] chore: use data from indexer for chart --- src/helper/constants.ts | 1 + .../Statistics/WrappedStats/WrappedStats.tsx | 21 ++++-- .../WrappedStats/useGetPoolDayData.ts | 64 +++++++++++++++++++ src/rest/graphClient.ts | 43 +++++++++++++ 4 files changed, 123 insertions(+), 6 deletions(-) create mode 100644 src/pages/Pool-V3/components/Statistics/WrappedStats/useGetPoolDayData.ts diff --git a/src/helper/constants.ts b/src/helper/constants.ts index 3f44766d8..b6f10f6e4 100644 --- a/src/helper/constants.ts +++ b/src/helper/constants.ts @@ -8,3 +8,4 @@ export const bitcoinLcd = 'https://btc.lcd.orai.io'; export const MIN_DEPOSIT_BTC = 600; export const MIN_WITHDRAW_BTC = 600; +export const DAY_IN_MILIS = 86400000; diff --git a/src/pages/Pool-V3/components/Statistics/WrappedStats/WrappedStats.tsx b/src/pages/Pool-V3/components/Statistics/WrappedStats/WrappedStats.tsx index ce8293aef..ec27d8df7 100644 --- a/src/pages/Pool-V3/components/Statistics/WrappedStats/WrappedStats.tsx +++ b/src/pages/Pool-V3/components/Statistics/WrappedStats/WrappedStats.tsx @@ -9,6 +9,8 @@ import TokensList from '../TokensList/TokensList'; import Volume from '../Volume/Volume'; import useGetStatistic from '../hooks/useGetStatistic'; import VolumeBar from '../volumeBar/VolumeBar'; +import { getPoolDayDataV3 } from 'rest/graphClient'; +import { useGetPoolDayData } from './useGetPoolDayData'; export const WrappedStats: React.FC = () => { const { classes } = useStyles(); @@ -32,15 +34,20 @@ export const WrappedStats: React.FC = () => { liquidityPlot: [] }); const { getStats } = useGetStatistic(); + const { liquidityPlotData, volumePlotData, isLoadingPoolsDayData, volume24h, tvl24h, fees24h } = useGetPoolDayData(); + + useEffect(() => { + getPoolDayDataV3(); + }, []); const { - volume24: volume24h, - tvl24: tvl24h, - fees24: fees24h, + // volume24: volume24h, + // tvl24: tvl24h, + // fees24: fees24h, tokensData, - poolsData, - volumePlot: volumePlotData, - liquidityPlot: liquidityPlotData + poolsData + // volumePlot: volumePlotData, + // liquidityPlot: liquidityPlotData } = stats; useEffect(() => { @@ -58,6 +65,8 @@ export const WrappedStats: React.FC = () => { // isLoadingStats ? ( // Loading // ) : + console.log({ volumePlotData, liquidityPlotData }); + return ( diff --git a/src/pages/Pool-V3/components/Statistics/WrappedStats/useGetPoolDayData.ts b/src/pages/Pool-V3/components/Statistics/WrappedStats/useGetPoolDayData.ts new file mode 100644 index 000000000..d1a944408 --- /dev/null +++ b/src/pages/Pool-V3/components/Statistics/WrappedStats/useGetPoolDayData.ts @@ -0,0 +1,64 @@ +import { useQuery } from '@tanstack/react-query'; +import { DAY_IN_MILIS } from 'helper/constants'; +import { getPoolDayDataV3, PoolDayDataV3 } from 'rest/graphClient'; + +export const useGetPoolDayData = () => { + const { data: poolsDayData, isLoading: isLoadingPoolsDayData } = useQuery(['pool-day-data'], getPoolDayDataV3, { + refetchOnWindowFocus: true, + placeholderData: [] + }); + + const convertPoolDayDataToLiquidityPlotData = (poolDayData: PoolDayDataV3) => { + return { + timestamp: Number(poolDayData.keys[0]) * DAY_IN_MILIS, + value: poolDayData.sum.tvlUSD + }; + }; + + const convertPoolDayDataToVolumePlotData = (poolDayData: PoolDayDataV3) => { + return { + timestamp: Number(poolDayData.keys[0]) * DAY_IN_MILIS, + value: poolDayData.sum.volumeInUSD + }; + }; + + const sortedPoolsDayData = [...poolsDayData].sort((a, b) => Number(a.keys[0]) - Number(b.keys[0])); + + const liquidityPlotData = sortedPoolsDayData.map(convertPoolDayDataToLiquidityPlotData); + const volumePlotData = sortedPoolsDayData + .map(convertPoolDayDataToVolumePlotData) + .slice(0, sortedPoolsDayData.length - 1); + + const volume24h = { + value: volumePlotData[volumePlotData.length - 1]?.value ?? 0, + change: + ((volumePlotData[volumePlotData.length - 1]?.value - volumePlotData[volumePlotData.length - 2]?.value) / + volumePlotData[volumePlotData.length - 2]?.value) * + 100 + }; + const tvl24h = { + value: liquidityPlotData[liquidityPlotData.length - 1]?.value ?? 0, + change: + ((liquidityPlotData[liquidityPlotData.length - 1]?.value - + liquidityPlotData[liquidityPlotData.length - 2]?.value) / + liquidityPlotData[liquidityPlotData.length - 2]?.value) * + 100 + }; + const fees24h = { + value: sortedPoolsDayData[sortedPoolsDayData.length - 1]?.sum.feesInUSD ?? 0, + change: + ((sortedPoolsDayData[sortedPoolsDayData.length - 1]?.sum.feesInUSD - + sortedPoolsDayData[sortedPoolsDayData.length - 2]?.sum.feesInUSD) / + sortedPoolsDayData[sortedPoolsDayData.length - 2]?.sum.feesInUSD) * + 100 + }; + + return { + liquidityPlotData, + volumePlotData, + isLoadingPoolsDayData, + volume24h, + tvl24h, + fees24h + }; +}; diff --git a/src/rest/graphClient.ts b/src/rest/graphClient.ts index e9139ad80..02e1a6a29 100644 --- a/src/rest/graphClient.ts +++ b/src/rest/graphClient.ts @@ -48,3 +48,46 @@ export const getFeeClaimData = async (address: string) => { return []; } }; + +export type PoolDayDataV3 = { + keys: string[]; + sum: { + tvlUSD: number; + volumeInUSD: number; + feesInUSD: number; + }; +}; + +export type PoolDayDataV3Raw = { + query: { + poolDayData: { + groupedAggregates: PoolDayDataV3[]; + }; + }; +}; + +export const getPoolDayDataV3 = async () => { + try { + const document = gql` + { + query { + poolDayData { + groupedAggregates(groupBy: DAY_INDEX) { + keys + sum { + tvlUSD + volumeInUSD + feesInUSD + } + } + } + } + } + `; + const result = await graphqlClient.request(document); + return result.query.poolDayData.groupedAggregates || []; + } catch (error) { + console.log('error getPoolDayDataV3', error); + return []; + } +}; From 868f2a46fe118ad3452f1d3ac8b78d47212584e2 Mon Sep 17 00:00:00 2001 From: vuonghuuhung Date: Thu, 8 Aug 2024 17:56:09 +0700 Subject: [PATCH 08/19] add apr data --- src/libs/contractSingleton.ts | 21 ++++++++---- .../Pool-V3/components/PoolDetail/index.tsx | 22 ++++++++++--- .../Pool-V3/components/PoolList/index.tsx | 22 ++++++++++--- .../Pool-V3/components/PositionItem/index.tsx | 22 ++++++++++--- .../Pool-V3/components/PositionList/index.tsx | 1 - .../Statistics/WrappedStats/WrappedStats.tsx | 3 ++ src/pages/Pool-V3/hooks/useGetFeeDailyData.ts | 28 ++++++++++++++++ src/pages/Pool-V3/index.tsx | 2 +- src/rest/graphClient.ts | 32 +++++++++++++++++-- 9 files changed, 127 insertions(+), 26 deletions(-) create mode 100644 src/pages/Pool-V3/hooks/useGetFeeDailyData.ts diff --git a/src/libs/contractSingleton.ts b/src/libs/contractSingleton.ts index cfa823cfb..97d6b0497 100644 --- a/src/libs/contractSingleton.ts +++ b/src/libs/contractSingleton.ts @@ -38,6 +38,7 @@ import { CoinGeckoId } from '@oraichain/oraidex-common'; import { extractAddress, extractDenom } from 'pages/Pool-V3/components/PriceRangePlot/utils'; import { oraichainTokens } from 'config/bridgeTokens'; import { calculateTokenAmounts } from 'pages/Pool-V3/helpers/helper'; +import { getFeeDailyData } from 'rest/graphClient'; export const ALL_FEE_TIERS_DATA: FeeTier[] = [ { fee: 100000000, tick_spacing: 1 }, @@ -225,6 +226,7 @@ export default class SingletonOraiswapV3 { upperTick: number, xToY: boolean ): Promise { + await this.loadCosmwasmClient(); const tickmaps = await this._handler.tickMap(poolKey, lowerTick, upperTick, xToY); return tickmaps; } @@ -267,7 +269,7 @@ export default class SingletonOraiswapV3 { } public static async getIncentivesPosition(positionIndex: number, ownerId: string): Promise { - console.log({ positionIndex, ownerId }); + await this.loadHandler(); return await this._handler.positionIncentives(positionIndex, ownerId); } @@ -286,6 +288,7 @@ export default class SingletonOraiswapV3 { } public static async getAllPosition(address: string): Promise { + await this.loadHandler(); const position = await this._handler.getPositions(address); return position; } @@ -341,6 +344,7 @@ export default class SingletonOraiswapV3 { public static async getAllLiquidityTicks(poolKey: PoolKey, tickmap: Tickmap): Promise { const ticks: number[] = []; + await this.loadHandler(); for (const [chunkIndex, chunk] of tickmap.bitmap.entries()) { for (let i = 0; i < 64; i++) { @@ -377,6 +381,7 @@ export default class SingletonOraiswapV3 { const tokenX = oraichainTokens.find((token) => extractAddress(token) === poolKey.token_x); const tokenY = oraichainTokens.find((token) => extractAddress(token) === poolKey.token_y); + await this.loadHandler(); const res = await this._handler.getPairLiquidityValues(pool); const tvlX = res.liquidityX; const tvlY = res.liquidityY; @@ -418,6 +423,7 @@ export default class SingletonOraiswapV3 { poolList[poolKeyToString(pool.pool_key)] = pool; }); + await this.loadHandler(); const allPosition = await this._handler.allPositions(); for (const position of allPosition) { @@ -449,6 +455,7 @@ export default class SingletonOraiswapV3 { prices: CoinGeckoPrices ): Promise> => { const poolLiquidities: Record = {}; + await this.loadHandler(); for (const pool of pools) { const poolKey = pool.pool_key; @@ -637,10 +644,10 @@ export async function fetchPositionAprInfo( prices: CoinGeckoPrices, tokenXLiquidityInUsd: number, tokenYLiquidityInUsd: number, - isInRange: boolean + isInRange: boolean, + feeAndLiquidityInfo: PoolFeeAndLiquidityDaily[] ): Promise { - const feeAndLiquidityInfo = await axios.get('pool-v3/fee', {}); - const avgFeeAPRs = feeAndLiquidityInfo.data.map((pool) => { + const avgFeeAPRs = feeAndLiquidityInfo.map((pool) => { const feeAPR = (pool.feeDaily * 365) / pool.liquidityDaily; return { poolKey: pool.poolKey, @@ -692,10 +699,10 @@ export type PoolAprInfo = { export async function fetchPoolAprInfo( poolKeys: PoolKey[], prices: CoinGeckoPrices, - poolLiquidities: Record + poolLiquidities: Record, + feeAndLiquidityInfo: PoolFeeAndLiquidityDaily[] ): Promise> { - const feeAndLiquidityInfo = await axios.get('pool-v3/fee', {}); - const avgFeeAPRs = feeAndLiquidityInfo.data.map((pool) => { + const avgFeeAPRs = feeAndLiquidityInfo.map((pool) => { const feeAPR = (pool.feeDaily * 365) / pool.liquidityDaily; return { poolKey: pool.poolKey, diff --git a/src/pages/Pool-V3/components/PoolDetail/index.tsx b/src/pages/Pool-V3/components/PoolDetail/index.tsx index 03b38fda9..e98405262 100644 --- a/src/pages/Pool-V3/components/PoolDetail/index.tsx +++ b/src/pages/Pool-V3/components/PoolDetail/index.tsx @@ -21,6 +21,7 @@ import { useNavigate, useParams } from 'react-router-dom'; import { getFeeClaimData } from 'rest/graphClient'; import PositionItem from '../PositionItem'; import styles from './index.module.scss'; +import { useGetFeeDailyData } from 'pages/Pool-V3/hooks/useGetFeeDailyData'; const PoolV3Detail = () => { const [address] = useConfigReducer('address'); @@ -57,6 +58,8 @@ const PoolV3Detail = () => { total: totalLiquidity, allocation: {} }); + const yesterdayIndex = Math.floor(Date.now() / (24 * 60 * 60 * 1000)) - 1; + const { feeDailyData, refetchfeeDailyData } = useGetFeeDailyData(yesterdayIndex); useEffect(() => { (async () => { @@ -80,7 +83,7 @@ const PoolV3Detail = () => { useEffect(() => { const getAPRInfo = async () => { - const res = await fetchPoolAprInfo([poolDetail.pool_key], prices, liquidityPools); + const res = await fetchPoolAprInfo([poolDetail.pool_key], prices, liquidityPools, feeDailyData); setAprInfo({ ...aprInfo, [poolKeyString]: res[poolKeyString] @@ -232,7 +235,12 @@ const PoolV3Detail = () => {
Swap Fee -

{numberWithCommas((aprInfo[poolKeyString]?.swapFee || 0) * 100)}%

+

+ {numberWithCommas((aprInfo[poolKeyString]?.swapFee || 0) * 100, undefined, { + maximumFractionDigits: 2 + })} + % +

@@ -242,18 +250,22 @@ const PoolV3Detail = () => {

{!aprInfo[poolKeyString]?.incentivesApr ? '-- ' - : `${numberWithCommas(aprInfo[poolKeyString].incentivesApr * 100)}%`} + : `${numberWithCommas(aprInfo[poolKeyString].incentivesApr * 100, undefined, { + maximumFractionDigits: 2 + })}%`}

Total APR -

{numberWithCommas((aprInfo[poolKeyString]?.apr || 0) * 100)}%

+

+ {numberWithCommas((aprInfo[poolKeyString]?.apr || 0) * 100, undefined, { maximumFractionDigits: 2 })}% +

- {

Your Liquidity Positions ({dataPosition?.length ?? 0})

} + {

My positions ({dataPosition?.length ?? 0})

}
{dataPosition.length diff --git a/src/pages/Pool-V3/components/PoolList/index.tsx b/src/pages/Pool-V3/components/PoolList/index.tsx index 391c6ad01..4a8079b17 100644 --- a/src/pages/Pool-V3/components/PoolList/index.tsx +++ b/src/pages/Pool-V3/components/PoolList/index.tsx @@ -23,6 +23,8 @@ import useConfigReducer from 'hooks/useConfigReducer'; import axios from 'axios'; import { oraichainTokens } from 'config/bridgeTokens'; import LoadingBox from 'components/LoadingBox'; +import { useGetFeeDailyData } from 'pages/Pool-V3/hooks/useGetFeeDailyData'; +import { toFixedIfNecessary } from 'helper/format'; const PoolList = () => { const { data: prices } = useCoinGeckoPrices(); @@ -38,6 +40,8 @@ const PoolList = () => { const [loading, setLoading] = useState(false); const [search, setSearch] = useState(); const [dataPool, setDataPool] = useState([...Array(0)]); + const yesterdayIndex = Math.floor(Date.now() / (24 * 60 * 60 * 1000)); + const { feeDailyData, refetchfeeDailyData } = useGetFeeDailyData(yesterdayIndex); useEffect(() => { (async () => { @@ -87,7 +91,7 @@ const PoolList = () => { const getAPRInfo = async () => { const poolKeys = dataPool.map((pool) => parsePoolKeyString(pool.poolKey)); - const res = await fetchPoolAprInfo(poolKeys, prices, liquidityPools); + const res = await fetchPoolAprInfo(poolKeys, prices, liquidityPools, feeDailyData); setAprInfo(res); }; if (dataPool.length && prices && liquidityPools) { @@ -467,7 +471,9 @@ const PoolItemTData = ({ item, theme, liquidity, volumn, aprInfo }) => {
- {numberWithCommas((aprInfo.apr ?? 0) * 100)}% + + {numberWithCommas(toFixedIfNecessary(((aprInfo.apr ?? 0) * 100).toString(), 2))}% + {
Swap fee - {numberWithCommas((aprInfo.swapFee ?? 0) * 100)}% + + {numberWithCommas(toFixedIfNecessary((aprInfo.swapFee ?? 0 * 100).toString(), 2))}% +
Incentives Boost  - {numberWithCommas((aprInfo.incentivesApr ?? 0) * 100)}% + + {numberWithCommas(toFixedIfNecessary(((aprInfo.incentivesApr ?? 0) * 100).toString(), 2))}% +
Total APR - {numberWithCommas((aprInfo.apr ?? 0) * 100)}% + + {numberWithCommas(toFixedIfNecessary(((aprInfo.apr ?? 0) * 100).toString(), 2))}% +
} diff --git a/src/pages/Pool-V3/components/PositionItem/index.tsx b/src/pages/Pool-V3/components/PositionItem/index.tsx index 7b7aec167..579c89c11 100644 --- a/src/pages/Pool-V3/components/PositionItem/index.tsx +++ b/src/pages/Pool-V3/components/PositionItem/index.tsx @@ -36,6 +36,7 @@ import { oraichainTokens } from 'config/bridgeTokens'; import { oraichainTokensWithIcon } from 'config/chainInfos'; import { toDisplay, parseAssetInfo, TokenItemType, BigDecimal, CW20_DECIMALS } from '@oraichain/oraidex-common'; import { Tick } from '@oraichain/oraidex-contracts-sdk/build/OraiswapV3.types'; +import { useGetFeeDailyData } from 'pages/Pool-V3/hooks/useGetFeeDailyData'; const shorterPrefixConfig: PrefixConfig = { B: 1000000000, @@ -86,6 +87,10 @@ const PositionItem = ({ position, setStatusRemove }) => { initialXtoY(tickerToAddress(position?.pool_key.token_x), tickerToAddress(position?.pool_key.token_y)) ); + const yesterdayIndex = Math.floor(Date.now() / (24 * 60 * 60 * 1000)) - 1; + console.log('yesterdayIndex', yesterdayIndex); + const { feeDailyData, refetchfeeDailyData } = useGetFeeDailyData(yesterdayIndex); + useOnClickOutside(ref, () => { setCollapse(false); }); @@ -103,7 +108,8 @@ const PositionItem = ({ position, setStatusRemove }) => { prices, position.tokenXLiqInUsd, position.tokenYLiqInUsd, - statusRange + statusRange, + feeDailyData ); setAprInfo(res); }; @@ -227,7 +233,7 @@ const PositionItem = ({ position, setStatusRemove }) => {

APR

- {numberWithCommas(aprInfo.total * 100)}%  + {numberWithCommas(aprInfo.total * 100, undefined, { maximumFractionDigits: 2 })}%  {
Swap fee - {numberWithCommas(aprInfo.swapFee * 100)}% + + {numberWithCommas(aprInfo.swapFee * 100, undefined, { maximumFractionDigits: 2 })}% +
Incentives Boost  - {numberWithCommas(aprInfo.incentive * 100)}% + + {numberWithCommas(aprInfo.incentive * 100, undefined, { maximumFractionDigits: 2 })}% +
Total APR - {numberWithCommas(aprInfo.total * 100)}% + + {numberWithCommas(aprInfo.total * 100, undefined, { maximumFractionDigits: 2 })}% +
} diff --git a/src/pages/Pool-V3/components/PositionList/index.tsx b/src/pages/Pool-V3/components/PositionList/index.tsx index 592876ddd..3113a5aa5 100644 --- a/src/pages/Pool-V3/components/PositionList/index.tsx +++ b/src/pages/Pool-V3/components/PositionList/index.tsx @@ -20,7 +20,6 @@ const PositionList = () => { const [dataPosition, setDataPosition] = useState([]); const [loading, setLoading] = useState(false); - const [feeClaimData, setFeeClaimData] = useState([]); const [statusRemove, setStatusRemove] = useState(undefined); useEffect(() => { diff --git a/src/pages/Pool-V3/components/Statistics/WrappedStats/WrappedStats.tsx b/src/pages/Pool-V3/components/Statistics/WrappedStats/WrappedStats.tsx index ce8293aef..2609ff0d4 100644 --- a/src/pages/Pool-V3/components/Statistics/WrappedStats/WrappedStats.tsx +++ b/src/pages/Pool-V3/components/Statistics/WrappedStats/WrappedStats.tsx @@ -46,6 +46,9 @@ export const WrappedStats: React.FC = () => { useEffect(() => { (async () => { setIsLoadingStats(true); + + + const data = await getStats(); if (data) { diff --git a/src/pages/Pool-V3/hooks/useGetFeeDailyData.ts b/src/pages/Pool-V3/hooks/useGetFeeDailyData.ts new file mode 100644 index 000000000..8e897737e --- /dev/null +++ b/src/pages/Pool-V3/hooks/useGetFeeDailyData.ts @@ -0,0 +1,28 @@ +import { useQuery } from '@tanstack/react-query'; +import { PoolFeeAndLiquidityDaily } from 'libs/contractSingleton'; +import { FeeDailyData, getFeeDailyData } from 'rest/graphClient'; + +export const useGetFeeDailyData = (dayIndex: number) => { + const { data, refetch: refetchfeeDailyData } = useQuery( + ['pool-v3-fee-daily-data'], + () => getFeeDailyData(dayIndex), + { + refetchOnWindowFocus: true, + placeholderData: [], + cacheTime: 5 * 60 * 1000 + } + ); + + const feeDailyData: PoolFeeAndLiquidityDaily[] = data.map((item) => { + return { + poolKey: item.poolId, + feeDaily: item.feesInUSD, + liquidityDaily: item.tvlUSD + }; + }); + + return { + feeDailyData, + refetchfeeDailyData + }; +}; diff --git a/src/pages/Pool-V3/index.tsx b/src/pages/Pool-V3/index.tsx index a568a2a7e..b12835490 100644 --- a/src/pages/Pool-V3/index.tsx +++ b/src/pages/Pool-V3/index.tsx @@ -23,7 +23,7 @@ type TabRender = { const listTab = Object.values(PoolV3PageType); const listTabRender: TabRender[] = [ { id: PoolV3PageType.POOL, value: 'Pools', content: PoolList }, - { id: PoolV3PageType.POSITION, value: 'Your Liquidity Positions', content: PositionList }, + { id: PoolV3PageType.POSITION, value: 'My positions', content: PositionList }, { id: PoolV3PageType.STAT, value: 'Stats', content: WrappedStats } ]; diff --git a/src/rest/graphClient.ts b/src/rest/graphClient.ts index e9139ad80..2ac2e065f 100644 --- a/src/rest/graphClient.ts +++ b/src/rest/graphClient.ts @@ -17,8 +17,7 @@ export const getFeeClaimData = async (address: string) => { principalAmountY fees { nodes { - amountXInUSD - amountYInUSD + amountInUSD amountX amountY claimFeeIncentiveTokens { @@ -48,3 +47,32 @@ export const getFeeClaimData = async (address: string) => { return []; } }; + +export type FeeDailyData = { + poolId: string; + tvlUSD: number; + feesInUSD: number; +}; + +export const getFeeDailyData = async (dayIndex: number): Promise => { + try { + const document = gql` + { + query { + poolDayData(filter: { dayIndex: { equalTo: ${dayIndex} } }) { + nodes { + poolId + tvlUSD + feesInUSD + } + } + } + } + `; + const result = await graphqlClient.request(document); + return result.query.poolDayData.nodes || []; + } catch (error) { + console.log('error', error); + return []; + } +}; From c793b5b8aa4c481d8e536fef364225c8cabab9dc Mon Sep 17 00:00:00 2001 From: vuonghuuhung Date: Fri, 9 Aug 2024 10:35:55 +0700 Subject: [PATCH 09/19] update volume and liquidity in pool list --- .../Pool-V3/components/PoolList/index.tsx | 225 ++---------------- .../Pool-V3/components/PositionItem/index.tsx | 2 - .../Pool-V3/hooks/useGetPoolLiqAndVol.ts | 28 +++ src/rest/graphClient.ts | 41 ++++ 4 files changed, 83 insertions(+), 213 deletions(-) create mode 100644 src/pages/Pool-V3/hooks/useGetPoolLiqAndVol.ts diff --git a/src/pages/Pool-V3/components/PoolList/index.tsx b/src/pages/Pool-V3/components/PoolList/index.tsx index 041744657..bd4c512c7 100644 --- a/src/pages/Pool-V3/components/PoolList/index.tsx +++ b/src/pages/Pool-V3/components/PoolList/index.tsx @@ -25,6 +25,7 @@ import { oraichainTokens } from 'config/bridgeTokens'; import LoadingBox from 'components/LoadingBox'; import { useGetFeeDailyData } from 'pages/Pool-V3/hooks/useGetFeeDailyData'; import { toFixedIfNecessary } from 'helper/format'; +import { useGetPoolLiqAndVol } from 'pages/Pool-V3/hooks/useGetPoolLiqAndVol'; const PoolList = () => { const { data: prices } = useCoinGeckoPrices(); @@ -43,13 +44,13 @@ const PoolList = () => { const yesterdayIndex = Math.floor(Date.now() / (24 * 60 * 60 * 1000)) - 1; const { feeDailyData, refetchfeeDailyData } = useGetFeeDailyData(yesterdayIndex); + const { poolLiquidities, poolVolume, refetchPoolLiqAndVol } = useGetPoolLiqAndVol(yesterdayIndex); useEffect(() => { (async () => { try { setLoading(true); const pools = await SingletonOraiswapV3.getPools(); - console.log('pools', pools); const fmtPools = (pools || []) .map((p) => { const isLight = theme === 'light'; @@ -79,8 +80,18 @@ const PoolList = () => { (async () => { try { if (dataPool.length) { - const liquidityByPools = await SingletonOraiswapV3.getPoolLiquidities(dataPool, prices); - setLiquidityPools(liquidityByPools); + setLiquidityPools(poolLiquidities); + setVolumnePools(Object.keys(poolVolume).map((poolAddress) => { + return { + apy: 0, + poolAddress, + fee: 0, + volume24: poolVolume[poolAddress], + tokenX: null, + tokenY: null, + tvl: null + } + })); } } catch (error) { console.log('error: get liquidities', error); @@ -100,214 +111,6 @@ const PoolList = () => { } }, [dataPool, prices, liquidityPools]); - useEffect(() => { - const fetchStatusAmmV3 = async () => { - try { - const res = await axios.get('/pool-v3/status', { baseURL: 'https://api-staging.oraidex.io/v1' }); - return res.data; - } catch (error) { - return []; - } - }; - - fetchStatusAmmV3().then(async (data) => { - const pools = await SingletonOraiswapV3.getPools(); - const allPoolsData = pools.map((pool) => { - return { - tokenX: pool.pool_key.token_x, - tokenY: pool.pool_key.token_y, - fee: BigInt(pool.pool_key.fee_tier.fee), - poolKey: poolKeyToString(pool.pool_key) - }; - }); - const poolsDataObject: Record< - string, - { - tokenX: string; - tokenY: string; - fee: bigint; - poolKey: string; - } - > = {}; - allPoolsData.forEach((pool) => { - poolsDataObject[pool.poolKey.toString()] = pool; - }); - - // let allTokens = oraichainTokens.reduce((acc, cur) => { - // return { ...acc, [cur.contractAddress || cur.denom]: cur }; - // }, {}); - - // const unknownTokens = new Set(); - // allPoolsData.forEach((pool) => { - // if (!allTokens[pool.tokenX.toString()]) { - // unknownTokens.add(pool.tokenX); - // } - - // if (!allTokens[pool.tokenY.toString()]) { - // unknownTokens.add(pool.tokenY); - // } - // }); - - // const tokenInfos = await SingletonOraiswapV3.getTokensInfo([...unknownTokens]); - // // yield* put(poolsActions.addTokens(newTokens)) - - // const preparedTokens: Record = {}; - // Object.entries(allTokens).forEach(([key, val]) => { - // // @ts-ignore - // if (typeof val.coinGeckoId !== 'undefined') { - // preparedTokens[key] = val as Required; - // } - // }); - - // let tokensPricesData: Record = {}; - - // const volume24 = { - // value: 0, - // change: 0 - // }; - // const tvl24 = { - // value: 0, - // change: 0 - // }; - // const fees24 = { - // value: 0, - // change: 0 - // }; - - // const tokensDataObject: Record = {}; - let poolsData: { - poolAddress: string; - tokenX: string; - tokenY: string; - fee: number; - volume24: number; - tvl: number; - apy: number; - }[] = []; - // const volumeForTimestamps: Record = {}; - // const liquidityForTimestamps: Record = {}; - // const feesForTimestamps: Record = {}; - - const lastTimestamp = Math.max( - ...Object.values(data) - .filter((snaps: any) => snaps.length > 0) - .map((snaps: any) => +snaps[snaps.length - 1].timestamp) - ); - - Object.entries(data).forEach(([address, snapshots]) => { - // if (!poolsDataObject[address]) { - // return; - // } - // const tokenXId = preparedTokens?.[poolsDataObject[address].tokenX.toString()]?.coingeckoId ?? ''; - // const tokenYId = preparedTokens?.[poolsDataObject[address].tokenY.toString()]?.coingeckoId ?? ''; - // if (!tokensDataObject[poolsDataObject[address].tokenX.toString()]) { - // tokensDataObject[poolsDataObject[address].tokenX.toString()] = { - // address: poolsDataObject[address].tokenX, - // price: tokensPricesData?.[tokenXId]?.price ?? 0, - // volume24: 0, - // tvl: 0, - // priceChange: 0 - // }; - // } - // if (!tokensDataObject[poolsDataObject[address].tokenY.toString()]) { - // tokensDataObject[poolsDataObject[address].tokenY.toString()] = { - // address: poolsDataObject[address].tokenY, - // price: tokensPricesData?.[tokenYId]?.price ?? 0, - // volume24: 0, - // tvl: 0, - // priceChange: 0 - // }; - // } - // @ts-ignore - if (!snapshots.length) { - poolsData.push({ - volume24: 0, - tvl: 0, - tokenX: poolsDataObject[address].tokenX, - tokenY: poolsDataObject[address].tokenY, - // TODO: hard code decimals - fee: Number(poolsDataObject[address].fee), - apy: 0, // TODO: calculate apy - poolAddress: address - }); - return; - } - // const tokenX = allTokens[poolsDataObject[address].tokenX.toString()]; - // const tokenY = allTokens[poolsDataObject[address].tokenY.toString()]; - //@ts-ignore - const lastSnapshot = snapshots[snapshots.length - 1]; - poolsData.push({ - volume24: - lastSnapshot.timestamp === lastTimestamp - ? lastSnapshot.volumeX.usdValue24 + lastSnapshot.volumeY.usdValue24 - : 0, - tvl: - lastSnapshot.timestamp === lastTimestamp - ? lastSnapshot.liquidityX.usdValue24 + lastSnapshot.liquidityY.usdValue24 - : 0, - tokenX: poolsDataObject[address]?.tokenX, - tokenY: poolsDataObject[address]?.tokenY, - fee: Number(poolsDataObject[address]?.fee), - apy: 0, // TODO: calculate apy - poolAddress: address - }); - // // @ts-ignore - // snapshots.slice(-30).forEach((snapshot) => { - // const timestamp = snapshot.timestamp.toString(); - // if (!volumeForTimestamps[timestamp]) { - // volumeForTimestamps[timestamp] = 0; - // } - // if (!liquidityForTimestamps[timestamp]) { - // liquidityForTimestamps[timestamp] = 0; - // } - // if (!feesForTimestamps[timestamp]) { - // feesForTimestamps[timestamp] = 0; - // } - // volumeForTimestamps[timestamp] += snapshot.volumeX.usdValue24 + snapshot.volumeY.usdValue24; - // liquidityForTimestamps[timestamp] += snapshot.liquidityX.usdValue24 + snapshot.liquidityY.usdValue24; - // feesForTimestamps[timestamp] += snapshot.feeX.usdValue24 + snapshot.feeY.usdValue24; - // }); - }); - - // const volumePlot: any[] = Object.entries(volumeForTimestamps) - // .map(([timestamp, value]) => ({ - // timestamp: +timestamp, - // value - // })) - // .sort((a, b) => a.timestamp - b.timestamp); - // const liquidityPlot: any[] = Object.entries(liquidityForTimestamps) - // .map(([timestamp, value]) => ({ - // timestamp: +timestamp, - // value - // })) - // .sort((a, b) => a.timestamp - b.timestamp); - // const feePlot: any[] = Object.entries(feesForTimestamps) - // .map(([timestamp, value]) => ({ - // timestamp: +timestamp, - // value - // })) - // .sort((a, b) => a.timestamp - b.timestamp); - - const tiersToOmit = [0.001, 0.003]; - - poolsData = poolsData.filter((pool) => !tiersToOmit.includes(pool.fee)); - - // volume24.value = volumePlot.length ? volumePlot[volumePlot.length - 1].value : 0; - // tvl24.value = liquidityPlot.length ? liquidityPlot[liquidityPlot.length - 1].value : 0; - // fees24.value = feePlot.length ? feePlot[feePlot.length - 1].value : 0; - - // const prevVolume24 = volumePlot.length > 1 ? volumePlot[volumePlot.length - 2].value : 0; - // const prevTvl24 = liquidityPlot.length > 1 ? liquidityPlot[liquidityPlot.length - 2].value : 0; - // const prevFees24 = feePlot.length > 1 ? feePlot[feePlot.length - 2].value : 0; - - // volume24.change = ((volume24.value - prevVolume24) / prevVolume24) * 100; - // tvl24.change = ((tvl24.value - prevTvl24) / prevTvl24) * 100; - // fees24.change = ((fees24.value - prevFees24) / prevFees24) * 100; - - setVolumnePools(poolsData); - }); - }, []); - return (
diff --git a/src/pages/Pool-V3/components/PositionItem/index.tsx b/src/pages/Pool-V3/components/PositionItem/index.tsx index 579c89c11..44b2730fa 100644 --- a/src/pages/Pool-V3/components/PositionItem/index.tsx +++ b/src/pages/Pool-V3/components/PositionItem/index.tsx @@ -88,7 +88,6 @@ const PositionItem = ({ position, setStatusRemove }) => { ); const yesterdayIndex = Math.floor(Date.now() / (24 * 60 * 60 * 1000)) - 1; - console.log('yesterdayIndex', yesterdayIndex); const { feeDailyData, refetchfeeDailyData } = useGetFeeDailyData(yesterdayIndex); useOnClickOutside(ref, () => { @@ -122,7 +121,6 @@ const PositionItem = ({ position, setStatusRemove }) => { if (!openCollapse) return; (async () => { const { pool_key, lower_tick_index, upper_tick_index } = position; - console.log('position', position); const [lowerTickData, upperTickData, incentives] = await Promise.all([ SingletonOraiswapV3.getTicks(lower_tick_index, pool_key), SingletonOraiswapV3.getTicks(upper_tick_index, pool_key), diff --git a/src/pages/Pool-V3/hooks/useGetPoolLiqAndVol.ts b/src/pages/Pool-V3/hooks/useGetPoolLiqAndVol.ts new file mode 100644 index 000000000..5e7ae457b --- /dev/null +++ b/src/pages/Pool-V3/hooks/useGetPoolLiqAndVol.ts @@ -0,0 +1,28 @@ +import { useQuery } from '@tanstack/react-query'; +import { PoolFeeAndLiquidityDaily } from 'libs/contractSingleton'; +import { FeeDailyData, getFeeDailyData, getPoolsLiquidityAndVolume, PoolLiquidityAndVolume } from 'rest/graphClient'; + +export const useGetPoolLiqAndVol = (dayIndex: number) => { + const { data, refetch: refetchPoolLiqAndVol } = useQuery( + ['pool-v3-liquidty-volume-daily'], + () => getPoolsLiquidityAndVolume(dayIndex), + { + refetchOnWindowFocus: true, + placeholderData: [], + cacheTime: 5 * 60 * 1000 + } + ); + + const poolLiquidities: Record = {}; + const poolVolume: Record = {}; + data.forEach((item) => { + poolLiquidities[item.id] = item.totalValueLockedInUSD; + poolVolume[item.id] = item.poolDayData.aggregates.sum.volumeInUSD; + }); + + return { + poolLiquidities, + poolVolume, + refetchPoolLiqAndVol + }; +}; diff --git a/src/rest/graphClient.ts b/src/rest/graphClient.ts index 9ec286874..58974b441 100644 --- a/src/rest/graphClient.ts +++ b/src/rest/graphClient.ts @@ -120,3 +120,44 @@ export const getFeeDailyData = async (dayIndex: number): Promise return []; } }; + +export type PoolLiquidityAndVolume = { + id: string; + totalValueLockedInUSD: number; + poolDayData: { + aggregates: { + sum: { + feesInUSD: number; + volumeInUSD: number; + }; + }; + }; +}; + +export const getPoolsLiquidityAndVolume = async (dayIndex: number): Promise => { + try { + const document = gql` + query { + pools { + nodes { + id + totalValueLockedInUSD + poolDayData(filter: { dayIndex: { equalTo: ${dayIndex} } }) { + aggregates { + sum { + feesInUSD + volumeInUSD + } + } + } + } + } + } + `; + const result = await graphqlClient.request(document); + return result.pools.nodes || []; + } catch (error) { + console.log('error getPoolsLiquidityAndVolume', error); + return []; + } +}; From 0c030a14bf7f990951fab7553957598809e74243 Mon Sep 17 00:00:00 2001 From: vuonghuuhung Date: Fri, 9 Aug 2024 11:35:08 +0700 Subject: [PATCH 10/19] rm MOCK DATA & use sdk test --- package.json | 2 +- .../Pool-V3/components/PositionList/index.tsx | 325 ------------------ yarn.lock | 39 +-- 3 files changed, 8 insertions(+), 358 deletions(-) diff --git a/package.json b/package.json index de3107167..97488ade0 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "ts-jest": "^29.1.1", "typed-scss-modules": "^7.1.4", "typescript": "^5.1.6", - "oraiswap-v3-test": "0.1.5-beta10" + "oraiswap-v3-test": "^0.1.6-beta1" }, "scripts": { "analyze": "source-map-explorer 'build/static/js/*.js'", diff --git a/src/pages/Pool-V3/components/PositionList/index.tsx b/src/pages/Pool-V3/components/PositionList/index.tsx index 3113a5aa5..49870bf6a 100644 --- a/src/pages/Pool-V3/components/PositionList/index.tsx +++ b/src/pages/Pool-V3/components/PositionList/index.tsx @@ -78,328 +78,3 @@ const PositionList = () => { }; export default PositionList; - -export const MOCK_DATA = [ - { - id: 'orai-orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh-3000000000-100-84', - poolId: 'orai-orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh-3000000000-100', - principalAmountX: '500000', - principalAmountY: '1126302', - fees: { - nodes: [ - { - amountXInUSD: null, - amountYInUSD: null, - amountX: '0', - amountY: '0', - claimFeeIncentiveTokens: { - nodes: [ - { - id: '0A8B981EC18080CA491EB23E18A571439B0902FA222D18F5D3B17EAADDC2DCF4-claimFee-orai-orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh-3000000000-100-84-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', - tokenId: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', - token: { - id: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', - denom: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', - name: 'ORAIX', - logo: 'https://i.ibb.co/VmMJtf7/oraix.png' - }, - rewardAmount: '1661' - } - ] - } - }, - { - amountXInUSD: null, - amountYInUSD: null, - amountX: '312', - amountY: '0', - claimFeeIncentiveTokens: { - nodes: [ - { - id: '446866EC0563851CF86AAF935601DD1F3E74DBC780820C8BF0B243DDD3EE3891-claimFee-orai-orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh-3000000000-100-84-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', - tokenId: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', - token: { - id: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', - denom: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', - name: 'ORAIX', - logo: 'https://i.ibb.co/VmMJtf7/oraix.png' - }, - rewardAmount: '398576' - } - ] - } - }, - { - amountXInUSD: null, - amountYInUSD: null, - amountX: '33', - amountY: '0', - claimFeeIncentiveTokens: { - nodes: [ - { - id: 'D5FB1C6E77640D4CD6EDC313BA043866D6A5C535282929861523F4B4C345C3AB-claimFee-orai-orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh-3000000000-100-84-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', - tokenId: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', - token: { - id: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', - denom: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', - name: 'ORAIX', - logo: 'https://i.ibb.co/VmMJtf7/oraix.png' - }, - rewardAmount: '164764' - } - ] - } - } - ] - } - }, - { - id: 'orai-orai15un8msx3n5zf9ahlxmfeqd2kwa5wm0nrpxer304m9nd5q6qq0g6sku5pdd-3000000000-100-154', - poolId: 'orai-orai15un8msx3n5zf9ahlxmfeqd2kwa5wm0nrpxer304m9nd5q6qq0g6sku5pdd-3000000000-100', - principalAmountX: '100000', - principalAmountY: '532732', - fees: { - nodes: [ - { - amountXInUSD: null, - amountYInUSD: null, - amountX: '0', - amountY: '0', - claimFeeIncentiveTokens: { - nodes: [ - { - id: '0E4913310390F391E21C47BE68F24F907DF9845F82466EC25AC00A3073F71D9B-claimFee-orai-orai15un8msx3n5zf9ahlxmfeqd2kwa5wm0nrpxer304m9nd5q6qq0g6sku5pdd-3000000000-100-154-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', - tokenId: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', - token: { - id: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', - denom: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', - name: 'ORAIX', - logo: 'https://i.ibb.co/VmMJtf7/oraix.png' - }, - rewardAmount: '7777' - } - ] - } - } - ] - } - }, - { - id: 'orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh-orai1hn8w33cqvysun2aujk5sv33tku4pgcxhhnsxmvnkfvdxagcx0p8qa4l98q-3000000000-100-17', - poolId: - 'orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh-orai1hn8w33cqvysun2aujk5sv33tku4pgcxhhnsxmvnkfvdxagcx0p8qa4l98q-3000000000-100', - principalAmountX: '387330', - principalAmountY: '1143314', - fees: { - nodes: [] - } - }, - { - id: 'orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100-160', - poolId: 'orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100', - principalAmountX: '100000', - principalAmountY: '539684344', - fees: { - nodes: [] - } - }, - { - id: 'orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh-orai15un8msx3n5zf9ahlxmfeqd2kwa5wm0nrpxer304m9nd5q6qq0g6sku5pdd-500000000-10-52', - poolId: - 'orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh-orai15un8msx3n5zf9ahlxmfeqd2kwa5wm0nrpxer304m9nd5q6qq0g6sku5pdd-500000000-10', - principalAmountX: '70374', - principalAmountY: '119972', - fees: { - nodes: [] - } - }, - { - id: 'orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100-98', - poolId: 'orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100', - principalAmountX: '93072', - principalAmountY: '105354416', - fees: { - nodes: [ - { - amountXInUSD: null, - amountYInUSD: null, - amountX: '169', - amountY: '0', - claimFeeIncentiveTokens: { - nodes: [ - { - id: '73D98E5910363AA2DD25AFCA680E405AF84EDF757E3B8E0B8F12AD833FD97A8B-claimFee-orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100-98-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', - tokenId: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', - token: { - id: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', - denom: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', - name: 'ORAIX', - logo: 'https://i.ibb.co/VmMJtf7/oraix.png' - }, - rewardAmount: '240408' - } - ] - } - }, - { - amountXInUSD: null, - amountYInUSD: null, - amountX: '0', - amountY: '0', - claimFeeIncentiveTokens: { - nodes: [] - } - } - ] - } - }, - { - id: 'orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh-orai15un8msx3n5zf9ahlxmfeqd2kwa5wm0nrpxer304m9nd5q6qq0g6sku5pdd-500000000-10-70', - poolId: - 'orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh-orai15un8msx3n5zf9ahlxmfeqd2kwa5wm0nrpxer304m9nd5q6qq0g6sku5pdd-500000000-10', - principalAmountX: '1982821', - principalAmountY: '2241197', - fees: { - nodes: [ - { - amountXInUSD: null, - amountYInUSD: null, - amountX: '0', - amountY: '6', - claimFeeIncentiveTokens: { - nodes: [] - } - } - ] - } - }, - { - id: 'factory/orai1wuvhex9xqs3r539mvc6mtm7n20fcj3qr2m0y9khx6n5vtlngfzes3k0rq9/ton-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100-153', - poolId: - 'factory/orai1wuvhex9xqs3r539mvc6mtm7n20fcj3qr2m0y9khx6n5vtlngfzes3k0rq9/ton-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100', - principalAmountX: '1000000000', - principalAmountY: '1543494902', - fees: { - nodes: [ - { - amountXInUSD: null, - amountYInUSD: null, - amountX: '2450494', - amountY: '0', - claimFeeIncentiveTokens: { - nodes: [] - } - } - ] - } - }, - { - id: 'orai-orai15un8msx3n5zf9ahlxmfeqd2kwa5wm0nrpxer304m9nd5q6qq0g6sku5pdd-3000000000-100-156', - poolId: 'orai-orai15un8msx3n5zf9ahlxmfeqd2kwa5wm0nrpxer304m9nd5q6qq0g6sku5pdd-3000000000-100', - principalAmountX: '1000000', - principalAmountY: '4345107', - fees: { - nodes: [] - } - }, - { - id: 'orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-100000000-1-81', - poolId: 'orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-100000000-1', - principalAmountX: '10000', - principalAmountY: '26756', - fees: { - nodes: [] - } - }, - { - id: 'orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-100000000-1-90', - poolId: 'orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-100000000-1', - principalAmountX: '100', - principalAmountY: '146', - fees: { - nodes: [] - } - }, - { - id: 'orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100-88', - poolId: 'orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100', - principalAmountX: '100', - principalAmountY: '113198', - fees: { - nodes: [ - { - amountXInUSD: null, - amountYInUSD: null, - amountX: '0', - amountY: '0', - claimFeeIncentiveTokens: { - nodes: [ - { - id: '97F86751A2C900A988ABC482CA50687C4F31AF6BF0B76E200B4640EF66C2FD86-claimFee-orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100-88-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', - tokenId: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', - token: { - id: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', - denom: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', - name: 'ORAIX', - logo: 'https://i.ibb.co/VmMJtf7/oraix.png' - }, - rewardAmount: '40' - } - ] - } - } - ] - } - }, - { - id: 'orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh-orai1hn8w33cqvysun2aujk5sv33tku4pgcxhhnsxmvnkfvdxagcx0p8qa4l98q-3000000000-100-18', - poolId: - 'orai12hzjxfh77wl572gdzct2fxv2arxcwh6gykc7qh-orai1hn8w33cqvysun2aujk5sv33tku4pgcxhhnsxmvnkfvdxagcx0p8qa4l98q-3000000000-100', - principalAmountX: '387325', - principalAmountY: '1143314', - fees: { - nodes: [] - } - }, - { - id: 'orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100-91', - poolId: 'orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100', - principalAmountX: '1', - principalAmountY: '11560', - fees: { - nodes: [ - { - amountXInUSD: null, - amountYInUSD: null, - amountX: '0', - amountY: '0', - claimFeeIncentiveTokens: { - nodes: [ - { - id: 'E8DAFABA05274A0A736B704AE2E681A9F823783B6CB2E275F1B071DFC89371E3-claimFee-orai-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100-91-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', - tokenId: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', - token: { - id: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', - denom: 'orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge', - name: 'ORAIX', - logo: 'https://i.ibb.co/VmMJtf7/oraix.png' - }, - rewardAmount: '6' - } - ] - } - } - ] - } - }, - { - id: 'factory/orai1wuvhex9xqs3r539mvc6mtm7n20fcj3qr2m0y9khx6n5vtlngfzes3k0rq9/ton-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100-152', - poolId: - 'factory/orai1wuvhex9xqs3r539mvc6mtm7n20fcj3qr2m0y9khx6n5vtlngfzes3k0rq9/ton-orai1lus0f0rhx8s03gdllx2n6vhkmf0536dv57wfge-3000000000-100', - principalAmountX: '10000000', - principalAmountY: '15434950', - fees: { - nodes: [] - } - } -]; diff --git a/yarn.lock b/yarn.lock index 046e1999a..b1e9d271f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14916,10 +14916,10 @@ ora@^5.4.1: strip-ansi "^6.0.0" wcwidth "^1.0.1" -oraiswap-v3-test@0.1.5-beta10: - version "0.1.5-beta10" - resolved "https://registry.yarnpkg.com/oraiswap-v3-test/-/oraiswap-v3-test-0.1.5-beta10.tgz#512d90264724013433b148deaf5cb13cc0985aed" - integrity sha512-tqQWb2XazwbwGGQQSGPFGxKyttDgGitx21DUq43qa8TsbM1iN35lbxETSU7bQmbZrwwUKT7iDFtkmhUptQBcww== +oraiswap-v3-test@^0.1.6-beta1: + version "0.1.6-beta1" + resolved "https://registry.yarnpkg.com/oraiswap-v3-test/-/oraiswap-v3-test-0.1.6-beta1.tgz#3314ba268a00bfc569172208620c239c27c5d439" + integrity sha512-O3FCTF1iposB2HoFNJxYY4B2sXcsIisLKsSsgprG7L9aQnBdxx24ADhjR2xlcE1ix0fsbjcak4N1bgKCOSmoCw== dependencies: "@cosmjs/cosmwasm-stargate" "^0.31.0" "@oraichain/oraidex-common" latest @@ -17900,7 +17900,7 @@ string-natural-compare@^3.0.1: resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== -"string-width-cjs@npm:string-width@^4.2.0": +"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -17918,15 +17918,6 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -18006,7 +17997,7 @@ stringify-object@^3.3.0: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -18027,13 +18018,6 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -19801,7 +19785,7 @@ workbox-window@6.6.1: "@types/trusted-types" "^2.0.2" workbox-core "6.6.1" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -19828,15 +19812,6 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 8ad6350eb4d9bb8bf5b01e182b5f2e7e67111d96 Mon Sep 17 00:00:00 2001 From: trungbach Date: Fri, 9 Aug 2024 12:04:56 +0700 Subject: [PATCH 11/19] chore: remove redundant code --- .../components/Statistics/WrappedStats/WrappedStats.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/pages/Pool-V3/components/Statistics/WrappedStats/WrappedStats.tsx b/src/pages/Pool-V3/components/Statistics/WrappedStats/WrappedStats.tsx index 818a5a624..4a695b1bf 100644 --- a/src/pages/Pool-V3/components/Statistics/WrappedStats/WrappedStats.tsx +++ b/src/pages/Pool-V3/components/Statistics/WrappedStats/WrappedStats.tsx @@ -34,7 +34,7 @@ export const WrappedStats: React.FC = () => { liquidityPlot: [] }); const { getStats } = useGetStatistic(); - const { liquidityPlotData, volumePlotData, isLoadingPoolsDayData, volume24h, tvl24h, fees24h } = useGetPoolDayData(); + const { liquidityPlotData, volumePlotData, volume24h, tvl24h, fees24h } = useGetPoolDayData(); useEffect(() => { getPoolDayDataV3(); @@ -54,8 +54,6 @@ export const WrappedStats: React.FC = () => { (async () => { setIsLoadingStats(true); - - const data = await getStats(); if (data) { From a4853f857d7254c96123d66ccdcb57af96ecf4ad Mon Sep 17 00:00:00 2001 From: vuonghuuhung Date: Fri, 9 Aug 2024 13:52:00 +0700 Subject: [PATCH 12/19] rm unused code --- src/pages/Pool-V3/components/CreatePosition/index.tsx | 3 --- src/pages/Pool-V3/components/NewPositionNoPool/index.tsx | 2 +- src/pages/Pool-V3/components/PoolList/index.tsx | 9 ++------- src/pages/Pool-V3/components/PositionItem/index.tsx | 7 ------- 4 files changed, 3 insertions(+), 18 deletions(-) diff --git a/src/pages/Pool-V3/components/CreatePosition/index.tsx b/src/pages/Pool-V3/components/CreatePosition/index.tsx index c877f8b34..3dde3e62c 100644 --- a/src/pages/Pool-V3/components/CreatePosition/index.tsx +++ b/src/pages/Pool-V3/components/CreatePosition/index.tsx @@ -6,12 +6,10 @@ import { TokenAmount } from '@oraichain/oraidex-contracts-sdk/build/OraiswapV3.types'; import { ReactComponent as BackIcon } from 'assets/icons/back.svg'; -import { ReactComponent as TooltipIc } from 'assets/icons/icon_tooltip.svg'; import { ReactComponent as SettingIcon } from 'assets/icons/setting.svg'; import { ReactComponent as Continuous } from 'assets/images/continuous.svg'; import { ReactComponent as Discrete } from 'assets/images/discrete.svg'; import classNames from 'classnames'; -import { TooltipIcon } from 'components/Tooltip'; import { oraichainTokens } from 'config/bridgeTokens'; import { useCoinGeckoPrices } from 'hooks/useCoingecko'; import useTheme from 'hooks/useTheme'; @@ -79,7 +77,6 @@ const CreatePosition = () => { startPrice: 1.0 }); const [isOpen, setIsOpen] = useState(false); - const [openTooltip, setOpenTooltip] = useState(false); const [slippage, setSlippage] = useState(1); const [typeChart, setTypeChart] = useState(TYPE_CHART.CONTINUOUS); const [focusId, setFocusId] = useState<'from' | 'to' | null>(null); diff --git a/src/pages/Pool-V3/components/NewPositionNoPool/index.tsx b/src/pages/Pool-V3/components/NewPositionNoPool/index.tsx index 7a5896340..46ac338c2 100644 --- a/src/pages/Pool-V3/components/NewPositionNoPool/index.tsx +++ b/src/pages/Pool-V3/components/NewPositionNoPool/index.tsx @@ -1,6 +1,6 @@ import NumberFormat from 'react-number-format'; import styles from './index.module.scss'; -import { TokenItemType, toDisplay, BigDecimal } from '@oraichain/oraidex-common'; +import { TokenItemType, BigDecimal } from '@oraichain/oraidex-common'; import { PriceInfo } from '../CreatePosition'; import { useCoinGeckoPrices } from 'hooks/useCoingecko'; import { numberWithCommas } from 'helper/format'; diff --git a/src/pages/Pool-V3/components/PoolList/index.tsx b/src/pages/Pool-V3/components/PoolList/index.tsx index bd4c512c7..bdbb65d9e 100644 --- a/src/pages/Pool-V3/components/PoolList/index.tsx +++ b/src/pages/Pool-V3/components/PoolList/index.tsx @@ -1,4 +1,4 @@ -import { BigDecimal, toDisplay } from '@oraichain/oraidex-common'; +import { toDisplay } from '@oraichain/oraidex-common'; import Loading from 'assets/gif/loading.gif'; import { ReactComponent as BootsIconDark } from 'assets/icons/boost-icon-dark.svg'; import { ReactComponent as BootsIcon } from 'assets/icons/boost-icon.svg'; @@ -9,22 +9,17 @@ import SearchLightSvg from 'assets/images/search-light-svg.svg'; import SearchSvg from 'assets/images/search-svg.svg'; import classNames from 'classnames'; import { TooltipIcon } from 'components/Tooltip'; -import { network } from 'config/networks'; import { useCoinGeckoPrices } from 'hooks/useCoingecko'; import useTheme from 'hooks/useTheme'; -import SingletonOraiswapV3, { fetchPoolAprInfo, PoolAprInfo, poolKeyToString } from 'libs/contractSingleton'; -import { getCosmWasmClient } from 'libs/cosmjs'; +import SingletonOraiswapV3, { fetchPoolAprInfo, poolKeyToString } from 'libs/contractSingleton'; import { formatPoolData, parsePoolKeyString } from 'pages/Pool-V3/helpers/format'; import { formatDisplayUsdt, numberWithCommas } from 'pages/Pools/helpers'; import { useEffect, useMemo, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import styles from './index.module.scss'; import useConfigReducer from 'hooks/useConfigReducer'; -import axios from 'axios'; -import { oraichainTokens } from 'config/bridgeTokens'; import LoadingBox from 'components/LoadingBox'; import { useGetFeeDailyData } from 'pages/Pool-V3/hooks/useGetFeeDailyData'; -import { toFixedIfNecessary } from 'helper/format'; import { useGetPoolLiqAndVol } from 'pages/Pool-V3/hooks/useGetPoolLiqAndVol'; const PoolList = () => { diff --git a/src/pages/Pool-V3/components/PositionItem/index.tsx b/src/pages/Pool-V3/components/PositionItem/index.tsx index 44b2730fa..f6bcab1da 100644 --- a/src/pages/Pool-V3/components/PositionItem/index.tsx +++ b/src/pages/Pool-V3/components/PositionItem/index.tsx @@ -21,7 +21,6 @@ import { getConvertedPosition, getTick, initialXtoY, - showPrefix, tickerToAddress } from 'pages/Pool-V3/helpers/helper'; import useConfigReducer from 'hooks/useConfigReducer'; @@ -38,12 +37,6 @@ import { toDisplay, parseAssetInfo, TokenItemType, BigDecimal, CW20_DECIMALS } f import { Tick } from '@oraichain/oraidex-contracts-sdk/build/OraiswapV3.types'; import { useGetFeeDailyData } from 'pages/Pool-V3/hooks/useGetFeeDailyData'; -const shorterPrefixConfig: PrefixConfig = { - B: 1000000000, - M: 1000000, - K: 1000 -}; - const PositionItem = ({ position, setStatusRemove }) => { const theme = useTheme(); const ref = useRef(); From ddb7fe67f96b47bad93ea77063c2b33cbd63e7d9 Mon Sep 17 00:00:00 2001 From: Hau Nguyen Van Date: Fri, 9 Aug 2024 15:06:14 +0700 Subject: [PATCH 13/19] yarn lock --- yarn.lock | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/yarn.lock b/yarn.lock index e8a5ddae4..d65ef001c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4605,6 +4605,11 @@ resolved "https://registry.yarnpkg.com/@oraichain/oraidex-contracts-sdk/-/oraidex-contracts-sdk-1.0.47.tgz#2e9df9900d38ebf3741f98f02b531a9671554726" integrity sha512-VkMYwyo6vG8En/GICZ+J8YfSuRJpBIK6ppEifuvbeGLUmiLrlA1TsMdqs2rIa1UJQNvEVO3mXodiSXr4V2IDLg== +"@oraichain/oraidex-contracts-sdk@^1.0.48": + version "1.0.49" + resolved "https://registry.yarnpkg.com/@oraichain/oraidex-contracts-sdk/-/oraidex-contracts-sdk-1.0.49.tgz#093221564552e92901c73f6043ce4dc72208d857" + integrity sha512-J15JR0+wueYMLMFjz/Omg5ADSKOmmTvsBstVf76NQjrvYpekzdlIGvoTIUCGjyf+DOdzu8MevOk5HDAnOrj3Fw== + "@oraichain/oraidex-universal-swap@1.0.97": version "1.0.97" resolved "https://registry.yarnpkg.com/@oraichain/oraidex-universal-swap/-/oraidex-universal-swap-1.0.97.tgz#b43148f7416482a7d0011b114d38daaa46533a8d" From 588e6fa1c56ef7bf4cf804797744554f1526f76f Mon Sep 17 00:00:00 2001 From: vuonghuuhung Date: Fri, 9 Aug 2024 17:20:15 +0700 Subject: [PATCH 14/19] update apr calculation --- src/libs/contractSingleton.ts | 14 ++--- .../Pool-V3/components/PoolList/index.tsx | 14 +++-- .../Pool-V3/hooks/useGetPoolLiqAndVol.ts | 3 +- .../Pool-V3/hooks/useGetPoolPositionInfo.ts | 45 ++++++++++++++ src/rest/graphClient.ts | 62 +++++++++++++++++++ 5 files changed, 124 insertions(+), 14 deletions(-) create mode 100644 src/pages/Pool-V3/hooks/useGetPoolPositionInfo.ts diff --git a/src/libs/contractSingleton.ts b/src/libs/contractSingleton.ts index 97d6b0497..97824f20e 100644 --- a/src/libs/contractSingleton.ts +++ b/src/libs/contractSingleton.ts @@ -663,9 +663,9 @@ export async function fetchPositionAprInfo( if (!isInRange) { return { - swapFee: feeAPR ? feeAPR : 0, + swapFee: feeAPR ?? 0, incentive: sumIncentivesApr, - total: feeAPR + total: feeAPR ?? 0 }; } @@ -683,9 +683,9 @@ export async function fetchPositionAprInfo( } return { - swapFee: feeAPR ? feeAPR : 0, + swapFee: feeAPR ?? 0, incentive: sumIncentivesApr, - total: sumIncentivesApr + (feeAPR ? feeAPR : 0) + total: sumIncentivesApr + (feeAPR ?? 0) }; } @@ -724,16 +724,16 @@ export async function fetchPoolAprInfo( const rewardInUsd = prices[token.coinGeckoId]; const totalPoolLiquidity = poolLiquidities[poolKeyToString(poolKey)]; const rewardPerYear = (rewardInUsd * Number(rewardsPerSec) * 86400 * 365) / 10 ** token.decimals; - if (totalPoolLiquidity) sumIncentivesApr += rewardPerYear / (totalPoolLiquidity * 0.25); + if (totalPoolLiquidity) sumIncentivesApr += rewardPerYear / totalPoolLiquidity; } poolAprs[poolKeyToString(poolKey)] = { - apr: sumIncentivesApr + (feeAPR ? feeAPR : 0), + apr: sumIncentivesApr + (feeAPR ?? 0), incentives: incentives.map((incentive) => { const token = oraichainTokens.find((token) => extractAddress(token) === parseAssetInfo(incentive.reward_token)); return token.denom.toUpperCase(); }), - swapFee: feeAPR ? feeAPR : 0, + swapFee: feeAPR ?? 0, incentivesApr: sumIncentivesApr }; } diff --git a/src/pages/Pool-V3/components/PoolList/index.tsx b/src/pages/Pool-V3/components/PoolList/index.tsx index bdbb65d9e..1835a9957 100644 --- a/src/pages/Pool-V3/components/PoolList/index.tsx +++ b/src/pages/Pool-V3/components/PoolList/index.tsx @@ -21,6 +21,7 @@ import useConfigReducer from 'hooks/useConfigReducer'; import LoadingBox from 'components/LoadingBox'; import { useGetFeeDailyData } from 'pages/Pool-V3/hooks/useGetFeeDailyData'; import { useGetPoolLiqAndVol } from 'pages/Pool-V3/hooks/useGetPoolLiqAndVol'; +import { useGetPoolPositionInfo } from 'pages/Pool-V3/hooks/useGetPoolPositionInfo'; const PoolList = () => { const { data: prices } = useCoinGeckoPrices(); @@ -28,6 +29,7 @@ const PoolList = () => { const [volumnePools, setVolumnePools] = useConfigReducer('volumnePools'); const [aprInfo, setAprInfo] = useConfigReducer('aprPools'); const [openTooltip, setOpenTooltip] = useState(false); + const [cachePrices] = useConfigReducer('coingecko'); const theme = useTheme(); @@ -38,8 +40,10 @@ const PoolList = () => { const [dataPool, setDataPool] = useState([...Array(0)]); const yesterdayIndex = Math.floor(Date.now() / (24 * 60 * 60 * 1000)) - 1; - const { feeDailyData, refetchfeeDailyData } = useGetFeeDailyData(yesterdayIndex); - const { poolLiquidities, poolVolume, refetchPoolLiqAndVol } = useGetPoolLiqAndVol(yesterdayIndex); + const { feeDailyData } = useGetFeeDailyData(yesterdayIndex); + const { poolLiquidities, poolVolume } = useGetPoolLiqAndVol(yesterdayIndex); + const { poolPositionInfo } = useGetPoolPositionInfo(prices); + // console.log({ poolPositionInfo }); useEffect(() => { (async () => { @@ -98,13 +102,13 @@ const PoolList = () => { const getAPRInfo = async () => { const poolKeys = dataPool.map((pool) => parsePoolKeyString(pool.poolKey)); - const res = await fetchPoolAprInfo(poolKeys, prices, liquidityPools, feeDailyData); + const res = await fetchPoolAprInfo(poolKeys, prices, poolPositionInfo, feeDailyData); setAprInfo(res); }; - if (dataPool.length && prices && liquidityPools) { + if (dataPool.length && prices && poolPositionInfo) { getAPRInfo(); } - }, [dataPool, prices, liquidityPools]); + }, [dataPool, prices, poolPositionInfo]); return (
diff --git a/src/pages/Pool-V3/hooks/useGetPoolLiqAndVol.ts b/src/pages/Pool-V3/hooks/useGetPoolLiqAndVol.ts index 5e7ae457b..c3778472f 100644 --- a/src/pages/Pool-V3/hooks/useGetPoolLiqAndVol.ts +++ b/src/pages/Pool-V3/hooks/useGetPoolLiqAndVol.ts @@ -1,6 +1,5 @@ import { useQuery } from '@tanstack/react-query'; -import { PoolFeeAndLiquidityDaily } from 'libs/contractSingleton'; -import { FeeDailyData, getFeeDailyData, getPoolsLiquidityAndVolume, PoolLiquidityAndVolume } from 'rest/graphClient'; +import { getPoolsLiquidityAndVolume, PoolLiquidityAndVolume } from 'rest/graphClient'; export const useGetPoolLiqAndVol = (dayIndex: number) => { const { data, refetch: refetchPoolLiqAndVol } = useQuery( diff --git a/src/pages/Pool-V3/hooks/useGetPoolPositionInfo.ts b/src/pages/Pool-V3/hooks/useGetPoolPositionInfo.ts new file mode 100644 index 000000000..c9ab22ae8 --- /dev/null +++ b/src/pages/Pool-V3/hooks/useGetPoolPositionInfo.ts @@ -0,0 +1,45 @@ +import { useQuery } from '@tanstack/react-query'; +import { CoinGeckoPrices } from 'hooks/useCoingecko'; +import { AmountDeltaResult, calculateAmountDelta, calculateSqrtPrice } from 'oraiswap-v3-test'; +import { getPoolPositionsInfo, PoolPositionsInfo } from 'rest/graphClient'; + +export const useGetPoolPositionInfo = (prices: CoinGeckoPrices) => { + const { data, refetch: refetchPoolPositionInfo } = useQuery( + ['pool-v3-pool-positions-info'], + () => getPoolPositionsInfo(), + { + refetchOnWindowFocus: true, + placeholderData: [], + cacheTime: 5 * 60 * 1000 + } + ); + + const poolPositionInfo: Record = {}; + data.forEach((item) => { + const inRangePositions = item.positions.nodes.filter( + (position) => Number(position.tickLower) <= Number(item.currentTick) && Number(position.tickUpper) >= Number(item.currentTick) + ); + let tokenXPrice = prices[item.tokenX.coingeckoId] ?? 0; + let tokenYPrice = prices[item.tokenY.coingeckoId] ?? 0; + let activeTvl = 0; + inRangePositions.forEach((position) => { + const res: AmountDeltaResult = calculateAmountDelta( + item.currentTick, + calculateSqrtPrice(item.currentTick), + BigInt(position.liquidity), + false, + position.tickUpper, + position.tickLower + ); + activeTvl += + Number(res.x / 10n ** BigInt(item.tokenX.decimals)) * tokenXPrice + + Number(res.y / 10n ** BigInt(item.tokenY.decimals)) * tokenYPrice; + }); + poolPositionInfo[item.id] = activeTvl; + }); + + return { + poolPositionInfo, + refetchPoolPositionInfo + }; +}; diff --git a/src/rest/graphClient.ts b/src/rest/graphClient.ts index 58974b441..5d1487074 100644 --- a/src/rest/graphClient.ts +++ b/src/rest/graphClient.ts @@ -161,3 +161,65 @@ export const getPoolsLiquidityAndVolume = async (dayIndex: number): Promise => { + try { + const document = gql` + { + query { + pools { + nodes { + id + currentTick + sqrtPrice + tokenX { + coingeckoId + decimals + } + tokenY { + coingeckoId + decimals + } + positions(filter: { status: { equalTo: true } }) { + nodes { + liquidity + tickLower + tickUpper + } + } + } + } + } + } + `; + const result = await graphqlClient.request(document); + console.log({ result }); + return result.query.pools.nodes || []; + } catch (error) { + console.log('error getPoolPositionsInfo', error); + return []; + } +}; From 5465f407e594b05278dd647e05e213345367c357 Mon Sep 17 00:00:00 2001 From: vuonghuuhung Date: Fri, 9 Aug 2024 17:44:14 +0700 Subject: [PATCH 15/19] fix dependency of use effect --- .../Pool-V3/components/PoolList/index.tsx | 43 +++++++++---------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/src/pages/Pool-V3/components/PoolList/index.tsx b/src/pages/Pool-V3/components/PoolList/index.tsx index 1835a9957..290287323 100644 --- a/src/pages/Pool-V3/components/PoolList/index.tsx +++ b/src/pages/Pool-V3/components/PoolList/index.tsx @@ -29,7 +29,6 @@ const PoolList = () => { const [volumnePools, setVolumnePools] = useConfigReducer('volumnePools'); const [aprInfo, setAprInfo] = useConfigReducer('aprPools'); const [openTooltip, setOpenTooltip] = useState(false); - const [cachePrices] = useConfigReducer('coingecko'); const theme = useTheme(); @@ -78,25 +77,27 @@ const PoolList = () => { useEffect(() => { (async () => { try { - if (dataPool.length) { + if (dataPool.length && poolLiquidities) { setLiquidityPools(poolLiquidities); - setVolumnePools(Object.keys(poolVolume).map((poolAddress) => { - return { - apy: 0, - poolAddress, - fee: 0, - volume24: poolVolume[poolAddress], - tokenX: null, - tokenY: null, - tvl: null - } - })); + setVolumnePools( + Object.keys(poolVolume).map((poolAddress) => { + return { + apy: 0, + poolAddress, + fee: 0, + volume24: poolVolume[poolAddress], + tokenX: null, + tokenY: null, + tvl: null + }; + }) + ); } } catch (error) { console.log('error: get liquidities', error); } })(); - }, [dataPool]); + }, [dataPool, poolLiquidities]); useEffect(() => { const getAPRInfo = async () => { @@ -262,11 +263,7 @@ const PoolItemTData = ({ item, theme, liquidity, volumn, aprInfo }) => { - {liquidity === 0 || liquidity ? ( - formatDisplayUsdt(liquidity) - ) : ( - loading - )} + {liquidity ? formatDisplayUsdt(liquidity) : loading} @@ -275,7 +272,7 @@ const PoolItemTData = ({ item, theme, liquidity, volumn, aprInfo }) => {
- {numberWithCommas(aprInfo.apr * 100, undefined, { maximumFractionDigits: 2 })}% + {numberWithCommas(aprInfo.apr * 100, undefined, { maximumFractionDigits: 2 })}% {
Swap fee - {numberWithCommas(aprInfo.swapFee * 100, undefined, { maximumFractionDigits: 2 })}% + {numberWithCommas(aprInfo.swapFee * 100, undefined, { maximumFractionDigits: 2 })}%
@@ -297,13 +294,13 @@ const PoolItemTData = ({ item, theme, liquidity, volumn, aprInfo }) => { - {numberWithCommas(aprInfo.incentivesApr * 100, undefined, { maximumFractionDigits: 2 })}% + {numberWithCommas(aprInfo.incentivesApr * 100, undefined, { maximumFractionDigits: 2 })}%
Total APR - {numberWithCommas(aprInfo.apr * 100, undefined, { maximumFractionDigits: 2 })}% + {numberWithCommas(aprInfo.apr * 100, undefined, { maximumFractionDigits: 2 })}%
From 6916eddcb89300e55b3361d420e17a4f572c655d Mon Sep 17 00:00:00 2001 From: vuonghuuhung Date: Fri, 9 Aug 2024 18:16:39 +0700 Subject: [PATCH 16/19] fix: fixed error infinity load --- .../Pool-V3/components/PoolList/index.tsx | 40 ++++++++----------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/src/pages/Pool-V3/components/PoolList/index.tsx b/src/pages/Pool-V3/components/PoolList/index.tsx index 290287323..58dc1d505 100644 --- a/src/pages/Pool-V3/components/PoolList/index.tsx +++ b/src/pages/Pool-V3/components/PoolList/index.tsx @@ -75,29 +75,23 @@ const PoolList = () => { }, [liquidityPools]); useEffect(() => { - (async () => { - try { - if (dataPool.length && poolLiquidities) { - setLiquidityPools(poolLiquidities); - setVolumnePools( - Object.keys(poolVolume).map((poolAddress) => { - return { - apy: 0, - poolAddress, - fee: 0, - volume24: poolVolume[poolAddress], - tokenX: null, - tokenY: null, - tvl: null - }; - }) - ); - } - } catch (error) { - console.log('error: get liquidities', error); - } - })(); - }, [dataPool, poolLiquidities]); + if (dataPool.length && poolLiquidities) { + setLiquidityPools(poolLiquidities); + setVolumnePools( + Object.keys(poolVolume).map((poolAddress) => { + return { + apy: 0, + poolAddress, + fee: 0, + volume24: poolVolume[poolAddress], + tokenX: null, + tokenY: null, + tvl: null + }; + }) + ); + } + }, [dataPool?.length, Object.values(poolLiquidities).length]); useEffect(() => { const getAPRInfo = async () => { From 6ec895dfe5352d83678e531de68064fa76f8eedb Mon Sep 17 00:00:00 2001 From: vuonghuuhung Date: Fri, 9 Aug 2024 19:57:11 +0700 Subject: [PATCH 17/19] fix load posiiton list --- src/pages/Pool-V3/components/PoolList/index.tsx | 2 +- src/pages/Pool-V3/index.tsx | 4 ++-- src/rest/graphClient.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pages/Pool-V3/components/PoolList/index.tsx b/src/pages/Pool-V3/components/PoolList/index.tsx index 58dc1d505..10b05ee81 100644 --- a/src/pages/Pool-V3/components/PoolList/index.tsx +++ b/src/pages/Pool-V3/components/PoolList/index.tsx @@ -257,7 +257,7 @@ const PoolItemTData = ({ item, theme, liquidity, volumn, aprInfo }) => { - {liquidity ? formatDisplayUsdt(liquidity) : loading} + {liquidity ? formatDisplayUsdt(liquidity) : (liquidity === 0 ? formatDisplayUsdt(0) : loading)} diff --git a/src/pages/Pool-V3/index.tsx b/src/pages/Pool-V3/index.tsx index b12835490..d931f3c59 100644 --- a/src/pages/Pool-V3/index.tsx +++ b/src/pages/Pool-V3/index.tsx @@ -11,7 +11,7 @@ import styles from './index.module.scss'; export enum PoolV3PageType { POOL = 'pools', POSITION = 'positions', - STAT = 'stats' + // STAT = 'stats' } type TabRender = { @@ -24,7 +24,7 @@ const listTab = Object.values(PoolV3PageType); const listTabRender: TabRender[] = [ { id: PoolV3PageType.POOL, value: 'Pools', content: PoolList }, { id: PoolV3PageType.POSITION, value: 'My positions', content: PositionList }, - { id: PoolV3PageType.STAT, value: 'Stats', content: WrappedStats } + // { id: PoolV3PageType.STAT, value: 'Stats', content: WrappedStats } ]; const PoolV3 = () => { diff --git a/src/rest/graphClient.ts b/src/rest/graphClient.ts index 5d1487074..dcd1e48f5 100644 --- a/src/rest/graphClient.ts +++ b/src/rest/graphClient.ts @@ -216,7 +216,7 @@ export const getPoolPositionsInfo = async (): Promise => { } `; const result = await graphqlClient.request(document); - console.log({ result }); + // console.log({ result }); return result.query.pools.nodes || []; } catch (error) { console.log('error getPoolPositionsInfo', error); From 533039aab01449b6fc785b53735f28d42013de96 Mon Sep 17 00:00:00 2001 From: vuonghuuhung Date: Fri, 9 Aug 2024 20:01:48 +0700 Subject: [PATCH 18/19] use sdk --- package.json | 2 +- src/libs/contractSingleton.ts | 4 ++-- .../components/CreatePosition/index.tsx | 2 +- .../components/NewPositionNoPool/index.tsx | 2 +- .../components/PriceRangePlot/utils.ts | 2 +- .../Pool-V3/components/TokenForm/index.tsx | 2 +- src/pages/Pool-V3/helpers/helper.ts | 2 +- src/pages/Pool-V3/hooks/useAddLiquidity.ts | 2 +- .../Pool-V3/hooks/useGetPoolPositionInfo.ts | 5 +++-- yarn.lock | 20 +++++++++---------- 10 files changed, 22 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index 806c24211..3085ca20a 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "ts-jest": "^29.1.1", "typed-scss-modules": "^7.1.4", "typescript": "^5.1.6", - "oraiswap-v3-test": "^0.1.6-beta1" + "@oraichain/oraiswap-v3": "0.1.5" }, "scripts": { "analyze": "source-map-explorer 'build/static/js/*.js'", diff --git a/src/libs/contractSingleton.ts b/src/libs/contractSingleton.ts index 97824f20e..66ee07c40 100644 --- a/src/libs/contractSingleton.ts +++ b/src/libs/contractSingleton.ts @@ -11,7 +11,7 @@ import { getLiquidityTicksLimit, getMaxTickmapQuerySize, OraiswapV3Handler -} from 'oraiswap-v3-test'; +} from '@oraichain/oraiswap-v3'; import { network } from 'config/networks'; import { AssetInfo, @@ -204,7 +204,7 @@ export default class SingletonOraiswapV3 { public static async loadCosmwasmClient() { if (!this._cosmwasmClient) { - this._cosmwasmClient = await CosmWasmClient.connect(network.rpc);; + this._cosmwasmClient = await CosmWasmClient.connect(network.rpc); } } diff --git a/src/pages/Pool-V3/components/CreatePosition/index.tsx b/src/pages/Pool-V3/components/CreatePosition/index.tsx index 3dde3e62c..99f6cdd33 100644 --- a/src/pages/Pool-V3/components/CreatePosition/index.tsx +++ b/src/pages/Pool-V3/components/CreatePosition/index.tsx @@ -21,7 +21,7 @@ import { getMaxTick, getMinTick, Price -} from 'oraiswap-v3-test'; +} from '@oraichain/oraiswap-v3'; import { useEffect, useMemo, useRef, useState } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; import NewPositionNoPool from '../NewPositionNoPool'; diff --git a/src/pages/Pool-V3/components/NewPositionNoPool/index.tsx b/src/pages/Pool-V3/components/NewPositionNoPool/index.tsx index 46ac338c2..b1a475aa3 100644 --- a/src/pages/Pool-V3/components/NewPositionNoPool/index.tsx +++ b/src/pages/Pool-V3/components/NewPositionNoPool/index.tsx @@ -8,7 +8,7 @@ import { ReactComponent as PlusIcon } from 'assets/icons/plus.svg'; import { ReactComponent as MinusIcon } from 'assets/icons/minus.svg'; import { ReactComponent as WarningIcon } from 'assets/icons/warning-fill-ic.svg'; import classNames from 'classnames'; -import { getMaxTick, getMinTick, Price } from 'oraiswap-v3-test'; +import { getMaxTick, getMinTick, Price } from '@oraichain/oraiswap-v3'; import { useEffect, useMemo, useRef, useState } from 'react'; import { calcPrice, diff --git a/src/pages/Pool-V3/components/PriceRangePlot/utils.ts b/src/pages/Pool-V3/components/PriceRangePlot/utils.ts index 97df7ff15..20fb1b388 100644 --- a/src/pages/Pool-V3/components/PriceRangePlot/utils.ts +++ b/src/pages/Pool-V3/components/PriceRangePlot/utils.ts @@ -10,7 +10,7 @@ import { Tick, Liquidity, getPriceScale -} from 'oraiswap-v3-test'; +} from '@oraichain/oraiswap-v3'; import { TokenItemType } from '@oraichain/oraidex-common'; import SingletonOraiswapV3, { Token } from 'libs/contractSingleton'; import { PlotTickData } from './PriceRangePlot'; diff --git a/src/pages/Pool-V3/components/TokenForm/index.tsx b/src/pages/Pool-V3/components/TokenForm/index.tsx index afed7704f..9b3d69d77 100644 --- a/src/pages/Pool-V3/components/TokenForm/index.tsx +++ b/src/pages/Pool-V3/components/TokenForm/index.tsx @@ -13,7 +13,7 @@ import useTheme from 'hooks/useTheme'; import { ALL_FEE_TIERS_DATA } from 'libs/contractSingleton'; import { InitPositionData } from 'pages/Pool-V3/helpers/helper'; import useAddLiquidity from 'pages/Pool-V3/hooks/useAddLiquidity'; -import { calculateSqrtPrice, newPoolKey } from 'oraiswap-v3-test'; +import { calculateSqrtPrice, newPoolKey } from '@oraichain/oraiswap-v3'; import { Dispatch, SetStateAction, useEffect, useMemo, useState } from 'react'; import NumberFormat from 'react-number-format'; import { useSelector } from 'react-redux'; diff --git a/src/pages/Pool-V3/helpers/helper.ts b/src/pages/Pool-V3/helpers/helper.ts index bd0e14b73..4e834e276 100644 --- a/src/pages/Pool-V3/helpers/helper.ts +++ b/src/pages/Pool-V3/helpers/helper.ts @@ -16,7 +16,7 @@ import { getSqrtPriceDenominator, getTickAtSqrtPrice, calculateFee as wasmCalculateFee -} from 'oraiswap-v3-test'; +} from '@oraichain/oraiswap-v3'; import { getIconPoolData } from './format'; import { network } from 'config/networks'; import { CoinGeckoPrices } from 'hooks/useCoingecko'; diff --git a/src/pages/Pool-V3/hooks/useAddLiquidity.ts b/src/pages/Pool-V3/hooks/useAddLiquidity.ts index f08b5040a..ed9081348 100644 --- a/src/pages/Pool-V3/hooks/useAddLiquidity.ts +++ b/src/pages/Pool-V3/hooks/useAddLiquidity.ts @@ -10,7 +10,7 @@ import { isNativeToken } from '../helpers/helper'; -import { newPoolKey } from 'oraiswap-v3-test'; +import { newPoolKey } from '@oraichain/oraiswap-v3'; import { getCosmWasmClient } from 'libs/cosmjs'; import { network } from 'config/networks'; diff --git a/src/pages/Pool-V3/hooks/useGetPoolPositionInfo.ts b/src/pages/Pool-V3/hooks/useGetPoolPositionInfo.ts index c9ab22ae8..504cd4e0b 100644 --- a/src/pages/Pool-V3/hooks/useGetPoolPositionInfo.ts +++ b/src/pages/Pool-V3/hooks/useGetPoolPositionInfo.ts @@ -1,6 +1,6 @@ import { useQuery } from '@tanstack/react-query'; import { CoinGeckoPrices } from 'hooks/useCoingecko'; -import { AmountDeltaResult, calculateAmountDelta, calculateSqrtPrice } from 'oraiswap-v3-test'; +import { AmountDeltaResult, calculateAmountDelta, calculateSqrtPrice } from '@oraichain/oraiswap-v3'; import { getPoolPositionsInfo, PoolPositionsInfo } from 'rest/graphClient'; export const useGetPoolPositionInfo = (prices: CoinGeckoPrices) => { @@ -17,7 +17,8 @@ export const useGetPoolPositionInfo = (prices: CoinGeckoPrices) => { const poolPositionInfo: Record = {}; data.forEach((item) => { const inRangePositions = item.positions.nodes.filter( - (position) => Number(position.tickLower) <= Number(item.currentTick) && Number(position.tickUpper) >= Number(item.currentTick) + (position) => + Number(position.tickLower) <= Number(item.currentTick) && Number(position.tickUpper) >= Number(item.currentTick) ); let tokenXPrice = prices[item.tokenX.coingeckoId] ?? 0; let tokenYPrice = prices[item.tokenY.coingeckoId] ?? 0; diff --git a/yarn.lock b/yarn.lock index d65ef001c..66f5c2b77 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4628,6 +4628,16 @@ resolved "https://registry.yarnpkg.com/@oraichain/oraiswap-v3-wasm/-/oraiswap-v3-wasm-0.1.0.tgz#aff12c614635ad2c4343ef62d8497e41d52408f4" integrity sha512-87YMqhBVgVJoX5BM+AeGc13I0dTR/hIHg6sIh+j9M/T0OecaCZR4O3h+CiaBKrK9Eej0gccv9zI02FwjAggAfw== +"@oraichain/oraiswap-v3@0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@oraichain/oraiswap-v3/-/oraiswap-v3-0.1.5.tgz#e833fc2ebc1b40dca81d32004900e4fe7d56ea01" + integrity sha512-tXRmXpx/sqZOJETzyY3c22/j8sr+JxfxHcJ/TF/vxDQGLw6EpxiAGhAcJjxLerOUqOJD4u0/mi85xk7GALXk/w== + dependencies: + "@cosmjs/cosmwasm-stargate" "^0.31.0" + "@oraichain/oraidex-common" latest + "@oraichain/oraidex-contracts-sdk" "^1.0.48" + "@oraichain/oraiswap-v3-wasm" "^0.1.0" + "@oraichain/wasm-json-toolkit@^1.0.24": version "1.0.24" resolved "https://registry.yarnpkg.com/@oraichain/wasm-json-toolkit/-/wasm-json-toolkit-1.0.24.tgz#e9a431560e8e946fbb7ec257e5f13d9320ffd23a" @@ -14931,16 +14941,6 @@ ora@^5.4.1: strip-ansi "^6.0.0" wcwidth "^1.0.1" -oraiswap-v3-test@^0.1.6-beta1: - version "0.1.6-beta1" - resolved "https://registry.yarnpkg.com/oraiswap-v3-test/-/oraiswap-v3-test-0.1.6-beta1.tgz#3314ba268a00bfc569172208620c239c27c5d439" - integrity sha512-O3FCTF1iposB2HoFNJxYY4B2sXcsIisLKsSsgprG7L9aQnBdxx24ADhjR2xlcE1ix0fsbjcak4N1bgKCOSmoCw== - dependencies: - "@cosmjs/cosmwasm-stargate" "^0.31.0" - "@oraichain/oraidex-common" latest - "@oraichain/oraidex-contracts-sdk" "^1.0.48" - "@oraichain/oraiswap-v3-wasm" "^0.1.0" - os-browserify@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" From 329e05b679a15961070ca7f4647045fef1d36dee Mon Sep 17 00:00:00 2001 From: vuonghuuhung Date: Sat, 10 Aug 2024 11:35:09 +0700 Subject: [PATCH 19/19] catch get pool list --- src/libs/contractSingleton.ts | 111 +++++++++++------- .../Pool-V3/components/PoolList/index.tsx | 4 +- src/rest/graphClient.ts | 31 ++++- 3 files changed, 103 insertions(+), 43 deletions(-) diff --git a/src/libs/contractSingleton.ts b/src/libs/contractSingleton.ts index 66ee07c40..65b4cbbd0 100644 --- a/src/libs/contractSingleton.ts +++ b/src/libs/contractSingleton.ts @@ -10,7 +10,8 @@ import { getChunkSize, getLiquidityTicksLimit, getMaxTickmapQuerySize, - OraiswapV3Handler + OraiswapV3Handler, + parsePoolKey } from '@oraichain/oraiswap-v3'; import { network } from 'config/networks'; import { @@ -38,7 +39,7 @@ import { CoinGeckoId } from '@oraichain/oraidex-common'; import { extractAddress, extractDenom } from 'pages/Pool-V3/components/PriceRangePlot/utils'; import { oraichainTokens } from 'config/bridgeTokens'; import { calculateTokenAmounts } from 'pages/Pool-V3/helpers/helper'; -import { getFeeDailyData } from 'rest/graphClient'; +import { getFeeDailyData, getPools } from 'rest/graphClient'; export const ALL_FEE_TIERS_DATA: FeeTier[] = [ { fee: 100000000, tick_spacing: 1 }, @@ -265,7 +266,37 @@ export default class SingletonOraiswapV3 { public static async getPools(): Promise { await this.loadHandler(); - return await this._handler.getPools(); + try { + return await this._handler.getPools(); + } catch (error) { + const pools = await getPools(); + return pools.map((pool) => { + const poolKey = parsePoolKey(pool.id); + return { + pool_key: { + token_x: poolKey.token_x, + token_y: poolKey.token_y, + fee_tier: { + fee: poolKey.fee_tier.fee, + tick_spacing: poolKey.fee_tier.tick_spacing + } + }, + pool: { + liquidity: pool.liquidity, + sqrt_price: calculateSqrtPrice(pool.currentTick), + current_tick_index: pool.currentTick, + fee_growth_global_x: "0", + fee_growth_global_y: "0", + fee_protocol_token_x: "0", + fee_protocol_token_y: "0", + fee_receiver: "", + last_timestamp: Date.now(), + start_timestamp: 0, + incentives: [] + } + }; + }); + } } public static async getIncentivesPosition(positionIndex: number, ownerId: string): Promise { @@ -413,42 +444,42 @@ export default class SingletonOraiswapV3 { }; }; - public static async queryPosition(): Promise { - const positionInfo: PositionInfo[] = []; + // public static async queryPosition(): Promise { + // const positionInfo: PositionInfo[] = []; - const allPools: PoolWithPoolKey[] = await this.getPools(); + // const allPools: PoolWithPoolKey[] = await this.getPools(); - const poolList: Record = {}; - allPools.forEach((pool) => { - poolList[poolKeyToString(pool.pool_key)] = pool; - }); + // const poolList: Record = {}; + // allPools.forEach((pool) => { + // poolList[poolKeyToString(pool.pool_key)] = pool; + // }); - await this.loadHandler(); - const allPosition = await this._handler.allPositions(); - - for (const position of allPosition) { - const positionData = position; - const poolKey = position.pool_key; - const res = calculateTokenAmounts(poolList[poolKeyToString(poolKey)].pool as any, position as any); - - const positionInfoData: PositionInfo = { - id: `${poolKeyToString(poolKey)}-${positionData.token_id}`, - tokenId: positionData.token_id, - poolId: poolKeyToString(poolKey), - status: true, - liquidity: BigInt(positionData.liquidity).toString(), - tickLower: positionData.lower_tick_index.toString(), - tickUpper: positionData.upper_tick_index.toString(), - principalAmountX: res.x.toString(), - principalAmountY: res.y.toString(), - createdAt: BigInt(Date.now()).toString() - }; + // await this.loadHandler(); + // const allPosition = await this._handler.allPositions(); - positionInfo.push(positionInfoData); - } + // for (const position of allPosition) { + // const positionData = position; + // const poolKey = position.pool_key; + // const res = calculateTokenAmounts(poolList[poolKeyToString(poolKey)].pool as any, position as any); - return positionInfo; - } + // const positionInfoData: PositionInfo = { + // id: `${poolKeyToString(poolKey)}-${positionData.token_id}`, + // tokenId: positionData.token_id, + // poolId: poolKeyToString(poolKey), + // status: true, + // liquidity: BigInt(positionData.liquidity).toString(), + // tickLower: positionData.lower_tick_index.toString(), + // tickUpper: positionData.upper_tick_index.toString(), + // principalAmountX: res.x.toString(), + // principalAmountY: res.y.toString(), + // createdAt: BigInt(Date.now()).toString() + // }; + + // positionInfo.push(positionInfoData); + // } + + // return positionInfo; + // } public static getPoolLiquidities = async ( pools: PoolWithPoolKey[], @@ -663,9 +694,9 @@ export async function fetchPositionAprInfo( if (!isInRange) { return { - swapFee: feeAPR ?? 0, + swapFee: feeAPR ? feeAPR : 0, incentive: sumIncentivesApr, - total: feeAPR ?? 0 + total: feeAPR ? feeAPR : 0 }; } @@ -683,9 +714,9 @@ export async function fetchPositionAprInfo( } return { - swapFee: feeAPR ?? 0, + swapFee: feeAPR ? feeAPR : 0, incentive: sumIncentivesApr, - total: sumIncentivesApr + (feeAPR ?? 0) + total: sumIncentivesApr + (feeAPR ? feeAPR : 0) }; } @@ -728,12 +759,12 @@ export async function fetchPoolAprInfo( } poolAprs[poolKeyToString(poolKey)] = { - apr: sumIncentivesApr + (feeAPR ?? 0), + apr: sumIncentivesApr + (feeAPR ? feeAPR : 0), incentives: incentives.map((incentive) => { const token = oraichainTokens.find((token) => extractAddress(token) === parseAssetInfo(incentive.reward_token)); return token.denom.toUpperCase(); }), - swapFee: feeAPR ?? 0, + swapFee: feeAPR ? feeAPR : 0, incentivesApr: sumIncentivesApr }; } diff --git a/src/pages/Pool-V3/components/PoolList/index.tsx b/src/pages/Pool-V3/components/PoolList/index.tsx index 10b05ee81..cc7496fba 100644 --- a/src/pages/Pool-V3/components/PoolList/index.tsx +++ b/src/pages/Pool-V3/components/PoolList/index.tsx @@ -100,10 +100,10 @@ const PoolList = () => { const res = await fetchPoolAprInfo(poolKeys, prices, poolPositionInfo, feeDailyData); setAprInfo(res); }; - if (dataPool.length && prices && poolPositionInfo) { + if (dataPool.length && prices && poolPositionInfo.length) { getAPRInfo(); } - }, [dataPool, prices, poolPositionInfo]); + }, [dataPool.length, prices, poolPositionInfo.length]); return (
diff --git a/src/rest/graphClient.ts b/src/rest/graphClient.ts index dcd1e48f5..18c4de791 100644 --- a/src/rest/graphClient.ts +++ b/src/rest/graphClient.ts @@ -181,7 +181,7 @@ export type PoolPositionsInfo = { decimals: number; }; positions: { - nodes: PositionInfo[]; + nodes: PositionInfo[]; }; }; @@ -223,3 +223,32 @@ export const getPoolPositionsInfo = async (): Promise => { return []; } }; + +export type Pool = { + id: string; + currentTick: number; + liquidity: string; +}; + +export const getPools = async (): Promise => { + try { + const document = gql` + { + query { + pools { + nodes { + id + currentTick + liquidity + } + } + } + } + `; + const result = await graphqlClient.request(document); + return result.query.pools.nodes || []; + } catch (error) { + console.log('error getPools', error); + return []; + } +};