diff --git a/.env.example b/.env.example
index 167425fd..5eb59ecd 100644
--- a/.env.example
+++ b/.env.example
@@ -1,37 +1,16 @@
-# DEVNET #
-NEXT_PUBLIC_NETWORK=devnet
-NEXT_PUBLIC_CHAIN_ID=devnet
-NEXT_PUBLIC_RPC=https://rpc.devnet.osmosis.zone/
-NEXT_PUBLIC_GQL=https://devnet-osmosis-gql.marsprotocol.io/graphql
-NEXT_PUBLIC_REST=https://lcd.devnet.osmosis.zone/
-
-
-# MAINNET #
NEXT_PUBLIC_NETWORK=mainnet
-NEXT_PUBLIC_CHAIN_ID=osmosis-1
-NEXT_PUBLIC_RPC=https://osmosis-node.marsprotocol.io/GGSFGSFGFG34/osmosis-rpc-front/
-NEXT_PUBLIC_GQL=https://osmosis-node.marsprotocol.io/GGSFGSFGFG34/osmosis-hive-front/graphql
-NEXT_PUBLIC_REST=https://osmosis-node.marsprotocol.io/GGSFGSFGFG34/osmosis-lcd-front/
+NEXT_PUBLIC_OSMOSIS_RPC=https://osmosis-node.marsprotocol.io/GGSFGSFGFG34/osmosis-rpc-front/
+NEXT_PUBLIC_OSMOSIS_REST=https://osmosis-node.marsprotocol.io/GGSFGSFGFG34/osmosis-lcd-front/
+NEXT_PUBLIC_OSMOSIS_TEST_RPC=https://rpc.devnet.osmosis.zone/
+NEXT_PUBLIC_OSMOSIS_TEST_REST=https://lcd.devnet.osmosis.zone/
+NEXT_PUBLIC_NEUTRON_TEST_RPC=https://rpc-palvus.pion-1.ntrn.tech/
+NEXT_PUBLIC_NEUTRON_TEST_REST=https://rest-palvus.pion-1.ntrn.tech/
-# COMMON #
-NEXT_PUBLIC_SWAP=https://app.osmosis.zone
-NEXT_PUBLIC_VAULT_APR=https://api.marsprotocol.io/v1/vaults/osmosis
-NEXT_PUBLIC_ACCOUNT_NFT=osmo1450hrg6dv2l58c0rvdwx8ec2a0r6dd50hn4frk370tpvqjhy8khqw7sw09
-NEXT_PUBLIC_ORACLE=osmo1mhznfr60vjdp2gejhyv2gax9nvyyzhd3z0qcwseyetkfustjauzqycsy2g
-NEXT_PUBLIC_RED_BANK=osmo1c3ljch9dfw5kf52nfwpxd2zmj2ese7agnx0p9tenkrryasrle5sqf3ftpg
-NEXT_PUBLIC_CREDIT_MANAGER=osmo1f2m24wktq0sw3c0lexlg7fv4kngwyttvzws3a3r3al9ld2s2pvds87jqvf
-NEXT_PUBLIC_INCENTIVES=osmo1nkahswfr8shg8rlxqwup0vgahp0dk4x8w6tkv3rra8rratnut36sk22vrm
-NEXT_PUBLIC_SWAPPER=osmo1wee0z8c7tcawyl647eapqs4a88q8jpa7ddy6nn2nrs7t47p2zhxswetwla
-NEXT_PUBLIC_PYTH=osmo13ge29x4e2s63a8ytz2px8gurtyznmue4a69n5275692v3qn3ks8q7cwck7
-NEXT_PUBLIC_ZAPPER=osmo17qwvc70pzc9mudr8t02t3pl74hhqsgwnskl734p4hug3s8mkerdqzduf7c
-NEXT_PUBLIC_PARAMS=osmo1nlmdxt9ctql2jr47qd4fpgzg84cjswxyw6q99u4y4u4q6c2f5ksq7ysent
-NEXT_PUBLIC_PYTH_ENDPOINT=https://hermes.pyth.network/api
-NEXT_PUBLIC_MAINNET_REST=https://osmosis-node.marsprotocol.io/GGSFGSFGFG34/osmosis-rpc-front/
-NEXT_PUBLIC_CANDLES_ENDPOINT_THE_GRAPH=https://osmosis-candles.marsprotocol.io/
-NEXT_PUBLIC_CANDLES_ENDPOINT_PYTH=https://benchmarks.pyth.network
NEXT_PUBLIC_WALLET_CONNECT_ID=d93fdffb159bae5ec87d8fee4cdbb045
-CHARTING_LIBRARY_REPOSITORY=github.com/tradingview/charting_library
-CHARTING_LIBRARY_ACCESS_TOKEN=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
-CHARTING_LIBRARY_USERNAME=mars-git-demo
-NEXT_PUBLIC_STRIDE_APRS=https://edge.stride.zone/api/stake-stats
+CHARTING_LIBRARY_USERNAME=git_username
+CHARTING_LIBRARY_ACCESS_TOKEN=access_token
+CHARTING_LIBRARY_REPOSITORY=github.com/tradingview/charting_library/
+
+NEXT_PUBLIC_PYTH_API=https://mars.rpc.p2p.world/api
+
diff --git a/__mocks__/fileMock.js b/__mocks__/fileMock.js
deleted file mode 100644
index 8761cdaa..00000000
--- a/__mocks__/fileMock.js
+++ /dev/null
@@ -1,6 +0,0 @@
-module.exports = {
- src: '/img.jpg',
- height: 24,
- width: 24,
- blurDataURL: 'data:image/png;base64,imagedata',
-}
diff --git a/__mocks__/helmet.js b/__mocks__/helmet.js
deleted file mode 100644
index 34967f49..00000000
--- a/__mocks__/helmet.js
+++ /dev/null
@@ -1,17 +0,0 @@
-jest.mock('react-helmet-async', () => {
- const React = require('react')
- const plugin = jest.requireActual('react-helmet-async')
- const mockHelmet = ({ children, ...props }) =>
- React.createElement(
- 'div',
- {
- ...props,
- className: 'mock-helmet',
- },
- children,
- )
- return {
- ...plugin,
- Helmet: jest.fn().mockImplementation(mockHelmet),
- }
-})
\ No newline at end of file
diff --git a/__mocks__/store.js b/__mocks__/store.js
deleted file mode 100644
index 0ceb53cc..00000000
--- a/__mocks__/store.js
+++ /dev/null
@@ -1,23 +0,0 @@
-jest.mock('store', () => {
- let state = {}
-
- const mockUseStore = (selectorFn) => {
- return selectorFn(state)
- }
-
- mockUseStore.setState = (newState) => {
- state = {
- ...state,
- ...newState,
- }
- }
-
- mockUseStore.clearState = () => {
- state = {}
- }
-
- return {
- __esModule: true,
- default: mockUseStore,
- }
-})
diff --git a/__mocks__/styleMock.js b/__mocks__/styleMock.js
deleted file mode 100644
index 4ba52ba2..00000000
--- a/__mocks__/styleMock.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = {}
diff --git a/__mocks__/svgMock.js b/__mocks__/svgMock.js
deleted file mode 100644
index 1e37d85b..00000000
--- a/__mocks__/svgMock.js
+++ /dev/null
@@ -1,7 +0,0 @@
-/* eslint-disable react/display-name */
-import React from 'react'
-
-const SvgrMock = React.forwardRef((props, ref) => )
-
-export const ReactComponent = SvgrMock
-export default SvgrMock
diff --git a/__tests__/Footer.test.tsx b/__tests__/Footer.test.tsx
deleted file mode 100644
index d68cd3a8..00000000
--- a/__tests__/Footer.test.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import { render } from '@testing-library/react'
-
-import Footer from 'components/Footer'
-
-import packageJSON from '../package.json'
-
-describe('', () => {
- it('should render package version correctly', () => {
- const { getByText, container } = render()
- const versionText = getByText(`v${packageJSON.version}`)
-
- expect(versionText).toBeInTheDocument()
- })
-})
diff --git a/__tests__/components/Account/AccountDetails.test.tsx b/__tests__/components/Account/AccountDetails.test.tsx
deleted file mode 100644
index d4f81f84..00000000
--- a/__tests__/components/Account/AccountDetails.test.tsx
+++ /dev/null
@@ -1,67 +0,0 @@
-import { render, screen } from '@testing-library/react'
-
-import AccountDetails from 'components/Account/AccountDetails'
-import useCurrentAccount from 'hooks/useCurrentAccount'
-import useStore from 'store'
-
-jest.mock('react-router', () => ({
- ...(jest.requireActual('react-router') as {}),
- useLocation: jest.fn().mockImplementation(() => {
- return { pathname: '/testroute' }
- }),
-}))
-jest.mock('hooks/useCurrentAccount', () => jest.fn(() => null))
-jest.mock('hooks/useHealthComputer', () =>
- jest.fn(() => ({
- health: 0,
- })),
-)
-// AccountBalancesTable component has wallet provider dependency, so we mock it
-jest.mock('components/Account/AccountBalancesTable', () => jest.fn(() => null))
-
-const mockedUseCurrentAccount = useCurrentAccount as jest.Mock
-const mockedAccounts: Account[] = [
- { id: '1', deposits: [], lends: [], debts: [], vaults: [], kind: 'default' },
- { id: '2', deposits: [], lends: [], debts: [], vaults: [], kind: 'default' },
-]
-jest.mock('hooks/useAccountId', () => jest.fn(() => '1'))
-jest.mock('hooks/useAccounts', () =>
- jest.fn(() => ({
- data: mockedAccounts,
- })),
-)
-jest.mock('hooks/useAccountIds', () =>
- jest.fn(() => ({
- data: ['1', '2'],
- })),
-)
-jest.mock('hooks/useCurrentAccount', () => jest.fn(() => mockedAccounts[0]))
-
-describe(' ', () => {
- beforeAll(() => {
- useStore.setState({
- address: 'walletAddress',
- accounts: mockedAccounts,
- })
- })
-
- afterAll(() => {
- useStore.clearState()
- })
-
- it('renders account details WHEN account is selected', () => {
- mockedUseCurrentAccount.mockReturnValue(mockedAccounts)
- render( )
-
- const container = screen.queryByTestId('account-details')
- expect(container).toBeInTheDocument()
- })
-
- it('does not render WHEN account is NOT selected', () => {
- mockedUseCurrentAccount.mockReturnValue(null)
- render( )
-
- const container = screen.queryByTestId('account-details')
- expect(container).not.toBeInTheDocument()
- })
-})
diff --git a/__tests__/components/Button/Button.test.tsx b/__tests__/components/Button/Button.test.tsx
deleted file mode 100644
index 7e52b677..00000000
--- a/__tests__/components/Button/Button.test.tsx
+++ /dev/null
@@ -1,157 +0,0 @@
-import { cleanup, render } from '@testing-library/react'
-
-import Button from 'components/Button'
-import {
- buttonColorClasses,
- buttonSizeClasses,
- buttonVariantClasses,
- focusClasses,
-} from 'components/Button/constants'
-import { parseMockComponentProps } from 'utils/testing'
-
-jest.mock('components/CircularProgress', () => {
- return {
- CircularProgress: (props: any) =>
- require('utils/testing').createMockComponent('circular-progress-component', props),
- }
-})
-
-describe(' ', () => {
- afterAll(() => {
- jest.unmock('components/CircularProgress')
- })
-
- it('should render', () => {
- const { container } = render( )
- expect(container).toBeInTheDocument()
- })
-
- it('should render `children` when its passed', () => {
- const children = Hello World!
- const { getByTestId } = render({children} )
-
- expect(getByTestId('test-id')).toBeInTheDocument()
- })
-
- it('should handle `className` prop correctly', () => {
- const testClass = 'test-class'
- const { container } = render( )
-
- expect(container.querySelector('button')).toHaveClass(testClass)
- })
-
- it('should handle `color` prop correctly', () => {
- const colors = Object.keys(buttonColorClasses) as [keyof typeof buttonColorClasses]
-
- colors.forEach((color) => {
- const { container } = render( )
-
- expect(container.querySelector('button')).toHaveClass(buttonColorClasses[color])
- })
- })
-
- it('should handle `disabled=true` prop correctly', () => {
- const testFunction = jest.fn()
- const { container } = render( )
- const button = container.querySelector('button')
-
- button?.click()
-
- expect(button).toHaveClass('pointer-events-none')
- expect(testFunction).not.toBeCalled()
- })
-
- it('should handle `disabled=false` prop correctly', () => {
- const testFunction = jest.fn()
- const { container } = render( )
- const button = container.querySelector('button')
-
- button?.click()
-
- expect(button).not.toHaveClass('pointer-events-none')
- expect(testFunction).toBeCalled()
- })
-
- it('should show progress indicator when `showProgressIndicator=true`', () => {
- const { getByTestId } = render( )
- const circularProgressComponent = getByTestId('circular-progress-component')
-
- expect(circularProgressComponent).toBeInTheDocument()
- })
-
- it('should set correct values for progress indicator size', () => {
- const sizeValues = { xs: 8, sm: 10, md: 12, lg: 18 }
-
- Object.entries(sizeValues).forEach(([size, value]) => {
- const { getByTestId } = render(
- ,
- )
- const circularProgressComponent = getByTestId('circular-progress-component')
- const sizeProp = parseMockComponentProps(circularProgressComponent).size
-
- expect(sizeProp).toBe(value)
- cleanup()
- })
- })
-
- it('should handle `size` prop correctly', () => {
- const sizes = Object.keys(buttonSizeClasses) as [keyof typeof buttonSizeClasses]
-
- sizes.forEach((size) => {
- const { container } = render( )
-
- expect(container.querySelector('button')).toHaveClass(buttonSizeClasses[size])
- })
- })
-
- it('should show `text` when its passed', () => {
- const text = 'Hello!'
- const { getByText } = render( )
-
- expect(getByText(text)).toBeInTheDocument()
- })
-
- it('should handle `variant` prop correctly', () => {
- const variants = Object.keys(buttonVariantClasses) as [keyof typeof buttonVariantClasses]
-
- variants.forEach((variant) => {
- const { container } = render( )
-
- expect(container.querySelector('button')).toHaveClass(buttonVariantClasses[variant])
- })
- })
-
- it('should show left icon when `leftIcon` prop is passed', () => {
- const icon = this is the left icon
- const { getByTestId } = render( )
-
- expect(getByTestId('left-icon')).toBeInTheDocument()
- })
-
- it('should show right icon when `rightIcon` prop is passed', () => {
- const icon = this is the right icon
- const { getByTestId } = render( )
-
- expect(getByTestId('right-icon')).toBeInTheDocument()
- })
-
- it('should handle `iconClassName` prop correctly', () => {
- const icon = just an icon
- const { getByTestId } = render( )
-
- expect(getByTestId('icon').parentElement).toHaveClass('test-icon-class')
- })
-
- it('should show submenu indicator when `hasSubmenu=true`', () => {
- const { getByTestId } = render( )
-
- expect(getByTestId('button-submenu-indicator')).toBeInTheDocument()
- })
-
- it('should set focus classes when `hasFocus=true`', () => {
- const { container } = render( )
- const button = container.querySelector('button')
-
- expect(button).toHaveClass(focusClasses['primary'])
- })
-})
diff --git a/__tests__/components/Card.test.tsx b/__tests__/components/Card.test.tsx
deleted file mode 100644
index 4bd8e615..00000000
--- a/__tests__/components/Card.test.tsx
+++ /dev/null
@@ -1,60 +0,0 @@
-import { render, screen } from '@testing-library/react'
-
-import Card from 'components/Card'
-
-jest.mock('components/Text', () => {
- return {
- __esModule: true,
- default: (props: any) =>
- require('utils/testing').createMockComponent('mock-text-component', props),
- }
-})
-
-describe(' ', () => {
- const defaultProps = {
- children: <>>,
- }
-
- afterAll(() => {
- jest.unmock('components/Text')
- })
-
- it('should render', () => {
- const { container } = render( )
- expect(container).toBeInTheDocument()
- })
-
- it('should handle `className` prop correctly', () => {
- const testClass = 'test-class'
- const { container } = render( )
- expect(container.querySelector('section')).toHaveClass(testClass)
- })
-
- it('should handle `contentClassName` prop correctly', () => {
- const testClass = 'test-class'
- const { container } = render( )
-
- expect(container.querySelector('div')).toHaveClass(testClass)
- })
-
- it('should handle `title` prop as string correctly', () => {
- const testTitle = 'this-is-the-test-title'
- const { queryByText } = render( )
-
- expect(queryByText(testTitle)).toBeInTheDocument()
- })
-
- it('should handle `title` prop as element correctly', () => {
- const testTitle =
Test title
- const { queryByTestId } = render( )
-
- expect(queryByTestId('test-title')).toBeInTheDocument()
- expect(queryByTestId('mock-text-component')).not.toBeInTheDocument()
- })
-
- it('should handle `id` prop as element correctly', () => {
- const testId = 'test-id'
- const { container } = render( )
- expect(container.querySelector(`section#${testId}`)).toBeInTheDocument()
- })
-})
diff --git a/__tests__/components/CircularProgress.test.tsx b/__tests__/components/CircularProgress.test.tsx
deleted file mode 100644
index 98251b19..00000000
--- a/__tests__/components/CircularProgress.test.tsx
+++ /dev/null
@@ -1,34 +0,0 @@
-import { render } from '@testing-library/react'
-
-import { CircularProgress } from 'components/CircularProgress'
-import { LocalStorageKeys } from 'constants/localStorageKeys'
-
-describe(' ', () => {
- afterAll(() => {
- localStorage.removeItem(LocalStorageKeys.REDUCE_MOTION)
- })
-
- it('should render', () => {
- const { container } = render( )
-
- expect(container).toBeInTheDocument()
- })
-
- it('should render `...` when animations disabled', () => {
- localStorage.setItem(LocalStorageKeys.REDUCE_MOTION, 'true')
-
- const { getByText } = render( )
- const threeDots = getByText('...')
-
- expect(threeDots).toBeInTheDocument()
- })
-
- it('should render the component with animation classes when animations enabled', () => {
- localStorage.setItem(LocalStorageKeys.REDUCE_MOTION, 'false')
-
- const { container } = render( )
- const progressWithAnimations = container.querySelector('.animate-progress')
-
- expect(progressWithAnimations).toBeInTheDocument()
- })
-})
diff --git a/__tests__/components/Modals/Unlock/UnlockModal.test.tsx b/__tests__/components/Modals/Unlock/UnlockModal.test.tsx
deleted file mode 100644
index c19fbdf3..00000000
--- a/__tests__/components/Modals/Unlock/UnlockModal.test.tsx
+++ /dev/null
@@ -1,65 +0,0 @@
-import { render } from '@testing-library/react'
-
-import Modal from 'components/Modal'
-import UnlockModal from 'components/Modals/Unlock'
-import { BN_ONE, BN_ZERO } from 'constants/math'
-import { TESTNET_VAULTS_META_DATA } from 'constants/vaults'
-import useStore from 'store'
-import { BN } from 'utils/helpers'
-
-jest.mock('components/Modal')
-const mockedModal = jest.mocked(Modal).mockImplementation(() => Mock
)
-
-const mockedDepositedVault: DepositedVault = {
- ...TESTNET_VAULTS_META_DATA[0],
- status: 'active',
- apy: 1,
- apr: null,
- ltv: {
- max: 0.65,
- liq: 0.7,
- },
- amounts: {
- primary: BN_ONE,
- secondary: BN_ONE,
- locked: BN_ONE,
- unlocked: BN_ONE,
- unlocking: BN_ONE,
- },
- values: {
- primary: BN_ZERO,
- secondary: BN_ZERO,
- unlocked: BN_ZERO,
- unlocking: BN_ZERO,
- },
- cap: {
- denom: 'mock',
- max: BN(10),
- used: BN_ONE,
- },
-}
-
-describe(' ', () => {
- afterAll(() => {
- useStore.clearState()
- })
-
- it('should render', () => {
- const { container } = render( )
- expect(container).toBeInTheDocument()
- })
-
- describe('should set content correctly', () => {
- it('should have no content when no modal is present in store', () => {
- useStore.setState({ unlockModal: null })
- render( )
- expect(mockedModal).toHaveBeenCalledTimes(0)
- })
-
- it('should have content when modal is present in store', () => {
- useStore.setState({ unlockModal: { vault: mockedDepositedVault } })
- render( )
- expect(mockedModal).toHaveBeenCalledTimes(1)
- })
- })
-})
diff --git a/__tests__/components/PageMetadata.test.tsx b/__tests__/components/PageMetadata.test.tsx
deleted file mode 100644
index e46492e0..00000000
--- a/__tests__/components/PageMetadata.test.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import { render } from '@testing-library/react'
-import * as rrd from 'react-router-dom'
-
-import PageMetadata from 'components/PageMetadata'
-import PAGE_METADATA from 'constants/pageMetadata'
-
-jest.mock('react-router-dom')
-const mockedUseLocation = rrd.useLocation as jest.Mock
-
-describe(' ', () => {
- afterAll(() => {
- jest.clearAllMocks()
- })
-
- Object.keys(PAGE_METADATA).forEach((page) => {
- it(`should render correct ${page} metadata`, () => {
- const pageKey = page as keyof typeof PAGE_METADATA
- const pageMetadata = PAGE_METADATA[pageKey]
-
- mockedUseLocation.mockReturnValue({ pathname: pageKey })
-
- const { container } = render( )
- const titleElement = container.querySelector('title')
- const descriptionElement = container.querySelector('meta[name="description"]')
- const keywordsElement = container.querySelector('meta[name="keywords"]')
-
- expect(titleElement).toHaveTextContent(pageMetadata.title)
- expect(descriptionElement).toHaveAttribute('content', pageMetadata.description)
- expect(keywordsElement).toHaveAttribute('content', pageMetadata.keywords)
- })
- })
-})
diff --git a/__tests__/components/TokenInput.test.tsx b/__tests__/components/TokenInput.test.tsx
deleted file mode 100644
index 6c67010b..00000000
--- a/__tests__/components/TokenInput.test.tsx
+++ /dev/null
@@ -1,98 +0,0 @@
-import { fireEvent, render } from '@testing-library/react'
-import BigNumber from 'bignumber.js'
-
-import TokenInput from 'components/TokenInput'
-import { ASSETS } from 'constants/assets'
-
-jest.mock('components/DisplayCurrency', () => {
- return {
- __esModule: true,
- default: (props: any) =>
- require('utils/testing').createMockComponent('mock-display-currency-component', props),
- }
-})
-
-describe(' ', () => {
- const asset = ASSETS[0]
- const defaultProps = {
- amount: new BigNumber(1),
- asset,
- max: new BigNumber(100),
- onChangeAsset: jest.fn(),
- onChange: jest.fn(),
- }
-
- afterAll(() => {
- jest.unmock('components/DisplayCurrency')
- })
-
- it('should render', () => {
- const { container } = render( )
- expect(container).toBeInTheDocument()
- })
-
- it('should handle `className` prop correctly', () => {
- const testClass = 'test-class'
- const { getByTestId } = render(
- ,
- )
- expect(getByTestId('token-input-component')).toHaveClass(testClass)
- })
-
- it('should handle `disabled` prop correctly', () => {
- const { getByTestId } = render(
- ,
- )
- expect(getByTestId('token-input-component')).toHaveClass('pointer-events-none', 'opacity-50')
- })
-
- it('should handle `maxText` prop correctly', () => {
- const { getByTestId } = render(
- ,
- )
- expect(getByTestId('token-input-max-button')).toBeInTheDocument()
- })
-
- describe('should render the max button', () => {
- it('when `maxText` prop is defined', () => {
- const { getByTestId } = render(
- ,
- )
- expect(getByTestId('token-input-max-button')).toBeInTheDocument()
- })
- it('not when `maxText` prop is undefined', () => {
- const { queryByTestId } = render( )
- expect(queryByTestId('token-input-max-button')).not.toBeInTheDocument()
- })
- })
-
- describe('should render ', () => {
- it('when `hasSelect` prop is true and balances is defined', () => {
- const { getByTestId } = render(
- ,
- )
- expect(getByTestId('select-component')).toBeInTheDocument()
- })
- it('not when `hasSelect` prop is true and balances is not defined', () => {
- const { queryByTestId } = render(
- ,
- )
- expect(queryByTestId('select-component')).not.toBeInTheDocument()
- })
- it('not when `hasSelect` prop is false and balances is defined', () => {
- const { queryByTestId } = render(
- ,
- )
- expect(queryByTestId('select-component')).not.toBeInTheDocument()
- })
- })
-
- it('should call onMaxBtnClick when the user clicks on max button', () => {
- const { getByTestId } = render(
- ,
- )
- const maxBtn = getByTestId('token-input-max-button')
- fireEvent.click(maxBtn)
- expect(defaultProps.onChange).toBeCalledWith(defaultProps.max)
- })
-})
diff --git a/__tests__/components/Tooltip/Tooltip.test.tsx b/__tests__/components/Tooltip/Tooltip.test.tsx
deleted file mode 100644
index 9f2a3894..00000000
--- a/__tests__/components/Tooltip/Tooltip.test.tsx
+++ /dev/null
@@ -1,45 +0,0 @@
-import { render } from '@testing-library/react'
-
-import { Tooltip } from 'components/Tooltip'
-
-describe(' ', () => {
- const defaultProps = {
- content: <>>,
- }
-
- it('should render', () => {
- const { container } = render( )
- expect(container).toBeInTheDocument()
- })
-
- it('should handle `children` prop correctly', () => {
- const { getByTestId } = render(
-
- Test text
- ,
- )
- expect(getByTestId('test-child')).toBeInTheDocument()
- })
-
- it('should handle `className` prop correctly', () => {
- const testClass = 'test-class'
- const { container } = render( )
- expect(container.getElementsByClassName(testClass)).toHaveLength(1)
- })
-
- describe('should handle `underline` prop correctly', () => {
- it('should have border class when children are passed', () => {
- const { container } = render(
-
- <>>
- ,
- )
- expect(container.getElementsByClassName('border-b-1')).toHaveLength(1)
- })
-
- it('should not have border class when children are passed', () => {
- const { container } = render( )
- expect(container.getElementsByClassName('border-b-1')).toHaveLength(0)
- })
- })
-})
diff --git a/__tests__/components/Tooltip/TooltipContent.test.tsx b/__tests__/components/Tooltip/TooltipContent.test.tsx
deleted file mode 100644
index a7e114c1..00000000
--- a/__tests__/components/Tooltip/TooltipContent.test.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-import { render } from '@testing-library/react'
-
-import TooltipContent from 'components/Tooltip/TooltipContent'
-
-describe(' ', () => {
- const defaultProps = {
- content: <>>,
- }
-
- it('should render', () => {
- const { container } = render( )
- expect(container).toBeInTheDocument()
- })
-
- it('should handle `type` prop correctly', () => {
- const types = { info: 'bg-white/20', warning: 'bg-warning', error: 'bg-error' }
- Object.entries(types).forEach(([key, value]) => {
- const { container } = render( )
- expect(container.getElementsByClassName(value)).toHaveLength(1)
- })
- })
-
- describe('should handle `content` props correctly', () => {
- it('should render Text component when type is string', () => {
- const testText = 'testText'
- const { getByTestId } = render(
- ,
- )
- const textComponent = getByTestId('text-component')
- expect(textComponent).toHaveTextContent(testText)
- })
-
- it('should render content when type is ReactNode', () => {
- const testNode = Test node
- const { queryByTestId } = render(
- ,
- )
-
- expect(queryByTestId('text-component')).not.toBeInTheDocument()
- expect(queryByTestId('test-node')).toBeInTheDocument()
- })
- })
-})
diff --git a/jest.config.js b/jest.config.js
deleted file mode 100644
index 377aee24..00000000
--- a/jest.config.js
+++ /dev/null
@@ -1,60 +0,0 @@
-module.exports = {
- collectCoverage: true,
- coverageProvider: 'v8',
- collectCoverageFrom: [
- '**/*.{js,jsx,ts,tsx}',
- '!**/*.d.ts',
- '!**/node_modules/**',
- '!/out/**',
- '!/.next/**',
- '!/*.config.js',
- '!/coverage/**',
- '!/src/types/**',
- '!/src/utils/charting_library/**',
- '!/src/utils/datafeeds/**',
- '!/public/charting_library/**',
- '!/public/datafeeds/**',
- '!/src/utils/health_computer/**',
- ],
- moduleNameMapper: {
- // Handle CSS imports (with CSS modules)
- // https://jestjs.io/docs/webpack#mocking-css-modules
- '^.+\\.module\\.(css|sass|scss)$': 'identity-obj-proxy',
-
- // Handle CSS imports (without CSS modules)
- '^.+\\.(css|sass|scss)$': '/__mocks__/styleMock.js',
-
- // Handle image imports
- // https://jestjs.io/docs/webpack#handling-static-assets
- '^.+\\.(png|jpg|jpeg|gif|webp|avif|ico|bmp)$/i': `/__mocks__/fileMock.js`,
- '^.+\\.svg$': `/__mocks__/svgMock.js`,
-
- // Handle module aliases
- '^app/(.*)$': '/src/app/$1',
- '^api/(.*)$': '/src/api/$1',
- '^components/(.*)$': '/src/components/$1',
- '^constants/(.*)$': '/src/constants/$1',
- '^fonts/(.*)$': '/src/fonts/$1',
- '^hooks/(.*)$': '/src/hooks/$1',
- '^pages/(.*)$': '/src/pages/$1',
- '^store/(.*)$': '/src/store/$1',
- '^styles/(.*)$': '/src/styles/$1',
- '^types/(.*)$': '/src/types/$1',
- '^utils/(.*)$': '/src/utils/$1',
- '^store': '/src/store',
- },
- // Add more setup options before each test is run
- setupFilesAfterEnv: [
- '/jest.setup.js',
- '/__mocks__/store.js',
- '/__mocks__/helmet.js',
- ],
- testPathIgnorePatterns: ['/node_modules/', '/.next/'],
- testEnvironment: 'jsdom',
- transform: {
- // Use babel-jest to transpile tests with the next/babel preset
- // https://jestjs.io/docs/configuration#transform-objectstring-pathtotransformer--pathtotransformer-object
- '^.+\\.(js|jsx|ts|tsx)$': ['babel-jest', { presets: ['next/babel'] }],
- },
- transformIgnorePatterns: ['/node_modules/', '^.+\\.module\\.(css|sass|scss)$'],
-}
diff --git a/jest.setup.js b/jest.setup.js
deleted file mode 100644
index 264828a9..00000000
--- a/jest.setup.js
+++ /dev/null
@@ -1 +0,0 @@
-import '@testing-library/jest-dom/extend-expect'
diff --git a/package.json b/package.json
index a11c1059..ef1e29ba 100644
--- a/package.json
+++ b/package.json
@@ -1,14 +1,12 @@
{
"name": "mars-v2-frontend",
- "version": "2.1.2",
+ "version": "2.2.0",
"private": true,
"scripts": {
"build": "yarn validate-env && next build",
"dev": "next dev",
- "test": "jest",
- "test:cov": "jest --coverage",
"lint": "eslint ./src/ && yarn prettier-check",
- "format": "eslint ./src/ ./__tests__/ --fix && prettier --write ./src/ ./__tests__/",
+ "format": "eslint ./src/ --fix && prettier --write ./src/ ",
"prettier-check": "prettier --ignore-path .gitignore --check ./src/",
"start": "next start",
"validate-env": "node ./validate-env",
@@ -17,15 +15,15 @@
},
"lint-staged": {
"*.ts*": [
- "eslint ./src/ ./__tests__/ --fix",
- "prettier --write ./src/ ./__tests__/"
+ "eslint ./src/ --fix",
+ "prettier --write ./src/"
]
},
"dependencies": {
- "@cosmjs/cosmwasm-stargate": "^0.31.1",
+ "@cosmjs/cosmwasm-stargate": "^0.32.2",
"@delphi-labs/shuttle-react": "^3.10.0",
"@keplr-wallet/cosmos": "^0.12.42",
- "@sentry/nextjs": "^7.84.0",
+ "@sentry/nextjs": "^7.94.1",
"@splinetool/react-spline": "^2.2.6",
"@splinetool/runtime": "^0.9.521",
"@tailwindcss/container-queries": "^0.1.1",
@@ -45,40 +43,35 @@
"react-draggable": "^4.4.6",
"react-helmet-async": "^2.0.3",
"react-qr-code": "^2.0.12",
- "react-router-dom": "^6.17.0",
+ "react-router-dom": "^6.21.3",
"react-spring": "^9.7.3",
"react-toastify": "^9.1.3",
"react-use-clipboard": "^1.0.9",
"recharts": "^2.10.1",
- "sharp": "^0.33.0",
+ "sharp": "^0.33.2",
"swr": "^2.2.4",
"tailwind-scrollbar-hide": "^1.1.7",
- "zustand": "^4.4.6"
+ "zustand": "^4.4.7"
},
"devDependencies": {
"@svgr/webpack": "^8.1.0",
- "@testing-library/jest-dom": "^5.17.0",
- "@testing-library/react": "^14.0.0",
"@types/debounce-promise": "^3.1.9",
"@types/lodash.debounce": "^4.0.9",
"@types/lodash.throttle": "^4.1.8",
- "@types/node": "^20.8.6",
+ "@types/node": "^20.10.6",
"@types/react": "18.2.41",
"@types/react-dom": "18.2.15",
"@types/react-helmet": "^6.1.11",
"autoprefixer": "^10.4.16",
- "babel-jest": "^29.7.0",
"dotenv": "^16.3.1",
"dotenv-cli": "^7.3.0",
- "eslint": "^8.54.0",
+ "eslint": "^8.56.0",
"eslint-config-next": "^14.0.4",
"eslint-plugin-import": "^2.29.0",
"husky": "^8.0.3",
"identity-obj-proxy": "^3.0.0",
- "jest": "^29.7.0",
- "jest-environment-jsdom": "^29.7.0",
"lint-staged": "^15.2.0",
- "prettier": "^3.0.3",
+ "prettier": "^3.2.4",
"prettier-plugin-tailwindcss": "^0.5.6",
"shelljs": "^0.8.5",
"tailwindcss": "^3.3.3",
diff --git a/public/images/tokens/ntrn.svg b/public/images/tokens/ntrn.svg
new file mode 100644
index 00000000..4fc072f5
--- /dev/null
+++ b/public/images/tokens/ntrn.svg
@@ -0,0 +1,16 @@
+
+
+
+
+
diff --git a/public/images/wallets/vectis.png b/public/images/wallets/vectis.png
new file mode 100644
index 00000000..f2434fd9
Binary files /dev/null and b/public/images/wallets/vectis.png differ
diff --git a/public/images/wallets/xdefi.png b/public/images/wallets/xdefi.png
index 5342a2cc..df50e131 100644
Binary files a/public/images/wallets/xdefi.png and b/public/images/wallets/xdefi.png differ
diff --git a/public/tradingview.css b/public/tradingview.css
index fbbc05d9..c0031ccc 100644
--- a/public/tradingview.css
+++ b/public/tradingview.css
@@ -40,6 +40,16 @@
cursor: pointer;
}
+.layout__area--center {
+ background: var(--tv-background) !important;
+}
+
+.chart-widget.chart-widget--themed-dark.chart-widget__top--themed-dark.chart-widget__bottom--themed-dark
+ > table
+ canvas {
+ background: transparent !important;
+}
+
/* Floating menu */
.floating-toolbar-react-widgets__button:hover,
[class^='button-']:hover:before {
diff --git a/src/api/accounts/getAccount.ts b/src/api/accounts/getAccount.ts
index b73f7a89..b1bdb98f 100644
--- a/src/api/accounts/getAccount.ts
+++ b/src/api/accounts/getAccount.ts
@@ -3,21 +3,25 @@ import { getCreditManagerQueryClient } from 'api/cosmwasm-client'
import getDepositedVaults from 'api/vaults/getDepositedVaults'
import { BNCoin } from 'types/classes/BNCoin'
import { Positions } from 'types/generated/mars-credit-manager/MarsCreditManager.types'
+import { resolvePerpsPositions } from 'utils/resolvers'
-export default async function getAccount(accountId?: string): Promise {
+export default async function getAccount(
+ chainConfig: ChainConfig,
+ accountId?: string,
+): Promise {
if (!accountId) return new Promise((_, reject) => reject('No account ID found'))
- const creditManagerQueryClient = await getCreditManagerQueryClient()
+ const creditManagerQueryClient = await getCreditManagerQueryClient(chainConfig)
const accountPosition: Positions = await cacheFn(
() => creditManagerQueryClient.positions({ accountId: accountId }),
positionsCache,
- `account/${accountId}`,
+ `${chainConfig.id}/account/${accountId}`,
)
const accountKind = await creditManagerQueryClient.accountKind({ accountId: accountId })
- const depositedVaults = await getDepositedVaults(accountId, accountPosition)
+ const depositedVaults = await getDepositedVaults(accountId, chainConfig, accountPosition)
if (accountPosition) {
return {
@@ -26,6 +30,7 @@ export default async function getAccount(accountId?: string): Promise {
lends: accountPosition.lends.map((lend) => new BNCoin(lend)),
deposits: accountPosition.deposits.map((deposit) => new BNCoin(deposit)),
vaults: depositedVaults,
+ perps: resolvePerpsPositions(accountPosition.perps),
kind: accountKind,
}
}
diff --git a/src/api/cosmwasm-client.ts b/src/api/cosmwasm-client.ts
index a4fa92c6..bca16491 100644
--- a/src/api/cosmwasm-client.ts
+++ b/src/api/cosmwasm-client.ts
@@ -1,6 +1,5 @@
import { CosmWasmClient } from '@cosmjs/cosmwasm-stargate'
-import { ENV } from 'constants/env'
import { ICNSQueryClient } from 'types/classes/ICNSClient.client'
import { MarsAccountNftQueryClient } from 'types/generated/mars-account-nft/MarsAccountNft.client'
import { MarsCreditManagerQueryClient } from 'types/generated/mars-credit-manager/MarsCreditManager.client'
@@ -8,142 +7,187 @@ import { MarsIncentivesQueryClient } from 'types/generated/mars-incentives/MarsI
import { MarsMockVaultQueryClient } from 'types/generated/mars-mock-vault/MarsMockVault.client'
import { MarsOracleOsmosisQueryClient } from 'types/generated/mars-oracle-osmosis/MarsOracleOsmosis.client'
import { MarsParamsQueryClient } from 'types/generated/mars-params/MarsParams.client'
+import { MarsPerpsQueryClient } from 'types/generated/mars-perps/MarsPerps.client'
import { MarsRedBankQueryClient } from 'types/generated/mars-red-bank/MarsRedBank.client'
import { MarsSwapperOsmosisQueryClient } from 'types/generated/mars-swapper-osmosis/MarsSwapperOsmosis.client'
-let _cosmWasmClient: CosmWasmClient
-let _accountNftQueryClient: MarsAccountNftQueryClient
-let _creditManagerQueryClient: MarsCreditManagerQueryClient
-let _oracleQueryClient: MarsOracleOsmosisQueryClient
-let _redBankQueryClient: MarsRedBankQueryClient
-let _paramsQueryClient: MarsParamsQueryClient
-let _incentivesQueryClient: MarsIncentivesQueryClient
-let _swapperOsmosisClient: MarsSwapperOsmosisQueryClient
-let _ICNSQueryClient: ICNSQueryClient
+let _cosmWasmClient: Map = new Map()
+let _accountNftQueryClient: Map = new Map()
+let _creditManagerQueryClient: Map = new Map()
+let _oracleQueryClient: Map = new Map()
+let _redBankQueryClient: Map = new Map()
+let _paramsQueryClient: Map = new Map()
+let _incentivesQueryClient: Map = new Map()
+let _swapperOsmosisClient: Map = new Map()
+let _perpsClient: Map = new Map()
+let _ICNSQueryClient: Map = new Map()
-const getClient = async () => {
+const getClient = async (rpc: string) => {
try {
- if (!_cosmWasmClient) {
- _cosmWasmClient = await CosmWasmClient.connect(ENV.URL_RPC)
+ if (!_cosmWasmClient.get(rpc)) {
+ const client = await CosmWasmClient.connect(rpc)
+ _cosmWasmClient.set(rpc, client)
}
- return _cosmWasmClient
+ return _cosmWasmClient.get(rpc)!
} catch (error) {
throw error
}
}
-const getAccountNftQueryClient = async () => {
+const getAccountNftQueryClient = async (chainConfig: ChainConfig) => {
try {
- if (!_accountNftQueryClient) {
- const client = await getClient()
- _accountNftQueryClient = new MarsAccountNftQueryClient(client, ENV.ADDRESS_ACCOUNT_NFT)
+ const contract = chainConfig.contracts.accountNft
+ const rpc = chainConfig.endpoints.rpc
+ const key = rpc + contract
+
+ if (!_accountNftQueryClient.get(key)) {
+ const client = await getClient(rpc)
+ _accountNftQueryClient.set(key, new MarsAccountNftQueryClient(client, contract))
}
- return _accountNftQueryClient
+ return _accountNftQueryClient.get(key)!
} catch (error) {
throw error
}
}
-const getCreditManagerQueryClient = async () => {
+const getCreditManagerQueryClient = async (chainConfig: ChainConfig) => {
try {
- if (!_creditManagerQueryClient) {
- const client = await getClient()
- _creditManagerQueryClient = new MarsCreditManagerQueryClient(
- client,
- ENV.ADDRESS_CREDIT_MANAGER,
- )
+ const contract = chainConfig.contracts.creditManager
+ const rpc = chainConfig.endpoints.rpc
+ const key = rpc + contract
+
+ if (!_creditManagerQueryClient.get(key)) {
+ const client = await getClient(rpc)
+ _creditManagerQueryClient.set(key, new MarsCreditManagerQueryClient(client, contract))
}
- return _creditManagerQueryClient
+ return _creditManagerQueryClient.get(key)!
} catch (error) {
throw error
}
}
-const getParamsQueryClient = async () => {
+const getParamsQueryClient = async (chainConfig: ChainConfig) => {
try {
- if (!_paramsQueryClient) {
- const client = await getClient()
- _paramsQueryClient = new MarsParamsQueryClient(client, ENV.ADDRESS_PARAMS)
+ const contract = chainConfig.contracts.params
+ const rpc = chainConfig.endpoints.rpc
+ const key = rpc + contract
+
+ if (!_paramsQueryClient.get(key)) {
+ const client = await getClient(rpc)
+ _paramsQueryClient.set(key, new MarsParamsQueryClient(client, contract))
}
- return _paramsQueryClient
+ return _paramsQueryClient.get(key)!
} catch (error) {
throw error
}
}
-const getOracleQueryClient = async () => {
+const getOracleQueryClient = async (chainConfig: ChainConfig) => {
try {
- if (!_oracleQueryClient) {
- const client = await getClient()
- _oracleQueryClient = new MarsOracleOsmosisQueryClient(client, ENV.ADDRESS_ORACLE)
+ const contract = chainConfig.contracts.oracle
+ const rpc = chainConfig.endpoints.rpc
+ const key = rpc + contract
+
+ if (!_oracleQueryClient.get(key)) {
+ const client = await getClient(rpc)
+ _oracleQueryClient.set(key, new MarsOracleOsmosisQueryClient(client, contract))
}
- return _oracleQueryClient
+ return _oracleQueryClient.get(key)!
} catch (error) {
throw error
}
}
-const getRedBankQueryClient = async () => {
+const getRedBankQueryClient = async (chainConfig: ChainConfig) => {
try {
- if (!_redBankQueryClient) {
- const client = await getClient()
- _redBankQueryClient = new MarsRedBankQueryClient(client, ENV.ADDRESS_RED_BANK)
+ const contract = chainConfig.contracts.redBank
+ const rpc = chainConfig.endpoints.rpc
+ const key = rpc + contract
+
+ if (!_redBankQueryClient.get(key)) {
+ const client = await getClient(rpc)
+ _redBankQueryClient.set(key, new MarsRedBankQueryClient(client, contract))
}
- return _redBankQueryClient
+ return _redBankQueryClient.get(key)!
} catch (error) {
throw error
}
}
-const getVaultQueryClient = async (address: string) => {
+const getVaultQueryClient = async (chainConfig: ChainConfig, address: string) => {
try {
- const client = await getClient()
+ const client = await getClient(chainConfig.endpoints.rpc)
return new MarsMockVaultQueryClient(client, address)
} catch (error) {
throw error
}
}
-const getIncentivesQueryClient = async () => {
+const getIncentivesQueryClient = async (chainConfig: ChainConfig) => {
try {
- if (!_incentivesQueryClient) {
- const client = await getClient()
- _incentivesQueryClient = new MarsIncentivesQueryClient(client, ENV.ADDRESS_INCENTIVES)
+ const contract = chainConfig.contracts.incentives
+ const rpc = chainConfig.endpoints.rpc
+ const key = rpc + contract
+ if (!_incentivesQueryClient.get(key)) {
+ const client = await getClient(rpc)
+ _incentivesQueryClient.set(key, new MarsIncentivesQueryClient(client, contract))
}
- return _incentivesQueryClient
+ return _incentivesQueryClient.get(key)!
} catch (error) {
throw error
}
}
-const getSwapperQueryClient = async () => {
+const getSwapperQueryClient = async (chainConfig: ChainConfig) => {
try {
- if (!_swapperOsmosisClient) {
- const client = await getClient()
- _swapperOsmosisClient = new MarsSwapperOsmosisQueryClient(client, ENV.ADDRESS_SWAPPER)
+ const contract = chainConfig.contracts.swapper
+ const rpc = chainConfig.endpoints.rpc
+ const key = rpc + contract
+ if (!_swapperOsmosisClient.get(key)) {
+ const client = await getClient(rpc)
+ _swapperOsmosisClient.set(key, new MarsSwapperOsmosisQueryClient(client, contract))
}
- return _swapperOsmosisClient
+ return _swapperOsmosisClient.get(key)!
} catch (error) {
throw error
}
}
-const getICNSQueryClient = async () => {
+const getPerpsQueryClient = async (chainConfig: ChainConfig) => {
try {
- if (!_ICNSQueryClient) {
- const client = await getClient()
- _ICNSQueryClient = new ICNSQueryClient(client)
+ const contract = chainConfig.contracts.perps
+ const rpc = chainConfig.endpoints.rpc
+ const key = rpc + contract
+ if (!_perpsClient.get(key)) {
+ const client = await getClient(rpc)
+ _perpsClient.set(key, new MarsPerpsQueryClient(client, contract))
}
- return _ICNSQueryClient
+ return _perpsClient.get(key)!
+ } catch (error) {
+ throw error
+ }
+}
+
+const getICNSQueryClient = async (chainConfig: ChainConfig) => {
+ try {
+ const contract = chainConfig.contracts.params
+ const rpc = chainConfig.endpoints.rpc
+ const key = rpc + contract
+ if (!_ICNSQueryClient.get(key)) {
+ const client = await getClient(rpc)
+ _ICNSQueryClient.set(key, new ICNSQueryClient(client))
+ }
+
+ return _ICNSQueryClient.get(key)!
} catch (error) {
throw error
}
@@ -160,4 +204,5 @@ export {
getRedBankQueryClient,
getSwapperQueryClient,
getVaultQueryClient,
+ getPerpsQueryClient,
}
diff --git a/src/api/hls/getAprs.ts b/src/api/hls/getAprs.ts
index deaf4041..51c9086a 100644
--- a/src/api/hls/getAprs.ts
+++ b/src/api/hls/getAprs.ts
@@ -1,9 +1,8 @@
import { cacheFn, stakingAprCache } from 'api/cache'
-import { ENV } from 'constants/env'
-export default async function getStakingAprs() {
+export default async function getStakingAprs(url: string) {
try {
- return cacheFn(() => fetchAprs(), stakingAprCache, `stakingAprs`)
+ return cacheFn(() => fetchAprs(url), stakingAprCache, `stakingAprs`)
} catch (error) {
throw error
}
@@ -13,9 +12,7 @@ interface StakingAprResponse {
stats: StakingApr[]
}
-async function fetchAprs(): Promise {
- const url = ENV.STRIDE_APRS
-
+async function fetchAprs(url: string): Promise {
const response = await fetch(url)
const body = (await response.json()) as StakingAprResponse
return body.stats
diff --git a/src/api/hls/getHLSStakingAccounts.ts b/src/api/hls/getHLSStakingAccounts.ts
index 3b5ab3eb..8431253c 100644
--- a/src/api/hls/getHLSStakingAccounts.ts
+++ b/src/api/hls/getHLSStakingAccounts.ts
@@ -4,24 +4,29 @@ import getAccounts from 'api/wallets/getAccounts'
import { calculateAccountLeverage, getAccountPositionValues, isAccountEmpty } from 'utils/accounts'
export default async function getHLSStakingAccounts(
+ chainConfig: ChainConfig,
address?: string,
): Promise {
- const accounts = await getAccounts('high_levered_strategy', address)
+ const accounts = await getAccounts('high_levered_strategy', chainConfig, address)
const activeAccounts = accounts.filter((account) => !isAccountEmpty(account))
- const hlsStrategies = await getHLSStakingAssets()
- const prices = await getPrices()
+ const hlsStrategies = await getHLSStakingAssets(chainConfig)
+ const prices = await getPrices(chainConfig)
const hlsAccountsWithStrategy: HLSAccountWithStrategy[] = []
activeAccounts.forEach((account) => {
if (account.deposits.length === 0) return
const strategy = hlsStrategies.find(
- (strategy) => strategy.denoms.deposit === account.deposits.at(0).denom,
+ (strategy) => strategy.denoms.deposit === account.deposits[0].denom,
)
if (!strategy) return
- const [deposits, lends, debts, vaults] = getAccountPositionValues(account, prices)
+ const [deposits, lends, debts, vaults] = getAccountPositionValues(
+ account,
+ prices,
+ chainConfig.assets,
+ )
hlsAccountsWithStrategy.push({
...account,
@@ -31,7 +36,7 @@ export default async function getHLSStakingAccounts(
debt: debts,
total: deposits,
},
- leverage: calculateAccountLeverage(account, prices).toNumber(),
+ leverage: calculateAccountLeverage(account, prices, chainConfig.assets).toNumber(),
})
})
diff --git a/src/api/hls/getHLSStakingAssets.ts b/src/api/hls/getHLSStakingAssets.ts
index 58a05526..0ef28f69 100644
--- a/src/api/hls/getHLSStakingAssets.ts
+++ b/src/api/hls/getHLSStakingAssets.ts
@@ -1,28 +1,29 @@
import { getParamsQueryClient } from 'api/cosmwasm-client'
import getStakingAprs from 'api/hls/getAprs'
import getAssetParams from 'api/params/getAssetParams'
-import { getAssetByDenom, getStakingAssets } from 'utils/assets'
+import { byDenom } from 'utils/array'
import { BN } from 'utils/helpers'
import { resolveHLSStrategies } from 'utils/resolvers'
-export default async function getHLSStakingAssets() {
- const stakingAssetDenoms = getStakingAssets().map((asset) => asset.denom)
- const assetParams = await getAssetParams()
+export default async function getHLSStakingAssets(chainConfig: ChainConfig) {
+ const stakingAssetDenoms = chainConfig.assets
+ .filter((asset) => asset.isStaking)
+ .map((asset) => asset.denom)
+ const assetParams = await getAssetParams(chainConfig)
const HLSAssets = assetParams
.filter((asset) => stakingAssetDenoms.includes(asset.denom))
.filter((asset) => asset.credit_manager.hls)
const strategies = resolveHLSStrategies('coin', HLSAssets)
-
- const client = await getParamsQueryClient()
+ const client = await getParamsQueryClient(chainConfig)
const depositCaps$ = strategies.map((strategy) =>
client.totalDeposit({ denom: strategy.denoms.deposit }),
)
- const aprs = await getStakingAprs()
+ const aprs = await getStakingAprs(chainConfig.endpoints.aprs.stride)
return Promise.all(depositCaps$).then((depositCaps) => {
return depositCaps.map((depositCap, index) => {
- const borrowSymbol = getAssetByDenom(strategies[index].denoms.borrow)?.symbol
+ const borrowSymbol = chainConfig.assets.find(byDenom(strategies[index].denoms.borrow))?.symbol
return {
...strategies[index],
depositCap: {
diff --git a/src/api/hls/getHLSVaults.ts b/src/api/hls/getHLSVaults.ts
index 2b09a9b3..6761af77 100644
--- a/src/api/hls/getHLSVaults.ts
+++ b/src/api/hls/getHLSVaults.ts
@@ -4,10 +4,10 @@ import { getVaultConfigs } from 'api/vaults/getVaultConfigs'
import { BN } from 'utils/helpers'
import { resolveHLSStrategies } from 'utils/resolvers'
-export default async function getHLSVaults() {
- const assetParams = await getAssetParams()
- const client = await getCreditManagerQueryClient()
- const vaultConfigs = await getVaultConfigs()
+export default async function getHLSVaults(chainConfig: ChainConfig) {
+ const assetParams = await getAssetParams(chainConfig)
+ const client = await getCreditManagerQueryClient(chainConfig)
+ const vaultConfigs = await getVaultConfigs(chainConfig)
const HLSAssets = assetParams.filter((asset) => asset.credit_manager.hls)
const strategies = resolveHLSStrategies('vault', HLSAssets)
diff --git a/src/api/incentives/calculateAssetIncentivesApy.ts b/src/api/incentives/calculateAssetIncentivesApy.ts
index d2c75c7c..243a952b 100644
--- a/src/api/incentives/calculateAssetIncentivesApy.ts
+++ b/src/api/incentives/calculateAssetIncentivesApy.ts
@@ -2,28 +2,28 @@ import getTotalActiveEmissionValue from 'api/incentives/getTotalActiveEmissionVa
import getMarket from 'api/markets/getMarket'
import getUnderlyingLiquidityAmount from 'api/markets/getMarketUnderlyingLiquidityAmount'
import getPrice from 'api/prices/getPrice'
-import { ASSETS } from 'constants/assets'
import { byDenom } from 'utils/array'
import { SECONDS_IN_A_YEAR } from 'utils/constants'
import { BN } from 'utils/helpers'
export default async function calculateAssetIncentivesApy(
+ chainConfig: ChainConfig,
denom: string,
): Promise {
try {
const [totalActiveEmissionValue, market] = await Promise.all([
- getTotalActiveEmissionValue(denom),
- getMarket(denom),
+ getTotalActiveEmissionValue(chainConfig, denom),
+ getMarket(chainConfig, denom),
])
if (!totalActiveEmissionValue) return null
const [marketLiquidityAmount, assetPrice] = await Promise.all([
- getUnderlyingLiquidityAmount(market),
- getPrice(denom),
+ getUnderlyingLiquidityAmount(chainConfig, market),
+ getPrice(chainConfig, denom),
])
- const assetDecimals = (ASSETS.find(byDenom(denom)) as Asset).decimals
+ const assetDecimals = (chainConfig.assets.find(byDenom(denom)) as Asset).decimals
const marketLiquidityValue = BN(marketLiquidityAmount)
.shiftedBy(-assetDecimals)
diff --git a/src/api/incentives/getTotalActiveEmissionValue.ts b/src/api/incentives/getTotalActiveEmissionValue.ts
index 082686ea..f71132a2 100644
--- a/src/api/incentives/getTotalActiveEmissionValue.ts
+++ b/src/api/incentives/getTotalActiveEmissionValue.ts
@@ -1,16 +1,16 @@
import { cacheFn, emissionsCache } from 'api/cache'
import { getIncentivesQueryClient } from 'api/cosmwasm-client'
import getPrice from 'api/prices/getPrice'
-import { ASSETS } from 'constants/assets'
import { BN_ZERO } from 'constants/math'
import { byDenom } from 'utils/array'
import { BN } from 'utils/helpers'
export default async function getTotalActiveEmissionValue(
+ chainConfig: ChainConfig,
denom: string,
): Promise {
try {
- const client = await getIncentivesQueryClient()
+ const client = await getIncentivesQueryClient(chainConfig)
const activeEmissions = await cacheFn(
() =>
client.activeEmissions({
@@ -26,12 +26,12 @@ export default async function getTotalActiveEmissionValue(
}
const prices = await Promise.all(
- activeEmissions.map((activeEmission) => getPrice(activeEmission.denom)),
+ activeEmissions.map((activeEmission) => getPrice(chainConfig, activeEmission.denom)),
)
return activeEmissions.reduce((accumulation, current, index) => {
const price = prices[index]
- const decimals = ASSETS.find(byDenom(current.denom))?.decimals as number
+ const decimals = chainConfig.assets.find(byDenom(current.denom))?.decimals as number
const emissionValue = BN(current.emission_rate).shiftedBy(-decimals).multipliedBy(price)
return accumulation.plus(emissionValue)
diff --git a/src/api/incentives/getUnclaimedRewards.ts b/src/api/incentives/getUnclaimedRewards.ts
index 46df88d4..66304905 100644
--- a/src/api/incentives/getUnclaimedRewards.ts
+++ b/src/api/incentives/getUnclaimedRewards.ts
@@ -1,17 +1,19 @@
import { cacheFn, unclaimedRewardsCache } from 'api/cache'
import { getIncentivesQueryClient } from 'api/cosmwasm-client'
-import { ENV } from 'constants/env'
import { BNCoin } from 'types/classes/BNCoin'
import iterateContractQuery from 'utils/iterateContractQuery'
-export default async function getUnclaimedRewards(accountId: string): Promise {
+export default async function getUnclaimedRewards(
+ chainConfig: ChainConfig,
+ accountId: string,
+): Promise {
try {
- const client = await getIncentivesQueryClient()
+ const client = await getIncentivesQueryClient(chainConfig)
const unclaimedRewards = await cacheFn(
() =>
iterateContractQuery(() =>
client.userUnclaimedRewards({
- user: ENV.ADDRESS_CREDIT_MANAGER,
+ user: chainConfig.contracts.creditManager,
accountId,
}),
),
diff --git a/src/api/markets/getMarket.ts b/src/api/markets/getMarket.ts
index add9d976..078bf5fc 100644
--- a/src/api/markets/getMarket.ts
+++ b/src/api/markets/getMarket.ts
@@ -2,14 +2,14 @@ import { cacheFn, marketCache } from 'api/cache'
import { getParamsQueryClient, getRedBankQueryClient } from 'api/cosmwasm-client'
import { resolveMarketResponse } from 'utils/resolvers'
-export default async function getMarket(denom: string): Promise {
- return cacheFn(() => fetchMarket(denom), marketCache, denom, 60)
+export default async function getMarket(chainConfig: ChainConfig, denom: string): Promise {
+ return cacheFn(() => fetchMarket(chainConfig, denom), marketCache, denom, 60)
}
-async function fetchMarket(denom: string) {
+async function fetchMarket(chainConfig: ChainConfig, denom: string) {
try {
- const redBankClient = await getRedBankQueryClient()
- const paramsClient = await getParamsQueryClient()
+ const redBankClient = await getRedBankQueryClient(chainConfig)
+ const paramsClient = await getParamsQueryClient(chainConfig)
const [market, assetParams, assetCap] = await Promise.all([
redBankClient.market({ denom }),
diff --git a/src/api/markets/getMarketBorrowings.ts b/src/api/markets/getMarketBorrowings.ts
index 65cbdf1b..1b0c65b8 100644
--- a/src/api/markets/getMarketBorrowings.ts
+++ b/src/api/markets/getMarketBorrowings.ts
@@ -1,19 +1,21 @@
import getMarketLiquidities from 'api/markets/getMarketLiquidities'
import getMarkets from 'api/markets/getMarkets'
import getPrices from 'api/prices/getPrices'
-import { getEnabledMarketAssets } from 'utils/assets'
import { BN } from 'utils/helpers'
-export default async function getMarketBorrowings(): Promise {
- const liquidities = await getMarketLiquidities()
- const enabledAssets = getEnabledMarketAssets()
- const borrowEnabledMarkets = (await getMarkets()).filter((market: Market) => market.borrowEnabled)
- const prices = await getPrices()
+export default async function getMarketBorrowings(
+ chainConfig: ChainConfig,
+): Promise {
+ const liquidities = await getMarketLiquidities(chainConfig)
+ const borrowEnabledMarkets = (await getMarkets(chainConfig)).filter(
+ (market: Market) => market.borrowEnabled,
+ )
+ const prices = await getPrices(chainConfig)
const borrow: BorrowAsset[] = borrowEnabledMarkets.map((market) => {
const price = prices.find((coin) => coin.denom === market.denom)?.amount ?? '1'
const amount = liquidities.find((coin) => coin.denom === market.denom)?.amount ?? '0'
- const asset = enabledAssets.find((asset) => asset.denom === market.denom)!
+ const asset = chainConfig.assets.find((asset) => asset.denom === market.denom)!
return {
...asset,
diff --git a/src/api/markets/getMarketDebts.ts b/src/api/markets/getMarketDebts.ts
index fc3dddf2..ab3e3c0f 100644
--- a/src/api/markets/getMarketDebts.ts
+++ b/src/api/markets/getMarketDebts.ts
@@ -3,10 +3,10 @@ import { getRedBankQueryClient } from 'api/cosmwasm-client'
import getMarkets from 'api/markets/getMarkets'
import { BNCoin } from 'types/classes/BNCoin'
-export default async function getMarketDebts(): Promise {
+export default async function getMarketDebts(chainConfig: ChainConfig): Promise {
try {
- const markets: Market[] = await getMarkets()
- const redBankQueryClient = await getRedBankQueryClient()
+ const markets: Market[] = await getMarkets(chainConfig)
+ const redBankQueryClient = await getRedBankQueryClient(chainConfig)
const debtQueries = markets.map((asset) =>
cacheFn(
diff --git a/src/api/markets/getMarketDeposits.ts b/src/api/markets/getMarketDeposits.ts
index 57e46f58..824c824e 100644
--- a/src/api/markets/getMarketDeposits.ts
+++ b/src/api/markets/getMarketDeposits.ts
@@ -2,10 +2,12 @@ import getMarkets from 'api/markets/getMarkets'
import getUnderlyingLiquidityAmount from 'api/markets/getMarketUnderlyingLiquidityAmount'
import { BNCoin } from 'types/classes/BNCoin'
-export default async function getMarketDeposits(): Promise {
+export default async function getMarketDeposits(chainConfig: ChainConfig): Promise {
try {
- const markets: Market[] = await getMarkets()
- const depositQueries = markets.map(getUnderlyingLiquidityAmount)
+ const markets: Market[] = await getMarkets(chainConfig)
+ const depositQueries = markets.map((market) =>
+ getUnderlyingLiquidityAmount(chainConfig, market),
+ )
const depositsResults = await Promise.all(depositQueries)
return depositsResults.map(
diff --git a/src/api/markets/getMarketLiquidities.ts b/src/api/markets/getMarketLiquidities.ts
index 51a9be61..0c8cb3e0 100644
--- a/src/api/markets/getMarketLiquidities.ts
+++ b/src/api/markets/getMarketLiquidities.ts
@@ -1,11 +1,10 @@
-import { BN } from 'utils/helpers'
-import getMarketDeposits from 'api/markets/getMarketDeposits'
import getMarketDebts from 'api/markets/getMarketDebts'
+import getMarketDeposits from 'api/markets/getMarketDeposits'
import { BNCoin } from 'types/classes/BNCoin'
-export default async function getMarketLiquidities(): Promise {
- const deposits = await getMarketDeposits()
- const debts = await getMarketDebts()
+export default async function getMarketLiquidities(chainConfig: ChainConfig): Promise {
+ const deposits = await getMarketDeposits(chainConfig)
+ const debts = await getMarketDebts(chainConfig)
const liquidity: BNCoin[] = deposits.map((deposit) => {
const debt = debts.find((debt) => debt.denom === deposit.denom)
diff --git a/src/api/markets/getMarketUnderlyingLiquidityAmount.ts b/src/api/markets/getMarketUnderlyingLiquidityAmount.ts
index 44c5aa6e..e2fe4de0 100644
--- a/src/api/markets/getMarketUnderlyingLiquidityAmount.ts
+++ b/src/api/markets/getMarketUnderlyingLiquidityAmount.ts
@@ -1,18 +1,21 @@
import { cacheFn, underlyingLiquidityAmountCache } from 'api/cache'
import { getRedBankQueryClient } from 'api/cosmwasm-client'
-export default async function getUnderlyingLiquidityAmount(market: Market): Promise {
+export default async function getUnderlyingLiquidityAmount(
+ chainConfig: ChainConfig,
+ market: Market,
+): Promise {
return cacheFn(
- () => fetchUnderlyingLiquidityAmount(market),
+ () => fetchUnderlyingLiquidityAmount(chainConfig, market),
underlyingLiquidityAmountCache,
`underlyingLiquidity/${market.denom}/amount/${market.collateralTotalScaled}`,
60,
)
}
-async function fetchUnderlyingLiquidityAmount(market: Market) {
+async function fetchUnderlyingLiquidityAmount(chainConfig: ChainConfig, market: Market) {
try {
- const client = await getRedBankQueryClient()
+ const client = await getRedBankQueryClient(chainConfig)
return await client.underlyingLiquidityAmount({
denom: market.denom,
amountScaled: market.collateralTotalScaled,
diff --git a/src/api/markets/getMarkets.ts b/src/api/markets/getMarkets.ts
index e4babe8c..cbcc4370 100644
--- a/src/api/markets/getMarkets.ts
+++ b/src/api/markets/getMarkets.ts
@@ -6,36 +6,46 @@ import {
} from 'types/generated/mars-params/MarsParams.types'
import { Market as RedBankMarket } from 'types/generated/mars-red-bank/MarsRedBank.types'
import { byDenom } from 'utils/array'
-import { getEnabledMarketAssets } from 'utils/assets'
import iterateContractQuery from 'utils/iterateContractQuery'
import { resolveMarketResponse } from 'utils/resolvers'
-export default async function getMarkets(): Promise {
+export default async function getMarkets(chainConfig: ChainConfig): Promise {
try {
- const redBankClient = await getRedBankQueryClient()
- const paramsClient = await getParamsQueryClient()
+ const redBankClient = await getRedBankQueryClient(chainConfig)
+ const paramsClient = await getParamsQueryClient(chainConfig)
- const enabledAssets = getEnabledMarketAssets()
- const capQueries = enabledAssets.map((asset) =>
+ const marketAssets = chainConfig.assets.filter((asset) => asset.isMarket)
+
+ const capQueries = marketAssets
+ .filter((asset) => asset.isMarket)
+ .map((asset) =>
+ cacheFn(
+ () => paramsClient.totalDeposit({ denom: asset.denom }),
+ totalDepositCache,
+ `chains/${chainConfig.id}/enabledMarkets/${asset.denom}`,
+ 60,
+ ),
+ )
+
+ const caps = await Promise.all(capQueries)
+
+ const [markets, assetParams, assetCaps] = await Promise.all([
cacheFn(
- () => paramsClient.totalDeposit({ denom: asset.denom }),
- totalDepositCache,
- `enabledMarkets/${asset.denom}`,
+ () => iterateContractQuery(redBankClient.markets),
+ marketsCache,
+ `chains/${chainConfig.id}/markets`,
60,
),
- )
- const [markets, assetParams, assetCaps] = await Promise.all([
- cacheFn(() => iterateContractQuery(redBankClient.markets), marketsCache, 'markets', 60),
cacheFn(
async () => await iterateContractQuery(paramsClient.allAssetParams),
allParamsCache,
- 'params',
+ `chains/${chainConfig.id}/params`,
60,
),
Promise.all(capQueries),
])
- return enabledAssets.map((asset) =>
+ return marketAssets.map((asset) =>
resolveMarketResponse(
markets.find(byDenom(asset.denom)) as RedBankMarket,
assetParams.find(byDenom(asset.denom)) as AssetParams,
@@ -43,6 +53,7 @@ export default async function getMarkets(): Promise {
),
)
} catch (ex) {
+ console.log(ex)
throw ex
}
}
diff --git a/src/api/params/getAssetParams.ts b/src/api/params/getAssetParams.ts
index d42ceee2..34e96071 100644
--- a/src/api/params/getAssetParams.ts
+++ b/src/api/params/getAssetParams.ts
@@ -3,15 +3,17 @@ import { getParamsQueryClient } from 'api/cosmwasm-client'
import { AssetParamsBaseForAddr } from 'types/generated/mars-params/MarsParams.types'
import iterateContractQuery from 'utils/iterateContractQuery'
-export default async function getAssetParams(): Promise {
+export default async function getAssetParams(
+ chainConfig: ChainConfig,
+): Promise {
try {
return await cacheFn(
async () => {
- const paramsQueryClient = await getParamsQueryClient()
+ const paramsQueryClient = await getParamsQueryClient(chainConfig)
return iterateContractQuery(paramsQueryClient.allAssetParams)
},
assetParamsCache,
- 'assetParams',
+ `${chainConfig.id}/assetParams`,
600,
)
} catch (ex) {
diff --git a/src/api/perps/getOpeningFee.ts b/src/api/perps/getOpeningFee.ts
new file mode 100644
index 00000000..f89d41c6
--- /dev/null
+++ b/src/api/perps/getOpeningFee.ts
@@ -0,0 +1,14 @@
+import { getPerpsQueryClient } from 'api/cosmwasm-client'
+import { BNCoin } from 'types/classes/BNCoin'
+
+export default async function getOpeningFee(
+ chainConfig: ChainConfig,
+ denom: string,
+ amount: string,
+) {
+ const perpsClient = await getPerpsQueryClient(chainConfig)
+
+ return perpsClient
+ .openingFee({ denom, size: amount as any })
+ .then((resp) => BNCoin.fromCoin(resp.fee))
+}
diff --git a/src/api/prices/getMarsPrice.ts b/src/api/prices/getMarsPrice.ts
index 906ad8df..b0cf2275 100644
--- a/src/api/prices/getMarsPrice.ts
+++ b/src/api/prices/getMarsPrice.ts
@@ -1,11 +1,10 @@
import getPoolPrice from 'api/prices/getPoolPrice'
-import { ASSETS } from 'constants/assets'
import { bySymbol } from 'utils/array'
-async function getMarsPrice() {
- const marsAsset = ASSETS.find(bySymbol('MARS'))
+async function getMarsPrice(chainConfig: ChainConfig) {
+ const marsAsset = chainConfig.assets.find(bySymbol('MARS'))
if (!marsAsset) return 0
- return await getPoolPrice(marsAsset)
+ return await getPoolPrice(chainConfig, marsAsset)
}
export default getMarsPrice
diff --git a/src/api/prices/getOraclePrices.ts b/src/api/prices/getOraclePrices.ts
index 008b461c..335ffb00 100644
--- a/src/api/prices/getOraclePrices.ts
+++ b/src/api/prices/getOraclePrices.ts
@@ -1,5 +1,6 @@
import { cacheFn, oraclePriceCache } from 'api/cache'
import { getOracleQueryClient } from 'api/cosmwasm-client'
+import { BN_ZERO } from 'constants/math'
import { PRICE_ORACLE_DECIMALS } from 'constants/query'
import { BNCoin } from 'types/classes/BNCoin'
import { PriceResponse } from 'types/generated/mars-oracle-osmosis/MarsOracleOsmosis.types'
@@ -7,15 +8,18 @@ import { byDenom } from 'utils/array'
import { BN } from 'utils/helpers'
import iterateContractQuery from 'utils/iterateContractQuery'
-export default async function getOraclePrices(...assets: Asset[]): Promise {
+export default async function getOraclePrices(
+ chainConfig: ChainConfig,
+ assets: Asset[],
+): Promise {
try {
if (!assets.length) return []
- const oracleQueryClient = await getOracleQueryClient()
+ const oracleQueryClient = await getOracleQueryClient(chainConfig)
const priceResults = await cacheFn(
() => iterateContractQuery(oracleQueryClient.prices),
oraclePriceCache,
- 'oraclePrices',
+ `${chainConfig.id}/oraclePrices`,
60,
)
@@ -24,7 +28,7 @@ export default async function getOraclePrices(...assets: Asset[]): Promise {
if (!asset.poolId) throw 'given asset should have a poolId to fetch the price'
- const [assetRate, baseAsset] = await getAssetRate(asset)
+ const [assetRate, baseAsset] = await getAssetRate(chainConfig, asset)
const baseAssetPrice =
(lookupPricesForBaseAsset &&
lookupPricesForBaseAsset.find(byDenom(baseAsset.token.denom))?.amount) ||
- (await getPrice(baseAsset.token.denom))
+ (await getPrice(chainConfig, baseAsset.token.denom))
if (!baseAssetPrice) throw 'base asset price must be available on Pyth or in Oracle contract'
return assetRate.multipliedBy(baseAssetPrice)
}
-const getAssetRate = async (asset: Asset) => {
- const url = `${ENV.URL_REST}osmosis/gamm/v1beta1/pools/${asset.poolId}`
+const getAssetRate = async (chainConfig: ChainConfig, asset: Asset) => {
+ const url = chainConfig.endpoints.pools.replace('POOL_ID', asset.poolId!.toString())
const response = await cacheFn(
() => fetch(url).then((res) => res.json()),
poolPriceCache,
- `poolPrices/${(asset.poolId || 0).toString()}`,
+ `${chainConfig.id}/poolPrices/${(asset.poolId || 0).toString()}`,
60,
)
const pool = response.pool
diff --git a/src/api/prices/getPrice.ts b/src/api/prices/getPrice.ts
index 009cb5f4..519e32ed 100644
--- a/src/api/prices/getPrice.ts
+++ b/src/api/prices/getPrice.ts
@@ -1,37 +1,20 @@
import { cacheFn, priceCache } from 'api/cache'
-import { getOracleQueryClient } from 'api/cosmwasm-client'
-import getPoolPrice from 'api/prices/getPoolPrice'
-import getPythPrice from 'api/prices/getPythPrices'
-import { ASSETS } from 'constants/assets'
-import { PRICE_ORACLE_DECIMALS } from 'constants/query'
+import getPrices from 'api/prices/getPrices'
+import { BN_ZERO } from 'constants/math'
import { byDenom } from 'utils/array'
-import { BN } from 'utils/helpers'
-export default async function getPrice(denom: string): Promise {
- return cacheFn(() => fetchPrice(denom), priceCache, `price/${denom}`, 60)
+export default async function getPrice(
+ chainConfig: ChainConfig,
+ denom: string,
+): Promise {
+ return cacheFn(() => fetchPrice(chainConfig, denom), priceCache, `price/${denom}`, 60)
}
-async function fetchPrice(denom: string) {
+async function fetchPrice(chainConfig: ChainConfig, denom: string) {
try {
- const asset = ASSETS.find(byDenom(denom)) as Asset
+ const prices = await getPrices(chainConfig)
- if (asset.pythPriceFeedId) {
- return (await getPythPrice(asset.pythPriceFeedId))[0]
- }
-
- if (asset.hasOraclePrice) {
- const oracleQueryClient = await getOracleQueryClient()
- const priceResponse = await oracleQueryClient.price({ denom: asset.denom })
- const decimalDiff = asset.decimals - PRICE_ORACLE_DECIMALS
-
- return BN(priceResponse.price).shiftedBy(decimalDiff)
- }
-
- if (asset.poolId) {
- return await getPoolPrice(asset)
- }
-
- throw `could not fetch the price info for the given denom: ${denom}`
+ return prices.find(byDenom(denom))?.amount ?? BN_ZERO
} catch (ex) {
throw ex
}
diff --git a/src/api/prices/getPriceData.ts b/src/api/prices/getPriceData.ts
deleted file mode 100644
index 71650bf2..00000000
--- a/src/api/prices/getPriceData.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import fetchPythPriceData from 'api/prices/getPythPriceData'
-import { getPythAssets } from 'utils/assets'
-
-export default async function getPricesData(): Promise {
- try {
- const assetsWithPythPriceFeedId = getPythAssets()
- const pythAndOraclePriceData = await requestPythPriceData(assetsWithPythPriceFeedId)
- return pythAndOraclePriceData
- } catch (ex) {
- console.error(ex)
- throw ex
- }
-}
-
-async function requestPythPriceData(assets: Asset[]): Promise {
- if (!assets.length) return []
-
- const priceFeedIds = assets.map((a) => a.pythPriceFeedId) as string[]
- return await fetchPythPriceData(...priceFeedIds)
-}
diff --git a/src/api/prices/getPrices.ts b/src/api/prices/getPrices.ts
index 8b4f077c..6dc5a1fd 100644
--- a/src/api/prices/getPrices.ts
+++ b/src/api/prices/getPrices.ts
@@ -1,29 +1,35 @@
import getOraclePrices from 'api/prices/getOraclePrices'
import getPoolPrice from 'api/prices/getPoolPrice'
import fetchPythPrices from 'api/prices/getPythPrices'
+import chains from 'configs/chains'
import useStore from 'store'
import { BNCoin } from 'types/classes/BNCoin'
import { partition } from 'utils/array'
-import { getAssetsMustHavePriceInfo } from 'utils/assets'
+import { getAllAssetsWithPythId } from 'utils/assets'
-export default async function getPrices(): Promise {
+export default async function getPrices(chainConfig: ChainConfig): Promise {
const usdPrice = new BNCoin({ denom: 'usd', amount: '1' })
+
+ const pythAndOraclePrices = []
+ const assetsToFetchPrices = useStore
+ .getState()
+ .chainConfig.assets.filter(
+ (asset) => (asset.isEnabled && asset.isMarket) || asset.forceFetchPrice,
+ )
+
+ const assetsWithPythPriceFeedId = getAllAssetsWithPythId(chains)
+ const pythPrices = await requestPythPrices(assetsWithPythPriceFeedId)
+ pythAndOraclePrices.push(...pythPrices)
+
try {
- const assetsToFetchPrices = getAssetsMustHavePriceInfo()
- const [assetsWithPythPriceFeedId, assetsWithOraclePrices, assetsWithPoolIds] =
+ const [assetsWithOraclePrices, assetsWithPoolIds] =
separateAssetsByPriceSources(assetsToFetchPrices)
+ const oraclePrices = await getOraclePrices(chainConfig, assetsWithOraclePrices)
+ const poolPrices = await requestPoolPrices(chainConfig, assetsWithPoolIds, pythAndOraclePrices)
- const pythAndOraclePrices = (
- await Promise.all([
- requestPythPrices(assetsWithPythPriceFeedId),
- getOraclePrices(...assetsWithOraclePrices),
- ])
- ).flat()
- const poolPrices = await requestPoolPrices(assetsWithPoolIds, pythAndOraclePrices)
+ if (oraclePrices) useStore.setState({ isOracleStale: false })
- useStore.setState({ isOracleStale: false })
-
- return [...pythAndOraclePrices, ...poolPrices, usdPrice]
+ return [...pythAndOraclePrices, ...oraclePrices, ...poolPrices, usdPrice]
} catch (ex) {
console.error(ex)
let message = 'Unknown Error'
@@ -31,41 +37,43 @@ export default async function getPrices(): Promise {
if (message.includes('price publish time is too old'))
useStore.setState({ isOracleStale: true })
- throw ex
+ return [...pythAndOraclePrices, usdPrice]
}
}
async function requestPythPrices(assets: Asset[]): Promise {
if (!assets.length) return []
- const priceFeedIds = assets.map((a) => a.pythPriceFeedId) as string[]
- return await fetchPythPrices(...priceFeedIds).then(mapResponseToBnCoin(assets))
+ const priceFeedIds = assets
+ .map((a) => a.pythPriceFeedId)
+ .filter((priceFeedId, index, array) => array.indexOf(priceFeedId) === index) as string[]
+ return await fetchPythPrices(priceFeedIds, assets)
}
-async function requestPoolPrices(assets: Asset[], lookupPrices: BNCoin[]): Promise {
- const requests = assets.map((asset) => getPoolPrice(asset, lookupPrices))
+async function requestPoolPrices(
+ chainConfig: ChainConfig,
+ assets: Asset[],
+ lookupPrices: BNCoin[],
+): Promise {
+ const requests = assets.map((asset) => getPoolPrice(chainConfig, asset, lookupPrices))
return await Promise.all(requests).then(mapResponseToBnCoin(assets))
}
-const mapResponseToBnCoin = (assets: Asset[]) => (prices: BigNumber[]) =>
- prices.map((price: BigNumber, index: number) =>
+const mapResponseToBnCoin = (assets: Asset[]) => (prices: BigNumber[]) => {
+ return prices.map((price: BigNumber, index: number) =>
BNCoin.fromDenomAndBigNumber(assets[index].denom, price),
)
+}
function separateAssetsByPriceSources(assets: Asset[]) {
- // Only fetch Pyth prices for mainnet
- const [assetsWithPythPriceFeedId, assetsWithoutPythPriceFeedId] = partition(
- assets,
- (asset) => !!asset.pythPriceFeedId,
- )
+ const assetsWithoutPythPriceFeedId = assets.filter((asset) => !asset.pythPriceFeedId)
- // Don't get oracle price if it's not mainnet and there is a poolId
const [assetsWithOraclePrice, assetsWithoutOraclePrice] = partition(
assetsWithoutPythPriceFeedId,
(asset) => asset.hasOraclePrice || !asset.poolId,
)
const assetsWithPoolId = assetsWithoutOraclePrice.filter((asset) => !!asset.poolId)
- return [assetsWithPythPriceFeedId, assetsWithOraclePrice, assetsWithPoolId]
+ return [assetsWithOraclePrice, assetsWithPoolId]
}
diff --git a/src/api/prices/getPythPriceData.ts b/src/api/prices/getPythPriceData.ts
index bb6b8d50..17339687 100644
--- a/src/api/prices/getPythPriceData.ts
+++ b/src/api/prices/getPythPriceData.ts
@@ -1,9 +1,9 @@
import { cacheFn, pythPriceCache } from 'api/cache'
-import { ENV } from 'constants/env'
+import { pythEndpoints } from 'constants/pyth'
-export default async function fetchPythPriceData(...priceFeedIds: string[]) {
+export default async function getPythPriceData(priceFeedIds: string[]) {
try {
- const pricesUrl = new URL(`${ENV.PYTH_ENDPOINT}/latest_vaas`)
+ const pricesUrl = new URL(`${pythEndpoints.api}/latest_vaas`)
priceFeedIds.forEach((id) => pricesUrl.searchParams.append('ids[]', id))
const pythDataResponse: string[] = await cacheFn(
@@ -14,6 +14,7 @@ export default async function fetchPythPriceData(...priceFeedIds: string[]) {
)
return pythDataResponse
} catch (ex) {
- throw ex
+ console.log(ex)
+ return []
}
}
diff --git a/src/api/prices/getPythPrices.ts b/src/api/prices/getPythPrices.ts
index 5add3652..8aa74d56 100644
--- a/src/api/prices/getPythPrices.ts
+++ b/src/api/prices/getPythPrices.ts
@@ -1,10 +1,11 @@
import { cacheFn, pythPriceCache } from 'api/cache'
-import { ENV } from 'constants/env'
+import { pythEndpoints } from 'constants/pyth'
+import { BNCoin } from 'types/classes/BNCoin'
import { BN } from 'utils/helpers'
-export default async function fetchPythPrices(...priceFeedIds: string[]) {
+export default async function fetchPythPrices(priceFeedIds: string[], assets: Asset[]) {
try {
- const pricesUrl = new URL(`${ENV.PYTH_ENDPOINT}/latest_price_feeds`)
+ const pricesUrl = new URL(`${pythEndpoints.api}/latest_price_feeds`)
priceFeedIds.forEach((id) => pricesUrl.searchParams.append('ids[]', id))
const pythResponse: PythPriceData[] = await cacheFn(
@@ -14,7 +15,18 @@ export default async function fetchPythPrices(...priceFeedIds: string[]) {
30,
)
- return pythResponse.map(({ price }) => BN(price.price).shiftedBy(price.expo))
+ const mappedPriceData = [] as BNCoin[]
+
+ assets.forEach((asset) => {
+ const price = pythResponse.find((pythPrice) => asset.pythPriceFeedId === pythPrice.id)?.price
+ if (price)
+ mappedPriceData.push(
+ BNCoin.fromDenomAndBigNumber(asset.denom, BN(price.price).shiftedBy(price.expo)),
+ )
+ return
+ })
+
+ return mappedPriceData
} catch (ex) {
throw ex
}
diff --git a/src/api/swap/estimateExactIn.ts b/src/api/swap/estimateExactIn.ts
index 6e7606c7..14e98a23 100644
--- a/src/api/swap/estimateExactIn.ts
+++ b/src/api/swap/estimateExactIn.ts
@@ -2,9 +2,13 @@ import { getSwapperQueryClient } from 'api/cosmwasm-client'
import { BN_ZERO } from 'constants/math'
import { BN } from 'utils/helpers'
-export default async function estimateExactIn(coinIn: Coin, denomOut: string) {
+export default async function estimateExactIn(
+ chainConfig: ChainConfig,
+ coinIn: Coin,
+ denomOut: string,
+) {
try {
- const swapperClient = await getSwapperQueryClient()
+ const swapperClient = await getSwapperQueryClient(chainConfig)
const estimatedAmount = (await swapperClient.estimateExactInSwap({ coinIn, denomOut })).amount
return BN(estimatedAmount)
diff --git a/src/api/swap/getOsmosisSwapFee.ts b/src/api/swap/getOsmosisSwapFee.ts
new file mode 100644
index 00000000..4577e687
--- /dev/null
+++ b/src/api/swap/getOsmosisSwapFee.ts
@@ -0,0 +1,53 @@
+import { BN_ZERO } from 'constants/math'
+import { STANDARD_SWAP_FEE } from 'utils/constants'
+
+export default async function getOsmosisSwapFee(
+ chainConfig: ChainConfig,
+ poolIds: string[],
+): Promise {
+ const promises = poolIds.map((poolId) =>
+ fetch(chainConfig.endpoints.pools.replace('POOL_ID', poolId)),
+ )
+
+ const responses = await Promise.all(promises)
+
+ const pools = await Promise.all(responses.map(async (pool) => (await pool.json()).pool as Pool))
+
+ if (!pools?.length) return STANDARD_SWAP_FEE
+
+ return pools
+ .reduce((acc, pool) => acc.plus(pool?.pool_params?.swap_fee || STANDARD_SWAP_FEE), BN_ZERO)
+ .toNumber()
+}
+
+interface Pool {
+ '@type': string
+ address: string
+ future_pool_governor: string
+ id: string
+ pool_assets?: PoolAsset[]
+ pool_liquidity?: PoolLiquidity[]
+ pool_params: PoolParams
+ total_shares: TotalShares
+ total_weight: string
+}
+
+interface PoolAsset {
+ token: TotalShares
+ weight: string
+}
+
+interface PoolLiquidity {
+ amount: string
+ denom: string
+}
+interface TotalShares {
+ amount: string
+ denom: string
+}
+
+interface PoolParams {
+ exit_fee: string
+ smooth_weight_change_params: null
+ swap_fee: string
+}
diff --git a/src/api/swap/getPools.ts b/src/api/swap/getPools.ts
deleted file mode 100644
index 27d49d4c..00000000
--- a/src/api/swap/getPools.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import { ENV } from 'constants/env'
-
-const url = `${ENV.URL_REST}osmosis/gamm/v1beta1/pools/`
-export default async function getPools(poolIds: string[]): Promise {
- const promises = poolIds.map((poolId) => fetch(url + poolId))
-
- const responses = await Promise.all(promises)
-
- return await Promise.all(responses.map(async (pool) => (await pool.json()).pool as Pool))
-}
-
-interface Pool {
- '@type': string
- address: string
- future_pool_governor: string
- id: string
- pool_assets?: PoolAsset[]
- pool_liquidity?: PoolLiquidity[]
- pool_params: PoolParams
- total_shares: TotalShares
- total_weight: string
-}
-
-interface PoolAsset {
- token: TotalShares
- weight: string
-}
-
-interface PoolLiquidity {
- amount: string
- denom: string
-}
-interface TotalShares {
- amount: string
- denom: string
-}
-
-interface PoolParams {
- exit_fee: string
- smooth_weight_change_params: null
- swap_fee: string
-}
diff --git a/src/api/swap/getSwapRoute.ts b/src/api/swap/getSwapRoute.ts
index c5501c49..1547fa3e 100644
--- a/src/api/swap/getSwapRoute.ts
+++ b/src/api/swap/getSwapRoute.ts
@@ -1,8 +1,12 @@
import { getSwapperQueryClient } from 'api/cosmwasm-client'
-export default async function getSwapRoute(denomIn: string, denomOut: string): Promise {
+export default async function getSwapRoute(
+ chainConfig: ChainConfig,
+ denomIn: string,
+ denomOut: string,
+): Promise {
try {
- const swapperClient = await getSwapperQueryClient()
+ const swapperClient = await getSwapperQueryClient(chainConfig)
const routes = await swapperClient.route({
denomIn,
denomOut,
diff --git a/src/api/vaults/getDepositedVaults.ts b/src/api/vaults/getDepositedVaults.ts
index 189d4734..14ccb939 100644
--- a/src/api/vaults/getDepositedVaults.ts
+++ b/src/api/vaults/getDepositedVaults.ts
@@ -21,9 +21,13 @@ import {
import { getCoinValue } from 'utils/formatters'
import { BN } from 'utils/helpers'
-async function getUnlocksAtTimestamp(unlockingId: number, vaultAddress: string) {
+async function getUnlocksAtTimestamp(
+ chainConfig: ChainConfig,
+ unlockingId: number,
+ vaultAddress: string,
+) {
try {
- const client = await getClient()
+ const client = await getClient(chainConfig.endpoints.rpc)
const vaultExtension = (await cacheFn(
() =>
@@ -42,6 +46,7 @@ async function getUnlocksAtTimestamp(unlockingId: number, vaultAddress: string)
}
async function getVaultPositionStatusAndUnlockIdAndUnlockTime(
+ chainConfig: ChainConfig,
vaultPosition: VaultPosition,
): Promise<[VaultStatus, number | undefined, number | undefined]> {
const amount = vaultPosition.amount
@@ -50,7 +55,11 @@ async function getVaultPositionStatusAndUnlockIdAndUnlockTime(
if (amount.locking.unlocking.length) {
const unlockId = amount.locking.unlocking[0].id
- const unlocksAtTimestamp = await getUnlocksAtTimestamp(unlockId, vaultPosition.vault.address)
+ const unlocksAtTimestamp = await getUnlocksAtTimestamp(
+ chainConfig,
+ unlockId,
+ vaultPosition.vault.address,
+ )
if (moment(unlocksAtTimestamp).isBefore(new Date())) {
return [VaultStatus.UNLOCKED, unlockId, unlocksAtTimestamp]
@@ -83,12 +92,13 @@ export function flatVaultPositionAmount(
}
export async function getLpTokensForVaultPosition(
+ chainConfig: ChainConfig,
vault: Vault,
vaultPosition: VaultPosition,
): Promise {
try {
- const vaultQueryClient = await getVaultQueryClient(vault.address)
- const creditManagerQueryClient = await getCreditManagerQueryClient()
+ const vaultQueryClient = await getVaultQueryClient(chainConfig, vault.address)
+ const creditManagerQueryClient = await getCreditManagerQueryClient(chainConfig)
const amounts = flatVaultPositionAmount(vaultPosition.amount)
const totalAmount = amounts.locked.plus(amounts.unlocked).plus(amounts.unlocking).toString()
@@ -133,15 +143,16 @@ export async function getLpTokensForVaultPosition(
async function getVaultValuesAndAmounts(
vault: Vault,
vaultPosition: VaultPosition,
+ chainConfig: ChainConfig,
): Promise {
try {
const pricesQueries = Promise.all([
- getPrice(vault.denoms.primary),
- getPrice(vault.denoms.secondary),
- getPrice(vault.denoms.lp),
+ getPrice(chainConfig, vault.denoms.primary),
+ getPrice(chainConfig, vault.denoms.secondary),
+ getPrice(chainConfig, vault.denoms.lp),
])
- const lpTokensQuery = getLpTokensForVaultPosition(vault, vaultPosition)
+ const lpTokensQuery = getLpTokensForVaultPosition(chainConfig, vault, vaultPosition)
const amounts = flatVaultPositionAmount(vaultPosition.amount)
const [[primaryLpToken, secondaryLpToken], [primaryPrice, secondaryPrice, lpPrice]] =
@@ -154,18 +165,26 @@ async function getVaultValuesAndAmounts(
secondary: BN(secondaryLpToken.amount),
},
values: {
- primary: getCoinValue(new BNCoin(primaryLpToken), [
- BNCoin.fromDenomAndBigNumber(primaryLpToken.denom, primaryPrice),
- ]),
- secondary: getCoinValue(new BNCoin(secondaryLpToken), [
- BNCoin.fromDenomAndBigNumber(secondaryLpToken.denom, secondaryPrice),
- ]),
- unlocking: getCoinValue(BNCoin.fromDenomAndBigNumber(vault.denoms.lp, amounts.unlocking), [
- BNCoin.fromDenomAndBigNumber(vault.denoms.lp, lpPrice),
- ]),
- unlocked: getCoinValue(BNCoin.fromDenomAndBigNumber(vault.denoms.lp, amounts.unlocked), [
- BNCoin.fromDenomAndBigNumber(vault.denoms.lp, lpPrice),
- ]),
+ primary: getCoinValue(
+ new BNCoin(primaryLpToken),
+ [BNCoin.fromDenomAndBigNumber(primaryLpToken.denom, primaryPrice)],
+ chainConfig.assets,
+ ),
+ secondary: getCoinValue(
+ new BNCoin(secondaryLpToken),
+ [BNCoin.fromDenomAndBigNumber(secondaryLpToken.denom, secondaryPrice)],
+ chainConfig.assets,
+ ),
+ unlocking: getCoinValue(
+ BNCoin.fromDenomAndBigNumber(vault.denoms.lp, amounts.unlocking),
+ [BNCoin.fromDenomAndBigNumber(vault.denoms.lp, lpPrice)],
+ chainConfig.assets,
+ ),
+ unlocked: getCoinValue(
+ BNCoin.fromDenomAndBigNumber(vault.denoms.lp, amounts.unlocked),
+ [BNCoin.fromDenomAndBigNumber(vault.denoms.lp, lpPrice)],
+ chainConfig.assets,
+ ),
},
}
} catch (ex) {
@@ -175,10 +194,11 @@ async function getVaultValuesAndAmounts(
async function getDepositedVaults(
accountId: string,
+ chainConfig: ChainConfig,
positions?: Positions,
): Promise {
try {
- const creditManagerQueryClient = await getCreditManagerQueryClient()
+ const creditManagerQueryClient = await getCreditManagerQueryClient(chainConfig)
if (!positions)
positions = await cacheFn(
@@ -189,7 +209,7 @@ async function getDepositedVaults(
if (!positions.vaults.length) return []
- const [allVaults] = await Promise.all([getVaults()])
+ const [allVaults] = await Promise.all([getVaults(chainConfig)])
const depositedVaults = positions.vaults.map(async (vaultPosition) => {
const vault = allVaults.find((v) => v.address === vaultPosition.vault.address)
@@ -199,8 +219,8 @@ async function getDepositedVaults(
}
const [[status, unlockId, unlocksAt], valuesAndAmounts] = await Promise.all([
- getVaultPositionStatusAndUnlockIdAndUnlockTime(vaultPosition),
- getVaultValuesAndAmounts(vault, vaultPosition),
+ getVaultPositionStatusAndUnlockIdAndUnlockTime(chainConfig, vaultPosition),
+ getVaultValuesAndAmounts(vault, vaultPosition, chainConfig),
])
return {
diff --git a/src/api/vaults/getVaultAprs.ts b/src/api/vaults/getVaultAprs.ts
index 36e643ab..633ca510 100644
--- a/src/api/vaults/getVaultAprs.ts
+++ b/src/api/vaults/getVaultAprs.ts
@@ -1,17 +1,22 @@
import { aprsCache, aprsCacheResponse, cacheFn } from 'api/cache'
-import { ENV } from 'constants/env'
-export default async function getAprs() {
+export default async function getAprs(chainConfig: ChainConfig) {
+ if (!chainConfig.farm) return []
try {
const response = await cacheFn(
- () => fetch(ENV.URL_VAULT_APR),
+ () => fetch(chainConfig.endpoints.aprs.vaults),
aprsCacheResponse,
- 'aprsResponse',
+ `${chainConfig.id}/aprsResponse`,
60,
)
if (response.ok) {
- const data: AprResponse = await cacheFn(() => response.json(), aprsCache, 'aprs', 60)
+ const data: AprResponse = await cacheFn(
+ () => response.json(),
+ aprsCache,
+ `${chainConfig.id}/aprs`,
+ 60,
+ )
return data.vaults.map((aprData) => {
const finalApr = aprData.apr.projected_apr * 100
diff --git a/src/api/vaults/getVaultConfigs.ts b/src/api/vaults/getVaultConfigs.ts
index af4aab4d..f8cb618c 100644
--- a/src/api/vaults/getVaultConfigs.ts
+++ b/src/api/vaults/getVaultConfigs.ts
@@ -3,13 +3,15 @@ import { getParamsQueryClient } from 'api/cosmwasm-client'
import { VaultConfigBaseForAddr } from 'types/generated/mars-params/MarsParams.types'
import iterateContractQuery from 'utils/iterateContractQuery'
-export const getVaultConfigs = async (): Promise => {
+export const getVaultConfigs = async (
+ chainConfig: ChainConfig,
+): Promise => {
try {
- const paramsQueryClient = await getParamsQueryClient()
+ const paramsQueryClient = await getParamsQueryClient(chainConfig)
return await cacheFn(
() => iterateContractQuery(paramsQueryClient.allVaultConfigs, 'addr'),
vaultConfigsCache,
- 'vaultConfigs',
+ `${chainConfig.id}/vaultConfigs`,
600,
)
} catch (ex) {
diff --git a/src/api/vaults/getVaultTokenFromLp.ts b/src/api/vaults/getVaultTokenFromLp.ts
deleted file mode 100644
index 1f4cde4d..00000000
--- a/src/api/vaults/getVaultTokenFromLp.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { cacheFn, previewDepositCache } from 'api/cache'
-import { getVaultQueryClient } from 'api/cosmwasm-client'
-
-export async function getVaultTokenFromLp(
- vaultAddress: string,
- lpAmount: string,
-): Promise<{ vaultAddress: string; amount: string }> {
- try {
- const client = await getVaultQueryClient(vaultAddress)
-
- return cacheFn(
- () =>
- client.previewDeposit({ amount: lpAmount }).then((amount) => ({ vaultAddress, amount })),
- previewDepositCache,
- `vaults/${vaultAddress}/amounts/${lpAmount}`,
- 30,
- )
- } catch (ex) {
- throw ex
- }
-}
diff --git a/src/api/vaults/getVaultUtilizations.ts b/src/api/vaults/getVaultUtilizations.ts
index 9177b86f..acbb1de6 100644
--- a/src/api/vaults/getVaultUtilizations.ts
+++ b/src/api/vaults/getVaultUtilizations.ts
@@ -1,14 +1,13 @@
import { cacheFn, vaultUtilizationCache } from 'api/cache'
import { getCreditManagerQueryClient } from 'api/cosmwasm-client'
-import { ENV } from 'constants/env'
import { VaultUtilizationResponse } from 'types/generated/mars-credit-manager/MarsCreditManager.types'
import { VaultConfigBaseForString } from 'types/generated/mars-params/MarsParams.types'
export const getVaultUtilizations = async (
+ chainConfig: ChainConfig,
vaultConfigs: VaultConfigBaseForString[],
): Promise => {
- if (!ENV.ADDRESS_PARAMS) return []
- const creditManagerQueryClient = await getCreditManagerQueryClient()
+ const creditManagerQueryClient = await getCreditManagerQueryClient(chainConfig)
try {
const vaultUtilizations$ = vaultConfigs.map((vaultConfig) => {
return cacheFn(
diff --git a/src/api/vaults/getVaults.ts b/src/api/vaults/getVaults.ts
index b0af108f..476f284b 100644
--- a/src/api/vaults/getVaults.ts
+++ b/src/api/vaults/getVaults.ts
@@ -2,20 +2,16 @@ import getAssetParams from 'api/params/getAssetParams'
import getAprs from 'api/vaults/getVaultAprs'
import { getVaultConfigs } from 'api/vaults/getVaultConfigs'
import { getVaultUtilizations } from 'api/vaults/getVaultUtilizations'
-import { ENV } from 'constants/env'
-import { TESTNET_VAULTS_META_DATA, VAULTS_META_DATA } from 'constants/vaults'
-import { NETWORK } from 'types/enums/network'
import { BN } from 'utils/helpers'
import { convertAprToApy } from 'utils/parsers'
import { resolveHLSStrategies } from 'utils/resolvers'
-export default async function getVaults(): Promise {
- const assetParams = await getAssetParams()
- const vaultConfigs = await getVaultConfigs()
- const $vaultUtilizations = getVaultUtilizations(vaultConfigs)
- const $aprs = getAprs()
- const vaultMetaDatas =
- ENV.NETWORK === NETWORK.TESTNET ? TESTNET_VAULTS_META_DATA : VAULTS_META_DATA
+export default async function getVaults(chainConfig: ChainConfig): Promise {
+ const assetParams = await getAssetParams(chainConfig)
+ const vaultConfigs = await getVaultConfigs(chainConfig)
+ const $vaultUtilizations = getVaultUtilizations(chainConfig, vaultConfigs)
+ const $aprs = getAprs(chainConfig)
+ const vaultMetaDatas = chainConfig.vaults
const HLSAssets = assetParams.filter((asset) => asset.credit_manager.hls)
const hlsStrategies = resolveHLSStrategies('vault', HLSAssets)
diff --git a/src/api/wallets/getAccountIds.ts b/src/api/wallets/getAccountIds.ts
index 485908ac..1e4a30b3 100644
--- a/src/api/wallets/getAccountIds.ts
+++ b/src/api/wallets/getAccountIds.ts
@@ -2,12 +2,13 @@ import { getCreditManagerQueryClient } from 'api/cosmwasm-client'
import { ITEM_LIMIT_PER_QUERY } from 'constants/query'
export default async function getAccountIds(
+ chainConfig: ChainConfig,
address?: string,
previousResults?: AccountIdAndKind[],
): Promise {
if (!address) return []
try {
- const client = await getCreditManagerQueryClient()
+ const client = await getCreditManagerQueryClient(chainConfig)
const lastItem = previousResults && previousResults.at(-1)
const accounts = (
@@ -24,7 +25,7 @@ export default async function getAccountIds(
return accumulated.sort((a, b) => parseInt(a.id) - parseInt(b.id))
}
- return await getAccountIds(address, accumulated)
+ return await getAccountIds(chainConfig, address, accumulated)
} catch {
return new Promise((_, reject) => reject('No data'))
}
diff --git a/src/api/wallets/getAccounts.ts b/src/api/wallets/getAccounts.ts
index cbb58e61..7b13ed02 100644
--- a/src/api/wallets/getAccounts.ts
+++ b/src/api/wallets/getAccounts.ts
@@ -2,16 +2,19 @@ import getAccount from 'api/accounts/getAccount'
import getWalletAccountIds from 'api/wallets/getAccountIds'
import { AccountKind } from 'types/generated/mars-rover-health-computer/MarsRoverHealthComputer.types'
-export default async function getAccounts(kind: AccountKind, address?: string): Promise {
+export default async function getAccounts(
+ kind: AccountKind,
+ chainConfig: ChainConfig,
+ address?: string,
+): Promise {
if (!address) return new Promise((_, reject) => reject('No address'))
- const accountIdsAndKinds = await getWalletAccountIds(address)
+ const accountIdsAndKinds = await getWalletAccountIds(chainConfig, address)
const $accounts = accountIdsAndKinds
.filter((a) => a.kind === kind)
- .map((account) => getAccount(account.id))
+ .map((account) => getAccount(chainConfig, account.id))
const accounts = await Promise.all($accounts).then((accounts) => accounts)
-
if (accounts) {
return accounts.sort((a, b) => Number(a.id) - Number(b.id))
}
diff --git a/src/api/wallets/getICNS.ts b/src/api/wallets/getICNS.ts
index 10870497..3e951714 100644
--- a/src/api/wallets/getICNS.ts
+++ b/src/api/wallets/getICNS.ts
@@ -1,11 +1,13 @@
import { getICNSQueryClient } from 'api/cosmwasm-client'
-import { ENV } from 'constants/env'
import { ChainInfoID } from 'types/enums/wallet'
-export default async function getICNS(address?: string): Promise {
- if (!address || ENV.CHAIN_ID !== ChainInfoID.Osmosis1) return
+export default async function getICNS(
+ chainConfig: ChainConfig,
+ address?: string,
+): Promise {
+ if (!address || chainConfig.id !== ChainInfoID.Osmosis1) return
try {
- const icnsQueryClient = await getICNSQueryClient()
+ const icnsQueryClient = await getICNSQueryClient(chainConfig)
return icnsQueryClient.primaryName({ address })
} catch (ex) {
throw ex
diff --git a/src/api/wallets/getWalletBalances.ts b/src/api/wallets/getWalletBalances.ts
index 798409a9..c6ea4d3f 100644
--- a/src/api/wallets/getWalletBalances.ts
+++ b/src/api/wallets/getWalletBalances.ts
@@ -1,9 +1,10 @@
-import { ENV } from 'constants/env'
-
-export default async function getWalletBalances(address: string): Promise {
+export default async function getWalletBalances(
+ chainConfig: ChainConfig,
+ address: string,
+): Promise {
const uri = '/cosmos/bank/v1beta1/balances/'
- const response = await fetch(`${ENV.URL_REST}${uri}${address}`)
+ const response = await fetch(`${chainConfig.endpoints.rest}${uri}${address}`)
if (response.ok) {
const data = await response.json()
diff --git a/src/components/Account/AccountBalancesTable/Columns/Asset.tsx b/src/components/Account/AccountBalancesTable/Columns/Asset.tsx
deleted file mode 100644
index fc26c5a5..00000000
--- a/src/components/Account/AccountBalancesTable/Columns/Asset.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import Text from 'components/Text'
-export const ASSET_META = { accessorKey: 'symbol', header: 'Asset', id: 'symbol' }
-
-interface Props {
- symbol: string
- type: 'deposits' | 'borrowing' | 'lending' | 'vault'
-}
-
-export const borderColor = (type: Props['type']): string =>
- type === 'borrowing' ? 'border-loss' : 'border-profit'
-
-export default function Asset(props: Props) {
- const { symbol, type } = props
- return (
-
- {symbol}
- {type === 'borrowing' && (debt) }
- {type === 'lending' && (lent) }
- {type === 'vault' && (farm) }
-
- )
-}
diff --git a/src/components/DepositCapMessage.tsx b/src/components/DepositCapMessage.tsx
deleted file mode 100644
index 6aaee248..00000000
--- a/src/components/DepositCapMessage.tsx
+++ /dev/null
@@ -1,50 +0,0 @@
-import classNames from 'classnames'
-import { HTMLAttributes } from 'react'
-
-import { FormattedNumber } from 'components/FormattedNumber'
-import { InfoCircle } from 'components/Icons'
-import Text from 'components/Text'
-import { BNCoin } from 'types/classes/BNCoin'
-import { getAssetByDenom } from 'utils/assets'
-
-interface Props extends HTMLAttributes {
- action: 'buy' | 'deposit' | 'fund'
- coins: BNCoin[]
- showIcon?: boolean
-}
-
-export default function DepositCapMessage(props: Props) {
- if (!props.coins.length) return null
-
- return (
-
- {props.showIcon &&
}
-
-
Deposit Cap Reached!
-
{`Unfortunately you're not able to ${
- props.action
- } more than the following amount${props.coins.length > 1 ? 's' : ''}:`}
- {props.coins.map((coin) => {
- const asset = getAssetByDenom(coin.denom)
-
- if (!asset) return null
-
- return (
-
- Cap Left:
-
-
- )
- })}
-
-
- )
-}
diff --git a/src/components/DirectionSelect.tsx b/src/components/DirectionSelect.tsx
deleted file mode 100644
index e94da6ed..00000000
--- a/src/components/DirectionSelect.tsx
+++ /dev/null
@@ -1,59 +0,0 @@
-import classNames from 'classnames'
-
-import Text from 'components/Text'
-
-interface Props {
- direction: OrderDirection
- onChangeDirection: (direction: OrderDirection) => void
- asset?: Asset
-}
-
-export function DirectionSelect(props: Props) {
- const hasAsset = props.asset
- const directions: OrderDirection[] = hasAsset ? ['buy', 'sell'] : ['long', 'short']
- return (
-
- props.onChangeDirection(directions[0])}
- direction={directions[0]}
- isActive={props.direction === directions[0]}
- asset={props.asset}
- />
- props.onChangeDirection(directions[1])}
- direction={directions[1]}
- isActive={props.direction === directions[1]}
- asset={props.asset}
- />
-
- )
-}
-
-interface DirectionProps {
- direction: 'long' | 'short' | 'buy' | 'sell'
- isActive: boolean
- onClick: () => void
- asset?: Asset
-}
-function Direction(props: DirectionProps) {
- const classString = props.direction === 'long' || props.direction === 'buy' ? 'success' : 'error'
- return (
-
-
- {props.asset ? `${props.direction} ${props.asset.symbol}` : props.direction}
-
-
- )
-}
diff --git a/src/components/DisplayCurrency.tsx b/src/components/DisplayCurrency.tsx
deleted file mode 100644
index d1ce5031..00000000
--- a/src/components/DisplayCurrency.tsx
+++ /dev/null
@@ -1,82 +0,0 @@
-import classNames from 'classnames'
-import { useMemo } from 'react'
-
-import { FormattedNumber } from 'components/FormattedNumber'
-import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
-import { LocalStorageKeys } from 'constants/localStorageKeys'
-import { ORACLE_DENOM } from 'constants/oracle'
-import useLocalStorage from 'hooks/useLocalStorage'
-import usePrices from 'hooks/usePrices'
-import { BNCoin } from 'types/classes/BNCoin'
-import { getDisplayCurrencies } from 'utils/assets'
-import { getCoinValue } from 'utils/formatters'
-import { BN } from 'utils/helpers'
-
-interface Props {
- coin: BNCoin
- className?: string
- isApproximation?: boolean
- parentheses?: boolean
- showZero?: boolean
- options?: FormatOptions
-}
-
-export default function DisplayCurrency(props: Props) {
- const displayCurrencies = getDisplayCurrencies()
- const [displayCurrency] = useLocalStorage(
- LocalStorageKeys.DISPLAY_CURRENCY,
- DEFAULT_SETTINGS.displayCurrency,
- )
- const { data: prices } = usePrices()
-
- const displayCurrencyAsset = useMemo(
- () =>
- displayCurrencies.find((asset) => asset.denom === displayCurrency) ?? displayCurrencies[0],
- [displayCurrency, displayCurrencies],
- )
-
- const isUSD = displayCurrencyAsset.id === 'USD'
-
- const amount = useMemo(() => {
- const coinValue = getCoinValue(props.coin, prices)
-
- if (displayCurrency === ORACLE_DENOM) return coinValue.toNumber()
-
- const displayDecimals = displayCurrencyAsset.decimals
- const displayPrice = getCoinValue(
- BNCoin.fromDenomAndBigNumber(displayCurrency, BN(1).shiftedBy(displayDecimals)),
- prices,
- )
-
- return coinValue.div(displayPrice).toNumber()
- }, [displayCurrency, displayCurrencyAsset.decimals, prices, props.coin])
-
- const isLessThanACent = (isUSD && amount < 0.01 && amount > 0) || (amount === 0 && props.showZero)
- const smallerThanPrefix = isLessThanACent ? '< ' : ''
-
- const prefix = isUSD
- ? `${props.isApproximation ? '~ ' : smallerThanPrefix}$`
- : `${props.isApproximation ? '~ ' : ''}`
- const suffix = isUSD
- ? ''
- : ` ${displayCurrencyAsset.symbol ? ` ${displayCurrencyAsset.symbol}` : ''}`
-
- return (
-
- )
-}
diff --git a/src/components/Earn/Farm/FeaturedVaults.tsx b/src/components/Earn/Farm/FeaturedVaults.tsx
deleted file mode 100644
index afa5b66f..00000000
--- a/src/components/Earn/Farm/FeaturedVaults.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-import { Suspense } from 'react'
-
-import Card from 'components/Card'
-import VaultCard from 'components/Earn/Farm/VaultCard'
-import useVaults from 'hooks/useVaults'
-
-function Content() {
- const { data: vaults } = useVaults()
- if (!vaults) return null
- const featuredVaults = vaults.filter((vault) => vault.isFeatured)
-
- if (!featuredVaults.length) return null
-
- return (
-
- {featuredVaults.map((vault) => (
-
- ))}
-
- )
-}
-
-export default function FeaturedVaults() {
- return (
-
-
-
- )
-}
diff --git a/src/components/Earn/Farm/VaultCard.tsx b/src/components/Earn/Farm/VaultCard.tsx
deleted file mode 100644
index a0864693..00000000
--- a/src/components/Earn/Farm/VaultCard.tsx
+++ /dev/null
@@ -1,83 +0,0 @@
-import ActionButton from 'components/Button/ActionButton'
-import DoubleLogo from 'components/DoubleLogo'
-import Text from 'components/Text'
-import TitleAndSubCell from 'components/TitleAndSubCell'
-import useCurrentAccount from 'hooks/useCurrentAccount'
-import useStore from 'store'
-import { getAssetByDenom } from 'utils/assets'
-import { formatPercent, formatValue } from 'utils/formatters'
-
-interface Props {
- vault: Vault
- title: string
- subtitle: string
- provider?: string
- unbondingPeriod?: number
-}
-
-export default function VaultCard(props: Props) {
- const currentAccount = useCurrentAccount()
-
- function openVaultModal() {
- useStore.setState({
- vaultModal: {
- vault: props.vault,
- selectedBorrowDenoms: [props.vault.denoms.secondary],
- isCreate: true,
- },
- })
- }
-
- return (
-
-
-
-
- {props.subtitle}
-
-
- {props.title}
- {props.provider && (
-
- via {props.provider}
-
- )}
-
-
-
-
-
-
-
-
-
-
-
-
- )
-}
diff --git a/src/components/Icons/ArrowRight.svg b/src/components/Icons/ArrowRight.svg
deleted file mode 100644
index b3432e1c..00000000
--- a/src/components/Icons/ArrowRight.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
diff --git a/src/components/Icons/index.ts b/src/components/Icons/index.ts
deleted file mode 100644
index 42b9ce7a..00000000
--- a/src/components/Icons/index.ts
+++ /dev/null
@@ -1,68 +0,0 @@
-// @index(['./*.svg'], f => `export { default as ${f.name} } from 'components/Icons/${f.name}.svg'`)
-export { default as Account } from 'components/Icons/Account.svg'
-export { default as AccountArrowDown } from 'components/Icons/AccountArrowDown.svg'
-export { default as ArrowChartLineUp } from 'components/Icons/ArrowChartLineUp.svg'
-export { default as ArrowCircle } from 'components/Icons/ArrowCircle.svg'
-export { default as ArrowCircledTopRight } from 'components/Icons/ArrowCircledTopRight.svg'
-export { default as ArrowDownLine } from 'components/Icons/ArrowDownLine.svg'
-export { default as ArrowRight } from 'components/Icons/ArrowRight.svg'
-export { default as ArrowUpLine } from 'components/Icons/ArrowUpLine.svg'
-export { default as Chain } from 'components/Icons/Chain.svg'
-export { default as Check } from 'components/Icons/Check.svg'
-export { default as CheckCircled } from 'components/Icons/CheckCircled.svg'
-export { default as ChevronDown } from 'components/Icons/ChevronDown.svg'
-export { default as ChevronLeft } from 'components/Icons/ChevronLeft.svg'
-export { default as ChevronRight } from 'components/Icons/ChevronRight.svg'
-export { default as ChevronUp } from 'components/Icons/ChevronUp.svg'
-export { default as Circle } from 'components/Icons/Circle.svg'
-export { default as Coins } from 'components/Icons/Coins.svg'
-export { default as CoinsSwap } from 'components/Icons/CoinsSwap.svg'
-export { default as Compass } from 'components/Icons/Compass.svg'
-export { default as Copy } from 'components/Icons/Copy.svg'
-export { default as Cross } from 'components/Icons/Cross.svg'
-export { default as CrossCircled } from 'components/Icons/CrossCircled.svg'
-export { default as Enter } from 'components/Icons/Enter.svg'
-export { default as ExclamationMarkCircled } from 'components/Icons/ExclamationMarkCircled.svg'
-export { default as ExclamationMarkTriangle } from 'components/Icons/ExclamationMarkTriangle.svg'
-export { default as ExternalLink } from 'components/Icons/ExternalLink.svg'
-export { default as Flag } from 'components/Icons/Flag.svg'
-export { default as Gear } from 'components/Icons/Gear.svg'
-export { default as GridGlobe } from 'components/Icons/GridGlobe.svg'
-export { default as GridHole } from 'components/Icons/GridHole.svg'
-export { default as GridLandscape } from 'components/Icons/GridLandscape.svg'
-export { default as GridPlanet } from 'components/Icons/GridPlanet.svg'
-export { default as GridTire } from 'components/Icons/GridTire.svg'
-export { default as GridWeb } from 'components/Icons/GridWeb.svg'
-export { default as HandCoins } from 'components/Icons/HandCoins.svg'
-export { default as Heart } from 'components/Icons/Heart.svg'
-export { default as InfoCircle } from 'components/Icons/InfoCircle.svg'
-export { default as LockLocked } from 'components/Icons/LockLocked.svg'
-export { default as LockUnlocked } from 'components/Icons/LockUnlocked.svg'
-export { default as Logo } from 'components/Icons/Logo.svg'
-export { default as Luggage } from 'components/Icons/Luggage.svg'
-export { default as MarsProtocol } from 'components/Icons/MarsProtocol.svg'
-export { default as Osmo } from 'components/Icons/Osmo.svg'
-export { default as OverlayMark } from 'components/Icons/OverlayMark.svg'
-export { default as Plus } from 'components/Icons/Plus.svg'
-export { default as PlusCircled } from 'components/Icons/PlusCircled.svg'
-export { default as PlusSquared } from 'components/Icons/PlusSquared.svg'
-export { default as PythLogoType } from 'components/Icons/PythLogoType.svg'
-export { default as Questionmark } from 'components/Icons/Questionmark.svg'
-export { default as ReceiptCheck } from 'components/Icons/ReceiptCheck.svg'
-export { default as Scale } from 'components/Icons/Scale.svg'
-export { default as Search } from 'components/Icons/Search.svg'
-export { default as Shield } from 'components/Icons/Shield.svg'
-export { default as SortAsc } from 'components/Icons/SortAsc.svg'
-export { default as SortDesc } from 'components/Icons/SortDesc.svg'
-export { default as SortNone } from 'components/Icons/SortNone.svg'
-export { default as StarFilled } from 'components/Icons/StarFilled.svg'
-export { default as StarOutlined } from 'components/Icons/StarOutlined.svg'
-export { default as Subtract } from 'components/Icons/Subtract.svg'
-export { default as SwapIcon } from 'components/Icons/SwapIcon.svg'
-export { default as ThreeDots } from 'components/Icons/ThreeDots.svg'
-export { default as TooltipArrow } from 'components/Icons/TooltipArrow.svg'
-export { default as TrashBin } from 'components/Icons/TrashBin.svg'
-export { default as Twitter } from 'components/Icons/Twitter.svg'
-export { default as VerticalThreeLine } from 'components/Icons/VerticalThreeLine.svg'
-export { default as Wallet } from 'components/Icons/Wallet.svg'
-// @endindex
diff --git a/src/components/Modals/Account/AccountDeleteAlertDialog.tsx b/src/components/Modals/Account/AccountDeleteAlertDialog.tsx
index e340fc12..865d0c31 100644
--- a/src/components/Modals/Account/AccountDeleteAlertDialog.tsx
+++ b/src/components/Modals/Account/AccountDeleteAlertDialog.tsx
@@ -1,6 +1,6 @@
import { useEffect } from 'react'
-import { Enter, InfoCircle } from 'components/Icons'
+import { Enter, InfoCircle } from 'components/common/Icons'
import useAlertDialog from 'hooks/useAlertDialog'
interface Props {
diff --git a/src/components/Modals/Account/AccountDeleteModal.tsx b/src/components/Modals/Account/AccountDeleteModal.tsx
index 13c6fd5a..ba001cdd 100644
--- a/src/components/Modals/Account/AccountDeleteModal.tsx
+++ b/src/components/Modals/Account/AccountDeleteModal.tsx
@@ -1,13 +1,14 @@
import { useCallback, useMemo } from 'react'
import { useLocation, useNavigate, useParams, useSearchParams } from 'react-router-dom'
-import AssetBalanceRow from 'components/Asset/AssetBalanceRow'
-import { ArrowRight, ExclamationMarkCircled } from 'components/Icons'
+import AssetBalanceRow from 'components/common/assets/AssetBalanceRow'
+import { ArrowRight, ExclamationMarkCircled } from 'components/common/Icons'
import AccountDeleteAlertDialog from 'components/Modals/Account/AccountDeleteAlertDialog'
-import Text from 'components/Text'
+import Text from 'components/common/Text'
+import useAllAssets from 'hooks/assets/useAllAssets'
import useStore from 'store'
import { BNCoin } from 'types/classes/BNCoin'
-import { getAssetByDenom } from 'utils/assets'
+import { byDenom } from 'utils/array'
import { combineBNCoins } from 'utils/parsers'
import { getPage, getRoute } from 'utils/route'
@@ -31,7 +32,7 @@ function AccountDeleteModal(props: Props) {
const { address } = useParams()
const { debts, vaults, id: accountId } = modal || {}
const [searchParams] = useSearchParams()
-
+ const assets = useAllAssets()
const closeDeleteAccountModal = useCallback(() => {
useStore.setState({ accountDeleteModal: null })
}, [])
@@ -117,7 +118,7 @@ function AccountDeleteModal(props: Props) {
{depositsAndLends.map((position, index) => {
const coin = BNCoin.fromDenomAndBigNumber(position.denom, position.amount)
- const asset = getAssetByDenom(position.denom)
+ const asset = assets.find(byDenom(position.denom))
if (!asset) return null
return
})}
diff --git a/src/components/Modals/AddVaultAssets/AddVaultBorrowAssetsModalContent.tsx b/src/components/Modals/AddVaultAssets/AddVaultBorrowAssetsModalContent.tsx
index 361b4191..8bd8e29f 100644
--- a/src/components/Modals/AddVaultAssets/AddVaultBorrowAssetsModalContent.tsx
+++ b/src/components/Modals/AddVaultAssets/AddVaultBorrowAssetsModalContent.tsx
@@ -1,9 +1,9 @@
import { useCallback, useMemo, useState } from 'react'
-import AssetSelectTable from 'components/Modals/AssetsSelect/AssetSelectTable'
-import SearchBar from 'components/SearchBar'
-import Text from 'components/Text'
-import useMarketBorrowings from 'hooks/useMarketBorrowings'
+import AssetsSelect from 'components/Modals/AssetsSelect'
+import SearchBar from 'components/common/SearchBar'
+import Text from 'components/common/Text'
+import useMarketBorrowings from 'hooks/markets/useMarketBorrowings'
import useStore from 'store'
interface Props {
@@ -89,11 +89,11 @@ export default function AddVaultAssetsModalContent(props: Props) {
Leverage will be set at 50% for both assets by default
-
Assets not in the liquidity pool
@@ -102,11 +102,11 @@ export default function AddVaultAssetsModalContent(props: Props) {
these assets below.
-
>
diff --git a/src/components/Modals/AddVaultAssets/index.tsx b/src/components/Modals/AddVaultAssets/index.tsx
index fb4e7e5f..f3d0c7a1 100644
--- a/src/components/Modals/AddVaultAssets/index.tsx
+++ b/src/components/Modals/AddVaultAssets/index.tsx
@@ -1,10 +1,10 @@
import { useCallback, useState } from 'react'
-import Button from 'components/Button'
-import { CircularProgress } from 'components/CircularProgress'
-import Modal from 'components/Modal'
+import Button from 'components/common/Button'
+import { CircularProgress } from 'components/common/CircularProgress'
+import Modal from 'components/Modals/Modal'
import AddVaultAssetsModalContent from 'components/Modals/AddVaultAssets/AddVaultBorrowAssetsModalContent'
-import Text from 'components/Text'
+import Text from 'components/common/Text'
import useStore from 'store'
export default function AddVaultBorrowAssetsModal() {
diff --git a/src/components/Modals/AlertDialog/ButtonIcons.tsx b/src/components/Modals/AlertDialog/ButtonIcons.tsx
index f4e028f7..9ad2debc 100644
--- a/src/components/Modals/AlertDialog/ButtonIcons.tsx
+++ b/src/components/Modals/AlertDialog/ButtonIcons.tsx
@@ -1,4 +1,4 @@
-import { Enter } from 'components/Icons'
+import { Enter } from 'components/common/Icons'
export function NoIcon() {
return (
diff --git a/src/components/Modals/AlertDialog/index.tsx b/src/components/Modals/AlertDialog/index.tsx
index 68512648..c61438f8 100644
--- a/src/components/Modals/AlertDialog/index.tsx
+++ b/src/components/Modals/AlertDialog/index.tsx
@@ -1,10 +1,10 @@
import classNames from 'classnames'
-import Button from 'components/Button'
-import Checkbox from 'components/Checkbox'
-import Modal from 'components/Modal'
+import Button from 'components/common/Button'
+import Checkbox from 'components/common/Checkbox'
+import Modal from 'components/Modals/Modal'
import { NoIcon, YesIcon } from 'components/Modals/AlertDialog/ButtonIcons'
-import Text from 'components/Text'
+import Text from 'components/common/Text'
import useAlertDialog from 'hooks/useAlertDialog'
import useToggle from 'hooks/useToggle'
diff --git a/src/components/Modals/AssetAmountSelectActionModal.tsx b/src/components/Modals/AssetAmountSelectActionModal.tsx
index c937223b..a8f1f2c2 100644
--- a/src/components/Modals/AssetAmountSelectActionModal.tsx
+++ b/src/components/Modals/AssetAmountSelectActionModal.tsx
@@ -1,22 +1,23 @@
import { useCallback, useState } from 'react'
-import CurrentAccountSummary from 'components/Account/CurrentAccountSummary'
-import AssetImage from 'components/Asset/AssetImage'
-import Button from 'components/Button'
-import Card from 'components/Card'
-import Divider from 'components/Divider'
-import { ArrowRight } from 'components/Icons'
-import Modal from 'components/Modal'
-import Text from 'components/Text'
-import TokenInputWithSlider from 'components/TokenInput/TokenInputWithSlider'
+import Modal from 'components/Modals/Modal'
+import CurrentAccountSummary from 'components/account/CurrentAccountSummary'
+import Button from 'components/common/Button'
+import Card from 'components/common/Card'
+import Divider from 'components/common/Divider'
+import { ArrowRight } from 'components/common/Icons'
+import Text from 'components/common/Text'
+import TokenInputWithSlider from 'components/common/TokenInput/TokenInputWithSlider'
+import AssetImage from 'components/common/assets/AssetImage'
import { BN_ZERO } from 'constants/math'
+import { BNCoin } from 'types/classes/BNCoin'
import { byDenom } from 'utils/array'
import { BN } from 'utils/helpers'
interface Props {
asset: Asset
title: string
- coinBalances: Coin[]
+ coinBalances: BNCoin[]
actionButtonText: string
contentHeader?: JSX.Element
onClose: () => void
diff --git a/src/components/Modals/AssetsSelect/AssetSelectTable.tsx b/src/components/Modals/AssetsSelect/AssetSelectTable.tsx
deleted file mode 100644
index 5ca92f93..00000000
--- a/src/components/Modals/AssetsSelect/AssetSelectTable.tsx
+++ /dev/null
@@ -1,154 +0,0 @@
-import {
- flexRender,
- getCoreRowModel,
- getSortedRowModel,
- RowSelectionState,
- SortingState,
- useReactTable,
-} from '@tanstack/react-table'
-import classNames from 'classnames'
-import { useEffect, useMemo, useState } from 'react'
-
-import { SortAsc, SortDesc, SortNone } from 'components/Icons'
-import useAssetTableColumns from 'components/Modals/AssetsSelect/useAssetTableColumns'
-import Text from 'components/Text'
-import useMarketAssets from 'hooks/useMarketAssets'
-import useStore from 'store'
-import { byDenom } from 'utils/array'
-
-interface Props {
- assets: Asset[] | BorrowAsset[]
- selectedDenoms: string[]
- onChangeSelected: (denoms: string[]) => void
- isBorrow: boolean
-}
-
-export default function AssetSelectTable(props: Props) {
- const { data: markets } = useMarketAssets()
- const defaultSelected = useMemo(() => {
- const assets = props.assets as BorrowAsset[]
- return assets.reduce(
- (acc, asset, index) => {
- if (props.selectedDenoms?.includes(asset.denom)) {
- acc[index] = true
- }
- return acc
- },
- {} as { [key: number]: boolean },
- )
- }, [props.selectedDenoms, props.assets])
- const [sorting, setSorting] = useState([{ id: 'symbol', desc: false }])
- const [selected, setSelected] = useState(defaultSelected)
- const balances = useStore((s) => s.balances)
- const columns = useAssetTableColumns(props.isBorrow)
- const tableData: AssetTableRow[] = useMemo(() => {
- return props.assets.map((asset) => {
- const balancesForAsset = balances.find(byDenom(asset.denom))
- return {
- asset,
- balance: balancesForAsset?.amount ?? '0',
- market: markets.find((market) => market.denom === asset.denom),
- }
- })
- }, [balances, props.assets, markets])
-
- const table = useReactTable({
- data: tableData,
- columns,
- state: {
- sorting,
- rowSelection: selected,
- },
- onRowSelectionChange: setSelected,
- onSortingChange: setSorting,
- getCoreRowModel: getCoreRowModel(),
- getSortedRowModel: getSortedRowModel(),
- })
-
- useEffect(() => {
- const newSelectedDenoms = props.assets
- .filter((_, index) => selected[index])
- .map((asset) => asset.denom)
-
- if (
- props.selectedDenoms.length === newSelectedDenoms.length &&
- newSelectedDenoms.every((denom) => props.selectedDenoms.includes(denom))
- )
- return
- props.onChangeSelected(newSelectedDenoms)
- }, [selected, props])
-
- return (
-
-
- {table.getHeaderGroups().map((headerGroup) => (
-
- {headerGroup.headers.map((header) => {
- return (
-
-
-
- {header.column.getCanSort()
- ? {
- asc: ,
- desc: ,
- false: ,
- }[header.column.getIsSorted() as string] ?? null
- : null}
-
-
- {flexRender(header.column.columnDef.header, header.getContext())}
-
-
-
- )
- })}
-
- ))}
-
-
- {table.getRowModel().rows.map((row) => {
- return (
- row.toggleSelected()}
- >
- {row.getVisibleCells().map((cell) => {
- return (
-
- {flexRender(cell.column.columnDef.cell, cell.getContext())}
-
- )
- })}
-
- )
- })}
-
-
- )
-}
diff --git a/src/components/Modals/AssetsSelect/Columns/Asset.tsx b/src/components/Modals/AssetsSelect/Columns/Asset.tsx
new file mode 100644
index 00000000..b29b098f
--- /dev/null
+++ b/src/components/Modals/AssetsSelect/Columns/Asset.tsx
@@ -0,0 +1,55 @@
+import { Row } from '@tanstack/react-table'
+
+import Checkbox from 'components/common/Checkbox'
+import Text from 'components/common/Text'
+import AssetImage from 'components/common/assets/AssetImage'
+import AssetRate from 'components/common/assets/AssetRate'
+
+export const ASSET_META = { id: 'name', header: 'Asset', accessorKey: 'asset.symbol' }
+
+interface Props {
+ row: Row
+}
+
+function isBorrowAsset(object?: any): object is BorrowAsset {
+ if (!object) return false
+ return 'borrowRate' in object
+}
+
+export default function Asset(props: Props) {
+ const { row } = props
+ const asset = row.original.asset
+ const market = row.original.market
+ const isBorrow = isBorrowAsset(asset)
+ const showRate = !isBorrow && market?.borrowEnabled
+ const apy = isBorrow ? market?.apy.borrow : market?.apy.deposit
+
+ return (
+
+
+
+
+
+ {asset.symbol}
+
+ {showRate && market ? (
+
+ ) : (
+
{asset.name}
+ )}
+
+
+ )
+}
diff --git a/src/components/Modals/AssetsSelect/Columns/Balance.tsx b/src/components/Modals/AssetsSelect/Columns/Balance.tsx
new file mode 100644
index 00000000..b26187eb
--- /dev/null
+++ b/src/components/Modals/AssetsSelect/Columns/Balance.tsx
@@ -0,0 +1,38 @@
+import { Row } from '@tanstack/react-table'
+
+import DisplayCurrency from 'components/common/DisplayCurrency'
+import { FormattedNumber } from 'components/common/FormattedNumber'
+import { BN_ZERO } from 'constants/math'
+import { BNCoin } from 'types/classes/BNCoin'
+import { demagnify } from 'utils/formatters'
+import { BN } from 'utils/helpers'
+
+export const BALANCE_META = { id: 'value', header: 'Balance', accessorKey: 'value' }
+
+interface Props {
+ row: Row
+}
+
+export const valueSortingFn = (a: Row, b: Row): number => {
+ const valueA = a.original.value ?? BN_ZERO
+ const valueB = b.original.value ?? BN_ZERO
+ return valueA.minus(valueB).toNumber()
+}
+
+export default function Balance(props: Props) {
+ const { row } = props
+ const asset = row.original.asset
+ const balance = BN(row.original.balance ?? '0')
+ const coin = BNCoin.fromDenomAndBigNumber(asset.denom, balance)
+
+ return (
+
+
+
+
+ )
+}
diff --git a/src/components/Modals/AssetsSelect/Columns/BorrowRate.tsx b/src/components/Modals/AssetsSelect/Columns/BorrowRate.tsx
new file mode 100644
index 00000000..4acf2a61
--- /dev/null
+++ b/src/components/Modals/AssetsSelect/Columns/BorrowRate.tsx
@@ -0,0 +1,25 @@
+import { Row } from '@tanstack/react-table'
+
+import Text from 'components/common/Text'
+import { formatPercent } from 'utils/formatters'
+
+export const BORROW_RATE_META = {
+ id: 'asset.borrowRate',
+ header: 'BorrowRate',
+ accessorKey: 'asset.borrowRate',
+}
+
+interface Props {
+ row: Row
+}
+
+export default function BorrowRate(props: Props) {
+ const { row } = props
+ const asset = row.original.asset as BorrowAsset
+
+ return (
+
+ {formatPercent(asset.borrowRate ?? 0)}
+
+ )
+}
diff --git a/src/components/Modals/AssetsSelect/Columns/useAssetSelectColumns.tsx b/src/components/Modals/AssetsSelect/Columns/useAssetSelectColumns.tsx
new file mode 100644
index 00000000..fa98bf42
--- /dev/null
+++ b/src/components/Modals/AssetsSelect/Columns/useAssetSelectColumns.tsx
@@ -0,0 +1,30 @@
+import { ColumnDef } from '@tanstack/react-table'
+import { useMemo } from 'react'
+
+import Asset, { ASSET_META } from 'components/Modals/AssetsSelect/Columns/Asset'
+import Balance, {
+ BALANCE_META,
+ valueSortingFn,
+} from 'components/Modals/AssetsSelect/Columns/Balance'
+import BorrowRate, { BORROW_RATE_META } from 'components/Modals/AssetsSelect/Columns/BorrowRate'
+
+export default function useAssetSelectColumns(isBorrow?: boolean) {
+ return useMemo[]>(() => {
+ return [
+ {
+ ...ASSET_META,
+ cell: ({ row }) => ,
+ },
+ isBorrow
+ ? {
+ ...BORROW_RATE_META,
+ cell: ({ row }) => ,
+ }
+ : {
+ ...BALANCE_META,
+ cell: ({ row }) => ,
+ sortingFn: valueSortingFn,
+ },
+ ]
+ }, [isBorrow])
+}
diff --git a/src/components/Modals/AssetsSelect/index.tsx b/src/components/Modals/AssetsSelect/index.tsx
new file mode 100644
index 00000000..3c8ffbf9
--- /dev/null
+++ b/src/components/Modals/AssetsSelect/index.tsx
@@ -0,0 +1,81 @@
+import { RowSelectionState } from '@tanstack/react-table'
+import { useEffect, useMemo, useState } from 'react'
+
+import useAssetSelectColumns from 'components/Modals/AssetsSelect/Columns/useAssetSelectColumns'
+import Table from 'components/common/Table'
+import useGetCoinValue from 'hooks/assets/useGetCoinValue'
+import useMarketAssets from 'hooks/markets/useMarketAssets'
+import useStore from 'store'
+import { BNCoin } from 'types/classes/BNCoin'
+import { byDenom } from 'utils/array'
+import { BN } from 'utils/helpers'
+
+interface Props {
+ assets: Asset[]
+ onChangeSelected: (selected: string[]) => void
+ selectedDenoms: string[]
+ isBorrow?: boolean
+}
+
+export default function AssetsSelect(props: Props) {
+ const { assets, onChangeSelected, selectedDenoms, isBorrow } = props
+ const columns = useAssetSelectColumns(isBorrow)
+ const { data: markets } = useMarketAssets()
+ const getCoinValue = useGetCoinValue()
+
+ const defaultSelected = useMemo(() => {
+ const selectableAssets = assets
+ return selectableAssets.reduce(
+ (acc, asset, index) => {
+ if (selectedDenoms?.includes(asset.denom)) {
+ acc[index] = true
+ }
+ return acc
+ },
+ {} as { [key: number]: boolean },
+ )
+ }, [selectedDenoms, assets])
+
+ const [selected, setSelected] = useState(defaultSelected)
+
+ const balances = useStore((s) => s.balances)
+ const tableData: AssetTableRow[] = useMemo(() => {
+ return assets.map((asset) => {
+ const balancesForAsset = balances.find(byDenom(asset.denom))
+ const coin = BNCoin.fromDenomAndBigNumber(asset.denom, BN(balancesForAsset?.amount ?? '0'))
+ const value = getCoinValue(coin)
+ return {
+ asset,
+ balance: balancesForAsset?.amount ?? '0',
+ value,
+ market: markets.find((market) => market.denom === asset.denom),
+ }
+ })
+ }, [balances, assets, markets, getCoinValue])
+
+ useEffect(() => {
+ const selectedAssets = assets.filter((_, index) => selected[index])
+
+ const newSelectedDenoms = selectedAssets
+ .sort((a, b) => a.symbol.localeCompare(b.symbol))
+ .map((asset) => asset.denom)
+ if (
+ selectedDenoms.length === newSelectedDenoms.length &&
+ newSelectedDenoms.every((denom) => selectedDenoms.includes(denom))
+ )
+ return
+ onChangeSelected(newSelectedDenoms)
+ }, [selected, props, assets, selectedDenoms, onChangeSelected])
+
+ return (
+
+ )
+}
diff --git a/src/components/Modals/AssetsSelect/useAssetTableColumns.tsx b/src/components/Modals/AssetsSelect/useAssetTableColumns.tsx
deleted file mode 100644
index 748c56b7..00000000
--- a/src/components/Modals/AssetsSelect/useAssetTableColumns.tsx
+++ /dev/null
@@ -1,96 +0,0 @@
-import { ColumnDef } from '@tanstack/react-table'
-import React from 'react'
-
-import AssetImage from 'components/Asset/AssetImage'
-import AssetRate from 'components/Asset/AssetRate'
-import Checkbox from 'components/Checkbox'
-import DisplayCurrency from 'components/DisplayCurrency'
-import { FormattedNumber } from 'components/FormattedNumber'
-import Text from 'components/Text'
-import { BNCoin } from 'types/classes/BNCoin'
-import { getAssetByDenom } from 'utils/assets'
-import { demagnify, formatPercent } from 'utils/formatters'
-
-function showBorrowRate(data: AssetTableRow[]) {
- const assetData = data.length && (data[0].asset as BorrowAsset)
- return !!(assetData && assetData?.borrowRate)
-}
-
-export default function useAssetTableColumns(isBorrow: boolean) {
- return React.useMemo[]>(
- () => [
- {
- header: 'Asset',
- accessorKey: 'symbol',
- id: 'symbol',
- cell: ({ row }) => {
- const asset = getAssetByDenom(row.original.asset.denom) as Asset
- const market = row.original.market
- const borrowAsset = row.original.asset as BorrowAsset
- const showRate = !borrowAsset?.borrowRate
- const apy = isBorrow ? market?.apy.borrow : market?.apy.deposit
-
- return (
-
-
-
-
-
- {asset.symbol}
-
- {showRate && market ? (
-
- ) : (
-
{asset.name}
- )}
-
-
- )
- },
- },
- {
- id: 'details',
- header: (data) => {
- const tableData = data.table.options.data as AssetTableRow[]
- if (showBorrowRate(tableData)) return 'Borrow Rate'
- return 'Balance'
- },
- cell: ({ row }) => {
- const asset = row.original.asset as BorrowAsset
- const balance = row.original.balance
- if (asset?.borrowRate)
- return (
-
- {formatPercent(asset.borrowRate ?? 0)}
-
- )
- if (!balance) return null
- const coin = new BNCoin({ denom: row.original.asset.denom, amount: balance })
- return (
-
-
-
-
- )
- },
- },
- ],
- [isBorrow],
- )
-}
diff --git a/src/components/Modals/BorrowModal.tsx b/src/components/Modals/BorrowModal.tsx
index 193674ee..81fb7b66 100644
--- a/src/components/Modals/BorrowModal.tsx
+++ b/src/components/Modals/BorrowModal.tsx
@@ -1,24 +1,24 @@
import BigNumber from 'bignumber.js'
import { useCallback, useEffect, useMemo, useState } from 'react'
-import AccountSummary from 'components/Account/AccountSummary'
-import AssetImage from 'components/Asset/AssetImage'
-import Button from 'components/Button'
-import Card from 'components/Card'
-import DisplayCurrency from 'components/DisplayCurrency'
-import Divider from 'components/Divider'
-import { FormattedNumber } from 'components/FormattedNumber'
-import { ArrowRight, InfoCircle } from 'components/Icons'
-import Modal from 'components/Modal'
-import Switch from 'components/Switch'
-import Text from 'components/Text'
-import TitleAndSubCell from 'components/TitleAndSubCell'
-import TokenInputWithSlider from 'components/TokenInput/TokenInputWithSlider'
+import AccountSummary from 'components/account/AccountSummary'
+import AssetImage from 'components/common/assets/AssetImage'
+import Button from 'components/common/Button'
+import Card from 'components/common/Card'
+import DisplayCurrency from 'components/common/DisplayCurrency'
+import Divider from 'components/common/Divider'
+import { FormattedNumber } from 'components/common/FormattedNumber'
+import { ArrowRight, InfoCircle } from 'components/common/Icons'
+import Switch from 'components/common/Switch'
+import Text from 'components/common/Text'
+import TitleAndSubCell from 'components/common/TitleAndSubCell'
+import TokenInputWithSlider from 'components/common/TokenInput/TokenInputWithSlider'
+import Modal from 'components/Modals/Modal'
import { BN_ZERO } from 'constants/math'
+import useCurrentAccount from 'hooks/accounts/useCurrentAccount'
+import useMarketAssets from 'hooks/markets/useMarketAssets'
import useAutoLend from 'hooks/useAutoLend'
-import useCurrentAccount from 'hooks/useCurrentAccount'
import useHealthComputer from 'hooks/useHealthComputer'
-import useMarketAssets from 'hooks/useMarketAssets'
import useToggle from 'hooks/useToggle'
import { useUpdatedAccount } from 'hooks/useUpdatedAccount'
import { getDepositAndLendCoinsToSpend } from 'hooks/useUpdatedAccount/functions'
diff --git a/src/components/Modals/FundWithdraw/FundAccount.tsx b/src/components/Modals/FundWithdraw/FundAccount.tsx
index 81b8da23..e5c5a2f4 100644
--- a/src/components/Modals/FundWithdraw/FundAccount.tsx
+++ b/src/components/Modals/FundWithdraw/FundAccount.tsx
@@ -1,4 +1,4 @@
-import AccountFundContent from 'components/Account/AccountFund/AccountFundContent'
+import AccountFundContent from 'components/account/AccountFund/AccountFundContent'
import useStore from 'store'
interface Props {
diff --git a/src/components/Modals/FundWithdraw/WithdrawFromAccount.tsx b/src/components/Modals/FundWithdraw/WithdrawFromAccount.tsx
index 52bd70a4..9488088a 100644
--- a/src/components/Modals/FundWithdraw/WithdrawFromAccount.tsx
+++ b/src/components/Modals/FundWithdraw/WithdrawFromAccount.tsx
@@ -1,14 +1,15 @@
import BigNumber from 'bignumber.js'
import { useEffect, useState } from 'react'
-import Button from 'components/Button'
-import Divider from 'components/Divider'
-import { ArrowRight } from 'components/Icons'
-import Switch from 'components/Switch'
-import Text from 'components/Text'
-import TokenInputWithSlider from 'components/TokenInput/TokenInputWithSlider'
-import { ASSETS } from 'constants/assets'
+import Button from 'components/common/Button'
+import Divider from 'components/common/Divider'
+import { ArrowRight } from 'components/common/Icons'
+import Switch from 'components/common/Switch'
+import Text from 'components/common/Text'
+import TokenInputWithSlider from 'components/common/TokenInput/TokenInputWithSlider'
import { BN_ZERO } from 'constants/math'
+import useAllAssets from 'hooks/assets/useAllAssets'
+import useMarketEnabledAssets from 'hooks/assets/useMarketEnabledAssets'
import useHealthComputer from 'hooks/useHealthComputer'
import useToggle from 'hooks/useToggle'
import { useUpdatedAccount } from 'hooks/useUpdatedAccount'
@@ -16,7 +17,6 @@ import useStore from 'store'
import { BNCoin } from 'types/classes/BNCoin'
import { cloneAccount, getMergedBalancesForAsset, removeDepositsAndLends } from 'utils/accounts'
import { byDenom } from 'utils/array'
-import { getEnabledMarketAssets } from 'utils/assets'
interface Props {
account: Account
@@ -24,8 +24,9 @@ interface Props {
export default function WithdrawFromAccount(props: Props) {
const { account } = props
+ const assets = useAllAssets()
const defaultAsset =
- ASSETS.find(byDenom(account.deposits[0]?.denom || account.lends[0]?.denom)) ?? ASSETS[0]
+ assets.find(byDenom(account.deposits[0]?.denom || account.lends[0]?.denom)) ?? assets[0]
const withdraw = useStore((s) => s.withdraw)
const [withdrawWithBorrowing, setWithdrawWithBorrowing] = useToggle()
const [currentAsset, setCurrentAsset] = useState(defaultAsset)
@@ -35,7 +36,8 @@ export default function WithdrawFromAccount(props: Props) {
const accountClone = cloneAccount(account)
const borrowAccount = removeDepositsAndLends(accountClone, currentAsset.denom)
const { computeMaxBorrowAmount } = useHealthComputer(borrowAccount)
- const balances = getMergedBalancesForAsset(account, getEnabledMarketAssets())
+ const marketEnabledAssets = useMarketEnabledAssets()
+ const balances = getMergedBalancesForAsset(account, marketEnabledAssets)
const maxWithdrawAmount = computeMaxWithdrawAmount(currentAsset.denom)
const maxWithdrawWithBorrowAmount = computeMaxBorrowAmount(currentAsset.denom, 'wallet').plus(
maxWithdrawAmount,
@@ -46,10 +48,12 @@ export default function WithdrawFromAccount(props: Props) {
const max = withdrawWithBorrowing ? maxWithdrawWithBorrowAmount : maxWithdrawAmount
const accountDeposit = account.deposits.find(byDenom(currentAsset.denom))?.amount ?? BN_ZERO
- const shouldReclaim =
- amount.isGreaterThan(accountDeposit) && !withdrawWithBorrowing && currentAsset.isAutoLendEnabled
- const reclaimAmount = shouldReclaim ? amount.minus(accountDeposit) : BN_ZERO
- const isReclaimingMaxAmount = maxWithdrawAmount.isEqualTo(amount)
+ const accountLent = account.lends.find(byDenom(currentAsset.denom))?.amount ?? BN_ZERO
+ const shouldReclaim = amount.isGreaterThan(accountDeposit) && !accountLent.isZero()
+ const isReclaimingMaxAmount = accountLent.isLessThanOrEqualTo(amount.minus(accountDeposit))
+ const reclaimAmount = isReclaimingMaxAmount
+ ? amount
+ : accountLent.minus(amount).minus(accountDeposit)
function onChangeAmount(val: BigNumber) {
setAmount(val)
@@ -65,13 +69,14 @@ export default function WithdrawFromAccount(props: Props) {
const borrow = !debtAmount.isZero()
? [BNCoin.fromDenomAndBigNumber(currentAsset.denom, debtAmount)]
: []
- const reclaims = !reclaimAmount.isZero()
- ? [
- BNCoin.fromDenomAndBigNumber(currentAsset.denom, reclaimAmount).toActionCoin(
- isReclaimingMaxAmount,
- ),
- ]
- : []
+ const reclaims =
+ shouldReclaim && !reclaimAmount.isZero()
+ ? [
+ BNCoin.fromDenomAndBigNumber(currentAsset.denom, reclaimAmount).toActionCoin(
+ isReclaimingMaxAmount,
+ ),
+ ]
+ : []
withdraw({
accountId: account.id,
diff --git a/src/components/Modals/FundWithdraw/index.tsx b/src/components/Modals/FundWithdraw/index.tsx
index 619bbae3..2891c3df 100644
--- a/src/components/Modals/FundWithdraw/index.tsx
+++ b/src/components/Modals/FundWithdraw/index.tsx
@@ -1,7 +1,7 @@
import FundWithdrawModalContent from 'components/Modals/FundWithdraw/FundAndWithdrawModalContent'
import ModalContentWithSummary from 'components/Modals/ModalContentWithSummary'
-import Text from 'components/Text'
-import useAccount from 'hooks/useAccount'
+import Text from 'components/common/Text'
+import useAccount from 'hooks/accounts/useAccount'
import useAccountId from 'hooks/useAccountId'
import useStore from 'store'
diff --git a/src/components/Modals/GetStartedModal.tsx b/src/components/Modals/GetStartedModal.tsx
index 802adc32..2a403d64 100644
--- a/src/components/Modals/GetStartedModal.tsx
+++ b/src/components/Modals/GetStartedModal.tsx
@@ -1,8 +1,8 @@
import { useCallback } from 'react'
-import { ChevronRight, Compass, HandCoins, Luggage } from 'components/Icons'
-import Modal from 'components/Modal'
-import Text from 'components/Text'
+import { ChevronRight, Compass, HandCoins, Luggage } from 'components/common/Icons'
+import Modal from 'components/Modals/Modal'
+import Text from 'components/common/Text'
import useStore from 'store'
import { DocURL } from 'types/enums/docURL'
diff --git a/src/components/Modals/HLS/Deposit/CreateAccount.tsx b/src/components/Modals/HLS/Deposit/CreateAccount.tsx
index f761fc08..a73b6147 100644
--- a/src/components/Modals/HLS/Deposit/CreateAccount.tsx
+++ b/src/components/Modals/HLS/Deposit/CreateAccount.tsx
@@ -1,10 +1,10 @@
import React, { useState } from 'react'
import { mutate } from 'swr'
-import Button from 'components/Button'
-import DocsLink from 'components/DocsLink'
-import { ArrowRight } from 'components/Icons'
-import Text from 'components/Text'
+import Button from 'components/common/Button'
+import DocsLink from 'components/common/DocsLink'
+import { ArrowRight } from 'components/common/Icons'
+import Text from 'components/common/Text'
import useStore from 'store'
export default function CreateAccount() {
diff --git a/src/components/Modals/HLS/Deposit/Leverage.tsx b/src/components/Modals/HLS/Deposit/Leverage.tsx
index e8e614e4..acb2da25 100644
--- a/src/components/Modals/HLS/Deposit/Leverage.tsx
+++ b/src/components/Modals/HLS/Deposit/Leverage.tsx
@@ -1,9 +1,9 @@
import React, { useMemo } from 'react'
-import Button from 'components/Button'
-import { ArrowRight } from 'components/Icons'
+import Button from 'components/common/Button'
+import { ArrowRight } from 'components/common/Icons'
import LeverageSummary from 'components/Modals/HLS/Deposit/LeverageSummary'
-import TokenInputWithSlider from 'components/TokenInput/TokenInputWithSlider'
+import TokenInputWithSlider from 'components/common/TokenInput/TokenInputWithSlider'
import { getLeveragedApy } from 'utils/math'
interface Props {
diff --git a/src/components/Modals/HLS/Deposit/LeverageSummary.tsx b/src/components/Modals/HLS/Deposit/LeverageSummary.tsx
index 995f66ba..7139eac2 100644
--- a/src/components/Modals/HLS/Deposit/LeverageSummary.tsx
+++ b/src/components/Modals/HLS/Deposit/LeverageSummary.tsx
@@ -1,6 +1,6 @@
import React, { useMemo } from 'react'
-import SummaryItems from 'components/SummaryItems'
+import SummaryItems from 'components/common/SummaryItems'
import useBorrowAsset from 'hooks/useBorrowAsset'
interface Props {
diff --git a/src/components/Modals/HLS/Deposit/ProvideCollateral.tsx b/src/components/Modals/HLS/Deposit/ProvideCollateral.tsx
index f1ed8b49..8bff06a0 100644
--- a/src/components/Modals/HLS/Deposit/ProvideCollateral.tsx
+++ b/src/components/Modals/HLS/Deposit/ProvideCollateral.tsx
@@ -1,8 +1,8 @@
import React from 'react'
-import Button from 'components/Button'
-import { ArrowRight } from 'components/Icons'
-import TokenInputWithSlider from 'components/TokenInput/TokenInputWithSlider'
+import Button from 'components/common/Button'
+import { ArrowRight } from 'components/common/Icons'
+import TokenInputWithSlider from 'components/common/TokenInput/TokenInputWithSlider'
interface Props {
amount: BigNumber
diff --git a/src/components/Modals/HLS/Deposit/SelectAccount.tsx b/src/components/Modals/HLS/Deposit/SelectAccount.tsx
index e0bf5362..e6a8330e 100644
--- a/src/components/Modals/HLS/Deposit/SelectAccount.tsx
+++ b/src/components/Modals/HLS/Deposit/SelectAccount.tsx
@@ -1,9 +1,9 @@
import classNames from 'classnames'
import React from 'react'
-import Button from 'components/Button'
-import { ArrowRight } from 'components/Icons'
-import Radio from 'components/Radio'
+import Button from 'components/common/Button'
+import { ArrowRight } from 'components/common/Icons'
+import Radio from 'components/common/Radio'
interface Props {
hlsAccounts: Account[]
diff --git a/src/components/Modals/HLS/Deposit/SubTitles.tsx b/src/components/Modals/HLS/Deposit/SubTitles.tsx
index 20dde03f..987f2bac 100644
--- a/src/components/Modals/HLS/Deposit/SubTitles.tsx
+++ b/src/components/Modals/HLS/Deposit/SubTitles.tsx
@@ -1,10 +1,11 @@
import classNames from 'classnames'
import React from 'react'
-import DisplayCurrency from 'components/DisplayCurrency'
-import { ExclamationMarkTriangle } from 'components/Icons'
-import Text from 'components/Text'
-import WarningMessages from 'components/WarningMessages'
+import DisplayCurrency from 'components/common/DisplayCurrency'
+import { ExclamationMarkTriangle } from 'components/common/Icons'
+import Text from 'components/common/Text'
+import WarningMessages from 'components/common/WarningMessages'
+import useAllAssets from 'hooks/assets/useAllAssets'
import { BNCoin } from 'types/classes/BNCoin'
import { formatAmountWithSymbol, formatLeverage } from 'utils/formatters'
@@ -33,6 +34,7 @@ interface CollateralSubTitleProps {
}
export function CollateralSubTitle(props: CollateralSubTitleProps) {
+ const assets = useAllAssets()
if (props.isOpen) return null
if (!props.isOpen && props.amount.isZero()) {
@@ -50,10 +52,13 @@ export function CollateralSubTitle(props: CollateralSubTitleProps) {
0 ? 'text-warning' : ''}
/>
diff --git a/src/components/Modals/HLS/Deposit/Summary/ApyBreakdown.tsx b/src/components/Modals/HLS/Deposit/Summary/ApyBreakdown.tsx
index 051d6921..8e4b0ddb 100644
--- a/src/components/Modals/HLS/Deposit/Summary/ApyBreakdown.tsx
+++ b/src/components/Modals/HLS/Deposit/Summary/ApyBreakdown.tsx
@@ -1,7 +1,7 @@
import React from 'react'
-import { FormattedNumber } from 'components/FormattedNumber'
-import Text from 'components/Text'
+import { FormattedNumber } from 'components/common/FormattedNumber'
+import Text from 'components/common/Text'
interface Props {
items: { title: string; amount: number }[]
diff --git a/src/components/Modals/HLS/Deposit/Summary/AssetSummary.tsx b/src/components/Modals/HLS/Deposit/Summary/AssetSummary.tsx
index db4e08e8..cfee11fe 100644
--- a/src/components/Modals/HLS/Deposit/Summary/AssetSummary.tsx
+++ b/src/components/Modals/HLS/Deposit/Summary/AssetSummary.tsx
@@ -1,10 +1,10 @@
import React from 'react'
-import AmountAndValue from 'components/AmountAndValue'
-import AssetImage from 'components/Asset/AssetImage'
-import { FormattedNumber } from 'components/FormattedNumber'
+import AmountAndValue from 'components/common/AmountAndValue'
+import AssetImage from 'components/common/assets/AssetImage'
+import { FormattedNumber } from 'components/common/FormattedNumber'
import Container from 'components/Modals/HLS/Deposit/Summary/Container'
-import Text from 'components/Text'
+import Text from 'components/common/Text'
interface Props {
amount: BigNumber
diff --git a/src/components/Modals/HLS/Deposit/Summary/Container.tsx b/src/components/Modals/HLS/Deposit/Summary/Container.tsx
index 39ae06f2..8f14c571 100644
--- a/src/components/Modals/HLS/Deposit/Summary/Container.tsx
+++ b/src/components/Modals/HLS/Deposit/Summary/Container.tsx
@@ -1,6 +1,6 @@
import React from 'react'
-import Text from 'components/Text'
+import Text from 'components/common/Text'
interface Props {
children: React.ReactNode
diff --git a/src/components/Modals/HLS/Deposit/Summary/YourPosition.tsx b/src/components/Modals/HLS/Deposit/Summary/YourPosition.tsx
index 3e0e57a2..ff4673c3 100644
--- a/src/components/Modals/HLS/Deposit/Summary/YourPosition.tsx
+++ b/src/components/Modals/HLS/Deposit/Summary/YourPosition.tsx
@@ -1,12 +1,12 @@
import React, { useMemo } from 'react'
-import DisplayCurrency from 'components/DisplayCurrency'
-import { FormattedNumber } from 'components/FormattedNumber'
-import { InfoCircle } from 'components/Icons'
+import DisplayCurrency from 'components/common/DisplayCurrency'
+import { FormattedNumber } from 'components/common/FormattedNumber'
+import { InfoCircle } from 'components/common/Icons'
import AprBreakdown from 'components/Modals/HLS/Deposit/Summary/ApyBreakdown'
import Container from 'components/Modals/HLS/Deposit/Summary/Container'
-import Text from 'components/Text'
-import { Tooltip } from 'components/Tooltip'
+import Text from 'components/common/Text'
+import { Tooltip } from 'components/common/Tooltip'
import { BNCoin } from 'types/classes/BNCoin'
interface Props {
diff --git a/src/components/Modals/HLS/Deposit/Summary/index.tsx b/src/components/Modals/HLS/Deposit/Summary/index.tsx
index a23140c4..43099a90 100644
--- a/src/components/Modals/HLS/Deposit/Summary/index.tsx
+++ b/src/components/Modals/HLS/Deposit/Summary/index.tsx
@@ -1,7 +1,7 @@
import React from 'react'
-import Button from 'components/Button'
-import { ArrowRight } from 'components/Icons'
+import Button from 'components/common/Button'
+import { ArrowRight } from 'components/common/Icons'
import AssetSummary from 'components/Modals/HLS/Deposit/Summary/AssetSummary'
import YourPosition from 'components/Modals/HLS/Deposit/Summary/YourPosition'
import useBorrowAsset from 'hooks/useBorrowAsset'
diff --git a/src/components/Modals/HLS/Deposit/index.tsx b/src/components/Modals/HLS/Deposit/index.tsx
index 119e0355..95d90401 100644
--- a/src/components/Modals/HLS/Deposit/index.tsx
+++ b/src/components/Modals/HLS/Deposit/index.tsx
@@ -1,11 +1,11 @@
import React, { useMemo, useState } from 'react'
-import Accordion from 'components/Accordion'
+import Accordion from 'components/common/Accordion'
import useStakingController from 'components/Modals/HLS/Deposit//useStakingController'
import useVaultController from 'components/Modals/HLS/Deposit//useVaultController'
import useAccordionItems from 'components/Modals/HLS/Deposit/useAccordionItems'
import { EMPTY_ACCOUNT_HLS } from 'constants/accounts'
-import useAccounts from 'hooks/useAccounts'
+import useAccounts from 'hooks/accounts/useAccounts'
import useCurrentWalletBalance from 'hooks/useCurrentWalletBalance'
import useIsOpenArray from 'hooks/useIsOpenArray'
import useVault from 'hooks/useVault'
diff --git a/src/components/Modals/HLS/Deposit/useAccordionItems.tsx b/src/components/Modals/HLS/Deposit/useAccordionItems.tsx
index 72c5fddc..e3080630 100644
--- a/src/components/Modals/HLS/Deposit/useAccordionItems.tsx
+++ b/src/components/Modals/HLS/Deposit/useAccordionItems.tsx
@@ -11,6 +11,7 @@ import {
} from 'components/Modals/HLS/Deposit/SubTitles'
import Summary from 'components/Modals/HLS/Deposit/Summary'
import { BN_ZERO } from 'constants/math'
+import useAllAssets from 'hooks/assets/useAllAssets'
import usePrices from 'hooks/usePrices'
import { BNCoin } from 'types/classes/BNCoin'
import { getCoinAmount, getCoinValue } from 'utils/formatters'
@@ -47,6 +48,7 @@ interface Props {
export default function useAccordionItems(props: Props) {
const { data: prices } = usePrices()
+ const assets = useAllAssets()
const depositCapLeft = useMemo(() => {
if (!props.strategy) return BN_ZERO
@@ -62,9 +64,10 @@ export default function useAccordionItems(props: Props) {
const value = getCoinValue(
BNCoin.fromDenomAndBigNumber(props.borrowAsset.denom, props.borrowAmount),
prices,
+ assets,
)
- return getCoinAmount(props.collateralAsset.denom, value, prices)
- }, [prices, props.borrowAmount, props.borrowAsset.denom, props.collateralAsset])
+ return getCoinAmount(props.collateralAsset.denom, value, prices, assets)
+ }, [assets, prices, props.borrowAmount, props.borrowAsset.denom, props.collateralAsset.denom])
const collateralWarningMessages = useMemo(() => {
const messages: string[] = []
@@ -73,11 +76,14 @@ export default function useAccordionItems(props: Props) {
}
if (props.depositAmount.isGreaterThan(depositCapLeft)) {
- messages.push(getDepositCapMessage(props.collateralAsset.denom, depositCapLeft, 'deposit'))
+ messages.push(
+ getDepositCapMessage(props.collateralAsset.denom, depositCapLeft, 'deposit', assets),
+ )
}
return messages
}, [
+ assets,
depositCapLeft,
props.collateralAsset.denom,
props.collateralAsset.symbol,
@@ -90,21 +96,22 @@ export default function useAccordionItems(props: Props) {
if (props.borrowAmount.isGreaterThan(props.maxBorrowAmount)) {
messages.push(
- getHealthFactorMessage(props.borrowAsset.denom, props.maxBorrowAmount, 'borrow'),
+ getHealthFactorMessage(props.borrowAsset.denom, props.maxBorrowAmount, 'borrow', assets),
)
}
if (props.borrowAmount.isGreaterThan(borrowLiquidity)) {
- messages.push(getLiquidityMessage(props.borrowAsset.denom, borrowLiquidity))
+ messages.push(getLiquidityMessage(props.borrowAsset.denom, borrowLiquidity, assets))
}
if (additionalDepositFromSwap.plus(props.depositAmount).isGreaterThan(props.maxBorrowAmount)) {
- messages.push(getDepositCapMessage(props.borrowAsset.denom, depositCapLeft, 'borrow'))
+ messages.push(getDepositCapMessage(props.borrowAsset.denom, depositCapLeft, 'borrow', assets))
}
return messages
}, [
additionalDepositFromSwap,
+ assets,
borrowLiquidity,
depositCapLeft,
props.borrowAmount,
diff --git a/src/components/Modals/HLS/Header.tsx b/src/components/Modals/HLS/Header.tsx
index f38c5b07..d9f747fd 100644
--- a/src/components/Modals/HLS/Header.tsx
+++ b/src/components/Modals/HLS/Header.tsx
@@ -1,8 +1,8 @@
import React from 'react'
-import DoubleLogo from 'components/DoubleLogo'
-import HLSTag from 'components/HLS/HLSTag'
-import Text from 'components/Text'
+import DoubleLogo from 'components/common/DoubleLogo'
+import HLSTag from 'components/hls/HLSTag'
+import Text from 'components/common/Text'
interface Props {
primaryAsset: Asset
diff --git a/src/components/Modals/HLS/Manage/ChangeLeverage.tsx b/src/components/Modals/HLS/Manage/ChangeLeverage.tsx
index 4405a401..b69cd869 100644
--- a/src/components/Modals/HLS/Manage/ChangeLeverage.tsx
+++ b/src/components/Modals/HLS/Manage/ChangeLeverage.tsx
@@ -1,13 +1,14 @@
import React, { useCallback, useMemo, useState } from 'react'
-import Button from 'components/Button'
+import Button from 'components/common/Button'
import LeverageSummary from 'components/Modals/HLS/Deposit/LeverageSummary'
-import TokenInputWithSlider from 'components/TokenInput/TokenInputWithSlider'
+import TokenInputWithSlider from 'components/common/TokenInput/TokenInputWithSlider'
import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
import { LocalStorageKeys } from 'constants/localStorageKeys'
import { BN_ZERO } from 'constants/math'
+import useAllAssets from 'hooks/assets/useAllAssets'
+import useLocalStorage from 'hooks/localStorage/useLocalStorage'
import useHealthComputer from 'hooks/useHealthComputer'
-import useLocalStorage from 'hooks/useLocalStorage'
import usePrices from 'hooks/usePrices'
import { useUpdatedAccount } from 'hooks/useUpdatedAccount'
import useStore from 'store'
@@ -28,6 +29,7 @@ interface Props {
export default function ChangeLeverage(props: Props) {
const { data: prices } = usePrices()
+ const assets = useAllAssets()
const [slippage] = useLocalStorage(LocalStorageKeys.SLIPPAGE, DEFAULT_SETTINGS.slippage)
const {
updatedAccount,
@@ -83,10 +85,11 @@ export default function ChangeLeverage(props: Props) {
const [deposits, lends, debts, vaults] = getAccountPositionValues(
updatedAccount || props.account,
prices,
+ assets,
)
return deposits.plus(lends).plus(debts).plus(vaults)
- }, [prices, props.account, updatedAccount])
+ }, [assets, prices, props.account, updatedAccount])
const handleOnClick = useCallback(() => {
useStore.setState({ hlsManageModal: null })
@@ -98,17 +101,19 @@ export default function ChangeLeverage(props: Props) {
props.borrowAsset.denom,
slippage,
prices,
+ assets,
)
changeHlsStakingLeverage({ accountId: props.account.id, actions })
}, [
currentDebt,
- changeHlsStakingLeverage,
previousDebt,
- prices,
- props.account.id,
- props.borrowAsset.denom,
props.collateralAsset.denom,
+ props.borrowAsset.denom,
+ props.account.id,
slippage,
+ prices,
+ assets,
+ changeHlsStakingLeverage,
])
const addedDepositAmount = useMemo(
@@ -132,20 +137,25 @@ export default function ChangeLeverage(props: Props) {
const borrowLiquidity = props.borrowAsset.liquidity?.amount || BN_ZERO
if (borrowLiquidity.isLessThan(currentDebt.minus(previousDebt))) {
- messages.push(getLiquidityMessage(props.borrowAsset.denom, borrowLiquidity))
+ messages.push(getLiquidityMessage(props.borrowAsset.denom, borrowLiquidity, assets))
}
if (maxBorrowAmount.isLessThan(currentDebt)) {
- messages.push(getHealthFactorMessage(props.borrowAsset.denom, maxBorrowAmount, 'borrow'))
+ messages.push(
+ getHealthFactorMessage(props.borrowAsset.denom, maxBorrowAmount, 'borrow', assets),
+ )
}
if (addedDepositAmount.isGreaterThan(depositCapLeft)) {
- messages.push(getDepositCapMessage(props.collateralAsset.denom, depositCapLeft, 'borrow'))
+ messages.push(
+ getDepositCapMessage(props.collateralAsset.denom, depositCapLeft, 'borrow', assets),
+ )
}
return messages
}, [
addedDepositAmount,
+ assets,
currentDebt,
depositCapLeft,
maxBorrowAmount,
diff --git a/src/components/Modals/HLS/Manage/Deposit.tsx b/src/components/Modals/HLS/Manage/Deposit.tsx
index 5dd91547..c41b58af 100644
--- a/src/components/Modals/HLS/Manage/Deposit.tsx
+++ b/src/components/Modals/HLS/Manage/Deposit.tsx
@@ -1,14 +1,15 @@
import BigNumber from 'bignumber.js'
import React, { useCallback, useMemo } from 'react'
-import Button from 'components/Button'
-import Divider from 'components/Divider'
-import SummaryItems from 'components/SummaryItems'
-import Switch from 'components/Switch'
-import Text from 'components/Text'
-import TokenInputWithSlider from 'components/TokenInput/TokenInputWithSlider'
+import Button from 'components/common/Button'
+import Divider from 'components/common/Divider'
+import SummaryItems from 'components/common/SummaryItems'
+import Switch from 'components/common/Switch'
+import Text from 'components/common/Text'
+import TokenInputWithSlider from 'components/common/TokenInput/TokenInputWithSlider'
import { BN_ZERO } from 'constants/math'
-import useDepositActions from 'hooks/HLS/useDepositActions'
+import useAllAssets from 'hooks/assets/useAllAssets'
+import useDepositActions from 'hooks/hls/useDepositActions'
import useBorrowAsset from 'hooks/useBorrowAsset'
import useCurrentWalletBalance from 'hooks/useCurrentWalletBalance'
import useHealthComputer from 'hooks/useHealthComputer'
@@ -40,6 +41,7 @@ export default function Deposit(props: Props) {
useUpdatedAccount(props.account)
const { computeMaxBorrowAmount } = useHealthComputer(updatedAccount)
+ const assets = useAllAssets()
const { data: prices } = usePrices()
const [keepLeverage, toggleKeepLeverage] = useToggle(true)
const collateralAssetAmountInWallet = BN(
@@ -49,8 +51,8 @@ export default function Deposit(props: Props) {
const borrowRate = useBorrowAsset(props.borrowAsset.denom)?.borrowRate || 0
const currentLeverage = useMemo(
- () => calculateAccountLeverage(props.account, prices).toNumber(),
- [prices, props.account],
+ () => calculateAccountLeverage(props.account, prices, assets).toNumber(),
+ [prices, props.account, assets],
)
const depositCoin = useMemo(
@@ -83,7 +85,7 @@ export default function Deposit(props: Props) {
)
if (capLeft.isLessThan(depositCoin.amount.plus(addedDepositFromSwap))) {
- messages.push(getDepositCapMessage(props.collateralAsset.denom, capLeft, 'deposit'))
+ messages.push(getDepositCapMessage(props.collateralAsset.denom, capLeft, 'deposit', assets))
}
if (collateralAssetAmountInWallet.isZero()) {
@@ -99,6 +101,7 @@ export default function Deposit(props: Props) {
props.account.strategy.depositCap.used,
props.collateralAsset.denom,
props.collateralAsset.symbol,
+ assets,
])
const maxBorrowAmount = useMemo(
@@ -109,17 +112,20 @@ export default function Deposit(props: Props) {
const borrowWarningMessages = useMemo(() => {
let messages: string[] = []
if (borrowCoin.amount.isGreaterThan(maxBorrowAmount)) {
- messages.push(getHealthFactorMessage(props.borrowAsset.denom, maxBorrowAmount, 'borrow'))
+ messages.push(
+ getHealthFactorMessage(props.borrowAsset.denom, maxBorrowAmount, 'borrow', assets),
+ )
}
const borrowLiquidity = props.borrowAsset.liquidity?.amount || BN_ZERO
if (borrowCoin.amount.isGreaterThan(borrowLiquidity)) {
- messages.push(getLiquidityMessage(props.borrowAsset.denom, borrowLiquidity))
+ messages.push(getLiquidityMessage(props.borrowAsset.denom, borrowLiquidity, assets))
}
return messages
}, [
+ assets,
borrowCoin.amount,
maxBorrowAmount,
props.borrowAsset.denom,
@@ -151,9 +157,10 @@ export default function Deposit(props: Props) {
const depositValue = getCoinValue(
BNCoin.fromDenomAndBigNumber(props.collateralAsset.denom, amount),
prices,
+ assets,
)
const borrowValue = BN(currentLeverage - 1).times(depositValue)
- additionalDebt = getCoinAmount(props.borrowAsset.denom, borrowValue, prices)
+ additionalDebt = getCoinAmount(props.borrowAsset.denom, borrowValue, prices, assets)
}
simulateHlsStakingDeposit(
@@ -168,6 +175,7 @@ export default function Deposit(props: Props) {
props.borrowAsset.denom,
props.collateralAsset.denom,
simulateHlsStakingDeposit,
+ assets,
],
)
diff --git a/src/components/Modals/HLS/Manage/Repay.tsx b/src/components/Modals/HLS/Manage/Repay.tsx
index 62da7f47..3dbf2ebf 100644
--- a/src/components/Modals/HLS/Manage/Repay.tsx
+++ b/src/components/Modals/HLS/Manage/Repay.tsx
@@ -1,9 +1,9 @@
import BigNumber from 'bignumber.js'
import { useCallback, useMemo } from 'react'
-import Button from 'components/Button'
-import SummaryItems from 'components/SummaryItems'
-import TokenInputWithSlider from 'components/TokenInput/TokenInputWithSlider'
+import Button from 'components/common/Button'
+import SummaryItems from 'components/common/SummaryItems'
+import TokenInputWithSlider from 'components/common/TokenInput/TokenInputWithSlider'
import { BN_ZERO } from 'constants/math'
import useCurrentWalletBalance from 'hooks/useCurrentWalletBalance'
import { useUpdatedAccount } from 'hooks/useUpdatedAccount'
@@ -28,7 +28,7 @@ export default function Repay(props: Props) {
const repay = useStore((s) => s.repay)
const currentDebt: BigNumber = useMemo(
- () => props.account.debts.find(byDenom(props.borrowAsset.denom)).amount || BN_ZERO,
+ () => props.account.debts.find(byDenom(props.borrowAsset.denom))?.amount || BN_ZERO,
[props.account.debts, props.borrowAsset.denom],
)
diff --git a/src/components/Modals/HLS/Manage/Withdraw.tsx b/src/components/Modals/HLS/Manage/Withdraw.tsx
index 9492e757..42121ae3 100644
--- a/src/components/Modals/HLS/Manage/Withdraw.tsx
+++ b/src/components/Modals/HLS/Manage/Withdraw.tsx
@@ -1,8 +1,9 @@
-import React, { useCallback, useMemo } from 'react'
+import { useCallback, useMemo } from 'react'
-import Button from 'components/Button'
-import TokenInputWithSlider from 'components/TokenInput/TokenInputWithSlider'
+import Button from 'components/common/Button'
+import TokenInputWithSlider from 'components/common/TokenInput/TokenInputWithSlider'
import { BN_ZERO } from 'constants/math'
+import useAllAssets from 'hooks/assets/useAllAssets'
import useHealthComputer from 'hooks/useHealthComputer'
import { useUpdatedAccount } from 'hooks/useUpdatedAccount'
import useStore from 'store'
@@ -20,6 +21,7 @@ interface Props {
export default function Withdraw(props: Props) {
const { removedDeposits, removeDeposits, updatedAccount } = useUpdatedAccount(props.account)
const { computeMaxWithdrawAmount } = useHealthComputer(updatedAccount)
+ const assets = useAllAssets()
const withdraw = useStore((s) => s.withdraw)
const handleChange = useCallback(
(amount: BigNumber) =>
@@ -40,6 +42,7 @@ export default function Withdraw(props: Props) {
const onClick = useCallback(() => {
useStore.setState({ hlsManageModal: null })
+ if (!removedDeposit) return
withdraw({
accountId: props.account.id,
coins: [{ coin: removedDeposit }],
@@ -52,10 +55,12 @@ export default function Withdraw(props: Props) {
const warningMessages = useMemo(() => {
if (maxWithdrawAmount.isLessThan(withdrawAmount) || maxWithdrawAmount.isZero()) {
- return [getHealthFactorMessage(props.collateralAsset.denom, maxWithdrawAmount, 'withdraw')]
+ return [
+ getHealthFactorMessage(props.collateralAsset.denom, maxWithdrawAmount, 'withdraw', assets),
+ ]
}
return []
- }, [maxWithdrawAmount, props.collateralAsset.denom, withdrawAmount])
+ }, [assets, maxWithdrawAmount, props.collateralAsset.denom, withdrawAmount])
return (
<>
diff --git a/src/components/Modals/HLS/Manage/index.tsx b/src/components/Modals/HLS/Manage/index.tsx
index 139fb738..b54c78df 100644
--- a/src/components/Modals/HLS/Manage/index.tsx
+++ b/src/components/Modals/HLS/Manage/index.tsx
@@ -6,15 +6,15 @@ import Deposit from 'components/Modals/HLS/Manage/Deposit'
import Repay from 'components/Modals/HLS/Manage/Repay'
import Withdraw from 'components/Modals/HLS/Manage/Withdraw'
import ModalContentWithSummary from 'components/Modals/ModalContentWithSummary'
-import useAccount from 'hooks/useAccount'
+import useAccount from 'hooks/accounts/useAccount'
+import useAsset from 'hooks/assets/useAsset'
import useBorrowAsset from 'hooks/useBorrowAsset'
import useStore from 'store'
-import { getAssetByDenom } from 'utils/assets'
export default function HlsManageModalController() {
const modal = useStore((s) => s.hlsManageModal)
const { data: account } = useAccount(modal?.accountId)
- const collateralAsset = getAssetByDenom(modal?.staking.strategy.denoms.deposit || '')
+ const collateralAsset = useAsset(modal?.staking.strategy.denoms.deposit || '')
const borrowAsset = useBorrowAsset(modal?.staking.strategy.denoms.borrow || '')
if (!modal || !collateralAsset || !borrowAsset || !account) return null
diff --git a/src/components/Modals/HLS/index.tsx b/src/components/Modals/HLS/index.tsx
index 6ad39d10..89b25210 100644
--- a/src/components/Modals/HLS/index.tsx
+++ b/src/components/Modals/HLS/index.tsx
@@ -1,16 +1,16 @@
import React from 'react'
-import Modal from 'components/Modal'
+import Modal from 'components/Modals/Modal'
import Content from 'components/Modals/HLS/Deposit'
import Header from 'components/Modals/HLS/Header'
+import useAsset from 'hooks/assets/useAsset'
import useBorrowAsset from 'hooks/useBorrowAsset'
import useStore from 'store'
-import { getAssetByDenom } from 'utils/assets'
export default function HlsModalController() {
const modal = useStore((s) => s.hlsModal)
- const primaryAsset = getAssetByDenom(
+ const primaryAsset = useAsset(
modal?.vault?.denoms.primary || modal?.strategy?.denoms.deposit || '',
)
diff --git a/src/components/Modals/LendAndReclaim/DetailsHeader.tsx b/src/components/Modals/LendAndReclaim/DetailsHeader.tsx
index f2439db7..c713a65c 100644
--- a/src/components/Modals/LendAndReclaim/DetailsHeader.tsx
+++ b/src/components/Modals/LendAndReclaim/DetailsHeader.tsx
@@ -1,6 +1,6 @@
-import DisplayCurrency from 'components/DisplayCurrency'
-import { FormattedNumber } from 'components/FormattedNumber'
-import TitleAndSubCell from 'components/TitleAndSubCell'
+import DisplayCurrency from 'components/common/DisplayCurrency'
+import { FormattedNumber } from 'components/common/FormattedNumber'
+import TitleAndSubCell from 'components/common/TitleAndSubCell'
import useAssetIncentivesApy from 'hooks/useAssetIncentiveApy'
import useCurrentWalletBalance from 'hooks/useCurrentWalletBalance'
import { BNCoin } from 'types/classes/BNCoin'
@@ -15,7 +15,7 @@ function DetailsHeader({ data }: Props) {
const balanceInWallet = useCurrentWalletBalance(asset.denom)
return (
-
+
{assetApy && (
<>
}
sub={'Deposited'}
diff --git a/src/components/Modals/LendAndReclaim/index.tsx b/src/components/Modals/LendAndReclaim/index.tsx
index 1e1aa532..28e9c00c 100644
--- a/src/components/Modals/LendAndReclaim/index.tsx
+++ b/src/components/Modals/LendAndReclaim/index.tsx
@@ -2,7 +2,7 @@ import { useCallback } from 'react'
import AssetAmountSelectActionModal from 'components/Modals/AssetAmountSelectActionModal'
import DetailsHeader from 'components/Modals/LendAndReclaim/DetailsHeader'
-import useCurrentAccount from 'hooks/useCurrentAccount'
+import useCurrentAccount from 'hooks/accounts/useCurrentAccount'
import useLendAndReclaimModal from 'hooks/useLendAndReclaimModal'
import { useUpdatedAccount } from 'hooks/useUpdatedAccount'
import useStore from 'store'
diff --git a/src/components/Modal.tsx b/src/components/Modals/Modal.tsx
similarity index 95%
rename from src/components/Modal.tsx
rename to src/components/Modals/Modal.tsx
index 14175290..5b9a9480 100644
--- a/src/components/Modal.tsx
+++ b/src/components/Modals/Modal.tsx
@@ -1,8 +1,8 @@
import classNames from 'classnames'
import { ReactNode, useEffect, useRef } from 'react'
-import EscButton from 'components/Button/EscButton'
-import Card from 'components/Card'
+import EscButton from 'components/common/Button/EscButton'
+import Card from 'components/common/Card'
export interface ModalProps {
header: string | ReactNode
diff --git a/src/components/Modals/ModalContentWithSummary.tsx b/src/components/Modals/ModalContentWithSummary.tsx
index e1d2db4f..cd0ef2a9 100644
--- a/src/components/Modals/ModalContentWithSummary.tsx
+++ b/src/components/Modals/ModalContentWithSummary.tsx
@@ -1,10 +1,10 @@
import classNames from 'classnames'
import React from 'react'
-import AccountSummary from 'components/Account/AccountSummary'
-import Card from 'components/Card'
-import { CircularProgress } from 'components/CircularProgress'
-import Modal, { ModalProps } from 'components/Modal'
+import AccountSummary from 'components/account/AccountSummary'
+import Card from 'components/common/Card'
+import { CircularProgress } from 'components/common/CircularProgress'
+import Modal, { ModalProps } from 'components/Modals/Modal'
import useStore from 'store'
interface Props extends ModalProps {
diff --git a/src/components/Modals/Settings/SettingsOptions.tsx b/src/components/Modals/Settings/SettingsOptions.tsx
index 1a22bbfb..70e3f0da 100644
--- a/src/components/Modals/Settings/SettingsOptions.tsx
+++ b/src/components/Modals/Settings/SettingsOptions.tsx
@@ -1,7 +1,7 @@
import classNames from 'classnames'
import { ReactNode } from 'react'
-import Text from 'components/Text'
+import Text from 'components/common/Text'
interface Props {
label: string
diff --git a/src/components/Modals/Settings/SettingsSwitch.tsx b/src/components/Modals/Settings/SettingsSwitch.tsx
index 65c09779..a52f7607 100644
--- a/src/components/Modals/Settings/SettingsSwitch.tsx
+++ b/src/components/Modals/Settings/SettingsSwitch.tsx
@@ -1,7 +1,7 @@
import classNames from 'classnames'
-import Switch from 'components/Switch'
-import Text from 'components/Text'
+import Switch from 'components/common/Switch'
+import Text from 'components/common/Text'
interface Props {
onChange: (value: boolean) => void
diff --git a/src/components/Modals/Settings/index.tsx b/src/components/Modals/Settings/index.tsx
index 11bc4934..0b899d5f 100644
--- a/src/components/Modals/Settings/index.tsx
+++ b/src/components/Modals/Settings/index.tsx
@@ -1,24 +1,26 @@
import classNames from 'classnames'
import { useCallback, useMemo, useState } from 'react'
-import AssetImage from 'components/Asset/AssetImage'
-import Button from 'components/Button'
-import { ArrowCircle, Enter } from 'components/Icons'
-import Modal from 'components/Modal'
+import Modal from 'components/Modals/Modal'
import SettingsOptions from 'components/Modals/Settings/SettingsOptions'
import SettingsSwitch from 'components/Modals/Settings/SettingsSwitch'
-import NumberInput from 'components/NumberInput'
-import Select from 'components/Select'
-import Text from 'components/Text'
-import { TextLink } from 'components/TextLink'
+import Button from 'components/common/Button'
+import { ArrowCircle, Enter } from 'components/common/Icons'
+import NumberInput from 'components/common/NumberInput'
+import Select from 'components/common/Select'
+import Text from 'components/common/Text'
+import { TextLink } from 'components/common/TextLink'
+import AssetImage from 'components/common/assets/AssetImage'
import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
import { LocalStorageKeys } from 'constants/localStorageKeys'
import { BN_ZERO } from 'constants/math'
+import useDisplayCurrencyAssets from 'hooks/assets/useDisplayCurrencyAssets'
+import useDisplayCurrency from 'hooks/localStorage/useDisplayCurrency'
+import useEnableAutoLendGlobal from 'hooks/localStorage/useEnableAutoLendGlobal'
+import useLocalStorage from 'hooks/localStorage/useLocalStorage'
import useAlertDialog from 'hooks/useAlertDialog'
import useAutoLend from 'hooks/useAutoLend'
-import useLocalStorage from 'hooks/useLocalStorage'
import useStore from 'store'
-import { getDisplayCurrencies } from 'utils/assets'
import { BN } from 'utils/helpers'
const slippages = [0.02, 0.03]
@@ -26,15 +28,13 @@ const slippages = [0.02, 0.03]
export default function SettingsModal() {
const modal = useStore((s) => s.settingsModal)
const { open: showResetDialog } = useAlertDialog()
- const displayCurrencies = getDisplayCurrencies()
+ const displayCurrencies = useDisplayCurrencyAssets()
const { setAutoLendOnAllAccounts } = useAutoLend()
const [customSlippage, setCustomSlippage] = useState
(0)
const [inputRef, setInputRef] = useState>()
const [isCustom, setIsCustom] = useState(false)
- const [displayCurrency, setDisplayCurrency] = useLocalStorage(
- LocalStorageKeys.DISPLAY_CURRENCY,
- DEFAULT_SETTINGS.displayCurrency,
- )
+
+ const [displayCurrency, setDisplayCurrency] = useDisplayCurrency()
const [reduceMotion, setReduceMotion] = useLocalStorage(
LocalStorageKeys.REDUCE_MOTION,
DEFAULT_SETTINGS.reduceMotion,
@@ -43,14 +43,15 @@ export default function SettingsModal() {
LocalStorageKeys.TUTORIAL,
DEFAULT_SETTINGS.tutorial,
)
- const [lendAssets, setLendAssets] = useLocalStorage(
- LocalStorageKeys.LEND_ASSETS,
- DEFAULT_SETTINGS.lendAssets,
- )
+ const [enableAutoLendGlobal, setLendAssets] = useEnableAutoLendGlobal()
const [slippage, setSlippage] = useLocalStorage(
LocalStorageKeys.SLIPPAGE,
DEFAULT_SETTINGS.slippage,
)
+ const [updateOracle, setUpdateOracle] = useLocalStorage(
+ LocalStorageKeys.UPDATE_ORACLE,
+ DEFAULT_SETTINGS.updateOracle,
+ )
const displayCurrenciesOptions = useMemo(
() =>
@@ -148,9 +149,16 @@ export default function SettingsModal() {
handleDisplayCurrency(DEFAULT_SETTINGS.displayCurrency)
handleSlippage(DEFAULT_SETTINGS.slippage)
handleReduceMotion(DEFAULT_SETTINGS.reduceMotion)
- handleLendAssets(DEFAULT_SETTINGS.lendAssets)
+ handleLendAssets(DEFAULT_SETTINGS.enableAutoLendGlobal)
}, [handleDisplayCurrency, handleReduceMotion, handleLendAssets, handleSlippage])
+ const handleUpdateOracle = useCallback(
+ (value: boolean) => {
+ setUpdateOracle(value)
+ },
+ [setUpdateOracle],
+ )
+
const showResetModal = useCallback(() => {
showResetDialog({
icon: (
@@ -193,12 +201,21 @@ export default function SettingsModal() {
>
+
+
getValueFromBNCoins(mergeBNCoinArrays(props.deposits, props.borrowings), prices),
- [props.borrowings, props.deposits, prices],
+ () => getValueFromBNCoins(mergeBNCoinArrays(props.deposits, props.borrowings), prices, assets),
+ [props.deposits, props.borrowings, prices, assets],
)
useEffect(() => {
@@ -176,7 +178,7 @@ export default function VaultBorrowings(props: VaultBorrowingsProps) {
return (
{props.borrowings.map((coin) => {
- const asset = getAssetByDenom(coin.denom)
+ const asset = assets.find(byDenom(coin.denom))
const maxAmount = maxBorrowAmounts.find(byDenom(coin.denom))?.amount
if (!asset || !maxAmount)
return
@@ -224,7 +226,7 @@ export default function VaultBorrowings(props: VaultBorrowingsProps) {
/>
{props.borrowings.map((coin) => {
- const asset = getAssetByDenom(coin.denom)
+ const asset = assets.find(byDenom(coin.denom))
const borrowRate = marketAssets?.find((market) => market.denom === coin.denom)?.apy.borrow
if (!asset || !borrowRate)
diff --git a/src/components/Modals/Vault/VaultBorrowingsSubTitle.tsx b/src/components/Modals/Vault/VaultBorrowingsSubTitle.tsx
index 409cb1c6..76b1588a 100644
--- a/src/components/Modals/Vault/VaultBorrowingsSubTitle.tsx
+++ b/src/components/Modals/Vault/VaultBorrowingsSubTitle.tsx
@@ -1,13 +1,14 @@
import classNames from 'classnames'
import { useMemo } from 'react'
-import DisplayCurrency from 'components/DisplayCurrency'
-import Text from 'components/Text'
+import DisplayCurrency from 'components/common/DisplayCurrency'
+import Text from 'components/common/Text'
import { BN_ZERO } from 'constants/math'
+import { ORACLE_DENOM } from 'constants/oracle'
+import useAllAssets from 'hooks/assets/useAllAssets'
import usePrices from 'hooks/usePrices'
import { BNCoin } from 'types/classes/BNCoin'
import { formatAmountWithSymbol, getCoinValue } from 'utils/formatters'
-import { ORACLE_DENOM } from 'constants/oracle'
interface Props {
borrowings: BNCoin[]
@@ -16,16 +17,16 @@ interface Props {
export default function VaultBorrowingsSubTitle(props: Props) {
const { data: prices } = usePrices()
-
+ const assets = useAllAssets()
const borrowingValue = useMemo(() => {
let borrowingValue = BN_ZERO
props.borrowings.map((coin) => {
const price = prices.find((p) => p.denom === coin.denom)?.amount
if (!price || coin.amount.isZero()) return
- borrowingValue = getCoinValue(coin, prices)
+ borrowingValue = getCoinValue(coin, prices, assets)
})
return borrowingValue
- }, [props.borrowings, prices])
+ }, [props.borrowings, prices, assets])
const borrowingTexts = useMemo(
() =>
@@ -38,10 +39,10 @@ export default function VaultBorrowingsSubTitle(props: Props) {
index !== 0 && 'ml-1 before:pr-1 before:content-["+"]',
)}
>
- {formatAmountWithSymbol(borrowing.toCoin())}
+ {formatAmountWithSymbol(borrowing.toCoin(), assets)}
)),
- [props.borrowings],
+ [assets, props.borrowings],
)
return (
diff --git a/src/components/Modals/Vault/VaultDeposits.tsx b/src/components/Modals/Vault/VaultDeposits.tsx
index 571f19c7..2bc4eb91 100644
--- a/src/components/Modals/Vault/VaultDeposits.tsx
+++ b/src/components/Modals/Vault/VaultDeposits.tsx
@@ -1,18 +1,19 @@
import BigNumber from 'bignumber.js'
import { useMemo, useState } from 'react'
-import Button from 'components/Button'
-import DepositCapMessage from 'components/DepositCapMessage'
-import DisplayCurrency from 'components/DisplayCurrency'
-import Divider from 'components/Divider'
-import { Gauge } from 'components/Gauge'
-import { ArrowRight, ExclamationMarkCircled } from 'components/Icons'
-import Slider from 'components/Slider'
-import Switch from 'components/Switch'
-import Text from 'components/Text'
-import TokenInput from 'components/TokenInput'
+import Button from 'components/common/Button'
+import DepositCapMessage from 'components/common/DepositCapMessage'
+import DisplayCurrency from 'components/common/DisplayCurrency'
+import Divider from 'components/common/Divider'
+import { Gauge } from 'components/common/Gauge'
+import { ArrowRight, ExclamationMarkCircled } from 'components/common/Icons'
+import Slider from 'components/common/Slider'
+import Switch from 'components/common/Switch'
+import Text from 'components/common/Text'
+import TokenInput from 'components/common/TokenInput'
import { BN_ZERO } from 'constants/math'
import { ORACLE_DENOM } from 'constants/oracle'
+import useAllAssets from 'hooks/assets/useAllAssets'
import usePrices from 'hooks/usePrices'
import { BNCoin } from 'types/classes/BNCoin'
import { accumulateAmounts } from 'utils/accounts'
@@ -41,6 +42,7 @@ export default function VaultDeposit(props: Props) {
[account.deposits, account.lends, primaryAsset.denom, secondaryAsset.denom],
)
const { data: prices } = usePrices()
+ const assets = useAllAssets()
const primaryPrice = prices.find(byDenom(primaryAsset.denom))?.amount ?? BN_ZERO
const secondaryPrice = prices.find(byDenom(secondaryAsset.denom))?.amount ?? BN_ZERO
@@ -55,13 +57,13 @@ export default function VaultDeposit(props: Props) {
}, [deposits, secondaryAsset.denom])
const primaryValue = useMemo(
- () => getValueFromBNCoins([primaryCoin], prices),
- [primaryCoin, prices],
+ () => getValueFromBNCoins([primaryCoin], prices, assets),
+ [primaryCoin, prices, assets],
)
const totalValue = useMemo(
- () => getValueFromBNCoins([primaryCoin, secondaryCoin], prices),
- [primaryCoin, secondaryCoin, prices],
+ () => getValueFromBNCoins([primaryCoin, secondaryCoin], prices, assets),
+ [primaryCoin, secondaryCoin, prices, assets],
)
const primaryValuePercentage = useMemo(() => {
diff --git a/src/components/Modals/Vault/VaultDepositsSubTitle.tsx b/src/components/Modals/Vault/VaultDepositsSubTitle.tsx
index 46477b08..78f61c55 100644
--- a/src/components/Modals/Vault/VaultDepositsSubTitle.tsx
+++ b/src/components/Modals/Vault/VaultDepositsSubTitle.tsx
@@ -2,13 +2,14 @@ import BigNumber from 'bignumber.js'
import classNames from 'classnames'
import { useMemo } from 'react'
-import DisplayCurrency from 'components/DisplayCurrency'
-import Text from 'components/Text'
+import DisplayCurrency from 'components/common/DisplayCurrency'
+import Text from 'components/common/Text'
+import { ORACLE_DENOM } from 'constants/oracle'
+import useAllAssets from 'hooks/assets/useAllAssets'
import usePrices from 'hooks/usePrices'
import { BNCoin } from 'types/classes/BNCoin'
import { formatAmountWithSymbol } from 'utils/formatters'
import { getValueFromBNCoins } from 'utils/helpers'
-import { ORACLE_DENOM } from 'constants/oracle'
interface Props {
primaryAmount: BigNumber
@@ -20,28 +21,35 @@ interface Props {
export default function VaultDepositSubTitle(props: Props) {
const { data: prices } = usePrices()
+ const assets = useAllAssets()
const primaryText = useMemo(
() => (
- {formatAmountWithSymbol({
- denom: props.primaryAsset.denom,
- amount: props.primaryAmount.toString(),
- })}
+ {formatAmountWithSymbol(
+ {
+ denom: props.primaryAsset.denom,
+ amount: props.primaryAmount.toString(),
+ },
+ assets,
+ )}
),
- [props.primaryAmount, props.primaryAsset.denom],
+ [assets, props.primaryAmount, props.primaryAsset.denom],
)
const secondaryText = useMemo(
() => (
- {formatAmountWithSymbol({
- denom: props.secondaryAsset.denom,
- amount: props.secondaryAmount.toString(),
- })}
+ {formatAmountWithSymbol(
+ {
+ denom: props.secondaryAsset.denom,
+ amount: props.secondaryAmount.toString(),
+ },
+ assets,
+ )}
),
- [props.secondaryAmount, props.secondaryAsset.denom],
+ [assets, props.secondaryAmount, props.secondaryAsset.denom],
)
const positionValue = getValueFromBNCoins(
@@ -50,6 +58,7 @@ export default function VaultDepositSubTitle(props: Props) {
BNCoin.fromDenomAndBigNumber(props.secondaryAsset.denom, props.secondaryAmount),
],
prices,
+ assets,
)
const showPrimaryText = !props.primaryAmount.isZero()
diff --git a/src/components/Modals/Vault/VaultModalContent.tsx b/src/components/Modals/Vault/VaultModalContent.tsx
index b307d24a..4a11fb10 100644
--- a/src/components/Modals/Vault/VaultModalContent.tsx
+++ b/src/components/Modals/Vault/VaultModalContent.tsx
@@ -1,19 +1,18 @@
import { useCallback, useMemo, useState } from 'react'
-import Accordion from 'components/Accordion'
-import AccountSummary from 'components/Account/AccountSummary'
+import Accordion from 'components/common/Accordion'
+import AccountSummary from 'components/account/AccountSummary'
import VaultBorrowings from 'components/Modals/Vault/VaultBorrowings'
import VaultBorrowingsSubTitle from 'components/Modals/Vault/VaultBorrowingsSubTitle'
import VaultDeposit from 'components/Modals/Vault/VaultDeposits'
import VaultDepositSubTitle from 'components/Modals/Vault/VaultDepositsSubTitle'
-import Text from 'components/Text'
-import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
-import { LocalStorageKeys } from 'constants/localStorageKeys'
+import Text from 'components/common/Text'
import { BN_ZERO } from 'constants/math'
+import useAllAssets from 'hooks/assets/useAllAssets'
import useDepositVault from 'hooks/broadcast/useDepositVault'
+import useDisplayCurrency from 'hooks/localStorage/useDisplayCurrency'
import useDisplayAsset from 'hooks/useDisplayAsset'
import useIsOpenArray from 'hooks/useIsOpenArray'
-import useLocalStorage from 'hooks/useLocalStorage'
import usePrices from 'hooks/usePrices'
import { useUpdatedAccount } from 'hooks/useUpdatedAccount'
import { BNCoin } from 'types/classes/BNCoin'
@@ -33,12 +32,10 @@ export default function VaultModalContent(props: Props) {
const { addedDebts, removedDeposits, removedLends, simulateVaultDeposit } = useUpdatedAccount(
props.account,
)
+ const assets = useAllAssets()
const { data: prices } = usePrices()
- const [displayCurrency] = useLocalStorage(
- LocalStorageKeys.DISPLAY_CURRENCY,
- DEFAULT_SETTINGS.displayCurrency,
- )
+ const [displayCurrency] = useDisplayCurrency()
const [isOpen, toggleOpen] = useIsOpenArray(2, false)
const [isCustomRatio, setIsCustomRatio] = useState(false)
const [depositCoins, setDepositCoins] = useState([])
@@ -60,6 +57,7 @@ export default function VaultModalContent(props: Props) {
getCoinValue(
BNCoin.fromDenomAndBigNumber(props.vault.cap.denom, capLeft),
prices,
+ assets,
).toString(),
displayAsset,
)
@@ -67,7 +65,7 @@ export default function VaultModalContent(props: Props) {
return [BNCoin.fromDenomAndBigNumber(displayAsset.denom, amount)]
}
return []
- }, [displayAsset, prices, props.vault.cap, totalValue])
+ }, [assets, displayAsset, prices, props.vault.cap, totalValue])
const onChangeIsCustomRatio = useCallback(
(isCustomRatio: boolean) => setIsCustomRatio(isCustomRatio),
diff --git a/src/components/Modals/Vault/VaultModalContentHeader.tsx b/src/components/Modals/Vault/VaultModalContentHeader.tsx
index b0b3352f..8a422527 100644
--- a/src/components/Modals/Vault/VaultModalContentHeader.tsx
+++ b/src/components/Modals/Vault/VaultModalContentHeader.tsx
@@ -1,8 +1,8 @@
import { useMemo } from 'react'
-import DisplayCurrency from 'components/DisplayCurrency'
-import { FormattedNumber } from 'components/FormattedNumber'
-import TitleAndSubCell from 'components/TitleAndSubCell'
+import DisplayCurrency from 'components/common/DisplayCurrency'
+import { FormattedNumber } from 'components/common/FormattedNumber'
+import TitleAndSubCell from 'components/common/TitleAndSubCell'
import { BN_ZERO } from 'constants/math'
import { PRICE_ORACLE_DECIMALS } from 'constants/query'
import { BNCoin } from 'types/classes/BNCoin'
diff --git a/src/components/Modals/Vault/index.tsx b/src/components/Modals/Vault/index.tsx
index 337b7799..f10c9753 100644
--- a/src/components/Modals/Vault/index.tsx
+++ b/src/components/Modals/Vault/index.tsx
@@ -1,22 +1,23 @@
import moment from 'moment'
import { useCallback, useMemo } from 'react'
-import DoubleLogo from 'components/DoubleLogo'
-import { InfoCircle } from 'components/Icons'
-import Modal from 'components/Modal'
+import DoubleLogo from 'components/common/DoubleLogo'
+import { InfoCircle } from 'components/common/Icons'
+import Text from 'components/common/Text'
+import { Tooltip } from 'components/common/Tooltip'
+import Modal from 'components/Modals/Modal'
import VaultModalContent from 'components/Modals/Vault/VaultModalContent'
import VaultModalContentHeader from 'components/Modals/Vault/VaultModalContentHeader'
-import Text from 'components/Text'
-import { Tooltip } from 'components/Tooltip'
-import { ASSETS } from 'constants/assets'
-import useCurrentAccount from 'hooks/useCurrentAccount'
+import useCurrentAccount from 'hooks/accounts/useCurrentAccount'
+import useAsset from 'hooks/assets/useAsset'
import useStore from 'store'
export default function VaultModalController() {
const currentAccount = useCurrentAccount()
const modal = useStore((s) => s.vaultModal)
- const primaryAsset = ASSETS.find((asset) => asset.denom === modal?.vault.denoms.primary)
- const secondaryAsset = ASSETS.find((asset) => asset.denom === modal?.vault.denoms.secondary)
+
+ const primaryAsset = useAsset(modal?.vault.denoms.primary || '')
+ const secondaryAsset = useAsset(modal?.vault.denoms.secondary || '')
if (!modal || !currentAccount || !primaryAsset || !secondaryAsset) return null
diff --git a/src/components/Modals/WalletAssets/WalletAssetsModalContent.tsx b/src/components/Modals/WalletAssets/WalletAssetsModalContent.tsx
index 95309aa0..1b6222b9 100644
--- a/src/components/Modals/WalletAssets/WalletAssetsModalContent.tsx
+++ b/src/components/Modals/WalletAssets/WalletAssetsModalContent.tsx
@@ -1,10 +1,10 @@
import { useCallback, useMemo, useState } from 'react'
-import AssetSelectTable from 'components/Modals/AssetsSelect/AssetSelectTable'
-import SearchBar from 'components/SearchBar'
+import AssetsSelect from 'components/Modals/AssetsSelect'
+import SearchBar from 'components/common/SearchBar'
+import useAllAssets from 'hooks/assets/useAllAssets'
import useStore from 'store'
import { byDenom } from 'utils/array'
-import { getAssetByDenom } from 'utils/assets'
interface Props {
onChangeDenoms: (denoms: string[]) => void
@@ -14,25 +14,26 @@ export default function WalletAssetsModalContent(props: Props) {
const { onChangeDenoms } = props
const [searchString, setSearchString] = useState('')
const balances = useStore((s) => s.balances)
+ const assets = useAllAssets()
- const assets = useMemo(() => {
- const assetsInWallet: Asset[] = []
+ const assetsInWallet = useMemo(() => {
+ const assetsInWalletInWallet: Asset[] = []
balances.forEach((balance) => {
- const asset = getAssetByDenom(balance.denom)
- if (asset && asset.isMarket) assetsInWallet.push(asset)
+ const asset = assets.find(byDenom(balance.denom))
+ if (asset && asset.isMarket) assetsInWalletInWallet.push(asset)
})
- return assetsInWallet
- }, [balances])
+ return assetsInWalletInWallet
+ }, [assets, balances])
const filteredAssets: Asset[] = useMemo(() => {
- return assets.filter(
+ return assetsInWallet.filter(
(asset) =>
asset.name.toLowerCase().includes(searchString.toLowerCase()) ||
asset.denom.toLowerCase().includes(searchString.toLowerCase()) ||
asset.symbol.toLowerCase().includes(searchString.toLowerCase()),
)
- }, [assets, searchString])
+ }, [assetsInWallet, searchString])
const isBorrow = useStore((s) => s.walletAssetsModal?.isBorrow ?? false)
const currentSelectedDenom = useStore((s) => s.walletAssetsModal?.selectedDenoms ?? [])
@@ -58,8 +59,7 @@ export default function WalletAssetsModalContent(props: Props) {
/>
-
s.withdrawFromVaultsModal)
@@ -22,6 +22,7 @@ export default function WithdrawFromVaultsModal() {
const { data: prices } = usePrices()
const withdrawFromVaults = useStore((s) => s.withdrawFromVaults)
const [slippage] = useLocalStorage(LocalStorageKeys.SLIPPAGE, DEFAULT_SETTINGS.slippage)
+ const assets = useAllAssets()
function onClose() {
useStore.setState({ withdrawFromVaultsModal: null })
@@ -56,8 +57,8 @@ export default function WithdrawFromVaultsModal() {
{modal.map((vault) => {
const positionValue = vault.values.unlocking
const coin = BNCoin.fromDenomAndBigNumber(ORACLE_DENOM, positionValue)
- const primaryAsset = getAssetByDenom(vault.denoms.primary)
- const secondaryAsset = getAssetByDenom(vault.denoms.secondary)
+ const primaryAsset = assets.find(byDenom(vault.denoms.primary))
+ const secondaryAsset = assets.find(byDenom(vault.denoms.secondary))
if (!primaryAsset || !secondaryAsset) return null
const primaryAssetPrice = prices.find(byDenom(primaryAsset.denom))?.amount ?? 1
@@ -72,17 +73,19 @@ export default function WithdrawFromVaultsModal() {
primaryDenom={vault.denoms.primary}
secondaryDenom={vault.denoms.secondary}
/>
-
-
{vault.name}
-
+
+
+ {vault.name}
+
+
Unlocked
-
-
+
+
{
- const { item } = props
- const [showMenu, setShowMenu] = useToggle()
-
- if (!item.submenu) return null
-
- return (
-
-
}
- color='quaternary'
- variant='transparent'
- onClick={() => setShowMenu(!showMenu)}
- text={item.label}
- className={classNames(
- '!text-base !p-0 !min-h-0',
- (getIsActive(item.pages) || showMenu) && '!text-white',
- )}
- />
- {showMenu && (
- <>
-
-
- {item.submenu.map((submenuitem, index) => (
-
- {index !== 0 && }
- setShowMenu(false)}
- className='flex items-center w-full gap-4 px-4 whitespace-nowrap'
- >
- {submenuitem.icon && {submenuitem.icon}
}
-
- {submenuitem.label}
- {submenuitem.subtitle && (
-
- {submenuitem.subtitle}
-
- )}
-
-
-
- ))}
-
-
-
setShowMenu(false)}
- role='button'
- />
- >
- )}
-
- )
-}
diff --git a/src/components/Perps/Module/PerpsModule.tsx b/src/components/Perps/Module/PerpsModule.tsx
deleted file mode 100644
index 54491b57..00000000
--- a/src/components/Perps/Module/PerpsModule.tsx
+++ /dev/null
@@ -1,59 +0,0 @@
-import { useState } from 'react'
-
-import Button from 'components/Button'
-import Card from 'components/Card'
-import { DirectionSelect } from 'components/DirectionSelect'
-import { ChevronDown } from 'components/Icons'
-import { LeverageButtons } from 'components/Perps/Module/LeverageButtons'
-import { Or } from 'components/Perps/Module/Or'
-import RangeInput from 'components/RangeInput'
-import { Spacer } from 'components/Spacer'
-import Text from 'components/Text'
-import AssetAmountInput from 'components/Trade/TradeModule/SwapForm/AssetAmountInput'
-import OrderTypeSelector from 'components/Trade/TradeModule/SwapForm/OrderTypeSelector'
-import { AvailableOrderType } from 'components/Trade/TradeModule/SwapForm/OrderTypeSelector/types'
-import { ASSETS } from 'constants/assets'
-import { BN_ZERO } from 'constants/math'
-
-export function PerpsModule() {
- const [selectedOrderType, setSelectedOrderType] = useState
('Market')
- const [selectedOrderDirection, setSelectedOrderDirection] = useState('long')
-
- return (
-
-
- ETH/USD
-
- }>
- All Markets
-
-
- }
- className='mb-4'
- >
-
-
- {}}
- asset={ASSETS[0]}
- maxButtonLabel='Max:'
- disabled={false}
- />
-
- Position Leverage
- {}} />
-
-
- {selectedOrderDirection} ETH
-
- )
-}
diff --git a/src/components/Perps/PerpsChart.tsx b/src/components/Perps/PerpsChart.tsx
deleted file mode 100644
index f6d52fae..00000000
--- a/src/components/Perps/PerpsChart.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import React from 'react'
-
-import TradeChart from 'components/Trade/TradeChart'
-import { ASSETS } from 'constants/assets'
-
-export function PerpsChart() {
- return (
-
-
-
- )
-}
diff --git a/src/components/Perps/PerpsInfo.tsx b/src/components/Perps/PerpsInfo.tsx
deleted file mode 100644
index ec93a67f..00000000
--- a/src/components/Perps/PerpsInfo.tsx
+++ /dev/null
@@ -1,99 +0,0 @@
-import React, { useMemo } from 'react'
-
-import AssetSymbol from 'components/Asset/AssetSymbol'
-import Card from 'components/Card'
-import DisplayCurrency from 'components/DisplayCurrency'
-import Divider from 'components/Divider'
-import { FormattedNumber } from 'components/FormattedNumber'
-import Loading from 'components/Loading'
-import Text from 'components/Text'
-import usePerpsMarket from 'hooks/perps/usePerpsMarket'
-import usePrice from 'hooks/usePrice'
-import { BNCoin } from 'types/classes/BNCoin'
-
-export function PerpsInfo() {
- const { data: market } = usePerpsMarket()
- const assetPrice = usePrice(market?.asset.denom || '')
-
- const items = useMemo(
- () => [
- ...(!assetPrice.isZero()
- ? [ ]
- : [ ]),
- }
- />,
- }
- />,
-
- ) : (
-
- )
- }
- />,
- ],
- [assetPrice, market],
- )
-
- return (
-
-
- {items.map((item, index) => (
-
- {item}
- {index !== items.length - 1 && }
-
- ))}
-
-
- )
-}
-
-interface InfoItemProps {
- item: React.ReactNode
- label: string
-}
-
-function InfoItem(props: InfoItemProps) {
- return (
-
-
- {props.label}
-
- {props.item}
-
- )
-}
-
-interface InterestItemProps {
- market: PerpsMarket | null
- type: 'long' | 'short'
-}
-function InterestItem(props: InterestItemProps) {
- if (!props.market) return
-
- return (
-
- )
-}
diff --git a/src/components/Perps/PerpsPositions.tsx b/src/components/Perps/PerpsPositions.tsx
deleted file mode 100644
index 03cb490e..00000000
--- a/src/components/Perps/PerpsPositions.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import AccountDetailsCard from 'components/Trade/AccountDetailsCard'
-
-export function PerpsPositions() {
- return
-}
diff --git a/src/components/Table/Row.tsx b/src/components/Table/Row.tsx
deleted file mode 100644
index ae0e35ca..00000000
--- a/src/components/Table/Row.tsx
+++ /dev/null
@@ -1,63 +0,0 @@
-import { flexRender, Row as TanstackRow, Table as TanstackTable } from '@tanstack/react-table'
-import classNames from 'classnames'
-
-interface Props {
- row: TanstackRow
- table: TanstackTable
- renderExpanded?: (row: TanstackRow, table: TanstackTable) => JSX.Element
- rowClassName?: string
- rowClickHandler?: () => void
- spacingClassName?: string
- isBalancesTable?: boolean
- className?: string
-}
-
-function getBorderColor(row: AccountBalanceRow) {
- return row.type === 'borrowing' ? 'border-loss' : 'border-profit'
-}
-
-export default function Row(props: Props) {
- const canExpand = !!props.renderExpanded
- return (
- <>
- {
- e.preventDefault()
- const isExpanded = props.row.getIsExpanded()
- props.table.resetExpanded()
- !isExpanded && props.row.toggleExpanded()
- }}
- >
- {props.row.getVisibleCells().map((cell) => {
- const isSymbolOrName = cell.column.id === 'symbol' || cell.column.id === 'name'
- const borderClasses =
- props.isBalancesTable && isSymbolOrName
- ? classNames('border-l', getBorderColor(cell.row.original as AccountBalanceRow))
- : ''
- return (
-
- {flexRender(cell.column.columnDef.cell, cell.getContext())}
-
- )
- })}
-
- {props.row.getIsExpanded() &&
- props.renderExpanded &&
- props.renderExpanded(props.row, props.table)}
- >
- )
-}
diff --git a/src/components/Trade/TradeChart/DataFeed.ts b/src/components/Trade/TradeChart/DataFeed.ts
deleted file mode 100644
index f07acda1..00000000
--- a/src/components/Trade/TradeChart/DataFeed.ts
+++ /dev/null
@@ -1,500 +0,0 @@
-import { defaultSymbolInfo } from 'components/Trade/TradeChart/constants'
-import { ASSETS } from 'constants/assets'
-import { ENV } from 'constants/env'
-import { MILLISECONDS_PER_MINUTE } from 'constants/math'
-import { byDenom } from 'utils/array'
-import { getAssetByDenom, getEnabledMarketAssets } from 'utils/assets'
-import {
- Bar,
- ErrorCallback,
- HistoryCallback,
- IDatafeedChartApi,
- LibrarySymbolInfo,
- OnReadyCallback,
- PeriodParams,
- ResolutionString,
- ResolveCallback,
-} from 'utils/charting_library'
-import { BN } from 'utils/helpers'
-import { devideByPotentiallyZero } from 'utils/math'
-
-interface PythBarQueryData {
- s: string
- t: number[]
- o: number[]
- h: number[]
- l: number[]
- c: number[]
- v: number[]
-}
-
-interface TheGraphBarQueryData {
- close: string
- high: string
- low: string
- open: string
- timestamp: string
- volume: string
-}
-
-export const PAIR_SEPARATOR = '<>'
-
-export class DataFeed implements IDatafeedChartApi {
- candlesEndpoint = ENV.CANDLES_ENDPOINT_PYTH
- candlesEndpointTheGraph = ENV.CANDLES_ENDPOINT_THE_GRAPH
- debug = false
- enabledMarketAssetDenoms: string[] = []
- batchSize = 1000
- baseDecimals: number = 6
- baseDenom: string = 'uosmo'
- intervalsTheGraph: { [key: string]: string } = {
- '15': '15m',
- '30': '30m',
- '60': '1h',
- '240': '4h',
- '1D': '1d',
- }
- millisecondsPerInterval: { [key: string]: number } = {
- '1': MILLISECONDS_PER_MINUTE * 1,
- '5': MILLISECONDS_PER_MINUTE * 5,
- '15': MILLISECONDS_PER_MINUTE * 15,
- '30': MILLISECONDS_PER_MINUTE * 30,
- '60': MILLISECONDS_PER_MINUTE * 60,
- '240': MILLISECONDS_PER_MINUTE * 240,
- '1D': MILLISECONDS_PER_MINUTE * 1440,
- }
- pairs: { baseAsset: string; quoteAsset: string }[] = []
- pairsWithData: string[] = []
- supportedPools: string[] = []
- supportedResolutions = ['1', '5', '15', '30', '60', '240', 'D'] as ResolutionString[]
-
- constructor(debug = false, baseDecimals: number, baseDenom: string) {
- if (debug) console.log('Start charting library datafeed')
- this.debug = debug
- this.baseDecimals = baseDecimals
- this.baseDenom = baseDenom
- const enabledMarketAssets = getEnabledMarketAssets()
- this.enabledMarketAssetDenoms = enabledMarketAssets.map((asset) => asset.denom)
- this.supportedPools = enabledMarketAssets
- .map((asset) => asset.poolId?.toString())
- .filter((poolId) => typeof poolId === 'string') as string[]
- }
-
- getDescription(pairName: string, inverted: boolean) {
- const [denom1, denom2] = pairName.split(PAIR_SEPARATOR)
- const asset1 = ASSETS.find(byDenom(denom1))
- const asset2 = ASSETS.find(byDenom(denom2))
- return inverted ? `${asset2?.symbol}/${asset1?.symbol}` : `${asset1?.symbol}/${asset2?.symbol}`
- }
-
- async getPairsWithData() {
- const query = `
- {
- pairs(first: ${this.batchSize},
- orderBy: symbol,
- orderDirection: asc,
- where: {
- baseAsset_in: ${JSON.stringify(this.enabledMarketAssetDenoms)},
- quoteAsset_in: ${JSON.stringify(this.enabledMarketAssetDenoms)},
- poolId_in: ${JSON.stringify(this.supportedPools)}
- }
- ) {
- baseAsset
- quoteAsset
- }
- }`
-
- return fetch(this.candlesEndpointTheGraph, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ query }),
- })
- .then((res) => res.json())
- .then((json) => {
- this.pairs = json.data.pairs
-
- this.pairsWithData = json.data.pairs.map(
- (pair: { baseAsset: string; quoteAsset: string }) => {
- return `${pair.quoteAsset}${PAIR_SEPARATOR}${pair.baseAsset}`
- },
- )
- })
- .catch((err) => {
- if (this.debug) console.error(err)
- throw err
- })
- }
-
- onReady(callback: OnReadyCallback) {
- const configurationData = {
- supported_resolutions: this.supportedResolutions,
- }
-
- setTimeout(async () => {
- await this.getPairsWithData()
- })
- callback(configurationData)
- }
-
- resolveSymbol(pairName: string, onResolve: ResolveCallback, onError: ErrorCallback) {
- pairName = this.getPairName(pairName)
- setTimeout(() => {
- const info: LibrarySymbolInfo = {
- ...defaultSymbolInfo,
- name: this.getDescription(pairName, false),
- full_name: this.getDescription(pairName, true),
- description: this.getDescription(pairName, true),
- ticker: this.getDescription(pairName, false),
- exchange: this.getExchangeName(pairName),
- listed_exchange: this.getExchangeName(pairName),
- supported_resolutions: this.supportedResolutions,
- base_name: [this.getDescription(pairName, false)],
- pricescale: this.getPriceScale(pairName),
- } as LibrarySymbolInfo
- onResolve(info)
- })
- }
-
- async getBars(
- symbolInfo: LibrarySymbolInfo,
- resolution: ResolutionString,
- periodParams: PeriodParams,
- onResult: HistoryCallback,
- ): Promise {
- try {
- let bars = [] as Bar[]
- const pythFeedIds = this.getPythFeedIds(symbolInfo.full_name)
- const now = new Date().getTime()
- const to = BN(now).dividedBy(1000).integerValue().toNumber()
- const from = BN(now)
- .minus(this.batchSize * this.millisecondsPerInterval[resolution])
- .dividedBy(1000)
- .integerValue()
- .toNumber()
- const pythFeedId1 = pythFeedIds[0]
- const pythFeedId2 = pythFeedIds[1]
-
- if (pythFeedId1 && pythFeedId2) {
- const asset1Bars = this.queryBarData(pythFeedId1, resolution, from, to)
- const asset2Bars = this.queryBarData(pythFeedId2, resolution, from, to)
-
- await Promise.all([asset1Bars, asset2Bars]).then(([asset1Bars, asset2Bars]) => {
- bars = this.combineBars(asset1Bars, asset2Bars)
- onResult(bars)
- })
- } else {
- //await this.getBarsFromTheGraph(symbolInfo, resolution, to).then((bars) => onResult(bars))
- onResult([], { noData: true })
- }
- } catch (error) {
- console.error(error)
- return onResult([], { noData: true })
- }
- }
-
- async getBarsFromTheGraph(
- symbolInfo: LibrarySymbolInfo,
- resolution: ResolutionString,
- to: number,
- ) {
- let pair1 = this.getPairName(symbolInfo.full_name)
- let pair2: string = ''
- let pair3: string = ''
- let theGraphBars = [] as Bar[]
-
- if (!this.pairsWithData.includes(pair1)) {
- if (this.debug) console.log('Pair does not have data, need to combine with other pairs')
-
- const [buyAssetDenom, sellAssetDenom] = pair1.split(PAIR_SEPARATOR)
-
- const pair1Pools = this.pairs.filter((pair) => pair.baseAsset === buyAssetDenom)
- const pair2Pools = this.pairs.filter((pair) => pair.quoteAsset === sellAssetDenom)
-
- const matchedPools = pair1Pools.filter((pool) => {
- const asset = pool.quoteAsset
- return !!pair2Pools.find((pool) => pool.baseAsset === asset)
- })
-
- if (matchedPools.length) {
- pair1 = `${buyAssetDenom}${PAIR_SEPARATOR}${matchedPools[0].quoteAsset}`
- pair2 = `${matchedPools[0].quoteAsset}${PAIR_SEPARATOR}${sellAssetDenom}`
- } else {
- const middlePair = this.pairs.filter(
- (pair) =>
- pair1Pools.map((pairs) => pairs.quoteAsset).includes(pair.baseAsset) &&
- pair2Pools.map((pairs) => pairs.baseAsset).includes(pair.quoteAsset),
- )
-
- pair1 = `${buyAssetDenom}${PAIR_SEPARATOR}${middlePair[0].baseAsset}`
- pair2 = `${middlePair[0].baseAsset}${PAIR_SEPARATOR}${middlePair[0].quoteAsset}`
- pair3 = `${middlePair[0].quoteAsset}${PAIR_SEPARATOR}${sellAssetDenom}`
- }
- }
-
- const pair1Bars = this.queryBarDataTheGraph(
- pair1.split(PAIR_SEPARATOR)[0],
- pair1.split(PAIR_SEPARATOR)[1],
- resolution,
- to,
- )
-
- let pair2Bars: Promise | null = null
-
- if (pair2) {
- pair2Bars = this.queryBarDataTheGraph(
- pair2.split(PAIR_SEPARATOR)[0],
- pair2.split(PAIR_SEPARATOR)[1],
- resolution,
- to,
- )
- }
-
- let pair3Bars: Promise | null = null
-
- if (pair3) {
- pair3Bars = this.queryBarDataTheGraph(
- pair3.split(PAIR_SEPARATOR)[0],
- pair3.split(PAIR_SEPARATOR)[1],
- resolution,
- to,
- )
- }
-
- await Promise.all([pair1Bars, pair2Bars, pair3Bars]).then(
- ([pair1Bars, pair2Bars, pair3Bars]) => {
- let bars = pair1Bars
-
- if (!bars.length) {
- return
- }
-
- if (pair2Bars) {
- bars = this.combineBars(pair1Bars, pair2Bars)
- }
- if (pair3Bars) {
- bars = this.combineBars(bars, pair3Bars)
- }
-
- const filler = Array.from({ length: this.batchSize - bars.length }).map((_, index) => ({
- time:
- (bars[0]?.time || new Date().getTime()) -
- (index * this.millisecondsPerInterval[resolution]) / 1000,
- close: 0,
- open: 0,
- high: 0,
- low: 0,
- volume: 0,
- }))
- theGraphBars = [...filler, ...bars]
- },
- )
-
- return theGraphBars
- }
-
- async queryBarData(
- feedSymbol: string,
- resolution: ResolutionString,
- from: PeriodParams['from'],
- to: PeriodParams['to'],
- ): Promise {
- const URI = new URL('/v1/shims/tradingview/history', this.candlesEndpoint)
- const params = new URLSearchParams(URI.search)
-
- params.append('to', to.toString())
- params.append('from', from.toString())
- params.append('resolution', resolution)
- params.append('symbol', feedSymbol)
- URI.search = params.toString()
-
- return fetch(URI)
- .then((res) => res.json())
- .then((json) => {
- return this.resolveBarData(json, resolution, to)
- })
- .catch((err) => {
- if (this.debug) console.error(err)
- throw err
- })
- }
-
- async queryBarDataTheGraph(
- quote: string,
- base: string,
- resolution: ResolutionString,
- to: PeriodParams['to'],
- ): Promise {
- const interval = this.intervalsTheGraph[resolution]
-
- const query = `
- {
- candles(
- first: ${this.batchSize},
- orderBy: "timestamp",
- orderDirection: "desc",
- where: {
- interval: "${interval}",
- quote: "${quote}",
- base: "${base}"
- poolId_in: ${JSON.stringify(this.supportedPools)}
- }
- ) {
- timestamp
- open
- high
- low
- close
- volume
- }
- }
- `
-
- return fetch(this.candlesEndpointTheGraph, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ query }),
- })
- .then((res) => res.json())
- .then((json: { data?: { candles: TheGraphBarQueryData[] } }) => {
- return this.resolveBarDataTheGraph(
- json.data?.candles.reverse() || [],
- base,
- quote,
- resolution,
- to,
- )
- })
- .catch((err) => {
- if (this.debug) console.error(err)
- throw err
- })
- }
-
- resolveBarData(data: PythBarQueryData, resolution: ResolutionString, to: number) {
- let barData = [] as Bar[]
-
- if (data['s'] === 'ok') {
- barData = data['t'].map((timestamp, index) => ({
- time: timestamp * 1000,
- close: data['c'][index],
- open: data['o'][index],
- high: data['h'][index],
- low: data['l'][index],
- }))
- }
-
- return this.fillBarData(barData, resolution, to)
- }
-
- resolveBarDataTheGraph(
- bars: TheGraphBarQueryData[],
- toDenom: string,
- fromDenom: string,
- resolution: ResolutionString,
- to: number,
- ) {
- let barData = [] as Bar[]
- const toDecimals = getAssetByDenom(toDenom)?.decimals || 6
- const fromDecimals = getAssetByDenom(fromDenom)?.decimals || 6
- const additionalDecimals = toDecimals - fromDecimals
-
- barData = bars.map((bar) => ({
- time: BN(bar.timestamp).multipliedBy(1000).toNumber(),
- close: BN(bar.close).shiftedBy(additionalDecimals).toNumber(),
- open: BN(bar.open).shiftedBy(additionalDecimals).toNumber(),
- high: BN(bar.high).shiftedBy(additionalDecimals).toNumber(),
- low: BN(bar.low).shiftedBy(additionalDecimals).toNumber(),
- volume: BN(bar.volume).shiftedBy(additionalDecimals).toNumber(),
- }))
-
- return this.fillBarData(barData, resolution, to)
- }
-
- fillBarData(barData: Bar[], resolution: ResolutionString, to: number) {
- if (barData.length < this.batchSize) {
- const filler = Array.from({ length: this.batchSize - barData.length }).map((_, index) => ({
- time: (barData[0]?.time || to) - index * this.millisecondsPerInterval[resolution],
- close: 0,
- open: 0,
- high: 0,
- low: 0,
- volume: 0,
- }))
-
- barData = [...filler, ...barData]
- }
-
- return barData.length > this.batchSize ? barData.slice(0, this.batchSize) : barData
- }
-
- combineBars(pair1Bars: Bar[], pair2Bars: Bar[]): Bar[] {
- const bars: Bar[] = []
-
- pair1Bars.forEach((pair1Bar, index) => {
- const pair2Bar = pair2Bars[index]
-
- bars.push({
- time: pair1Bar.time,
- open: devideByPotentiallyZero(pair1Bar.open, pair2Bar.open),
- close: devideByPotentiallyZero(pair1Bar.close, pair2Bar.close),
- high: devideByPotentiallyZero(pair1Bar.high, pair2Bar.high),
- low: devideByPotentiallyZero(pair1Bar.low, pair2Bar.low),
- })
- })
- return bars
- }
-
- getPairName(name: string) {
- if (name.includes(PAIR_SEPARATOR)) return name
-
- const [symbol1, symbol2] = name.split('/')
-
- const asset1 = ASSETS.find((asset) => asset.symbol === symbol1)
- const asset2 = ASSETS.find((asset) => asset.symbol === symbol2)
- return `${asset1?.denom}${PAIR_SEPARATOR}${asset2?.denom}`
- }
-
- getPriceScale(name: string) {
- const denoms = name.split(PAIR_SEPARATOR)
- const asset2 = ASSETS.find(byDenom(denoms[1]))
- const decimalsOut = asset2?.decimals ?? 6
- return BN(1)
- .shiftedBy(decimalsOut > 8 ? 8 : decimalsOut)
- .toNumber()
- }
-
- getExchangeName(name: string) {
- const denoms = name.split(PAIR_SEPARATOR)
- const pythFeedId1 = ASSETS.find(byDenom(denoms[0]))?.pythHistoryFeedId
- const pythFeedId2 = ASSETS.find(byDenom(denoms[1]))?.pythHistoryFeedId
- //if (!pythFeedId1 || !pythFeedId2) return 'Osmosis'
- return 'Pyth Oracle'
- }
-
- getPythFeedIds(name: string) {
- if (name.includes(PAIR_SEPARATOR)) {
- const [denom1, denom2] = name.split(PAIR_SEPARATOR)
- const denomFeedId1 = ASSETS.find((asset) => asset.denom === denom1)?.pythHistoryFeedId
- const denomFeedId2 = ASSETS.find((asset) => asset.denom === denom2)?.pythHistoryFeedId
- return [denomFeedId1, denomFeedId2]
- }
-
- const [symbol1, symbol2] = name.split('/')
- const feedId1 = ASSETS.find((asset) => asset.symbol === symbol1)?.pythHistoryFeedId
- const feedId2 = ASSETS.find((asset) => asset.symbol === symbol2)?.pythHistoryFeedId
-
- return [feedId1, feedId2]
- }
-
- searchSymbols(): void {
- // Don't allow to search for symbols
- }
-
- subscribeBars(): void {
- // TheGraph doesn't support websockets yet
- }
-
- unsubscribeBars(listenerGuid: string): void {
- // TheGraph doesn't support websockets yet
- }
-}
diff --git a/src/components/Trade/TradeChart/TVChartContainer.tsx b/src/components/Trade/TradeChart/TVChartContainer.tsx
deleted file mode 100644
index a64dc1e7..00000000
--- a/src/components/Trade/TradeChart/TVChartContainer.tsx
+++ /dev/null
@@ -1,166 +0,0 @@
-import { useEffect, useMemo, useRef } from 'react'
-
-import Card from 'components/Card'
-import DisplayCurrency from 'components/DisplayCurrency'
-import { FormattedNumber } from 'components/FormattedNumber'
-import Loading from 'components/Loading'
-import Text from 'components/Text'
-import { DataFeed, PAIR_SEPARATOR } from 'components/Trade/TradeChart/DataFeed'
-import PoweredByPyth from 'components/Trade/TradeChart/PoweredByPyth'
-import { disabledFeatures, enabledFeatures, overrides } from 'components/Trade/TradeChart/constants'
-import { BN_ZERO } from 'constants/math'
-import usePrices from 'hooks/usePrices'
-import useStore from 'store'
-import { BNCoin } from 'types/classes/BNCoin'
-import { byDenom } from 'utils/array'
-import {
- ChartingLibraryWidgetOptions,
- IChartingLibraryWidget,
- ResolutionString,
- Timezone,
- widget,
-} from 'utils/charting_library'
-import { magnify } from 'utils/formatters'
-
-interface Props {
- buyAsset: Asset
- sellAsset: Asset
-}
-
-export const TVChartContainer = (props: Props) => {
- const chartContainerRef = useRef() as React.MutableRefObject
- const widgetRef = useRef()
- const defaultSymbol = useRef(
- `${props.sellAsset.denom}${PAIR_SEPARATOR}${props.buyAsset.denom}`,
- )
- const baseCurrency = useStore((s) => s.baseCurrency)
- const dataFeed = useMemo(
- () => new DataFeed(false, baseCurrency.decimals, baseCurrency.denom),
- [baseCurrency],
- )
- const { data: prices, isLoading } = usePrices()
- const ratio = useMemo(() => {
- const priceBuyAsset = prices.find(byDenom(props.buyAsset.denom))?.amount
- const priceSellAsset = prices.find(byDenom(props.sellAsset.denom))?.amount
-
- if (!priceBuyAsset || !priceSellAsset) return BN_ZERO
- return priceBuyAsset.dividedBy(priceSellAsset)
- }, [prices, props.buyAsset.denom, props.sellAsset.denom])
-
- useEffect(() => {
- const widgetOptions: ChartingLibraryWidgetOptions = {
- symbol: defaultSymbol.current,
- datafeed: dataFeed,
- interval: '1h' as ResolutionString,
- library_path: '/charting_library/',
- locale: 'en',
- time_scale: {
- min_bar_spacing: 12,
- },
- toolbar_bg: '#220E1D',
- disabled_features: disabledFeatures,
- enabled_features: enabledFeatures,
- charts_storage_api_version: '1.1',
- client_id: 'sample-implementation',
- timezone: 'Etc/UTC' as Timezone,
- user_id: 'not-set',
- fullscreen: false,
- autosize: true,
- container: chartContainerRef.current,
- custom_css_url: '/tradingview.css',
- settings_overrides: {
- 'paneProperties.background': '#220E1D',
- 'paneProperties.backgroundType': 'solid',
- 'paneProperties.vertGridProperties.color': '#220E1D',
- 'paneProperties.horzGridProperties.color': '#220E1D',
- 'mainSeriesProperties.candleStyle.upColor': '#3DAE9A',
- 'mainSeriesProperties.candleStyle.downColor': '#AE3D3D',
- 'mainSeriesProperties.candleStyle.borderColor': '#232834',
- 'mainSeriesProperties.candleStyle.borderUpColor': '#3DAE9A',
- 'mainSeriesProperties.candleStyle.borderDownColor': '#AE3D3D',
- 'mainSeriesProperties.candleStyle.wickUpColor': '#3DAE9A',
- 'mainSeriesProperties.candleStyle.wickDownColor': '#AE3D3D',
- 'mainSeriesProperties.candleStyle.barColorsOnPrevClose': false,
- 'scalesProperties.textColor': 'rgba(255, 255, 255, 0.7)',
- 'paneProperties.legendProperties.showSeriesTitle': true,
- 'paneProperties.legendProperties.showVolume': false,
- 'paneProperties.legendProperties.showStudyValues': false,
- 'paneProperties.legendProperties.showStudyTitles': false,
- 'scalesProperties.axisHighlightColor': '#381730',
- 'linetooltrendline.color': '#3DAE9A',
- 'linetooltrendline.linewidth': 10,
- },
- overrides,
- loading_screen: {
- backgroundColor: '#220E1D',
- foregroundColor: 'rgba(255, 255, 255, 0.3)',
- },
- theme: 'dark',
- }
-
- const tvWidget = new widget(widgetOptions)
-
- tvWidget.onChartReady(() => {
- widgetRef.current = tvWidget
- })
-
- return () => {
- tvWidget.remove()
- }
- }, [dataFeed, defaultSymbol])
-
- useEffect(() => {
- if (widgetRef?.current) {
- widgetRef.current.setSymbol(
- `${props.sellAsset.denom}${PAIR_SEPARATOR}${props.buyAsset.denom}`,
- widgetRef.current.chart().resolution() || ('1h' as ResolutionString),
- () => {},
- )
- }
- }, [props.buyAsset.denom, props.sellAsset.denom])
-
- return (
-
-
- Trading Chart
-
- {ratio.isZero() || isLoading ? (
-
- ) : (
-
- 1 {props.buyAsset.symbol}
-
-
-
- )}
-
- }
- contentClassName='px-0.5 pb-0.5 h-full bg-chart'
- className='h-[70dvh] max-h-[980px] min-h-[560px]'
- >
-
-
-
- )
-}
diff --git a/src/components/Trade/TradeChart/index.tsx b/src/components/Trade/TradeChart/index.tsx
deleted file mode 100644
index 77ad2c0f..00000000
--- a/src/components/Trade/TradeChart/index.tsx
+++ /dev/null
@@ -1,59 +0,0 @@
-import dynamic from 'next/dynamic'
-import Script from 'next/script'
-import { useState } from 'react'
-
-import Card from 'components/Card'
-import { CircularProgress } from 'components/CircularProgress'
-import Loading from 'components/Loading'
-import Text from 'components/Text'
-import PoweredByPyth from 'components/Trade/TradeChart/PoweredByPyth'
-
-const TVChartContainer = dynamic(
- () => import('components/Trade/TradeChart/TVChartContainer').then((mod) => mod.TVChartContainer),
- { ssr: false },
-)
-
-interface Props {
- buyAsset: Asset
- sellAsset: Asset
-}
-
-export default function TradeChart(props: Props) {
- const [isScriptReady, setIsScriptReady] = useState(false)
-
- return (
- <>
-