diff --git a/src/components/layout/SwapRoutes.tsx b/src/components/layout/SwapRoutes.tsx
index 740f0d24a..879d08bec 100644
--- a/src/components/layout/SwapRoutes.tsx
+++ b/src/components/layout/SwapRoutes.tsx
@@ -15,7 +15,11 @@ import { toRealSymbol } from '../../utils/token';
import { EstimateSwapView } from 'src/services/swap';
-import { getPoolAllocationPercents, percent } from '../../utils/numbers';
+import {
+ getPoolAllocationPercents,
+ percent,
+ getRouteAllocationPercents,
+} from '../../utils/numbers';
import { Pool } from '../../services/pool';
import { FaAngleUp, FaAngleDown } from '../reactIcons';
import { Card } from '../card/Card';
@@ -72,8 +76,14 @@ import { displayNumberToAppropriateDecimals } from '../../services/commonV3';
import { numberWithCommas } from '../../pages/Orderly/utiles';
import { get_pool_name, openUrl } from '../../services/commonV3';
import getConfigV2 from '../../services/configV2';
+
import { REF_FI_BEST_MARKET_ROUTE } from '../../state/swap';
import { PolygonRight } from '../../pages/Orderly/components/Common/Icons';
+import {
+ IEstimateSwapServerView,
+ IServerRoute,
+ getTokensOfRoute,
+} from '../../services/smartRouterFromServer';
const configV2 = getConfigV2();
export const GetPriceImpact = (
value: string,
@@ -717,16 +727,23 @@ export const getDexAction = (market: SwapMarket) => {
export const SwapRoute = ({
route,
- p,
market,
+ routeServer,
}: {
- route: EstimateSwapView[];
- p: string;
- tokenIn: TokenMetadata;
- tokenOut: TokenMetadata;
+ route?: EstimateSwapView[];
market: SwapMarket;
+ routeServer?: IServerRoute;
}) => {
- const tokens = route[0].tokens;
+ const [tokens, setTokens] = useState([]);
+ useEffect(() => {
+ if (route) {
+ setTokens(route[0].tokens);
+ } else if (routeServer) {
+ getTokensOfRoute(routeServer).then((res) => {
+ setTokens(res);
+ });
+ }
+ }, [route, routeServer]);
const { swapType } = useContext(SwapProContext);
@@ -771,6 +788,7 @@ export const SwapRoute = ({
tokens.map((t, i) => {
return (
7
? 'xsm:overflow-hidden'
@@ -802,9 +820,11 @@ export const SwapRoute = ({
export const SwapRouteMoreThan2 = ({
market,
trade,
+ throughPools,
}: {
market: SwapMarket;
trade: ExchangeEstimate;
+ throughPools: number;
}) => {
const intl = useIntl();
@@ -846,7 +866,7 @@ export const SwapRouteMoreThan2 = ({
id: 'steps_in_the_route_zh',
})}
- {trade.estimates.length}
+ {throughPools}
-
+
{toRealSymbol(token.symbol)}
@@ -1742,7 +1762,7 @@ export const RightBracket = ({ size }: { size: number }) => {
@@ -1754,7 +1774,7 @@ export const LeftBracket = ({ size }: { size: number }) => {
@@ -1770,6 +1790,47 @@ export const TradeRoute = ({
tokenIn: TokenMetadata;
tokenOut: TokenMetadata;
}) => {
+ const [estimatesServerUI, setEstimatesServerUI] =
+ useState();
+ const { estimates, estimatesServer } = trade || {};
+ const identicalRoutes = estimates
+ ? separateRoutes(estimates, estimates[estimates.length - 1].outputToken)
+ : [];
+
+ const pools = identicalRoutes.map((r) => r[0]).map((hub) => hub.pool);
+ useEffect(() => {
+ if (estimatesServer) {
+ getTokensDataOfEstimatesServer();
+ } else {
+ setEstimatesServerUI(undefined);
+ }
+ }, [JSON.stringify(estimatesServer || {})]);
+ async function getTokensDataOfEstimatesServer() {
+ const pending = estimatesServer.routes.map((route) =>
+ getTokensOfRoute(route)
+ );
+ const tokens_of_routes = await Promise.all(pending);
+ estimatesServer.routes.map((route, index) => {
+ route.tokens = tokens_of_routes[index];
+ });
+ setEstimatesServerUI(estimatesServer);
+ }
+ const percents = useMemo(() => {
+ try {
+ return getPoolAllocationPercents(pools);
+ } catch (error) {
+ if (identicalRoutes.length === 0) return ['100'];
+ else return identicalRoutes.map((r) => r[0].percent);
+ }
+ }, [identicalRoutes, pools]);
+ const percentsServer = useMemo(() => {
+ const routes = estimatesServer?.routes || [];
+ try {
+ return getRouteAllocationPercents(routes);
+ } catch (error) {
+ return ['100'];
+ }
+ }, [(estimatesServer?.routes || []).length]);
if (!tokenIn || !tokenOut) return null;
if (!trade || !trade?.availableRoute || tokenIn?.id === tokenOut?.id) {
@@ -1801,70 +1862,102 @@ export const TradeRoute = ({
);
}
-
- const { estimates } = trade;
-
- const { market } = trade;
-
- const identicalRoutes = separateRoutes(
- estimates,
- estimates[estimates.length - 1].outputToken
- );
-
- const pools = identicalRoutes.map((r) => r[0]).map((hub) => hub.pool);
-
- const percents = useMemo(() => {
- try {
- return getPoolAllocationPercents(pools);
- } catch (error) {
- if (identicalRoutes.length === 0) return ['100'];
- else return identicalRoutes.map((r) => r[0].percent);
- }
- }, [identicalRoutes, pools]);
-
+ const routeLength =
+ identicalRoutes.length || trade.estimatesServer?.routes?.length;
return (
-
-
- {identicalRoutes.map((route, j) => {
- return (
-
-
{percents[j]}%
+
+ {/* from script routes */}
+ {trade.estimates ? (
+
+ {identicalRoutes.map((route, j) => {
+ return (
-
- {route[0].tokens
- .slice(1, route[0].tokens.length)
- .map((t, i) => {
+ >
+
{percents[j]}%
+
+
+ {route[0].tokens
+ .slice(1, route[0].tokens.length)
+ .map((t, i) => {
+ return (
+ <>
+
+ {t.id !==
+ route[0].tokens[route[0].tokens.length - 1]?.id && (
+
+ )}
+ >
+ );
+ })}
+
+
+
+
+ );
+ })}
+
+ ) : null}
+
+ {/* from server routes */}
+ {estimatesServerUI ? (
+
+ {estimatesServerUI.routes.map((route, j) => {
+ const { pools, tokens } = route;
+ return (
+
+
+ {percentsServer[j]}%
+
+
+
+ {tokens?.slice(1, tokens.length).map((t, i) => {
return (
<>
- {t.id !==
- route[0].tokens[route[0].tokens.length - 1]?.id && (
+ {t.id !== tokens[tokens.length - 1]?.id && (
@@ -1872,14 +1965,16 @@ export const TradeRoute = ({
>
);
})}
+
+
+
+ );
+ })}
+
+ ) : null}
-
-
- );
- })}
-
-
+
@@ -1900,7 +1995,7 @@ export const TradeRouteModal = (
/>
}
{...props}
- customWidth={isMobile() ? '95vw' : '700px'}
+ customWidth={isMobile() ? '95vw' : '800px'}
>
r[0]).map((hub) => hub.pool);
-
- const percents = useMemo(() => {
- try {
- return getPoolAllocationPercents(pools);
- } catch (error) {
- if (identicalRoutes.length === 0) return ['100'];
- else return identicalRoutes.map((r) => r[0].percent);
- }
- }, [identicalRoutes, pools]);
-
const [showRouteDetail, setShowRouteDetail] = useState(false);
-
+ const { estimates, tokenIn, tokenOut, market, estimatesServer } = trade;
+ const { swapType } = useContext(SwapProContext);
+ if (!estimates && !estimatesServer) return null;
+ const identicalRoutes = estimates
+ ? separateRoutes(estimates, estimates[estimates.length - 1].outputToken)
+ : [];
+ const estimatesServerRoutes = estimatesServer?.routes || [];
+ let throughPools = 0;
+ if (estimatesServer) {
+ throughPools = estimatesServer.routes
+ .reduce((acc, cur) => {
+ return acc.plus(cur.pools.length);
+ }, Big(0))
+ .toNumber();
+ } else if (estimates) {
+ throughPools = estimates.length;
+ }
+ const isMoreThan2 =
+ identicalRoutes?.length > 1 || estimatesServer?.routes?.length > 1;
return (
{swapType === SWAP_TYPE.LITE ? (
@@ -351,20 +347,19 @@ export function AutoRouter({ trade }: { trade: ExchangeEstimate }) {
}
}}
>
- {trade.estimates.length > 2 ? (
-
- ) : (
- identicalRoutes.map((route, index) => (
-
- ))
- )}
+ {isMoreThan2 ? (
+
+ ) : null}
+ {!isMoreThan2 && identicalRoutes.length > 0 ? (
+
+ ) : null}
+ {!isMoreThan2 && estimatesServerRoutes.length > 0 ? (
+
+ ) : null}
= ({ children }) => {
if (!selector) {
return;
}
-
const subscription = selector.store.observable
.pipe(
map((state) => state.accounts),
@@ -242,6 +242,15 @@ export const WalletSelectorContextProvider: React.FC = ({ children }) => {
return () => subscription.unsubscribe();
}, [selector, accountId]);
+ useEffect(() => {
+ const selectedWalletId = selector?.store?.getState()?.selectedWalletId;
+ if (accountId && selectedWalletId) {
+ addUserWallet({
+ account_id: accountId,
+ wallet_address: selectedWalletId,
+ });
+ }
+ }, [selector?.store?.getState()?.selectedWalletId, accountId]);
const getAllKeys = async (accountId: string) => {
const account = await near.account(accountId);
diff --git a/src/pages/SwapPage.tsx b/src/pages/SwapPage.tsx
index 6bc777951..e51c4629b 100644
--- a/src/pages/SwapPage.tsx
+++ b/src/pages/SwapPage.tsx
@@ -36,6 +36,7 @@ import OrderlyAirDropPop from '../components/orderlyAirdrop/index';
import OrderlyAirDropPopMobile from '../components/orderlyAirdropMobile/index';
import { useOrderlyGuidePopStore } from '../stores/orderlyGuidePop';
import { isMobile } from 'src/utils/device';
+import { IEstimateSwapServerView } from '~src/services/smartRouterFromServer';
export const SWAP_MODE_KEY = 'SWAP_MODE_VALUE';
@@ -71,6 +72,7 @@ export type SwapContractType =
export interface ExchangeEstimate {
estimates?: EstimateSwapView[];
+ estimatesServer?: IEstimateSwapServerView;
fee?: number;
priceImpact?: string;
minAmountOut?: string;
diff --git a/src/services/config.ts b/src/services/config.ts
index af9ba52e8..aeefe0e12 100644
--- a/src/services/config.ts
+++ b/src/services/config.ts
@@ -149,8 +149,8 @@ export default function getConfig(
explorerUrl: 'https://nearblocks.io',
pikespeakUrl: 'https://pikespeak.ai',
nearExplorerUrl: 'https://explorer.near.org/',
- indexerUrl: 'https://api.ref.finance',
- // indexerUrl: 'https://apiself.cclp.finance',
+ // indexerUrl: 'https://api.ref.finance',
+ indexerUrl: 'https://mainnet-indexer.ref-finance.com',
sodakiApiUrl: 'https://api.stats.ref.finance/api',
newSodakiApiUrl: 'https://api.data-service.ref.finance/api',
txIdApiUrl: 'https://api3.nearblocks.io',
diff --git a/src/services/indexer.ts b/src/services/indexer.ts
index 770efa612..a5293eb87 100644
--- a/src/services/indexer.ts
+++ b/src/services/indexer.ts
@@ -1174,3 +1174,15 @@ export const getTokens = async () => {
return tokens;
});
};
+export const addUserWallet = async (params) => {
+ return await fetch(config.indexerUrl + '/add-user-wallet', {
+ method: 'POST',
+ headers: {
+ 'Content-type': 'application/json; charset=UTF-8',
+ ...getAuthenticationHeaders('/add-user-wallet'),
+ },
+ body: JSON.stringify(params),
+ }).catch(async (res) => {
+ console.log('add user wallet failed', res);
+ });
+};
diff --git a/src/services/pool.ts b/src/services/pool.ts
index 8a853e363..07a81f9c2 100644
--- a/src/services/pool.ts
+++ b/src/services/pool.ts
@@ -462,6 +462,83 @@ export const getPoolsByTokens = async ({
});
return { filteredPools, pool_protocol };
};
+export const getAllPoolsByTokens = async (): Promise<{
+ filteredPools: Pool[];
+}> => {
+ let pools;
+
+ const cachePools = async (pools: any) => {
+ await db.cachePoolsByTokens(
+ pools.filter(filterBlackListPools).filter((p: any) => isNotStablePool(p))
+ );
+ };
+ try {
+ const cachedPoolProtocol = sessionStorage.getItem(REF_FI_POOL_PROTOCOL);
+
+ if (cachedPoolProtocol === 'rpc') {
+ pools = await db.getAllPoolsTokens();
+
+ if (!pools || pools.length === 0) {
+ pools = await fetchPoolsRPC();
+ await cachePools(pools);
+ }
+ } else {
+ const poolsRaw = await db.queryTopPools();
+ if (poolsRaw && poolsRaw?.length > 0) {
+ pools = poolsRaw.map((p) => {
+ const parsedP = parsePool({
+ ...p,
+ share: p.shares_total_supply,
+ id: Number(p.id),
+ tvl: Number(p.tvl),
+ });
+
+ return {
+ ...parsedP,
+ Dex: 'ref',
+ };
+ });
+ } else {
+ const poolsRaw = await fetchPoolsIndexer();
+
+ await db.cacheTopPools(poolsRaw);
+
+ pools = poolsRaw.map((p: any) => {
+ return {
+ ...parsePool(p),
+ Dex: 'ref',
+ };
+ });
+
+ await cachePools(pools);
+ }
+ }
+ } catch (error) {
+ const { pools: poolsRaw, protocol } = await fetchTopPools();
+
+ if (protocol === 'indexer') {
+ await db.cacheTopPools(poolsRaw);
+ pools = poolsRaw.map((p: any) => {
+ return {
+ ...parsePool(p),
+ Dex: 'ref',
+ };
+ });
+ sessionStorage.setItem(REF_FI_POOL_PROTOCOL, 'indexer');
+ } else {
+ pools = poolsRaw;
+ sessionStorage.setItem(REF_FI_POOL_PROTOCOL, 'rpc');
+ }
+ await cachePools(pools);
+ await cacheAllDCLPools();
+ }
+ const filteredPools = pools
+ .filter(filterBlackListPools)
+ .filter((pool: any) => {
+ return isNotStablePool(pool);
+ });
+ return { filteredPools };
+};
export const getPoolsByTokensAurora = async ({
tokenInId,
@@ -542,12 +619,11 @@ export const getPoolsByTokensAurora = async ({
return filtered_pools;
};
-export const getRefPoolsByToken1ORToken2 = async (
- tokenId1: string,
- tokenId2: string
-) => {
- return await db.queryPoolsByTokens2(tokenId1, tokenId2);
- //return await db.poolsTokens;
+export const getRefPoolsByToken1ORToken2 = async () => {
+ return await db.queryPoolsByTokens2();
+};
+export const getRefPoolsByToken1ORToken2Parsed = async () => {
+ return await db.getAllPoolsTokens();
};
export const getPool = async (id: number): Promise => {
diff --git a/src/services/smartRouterFromServer.ts b/src/services/smartRouterFromServer.ts
new file mode 100644
index 000000000..307119b9d
--- /dev/null
+++ b/src/services/smartRouterFromServer.ts
@@ -0,0 +1,226 @@
+import Big from 'big.js';
+import {
+ toNonDivisibleNumber,
+ scientificNotationToString,
+ calculateMarketPrice,
+} from '../utils/numbers';
+import { TokenMetadata, ftGetTokenMetadata } from './ft-contract';
+import { getAllPoolsByTokens, getAllStablePoolsFromCache, Pool } from './pool';
+import { isStablePool } from '../services/near';
+export interface IEstimateSwapServerView {
+ amount_in: string;
+ amount_out: string;
+ contract_in: string;
+ contract_out: string;
+ routes: IServerRoute[];
+ contract?: string;
+}
+export interface IServerRoute {
+ amount_in: string;
+ min_amount_out: string;
+ pools: IServerPool[];
+ tokens?: TokenMetadata[];
+}
+export interface IServerPool {
+ amount_in: string;
+ min_amount_out: string;
+ pool_id: string | number;
+ token_in: string;
+ token_out: string;
+}
+
+export const estimateSwapFromServer = async ({
+ tokenIn,
+ tokenOut,
+ amountIn,
+ slippage,
+ supportLedger,
+}) => {
+ const timeoutDuration = 5000;
+ const controller = new AbortController();
+ const env = process.env.REACT_APP_NEAR_ENV;
+ const timeOutId = setTimeout(() => {
+ controller.abort();
+ }, timeoutDuration);
+ const domain =
+ env === 'pub-testnet'
+ ? 'smartroutertest.refburrow.top'
+ : 'smartrouter.ref.finance';
+ const resultFromServer = await fetch(
+ `https://${domain}/findPath?amountIn=${amountIn}&tokenIn=${
+ tokenIn.id
+ }&tokenOut=${tokenOut.id}&pathDeep=${supportLedger ? 1 : 3}&slippage=${
+ Number(slippage) / 100
+ }`,
+ {
+ signal: controller.signal,
+ }
+ )
+ .then((res) => {
+ return res.json();
+ })
+ .finally(() => {
+ clearTimeout(timeOutId);
+ });
+ return resultFromServer;
+};
+
+export async function getAvgFeeFromServer({
+ estimatesFromServer,
+ setAvgFee,
+ tokenInAmount,
+ tokenIn,
+ poolsMap,
+}: {
+ tokenInAmount: string;
+ tokenIn: TokenMetadata;
+ estimatesFromServer: IEstimateSwapServerView;
+ setAvgFee: (fee: number) => void;
+ poolsMap: Record;
+}) {
+ let avgFee: number = 0;
+ const { routes } = estimatesFromServer;
+ routes.forEach((route) => {
+ const { amount_in, pools } = route;
+ const allocation = new Big(amount_in).div(
+ new Big(toNonDivisibleNumber(tokenIn.decimals, tokenInAmount))
+ );
+ const routeFee = pools.reduce((acc, cur) => {
+ return acc.plus(poolsMap[cur.pool_id]?.fee || 0);
+ }, new Big(0));
+ avgFee += allocation.mul(routeFee).toNumber();
+ });
+ setAvgFee(avgFee);
+}
+export async function getUsedPools(routes: IServerRoute[]) {
+ const { topPools, stablePools } = await getAllPoolsFromCache();
+ const pools: Record = {};
+ routes.forEach((route) => {
+ route.pools.forEach((cur) => {
+ let p;
+ p = topPools.find((p) => +p.id === +cur.pool_id);
+ if (!p) {
+ p = stablePools.find((p) => +p.id === +cur.pool_id);
+ }
+ if (p) {
+ pools[p.id] = p;
+ }
+ });
+ });
+ return pools;
+}
+export async function getUsedTokens(routes: IServerRoute[]) {
+ const pending = routes.map((route) => getTokensOfRoute(route));
+ const tokensList = await Promise.all(pending);
+ const list = tokensList.flat();
+ const tokens: Record = list.reduce((acc, cur) => {
+ acc[cur.id] = cur;
+ return acc;
+ }, {});
+ return tokens;
+}
+export async function getTokensOfRoute(route: IServerRoute) {
+ const tokenIds = route.pools.reduce((acc, cur, index) => {
+ if (index == 0) {
+ acc.push(cur.token_in, cur.token_out);
+ } else {
+ acc.push(cur.token_out);
+ }
+ return acc;
+ }, []);
+ const pending = tokenIds.map((tokenId) => ftGetTokenMetadata(tokenId));
+ const tokens = await Promise.all(pending);
+ return tokens as TokenMetadata[];
+}
+export async function getAllPoolsFromCache() {
+ const { filteredPools: topPools } = await getAllPoolsByTokens();
+ const { allStablePools } = await getAllStablePoolsFromCache();
+ const topPoolsMap = topPools.reduce((acc, p) => {
+ acc[p.id] = p;
+ return acc;
+ }, {});
+ const stablePoolsMap = allStablePools.reduce((acc, p) => {
+ acc[p.id] = p;
+ return acc;
+ }, {});
+ return {
+ topPools,
+ stablePools: allStablePools,
+ poolsMap: { ...topPoolsMap, ...stablePoolsMap },
+ };
+}
+export async function getPriceImpactFromServer({
+ estimatesFromServer,
+ tokenIn,
+ tokenOut,
+ tokenInAmount,
+ tokenOutAmount,
+ tokenPriceList,
+ setPriceImpactValue,
+ poolsMap,
+ tokensMap,
+}: {
+ estimatesFromServer: IEstimateSwapServerView;
+ tokenInAmount: string;
+ tokenIn: TokenMetadata;
+ tokenOut: TokenMetadata;
+ tokenOutAmount: string;
+ tokenPriceList: any;
+ setPriceImpactValue: (impact: string) => void;
+ poolsMap: Record;
+ tokensMap: Record;
+}) {
+ try {
+ const newPrice = new Big(tokenInAmount || '0').div(
+ new Big(tokenOutAmount || '1')
+ );
+ const { routes } = estimatesFromServer;
+ const priceIn = tokenPriceList[tokenIn.id]?.price;
+ const priceOut = tokenPriceList[tokenOut.id]?.price;
+ const priceImpactForRoutes = routes.map((route) => {
+ let oldPrice: Big;
+ if (!!priceIn && !!priceOut) {
+ oldPrice = new Big(priceOut).div(new Big(priceIn));
+
+ return newPrice.lt(oldPrice)
+ ? '0'
+ : newPrice.minus(oldPrice).div(newPrice).times(100).abs().toFixed();
+ }
+ const pools = route.pools.map((pool) => poolsMap[pool.pool_id]);
+ oldPrice = pools.reduce((acc, pool, i) => {
+ const curRate = isStablePool(pool.id)
+ ? new Big(pool.rates[route.pools[i].token_out]).div(
+ new Big(pool.rates[route.pools[i].token_in])
+ )
+ : new Big(
+ scientificNotationToString(
+ calculateMarketPrice(
+ pool,
+ tokensMap[route.pools[i].token_in],
+ tokensMap[route.pools[i].token_out]
+ ).toString()
+ )
+ );
+
+ return acc.mul(curRate);
+ }, new Big(1));
+ return newPrice.lt(oldPrice)
+ ? '0'
+ : newPrice.minus(oldPrice).div(newPrice).times(100).abs().toFixed();
+ });
+ const rawRes = priceImpactForRoutes.reduce(
+ (pre, cur, i) => {
+ return pre.plus(
+ new Big(routes[i].amount_in)
+ .div(new Big(toNonDivisibleNumber(tokenIn.decimals, tokenInAmount)))
+ .mul(cur)
+ );
+ },
+
+ new Big(0)
+ );
+ setPriceImpactValue(scientificNotationToString(rawRes.toString()));
+ } catch (error) {
+ setPriceImpactValue('0');
+ }
+}
diff --git a/src/services/swap.ts b/src/services/swap.ts
index aeddae963..cb83939af 100644
--- a/src/services/swap.ts
+++ b/src/services/swap.ts
@@ -48,7 +48,7 @@ import {
StablePool,
} from './pool';
-// import { stableSmart } from './smartRouteLogic';
+import { cacheAllDCLPools } from './swapV3';
import {
createSmartRouteLogicWorker,
transformWorkerResult,
@@ -60,6 +60,13 @@ import {
nearWithdrawTransaction,
WRAP_NEAR_CONTRACT_ID,
} from './wrap-near';
+import {
+ IEstimateSwapServerView,
+ estimateSwapFromServer,
+ getUsedPools,
+ getUsedTokens,
+} from './smartRouterFromServer';
+import { REF_DCL_POOL_CACHE_KEY } from '../state/swap';
export const REF_FI_SWAP_SIGNAL = 'REF_FI_SWAP_SIGNAL_KEY';
const { NO_REQUIRED_REGISTRATION_TOKEN_IDS } = getConfigV2();
@@ -90,6 +97,7 @@ interface EstimateSwapOptions {
setSwapsToDoTri?: (todos: EstimateSwapView[]) => void;
setSwapsToDoRef?: (todos: EstimateSwapView[]) => void;
proGetCachePool?: boolean;
+ slippage?: number;
}
export interface ReservesMap {
@@ -316,46 +324,9 @@ export const estimateSwapFlow = async ({
//@ts-ignore
if (tokenFlow?.data === null || tokenFlow === null) throwNoPoolError();
-
- // const res = await Promise.all(
- // tokenFlow
- // .map((flow) => {
- // return flow.pool_ids.map(async (pool_id, i) => {
- // const pool = isStablePool(pool_id)
- // ? (await getStablePoolFromCache(pool_id.toString()))[0]
- // : await db
- // .queryTopPoolsByIds({
- // poolIds: [pool_id],
- // })
- // .then((pools) => pools?.[0]);
-
- // return {
- // estimate:
- // i === flow.pool_ids.length - 1
- // ? new Big(flow.amount).toFixed(tokenOut.decimals)
- // : '',
- // inputToken: flow.all_tokens[i],
- // outputToken: flow.all_tokens[i + 1],
- // tokens: await Promise.all(
- // flow.all_tokens.map((t) => ftGetTokenMetadata(t))
- // ),
- // percent: flow.swap_ratio.toString(),
- // partialAmountIn:
- // i === 0
- // ? new Big(parsedAmountIn)
- // .mul(new Big(flow.swap_ratio))
- // .div(100)
- // .toFixed(0, 0)
- // : '',
- // pool: pool,
- // } as EstimateSwapView;
- // });
- // })
- // .flat()
- // );
-
return { estimates: [] };
};
+const SHUTDOWN_SRVER = false;
export const estimateSwap = async ({
tokenIn,
tokenOut,
@@ -365,6 +336,95 @@ export const estimateSwap = async ({
loadingTrigger,
supportLedger,
proGetCachePool,
+ slippage,
+}: EstimateSwapOptions): Promise<{
+ estimates?: EstimateSwapView[];
+ estimatesFromServer?: IEstimateSwapServerView;
+ tag: string;
+ source: 'script' | 'server';
+ poolsMap?: Record;
+ tokensMap?: Record;
+}> => {
+ if (!SHUTDOWN_SRVER) {
+ const resultFromServer = await estimateSwapFromServer({
+ tokenIn,
+ tokenOut,
+ amountIn: toNonDivisibleNumber(tokenIn.decimals, amountIn),
+ slippage,
+ supportLedger,
+ }).catch(() => ({}));
+ if (
+ !(
+ resultFromServer?.result_code !== 0 ||
+ !resultFromServer?.result_data?.routes?.length
+ )
+ ) {
+ const routes = resultFromServer.result_data?.routes;
+ let poolsMap = {};
+ let tokensMap = {};
+ try {
+ if (!localStorage.getItem(REF_DCL_POOL_CACHE_KEY)) {
+ await cacheAllDCLPools();
+ }
+ } catch (error) {}
+ try {
+ poolsMap = await getUsedPools(routes);
+ } catch (error) {}
+ try {
+ tokensMap = await getUsedTokens(routes);
+ } catch (error) {}
+ return {
+ estimatesFromServer: resultFromServer.result_data,
+ tag: `${tokenIn.id}-${toNonDivisibleNumber(
+ tokenIn.decimals,
+ amountIn
+ )}-${tokenOut.id}`,
+ source: 'server',
+ poolsMap,
+ tokensMap,
+ };
+ } else {
+ const resultFromScript = await estimateSwapFromScript({
+ tokenIn,
+ tokenOut,
+ amountIn,
+ intl,
+ setLoadingData,
+ loadingTrigger,
+ supportLedger,
+ proGetCachePool,
+ });
+ return {
+ ...resultFromScript,
+ source: 'script',
+ };
+ }
+ } else {
+ const resultFromScript = await estimateSwapFromScript({
+ tokenIn,
+ tokenOut,
+ amountIn,
+ intl,
+ setLoadingData,
+ loadingTrigger,
+ supportLedger,
+ proGetCachePool,
+ });
+ return {
+ ...resultFromScript,
+ source: 'script',
+ };
+ }
+};
+export const estimateSwapFromScript = async ({
+ tokenIn,
+ tokenOut,
+ amountIn,
+ intl,
+ setLoadingData,
+ loadingTrigger,
+ supportLedger,
+ proGetCachePool,
}: EstimateSwapOptions): Promise<{
estimates: EstimateSwapView[];
tag: string;
@@ -422,7 +482,7 @@ export const estimateSwap = async ({
return { estimates: supportLedgerRes, tag };
}
- const orpools = await getRefPoolsByToken1ORToken2(tokenIn.id, tokenOut.id);
+ const orpools = await getRefPoolsByToken1ORToken2();
let res;
let smartRouteV2OutputEstimate;
@@ -1032,12 +1092,13 @@ export async function getHybridStableSmart(
interface SwapOptions {
useNearBalance?: boolean;
- swapsToDo: EstimateSwapView[];
+ swapsToDo?: EstimateSwapView[];
tokenIn: TokenMetadata;
tokenOut: TokenMetadata;
amountIn: string;
- slippageTolerance: number;
+ slippageTolerance?: number;
swapMarket?: SwapMarket;
+ swapsToDoServer?: IEstimateSwapServerView;
}
export const swap = async ({
@@ -1088,15 +1149,118 @@ export const instantSwap = async ({
});
}
};
+export const swapFromServer = async ({
+ tokenIn,
+ tokenOut,
+ amountIn,
+ swapsToDoServer,
+}: SwapOptions) => {
+ const transactions: Transaction[] = [];
+ const tokenOutActions: RefFiFunctionCallOptions[] = [];
+ const { contract_out, routes } = swapsToDoServer;
+ const registerToken = async (token: TokenMetadata) => {
+ const tokenRegistered = await ftGetStorageBalance(token.id).catch(() => {
+ throw new Error(`${token.id} doesn't exist.`);
+ });
+ if (tokenRegistered === null) {
+ if (NO_REQUIRED_REGISTRATION_TOKEN_IDS.includes(token.id)) {
+ const r = await native_usdc_has_upgrated(token.id);
+ if (r) {
+ tokenOutActions.push({
+ methodName: 'storage_deposit',
+ args: {
+ registration_only: true,
+ account_id: getCurrentWallet()?.wallet?.getAccountId(),
+ },
+ gas: '30000000000000',
+ amount: STORAGE_TO_REGISTER_WITH_MFT,
+ });
+ } else {
+ tokenOutActions.push({
+ methodName: 'register_account',
+ args: {
+ account_id: getCurrentWallet()?.wallet?.getAccountId(),
+ },
+ gas: '10000000000000',
+ });
+ }
+ } else {
+ tokenOutActions.push({
+ methodName: 'storage_deposit',
+ args: {
+ registration_only: true,
+ account_id: getCurrentWallet()?.wallet?.getAccountId(),
+ },
+ gas: '30000000000000',
+ amount: STORAGE_TO_REGISTER_WITH_MFT,
+ });
+ }
+ transactions.push({
+ receiverId: token.id,
+ functionCalls: tokenOutActions,
+ });
+ }
+ };
+
+ if (tokenOut.id !== contract_out) {
+ return window.location.reload();
+ }
+
+ //making sure all actions get included.
+ await registerToken(tokenOut);
+ const actionsList = [];
+ routes.forEach((route) => {
+ route.pools.forEach((pool) => {
+ if (+pool.amount_in == 0) {
+ delete pool.amount_in;
+ }
+ pool.pool_id = Number(pool.pool_id);
+ actionsList.push(pool);
+ });
+ });
+ transactions.push({
+ receiverId: tokenIn.id,
+ functionCalls: [
+ {
+ methodName: 'ft_transfer_call',
+ args: {
+ receiver_id: REF_FI_CONTRACT_ID,
+ amount: toNonDivisibleNumber(tokenIn.decimals, amountIn),
+ msg: JSON.stringify({
+ force: 0,
+ actions: actionsList,
+ ...(tokenOut.symbol == 'NEAR' ? { skip_unwrap_near: false } : {}),
+ }),
+ },
+ gas: '180000000000000',
+ amount: ONE_YOCTO_NEAR,
+ },
+ ],
+ });
+
+ if (tokenIn.id === WRAP_NEAR_CONTRACT_ID && tokenIn?.symbol == 'NEAR') {
+ transactions.unshift(nearDepositTransaction(amountIn));
+ }
+ if (tokenIn.id === WRAP_NEAR_CONTRACT_ID) {
+ const registered = await ftGetStorageBalance(WRAP_NEAR_CONTRACT_ID);
+ if (registered === null) {
+ transactions.unshift({
+ receiverId: WRAP_NEAR_CONTRACT_ID,
+ functionCalls: [registerAccountOnToken()],
+ });
+ }
+ }
+
+ return executeMultipleTransactions(transactions);
+};
export const nearInstantSwap = async ({
tokenIn,
tokenOut,
amountIn,
swapsToDo,
slippageTolerance,
-}: // minAmountOut,
-SwapOptions) => {
+}: SwapOptions) => {
const transactions: Transaction[] = [];
const tokenOutActions: RefFiFunctionCallOptions[] = [];
@@ -1228,31 +1392,6 @@ SwapOptions) => {
if (tokenIn.id === WRAP_NEAR_CONTRACT_ID && tokenIn?.symbol == 'NEAR') {
transactions.unshift(nearDepositTransaction(amountIn));
}
- // if (tokenOut.id === WRAP_NEAR_CONTRACT_ID) {
- // const outEstimate = new Big(0);
- // const routes = separateRoutes(swapsToDo, tokenOut.id);
-
- // const bigEstimate = routes.reduce((acc, cur) => {
- // const curEstimate = round(
- // 24,
- // toNonDivisibleNumber(
- // 24,
- // percentLess(slippageTolerance, cur[cur.length - 1].estimate)
- // )
- // );
- // return acc.plus(curEstimate);
- // }, outEstimate);
-
- // const minAmountOut = toReadableNumber(
- // 24,
- // scientificNotationToString(bigEstimate.toString())
- // );
-
- // if (tokenOut.symbol == 'NEAR') {
- // transactions.push(nearWithdrawTransaction(minAmountOut));
- // }
- // }
-
if (tokenIn.id === WRAP_NEAR_CONTRACT_ID) {
const registered = await ftGetStorageBalance(WRAP_NEAR_CONTRACT_ID);
if (registered === null) {
diff --git a/src/state/pool.ts b/src/state/pool.ts
index 9b212f9cb..5593a4d23 100644
--- a/src/state/pool.ts
+++ b/src/state/pool.ts
@@ -525,49 +525,6 @@ export const useMorePoolIds = ({
return ids;
};
-// export const usePoolsMorePoolIds = () => {
-// // top pool id to more pool ids:Array
-// const [poolsMorePoolIds, setMorePoolIds] = useState>(
-// {}
-// );
-
-// const getAllPoolsTokens = async () => {
-// return (await getAllPoolsIndexer()).filter(
-// (p: Pool) => p.pool_kind && p.pool_kind === 'SIMPLE_POOL'
-// );
-// };
-
-// useEffect(() => {
-// getAllPoolsTokens().then((res) => {
-// const poolsMorePoolIds = res.map((p: any) => {
-// const id1 = p.tokenIds[0];
-// const id2 = p.tokenIds[1];
-
-// return res
-// .filter(
-// (resP: any) =>
-// resP.tokenIds.includes(id1) && resP.tokenIds.includes(id2)
-// )
-// .map((a: any) => a.id.toString());
-// });
-
-// const parsedIds = poolsMorePoolIds.reduce(
-// (acc: any, cur: any, i: number) => {
-// return {
-// ...acc,
-// [res[i].id.toString()]: cur,
-// };
-// },
-// {}
-// );
-
-// setMorePoolIds(parsedIds);
-// });
-// }, []);
-
-// return poolsMorePoolIds;
-// };
-
export const useMorePools = ({
tokenIds,
order,
diff --git a/src/state/swap.tsx b/src/state/swap.tsx
index a270a97a6..b98cd6f23 100644
--- a/src/state/swap.tsx
+++ b/src/state/swap.tsx
@@ -46,7 +46,7 @@ import {
PoolMode,
REF_FI_SWAP_SIGNAL,
} from '../services/swap';
-import { EstimateSwapView, swap } from '../services/swap';
+import { EstimateSwapView, swap, swapFromServer } from '../services/swap';
import {
get_pool,
PoolInfo,
@@ -72,6 +72,11 @@ import { toRealSymbol } from '../utils/token';
import { getCurrentWallet, WalletContext } from '../utils/wallets-integration';
import { useIndexerStatus } from './pool';
import { useTokenPriceList } from './token';
+import {
+ IEstimateSwapServerView,
+ getAvgFeeFromServer,
+ getPriceImpactFromServer,
+} from '../services/smartRouterFromServer';
const ONLY_ZEROS = /^0*\.?0*$/;
export const REF_DCL_POOL_CACHE_KEY = 'REF_DCL_POOL_CACHE_VALUE';
@@ -368,25 +373,38 @@ export const estimateValidator = (
swapTodos: EstimateSwapView[],
tokenIn: TokenMetadata,
parsedAmountIn: string,
- tokenOut: TokenMetadata
+ tokenOut: TokenMetadata,
+ swapsToDoServer: IEstimateSwapServerView
) => {
- if (swapTodos && swapTodos?.[0]?.pool === null) return true;
-
- const tokenInId = swapTodos[0]?.inputToken;
- const tokenOutId = swapTodos[swapTodos.length - 1]?.outputToken;
-
- if (
- tokenInId !== tokenIn.id ||
- tokenOutId !== tokenOut.id ||
- !BigNumber.sum(...swapTodos.map((st) => st.partialAmountIn || 0)).isEqualTo(
- parsedAmountIn
- ) ||
- (!!localStorage.getItem(SUPPORT_LEDGER_KEY) && swapTodos?.length > 1)
- ) {
- return false;
+ if (swapTodos?.[0]?.pool === null || !swapsToDoServer) return true;
+ if (swapTodos) {
+ const tokenInId = swapTodos[0]?.inputToken;
+ const tokenOutId = swapTodos[swapTodos.length - 1]?.outputToken;
+ if (
+ tokenInId !== tokenIn.id ||
+ tokenOutId !== tokenOut.id ||
+ !BigNumber.sum(
+ ...swapTodos.map((st) => st.partialAmountIn || 0)
+ ).isEqualTo(parsedAmountIn) ||
+ (!!localStorage.getItem(SUPPORT_LEDGER_KEY) && swapTodos?.length > 1)
+ ) {
+ return false;
+ }
+ }
+ if (swapsToDoServer) {
+ const { contract_in, contract_out, amount_in } = swapsToDoServer;
+ if (
+ contract_in !== tokenIn.id ||
+ contract_out !== tokenOut.id ||
+ !BigNumber(amount_in).isEqualTo(parsedAmountIn)
+ ) {
+ return false;
+ }
}
+
return true;
};
+// TODO 1
export const useSwap = ({
tokenIn,
tokenInAmount,
@@ -406,13 +424,15 @@ export const useSwap = ({
const [tokenOutAmount, setTokenOutAmount] = useState('');
const [swapError, setSwapError] = useState();
const [swapsToDo, setSwapsToDo] = useState();
+ const [swapsToDoServer, setSwapsToDoServer] =
+ useState();
const [quoteDone, setQuoteDone] = useState(false);
const tokenPriceList = useTokenPriceList(loadingTrigger);
const { enableTri } = useContext(SwapProContext);
- const [forceEstimate, setForceEstimate] = useState(false);
+ const [tag, setTag] = useState();
const [priceImpactValue, setPriceImpactValue] = useState('0');
@@ -459,29 +479,61 @@ export const useSwap = ({
setAvgFee(avgFee);
};
-
const getEstimate = async () => {
setCanSwap(false);
setQuoteDone(false);
+ setEstimating(true);
- if (tokenIn && tokenOut && tokenIn.id !== tokenOut.id) {
- if (!tokenInAmount || ONLY_ZEROS.test(tokenInAmount)) {
- setTokenOutAmount('0');
- setSwapsToDo(null);
-
- return;
- }
-
- setEstimating(true);
- estimateSwap({
- tokenIn,
- tokenOut,
- amountIn: tokenInAmount,
- intl,
- supportLedger,
- loadingTrigger,
- })
- .then(async ({ estimates: estimatesRes }) => {
+ estimateSwap({
+ tokenIn,
+ tokenOut,
+ amountIn: tokenInAmount,
+ intl,
+ supportLedger,
+ loadingTrigger,
+ slippage: slippageTolerance,
+ })
+ .then(async (estimateResult) => {
+ if (estimateResult.source == 'server') {
+ const { estimatesFromServer, poolsMap, tokensMap } = estimateResult;
+ const { amount_out } = estimatesFromServer;
+ const expectedOut = toReadableNumber(tokenOut.decimals, amount_out);
+ setSwapError(null);
+ setSwapsToDo(null);
+ setTokenOutAmount(scientificNotationToString(expectedOut));
+ setEstimateInOut([tokenInAmount, expectedOut]);
+ setCanSwap(true);
+ setQuoteDone(true);
+ setSwapsToDoServer(estimatesFromServer);
+ getAvgFeeFromServer({
+ estimatesFromServer,
+ setAvgFee,
+ tokenInAmount,
+ tokenIn,
+ poolsMap,
+ });
+ const tokenPriceListForCal = !!tokenPriceList?.NEAR
+ ? tokenPriceList
+ : (await getTokenPriceListFromCache()).reduce(
+ (acc, cur) => ({
+ ...acc,
+ [cur.id]: cur,
+ }),
+ {}
+ );
+ getPriceImpactFromServer({
+ estimatesFromServer,
+ tokenIn,
+ tokenOut,
+ tokenInAmount,
+ tokenOutAmount: scientificNotationToString(expectedOut.toString()),
+ tokenPriceList: tokenPriceListForCal,
+ setPriceImpactValue,
+ poolsMap,
+ tokensMap,
+ });
+ } else if (estimateResult.source == 'script') {
+ const { estimates: estimatesRes } = estimateResult;
const estimates = estimatesRes.map((e) => ({
...e,
partialAmountIn: e.pool.partialAmountIn,
@@ -498,6 +550,7 @@ export const useSwap = ({
if (tokenInAmount && !ONLY_ZEROS.test(tokenInAmount)) {
setAverageFee(estimates);
setSwapError(null);
+ setSwapsToDoServer(null);
const expectedOut = estimates.reduce(
(acc, cur) =>
@@ -539,103 +592,53 @@ export const useSwap = ({
}
setPool(estimates[0].pool);
- })
- .catch((err) => {
- // if (!loadingTrigger) {
- setCanSwap(false);
- setTokenOutAmount('');
- setSwapError(err);
- setQuoteDone(true);
-
- // }
- })
- .finally(() => {
- setForceEstimate && setForceEstimate(false);
- setLoadingTrigger && setLoadingTrigger(false);
- setEstimating && setEstimating(false);
- setShowSwapLoading && setShowSwapLoading(false);
- });
- } else if (
- tokenIn &&
- tokenOut &&
- !tokenInAmount &&
- ONLY_ZEROS.test(tokenInAmount) &&
- tokenIn.id !== tokenOut.id
- ) {
- setTokenOutAmount('0');
- }
+ }
+ })
+ .catch((err) => {
+ setCanSwap(false);
+ setTokenOutAmount('');
+ setSwapError(err);
+ setQuoteDone(true);
+ })
+ .finally(() => {
+ setLoadingTrigger && setLoadingTrigger(false);
+ setEstimating && setEstimating(false);
+ setShowSwapLoading && setShowSwapLoading(false);
+ setTag(`${tokenIn?.id}|${tokenOut?.id}|${tokenInAmount}`);
+ });
};
useEffect(() => {
- const valRes =
- !swapError &&
- swapsToDo &&
- tokenIn &&
- tokenOut &&
- estimateValidator(
- swapsToDo,
- tokenIn,
- toNonDivisibleNumber(
- tokenIn?.decimals === null || tokenIn?.decimals === undefined
- ? 24
- : tokenIn.decimals,
- tokenInAmount
- ),
- tokenOut
- );
- if (!tokenDeflationRateData) return;
- if (estimating && swapsToDo && !forceEstimate) return;
-
- if (valRes && !loadingTrigger && !forceEstimate) {
- return;
+ if (
+ tokenIn?.id &&
+ tokenOut?.id &&
+ tokenIn.id !== tokenOut.id &&
+ Number(tokenInAmount || 0) > 0
+ ) {
+ getEstimate();
+ } else if (ONLY_ZEROS.test(tokenInAmount || '0')) {
+ setTokenOutAmount('0');
}
-
- getEstimate();
}, [
- loadingTrigger,
- loadingPause,
- tokenIn?.id,
- tokenOut?.id,
tokenInAmount,
reEstimateTrigger,
- enableTri,
- forceEstimate,
- tokenDeflationRateData?.rate,
- ]);
-
- useEffect(() => {
- const valRes =
- swapsToDo &&
- tokenIn &&
- tokenOut &&
- estimateValidator(
- swapsToDo,
- tokenIn,
- toNonDivisibleNumber(
- tokenIn?.decimals === null || tokenIn?.decimals === undefined
- ? 24
- : tokenIn.decimals,
- tokenInAmount
- ),
- tokenOut
- );
- if (!tokenDeflationRateData) return;
- if (estimating && swapsToDo && !forceEstimate) return;
-
- if (((valRes && !loadingTrigger) || swapError) && !forceEstimate) return;
- getEstimate();
- }, [estimating, tokenDeflationRateData?.rate]);
-
- useEffect(() => {
- setForceEstimate(true);
- }, [
tokenIn?.id,
tokenOut?.id,
- tokenIn?.symbol,
- tokenOut?.symbol,
supportLedger,
+ enableTri,
+ slippageTolerance,
]);
-
+ useEffect(() => {
+ if (
+ loadingTrigger &&
+ tokenIn?.id &&
+ tokenOut?.id &&
+ tokenIn.id !== tokenOut.id &&
+ Number(tokenInAmount || 0) > 0
+ ) {
+ getEstimate();
+ }
+ }, [loadingTrigger]);
useEffect(() => {
let id: any = null;
if (!loadingTrigger && !loadingPause) {
@@ -652,18 +655,28 @@ export const useSwap = ({
}, [count, loadingTrigger, loadingPause]);
const makeSwap = () => {
- swap({
- slippageTolerance,
- swapsToDo,
- tokenIn,
- amountIn: Big(tokenInAmount)
- .div(Big(1).minus(tokenDeflationRateData?.rate || 0))
- .toFixed(),
- tokenOut,
- swapMarket: 'ref',
- }).catch(setSwapError);
+ if (swapsToDo) {
+ swap({
+ slippageTolerance,
+ swapsToDo,
+ tokenIn,
+ amountIn: Big(tokenInAmount)
+ .div(Big(1).minus(tokenDeflationRateData?.rate || 0))
+ .toFixed(),
+ tokenOut,
+ swapMarket: 'ref',
+ }).catch(setSwapError);
+ } else if (swapsToDoServer) {
+ swapFromServer({
+ swapsToDoServer,
+ tokenIn,
+ amountIn: Big(tokenInAmount)
+ .div(Big(1).minus(tokenDeflationRateData?.rate || 0))
+ .toFixed(),
+ tokenOut,
+ }).catch(setSwapError);
+ }
};
-
return {
canSwap,
tokenOutAmount,
@@ -673,9 +686,8 @@ export const useSwap = ({
swapError,
makeSwap,
avgFee,
- tokenInAmount: !swapsToDo
- ? '1'
- : toReadableNumber(
+ tokenInAmount: swapsToDo
+ ? toReadableNumber(
tokenIn.decimals,
swapsToDo
.reduce(
@@ -683,7 +695,11 @@ export const useSwap = ({
new Big(0)
)
.toFixed()
- ),
+ )
+ : swapsToDoServer
+ ? toReadableNumber(tokenIn.decimals, swapsToDoServer.amount_in || '0')
+ : '1',
+
pools: swapsToDo?.map((estimate) => estimate.pool),
swapsToDo,
isParallelSwap: swapsToDo?.every((e) => e.status === PoolMode.PARALLEL),
@@ -692,6 +708,8 @@ export const useSwap = ({
new Big(priceImpactValue).minus(new Big((avgFee || 0) / 100)).toString()
),
estimateInOut,
+ swapsToDoServer,
+ tag,
};
};
export const useSwapV3 = ({
@@ -782,14 +800,13 @@ export const useSwapV3 = ({
input_token: tokenIn,
output_token: tokenOut,
input_amount: tokenInAmount,
- tag: `${tokenIn.id}|${fee}|${tokenInAmount}`,
+ tag: `${tokenIn.id}|${tokenOut.id}|${tokenInAmount}`,
}).catch((e) => null);
};
const bestFee = bestEstimate?.tag?.split('|')?.[1]
? Number(bestEstimate?.tag?.split('|')?.[1])
: null;
-
useEffect(() => {
if (!bestFee || wrapOperation) return;
@@ -805,7 +822,6 @@ export const useSwapV3 = ({
useEffect(() => {
if (!tokenIn || !tokenOut || !tokenInAmount || wrapOperation) return;
-
setQuoteDone(false);
const storedPools = localStorage.getItem(REF_DCL_POOL_CACHE_KEY);
@@ -818,7 +834,6 @@ export const useSwapV3 = ({
const allDCLPools = JSON.parse(
localStorage.getItem(REF_DCL_POOL_CACHE_KEY)
);
-
Promise.all(
fees.map((fee) => getQuote(fee, tokenIn, tokenOut, allDCLPools))
)
@@ -840,9 +855,6 @@ export const useSwapV3 = ({
setTokenOutAmount(
toReadableNumber(tokenOut?.decimals || 24, bestEstimate.amount)
);
-
- setTag(bestEstimate.tag);
-
return;
}
})
@@ -851,6 +863,7 @@ export const useSwapV3 = ({
setQuoteDone(true);
setPoolReFetch(!poolReFetch);
setLoadingTrigger && setLoadingTrigger(false);
+ setTag(`${tokenIn?.id}|${tokenOut?.id}|${tokenInAmount}`);
});
}, [
tokenIn?.id,
@@ -1513,6 +1526,8 @@ export const useRefSwap = ({
priceImpactValue,
tokenInAmount: tokenInAmountV1,
estimateInOut,
+ swapsToDoServer,
+ tag,
} = useSwap({
tokenIn,
tokenInAmount,
@@ -1530,7 +1545,6 @@ export const useRefSwap = ({
tokenDeflationRateData,
});
const [estimateInAmount, tokenOutAmount] = estimateInOut;
-
const {
makeSwap: makeSwapV2,
tokenOutAmount: tokenOutAmountV2,
@@ -1542,7 +1556,7 @@ export const useRefSwap = ({
canSwap: canSwapV2,
swapErrorV3: swapErrorV2,
tokenInAmount: tokenInAmountV2,
- tag: tagV2,
+ tag: tagV3,
} = useSwapV3({
tokenIn,
tokenOut,
@@ -1554,11 +1568,23 @@ export const useRefSwap = ({
setLoadingTrigger,
reEstimateTrigger,
});
-
- const quoteDoneRef =
- quoteDoneV2 &&
- quoteDone &&
- Big(estimateInAmount || 0).eq(tokenInAmount || 0);
+ function validator() {
+ if (tag && tagV3) {
+ const [inId, outId, inAmount] = tag.split('|');
+ const [dclInId, dclOutId, dclInAmount] = tagV3.split('|');
+ return (
+ inId == tokenIn?.id &&
+ outId == tokenOut.id &&
+ inAmount == tokenInAmount &&
+ dclInId == tokenIn?.id &&
+ dclOutId == tokenOut.id &&
+ dclInAmount == tokenInAmount
+ );
+ }
+ return false;
+ }
+ // TODO 2
+ const quoteDoneRef = quoteDoneV2 && quoteDone && validator();
if (!quoteDoneRef)
return {
quoteDone: false,
@@ -1576,11 +1602,15 @@ export const useRefSwap = ({
? 'v2'
: 'v1';
if (bestSwap === 'v1') {
+ if (swapsToDoServer) {
+ swapsToDoServer.contract = 'Ref_Classic';
+ }
return {
quoteDone: true,
canSwap,
makeSwap: makeSwapV1,
estimates: swapsToDo?.map((s) => ({ ...s, contract: 'Ref_Classic' })),
+ estimatesServer: swapsToDoServer ?? null,
tokenOutAmount:
!tokenOutAmount || swapError
? ''
@@ -1947,6 +1977,7 @@ export const useRefSwapPro = ({
selectMarket,
swapType,
} = useContext(SwapProContext);
+ // TODO 3
const resRef = useRefSwap({
tokenIn,
tokenInAmount,
@@ -2030,17 +2061,18 @@ export const useRefSwapPro = ({
});
resValid =
- resValid &&
- (!resAurora?.availableRoute ||
- resAurora.tokenOutAmount ===
- toPrecision(
- resAurora.tokenOutAmount || '0',
- Math.min(tokenOut.decimals, 8)
- )) &&
- (!resRef?.availableRoute ||
- resRef.estimates?.[0]?.tokens?.[
- resRef.estimates?.[0]?.tokens.length - 1
- ]?.id === localStorage.getItem('REF_FI_SWAP_OUT'));
+ (resValid &&
+ (!resAurora?.availableRoute ||
+ resAurora.tokenOutAmount ===
+ toPrecision(
+ resAurora.tokenOutAmount || '0',
+ Math.min(tokenOut.decimals, 8)
+ )) &&
+ (!resRef?.availableRoute ||
+ resRef.estimates?.[0]?.tokens?.[
+ resRef.estimates?.[0]?.tokens.length - 1
+ ]?.id === localStorage.getItem('REF_FI_SWAP_OUT'))) ||
+ (resRef.estimatesServer && !resRef.estimates);
if (!resValid) {
setReEstimateTrigger(!reEstimateTrigger);
diff --git a/src/store/RefDatabase.ts b/src/store/RefDatabase.ts
index 75f7b6f31..7c1358d0c 100644
--- a/src/store/RefDatabase.ts
+++ b/src/store/RefDatabase.ts
@@ -423,7 +423,7 @@ class RefDatabase extends Dexie {
return result;
}
- async queryPoolsByTokens2(tokenInId: string, tokenOutId: string) {
+ async queryPoolsByTokens2() {
//Queries for any pools that contain either tokenInId OR tokenOutId OR both.
const normalItems = await this.poolsTokens.toArray();
diff --git a/src/utils/numbers.ts b/src/utils/numbers.ts
index 3f0d0ad41..e4063f5f2 100644
--- a/src/utils/numbers.ts
+++ b/src/utils/numbers.ts
@@ -10,6 +10,7 @@ import Big from 'big.js';
import _, { sortBy } from 'lodash';
import { getStablePoolDecimal } from '../pages/stable/StableSwapEntry';
import { WRAP_NEAR_CONTRACT_ID } from '../services/wrap-near';
+import { IServerRoute } from '~src/services/smartRouterFromServer';
const BPS_CONVERSION = 10000;
@@ -660,6 +661,58 @@ export function getPoolAllocationPercents(pools: Pool[]) {
return [];
}
}
+export function getRouteAllocationPercents(routes: IServerRoute[]) {
+ if (routes.length === 1) return ['100'];
+
+ if (routes) {
+ const partialAmounts = routes.map((route) => {
+ return math.bignumber(route.amount_in);
+ });
+
+ const ps: string[] = new Array(partialAmounts.length).fill('0');
+
+ const sum =
+ partialAmounts.length === 1
+ ? partialAmounts[0]
+ : math.sum(...partialAmounts);
+
+ const sortedAmount = sortBy(partialAmounts, (p) => Number(p));
+
+ const minIndexes: number[] = [];
+
+ for (let k = 0; k < sortedAmount.length - 1; k++) {
+ let minIndex = -1;
+
+ for (let j = 0; j < partialAmounts.length; j++) {
+ if (partialAmounts[j].eq(sortedAmount[k]) && !minIndexes.includes(j)) {
+ minIndex = j;
+ minIndexes.push(j);
+ break;
+ }
+ }
+ const res = math
+ .round(percent(partialAmounts[minIndex].toString(), sum))
+ .toString();
+
+ if (Number(res) === 0) {
+ ps[minIndex] = '1';
+ } else {
+ ps[minIndex] = res;
+ }
+ }
+
+ const finalPIndex = ps.indexOf('0');
+
+ ps[finalPIndex] = subtraction(
+ '100',
+ ps.length === 1 ? Number(ps[0]) : math.sum(...ps.map((p) => Number(p)))
+ ).toString();
+
+ return ps;
+ } else {
+ return [];
+ }
+}
export function getAllocationsLeastOne(arr: string[]) {
if (arr.length === 0) return [];