From e8486e0752522dd69b6923987b0b4fa37344a068 Mon Sep 17 00:00:00 2001 From: Connor Barr Date: Wed, 12 Jun 2024 17:31:39 +0100 Subject: [PATCH] feat: first pass orderbook hook --- .../drawers/token-select-drawer-limit.tsx | 1 - .../web/components/place-limit-tool/index.tsx | 27 ++++- .../hooks/limit-orders/use-orderbook-pool.ts | 16 +-- .../web/hooks/limit-orders/use-orderbook.ts | 107 ++++++++++++++++++ 4 files changed, 139 insertions(+), 12 deletions(-) create mode 100644 packages/web/hooks/limit-orders/use-orderbook.ts diff --git a/packages/web/components/drawers/token-select-drawer-limit.tsx b/packages/web/components/drawers/token-select-drawer-limit.tsx index 095a8aab88..076652829d 100644 --- a/packages/web/components/drawers/token-select-drawer-limit.tsx +++ b/packages/web/components/drawers/token-select-drawer-limit.tsx @@ -202,7 +202,6 @@ export const TokenSelectDrawerLimit: FunctionComponent<{ const assetToActivate = assets.find( (asset) => asset.coinDenom === confirmUnverifiedAssetDenom ); - return (
= observer( ({ orderDirection = OrderDirection.Bid }) => { const { accountStore } = useStore(); const { t } = useTranslation(); + const { + selectableBaseDenoms, + selectableQuoteDenoms, + selectableBaseAssets, + } = useOrderbookSelectableDenoms(); const [reviewOpen, setReviewOpen] = useState(false); - const [baseDenom, setBaseDenom] = useState("ION"); - const quoteDenom = "OSMO"; + const [baseDenom, setBaseDenom] = useState("OSMO"); + const [quoteDenom, setQuoteDenom] = useState("USDC"); + + useEffect(() => { + if (selectableBaseDenoms.length > 0) { + const baseDenom = selectableBaseDenoms[0]; + setBaseDenom(baseDenom); + } + }, [selectableBaseDenoms, selectableQuoteDenoms]); + useEffect(() => { + if (Object.keys(selectableQuoteDenoms).length > 0) { + const quoteDenom = selectableQuoteDenoms[baseDenom][0]; + setQuoteDenom(quoteDenom); + } + }, [selectableQuoteDenoms, baseDenom]); const { poolId, contractAddress, makerFee } = useOrderbookPool({ baseDenom, @@ -56,7 +75,7 @@ export const PlaceLimitTool: FunctionComponent = observer( <>
{ - const [contractAddress] = useState( - "osmo1svmdh0ega4jg44xc3gg36tkjpzrzlrgajv6v6c2wf0ul8m3gjajs0dps9w" - ); + const { orderbook } = useOrderbookByDenoms({ + baseDenom, + quoteDenom, + }); const { accountStore } = useStore(); const { makerFee, isLoading: isMakerFeeLoading } = useMakerFee({ - orderbookAddress: contractAddress, + orderbookAddress: orderbook?.contractAddress ?? "", }); const account = accountStore.getWallet(accountStore.osmosisChainId); const orderState = useOrders({ - orderbookAddress: contractAddress, + orderbookAddress: orderbook?.contractAddress ?? "", userAddress: account?.address ?? "", }); return { poolId: "1", baseDenom, quoteDenom, - contractAddress, + contractAddress: orderbook?.contractAddress ?? "", makerFee, isMakerFeeLoading, orderState, diff --git a/packages/web/hooks/limit-orders/use-orderbook.ts b/packages/web/hooks/limit-orders/use-orderbook.ts new file mode 100644 index 0000000000..a052d3bf9f --- /dev/null +++ b/packages/web/hooks/limit-orders/use-orderbook.ts @@ -0,0 +1,107 @@ +import { getAssetFromAssetList, makeMinimalAsset } from "@osmosis-labs/utils"; +import { useMemo } from "react"; + +import { AssetLists } from "~/config/generated/asset-lists"; +import { api } from "~/utils/trpc"; + +const testnetOrderbooks = [ + { + baseDenom: "OSMO", + quoteDenom: "USDC", + contractAddress: + "osmo1kgvlc4gmd9rvxuq2e63m0fn4j58cdnzdnrxx924mrzrjclcgqx5qxn3dga", + }, + { + baseDenom: "ION", + quoteDenom: "OSMO", + contractAddress: + "osmo1ruxn39qj6x44gms8pfzw22kd7kemslc5fahgua3wuz0tkyks0uhq2f25wh", + }, +]; + +export const useOrderbooks = () => { + const { orderbooks, isLoading } = { + orderbooks: testnetOrderbooks, + isLoading: false, + }; + + return { orderbooks, isLoading }; +}; + +export const useOrderbookByDenoms = ({ + baseDenom, + quoteDenom, +}: { + baseDenom: string; + quoteDenom: string; +}) => { + const { orderbooks, isLoading } = useOrderbooks(); + + const orderbook = orderbooks.find( + (orderbook) => + orderbook.baseDenom === baseDenom && orderbook.quoteDenom === quoteDenom + ); + + return { orderbook, isLoading }; +}; + +export const useOrderbookSelectableDenoms = () => { + const { orderbooks, isLoading } = useOrderbooks(); + + const { data: selectableAssetPages } = + api.edge.assets.getUserAssets.useInfiniteQuery( + { + limit: 50, // items per page + }, + { + enabled: true, + getNextPageParam: (lastPage: any) => lastPage.nextCursor, + initialCursor: 0, + } + ); + + const selectableBaseDenoms = useMemo(() => { + const selectableDenoms = orderbooks.map((orderbook) => orderbook.baseDenom); + return Array.from(new Set(selectableDenoms)); + }, [orderbooks]); + + const selectableAssets = useMemo(() => { + return selectableAssetPages?.pages.flatMap((page) => page.items) ?? []; + }, [selectableAssetPages]); + + const selectableBaseAssets = selectableBaseDenoms.map((denom) => { + const existingAsset = selectableAssets.find( + (asset) => asset.coinDenom === denom + ); + if (existingAsset) { + return existingAsset; + } + const asset = getAssetFromAssetList({ + symbol: denom, + sourceDenom: denom, + assetLists: AssetLists, + }); + + if (!asset) return; + + return makeMinimalAsset(asset.rawAsset); + }); + + console.log(selectableBaseAssets); + const selectableQuoteDenoms = useMemo(() => { + const quoteDenoms: Record = {}; + for (let i = 0; i < selectableBaseDenoms.length; i++) { + quoteDenoms[selectableBaseDenoms[i]] = orderbooks + .filter((orderbook) => orderbook.baseDenom === selectableBaseDenoms[i]) + .map((orderbook) => orderbook.quoteDenom); + } + return quoteDenoms; + }, [selectableBaseDenoms, orderbooks]); + + return { + selectableBaseDenoms, + selectableQuoteDenoms, + selectableBaseAssets, + isLoading, + }; +};