diff --git a/package.json b/package.json index e150e5ae..8f26df3e 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,6 @@ "@tippyjs/react": "^4.2.6", "bignumber.js": "^9.1.1", "classnames": "^2.3.2", - "graphql-request": "^6.0.0", "moment": "^2.29.4", "next": "^13.4.3", "react": "^18.2.0", diff --git a/src/api/cosmwasm-client.ts b/src/api/cosmwasm-client.ts index 40d0aa78..08a3f7ef 100644 --- a/src/api/cosmwasm-client.ts +++ b/src/api/cosmwasm-client.ts @@ -7,7 +7,7 @@ let _cosmWasmClient: CosmWasmClient const getClient = async () => { try { if (!_cosmWasmClient) { - _cosmWasmClient = await CosmWasmClient.connect(ENV.URL_RPC || '') + _cosmWasmClient = await CosmWasmClient.connect(ENV.URL_RPC) } return _cosmWasmClient diff --git a/src/api/markets/getMarketBalances.ts b/src/api/markets/getMarketBalances.ts deleted file mode 100644 index 78920b80..00000000 --- a/src/api/markets/getMarketBalances.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { gql, request as gqlRequest } from 'graphql-request' - -import { ENV } from 'constants/env' - -export default async function getBalances() { - const result = await gqlRequest( - ENV.URL_GQL, - gql` - query RedbankBalances { - bank { - balance( - address: "${ENV.ADDRESS_RED_BANK}" - ) { - amount - denom - } - } - } - `, - ) - - return result.bank.balance -} - -interface Result { - bank: { - balance: Coin[] - } -} diff --git a/src/api/markets/getMarketDebts.ts b/src/api/markets/getMarketDebts.ts index 0bbaa250..cb7c4f80 100644 --- a/src/api/markets/getMarketDebts.ts +++ b/src/api/markets/getMarketDebts.ts @@ -1,54 +1,24 @@ -import { gql, request as gqlRequest } from 'graphql-request' - import { ENV } from 'constants/env' -import { denomToKey, getContractQuery, keyToDenom } from 'utils/query' import getMarkets from 'api/markets/getMarkets' +import { getClient } from 'api/cosmwasm-client' export default async function getMarketDebts(): Promise { - const markets: Market[] = await getMarkets() + try { + const markets: Market[] = await getMarkets() + const client = await getClient() - let query = '' - - markets.forEach((asset) => { - query += getContractQuery( - denomToKey(asset.denom), - ENV.ADDRESS_RED_BANK || '', - ` - { + const debtQueries = markets.map((asset) => + client.queryContractSmart(ENV.ADDRESS_RED_BANK, { underlying_debt_amount: { - denom: "${asset.denom}" - amount_scaled: "${asset.debtTotalScaled}" - } - }`, + denom: asset.denom, + amount_scaled: asset.debtTotalScaled, + }, + }), ) - }) + const debtsResults = await Promise.all(debtQueries) - const result = await gqlRequest( - ENV.URL_GQL, - gql` - query RedbankBalances { - debts: wasm { - ${query} - } - } - `, - ) - - if (result) { - const debts = Object.keys(result.debts).map((key) => { - return { - denom: keyToDenom(key), - amount: result.debts[key], - } - }) - return debts - } - - return new Promise((_, reject) => reject('No data')) -} - -interface DebtsQuery { - debts: { - [key: string]: string + return debtsResults.map((debt, index) => ({ denom: markets[index].denom, amount: debt })) + } catch (ex) { + throw ex } } diff --git a/src/api/markets/getMarketDeposits.ts b/src/api/markets/getMarketDeposits.ts index f4b4e337..4a2e9b39 100644 --- a/src/api/markets/getMarketDeposits.ts +++ b/src/api/markets/getMarketDeposits.ts @@ -1,54 +1,27 @@ -import { gql, request as gqlRequest } from 'graphql-request' - import { ENV } from 'constants/env' -import { denomToKey, getContractQuery, keyToDenom } from 'utils/query' import getMarkets from 'api/markets/getMarkets' +import { getClient } from 'api/cosmwasm-client' export default async function getMarketDeposits(): Promise { - const markets = await getMarkets() + try { + const markets: Market[] = await getMarkets() + const client = await getClient() - let query = '' - - markets.forEach((market: Market) => { - query += getContractQuery( - denomToKey(market.denom), - ENV.ADDRESS_RED_BANK || '', - ` - { - underlying_liquidity_amount: { - denom: "${market.denom}" - amount_scaled: "${market.collateralTotalScaled}" - } - }`, + const depositQueries = markets.map((asset) => + client.queryContractSmart(ENV.ADDRESS_RED_BANK, { + underlying_liquidity_amount: { + denom: asset.denom, + amount_scaled: asset.collateralTotalScaled, + }, + }), ) - }) + const depositsResults = await Promise.all(depositQueries) - const result = await gqlRequest( - ENV.URL_GQL, - gql` - query RedbankBalances { - deposits: wasm { - ${query} - } - } - `, - ) - - if (result) { - const deposits = Object.keys(result.deposits).map((key) => { - return { - denom: keyToDenom(key), - amount: result.deposits[key], - } - }) - return deposits - } - - return new Promise((_, reject) => reject('No data')) -} - -interface DepositsQuery { - deposits: { - [key: string]: string + return depositsResults.map((deposit, index) => ({ + denom: markets[index].denom, + amount: deposit, + })) + } catch (ex) { + throw ex } } diff --git a/src/api/markets/getMarkets.ts b/src/api/markets/getMarkets.ts index e7bccb2c..381341a9 100644 --- a/src/api/markets/getMarkets.ts +++ b/src/api/markets/getMarkets.ts @@ -1,41 +1,24 @@ -import { gql, request as gqlRequest } from 'graphql-request' - import { ENV } from 'constants/env' -import { getMarketAssets } from 'utils/assets' -import { denomToKey } from 'utils/query' +import { getEnabledMarketAssets } from 'utils/assets' import { resolveMarketResponses } from 'utils/resolvers' +import { getClient } from 'api/cosmwasm-client' export default async function getMarkets(): Promise { - const marketAssets = getMarketAssets() + try { + const enabledAssets = getEnabledMarketAssets() + const client = await getClient() - const marketQueries = marketAssets.map( - (asset: Asset) => - `${denomToKey(asset.denom)}: contractQuery( - contractAddress: "${ENV.ADDRESS_RED_BANK}" - query: { market: { denom: "${asset.denom}" } } - )`, - ) + const marketQueries = enabledAssets.map((asset) => + client.queryContractSmart(ENV.ADDRESS_RED_BANK, { + market: { + denom: asset.denom, + }, + }), + ) + const marketResults = await Promise.all(marketQueries) - const result = await gqlRequest( - ENV.URL_GQL, - gql` - query RedbankQuery { - rbwasmkey: wasm { - ${marketQueries} - } - } - `, - ) - - const markets = marketAssets.map((asset) => { - const market = result.rbwasmkey[`${denomToKey(asset.denom)}`] - return market - }) - return resolveMarketResponses(markets) -} - -interface RedBankData { - rbwasmkey: { - [key: string]: MarketResponse + return resolveMarketResponses(marketResults) + } catch (ex) { + throw ex } } diff --git a/src/api/prices/getPrices.ts b/src/api/prices/getPrices.ts index f188e72f..841ec73a 100644 --- a/src/api/prices/getPrices.ts +++ b/src/api/prices/getPrices.ts @@ -1,59 +1,36 @@ -import { gql, request as gqlRequest } from 'graphql-request' - import { ASSETS } from 'constants/assets' import { ENV } from 'constants/env' -import { getMarketAssets } from 'utils/assets' +import { getEnabledMarketAssets } from 'utils/assets' import { BN } from 'utils/helpers' +import { getClient } from 'api/cosmwasm-client' export default async function getPrices(): Promise { - const marketAssets = getMarketAssets() - const baseCurrency = ASSETS[0] + try { + const enabledAssets = getEnabledMarketAssets() + const client = await getClient() + const baseCurrency = ASSETS[0] - const result = await gqlRequest( - ENV.URL_GQL, - gql` - query PriceOracle { - prices: wasm { - ${marketAssets.map((asset) => { - return `${asset.id}: contractQuery( - contractAddress: "${ENV.ADDRESS_ORACLE}" - query: { - price: { - denom: "${asset.denom}" - } - } - )` - })} - } + const priceQueries = enabledAssets.map((asset) => + client.queryContractSmart(ENV.ADDRESS_ORACLE, { + price: { + denom: asset.denom, + }, + }), + ) + const priceResults: PriceResult[] = await Promise.all(priceQueries) + + const assetPrices = priceResults.map(({ denom, price }, index) => { + const asset = enabledAssets[index] + const decimalDiff = asset.decimals - baseCurrency.decimals + + return { + denom, + amount: BN(price).shiftedBy(decimalDiff).toString(), } - `, - ) + }) - const data: Coin[] = Object.values(result?.prices).reduce((acc: Coin[], curr) => { - const asset = marketAssets.find((asset) => asset.denom === curr.denom) - const additionalDecimals = asset - ? asset.decimals > baseCurrency.decimals - ? asset.decimals - baseCurrency.decimals - : 0 - : 0 - - return [ - ...acc, - { - denom: curr.denom, - amount: BN(curr.price).shiftedBy(additionalDecimals).toString(), - }, - ] as Coin[] - }, []) - - return data -} - -interface TokenPricesResult { - prices: { - [key: string]: { - denom: string - price: string - } + return assetPrices + } catch (ex) { + throw ex } } diff --git a/src/components/Borrow/AssetExpanded.tsx b/src/components/Borrow/AssetExpanded.tsx index 0be6516b..3afb6991 100644 --- a/src/components/Borrow/AssetExpanded.tsx +++ b/src/components/Borrow/AssetExpanded.tsx @@ -2,7 +2,7 @@ import { Row } from '@tanstack/react-table' import Button from 'components/Button' import useStore from 'store' -import { getMarketAssets } from 'utils/assets' +import { getEnabledMarketAssets } from 'utils/assets' type AssetRowProps = { row: Row @@ -12,7 +12,7 @@ type AssetRowProps = { } export default function AssetExpanded(props: AssetRowProps) { - const marketAssets = getMarketAssets() + const marketAssets = getEnabledMarketAssets() const asset = marketAssets.find((asset) => asset.denom === props.row.original.denom) let isActive: boolean = false diff --git a/src/components/Borrow/AssetRow.tsx b/src/components/Borrow/AssetRow.tsx index cbaa202f..910ae6d2 100644 --- a/src/components/Borrow/AssetRow.tsx +++ b/src/components/Borrow/AssetRow.tsx @@ -1,7 +1,7 @@ import { flexRender, Row } from '@tanstack/react-table' import classNames from 'classnames' -import { getMarketAssets } from 'utils/assets' +import { getEnabledMarketAssets } from 'utils/assets' type AssetRowProps = { row: Row @@ -9,7 +9,7 @@ type AssetRowProps = { } export const AssetRow = (props: AssetRowProps) => { - const marketAssets = getMarketAssets() + const marketAssets = getEnabledMarketAssets() const asset = marketAssets.find((asset) => asset.denom === props.row.original.denom) if (!asset) return null diff --git a/src/components/Borrow/BorrowTable.tsx b/src/components/Borrow/BorrowTable.tsx index 388ee469..3320566a 100644 --- a/src/components/Borrow/BorrowTable.tsx +++ b/src/components/Borrow/BorrowTable.tsx @@ -17,7 +17,7 @@ import { ChevronDown, SortAsc, SortDesc, SortNone } from 'components/Icons' import Loading from 'components/Loading' import Text from 'components/Text' import TitleAndSubCell from 'components/TitleAndSubCell' -import { getMarketAssets } from 'utils/assets' +import { getEnabledMarketAssets } from 'utils/assets' import { formatPercent } from 'utils/formatters' type Props = { @@ -26,7 +26,7 @@ type Props = { export const BorrowTable = (props: Props) => { const [sorting, setSorting] = React.useState([]) - const marketAssets = getMarketAssets() + const marketAssets = getEnabledMarketAssets() const columns = React.useMemo[]>( () => [ diff --git a/src/components/Borrow/Borrowings.tsx b/src/components/Borrow/Borrowings.tsx index 40fe8299..2599a397 100644 --- a/src/components/Borrow/Borrowings.tsx +++ b/src/components/Borrow/Borrowings.tsx @@ -2,7 +2,7 @@ import { Suspense } from 'react' import { useParams } from 'react-router-dom' import Card from 'components/Card' -import { getMarketAssets } from 'utils/assets' +import { getEnabledMarketAssets } from 'utils/assets' import { BorrowTable } from 'components/Borrow/BorrowTable' import useAccountDebts from 'hooks/useAccountDebts' import useMarketBorrowings from 'hooks/useMarketBorrowings' @@ -16,7 +16,7 @@ function Content(props: Props) { const { data: debtData } = useAccountDebts(accountId) const { data: borrowData } = useMarketBorrowings() - const marketAssets = getMarketAssets() + const marketAssets = getEnabledMarketAssets() function getBorrowAssets() { return marketAssets.reduce( @@ -60,7 +60,7 @@ function Content(props: Props) { } function Fallback() { - const marketAssets = getMarketAssets() + const marketAssets = getEnabledMarketAssets() const available: BorrowAsset[] = marketAssets.reduce((prev: BorrowAsset[], curr) => { prev.push({ ...curr, borrowRate: null, liquidity: null }) diff --git a/src/components/Wallet/ConnectedButton.tsx b/src/components/Wallet/ConnectedButton.tsx index f031a45b..2a3be445 100644 --- a/src/components/Wallet/ConnectedButton.tsx +++ b/src/components/Wallet/ConnectedButton.tsx @@ -18,7 +18,7 @@ import Text from 'components/Text' import { IS_TESTNET } from 'constants/env' import useToggle from 'hooks/useToggle' import useStore from 'store' -import { getBaseAsset, getMarketAssets } from 'utils/assets' +import { getBaseAsset, getEnabledMarketAssets } from 'utils/assets' import { formatValue, truncate } from 'utils/formatters' import useWalletBalances from 'hooks/useWalletBalances' @@ -26,7 +26,7 @@ export default function ConnectedButton() { // --------------- // EXTERNAL HOOKS // --------------- - const marketAssets = getMarketAssets() + const marketAssets = getEnabledMarketAssets() const { disconnect } = useWallet() const { disconnect: terminate } = useWalletManager() const address = useStore((s) => s.address) diff --git a/src/types/interfaces/responses.d.ts b/src/types/interfaces/responses.d.ts index 8fe8b7ee..3f8ccb4c 100644 --- a/src/types/interfaces/responses.d.ts +++ b/src/types/interfaces/responses.d.ts @@ -29,3 +29,8 @@ interface MarketResponse { borrow_enabled: boolean deposit_cap: string } + +interface PriceResult { + denom: string + price: string +} diff --git a/src/utils/assets.ts b/src/utils/assets.ts index 233b14bd..80dc8c71 100644 --- a/src/utils/assets.ts +++ b/src/utils/assets.ts @@ -8,7 +8,7 @@ export function getAssetBySymbol(symbol: string) { return ASSETS.find((asset) => asset.symbol === symbol) } -export function getMarketAssets(): Asset[] { +export function getEnabledMarketAssets(): Asset[] { return ASSETS.filter((asset) => asset.isEnabled && asset.isMarket) } diff --git a/src/utils/formatters.ts b/src/utils/formatters.ts index fb66bb6e..ffd2bee4 100644 --- a/src/utils/formatters.ts +++ b/src/utils/formatters.ts @@ -1,6 +1,6 @@ import BigNumber from 'bignumber.js' -import { getMarketAssets } from 'utils/assets' +import { getEnabledMarketAssets } from 'utils/assets' import { BN } from 'utils/helpers' export function truncate(text = '', [h, t]: [number, number] = [6, 6]): string { @@ -126,7 +126,7 @@ export function formatPercent(percent: number | string, minDecimals?: number) { } export function formatAmountWithSymbol(coin: Coin) { - const marketAssets = getMarketAssets() + const marketAssets = getEnabledMarketAssets() const asset = marketAssets.find((asset) => asset.denom === coin.denom) @@ -157,7 +157,7 @@ export function demagnify(amount: number | string | BigNumber, asset: Asset) { export function convertToDisplayAmount(coin: Coin, displayCurrency: Asset, prices: Coin[]) { const price = prices.find((price) => price.denom === coin.denom) - const asset = getMarketAssets().find((asset) => asset.denom === coin.denom) + const asset = getEnabledMarketAssets().find((asset) => asset.denom === coin.denom) const displayPrice = prices.find((price) => price.denom === displayCurrency.denom) if (!price || !asset || !displayPrice) return '0' diff --git a/yarn.lock b/yarn.lock index 2ecdeadd..47244239 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2059,7 +2059,7 @@ "@ethersproject/properties" "^5.7.0" "@ethersproject/strings" "^5.7.0" -"@graphql-typed-document-node/core@^3.1.1", "@graphql-typed-document-node/core@^3.2.0": +"@graphql-typed-document-node/core@^3.1.1": version "3.2.0" resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861" integrity sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ== @@ -4719,13 +4719,6 @@ create-hmac@^1.1.4, create-hmac@^1.1.7: safe-buffer "^5.0.1" sha.js "^2.4.8" -cross-fetch@^3.1.5: - version "3.1.5" - resolved "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz" - integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== - dependencies: - node-fetch "2.6.7" - cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" @@ -6072,14 +6065,6 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== -graphql-request@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-6.0.0.tgz#9c8b6a0c341f289e049936d03cc9205300faae1c" - integrity sha512-2BmHTuglonjZvmNVw6ZzCfFlW/qkIPds0f+Qdi/Lvjsl3whJg2uvHmSvHnLWhUTEw6zcxPYAHiZoPvSVKOZ7Jw== - dependencies: - "@graphql-typed-document-node/core" "^3.2.0" - cross-fetch "^3.1.5" - graphql-tag@^2.12.6: version "2.12.6" resolved "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz" @@ -7532,13 +7517,6 @@ node-addon-api@^5.0.0: resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz" integrity sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA== -node-fetch@2.6.7: - version "2.6.7" - resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz" - integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== - dependencies: - whatwg-url "^5.0.0" - node-fetch@^2.6.7: version "2.6.9" resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz"