Skip to content

Commit

Permalink
Use in-bundle asset list for to, from, and recommended assets (osmosi…
Browse files Browse the repository at this point in the history
…s-labs#2924) (osmosis-labs#2927)

* use in-bundle asset list for to, from, and recommended assets

* just return pool ID from split

* fix build

* fix check

* remove getasset

---------

Co-authored-by: Jon Ator <[email protected]>
  • Loading branch information
ValarDragon and jonator authored Mar 8, 2024
1 parent 6bd3da8 commit 6686302
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 127 deletions.
5 changes: 4 additions & 1 deletion packages/utils/src/asset-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,28 @@ import type { Asset, AssetList, Currency } from "@osmosis-labs/types";

/** Find asset in asset list config given any of the available identifiers. */
export function getAssetFromAssetList({
symbol,
/** Denom as it exists on source chain. */
sourceDenom,
coinMinimalDenom,
coinGeckoId,
assetLists,
}: {
symbol?: string;
sourceDenom?: string;
coinMinimalDenom?: string;
coinGeckoId?: string;
assetLists: AssetList[];
}) {
if (!sourceDenom && !coinGeckoId && !coinMinimalDenom) {
if (!symbol && !sourceDenom && !coinGeckoId && !coinMinimalDenom) {
return undefined;
}

const asset = assetLists
.flatMap(({ assets }) => assets)
.find(
(asset) =>
(symbol && asset.symbol === symbol) ||
(sourceDenom && asset.sourceDenom === sourceDenom) ||
(asset.coingeckoId ? asset.coingeckoId === coinGeckoId : false) ||
asset.coinMinimalDenom === coinMinimalDenom
Expand Down
10 changes: 7 additions & 3 deletions packages/web/components/navbar-osmo-price.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { WalletStatus } from "@cosmos-kit/core";
import { makeMinimalAsset } from "@osmosis-labs/utils";
import classNames from "classnames";
import { observer } from "mobx-react-lite";
import Image from "next/image";
Expand All @@ -10,6 +11,7 @@ import { Sparkline } from "~/components/chart/sparkline";
import SkeletonLoader from "~/components/loaders/skeleton-loader";
import { Button } from "~/components/ui/button";
import { EventName } from "~/config";
import { AssetLists } from "~/config/generated/asset-lists";
import {
useAmplitudeAnalytics,
useDisclosure,
Expand All @@ -21,6 +23,11 @@ import { useStore } from "~/stores";
import { theme } from "~/tailwind.config";
import { api } from "~/utils/trpc";

const osmoAsset = AssetLists.flatMap(({ assets }) => assets).find(
(asset) => asset.symbol === "OSMO"
);
const osmoCurrency = makeMinimalAsset(osmoAsset!);

const NavbarOsmoPrice = observer(() => {
const { accountStore, chainStore } = useStore();
const { t } = useTranslation();
Expand All @@ -36,9 +43,6 @@ const NavbarOsmoPrice = observer(() => {
const { chainId } = chainStore.osmosis;
const wallet = accountStore.getWallet(chainId);

const { data: osmoCurrency } = api.edge.assets.getAsset.useQuery({
findMinDenomOrSymbol: "OSMO",
});
const { data: osmoPrice } = api.edge.assets.getAssetPrice.useQuery(
{ coinMinimalDenom: osmoCurrency?.coinMinimalDenom ?? "" },
{ enabled: Boolean(osmoCurrency) }
Expand Down
102 changes: 43 additions & 59 deletions packages/web/components/swap-tool/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -423,38 +423,29 @@ export const SwapTool: FunctionComponent<SwapToolProps> = observer(
</div>
</div>
<div className="mt-3 flex place-content-between items-center">
<SkeletonLoader
className={
swapState.isLoadingFromAsset
? "h-full w-full"
: "h-fit w-fit"
}
isLoaded={!swapState.isLoadingFromAsset}
>
<TokenSelectWithDrawer
isFromSelect
dropdownOpen={showFromTokenSelectDropdown}
swapState={swapState}
setDropdownState={useCallback(
(isOpen) => {
if (isOpen) {
setOneTokenSelectOpen("from");
} else {
closeTokenSelectDropdowns();
}
},
[setOneTokenSelectOpen, closeTokenSelectDropdowns]
)}
onSelect={useCallback(
(tokenDenom: string) => {
swapState.setFromAssetDenom(tokenDenom);
<TokenSelectWithDrawer
isFromSelect
dropdownOpen={showFromTokenSelectDropdown}
swapState={swapState}
setDropdownState={useCallback(
(isOpen) => {
if (isOpen) {
setOneTokenSelectOpen("from");
} else {
closeTokenSelectDropdowns();
fromAmountInputEl.current?.focus();
},
[swapState, closeTokenSelectDropdowns]
)}
/>
</SkeletonLoader>
}
},
[setOneTokenSelectOpen, closeTokenSelectDropdowns]
)}
onSelect={useCallback(
(tokenDenom: string) => {
swapState.setFromAssetDenom(tokenDenom);
closeTokenSelectDropdowns();
fromAmountInputEl.current?.focus();
},
[swapState, closeTokenSelectDropdowns]
)}
/>
<div className="flex w-full flex-col items-end">
<input
ref={fromAmountInputEl}
Expand Down Expand Up @@ -556,35 +547,28 @@ export const SwapTool: FunctionComponent<SwapToolProps> = observer(
</button>
<div className="rounded-xl bg-osmoverse-900 px-4 py-[22px] transition-all md:rounded-xl md:px-3 md:py-2.5">
<div className="flex place-content-between items-center transition-transform">
<SkeletonLoader
className={
swapState.isLoadingToAsset ? "h-full w-full" : "h-fit w-fit"
}
isLoaded={!swapState.isLoadingToAsset}
>
<TokenSelectWithDrawer
isFromSelect={false}
dropdownOpen={showToTokenSelectDropdown}
swapState={swapState}
onSelect={useCallback(
(tokenDenom: string) => {
swapState.setToAssetDenom(tokenDenom);
<TokenSelectWithDrawer
isFromSelect={false}
dropdownOpen={showToTokenSelectDropdown}
swapState={swapState}
onSelect={useCallback(
(tokenDenom: string) => {
swapState.setToAssetDenom(tokenDenom);
closeTokenSelectDropdowns();
},
[swapState, closeTokenSelectDropdowns]
)}
setDropdownState={useCallback(
(isOpen) => {
if (isOpen) {
setOneTokenSelectOpen("to");
} else {
closeTokenSelectDropdowns();
},
[swapState, closeTokenSelectDropdowns]
)}
setDropdownState={useCallback(
(isOpen) => {
if (isOpen) {
setOneTokenSelectOpen("to");
} else {
closeTokenSelectDropdowns();
}
},
[setOneTokenSelectOpen, closeTokenSelectDropdowns]
)}
/>
</SkeletonLoader>
}
},
[setOneTokenSelectOpen, closeTokenSelectDropdowns]
)}
/>
<div className="flex w-full flex-col items-end">
<h5
className={classNames(
Expand Down
91 changes: 48 additions & 43 deletions packages/web/hooks/use-swap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
NotEnoughQuotedError,
} from "@osmosis-labs/pools";
import { Currency } from "@osmosis-labs/types";
import { isNil } from "@osmosis-labs/utils";
import { isNil, makeMinimalAsset } from "@osmosis-labs/utils";
import { useQueryClient } from "@tanstack/react-query";
import { createTRPCReact, TRPCClientError } from "@trpc/react-query";
import { useRouter } from "next/router";
Expand All @@ -14,6 +14,8 @@ import { useMemo } from "react";
import { useCallback } from "react";
import { useEffect } from "react";

import { RecommendedSwapDenoms } from "~/config";
import { AssetLists } from "~/config/generated/asset-lists";
import { useShowPreviewAssets } from "~/hooks/use-show-preview-assets";
import type { RouterKey } from "~/server/api/edge-routers/swap-router";
import type { AppRouter } from "~/server/api/root";
Expand Down Expand Up @@ -286,11 +288,7 @@ export function useSwap({
isQuoteLoading,
/** Spot price or user input quote. */
isAnyQuoteLoading: isQuoteLoading || isSpotPriceQuoteLoading,
isLoading:
swapAssets.isLoadingFromAsset ||
swapAssets.isLoadingToAsset ||
isQuoteLoading ||
isSpotPriceQuoteLoading,
isLoading: isQuoteLoading || isSpotPriceQuoteLoading,
sendTradeTokenInTx,
};
}
Expand Down Expand Up @@ -366,25 +364,15 @@ export function useSwapAssets({
[selectableAssetPages?.pages]
);

const { asset: fromAsset, isLoading: isLoadingFromAsset } = useSwapAsset(
const { asset: fromAsset } = useSwapAsset(
fromAssetDenom,
allSelectableAssets
);
const { asset: toAsset, isLoading: isLoadingToAsset } = useSwapAsset(
toAssetDenom,
allSelectableAssets
);
const { asset: toAsset } = useSwapAsset(toAssetDenom, allSelectableAssets);

const { data: recommendedAssets_, isLoading: isLoadingRecommendedAssets } =
api.edge.assets.getRecommendedAssets.useQuery();
const recommendedAssets = useMemo(
() =>
recommendedAssets_?.filter(
(asset) =>
asset.coinMinimalDenom !== fromAsset?.coinMinimalDenom &&
asset.coinMinimalDenom !== toAsset?.coinMinimalDenom
) ?? [],
[recommendedAssets_, fromAsset, toAsset]
const recommendedAssets = useRecommendedAssets(
fromAsset?.coinMinimalDenom,
toAsset?.coinMinimalDenom
);

/** Remove to and from assets from assets that can be selected. */
Expand All @@ -404,13 +392,10 @@ export function useSwapAssets({
assetsQueryInput,
selectableAssets: filteredSelectableAssets,
isLoadingSelectAssets,
isLoadingFromAsset,
isLoadingToAsset,
hasNextPageAssets: hasNextPage,
isFetchingNextPageAssets: isFetchingNextPage,
/** Recommended assets, with to and from tokens filtered. */
recommendedAssets,
isLoadingRecommendedAssets,
setAssetsQueryInput,
setFromAssetDenom,
setToAssetDenom,
Expand Down Expand Up @@ -501,29 +486,23 @@ function useSwapAsset<TAsset extends Asset>(
asset.coinDenom === minDenomOrSymbol ||
asset.coinMinimalDenom === minDenomOrSymbol
);
const queryEnabled =
!isNil(minDenomOrSymbol) &&
typeof minDenomOrSymbol === "string" &&
!existingAsset;
const { data: asset, isLoading } = api.edge.assets.getAsset.useQuery(
{
findMinDenomOrSymbol: minDenomOrSymbol ?? "",
},
{
enabled: queryEnabled,
!existingAsset;
const asset = useMemo(() => {
if (existingAsset) return existingAsset;

const asset = AssetLists.flatMap(({ assets }) => assets).find(
(asset) =>
minDenomOrSymbol &&
(asset.symbol === minDenomOrSymbol ||
asset.coinMinimalDenom === minDenomOrSymbol)
);
if (!asset) return;

// since asset is often point of attention, don't block on other potentially expensive queries
trpc: {
context: {
skipBatch: true,
},
},
}
);
return makeMinimalAsset(asset);
}, [minDenomOrSymbol, existingAsset]);

return {
asset: existingAsset ?? (asset as TAsset),
isLoading: isLoading && !existingAsset,
};
}

Expand Down Expand Up @@ -677,3 +656,29 @@ function makeRouterErrorFromTrpcError(
};
}
}

/** Gets recommended assets directly from asset list. */
function useRecommendedAssets(
fromCoinMinimalDenom?: string,
toCoinMinimalDenom?: string
) {
return useMemo(
() =>
RecommendedSwapDenoms.map((denom) => {
const asset = AssetLists.flatMap(({ assets }) => assets).find(
(asset) => asset.symbol === denom
);
if (!asset) return;

return makeMinimalAsset(asset);
})
.filter((c): c is NonNullable<typeof c> => !!c)
.filter(
(currency) =>
currency &&
currency.coinMinimalDenom !== fromCoinMinimalDenom &&
currency.coinMinimalDenom !== toCoinMinimalDenom
),
[fromCoinMinimalDenom, toCoinMinimalDenom]
);
}
20 changes: 0 additions & 20 deletions packages/web/server/api/edge-routers/assets-router.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { PricePretty } from "@keplr-wallet/unit";
import { z } from "zod";

import { RecommendedSwapDenoms } from "~/config/feature-flag";
import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";
import {
Asset,
AssetFilterSchema,
getAsset,
getAssetHistoricalPrice,
Expand Down Expand Up @@ -35,15 +33,6 @@ const GetInfiniteAssetsInputSchema = InfiniteQuerySchema.merge(
).merge(UserOsmoAddressSchema);

export const assetsRouter = createTRPCRouter({
getAsset: publicProcedure
.input(
z.object({
findMinDenomOrSymbol: z.string(),
})
)
.query(async ({ input: { findMinDenomOrSymbol } }) =>
getAsset({ anyDenom: findMinDenomOrSymbol })
),
getUserAsset: publicProcedure
.input(
z
Expand Down Expand Up @@ -100,15 +89,6 @@ export const assetsRouter = createTRPCRouter({

return new PricePretty(DEFAULT_VS_CURRENCY, price);
}),
getRecommendedAssets: publicProcedure.query(async () => {
const assets = await Promise.all(
RecommendedSwapDenoms.map((denom) =>
getAsset({ anyDenom: denom }).catch(() => null)
)
);

return assets.filter((a): a is Asset => !!a);
}),
getMarketAsset: publicProcedure
.input(
z
Expand Down
2 changes: 1 addition & 1 deletion packages/web/server/api/edge-routers/swap-router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ async function makeDisplayableSplit(split: SplitTokenInQuote["split"]) {
});

return {
...pool,
id: pool.id,
spreadFactor: pool_?.spreadFactor,
type: pool_?.type,
inCurrency: inAsset,
Expand Down

0 comments on commit 6686302

Please sign in to comment.