Skip to content

Commit

Permalink
Smart router call (#566)
Browse files Browse the repository at this point in the history
* smart router optimization

* adjust ledger tip logic

* fix ui display issue

* remove ledger tip
  • Loading branch information
xieqiancaosissi authored Jul 16, 2024
1 parent 2bf61e5 commit 676297f
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 28 deletions.
9 changes: 8 additions & 1 deletion src/components/swap/SwapRateChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ import { OrderlyLoading } from '../../pages/Orderly/components/Common/Icons';
import { numberWithCommas } from '../../pages/Orderly/utiles';
import { useClientMobile } from '../../utils/device';
import { SwapProContext } from '../../pages/SwapPage';
import { scientificNotationToString, toPrecision } from '../../utils/numbers';
import {
scientificNotationToString,
toPrecision,
toInternationalCurrencySystemLongString,
} from '../../utils/numbers';
import Big from 'big.js';
import { toRealSymbol } from '../../utils/token';
import SwapProTab from './SwapProTab';
Expand All @@ -44,6 +48,9 @@ export interface SwapRateChartProps {
type Dimensions = '24H' | '7D' | '1M' | '1Y' | 'All';

const priceFormatter = (price: string | number) => {
if (Number(price) >= 1000000) {
return toInternationalCurrencySystemLongString(price.toString());
}
return numberWithCommas(
Number(price) === 0
? 0
Expand Down
8 changes: 8 additions & 0 deletions src/services/ft-contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,14 @@ export const ftGetTokenMetadata = async (
id: string,
accountPage?: boolean
): Promise<TokenMetadata> => {
if (!id)
return {
id,
name: id,
symbol: id?.split('.')[0].slice(0, 8),
decimals: 6,
icon: null,
};
try {
let metadata = await db.allTokens().where({ id }).first();
if (!metadata) {
Expand Down
121 changes: 102 additions & 19 deletions src/services/pool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,10 @@ export const getPoolsByTokens = async ({
});
return { filteredPools, pool_protocol };
};
export const getAllPoolsByTokens = async (): Promise<{
// for server
export const getAllPoolsByTokens = async (
needCheckExpiration?: boolean
): Promise<{
filteredPools: Pool[];
}> => {
let pools;
Expand All @@ -473,18 +476,36 @@ export const getAllPoolsByTokens = async (): Promise<{
);
};
try {
const cachedPoolProtocol = sessionStorage.getItem(REF_FI_POOL_PROTOCOL);

const cachedPoolProtocol =
sessionStorage.getItem(REF_FI_POOL_PROTOCOL) || 'indexer';
if (cachedPoolProtocol === 'rpc') {
pools = await db.getAllPoolsTokens();

if (!pools || pools.length === 0) {
const validCache = await db.checkPoolsTokens();
if (
!pools ||
pools.length === 0 ||
(needCheckExpiration && !validCache)
) {
pools = await fetchPoolsRPC();
await cachePools(pools);
}
} else {
const poolsRaw = await db.queryTopPools();
if (poolsRaw && poolsRaw?.length > 0) {
const validCache = await db.checkTopPools();
if (!poolsRaw?.length || (needCheckExpiration && !validCache)) {
const poolsRaw = await fetchPoolsIndexer();

await db.cacheTopPools(poolsRaw);

pools = poolsRaw.map((p: any) => {
return {
...parsePool(p),
Dex: 'ref',
};
});

await cachePools(pools);
} else {
pools = poolsRaw.map((p) => {
const parsedP = parsePool({
...p,
Expand All @@ -498,19 +519,6 @@ export const getAllPoolsByTokens = async (): Promise<{
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) {
Expand Down Expand Up @@ -1574,3 +1582,78 @@ export const getAllStablePoolsFromCache = async (loadingTriger?: boolean) => {
allStablePoolsInfo,
};
};

// for server router
export const getStablePoolFromCacheForServer = async (id: string) => {
const stable_pool_id = id;

const pool_key = getStablePoolKey(stable_pool_id);

const info = getStablePoolInfoKey(stable_pool_id);

const stablePoolCache = JSON.parse(localStorage.getItem(pool_key));

const stablePoolInfoCache = JSON.parse(localStorage.getItem(info));

const isStablePoolCached = !!stablePoolCache;

const isStablePoolInfoCached = !!stablePoolInfoCache;

const stablePool = isStablePoolCached
? stablePoolCache
: await getPool(Number(stable_pool_id));

const stablePoolInfo = isStablePoolInfoCached
? stablePoolInfoCache
: await getStablePool(Number(stable_pool_id));

if (!isStablePoolCached) {
localStorage.setItem(
pool_key,
JSON.stringify({ ...stablePool, update_time: moment().unix() })
);
}

if (!isStablePoolInfoCached) {
localStorage.setItem(
info,
JSON.stringify({ ...stablePoolInfo, update_time: moment().unix() })
);
}
stablePool.rates = stablePoolInfo.token_account_ids.reduce(
(acc: any, cur: any, i: number) => ({
...acc,
[cur]: toReadableNumber(
getStablePoolDecimal(stablePool.id),
stablePoolInfo.rates[i]
),
}),
{}
);

return [stablePool, stablePoolInfo];
};
export const getAllStablePoolsFromCacheForServer = async () => {
const res = await Promise.all(
ALL_STABLE_POOL_IDS.filter((id) => {
return !BLACKLIST_POOL_IDS.includes(id.toString());
}).map((id) => getStablePoolFromCacheForServer(id.toString()))
);

const allStablePoolsById = res.reduce((pre, cur, i) => {
return {
...pre,
[cur[0].id]: cur,
};
}, {}) as {
[id: string]: [Pool, StablePool];
};
const allStablePools = Object.values(allStablePoolsById).map((p) => p[0]);
const allStablePoolsInfo = Object.values(allStablePoolsById).map((p) => p[1]);

return {
allStablePoolsById,
allStablePools,
allStablePoolsInfo,
};
};
41 changes: 35 additions & 6 deletions src/services/smartRouterFromServer.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import Big from 'big.js';
import db from '../store/RefDatabase';
import {
toNonDivisibleNumber,
scientificNotationToString,
calculateMarketPrice,
} from '../utils/numbers';
import { TokenMetadata, ftGetTokenMetadata } from './ft-contract';
import { getAllPoolsByTokens, getAllStablePoolsFromCache, Pool } from './pool';
import {
getAllPoolsByTokens,
getAllStablePoolsFromCacheForServer,
Pool,
} from './pool';
import { isStablePool } from '../services/near';
import { getTokenPriceList } from '../services/indexer';
export interface IEstimateSwapServerView {
amount_in: string;
amount_out: string;
Expand Down Expand Up @@ -92,8 +98,13 @@ export async function getAvgFeeFromServer({
});
setAvgFee(avgFee);
}
export async function getUsedPools(routes: IServerRoute[]) {
const { topPools, stablePools } = await getAllPoolsFromCache();
export async function getUsedPools(
routes: IServerRoute[],
needCheckExpiration?: boolean
) {
const { topPools, stablePools } = await getAllPoolsFromCache(
needCheckExpiration
);
const pools: Record<string, Pool> = {};
routes.forEach((route) => {
route.pools.forEach((cur) => {
Expand Down Expand Up @@ -132,9 +143,11 @@ export async function getTokensOfRoute(route: IServerRoute) {
const tokens = await Promise.all(pending);
return tokens as TokenMetadata[];
}
export async function getAllPoolsFromCache() {
const { filteredPools: topPools } = await getAllPoolsByTokens();
const { allStablePools } = await getAllStablePoolsFromCache();
export async function getAllPoolsFromCache(needCheckExpiration?: boolean) {
const { filteredPools: topPools } = await getAllPoolsByTokens(
needCheckExpiration
);
const { allStablePools } = await getAllStablePoolsFromCacheForServer();
const topPoolsMap = topPools.reduce((acc, p) => {
acc[p.id] = p;
return acc;
Expand Down Expand Up @@ -224,3 +237,19 @@ export async function getPriceImpactFromServer({
setPriceImpactValue('0');
}
}
export const getTokenPriceListFromCacheForServer = async () => {
let prices;
prices = await db.queryTokenPrices();
const validCache = await db.checkTokenPrices();
if (!prices?.length || !validCache) {
prices = await getTokenPriceList();
db.cacheTokenPrices(prices);
}
const map = prices?.reduce((acc, cur) => {
return {
...acc,
[cur.id]: cur,
};
}, {});
return map || {};
};
6 changes: 5 additions & 1 deletion src/services/swap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ import {
getUsedTokens,
} from './smartRouterFromServer';
import { REF_DCL_POOL_CACHE_KEY } from '../state/swap';
import { getTokenPriceListFromCacheForServer } from '../services/smartRouterFromServer';

export const REF_FI_SWAP_SIGNAL = 'REF_FI_SWAP_SIGNAL_KEY';
const { NO_REQUIRED_REGISTRATION_TOKEN_IDS } = getConfigV2();
Expand Down Expand Up @@ -368,7 +369,10 @@ export const estimateSwap = async ({
}
} catch (error) {}
try {
poolsMap = await getUsedPools(routes);
const prices = await getTokenPriceListFromCacheForServer();
const isLosePrice =
!prices?.[tokenIn.id]?.price || !prices?.[tokenOut.id]?.price;
poolsMap = await getUsedPools(routes, isLosePrice);
} catch (error) {}
try {
tokensMap = await getUsedTokens(routes);
Expand Down
5 changes: 4 additions & 1 deletion src/state/swap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ import {
IEstimateSwapServerView,
getAvgFeeFromServer,
getPriceImpactFromServer,
getAllPoolsFromCache,
} from '../services/smartRouterFromServer';
const ONLY_ZEROS = /^0*\.?0*$/;

Expand Down Expand Up @@ -607,7 +608,9 @@ export const useSwap = ({
setTag(`${tokenIn?.id}|${tokenOut?.id}|${tokenInAmount}`);
});
};

useEffect(() => {
getAllPoolsFromCache(true);
}, []);
useEffect(() => {
if (
tokenIn?.id &&
Expand Down
12 changes: 12 additions & 0 deletions src/store/RefDatabase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,18 @@ class RefDatabase extends Dexie {
)
);
}
public async checkPoolsTokens() {
const items = await this.poolsTokens.limit(10).toArray();
return (
items.length > 0 &&
items.every(
(item) =>
Number(item.update_time) >=
Number(moment().unix()) -
Number(getConfig().TOP_POOLS_TOKEN_REFRESH_INTERVAL)
)
);
}

public async queryTopPools() {
const pools = await this.topPools.toArray();
Expand Down

0 comments on commit 676297f

Please sign in to comment.