mirror of
https://github.com/cerc-io/mars-interface.git
synced 2024-12-22 20:27:44 +00:00
v1.1.0
This commit is contained in:
parent
5f019f3fdd
commit
04537f8ad8
28
README.md
28
README.md
@ -2,11 +2,11 @@
|
||||
|
||||
![mars-banner-1200w](https://marsprotocol.io/banner.png)
|
||||
|
||||
## Web App
|
||||
## 1. Web App
|
||||
|
||||
This project is a [NextJS](https://nextjs.org/). React application.
|
||||
|
||||
The project utilises [React hooks](https://reactjs.org/docs/hooks-intro.html), functional components, Zustand for state management, and useQuery for general data fetching and management.
|
||||
The project utilises [React hooks](https://reactjs.org/docs/hooks-intro.html), functional components, [Zustand](https://github.com/pmndrs/zustand) for state management, and [useQuery](https://github.com/TanStack/query) for general data fetching and management.
|
||||
|
||||
Typescript is added and utilised (but optional if you want to create .jsx or .tsx files).
|
||||
|
||||
@ -14,7 +14,7 @@ SCSS with [CSS modules](https://create-react-app.dev/docs/adding-a-css-modules-s
|
||||
|
||||
Sentry is used for front end error logging/exception & bug reporting.
|
||||
|
||||
## Deployment
|
||||
## 2. Deployment
|
||||
|
||||
Start web server
|
||||
|
||||
@ -22,16 +22,18 @@ Start web server
|
||||
yarn && yarn dev
|
||||
```
|
||||
|
||||
### Contributing
|
||||
## 3. Text and translations
|
||||
|
||||
We welcome and encourage contributions! Please create a pull request with as much information about the work you did and what your motivation/intention was.
|
||||
This repository makes use of a [translation repository](https://github.com/mars-protocol/translations). This repository containes all of the translation key values that are used within the UI. The rationale is to have no _hardcoded_ display string values in this repository.
|
||||
|
||||
## Imports
|
||||
## 4. Development practices
|
||||
|
||||
### 4.1 Imports
|
||||
|
||||
Local components are imported via index files, which can be automatically generated with `yarn index`. This command targets index.ts files with a specific pattern in order to automate component exports. This results in clean imports throughout the pages:
|
||||
|
||||
```
|
||||
import { Button, Card, Titlte } from 'components/common'
|
||||
import { Button, Card, Title } from 'components/common'
|
||||
```
|
||||
|
||||
or
|
||||
@ -42,6 +44,16 @@ import { Breakdown, RepayInput } from 'components/fields'
|
||||
|
||||
In order for this to work, components are place in a folder with UpperCamelCase with the respective Component.tsx file. The component cannot be exported at default, so rather export the `const` instead.
|
||||
|
||||
## License
|
||||
### 4.2 Data orchestration
|
||||
|
||||
Data is handled with a combination of container components, useQuery and Zustand. Container components are responsible for syncing the application state with the wallet-provider state. This fire of the required queries in useQuery, which are for many cases also stored in Zustand.
|
||||
|
||||
We aim to have as much as possible available in Zustand, to have one source of truth.
|
||||
|
||||
## 5. Contributing
|
||||
|
||||
We welcome and encourage contributions! Please create a pull request with as much information about the work you did and what your motivation/intention was.
|
||||
|
||||
## 6. License
|
||||
|
||||
Contents of this repository are open source under the [Mars Protocol Web Application License Agreement](./LICENSE).
|
||||
|
76
package.json
76
package.json
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "mars",
|
||||
"homepage": "./",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"private": false,
|
||||
"license": "SEE LICENSE IN LICENSE FILE",
|
||||
"scripts": {
|
||||
@ -22,48 +22,48 @@
|
||||
"@cosmjs/launchpad": "^0.27.1",
|
||||
"@cosmjs/proto-signing": "^0.29.5",
|
||||
"@cosmjs/stargate": "^0.29.5",
|
||||
"@marsprotocol/wallet-connector": "^0.9.12",
|
||||
"@marsprotocol/wallet-connector": "^1.2.3",
|
||||
"@material-ui/core": "^4.12.4",
|
||||
"@material-ui/icons": "^4.11.3",
|
||||
"@ramonak/react-progress-bar": "^5.0.2",
|
||||
"@sentry/nextjs": "^7.12.1",
|
||||
"@tanstack/react-query": "^4.3.4",
|
||||
"@tanstack/react-table": "^8.5.13",
|
||||
"@testing-library/dom": "^8.17.1",
|
||||
"@ramonak/react-progress-bar": "^5.0.3",
|
||||
"@sentry/nextjs": "^7.34.0",
|
||||
"@tanstack/react-query": "^4.24.4",
|
||||
"@tanstack/react-table": "^8.7.9",
|
||||
"@testing-library/dom": "^8.20.0",
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@testing-library/react": "^13.4.0",
|
||||
"@testing-library/user-event": "^14.4.3",
|
||||
"@tippyjs/react": "^4.2.6",
|
||||
"bignumber.js": "^9.1.0",
|
||||
"chart.js": "^3.9.1",
|
||||
"classnames": "^2.3.1",
|
||||
"bignumber.js": "^9.1.1",
|
||||
"chart.js": "^4.2.0",
|
||||
"classnames": "^2.3.2",
|
||||
"create-conical-gradient": "^1.1.0",
|
||||
"graphql": "^16.6.0",
|
||||
"graphql-request": "^5.0.0",
|
||||
"i18next": "^21.9.1",
|
||||
"i18next-browser-languagedetector": "^6.1.5",
|
||||
"i18next-http-backend": "^1.4.1",
|
||||
"graphql-request": "^5.1.0",
|
||||
"i18next": "^22.4.9",
|
||||
"i18next-browser-languagedetector": "^7.0.1",
|
||||
"i18next-http-backend": "^2.1.1",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"lodash.throttle": "^4.1.1",
|
||||
"moment": "^2.29.4",
|
||||
"moment-duration-format": "^2.3.2",
|
||||
"next": "^12.2.5",
|
||||
"next": "^13.1.6",
|
||||
"numeral": "^2.0.6",
|
||||
"ramda": "^0.28.0",
|
||||
"react": "^18.2.0",
|
||||
"react-chartjs-2": "^4.3.1",
|
||||
"react-currency-input-field": "^3.6.4",
|
||||
"react-chartjs-2": "^5.2.0",
|
||||
"react-currency-input-field": "^3.6.9",
|
||||
"react-device-detect": "^2.2.2",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-i18next": "^11.18.5",
|
||||
"react-spring": "^9.5.5",
|
||||
"react-i18next": "^12.1.4",
|
||||
"react-spring": "^9.6.1",
|
||||
"react-table": "^7.8.0",
|
||||
"react-use-clipboard": "^1.0.8",
|
||||
"sass": "^1.56.1",
|
||||
"typescript": "^4.8.2",
|
||||
"web-vitals": "^3.0.1",
|
||||
"zustand": "^4.1.1"
|
||||
"react-use-clipboard": "^1.0.9",
|
||||
"sass": "^1.57.1",
|
||||
"typescript": "^4.9.5",
|
||||
"web-vitals": "^3.1.1",
|
||||
"zustand": "^4.3.2"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
@ -80,26 +80,26 @@
|
||||
"devDependencies": {
|
||||
"@types/chart.js": "^2.9.37",
|
||||
"@types/classnames": "^2.3.1",
|
||||
"@types/jest": "^29.2.3",
|
||||
"@types/jest": "^29.4.0",
|
||||
"@types/lodash.clonedeep": "^4.5.7",
|
||||
"@types/lodash.isequal": "^4.5.6",
|
||||
"@types/lodash.throttle": "^4.1.7",
|
||||
"@types/node": "^18.7.15",
|
||||
"@types/node": "^18.11.18",
|
||||
"@types/numeral": "^2.0.2",
|
||||
"@types/prettier": "^2.7.0",
|
||||
"@types/ramda": "^0.28.15",
|
||||
"@types/react": "^18.0.18",
|
||||
"@types/react-dom": "^18.0.6",
|
||||
"@types/react-table": "^7.7.12",
|
||||
"eslint": "^8.23.0",
|
||||
"eslint-config-next": "^12.2.5",
|
||||
"eslint-plugin-simple-import-sort": "^8.0.0",
|
||||
"@types/prettier": "^2.7.2",
|
||||
"@types/ramda": "^0.28.22",
|
||||
"@types/react": "^18.0.27",
|
||||
"@types/react-dom": "^18.0.10",
|
||||
"@types/react-table": "^7.7.14",
|
||||
"eslint": "^8.33.0",
|
||||
"eslint-config-next": "^13.1.6",
|
||||
"eslint-plugin-simple-import-sort": "^10.0.0",
|
||||
"eslint-plugin-unused-imports": "^2.0.0",
|
||||
"jest": "^29.3.1",
|
||||
"jest-environment-jsdom": "^29.3.1",
|
||||
"prettier": "^2.7.1",
|
||||
"jest": "^29.4.1",
|
||||
"jest-environment-jsdom": "^29.4.1",
|
||||
"prettier": "^2.8.3",
|
||||
"pretty-quick": "^3.1.3",
|
||||
"vscode-generate-index-standalone": "^1.6.0"
|
||||
"vscode-generate-index-standalone": "^1.7.1"
|
||||
},
|
||||
"engines": {
|
||||
"npm": "please-use-yarn",
|
||||
|
@ -1,4 +1,4 @@
|
||||
import classNames from 'classnames/bind'
|
||||
import classNames from 'classnames'
|
||||
|
||||
import styles from './Backdrop.module.scss'
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import classNames from 'classnames/bind'
|
||||
import classNames from 'classnames'
|
||||
import { AnimatedNumber, DisplayCurrency } from 'components/common'
|
||||
import { lookup } from 'libs/parse'
|
||||
|
||||
|
@ -1,4 +1,11 @@
|
||||
import { useWallet } from '@marsprotocol/wallet-connector'
|
||||
import { CosmWasmClient } from '@cosmjs/cosmwasm-stargate'
|
||||
import {
|
||||
getChainInfo,
|
||||
getClient,
|
||||
useWallet,
|
||||
useWalletManager,
|
||||
WalletConnectionStatus,
|
||||
} from '@marsprotocol/wallet-connector'
|
||||
import { useQueryClient } from '@tanstack/react-query'
|
||||
import { MARS_SYMBOL, USDC_SYMBOL } from 'constants/appConstants'
|
||||
import {
|
||||
@ -9,9 +16,10 @@ import {
|
||||
useUserBalance,
|
||||
useUserDebt,
|
||||
useUserDeposit,
|
||||
useUserIcns,
|
||||
} from 'hooks/queries'
|
||||
import { useSpotPrice } from 'hooks/queries/useSpotPrice'
|
||||
import { ReactNode, useEffect } from 'react'
|
||||
import { ReactNode, useEffect, useState } from 'react'
|
||||
import useStore from 'store'
|
||||
import { State } from 'types/enums'
|
||||
import { Network } from 'types/enums/network'
|
||||
@ -24,9 +32,15 @@ export const CommonContainer = ({ children }: CommonContainerProps) => {
|
||||
// ------------------
|
||||
// EXTERNAL HOOKS
|
||||
// ---------------
|
||||
const { chainInfo, address, signingCosmWasmClient, name } = useWallet()
|
||||
const { recentWallet, simulate, sign, broadcast } = useWallet()
|
||||
const { status } = useWalletManager()
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
const chainInfo = recentWallet?.network ? getChainInfo(recentWallet?.network.chainId) : undefined
|
||||
const address = status !== WalletConnectionStatus.Connected ? '' : recentWallet?.account.address
|
||||
|
||||
const [cosmWasmClient, setCosmWasmClient] = useState<CosmWasmClient | undefined>()
|
||||
|
||||
// ------------------
|
||||
// STORE STATE
|
||||
// ------------------
|
||||
@ -54,7 +68,6 @@ export const CommonContainer = ({ children }: CommonContainerProps) => {
|
||||
const setClient = useStore((s) => s.setClient)
|
||||
const setUserBalancesState = useStore((s) => s.setUserBalancesState)
|
||||
const setUserWalletAddress = useStore((s) => s.setUserWalletAddress)
|
||||
const setUserWalletName = useStore((s) => s.setUserWalletName)
|
||||
|
||||
// ------------------
|
||||
// SETTERS
|
||||
@ -75,21 +88,11 @@ export const CommonContainer = ({ children }: CommonContainerProps) => {
|
||||
setUserWalletAddress(address || '')
|
||||
}, [setUserWalletAddress, address])
|
||||
|
||||
useEffect(() => {
|
||||
if (!name) return
|
||||
setUserWalletName(name)
|
||||
}, [setUserWalletName, name])
|
||||
|
||||
useEffect(() => {
|
||||
if (!rpc || !chainID) return
|
||||
setLcdClient(rpc, chainID)
|
||||
}, [rpc, chainID, setLcdClient])
|
||||
|
||||
useEffect(() => {
|
||||
if (!signingCosmWasmClient) return
|
||||
setClient(signingCosmWasmClient)
|
||||
}, [signingCosmWasmClient, setClient])
|
||||
|
||||
useEffect(() => {
|
||||
if (userDebts && userDeposits && userBalances) {
|
||||
setUserBalancesState(State.READY)
|
||||
@ -98,6 +101,28 @@ export const CommonContainer = ({ children }: CommonContainerProps) => {
|
||||
}
|
||||
}, [userDebts, userDeposits, userBalances, setUserBalancesState])
|
||||
|
||||
useEffect(() => {
|
||||
if (!recentWallet) return
|
||||
if (!cosmWasmClient) {
|
||||
const getCosmWasmClient = async () => {
|
||||
const cosmClient = await getClient(recentWallet.network.rpc)
|
||||
setCosmWasmClient(cosmClient)
|
||||
}
|
||||
|
||||
getCosmWasmClient()
|
||||
return
|
||||
}
|
||||
|
||||
const client = {
|
||||
broadcast,
|
||||
cosmWasmClient,
|
||||
recentWallet,
|
||||
sign,
|
||||
simulate,
|
||||
}
|
||||
setClient(client)
|
||||
}, [simulate, sign, recentWallet, cosmWasmClient, broadcast, setClient])
|
||||
|
||||
useEffect(() => {
|
||||
setRedBankAssets()
|
||||
}, [
|
||||
@ -126,6 +151,7 @@ export const CommonContainer = ({ children }: CommonContainerProps) => {
|
||||
useBlockHeight()
|
||||
useRedBank()
|
||||
useUserBalance()
|
||||
useUserIcns()
|
||||
useUserDeposit()
|
||||
useUserDebt()
|
||||
useMarsOracle()
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React, { ReactNode, useEffect } from 'react'
|
||||
import useStore from 'store'
|
||||
import { AccountNftClient, CreditManagerClient } from 'types/classes'
|
||||
|
||||
interface FieldsContainerProps {
|
||||
children: ReactNode
|
||||
@ -9,15 +10,17 @@ export const FieldsContainer = ({ children }: FieldsContainerProps) => {
|
||||
const client = useStore((s) => s.client)
|
||||
const networkConfig = useStore((s) => s.networkConfig)
|
||||
const userWalletAddress = useStore((s) => s.userWalletAddress)
|
||||
const setAccountNftClient = useStore((s) => s.setAccountNftClient)
|
||||
const setCreditManagerClient = useStore((s) => s.setCreditManagerClient)
|
||||
const setCreditManagerMsgComposer = useStore((s) => s.setCreditManagerMsgComposer)
|
||||
|
||||
useEffect(() => {
|
||||
if (!client) return
|
||||
setAccountNftClient(client)
|
||||
setCreditManagerClient(client)
|
||||
}, [client, setAccountNftClient, setCreditManagerClient])
|
||||
if (!client || !networkConfig) return
|
||||
useStore.setState({
|
||||
creditManagerClient: new CreditManagerClient(networkConfig?.contracts.creditManager, client),
|
||||
})
|
||||
useStore.setState({
|
||||
accountNftClient: new AccountNftClient(networkConfig?.contracts.accountNft, client),
|
||||
})
|
||||
}, [client, networkConfig])
|
||||
|
||||
useEffect(() => {
|
||||
if (!userWalletAddress || !networkConfig?.contracts.creditManager) return
|
||||
|
@ -1,152 +1,8 @@
|
||||
@import 'src/styles/master';
|
||||
|
||||
.overlay {
|
||||
background-color: $alphaBlack60;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
z-index: 50;
|
||||
.loader {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 0 0 100%;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
margin: 0;
|
||||
|
||||
.loader {
|
||||
display: flex;
|
||||
flex: 0 0 100%;
|
||||
justify-content: center;
|
||||
@include margin(4, 0);
|
||||
}
|
||||
|
||||
.button {
|
||||
@include margin(4, 0, 0);
|
||||
}
|
||||
|
||||
.content {
|
||||
@include layoutTile;
|
||||
width: rem-calc(540);
|
||||
max-width: 100vw;
|
||||
transform: translateX(-50%);
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
@include padding(4);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
outline: none;
|
||||
cursor: auto;
|
||||
|
||||
.header {
|
||||
@include typoXXLcaps;
|
||||
text-align: center;
|
||||
color: $fontColorLightPrimary;
|
||||
font-weight: $fontWeightRegular;
|
||||
@include margin(0, 0, 4);
|
||||
}
|
||||
|
||||
.enableContent {
|
||||
display: flex;
|
||||
flex: 0 0 100%;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.text {
|
||||
@include typoM;
|
||||
text-align: center;
|
||||
color: $fontColorLightSecondary;
|
||||
width: 100%;
|
||||
display: block;
|
||||
|
||||
button {
|
||||
@include typoM;
|
||||
appearance: none;
|
||||
font-weight: $fontWeightSemibold;
|
||||
color: $colorPrimary;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list {
|
||||
@include padding(2, 0);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: space(4);
|
||||
.wallet,
|
||||
button,
|
||||
a {
|
||||
background: transparent;
|
||||
@include padding(2);
|
||||
box-shadow: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
appearance: none;
|
||||
border: none;
|
||||
width: 100%;
|
||||
text-decoration: none;
|
||||
border-radius: space(2);
|
||||
cursor: pointer;
|
||||
|
||||
&.disabled {
|
||||
pointer-events: none;
|
||||
img,
|
||||
.info .name {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $alphaWhite10;
|
||||
}
|
||||
|
||||
img {
|
||||
height: space(15);
|
||||
width: space(15);
|
||||
}
|
||||
|
||||
.info {
|
||||
font-weight: $fontWeightRegular;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-left: space(5);
|
||||
|
||||
.name {
|
||||
@include typoLcaps;
|
||||
color: $fontColorLightPrimary;
|
||||
}
|
||||
|
||||
.description {
|
||||
@include margin(1, 0, 0);
|
||||
color: $fontColorLightTertiary;
|
||||
text-align: left;
|
||||
@include typoM;
|
||||
|
||||
&.capitalize {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
canvas {
|
||||
max-width: 90vw;
|
||||
max-height: 90vw;
|
||||
height: rem-calc(320);
|
||||
width: rem-calc(320);
|
||||
border: space(3) solid $colorWhite;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
@include margin(4, 0);
|
||||
}
|
||||
|
@ -1,13 +1,6 @@
|
||||
import { ChainInfoID, WalletManagerProvider, WalletType } from '@marsprotocol/wallet-connector'
|
||||
import { ChainInfoID, WalletID, WalletManagerProvider } from '@marsprotocol/wallet-connector'
|
||||
import { CircularProgress, SVG } from 'components/common'
|
||||
import buttonStyles from 'components/common/Button/Button.module.scss'
|
||||
import { NETWORK_CONFIG } from 'configs/osmo-test-4'
|
||||
import { SESSION_WALLET_KEY } from 'constants/appConstants'
|
||||
import KeplrImage from 'images/keplr-wallet-extension.png'
|
||||
import WalletConnectImage from 'images/walletconnect-keplr.png'
|
||||
import { FC } from 'react'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import useStore from 'store'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
import styles from './CosmosWalletConnectProvider.module.scss'
|
||||
|
||||
@ -15,66 +8,48 @@ type Props = {
|
||||
children?: React.ReactNode
|
||||
}
|
||||
|
||||
export const CosmosWalletConnectProvider: FC<Props> = ({ children }) => {
|
||||
const { t } = useTranslation()
|
||||
const chainId = useStore((s) => s.currentNetwork)
|
||||
const defaultChain = ChainInfoID.OsmosisTestnet
|
||||
|
||||
export const CosmosWalletConnectProvider = ({ children }: Props) => {
|
||||
const [chainInfoOverrides, setChainInfoOverrides] = useState<{ rpc: string; rest: string }>()
|
||||
const [enabledWallets, setEnabledWallets] = useState<WalletID[]>([])
|
||||
|
||||
useEffect(() => {
|
||||
if (chainInfoOverrides) return
|
||||
|
||||
const fetchConfig = async () => {
|
||||
const file = await import(
|
||||
`../../../configs/${
|
||||
process.env.NEXT_PUBLIC_NETWORK === 'mainnet' ? 'osmosis-1' : 'osmo-test-4'
|
||||
}.ts`
|
||||
)
|
||||
|
||||
const networkConfig: NetworkConfig = file.NETWORK_CONFIG
|
||||
|
||||
setChainInfoOverrides({
|
||||
rpc: networkConfig.rpcUrl,
|
||||
rest: networkConfig.restUrl,
|
||||
})
|
||||
setEnabledWallets(networkConfig.wallets)
|
||||
}
|
||||
|
||||
fetchConfig()
|
||||
})
|
||||
|
||||
if (!chainInfoOverrides || !enabledWallets?.length) return null
|
||||
|
||||
return (
|
||||
<WalletManagerProvider
|
||||
chainInfoOverrides={{
|
||||
[ChainInfoID.OsmosisTestnet]: {
|
||||
rpc: NETWORK_CONFIG.rpcUrl,
|
||||
rest: NETWORK_CONFIG.restUrl,
|
||||
},
|
||||
}}
|
||||
classNames={{
|
||||
modalContent: styles.content,
|
||||
modalOverlay: styles.overlay,
|
||||
modalHeader: styles.header,
|
||||
modalCloseButton: styles.close,
|
||||
walletList: styles.list,
|
||||
wallet: styles.wallet,
|
||||
walletImage: styles.image,
|
||||
walletInfo: styles.info,
|
||||
walletName: styles.name,
|
||||
walletDescription: styles.description,
|
||||
textContent: styles.text,
|
||||
}}
|
||||
chainInfoOverrides={chainInfoOverrides}
|
||||
closeIcon={<SVG.Close />}
|
||||
defaultChainId={chainId}
|
||||
enabledWalletTypes={[WalletType.Keplr, WalletType.WalletConnectKeplr]}
|
||||
enablingMeta={{
|
||||
text: <Trans i18nKey='global.walletResetText' />,
|
||||
textClassName: styles.text,
|
||||
buttonText: <Trans i18nKey='global.walletReset' />,
|
||||
buttonClassName: ` ${buttonStyles.button} ${buttonStyles.primary} ${buttonStyles.small} ${buttonStyles.solid} ${styles.button}`,
|
||||
contentClassName: styles.enableContent,
|
||||
}}
|
||||
enablingStringOverride={t('global.connectingToWallet')}
|
||||
localStorageKey={SESSION_WALLET_KEY}
|
||||
defaultChainId={defaultChain}
|
||||
enabledWallets={enabledWallets}
|
||||
persistent
|
||||
renderLoader={() => (
|
||||
<div className={styles.loader}>
|
||||
<CircularProgress size={30} />
|
||||
</div>
|
||||
)}
|
||||
walletConnectClientMeta={{
|
||||
name: 'Mars Protocol',
|
||||
description:
|
||||
'Lend, borrow and earn on the galaxy`s most powerful credit protocol or enter the Fields of Mars for advanced DeFi strategies.',
|
||||
url: 'https://marsprotocol.io',
|
||||
icons: ['https://marsprotocol.io/favicon.svg'],
|
||||
}}
|
||||
walletMetaOverride={{
|
||||
[WalletType.Keplr]: {
|
||||
description: <Trans i18nKey='global.keplrBrowserExtension' />,
|
||||
imageUrl: KeplrImage.src,
|
||||
},
|
||||
[WalletType.WalletConnectKeplr]: {
|
||||
name: <Trans i18nKey='global.walletConnect' />,
|
||||
description: <Trans i18nKey='global.walletConnectDescription' />,
|
||||
imageUrl: WalletConnectImage.src,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</WalletManagerProvider>
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { useWallet, WalletConnectionStatus } from '@marsprotocol/wallet-connector'
|
||||
import { useWalletManager, WalletConnectionStatus } from '@marsprotocol/wallet-connector'
|
||||
import { ConnectButton, ConnectedButton } from 'components/common'
|
||||
|
||||
export const Connect = () => {
|
||||
const { status } = useWallet()
|
||||
const { status } = useWalletManager()
|
||||
|
||||
if (status === WalletConnectionStatus.Connected) return <ConnectedButton />
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ChainInfoID, SimpleChainInfoList, useWalletManager } from '@marsprotocol/wallet-connector'
|
||||
import { ChainInfoID, useWallet, useWalletManager } from '@marsprotocol/wallet-connector'
|
||||
import { AnimatedNumber, Button, CircularProgress, DisplayCurrency, SVG } from 'components/common'
|
||||
import { findByDenom } from 'functions'
|
||||
import { useUserBalance } from 'hooks/queries'
|
||||
@ -16,7 +16,8 @@ export const ConnectedButton = () => {
|
||||
// ---------------
|
||||
// EXTERNAL HOOKS
|
||||
// ---------------
|
||||
const { disconnect } = useWalletManager()
|
||||
const { disconnect } = useWallet()
|
||||
const { disconnect: terminate } = useWalletManager()
|
||||
const { t } = useTranslation()
|
||||
|
||||
// ---------------
|
||||
@ -25,7 +26,7 @@ export const ConnectedButton = () => {
|
||||
const baseCurrency = useStore((s) => s.baseCurrency)
|
||||
const chainInfo = useStore((s) => s.chainInfo)
|
||||
const userWalletAddress = useStore((s) => s.userWalletAddress)
|
||||
const userWalletName = useStore((s) => s.userWalletName)
|
||||
const userIcns = useStore((s) => s.userIcns)
|
||||
|
||||
// ---------------
|
||||
// LOCAL STATE
|
||||
@ -34,18 +35,16 @@ export const ConnectedButton = () => {
|
||||
successDuration: 1000 * 5,
|
||||
})
|
||||
const { data, isLoading } = useUserBalance()
|
||||
|
||||
// ---------------
|
||||
// VARIABLES
|
||||
// ---------------
|
||||
const baseCurrencyBalance = Number(findByDenom(data || [], baseCurrency.denom || '')?.amount || 0)
|
||||
const explorerName =
|
||||
chainInfo && SimpleChainInfoList[chainInfo.chainId as ChainInfoID].explorerName
|
||||
const explorerName = chainInfo ? chainInfo.explorerName : ''
|
||||
|
||||
const [showDetails, setShowDetails] = useState(false)
|
||||
|
||||
const viewOnFinder = useCallback(() => {
|
||||
const explorerUrl = chainInfo && SimpleChainInfoList[chainInfo.chainId as ChainInfoID].explorer
|
||||
const explorerUrl = chainInfo ? chainInfo.explorer : ''
|
||||
|
||||
window.open(`${explorerUrl}account/${userWalletAddress}`, '_blank')
|
||||
}, [chainInfo, userWalletAddress])
|
||||
@ -60,6 +59,11 @@ export const ConnectedButton = () => {
|
||||
baseCurrency.decimals,
|
||||
)
|
||||
|
||||
const handleDisconnect = () => {
|
||||
disconnect()
|
||||
terminate()
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.wrapper}>
|
||||
{chainInfo?.chainId !== ChainInfoID.Osmosis1 && (
|
||||
@ -75,18 +79,11 @@ export const ConnectedButton = () => {
|
||||
text={
|
||||
<>
|
||||
<span className={styles.address}>
|
||||
{userWalletName ? userWalletName : truncate(userWalletAddress, [2, 4])}
|
||||
{userIcns ? userIcns.split('.')[0] : truncate(userWalletAddress, [2, 4])}
|
||||
</span>
|
||||
<span className={`${styles.balance} number`}>
|
||||
{!isLoading ? (
|
||||
`${formatValue(
|
||||
currentBalanceAmount,
|
||||
2,
|
||||
2,
|
||||
true,
|
||||
false,
|
||||
` ${chainInfo?.stakeCurrency?.coinDenom}`,
|
||||
)}`
|
||||
`${formatValue(currentBalanceAmount, 2, 2, true, false, ` ${baseCurrency.symbol}`)}`
|
||||
) : (
|
||||
<CircularProgress className={styles.circularProgress} size={12} />
|
||||
)}
|
||||
@ -99,26 +96,28 @@ export const ConnectedButton = () => {
|
||||
<div className={styles.details}>
|
||||
<div className={styles.detailsHeader}>
|
||||
<div className={styles.detailsBalance}>
|
||||
<div className={styles.detailsDenom}>{chainInfo?.stakeCurrency?.coinDenom}</div>
|
||||
<div className={styles.detailsDenom}>{baseCurrency.symbol}</div>
|
||||
<div className={`${styles.detailsBalanceAmount}`}>
|
||||
<AnimatedNumber amount={currentBalanceAmount} abbreviated={false} />
|
||||
<DisplayCurrency
|
||||
className='s faded'
|
||||
coin={{
|
||||
amount: baseCurrencyBalance.toString(),
|
||||
denom: baseCurrency.denom,
|
||||
denom: baseCurrency.symbol,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.detailsButton}>
|
||||
<Button color='secondary' onClick={disconnect} text={t('common.disconnect')} />
|
||||
<Button
|
||||
color='secondary'
|
||||
onClick={handleDisconnect}
|
||||
text={t('common.disconnect')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.detailsBody}>
|
||||
<p className={styles.addressLabel}>
|
||||
{userWalletName ? `‘${userWalletName}’` : t('common.yourAddress')}
|
||||
</p>
|
||||
<p className={styles.addressLabel}>{userIcns ? userIcns : t('common.yourAddress')}</p>
|
||||
<p className={styles.address}>{userWalletAddress}</p>
|
||||
<p className={styles.addressMobile}>{truncate(userWalletAddress, [14, 14])}</p>
|
||||
<div className={styles.buttons}>
|
||||
|
@ -63,7 +63,6 @@
|
||||
|
||||
.active {
|
||||
opacity: 1;
|
||||
pointer-events: none;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
@ -74,6 +73,10 @@
|
||||
background-color: $fontColorLightPrimary;
|
||||
}
|
||||
}
|
||||
|
||||
.unclickable {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,21 +20,28 @@ export const Header = () => {
|
||||
<SVG.Logo />
|
||||
</div>
|
||||
<div className={styles.navbar}>
|
||||
<Link href='/redbank' passHref>
|
||||
<a className={classNames(styles.nav, !router.pathname.includes('farm') && styles.active)}>
|
||||
{t('global.redBank')}
|
||||
</a>
|
||||
<Link
|
||||
passHref
|
||||
href='/redbank'
|
||||
className={classNames(
|
||||
styles.nav,
|
||||
!router.pathname.includes('farm') && styles.active,
|
||||
router.pathname === '/redbank' && styles.unclickable,
|
||||
)}
|
||||
>
|
||||
{t('global.redBank')}
|
||||
</Link>
|
||||
<Link href='/farm' passHref>
|
||||
<a
|
||||
className={classNames(
|
||||
!FIELDS_FEATURE && styles.disabled,
|
||||
styles.nav,
|
||||
router.pathname.includes('farm') && styles.active,
|
||||
)}
|
||||
>
|
||||
{t('global.fields')}
|
||||
</a>
|
||||
<Link
|
||||
passHref
|
||||
href='/farm'
|
||||
className={classNames(
|
||||
!FIELDS_FEATURE && styles.disabled,
|
||||
styles.nav,
|
||||
router.pathname.includes('farm') && styles.active,
|
||||
router.pathname === '/farm' && styles.unclickable,
|
||||
)}
|
||||
>
|
||||
{t('global.fields')}
|
||||
</Link>
|
||||
<a className={styles.nav} href={networkConfig?.councilUrl} target='_blank' rel='noreferrer'>
|
||||
{t('global.council')}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { ExecuteResult } from '@cosmjs/cosmwasm-stargate'
|
||||
import { ChainInfoID, SimpleChainInfoList } from '@marsprotocol/wallet-connector'
|
||||
import { ChainInfoID, SimpleChainInfoList, TxBroadcastResult } from '@marsprotocol/wallet-connector'
|
||||
import { useQueryClient } from '@tanstack/react-query'
|
||||
import classNames from 'classnames'
|
||||
import { AnimatedNumber, Button, DisplayCurrency, SVG, Tooltip, TxLink } from 'components/common'
|
||||
@ -38,7 +37,7 @@ export const IncentivesButton = () => {
|
||||
const [showDetails, setShowDetails] = useState(false)
|
||||
const [disabled, setDisabled] = useState(true)
|
||||
const [submitted, setSubmitted] = useState(false)
|
||||
const [response, setResponse] = useState<ExecuteResult>()
|
||||
const [response, setResponse] = useState<TxBroadcastResult>()
|
||||
const [error, setError] = useState<string>()
|
||||
const [hasUnclaimedRewards, setHasUnclaimedRewards] = useState(false)
|
||||
|
||||
@ -77,7 +76,7 @@ export const IncentivesButton = () => {
|
||||
setSubmitted(false)
|
||||
return
|
||||
}
|
||||
if (response?.transactionHash) {
|
||||
if (response?.hash) {
|
||||
setDisabled(true)
|
||||
setSubmitted(false)
|
||||
return
|
||||
@ -156,8 +155,8 @@ export const IncentivesButton = () => {
|
||||
<div className={`${styles.container} ${styles.info}`}>
|
||||
<p className='m'>{t('incentives.successfullyClaimed')}</p>
|
||||
<TxLink
|
||||
hash={response?.transactionHash || ''}
|
||||
link={`${explorerUrl}txs/${response?.transactionHash}`}
|
||||
hash={response?.hash || ''}
|
||||
link={`${explorerUrl}txs/${response?.hash}`}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useWallet, WalletConnectionStatus } from '@marsprotocol/wallet-connector'
|
||||
import { useWalletManager, WalletConnectionStatus } from '@marsprotocol/wallet-connector'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import classNames from 'classnames/bind'
|
||||
import classNames from 'classnames'
|
||||
import { Button, NumberInput, SVG, Toggle, Tooltip } from 'components/common'
|
||||
import React, { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -19,11 +19,11 @@ export const Settings = () => {
|
||||
const [inputRef, setInputRef] = useState<React.RefObject<HTMLInputElement>>()
|
||||
const [isCustom, setIsCustom] = useState(false)
|
||||
const enableAnimations = useStore((s) => s.enableAnimations)
|
||||
const { status } = useWallet()
|
||||
const { status } = useWalletManager()
|
||||
|
||||
const onInputChange = (value: number) => {
|
||||
setCustomSlippage(value.toString())
|
||||
if (value.toString() === '') {
|
||||
if (!value.toString()) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import classNames from 'classnames/bind'
|
||||
import classNames from 'classnames'
|
||||
import { ReactNode } from 'react'
|
||||
|
||||
import styles from './Highlight.module.scss'
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useWallet, WalletConnectionStatus } from '@marsprotocol/wallet-connector'
|
||||
import { useWalletManager, WalletConnectionStatus } from '@marsprotocol/wallet-connector'
|
||||
import classNames from 'classnames'
|
||||
import { Footer, Header, MobileNav } from 'components/common'
|
||||
import { FieldsNotConnected } from 'components/fields'
|
||||
@ -21,13 +21,11 @@ export const Layout = ({ children }: Props) => {
|
||||
const enableAnimations = useStore((s) => s.enableAnimations)
|
||||
const backgroundClasses = classNames('background', !userWalletAddress && 'night')
|
||||
const vaultConfigs = useStore((s) => s.vaultConfigs)
|
||||
const wallet = useWallet()
|
||||
const wasConnectedBefore = !!localStorage.getItem(SESSION_WALLET_KEY)
|
||||
const connectionSuccess = !!(
|
||||
(wallet.status === WalletConnectionStatus.Connecting && wasConnectedBefore) ||
|
||||
wallet.status === WalletConnectionStatus.Connected
|
||||
)
|
||||
const isConnected = !!userWalletAddress || connectionSuccess
|
||||
const { status } = useWalletManager()
|
||||
const isConnected = status === WalletConnectionStatus.Connected
|
||||
const wasConnectedBefore =
|
||||
localStorage.getItem(SESSION_WALLET_KEY) !== null &&
|
||||
localStorage.getItem(SESSION_WALLET_KEY) !== '[]'
|
||||
|
||||
useEffect(() => {
|
||||
if (!userWalletAddress) {
|
||||
@ -41,7 +39,7 @@ export const Layout = ({ children }: Props) => {
|
||||
<Header />
|
||||
<div className='appContainer'>
|
||||
<div className='widthBox'>
|
||||
{isConnected ? (
|
||||
{isConnected || wasConnectedBefore ? (
|
||||
<div className={'body'}>{children}</div>
|
||||
) : router.route.includes('farm') ? (
|
||||
<FieldsNotConnected />
|
||||
|
@ -14,21 +14,25 @@ export const MobileNav = () => {
|
||||
|
||||
return (
|
||||
<nav className={styles.mobileNav}>
|
||||
<Link href='/redbank' passHref>
|
||||
<a className={classNames(styles.nav, !router.pathname.includes('farm') && styles.active)}>
|
||||
<SVG.RedBankIcon />
|
||||
<span>{t('global.redBank')}</span>
|
||||
</a>
|
||||
<Link
|
||||
href='/redbank'
|
||||
passHref
|
||||
className={classNames(styles.nav, !router.pathname.includes('farm') && styles.active)}
|
||||
>
|
||||
<SVG.RedBankIcon />
|
||||
<span>{t('global.redBank')}</span>
|
||||
</Link>
|
||||
<a className={styles.nav} target='_blank' href={networkConfig?.councilUrl} rel='noreferrer'>
|
||||
<SVG.CouncilIcon />
|
||||
<span>{t('global.council')}</span>
|
||||
</a>
|
||||
<Link href='/farm' passHref>
|
||||
<a className={classNames(styles.nav, router.pathname.includes('farm') && styles.active)}>
|
||||
<SVG.FieldsIcon />
|
||||
<span>{t('global.fields')}</span>
|
||||
</a>
|
||||
<Link
|
||||
href='/farm'
|
||||
passHref
|
||||
className={classNames(styles.nav, router.pathname.includes('farm') && styles.active)}
|
||||
>
|
||||
<SVG.FieldsIcon />
|
||||
<span>{t('global.fields')}</span>
|
||||
</Link>
|
||||
</nav>
|
||||
)
|
||||
|
@ -110,7 +110,7 @@ export const NumberInput = (props: Props) => {
|
||||
return
|
||||
}
|
||||
|
||||
if (value === '') {
|
||||
if (!value) {
|
||||
updateValues(value, 0)
|
||||
return
|
||||
}
|
||||
|
23
src/components/common/TextTooltip/TextTooltip.tsx
Normal file
23
src/components/common/TextTooltip/TextTooltip.tsx
Normal file
@ -0,0 +1,23 @@
|
||||
import Tippy from '@tippyjs/react'
|
||||
|
||||
interface Props {
|
||||
text: string
|
||||
tooltip: string
|
||||
}
|
||||
export const TextTooltip = (props: Props) => {
|
||||
return (
|
||||
<Tippy
|
||||
appendTo={() => document.body}
|
||||
animation={false}
|
||||
render={(attrs) => {
|
||||
return (
|
||||
<div className='tippyContainer' {...attrs}>
|
||||
{props.tooltip}
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
>
|
||||
<div>{props.text}</div>
|
||||
</Tippy>
|
||||
)
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
@import 'src/styles/master';
|
||||
|
||||
.container {
|
||||
position: fixed;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@include layoutTooltip;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import Tippy from '@tippyjs/react'
|
||||
import classNames from 'classnames/bind'
|
||||
import classNames from 'classnames'
|
||||
import { SVG } from 'components/common'
|
||||
import { ReactNode } from 'react'
|
||||
|
||||
|
@ -1,15 +1,14 @@
|
||||
import { ExecuteResult } from '@cosmjs/cosmwasm-stargate'
|
||||
import { decodeTxRaw } from '@cosmjs/proto-signing'
|
||||
import { Coin } from '@cosmjs/stargate'
|
||||
import { Card } from 'components/common'
|
||||
import { TxFailedContent, TxSuccessContent } from 'components/common'
|
||||
import { TxBroadcastResult } from '@marsprotocol/wallet-connector'
|
||||
import { Card, TxFailedContent, TxSuccessContent } from 'components/common'
|
||||
import { getFeeFromResponse } from 'functions'
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import useStore from 'store'
|
||||
import { TxStatus } from 'types/enums/RedBankAction'
|
||||
|
||||
interface Props {
|
||||
response?: ExecuteResult
|
||||
response?: TxBroadcastResult
|
||||
error?: string
|
||||
title: string
|
||||
actions?: FieldsAction[]
|
||||
@ -33,18 +32,18 @@ export const TxResponse = ({
|
||||
const rpc = useStore((s) => s.chainInfo?.rpc)
|
||||
const chainID = useStore((s) => s.chainInfo?.chainId)
|
||||
const client = useStore((s) => s.client)
|
||||
const baseCurrency = useStore((s) => s.baseCurrency)
|
||||
|
||||
useEffect(() => {
|
||||
const getTxInfo = async (hash: string) => {
|
||||
const getTxInfo = async (hash?: string) => {
|
||||
if (txStatus !== TxStatus.LOADING) return
|
||||
if (!rpc || !chainID) return
|
||||
if (!rpc || !chainID || !hash || !response) return
|
||||
|
||||
try {
|
||||
const txInfoResponse = await client?.getTx(hash)
|
||||
const coin = getFeeFromResponse(response)
|
||||
|
||||
if (txInfoResponse) {
|
||||
const decoded = decodeTxRaw(txInfoResponse?.tx)
|
||||
setTxFee(decoded.authInfo.fee?.amount[0])
|
||||
if (coin) {
|
||||
setTxFee(coin)
|
||||
}
|
||||
|
||||
setTxStatus(TxStatus.SUCCESS)
|
||||
@ -56,8 +55,8 @@ export const TxResponse = ({
|
||||
}
|
||||
}
|
||||
|
||||
getTxInfo(response?.transactionHash || '')
|
||||
}, [client, response, rpc, chainID, checkTxStatus, onSuccess, txStatus])
|
||||
getTxInfo(response?.hash || undefined)
|
||||
}, [client, response, rpc, chainID, checkTxStatus, onSuccess, txStatus, baseCurrency.denom])
|
||||
|
||||
// reset scroll
|
||||
useEffect(() => {
|
||||
@ -79,7 +78,7 @@ export const TxResponse = ({
|
||||
{txStatus === TxStatus.FAILURE ? (
|
||||
<TxFailedContent
|
||||
handleClose={handleClose}
|
||||
hash={response?.transactionHash || ''}
|
||||
hash={response?.response.transactionHash || ''}
|
||||
message={error}
|
||||
/>
|
||||
) : (
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { ExecuteResult } from '@cosmjs/cosmwasm-stargate'
|
||||
import { Coin } from '@cosmjs/stargate'
|
||||
import { ChainInfoID, SimpleChainInfoList } from '@marsprotocol/wallet-connector'
|
||||
import { Button, TxFee, TxLink } from 'components/common'
|
||||
import { InfoTitle } from 'components/common'
|
||||
import { ChainInfoID, SimpleChainInfoList, TxBroadcastResult } from '@marsprotocol/wallet-connector'
|
||||
import { Button, InfoTitle, TxFee, TxLink } from 'components/common'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import useStore from 'store'
|
||||
import { TxStatus } from 'types/enums/RedBankAction'
|
||||
@ -11,7 +9,7 @@ import styles from './TxSuccessContent.module.scss'
|
||||
|
||||
interface Props {
|
||||
title: string
|
||||
response?: ExecuteResult
|
||||
response?: TxBroadcastResult | null
|
||||
txFee?: Coin
|
||||
txStatus: TxStatus
|
||||
actions: { label: string; values: string[] }[]
|
||||
@ -68,8 +66,8 @@ export const TxSuccessContent = ({
|
||||
<div className={styles.item}>
|
||||
<div className={styles.label}>{t('common.txHash')}</div>
|
||||
<TxLink
|
||||
hash={response?.transactionHash || ''}
|
||||
link={`${explorerUrl}txs/${response?.transactionHash}`}
|
||||
hash={response?.response.transactionHash || ''}
|
||||
link={`${explorerUrl}txs/${response?.response.transactionHash}`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -28,6 +28,7 @@ export { MobileNav } from './MobileNav/MobileNav'
|
||||
export { Notification } from './Notification/Notification'
|
||||
export { NumberInput } from './NumberInput/NumberInput'
|
||||
export { SVG } from './SVG/SVG'
|
||||
export { TextTooltip } from './TextTooltip/TextTooltip'
|
||||
export { Title } from './Title/Title'
|
||||
export { Toggle } from './Toggle/Toggle'
|
||||
export { TokenBalance } from './TokenBalance/TokenBalance'
|
||||
|
@ -1,5 +1,17 @@
|
||||
@import 'src/styles/master';
|
||||
|
||||
$color: ':nth-child(1)';
|
||||
$logo: ':nth-child(2)';
|
||||
$name: ':nth-child(3)';
|
||||
$posValue: ':nth-child(4)';
|
||||
$netValue: ':nth-child(5)';
|
||||
$borrowValue: ':nth-child(6)';
|
||||
$vaultCap: ':nth-child(7)';
|
||||
$apy: ':nth-child(8)';
|
||||
$leverage: ':nth-child(9)';
|
||||
$borrowCapacity: ':nth-child(10)';
|
||||
$actions: ':nth-child(11)';
|
||||
|
||||
.table {
|
||||
display: none;
|
||||
@include margin(0, 0, 6, 0);
|
||||
@ -32,13 +44,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Not color indicator
|
||||
&:not(:first-child) {
|
||||
&:not(#{$color}) {
|
||||
@include padding(4, 2);
|
||||
}
|
||||
|
||||
// Name
|
||||
&:nth-child(3) {
|
||||
&#{$name} {
|
||||
@include padding(4, 2, 4, 0);
|
||||
}
|
||||
}
|
||||
@ -64,24 +74,15 @@
|
||||
.td {
|
||||
position: relative;
|
||||
|
||||
// Logos
|
||||
&:nth-child(2) {
|
||||
&#{$logo} {
|
||||
width: rem-calc(64);
|
||||
}
|
||||
|
||||
// Not color indicator
|
||||
&:not(:first-child) {
|
||||
&:not(#{$color}) {
|
||||
@include padding(0, 2);
|
||||
}
|
||||
|
||||
// Name
|
||||
&:nth-child(3) {
|
||||
text-align: left;
|
||||
@include padding(0, 2, 0, 0);
|
||||
}
|
||||
|
||||
// Leverage
|
||||
&:nth-child(3) {
|
||||
&#{$name} {
|
||||
text-align: left;
|
||||
@include padding(0, 2, 0, 0);
|
||||
}
|
||||
@ -92,11 +93,9 @@
|
||||
.table {
|
||||
.td,
|
||||
.th {
|
||||
// Leverage
|
||||
&:nth-child(5),
|
||||
&:nth-child(6),
|
||||
&:nth-child(8),
|
||||
&:nth-child(9) {
|
||||
&#{$vaultCap},
|
||||
&#{$borrowValue},
|
||||
&#{$leverage} {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ export const ActiveVaultsTable = () => {
|
||||
title={t('fields.activeVaults')}
|
||||
hideHeaderBorder
|
||||
styleOverride={{ marginBottom: 40 }}
|
||||
tooltip={<Trans i18nKey='fields.tooltips.activeVaults' />}
|
||||
tooltip={<Trans i18nKey='fields.tooltips.activeVaults.desktop' />}
|
||||
>
|
||||
<table className={styles.table}>
|
||||
<thead className={styles.thead}>
|
||||
|
@ -4,6 +4,11 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.link {
|
||||
color: unset;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: rem-calc(64) 1fr 1fr;
|
||||
|
@ -1,8 +1,8 @@
|
||||
import Tippy from '@tippyjs/react'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import { BorrowCapacity, Card, DisplayCurrency } from 'components/common'
|
||||
import { AnimatedNumber, Apy, BorrowCapacity, Card, DisplayCurrency } from 'components/common'
|
||||
import { VaultLogo, VaultName } from 'components/fields'
|
||||
import { FIELDS_TUTORIAL_KEY } from 'constants/appConstants'
|
||||
import { formatValue } from 'libs/parse'
|
||||
import Link from 'next/link'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import useStore from 'store'
|
||||
@ -45,7 +45,7 @@ export const ActiveVaultsTableMobile = () => {
|
||||
<Card
|
||||
title={t('fields.activeVaults')}
|
||||
styleOverride={{ marginBottom: 40 }}
|
||||
tooltip={<Trans i18nKey='fields.tooltips.activeVaults' />}
|
||||
tooltip={<Trans i18nKey='fields.tooltips.activeVaults.mobile' />}
|
||||
>
|
||||
<div className={styles.container}>
|
||||
{activeVaults.map((vault, i) => {
|
||||
@ -55,24 +55,39 @@ export const ActiveVaultsTableMobile = () => {
|
||||
<VaultLogo vault={vault} />
|
||||
</div>
|
||||
<div className={styles.name}>{getVaultSubText(vault)}</div>
|
||||
|
||||
<div className={styles.position}>
|
||||
<DisplayCurrency
|
||||
coin={{
|
||||
denom: baseCurrency.denom,
|
||||
amount: vault.position.values.total.toString(),
|
||||
}}
|
||||
className={'xl'}
|
||||
/>
|
||||
<div className='xl' onClick={(e) => e.preventDefault()}>
|
||||
<span className='faded'>{t('common.apy')} </span>
|
||||
<span>
|
||||
<Tippy
|
||||
content={
|
||||
<Apy
|
||||
apyData={{
|
||||
borrow: vault.position.apy.borrow,
|
||||
total: vault.position.apy.total,
|
||||
}}
|
||||
leverage={vault.position.currentLeverage}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<span className='tooltip xl'>
|
||||
<AnimatedNumber amount={vault.position.apy.net} className='xl' suffix='%' />
|
||||
</span>
|
||||
</Tippy>
|
||||
</span>
|
||||
</div>
|
||||
<div className='s'>
|
||||
<span className='faded'>{t('common.debt')} </span>
|
||||
<span className='faded'>{t('fields.positionValueShort')} </span>
|
||||
<DisplayCurrency
|
||||
coin={{
|
||||
denom: baseCurrency.denom,
|
||||
amount: vault.position.values.borrowed.toString(),
|
||||
amount: vault.position.values.total.toString(),
|
||||
}}
|
||||
className={styles.inline}
|
||||
className={`s ${styles.inline}`}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='s'>
|
||||
<span className='faded'>{t('common.net')} </span>
|
||||
<DisplayCurrency
|
||||
@ -84,20 +99,18 @@ export const ActiveVaultsTableMobile = () => {
|
||||
/>
|
||||
</div>
|
||||
<div className='s'>
|
||||
<span className='faded'>{t('fields.leverage')} </span>
|
||||
{new BigNumber(vault.position.currentLeverage).toPrecision(3)}
|
||||
<span className='faded'>{t('common.debt')} </span>
|
||||
<DisplayCurrency
|
||||
coin={{
|
||||
denom: baseCurrency.denom,
|
||||
amount: vault.position.values.borrowed.toString(),
|
||||
}}
|
||||
className={styles.inline}
|
||||
/>
|
||||
</div>
|
||||
<div className='s'>
|
||||
<span className='faded'>{t('fields.vaultCap')} </span>
|
||||
|
||||
{formatValue(
|
||||
(vault.vaultCap?.max || 0) / 10 ** baseCurrency.decimals,
|
||||
0,
|
||||
0,
|
||||
true,
|
||||
'',
|
||||
` ${baseCurrency.symbol}`,
|
||||
)}
|
||||
<span className='faded'>{t('fields.leverage')} </span>
|
||||
{new BigNumber(vault.position.currentLeverage).toPrecision(3)}
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.borrowCapacity}>
|
||||
@ -124,6 +137,7 @@ export const ActiveVaultsTableMobile = () => {
|
||||
href={`/farm/vault/${vault.address}/${
|
||||
vault.position.status === 'active' ? 'edit' : 'close'
|
||||
}`}
|
||||
className={styles.link}
|
||||
>
|
||||
<div>{content}</div>
|
||||
</Link>
|
||||
|
@ -1,20 +1,28 @@
|
||||
import { ColumnDef, createColumnHelper } from '@tanstack/react-table'
|
||||
import Tippy from '@tippyjs/react'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import classNames from 'classnames/bind'
|
||||
import classNames from 'classnames'
|
||||
import {
|
||||
AnimatedNumber,
|
||||
Apy,
|
||||
BorrowCapacity,
|
||||
Button,
|
||||
DisplayCurrency,
|
||||
SVG,
|
||||
TextTooltip,
|
||||
TokenBalance,
|
||||
} from 'components/common'
|
||||
import { VaultLogo, VaultName } from 'components/fields'
|
||||
import { VAULT_DEPOSIT_BUFFER } from 'constants/appConstants'
|
||||
import { convertPercentage } from 'functions'
|
||||
import { getLiqBorrowValue, getMaxBorrowValue } from 'functions/fields'
|
||||
import { convertApyToDailyApy, formatUnlockDate, formatValue, ltvToLeverage } from 'libs/parse'
|
||||
import {
|
||||
convertApyToDailyApy,
|
||||
formatUnlockDate,
|
||||
formatValue,
|
||||
getTimeAndUnit,
|
||||
ltvToLeverage,
|
||||
} from 'libs/parse'
|
||||
import { useRouter } from 'next/router'
|
||||
import { ReactNode, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -43,11 +51,38 @@ export const useActiveVaultsColumns = () => {
|
||||
columnHelper.accessor('name', {
|
||||
enableSorting: true,
|
||||
header: t('fields.position'),
|
||||
cell: ({ row }) => <VaultName vault={row.original} />,
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<Tippy
|
||||
appendTo={() => document.body}
|
||||
animation={false}
|
||||
render={(attrs) => {
|
||||
return (
|
||||
<div className='tippyContainer' {...attrs}>
|
||||
{t('fields.tooltips.name', {
|
||||
asset1: row.original.symbols.primary,
|
||||
asset2: row.original.symbols.secondary,
|
||||
...getTimeAndUnit(row.original.lockup),
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<VaultName vault={row.original} />
|
||||
</div>
|
||||
</Tippy>
|
||||
)
|
||||
},
|
||||
}),
|
||||
columnHelper.accessor('position.values.total', {
|
||||
enableSorting: true,
|
||||
header: t('fields.positionValueShort'),
|
||||
header: () => (
|
||||
<TextTooltip
|
||||
text={t('fields.positionValueShort')}
|
||||
tooltip={t('fields.tooltips.positionValue')}
|
||||
/>
|
||||
),
|
||||
cell: ({ row }) => {
|
||||
const primaryCoin = {
|
||||
denom: row.original.denoms.primary,
|
||||
@ -89,7 +124,9 @@ export const useActiveVaultsColumns = () => {
|
||||
}),
|
||||
columnHelper.accessor('position.values.primary', {
|
||||
enableSorting: true,
|
||||
header: t('fields.netValue'),
|
||||
header: () => (
|
||||
<TextTooltip text={t('fields.netValue')} tooltip={t('fields.tooltips.netValue')} />
|
||||
),
|
||||
cell: ({ row }) => {
|
||||
const position = row.original.position
|
||||
const netValue = position.values.primary + position.values.secondary
|
||||
@ -129,7 +166,9 @@ export const useActiveVaultsColumns = () => {
|
||||
}),
|
||||
columnHelper.accessor('position.values.borrowed', {
|
||||
enableSorting: true,
|
||||
header: t('common.borrowed'),
|
||||
header: () => (
|
||||
<TextTooltip text={t('common.borrowed')} tooltip={t('fields.tooltips.borrowValue')} />
|
||||
),
|
||||
cell: (info) => {
|
||||
const borrowAsset = whitelistedAssets.find(
|
||||
(asset) => asset.denom === info.row.original.denoms.secondary,
|
||||
@ -169,7 +208,9 @@ export const useActiveVaultsColumns = () => {
|
||||
}),
|
||||
columnHelper.accessor('vaultCap', {
|
||||
enableSorting: true,
|
||||
header: t('fields.vaultCap'),
|
||||
header: () => (
|
||||
<TextTooltip text={t('fields.vaultCap')} tooltip={t('fields.tooltips.vaultCap')} />
|
||||
),
|
||||
cell: ({ row }) => {
|
||||
if (!row.original.vaultCap) {
|
||||
return null
|
||||
@ -217,7 +258,9 @@ export const useActiveVaultsColumns = () => {
|
||||
columnHelper.accessor('position.apy', {
|
||||
id: 'apy',
|
||||
enableSorting: true,
|
||||
header: t('common.apy'),
|
||||
header: () => (
|
||||
<TextTooltip text={t('common.apy')} tooltip={t('fields.tooltips.apy.active')} />
|
||||
),
|
||||
cell: ({ row }) => {
|
||||
switch (row.original.position.status) {
|
||||
case 'unlocked':
|
||||
@ -228,13 +271,28 @@ export const useActiveVaultsColumns = () => {
|
||||
</>
|
||||
)
|
||||
case 'active':
|
||||
const apy = new BigNumber(row.original.position.apy).decimalPlaces(2).toNumber()
|
||||
const apy = new BigNumber(row.original.position.apy.net).decimalPlaces(2).toNumber()
|
||||
|
||||
const apyData = {
|
||||
total: row.original.apy || 0,
|
||||
borrow: row.original.position.apy.borrow,
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<AnimatedNumber amount={apy} className='m' suffix='%' />
|
||||
<p className='s faded'>
|
||||
{convertApyToDailyApy(row.original.position.apy)}%/{t('common.day')}
|
||||
</p>
|
||||
<Tippy
|
||||
appendTo={() => document.body}
|
||||
animation={false}
|
||||
content={
|
||||
<Apy apyData={apyData} leverage={row.original.position.currentLeverage} />
|
||||
}
|
||||
>
|
||||
<span className='tooltip'>
|
||||
<AnimatedNumber amount={apy} className='m' suffix='%' />
|
||||
<p className='s faded'>
|
||||
{convertApyToDailyApy(row.original.position.apy.net)}%/{t('common.day')}
|
||||
</p>
|
||||
</span>
|
||||
</Tippy>
|
||||
</>
|
||||
)
|
||||
case 'unlocking':
|
||||
@ -242,7 +300,6 @@ export const useActiveVaultsColumns = () => {
|
||||
<>
|
||||
<p className='m'>{t('fields.unlocking')}</p>
|
||||
<p className='s faded'>
|
||||
{/* {new Date(row.original.position?.unlockAtTimestamp || 0).} */}
|
||||
{formatUnlockDate(row.original.position?.unlockAtTimestamp || 0)}
|
||||
</p>
|
||||
</>
|
||||
@ -252,7 +309,9 @@ export const useActiveVaultsColumns = () => {
|
||||
}),
|
||||
columnHelper.accessor('ltv', {
|
||||
enableSorting: true,
|
||||
header: t('fields.leverage'),
|
||||
header: () => (
|
||||
<TextTooltip text={t('fields.leverage')} tooltip={t('fields.tooltips.leverage.active')} />
|
||||
),
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<>
|
||||
@ -275,7 +334,12 @@ export const useActiveVaultsColumns = () => {
|
||||
}),
|
||||
columnHelper.accessor('position.amounts.borrowed', {
|
||||
enableSorting: false,
|
||||
header: t('common.borrowingCapacity'),
|
||||
header: () => (
|
||||
<TextTooltip
|
||||
text={t('common.borrowingCapacity')}
|
||||
tooltip={t('fields.tooltips.borrowCapacity')}
|
||||
/>
|
||||
),
|
||||
cell: ({ row }) => {
|
||||
const maxBorrowValue = getMaxBorrowValue(row.original, row.original.position)
|
||||
|
||||
|
@ -47,8 +47,6 @@ $action: ':nth-child(9)';
|
||||
}
|
||||
}
|
||||
|
||||
$number: 1;
|
||||
|
||||
&:not(#{$color}) {
|
||||
@include padding(4, 2);
|
||||
}
|
||||
@ -111,7 +109,7 @@ $action: ':nth-child(9)';
|
||||
&#{$description} {
|
||||
text-align: left;
|
||||
width: rem-calc(300);
|
||||
@include padding(0, 2, 0, 0);
|
||||
@include padding(2, 2, 2, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ export const AvailableVaultsTable = () => {
|
||||
title={t('fields.availableVaults')}
|
||||
hideHeaderBorder
|
||||
styleOverride={{ marginBottom: 40 }}
|
||||
tooltip={<Trans i18nKey='fields.tooltips.activeVaults' />}
|
||||
tooltip={<Trans i18nKey='fields.tooltips.availableVaults.desktop' />}
|
||||
>
|
||||
<table className={styles.table}>
|
||||
<thead className={styles.thead}>
|
||||
@ -68,7 +68,7 @@ export const AvailableVaultsTable = () => {
|
||||
const wrapperClasses = classes({
|
||||
wrapper: true,
|
||||
left: header.id === 'name' || header.id === 'description',
|
||||
center: header.id === 'provider_name',
|
||||
center: header.id === 'provider',
|
||||
})
|
||||
|
||||
return (
|
||||
|
@ -4,6 +4,15 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.inline {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.link {
|
||||
color: unset;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: rem-calc(64) 1fr 1fr;
|
||||
|
@ -1,7 +1,9 @@
|
||||
import Tippy from '@tippyjs/react'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import { AnimatedNumber, Card } from 'components/common'
|
||||
import { AnimatedNumber, Apy, Card, DisplayCurrency } from 'components/common'
|
||||
import { VaultLogo, VaultName } from 'components/fields'
|
||||
import { formatValue, ltvToLeverage } from 'libs/parse'
|
||||
import { getTimeAndUnit, ltvToLeverage } from 'libs/parse'
|
||||
import Link from 'next/link'
|
||||
import React from 'react'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
import useStore from 'store'
|
||||
@ -12,6 +14,7 @@ export const AvailableVaultsTableMobile = () => {
|
||||
const { t } = useTranslation()
|
||||
const availableVaults = useStore((s) => s.availableVaults)
|
||||
const baseCurrency = useStore((s) => s.baseCurrency)
|
||||
const redBankAssets = useStore((s) => s.redBankAssets)
|
||||
|
||||
if (!availableVaults?.length) return null
|
||||
|
||||
@ -19,49 +22,78 @@ export const AvailableVaultsTableMobile = () => {
|
||||
<Card
|
||||
title={t('fields.availableVaults')}
|
||||
styleOverride={{ marginBottom: 40 }}
|
||||
tooltip={<Trans i18nKey='fields.tooltips.availableVaults' />}
|
||||
tooltip={<Trans i18nKey='fields.tooltips.availableVaults.mobile' />}
|
||||
>
|
||||
<div className={styles.container}>
|
||||
{availableVaults.map((vault, i) => {
|
||||
const minAPY = new BigNumber(vault.apy || 0).decimalPlaces(2).toNumber()
|
||||
const maxAPY = new BigNumber(minAPY).times(ltvToLeverage(vault.ltv.max)).toNumber()
|
||||
const borrowAsset = redBankAssets.find((asset) => asset.denom === vault.denoms.secondary)
|
||||
const maxBorrowRate = Number(borrowAsset?.borrowRate ?? 0) * vault.ltv.max
|
||||
const minAPY = new BigNumber(vault.apy || 0).toNumber()
|
||||
|
||||
const leverage = ltvToLeverage(vault.ltv.max)
|
||||
const maxAPY =
|
||||
new BigNumber(minAPY).times(leverage).decimalPlaces(2).toNumber() - maxBorrowRate
|
||||
const apyDataNoLev = { total: vault.apy || 0, borrow: 0 }
|
||||
const apyDataLev = { total: vault.apy || 0, borrow: maxBorrowRate }
|
||||
return (
|
||||
<div className={styles.grid} key={`${vault.address}-${i}`}>
|
||||
<div className={styles.logo}>
|
||||
<VaultLogo vault={vault} />
|
||||
</div>
|
||||
<div className={styles.name}>
|
||||
<VaultName vault={vault} />
|
||||
</div>
|
||||
<div className={styles.stats}>
|
||||
<div className='xl'>
|
||||
<span className='faded'>{t('common.apy')} </span>
|
||||
<span>
|
||||
<AnimatedNumber amount={minAPY} suffix='-' />
|
||||
<AnimatedNumber amount={maxAPY} suffix='%' />
|
||||
</span>
|
||||
<Link
|
||||
key={`${vault.address}-${i}`}
|
||||
href={`/farm/vault/${vault.address}/create`}
|
||||
className={styles.link}
|
||||
>
|
||||
<div className={styles.grid} key={`${vault.address}-${i}`}>
|
||||
<div className={styles.logo}>
|
||||
<VaultLogo vault={vault} />
|
||||
</div>
|
||||
<div className='s'>
|
||||
<span className='faded'>{t('fields.leverage')} </span>
|
||||
<AnimatedNumber amount={leverage} suffix='x' />
|
||||
<div className={styles.name}>
|
||||
<VaultName vault={vault} />
|
||||
</div>
|
||||
<div className='s'>
|
||||
<span className='faded'>{t('fields.vaultCap')} </span>
|
||||
<span>
|
||||
{formatValue(
|
||||
(vault.vaultCap?.max || 0) / 10 ** baseCurrency.decimals,
|
||||
0,
|
||||
0,
|
||||
true,
|
||||
'',
|
||||
' ' + baseCurrency.symbol,
|
||||
)}
|
||||
</span>
|
||||
<div className={styles.stats}>
|
||||
<div onClick={(e) => e.preventDefault()} className='xl'>
|
||||
<span className='faded'>{t('common.apy')} </span>
|
||||
<span>
|
||||
<Tippy content={<Apy apyData={apyDataNoLev} leverage={1} />}>
|
||||
<span className='tooltip xl'>
|
||||
<AnimatedNumber amount={minAPY} suffix='-' />
|
||||
</span>
|
||||
</Tippy>
|
||||
<Tippy
|
||||
content={
|
||||
<Apy apyData={apyDataLev} leverage={ltvToLeverage(vault.ltv.max)} />
|
||||
}
|
||||
>
|
||||
<span className='tooltip xl'>
|
||||
<AnimatedNumber amount={maxAPY} suffix='%' />
|
||||
</span>
|
||||
</Tippy>
|
||||
</span>
|
||||
</div>
|
||||
<div className='s'>
|
||||
<span className='faded'>{t('fields.leverage')} </span>
|
||||
<AnimatedNumber amount={leverage} suffix='x' />
|
||||
</div>
|
||||
<div className='s'>
|
||||
<span className='faded'>{t('fields.vaultCap')} </span>
|
||||
<span>
|
||||
<DisplayCurrency
|
||||
coin={{
|
||||
denom: baseCurrency.denom,
|
||||
amount: (vault.vaultCap?.max || 0).toString(),
|
||||
}}
|
||||
className={styles.inline}
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.description}>
|
||||
{t('fields.tooltips.name', {
|
||||
asset1: vault.symbols.primary,
|
||||
asset2: vault.symbols.secondary,
|
||||
...getTimeAndUnit(vault.lockup),
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.description}>{vault.description}</div>
|
||||
</div>
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
@ -4,6 +4,6 @@
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: rem-calc(7);
|
||||
height: space(16);
|
||||
height: 100%;
|
||||
margin-left: rem-calc(-7);
|
||||
}
|
||||
|
@ -1,12 +1,20 @@
|
||||
import { ColumnDef, createColumnHelper } from '@tanstack/react-table'
|
||||
import Tippy from '@tippyjs/react'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import classNames from 'classnames/bind'
|
||||
import { AnimatedNumber, Button, DisplayCurrency, SVG, TokenBalance } from 'components/common'
|
||||
import classNames from 'classnames'
|
||||
import {
|
||||
AnimatedNumber,
|
||||
Apy,
|
||||
Button,
|
||||
DisplayCurrency,
|
||||
SVG,
|
||||
TextTooltip,
|
||||
TokenBalance,
|
||||
} from 'components/common'
|
||||
import { VaultLogo, VaultName } from 'components/fields'
|
||||
import { VAULT_DEPOSIT_BUFFER } from 'constants/appConstants'
|
||||
import { convertPercentage } from 'functions'
|
||||
import { convertApyToDailyApy, formatValue, ltvToLeverage } from 'libs/parse'
|
||||
import { convertApyToDailyApy, formatValue, getTimeAndUnit, ltvToLeverage } from 'libs/parse'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@ -19,6 +27,8 @@ export const useAvailableVaultsColumns = () => {
|
||||
const router = useRouter()
|
||||
const baseCurrency = useStore((s) => s.baseCurrency)
|
||||
const columnHelper = createColumnHelper<Vault>()
|
||||
const redBankAssets = useStore((s) => s.redBankAssets)
|
||||
|
||||
const defaultAvailableVaultsColumns: ColumnDef<Vault, any>[] = useMemo(
|
||||
() => [
|
||||
columnHelper.accessor('color', {
|
||||
@ -33,12 +43,39 @@ export const useAvailableVaultsColumns = () => {
|
||||
}),
|
||||
columnHelper.accessor('name', {
|
||||
enableSorting: true,
|
||||
header: t('fields.position'),
|
||||
cell: ({ row }) => <VaultName vault={row.original} />,
|
||||
header: t('fields.name'),
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<Tippy
|
||||
appendTo={() => document.body}
|
||||
animation={false}
|
||||
render={(attrs) => {
|
||||
return (
|
||||
<div className='tippyContainer' {...attrs}>
|
||||
{t('fields.tooltips.name', {
|
||||
asset1: row.original.symbols.primary,
|
||||
asset2: row.original.symbols.secondary,
|
||||
...getTimeAndUnit(row.original.lockup),
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<VaultName vault={row.original} />
|
||||
</div>
|
||||
</Tippy>
|
||||
)
|
||||
},
|
||||
}),
|
||||
columnHelper.accessor('ltv', {
|
||||
enableSorting: true,
|
||||
header: t('fields.leverage'),
|
||||
header: () => (
|
||||
<TextTooltip
|
||||
text={t('fields.leverage')}
|
||||
tooltip={t('fields.tooltips.leverage.available')}
|
||||
/>
|
||||
),
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<>
|
||||
@ -53,16 +90,22 @@ export const useAvailableVaultsColumns = () => {
|
||||
columnHelper.accessor('apy', {
|
||||
id: 'apy',
|
||||
enableSorting: true,
|
||||
header: t('common.apy'),
|
||||
header: () => (
|
||||
<TextTooltip text={t('common.apy')} tooltip={t('fields.tooltips.apy.available')} />
|
||||
),
|
||||
cell: ({ row }) => {
|
||||
if (!row.original.apy) {
|
||||
return null
|
||||
}
|
||||
|
||||
const maxLeverage = ltvToLeverage(row.original.ltv.max)
|
||||
|
||||
const borrowAsset = redBankAssets.find(
|
||||
(asset) => asset.denom === row.original.denoms.secondary,
|
||||
)
|
||||
const maxBorrowRate = Number(borrowAsset?.borrowRate ?? 0) * row.original.ltv.max
|
||||
const minAPY = new BigNumber(row.original.apy).decimalPlaces(2).toNumber()
|
||||
const maxAPY = new BigNumber(minAPY).times(maxLeverage).decimalPlaces(2).toNumber()
|
||||
|
||||
const maxAPY = new BigNumber(minAPY).times(maxLeverage).toNumber() - maxBorrowRate
|
||||
const minDailyAPY = new BigNumber(convertApyToDailyApy(row.original.apy))
|
||||
.decimalPlaces(2)
|
||||
.toNumber()
|
||||
@ -70,13 +113,27 @@ export const useAvailableVaultsColumns = () => {
|
||||
.times(maxLeverage)
|
||||
.decimalPlaces(2)
|
||||
.toNumber()
|
||||
const apyDataNoLev = { total: row.original.apy || 0, borrow: 0 }
|
||||
const apyDataLev = { total: row.original.apy || 0, borrow: maxBorrowRate }
|
||||
|
||||
return (
|
||||
<>
|
||||
<p className='m'>
|
||||
<AnimatedNumber amount={minAPY} />
|
||||
<span>-</span>
|
||||
<AnimatedNumber amount={maxAPY} suffix='%' />
|
||||
</p>
|
||||
<Tippy content={<Apy apyData={apyDataNoLev} leverage={1} />}>
|
||||
<span className='tooltip m'>
|
||||
<AnimatedNumber amount={minAPY} />
|
||||
</span>
|
||||
</Tippy>
|
||||
<span>-</span>
|
||||
<Tippy
|
||||
content={
|
||||
<Apy apyData={apyDataLev} leverage={ltvToLeverage(row.original.ltv.max)} />
|
||||
}
|
||||
>
|
||||
<span className='tooltip ,'>
|
||||
<AnimatedNumber amount={maxAPY} suffix='%' />
|
||||
</span>
|
||||
</Tippy>
|
||||
|
||||
<p className='s faded'>
|
||||
{minDailyAPY}-{maxDailyAPY}%/
|
||||
{t('common.day')}
|
||||
@ -87,7 +144,9 @@ export const useAvailableVaultsColumns = () => {
|
||||
}),
|
||||
columnHelper.accessor('vaultCap', {
|
||||
enableSorting: true,
|
||||
header: t('fields.vaultCap'),
|
||||
header: () => (
|
||||
<TextTooltip text={t('fields.vaultCap')} tooltip={t('fields.tooltips.vaultCap')} />
|
||||
),
|
||||
cell: ({ row }) => {
|
||||
if (!row.original.vaultCap) {
|
||||
return null
|
||||
@ -140,7 +199,25 @@ export const useAvailableVaultsColumns = () => {
|
||||
columnHelper.accessor('description', {
|
||||
enableSorting: true,
|
||||
header: t('common.description'),
|
||||
cell: ({ row }) => <p>{row.original.description}</p>,
|
||||
cell: ({ row }) => (
|
||||
<Tippy
|
||||
appendTo={() => document.body}
|
||||
animation={false}
|
||||
render={(attrs) => {
|
||||
return (
|
||||
<div className='tippyContainer' {...attrs}>
|
||||
{t('fields.tooltips.name', {
|
||||
asset1: row.original.symbols.primary,
|
||||
asset2: row.original.symbols.secondary,
|
||||
...getTimeAndUnit(row.original.lockup),
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
>
|
||||
<p>{row.original.description}</p>
|
||||
</Tippy>
|
||||
),
|
||||
}),
|
||||
columnHelper.display({
|
||||
id: 'actions',
|
||||
|
@ -1,4 +1,4 @@
|
||||
import classNames from 'classnames/bind'
|
||||
import classNames from 'classnames'
|
||||
import { BreakdownGraph, BreakdownTable } from 'components/fields'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
@ -1,5 +1,5 @@
|
||||
import Tippy from '@tippyjs/react'
|
||||
import classNames from 'classnames/bind'
|
||||
import classNames from 'classnames'
|
||||
|
||||
import styles from './AssetBar.module.scss'
|
||||
|
||||
@ -12,11 +12,11 @@ interface Props {
|
||||
}
|
||||
|
||||
export const AssetBar = (props: Props) => {
|
||||
const labelClasses = classNames([
|
||||
const labelClasses = classNames(
|
||||
styles.label,
|
||||
props.alignRight && styles.alignRight,
|
||||
props.showLabel ? styles.show : styles.hide,
|
||||
])
|
||||
)
|
||||
return (
|
||||
<Tippy
|
||||
content={
|
||||
|
@ -1,8 +1,7 @@
|
||||
import classNames from 'classnames/bind'
|
||||
import classNames from 'classnames'
|
||||
import { DisplayCurrency } from 'components/common'
|
||||
import { AssetBar } from 'components/fields'
|
||||
import { lookup } from 'libs/parse'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import useStore from 'store'
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import Tippy from '@tippyjs/react'
|
||||
import classNames from 'classnames/bind'
|
||||
import classNames from 'classnames'
|
||||
import {
|
||||
AnimatedNumber,
|
||||
Apy,
|
||||
|
@ -1,16 +1,13 @@
|
||||
import { ExecuteResult } from '@cosmjs/cosmwasm-stargate'
|
||||
import { TxResponse } from 'components/common'
|
||||
import { useFieldsActionMessages } from 'hooks/data'
|
||||
import { useRouter } from 'next/router'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import useStore from 'store'
|
||||
|
||||
import styles from './ClosePositionResponse.module.scss'
|
||||
|
||||
interface Props {
|
||||
data?: ExecuteResult
|
||||
error: Error | null
|
||||
data?: ResultData
|
||||
isLoading: boolean
|
||||
accountId: string
|
||||
}
|
||||
@ -20,7 +17,7 @@ export const ClosePositionResponse = (props: Props) => {
|
||||
const router = useRouter()
|
||||
const getVaults = useStore((s) => s.getVaults)
|
||||
|
||||
const { repayMessage, withdrawMessage } = useFieldsActionMessages(props.data)
|
||||
const { repayMessage, withdrawMessage } = useFieldsActionMessages(props.data?.result)
|
||||
|
||||
const actions = [
|
||||
...(repayMessage ? [repayMessage] : []),
|
||||
@ -30,12 +27,12 @@ export const ClosePositionResponse = (props: Props) => {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<TxResponse
|
||||
error={props.error?.message}
|
||||
error={props.data?.error}
|
||||
handleClose={() => router.replace('/farm')}
|
||||
onSuccess={() => {
|
||||
getVaults({ refetch: true })
|
||||
}}
|
||||
response={props.data}
|
||||
response={props.data?.result}
|
||||
title={t('fields.txMessages.close')}
|
||||
actions={actions}
|
||||
/>
|
||||
|
@ -1,40 +1,38 @@
|
||||
import { ExecuteResult } from '@cosmjs/cosmwasm-stargate'
|
||||
import { TxResponse } from 'components/common'
|
||||
import { useFieldsActionMessages } from 'hooks/data'
|
||||
import { useRouter } from 'next/router'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import useStore from 'store'
|
||||
|
||||
import styles from './EditResponse.module.scss'
|
||||
|
||||
interface Props {
|
||||
data?: ExecuteResult
|
||||
error: Error | null
|
||||
data?: ResultData
|
||||
isLoading: boolean
|
||||
activeVault: ActiveVault
|
||||
}
|
||||
|
||||
export const EditResponse = (props: Props) => {
|
||||
const { t } = useTranslation()
|
||||
const getVaults = useStore((s) => s.getVaults)
|
||||
const router = useRouter()
|
||||
const { depositMessage, borrowMessage, swapMessage } = useFieldsActionMessages(props.data)
|
||||
const getVaults = useStore((s) => s.getVaults)
|
||||
const { depositMessage, borrowMessage, swapMessage } = useFieldsActionMessages(props.data?.result)
|
||||
|
||||
const actions = [
|
||||
...(depositMessage ? [depositMessage] : []),
|
||||
...(borrowMessage ? [borrowMessage] : []),
|
||||
...(swapMessage ? [swapMessage] : []),
|
||||
]
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<TxResponse
|
||||
error={props.error?.message}
|
||||
error={props.data?.error}
|
||||
handleClose={() => router.replace('/farm')}
|
||||
onSuccess={() => {
|
||||
getVaults({ refetch: true })
|
||||
}}
|
||||
response={props.data}
|
||||
response={props.data?.result}
|
||||
title={t('fields.txMessages.edit')}
|
||||
actions={actions}
|
||||
/>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import classNames from 'classnames/bind'
|
||||
import classNames from 'classnames'
|
||||
import { Tutorial } from 'components/common'
|
||||
import { TokenInput } from 'components/fields'
|
||||
import { FIELDS_TUTORIAL_KEY } from 'constants/appConstants'
|
||||
|
@ -1,5 +1,5 @@
|
||||
import BigNumber from 'bignumber.js'
|
||||
import classNames from 'classnames/bind'
|
||||
import classNames from 'classnames'
|
||||
import { InputSlider, Tutorial } from 'components/common'
|
||||
import { FIELDS_TUTORIAL_KEY } from 'constants/appConstants'
|
||||
import { formatValue, ltvToLeverage } from 'libs/parse'
|
||||
|
@ -1,4 +1,4 @@
|
||||
import classNames from 'classnames/bind'
|
||||
import classNames from 'classnames'
|
||||
import { Button, SVG, Tutorial } from 'components/common'
|
||||
import { TokenInput } from 'components/fields'
|
||||
import { FIELDS_TUTORIAL_KEY } from 'constants/appConstants'
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Coin } from '@cosmjs/proto-signing'
|
||||
import classNames from 'classnames/bind'
|
||||
import classNames from 'classnames'
|
||||
import { Button, DisplayCurrency, NumberInput } from 'components/common'
|
||||
import { findByDenom } from 'functions'
|
||||
import { useAsset } from 'hooks/data'
|
||||
|
@ -1,16 +1,13 @@
|
||||
import { ExecuteResult } from '@cosmjs/cosmwasm-stargate'
|
||||
import { TxResponse } from 'components/common'
|
||||
import { useFieldsActionMessages } from 'hooks/data'
|
||||
import { useRouter } from 'next/router'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import useStore from 'store'
|
||||
|
||||
import styles from './RepayResponse.module.scss'
|
||||
|
||||
interface Props {
|
||||
data?: ExecuteResult
|
||||
error: Error | null
|
||||
data?: ResultData
|
||||
isLoading: boolean
|
||||
vault: ActiveVault
|
||||
}
|
||||
@ -19,19 +16,19 @@ export const RepayResponse = (props: Props) => {
|
||||
const { t } = useTranslation()
|
||||
const getVaults = useStore((s) => s.getVaults)
|
||||
const router = useRouter()
|
||||
const { repayMessage } = useFieldsActionMessages(props.data)
|
||||
const { repayMessage } = useFieldsActionMessages(props.data?.result)
|
||||
|
||||
const actions = [...(repayMessage ? [repayMessage] : [])]
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<TxResponse
|
||||
error={props.error?.message}
|
||||
error={props.data?.error}
|
||||
handleClose={() => router.replace('/farm')}
|
||||
onSuccess={() => {
|
||||
getVaults({ refetch: true })
|
||||
}}
|
||||
response={props.data}
|
||||
response={props.data?.result}
|
||||
title={t('fields.txMessages.repay')}
|
||||
actions={actions}
|
||||
/>
|
||||
|
@ -1,16 +1,13 @@
|
||||
import { ExecuteResult } from '@cosmjs/cosmwasm-stargate'
|
||||
import { TxResponse } from 'components/common'
|
||||
import { useFieldsActionMessages } from 'hooks/data'
|
||||
import { useRouter } from 'next/router'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import useStore from 'store'
|
||||
|
||||
import styles from './SetUpResponse.module.scss'
|
||||
|
||||
interface Props {
|
||||
data?: ExecuteResult
|
||||
error: Error | null
|
||||
data?: ResultData
|
||||
isLoading: boolean
|
||||
accountId: string
|
||||
}
|
||||
@ -18,8 +15,8 @@ interface Props {
|
||||
export const SetUpResponse = (props: Props) => {
|
||||
const { t } = useTranslation()
|
||||
const router = useRouter()
|
||||
const { depositMessage, borrowMessage, swapMessage } = useFieldsActionMessages(props.data)
|
||||
const getVaults = useStore((s) => s.getVaults)
|
||||
const { depositMessage, borrowMessage, swapMessage } = useFieldsActionMessages(props.data?.result)
|
||||
|
||||
const actions = [
|
||||
...(depositMessage ? [depositMessage] : []),
|
||||
@ -30,12 +27,12 @@ export const SetUpResponse = (props: Props) => {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<TxResponse
|
||||
error={props.error?.message}
|
||||
error={props.data?.error}
|
||||
handleClose={() => router.replace('/farm')}
|
||||
onSuccess={() => {
|
||||
getVaults({ refetch: true })
|
||||
}}
|
||||
response={props.data}
|
||||
response={props.data?.result}
|
||||
title={t('fields.txMessages.setup')}
|
||||
actions={actions}
|
||||
/>
|
||||
|
@ -1,16 +1,13 @@
|
||||
import { ExecuteResult } from '@cosmjs/cosmwasm-stargate'
|
||||
import { TxResponse } from 'components/common'
|
||||
import { useFieldsActionMessages } from 'hooks/data'
|
||||
import { useRouter } from 'next/router'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import useStore from 'store'
|
||||
|
||||
import styles from './UnlockResponse.module.scss'
|
||||
|
||||
interface Props {
|
||||
data?: ExecuteResult
|
||||
error: Error | null
|
||||
data?: ResultData
|
||||
isLoading: boolean
|
||||
activeVault: ActiveVault
|
||||
}
|
||||
@ -19,15 +16,15 @@ export const UnlockResponse = (props: Props) => {
|
||||
const { t } = useTranslation()
|
||||
const getVaults = useStore((s) => s.getVaults)
|
||||
const router = useRouter()
|
||||
const { unlockMessages } = useFieldsActionMessages(props.data, props.activeVault)
|
||||
const { unlockMessages } = useFieldsActionMessages(props.data?.result, props.activeVault)
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<TxResponse
|
||||
error={props.error?.message}
|
||||
error={props.data?.error}
|
||||
handleClose={() => router.replace('/farm')}
|
||||
onSuccess={() => getVaults({ refetch: true })}
|
||||
response={props.data}
|
||||
response={props.data?.result}
|
||||
title={t('fields.txMessages.unlock')}
|
||||
actions={unlockMessages}
|
||||
/>
|
||||
|
@ -58,7 +58,7 @@ export const ActionsRow = ({ row, type }: Props) => {
|
||||
<div className='tippyContainer' {...attrs}>
|
||||
{t('redbank.toDepositAssetOnChain', {
|
||||
asset: assetSymbol,
|
||||
chain: chainInfo?.chainName,
|
||||
chain: chainInfo?.name,
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
|
@ -27,7 +27,7 @@ export const useBorrowColumns = () => {
|
||||
header: '',
|
||||
cell: (info) => (
|
||||
<div className={styles.logo}>
|
||||
<Image alt='logo' height='100%' src={info.getValue().src} width='100%' />
|
||||
<Image alt='logo' src={info.getValue().src} width={32} height={32} />
|
||||
</div>
|
||||
),
|
||||
}),
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { ColumnDef, createColumnHelper } from '@tanstack/react-table'
|
||||
import Tippy from '@tippyjs/react'
|
||||
import classNames from 'classnames/bind'
|
||||
import classNames from 'classnames'
|
||||
import { AnimatedNumber, Apr, Button, CellAmount, SVG } from 'components/common'
|
||||
import { convertPercentage } from 'functions'
|
||||
import { formatValue } from 'libs/parse'
|
||||
@ -32,7 +32,7 @@ export const useDepositColumns = () => {
|
||||
header: '',
|
||||
cell: (info) => (
|
||||
<div className={styles.logo}>
|
||||
<Image alt='logo' height='100%' src={info.getValue().src} width='100%' />
|
||||
<Image alt='logo' src={info.getValue().src} width={32} height={32} />
|
||||
</div>
|
||||
),
|
||||
}),
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ExecuteResult } from '@cosmjs/cosmwasm-stargate'
|
||||
import { TxBroadcastResult } from '@marsprotocol/wallet-connector'
|
||||
import { useQueryClient } from '@tanstack/react-query'
|
||||
import { Action, Notification, TxResponse } from 'components/common'
|
||||
import { findByDenom } from 'functions'
|
||||
@ -13,8 +13,7 @@ import { ltvWeightedDepositValue, maintainanceMarginWeightedDepositValue } from
|
||||
import { lookup, lookupDecimals } from 'libs/parse'
|
||||
import isEqual from 'lodash.isequal'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useMemo, useState } from 'react'
|
||||
import React from 'react'
|
||||
import React, { useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import useStore from 'store'
|
||||
import { NotificationType, ViewType } from 'types/enums'
|
||||
@ -54,7 +53,7 @@ export const RedbankAction = React.memo(
|
||||
// ------------------
|
||||
const [amount, setAmount] = useState(0)
|
||||
const [submitted, setSubmitted] = useState(false)
|
||||
const [response, setResponse] = useState<ExecuteResult>()
|
||||
const [response, setResponse] = useState<TxBroadcastResult>()
|
||||
const [error, setError] = useState<string>()
|
||||
const [isMax, setIsMax] = useState<boolean>(false)
|
||||
const [capHit, setCapHit] = useState<boolean>(false)
|
||||
@ -126,7 +125,7 @@ export const RedbankAction = React.memo(
|
||||
funds:
|
||||
activeView === ViewType.Deposit || activeView === ViewType.Repay
|
||||
? [{ denom, amount: amount > 0 ? amount.toFixed(0) : '1' }]
|
||||
: [],
|
||||
: undefined,
|
||||
contract: redBankContractAddress,
|
||||
})
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ChainInfoID } from '@marsprotocol/wallet-connector'
|
||||
import { ChainInfoID, WalletID } from '@marsprotocol/wallet-connector'
|
||||
import atom from 'images/atom.svg'
|
||||
import axlusdc from 'images/axlusdc.svg'
|
||||
import juno from 'images/juno.svg'
|
||||
@ -63,9 +63,9 @@ const OTHER_ASSETS: { [denom: string]: OtherAsset } = {
|
||||
|
||||
export const NETWORK_CONFIG: NetworkConfig = {
|
||||
name: ChainInfoID.OsmosisTestnet,
|
||||
hiveUrl: 'https://osmosis-delphi-testnet-1.simply-vc.com.mt/XF32UOOU55CX/osmosis-hive/graphql',
|
||||
rpcUrl: 'https://osmosis-delphi-testnet-1.simply-vc.com.mt/XF32UOOU55CX/osmosis-rpc',
|
||||
restUrl: 'https://osmosis-delphi-testnet-1.simply-vc.com.mt/XF32UOOU55CX/osmosis-lcd',
|
||||
hiveUrl: 'https://osmosis-delphi-testnet-1.simply-vc.com.mt/XF32UOOU55CX/osmosis-hive/graphql/',
|
||||
rpcUrl: 'https://osmosis-delphi-testnet-1.simply-vc.com.mt/XF32UOOU55CX/osmosis-rpc/',
|
||||
restUrl: 'https://osmosis-delphi-testnet-1.simply-vc.com.mt/XF32UOOU55CX/osmosis-lcd/',
|
||||
apolloAprUrl: 'https://stats.apollo.farm/api/apr/v1/all',
|
||||
contracts: {
|
||||
addressProvider: 'osmo17dyy6hyzzy6u5khy5lau7afa2y9kwknu0aprwqn8twndw2qhv8ls6msnjr',
|
||||
@ -76,8 +76,8 @@ export const NETWORK_CONFIG: NetworkConfig = {
|
||||
treasury: 'osmo1qv74pu0gjc9vuvkhayuj5j3q8fzmf4pnl643djqpv7enxr925g5q0wf7p3',
|
||||
safetyFund: 'osmo1j2mnzs7eqld4umtwky4hyf6f7kqcsg7ragh2l76ev7ucxcjvdjrs3tdezf',
|
||||
protocolRewardsCollector: 'osmo1xl7jguvkg807ya00s0l722nwcappfzyzrac3ug5tnjassnrmnfrs47wguz',
|
||||
creditManager: 'osmo1prwnxn3vlvh0kqmwxn8whqnavk8ze9hrccwpsapysgpa3pj8r2csy84grp',
|
||||
accountNft: 'osmo1ua5rw84jxg6e7ma4hx7v7yhqcks74cjnx38gpnsvtfzrtxhwcvjqgsxulx',
|
||||
creditManager: 'osmo169xhpftsee275j3cjudj6qfzdpfp8sdllgeeprud4ynwr4sj6m4qel2ezp',
|
||||
accountNft: 'osmo1xpgx06z2c6zjk49feq75swgv78m6dvht6wramu2gltzjz5j959nq4hggxz',
|
||||
},
|
||||
assets: {
|
||||
base: ASSETS.osmo,
|
||||
@ -85,7 +85,8 @@ export const NETWORK_CONFIG: NetworkConfig = {
|
||||
other: [OTHER_ASSETS.mars, OTHER_ASSETS.axlusdc],
|
||||
},
|
||||
appUrl: 'https://testnet.osmosis.zone',
|
||||
councilUrl: 'https://testnet.keplr.app/chains/mars-protocol-testnet',
|
||||
councilUrl: 'https://testnet.keplr.app/chains/mars-hub-testnet',
|
||||
wallets: [WalletID.Keplr, WalletID.Leap, WalletID.Cosmostation],
|
||||
}
|
||||
|
||||
export const VAULT_CONFIGS: Vault[] = [
|
||||
@ -104,7 +105,8 @@ export const VAULT_CONFIGS: Vault[] = [
|
||||
color: '#DD5B65',
|
||||
lockup: 86400,
|
||||
provider: 'Apollo vault',
|
||||
description: 'Up to 2× Leveraged Yield Farming with auto compounding of the LP tokens.',
|
||||
description:
|
||||
'Up to 2.67× leveraged yield farming with auto compounding of the OSMO-ATOM LP tokens.',
|
||||
ltv: {
|
||||
max: 0.625,
|
||||
contract: 0.63,
|
||||
@ -126,7 +128,8 @@ export const VAULT_CONFIGS: Vault[] = [
|
||||
color: '#DD5B65',
|
||||
lockup: 86400 * 14,
|
||||
provider: 'Apollo vault',
|
||||
description: 'Up to 2× Leveraged Yield Farming with auto compounding of the LP tokens.',
|
||||
description:
|
||||
'Up to 2.67× leveraged yield farming with auto compounding of the OSMO-ATOM LP tokens.',
|
||||
ltv: {
|
||||
max: 0.625,
|
||||
contract: 0.63,
|
||||
@ -148,7 +151,8 @@ export const VAULT_CONFIGS: Vault[] = [
|
||||
color: '#DD5B65',
|
||||
lockup: 86400 * 1,
|
||||
provider: 'Apollo vault',
|
||||
description: 'Up to 2× Leveraged Yield Farming with auto compounding of the LP tokens.',
|
||||
description:
|
||||
'Up to 1.67× leveraged yield farming with auto compounding of the OSMO-JUNO LP tokens.',
|
||||
ltv: {
|
||||
max: 0.4,
|
||||
contract: 0.4115,
|
||||
@ -170,7 +174,8 @@ export const VAULT_CONFIGS: Vault[] = [
|
||||
color: '#DD5B65',
|
||||
lockup: 86400 * 14,
|
||||
provider: 'Apollo vault',
|
||||
description: 'Up to 2× Leveraged Yield Farming with auto compounding of the LP tokens.',
|
||||
description:
|
||||
'Up to 1.67× leveraged yield farming with auto compounding of the OSMO-JUNO LP tokens.',
|
||||
ltv: {
|
||||
max: 0.4,
|
||||
contract: 4.115,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ChainInfoID } from '@marsprotocol/wallet-connector'
|
||||
import { ChainInfoID, WalletID } from '@marsprotocol/wallet-connector'
|
||||
import atom from 'images/atom.svg'
|
||||
import axlusdc from 'images/axlusdc.svg'
|
||||
import mars from 'images/mars.svg'
|
||||
@ -50,9 +50,9 @@ const OTHER_ASSETS: { [denom: string]: OtherAsset } = {
|
||||
|
||||
export const NETWORK_CONFIG: NetworkConfig = {
|
||||
name: ChainInfoID.OsmosisTestnet,
|
||||
hiveUrl: 'https://osmosis-delphi-testnet-1.simply-vc.com.mt/XF32UOOU55CX/osmosis-hive/graphql',
|
||||
rpcUrl: 'https://osmosis-delphi-testnet-1.simply-vc.com.mt/XF32UOOU55CX/osmosis-rpc',
|
||||
restUrl: 'https://osmosis-delphi-testnet-1.simply-vc.com.mt/XF32UOOU55CX/osmosis-lcd',
|
||||
hiveUrl: 'https://osmosis-delphi-testnet-1.simply-vc.com.mt/XF32UOOU55CX/osmosis-hive/graphql/',
|
||||
rpcUrl: 'https://osmosis-delphi-testnet-1.simply-vc.com.mt/XF32UOOU55CX/osmosis-rpc/',
|
||||
restUrl: 'https://osmosis-delphi-testnet-1.simply-vc.com.mt/XF32UOOU55CX/osmosis-lcd/',
|
||||
apolloAprUrl: 'https://stats.apollo.farm/api/apr/v1/all',
|
||||
contracts: {
|
||||
addressProvider: 'osmo17dyy6hyzzy6u5khy5lau7afa2y9kwknu0aprwqn8twndw2qhv8ls6msnjr',
|
||||
@ -72,7 +72,8 @@ export const NETWORK_CONFIG: NetworkConfig = {
|
||||
other: [OTHER_ASSETS.mars],
|
||||
},
|
||||
appUrl: 'https://testnet.osmosis.zone',
|
||||
councilUrl: 'https://testnet.keplr.app/chains/mars-protocol-testnet',
|
||||
councilUrl: 'https://council.marsprotocol.io',
|
||||
wallets: [WalletID.Keplr, WalletID.Leap, WalletID.Cosmostation, WalletID.Falcon],
|
||||
}
|
||||
|
||||
export const VAULT_CONFIGS: Vault[] = [
|
||||
|
@ -11,7 +11,7 @@ export const DEFAULT_SLIPPAGE = 0.01
|
||||
|
||||
/* other */
|
||||
export const FEE_EST_AMOUNT = '1'
|
||||
export const SESSION_WALLET_KEY = 'walletConnection'
|
||||
export const SESSION_WALLET_KEY = 'shuttle'
|
||||
export const SWAP_THRESHOLD = 10
|
||||
export const VAULT_DEPOSIT_BUFFER = 0.99
|
||||
export const GAS_ADJUSTMENT = 1.3
|
||||
|
@ -19,7 +19,11 @@ export const DEFAULT_POSITION: Position = {
|
||||
total: 0,
|
||||
net: 0,
|
||||
},
|
||||
apy: 0,
|
||||
apy: {
|
||||
borrow: 5.2,
|
||||
net: 7.7,
|
||||
total: 19,
|
||||
},
|
||||
ltv: 0.5,
|
||||
currentLeverage: 1,
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,14 +0,0 @@
|
||||
import { ExecuteResult } from '@cosmjs/cosmwasm-stargate'
|
||||
|
||||
export const getAmountFromUnlockRes = (unlockData: ExecuteResult) => {
|
||||
const stringValue = unlockData?.logs[0].events
|
||||
.find((item) => item.type === 'coin_received')
|
||||
?.attributes.find((item) => item.key === 'amount')?.value
|
||||
|
||||
if (!stringValue) return ''
|
||||
|
||||
if (stringValue?.indexOf('ibc/') > 0) {
|
||||
return stringValue.split('ibc/')[0]
|
||||
}
|
||||
return stringValue.split('factory/')[0]
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import { findAssetByDenom, formatValue } from 'libs/parse'
|
||||
import { findAssetByDenom, formatValue, lookup } from 'libs/parse'
|
||||
import { Coin } from 'types/generated/mars-credit-manager/MarsCreditManager.types'
|
||||
|
||||
export const getTokenValueFromCoins = (assets: Asset[], coins: Coin[] = []) => {
|
||||
@ -7,6 +7,15 @@ export const getTokenValueFromCoins = (assets: Asset[], coins: Coin[] = []) => {
|
||||
|
||||
if (!asset) return ''
|
||||
|
||||
return `${formatValue(Number(token.amount) / 10 ** asset.decimals, 2, 2, true)} ${asset.symbol}`
|
||||
const convertedValue = lookup(Number(token.amount), asset.symbol, asset.decimals)
|
||||
|
||||
return formatValue(
|
||||
convertedValue,
|
||||
2,
|
||||
2,
|
||||
true,
|
||||
convertedValue >= 0.01 ? false : '>',
|
||||
` ${asset.symbol}`,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
// @index(['./*.ts'], f => `export { ${f.name} } from '${f.path}'`)
|
||||
export { coinsToActionCoins } from './coinsToActionCoins'
|
||||
export { getAmountFromUnlockRes } from './getAmountFromUnlockRes'
|
||||
export { getAmountsFromActiveVault } from './getAmountsFromActiveVault'
|
||||
export { getClosePositionActions } from './getClosePositionActions'
|
||||
export { getCoinFromPosition } from './getCoinFromPosition'
|
||||
|
15
src/functions/getFeeFromResponse.ts
Normal file
15
src/functions/getFeeFromResponse.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { Coin } from '@cosmjs/launchpad'
|
||||
import { TxBroadcastResult } from '@marsprotocol/wallet-connector'
|
||||
import { extractCoinFromLog } from 'libs/parse'
|
||||
|
||||
export const getFeeFromResponse = (response: TxBroadcastResult): Coin | null => {
|
||||
const stringValue = response?.response.events
|
||||
.filter((msg: Record<string, string>) => msg.type === 'tx')
|
||||
.map((msg: Record<string, string>) => msg.attributes)
|
||||
.flat()
|
||||
.find((msg: Record<string, string>) => msg.key === 'fee')?.value
|
||||
|
||||
if (!stringValue) return null
|
||||
|
||||
return extractCoinFromLog(stringValue)
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
export { convertPercentage } from './convertPercentage'
|
||||
export { findByDenom } from './findByDenom'
|
||||
export { formatToValueSymbol } from './formatToValueSymbol'
|
||||
export { getFeeFromResponse } from './getFeeFromResponse'
|
||||
export { getSwapUrl } from './getSwapUrl'
|
||||
export { updateExchangeRate } from './updateExchangeRate'
|
||||
// @endindex
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ExecuteResult } from '@cosmjs/cosmwasm-stargate'
|
||||
import { getAmountFromUnlockRes, getTokenValueFromCoins } from 'functions/fields'
|
||||
import { TxBroadcastResult } from '@marsprotocol/wallet-connector'
|
||||
import { getTokenValueFromCoins } from 'functions/fields'
|
||||
import { useUnlockMessages } from 'hooks/queries'
|
||||
import { extractCoinFromLog, parseActionMessages } from 'libs/parse'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
@ -8,7 +8,7 @@ import useStore from 'store'
|
||||
import { Coin } from 'types/generated/mars-credit-manager/MarsCreditManager.types'
|
||||
|
||||
export const useFieldsActionMessages = (
|
||||
data?: ExecuteResult,
|
||||
data?: TxBroadcastResult,
|
||||
vault?: ActiveVault,
|
||||
): {
|
||||
depositMessage?: FieldsAction
|
||||
@ -31,11 +31,9 @@ export const useFieldsActionMessages = (
|
||||
|
||||
const getDepositedCoins = useCallback((messages: unknown[]): Coin[] => {
|
||||
try {
|
||||
return (
|
||||
messages.filter(
|
||||
(message: any) => message?.action === 'rover/execute/update_credit_account',
|
||||
) as any
|
||||
).map((msg: any) => extractCoinFromLog(msg.coin_deposited))
|
||||
return (messages.filter((message: any) => message?.action === 'callback/deposit') as any).map(
|
||||
(msg: any) => extractCoinFromLog(msg.coin_deposited),
|
||||
)
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
@ -44,7 +42,7 @@ export const useFieldsActionMessages = (
|
||||
const getBorrowedCoins = useCallback((messages: any[]): Coin[] => {
|
||||
try {
|
||||
return (
|
||||
messages.filter((message: any) => message?.action === 'outposts/red-bank/borrow') as any
|
||||
messages.filter((message: any) => message?.action === 'borrow' && message?.denom) as any
|
||||
).map((msg: any) => ({ denom: msg.denom, amount: msg.amount }))
|
||||
} catch {
|
||||
return []
|
||||
@ -53,9 +51,9 @@ export const useFieldsActionMessages = (
|
||||
|
||||
const getSwapCoinIn = useCallback((messages: unknown[]): Coin | null => {
|
||||
try {
|
||||
return (
|
||||
messages.filter((message: any) => message?.action === 'rover/swapper/swap_fn') as any
|
||||
).map((msg: any) => ({ denom: msg.denom_in, amount: msg.amount_in }))[0]
|
||||
return (messages.filter((message: any) => message?.action === 'swap_fn') as any).map(
|
||||
(msg: any) => ({ denom: msg.denom_in, amount: msg.amount_in }),
|
||||
)[0]
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
@ -64,7 +62,7 @@ export const useFieldsActionMessages = (
|
||||
const getSwapCoinOut = useCallback((messages: unknown[]): Coin | null => {
|
||||
try {
|
||||
const coinsSwapOutIndex = messages.findIndex(
|
||||
(message: any) => message?.action === 'rover/swapper/transfer_result',
|
||||
(message: any) => message?.action === 'transfer_result',
|
||||
) as any
|
||||
|
||||
const msg: any = messages[coinsSwapOutIndex + 1]
|
||||
@ -80,8 +78,10 @@ export const useFieldsActionMessages = (
|
||||
const getRepayCoin = useCallback((messages: any[]): Coin | null => {
|
||||
try {
|
||||
return messages
|
||||
.filter((message: any) => message?.action === ('outposts/red-bank/repay' as any))
|
||||
.map((msg: any) => ({ denom: msg.denom, amount: msg.amount }))[0]
|
||||
.filter((message: any) => message?.action === ('repay' as any) && message?.denom)
|
||||
.map((msg: any) => {
|
||||
return { denom: msg.denom, amount: msg.amount }
|
||||
})[0]
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
@ -90,9 +90,7 @@ export const useFieldsActionMessages = (
|
||||
const getWithdrawnCoins = useCallback((messages: any[]): Coin[] => {
|
||||
try {
|
||||
return (
|
||||
messages.filter(
|
||||
(message: any) => message?.action === 'rover/credit-manager/callback/withdraw',
|
||||
) as any
|
||||
messages.filter((message: any) => message?.action === 'callback/withdraw') as any
|
||||
).map((msg: any) => {
|
||||
return extractCoinFromLog(msg.coin_withdrawn)
|
||||
})
|
||||
@ -101,6 +99,18 @@ export const useFieldsActionMessages = (
|
||||
}
|
||||
}, [])
|
||||
|
||||
const getVaultUnlockAmount = useCallback((messages: any[]): string | null => {
|
||||
try {
|
||||
return (
|
||||
messages.filter((message: any) => message?.action === 'vault/request_unlock') as any
|
||||
).map((msg: any) => {
|
||||
return msg.unlock_amount
|
||||
})[0]
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (!data) {
|
||||
return
|
||||
@ -117,9 +127,10 @@ export const useFieldsActionMessages = (
|
||||
const swapCoinOut = getSwapCoinOut(messages)
|
||||
const repayCoin = getRepayCoin(messages)
|
||||
const withdrawnCoins = getWithdrawnCoins(messages)
|
||||
const vaultUnlockAmount = getVaultUnlockAmount(messages)
|
||||
|
||||
if (!vaultTokenAmount) {
|
||||
setVaultTokenAmount(getAmountFromUnlockRes(data))
|
||||
if (!vaultTokenAmount && vaultUnlockAmount) {
|
||||
setVaultTokenAmount(vaultUnlockAmount)
|
||||
}
|
||||
|
||||
if (depositedCoins.length) {
|
||||
@ -170,6 +181,7 @@ export const useFieldsActionMessages = (
|
||||
getRepayCoin,
|
||||
getWithdrawnCoins,
|
||||
vaultTokenAmount,
|
||||
getVaultUnlockAmount,
|
||||
whitelistedAssets,
|
||||
])
|
||||
|
||||
|
@ -1,12 +1,32 @@
|
||||
import { StdFee } from '@cosmjs/stargate'
|
||||
import { useMutation } from '@tanstack/react-query'
|
||||
import { parseActionMessages } from 'libs/parse'
|
||||
import useStore from 'store'
|
||||
|
||||
export const useCreateCreditAccount = () => {
|
||||
const creditManagerClient = useStore((s) => s.creditManagerClient)
|
||||
const executeMsg = useStore((s) => s.executeMsg)
|
||||
const networkConfig = useStore((s) => s.networkConfig)
|
||||
|
||||
return useMutation(async (fee: StdFee) => {
|
||||
const executeResult = await creditManagerClient?.createCreditAccount(fee)
|
||||
return executeResult?.logs[0].events[2].attributes[6].value
|
||||
const message = { create_credit_account: {} }
|
||||
|
||||
if (!networkConfig) return null
|
||||
return executeMsg({
|
||||
msg: message,
|
||||
fee,
|
||||
contract: networkConfig.contracts.creditManager,
|
||||
}).then((broadcastResult) => {
|
||||
if (broadcastResult) {
|
||||
try {
|
||||
const messages = parseActionMessages(broadcastResult)
|
||||
|
||||
return (
|
||||
messages?.find(
|
||||
(message: Record<string, string>) => message?.action === 'mint',
|
||||
) as Record<string, string>
|
||||
)['token_id']
|
||||
} catch {}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -13,29 +13,33 @@ interface Props {
|
||||
|
||||
export const useUpdateAccount = () => {
|
||||
const queryClient = useQueryClient()
|
||||
const creditManagerClient = useStore((s) => s.creditManagerClient)
|
||||
const executeMsg = useStore((s) => s.executeMsg)
|
||||
const networkConfig = useStore((s) => s.networkConfig)
|
||||
const getVaults = useStore((s) => s.getVaults)
|
||||
|
||||
return useMutation(
|
||||
async (props: Props) => {
|
||||
queryClient.removeQueries([QUERY_KEYS.ESTIMATE_FARM_FEE])
|
||||
return creditManagerClient?.updateCreditAccount(
|
||||
{
|
||||
accountId: props.accountId,
|
||||
actions: props.actions,
|
||||
},
|
||||
props.fee,
|
||||
undefined,
|
||||
props.funds,
|
||||
)
|
||||
},
|
||||
{
|
||||
onSuccess: () => {
|
||||
return useMutation(async (props: Props) => {
|
||||
queryClient.removeQueries([QUERY_KEYS.ESTIMATE_FARM_FEE])
|
||||
const message = {
|
||||
update_credit_account: {
|
||||
account_id: props.accountId,
|
||||
actions: props.actions,
|
||||
},
|
||||
}
|
||||
|
||||
if (!networkConfig) return
|
||||
|
||||
return executeMsg({
|
||||
msg: message,
|
||||
fee: props.fee,
|
||||
contract: networkConfig.contracts.creditManager,
|
||||
funds: props.funds,
|
||||
}).then((broadcastResult) => {
|
||||
if (broadcastResult?.response.code === 0) {
|
||||
getVaults({ refetch: true })
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
return `${error.message}`
|
||||
},
|
||||
},
|
||||
)
|
||||
return { result: broadcastResult }
|
||||
} else {
|
||||
return { error: broadcastResult?.rawLogs }
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -16,4 +16,5 @@ export { useUnlockMessages } from './useUnlockMessages'
|
||||
export { useUserBalance } from './useUserBalance'
|
||||
export { useUserDebt } from './useUserDebt'
|
||||
export { useUserDeposit } from './useUserDeposit'
|
||||
export { useUserIcns } from './useUserIcns'
|
||||
// @endindex
|
||||
|
@ -9,7 +9,7 @@ import { Action, Coin } from 'types/generated/mars-credit-manager/MarsCreditMana
|
||||
import { useEstimateFarmFee } from './useEstimateFarmFee'
|
||||
|
||||
interface Props {
|
||||
accountId?: string
|
||||
accountId?: null | string
|
||||
prevPosition?: Position
|
||||
position: Position
|
||||
vault: Vault
|
||||
|
@ -1,14 +1,13 @@
|
||||
import { MsgExecuteContractEncodeObject } from '@cosmjs/cosmwasm-stargate'
|
||||
import { GasPrice } from '@cosmjs/stargate'
|
||||
import { MsgExecuteContract } from '@marsprotocol/wallet-connector'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import { GAS_ADJUSTMENT, GAS_PRICE } from 'constants/appConstants'
|
||||
import { GAS_ADJUSTMENT } from 'constants/appConstants'
|
||||
import useStore from 'store'
|
||||
import { QUERY_KEYS } from 'types/enums/queryKeys'
|
||||
import { Action, Coin } from 'types/generated/mars-credit-manager/MarsCreditManager.types'
|
||||
|
||||
interface Props {
|
||||
accountId?: string
|
||||
accountId?: null | string
|
||||
actions?: Action[]
|
||||
funds?: Coin[]
|
||||
isCreate?: boolean
|
||||
@ -17,44 +16,48 @@ interface Props {
|
||||
|
||||
export const useEstimateFarmFee = (props: Props) => {
|
||||
const userWalletAddress = useStore((s) => s.userWalletAddress)
|
||||
const creditManagerMsgComposer = useStore((s) => s.creditManagerMsgComposer)
|
||||
const client = useStore((s) => s.client)
|
||||
const networkConfig = useStore((s) => s.networkConfig)
|
||||
|
||||
return useQuery(
|
||||
[QUERY_KEYS.ESTIMATE_FARM_FEE, props.actions],
|
||||
async () => {
|
||||
const gasPrice = GasPrice.fromString(GAS_PRICE)
|
||||
const gasAdjustment = GAS_ADJUSTMENT
|
||||
|
||||
if (!creditManagerMsgComposer || !client) return null
|
||||
if (!client) return null
|
||||
|
||||
let msg: MsgExecuteContractEncodeObject | null = null
|
||||
|
||||
if (props.isCreate) {
|
||||
msg = creditManagerMsgComposer.createCreditAccount()
|
||||
} else if (props.accountId && props.actions?.length) {
|
||||
msg = creditManagerMsgComposer.updateCreditAccount(
|
||||
{
|
||||
accountId: props.accountId,
|
||||
actions: props.actions,
|
||||
},
|
||||
props.funds,
|
||||
)
|
||||
}
|
||||
|
||||
if (!msg) return null
|
||||
if (!networkConfig) return null
|
||||
|
||||
try {
|
||||
const gasUsed = await client.simulate(userWalletAddress, [msg], undefined)
|
||||
|
||||
const fee = new BigNumber(Number(gasPrice.amount))
|
||||
.multipliedBy(gasUsed)
|
||||
.multipliedBy(gasAdjustment)
|
||||
|
||||
return {
|
||||
amount: [{ denom: 'uosmo', amount: fee.toFixed(0) }],
|
||||
gas: new BigNumber(gasUsed).multipliedBy(gasAdjustment).toFixed(0),
|
||||
const simulateOptions = {
|
||||
messages: [
|
||||
new MsgExecuteContract({
|
||||
sender: userWalletAddress,
|
||||
contract: networkConfig.contracts.creditManager,
|
||||
msg: props.isCreate
|
||||
? { create_credit_account: {} }
|
||||
: {
|
||||
update_credit_account: {
|
||||
account_id: props.accountId,
|
||||
actions: props.actions,
|
||||
},
|
||||
},
|
||||
funds: props.funds,
|
||||
}),
|
||||
],
|
||||
wallet: client.recentWallet,
|
||||
}
|
||||
|
||||
const result = await client.simulate(simulateOptions)
|
||||
|
||||
return result.success
|
||||
? {
|
||||
amount: result.fee ? result.fee.amount : [],
|
||||
gas: new BigNumber(result.fee ? result.fee.gas : 0)
|
||||
.multipliedBy(gasAdjustment)
|
||||
.toFixed(0),
|
||||
}
|
||||
: null
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
@ -63,7 +66,6 @@ export const useEstimateFarmFee = (props: Props) => {
|
||||
enabled:
|
||||
!props.isLoading &&
|
||||
!!client &&
|
||||
!!creditManagerMsgComposer &&
|
||||
!!userWalletAddress &&
|
||||
(props.isCreate || (!!props.accountId && !!props.actions?.length)),
|
||||
},
|
||||
|
@ -1,10 +1,9 @@
|
||||
import { MsgExecuteContractEncodeObject } from '@cosmjs/cosmwasm-stargate'
|
||||
import { toUtf8 } from '@cosmjs/encoding'
|
||||
import { Coin } from '@cosmjs/proto-signing'
|
||||
import { GasPrice } from '@cosmjs/stargate'
|
||||
import { MsgExecuteContract } from '@marsprotocol/wallet-connector'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import { GAS_ADJUSTMENT, GAS_PRICE } from 'constants/appConstants'
|
||||
import { GAS_ADJUSTMENT } from 'constants/appConstants'
|
||||
import useStore from 'store'
|
||||
import { QUERY_KEYS } from 'types/enums/queryKeys'
|
||||
import { ContractMsg } from 'types/types'
|
||||
@ -22,37 +21,35 @@ export const useEstimateFee = (props: Props) => {
|
||||
const client = useStore((s) => s.client)
|
||||
|
||||
return useQuery(
|
||||
[QUERY_KEYS.ESTIMATE_FEE],
|
||||
[QUERY_KEYS.ESTIMATE_FEE, props.msg],
|
||||
async () => {
|
||||
const sender = props.sender ? props.sender : userWalletAddress
|
||||
const gasPrice = GasPrice.fromString(GAS_PRICE)
|
||||
const gasAdjustment = GAS_ADJUSTMENT
|
||||
|
||||
if (!client) return
|
||||
|
||||
const msg = props.executeMsg
|
||||
? props.executeMsg
|
||||
: {
|
||||
typeUrl: '/cosmwasm.wasm.v1.MsgExecuteContract',
|
||||
value: {
|
||||
sender: sender,
|
||||
contract: props.contract,
|
||||
msg: toUtf8(JSON.stringify(props.msg)),
|
||||
funds: props.funds,
|
||||
},
|
||||
}
|
||||
if (!client || !props.contract || !props.msg) return
|
||||
|
||||
try {
|
||||
const gasUsed = await client.simulate(sender, [msg], undefined)
|
||||
|
||||
const fee = new BigNumber(Number(gasPrice.amount))
|
||||
.multipliedBy(gasUsed)
|
||||
.multipliedBy(gasAdjustment)
|
||||
|
||||
return {
|
||||
amount: [{ denom: 'uosmo', amount: fee.toFixed(0) }],
|
||||
gas: new BigNumber(gasUsed).multipliedBy(gasAdjustment).toFixed(0),
|
||||
const simulateOptions = {
|
||||
messages: [
|
||||
new MsgExecuteContract({
|
||||
sender: sender,
|
||||
contract: props.contract,
|
||||
msg: props.msg,
|
||||
funds: props.funds,
|
||||
}),
|
||||
],
|
||||
wallet: client.recentWallet,
|
||||
}
|
||||
|
||||
const result = await client.simulate(simulateOptions)
|
||||
return result.success
|
||||
? {
|
||||
amount: result.fee ? result.fee.amount : [],
|
||||
gas: new BigNumber(result.fee ? result.fee.gas : 0)
|
||||
.multipliedBy(gasAdjustment)
|
||||
.toFixed(0),
|
||||
}
|
||||
: null
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
|
@ -11,13 +11,15 @@ interface Props {
|
||||
export const useProvideLiquidity = (props: Props) => {
|
||||
const creditManagerClient = useStore((s) => s.creditManagerClient)
|
||||
|
||||
return useQuery(
|
||||
return useQuery<number>(
|
||||
[QUERY_KEYS.PROVIDE_LIQUIDITY, props.coins],
|
||||
async () => {
|
||||
if (!creditManagerClient || !props.coins.length) return null
|
||||
return creditManagerClient.estimateProvideLiquidity({
|
||||
coinsIn: props.coins,
|
||||
lpTokenOut: props.vault?.denoms.lpToken || '',
|
||||
return creditManagerClient.query({
|
||||
estimate_provide_liquidity: {
|
||||
coins_in: props.coins,
|
||||
lp_token_out: props.vault?.denoms.lpToken || '',
|
||||
},
|
||||
})
|
||||
},
|
||||
{
|
||||
|
@ -5,7 +5,7 @@ import { useAsset } from 'hooks/data'
|
||||
import useStore from 'store'
|
||||
import { QUERY_KEYS } from 'types/enums/queryKeys'
|
||||
|
||||
const poolsEndpoint = '/osmosis/gamm/v1beta1/pools/'
|
||||
const poolsEndpoint = 'osmosis/gamm/v1beta1/pools/'
|
||||
|
||||
export const useSpotPrice = (symbol: string) => {
|
||||
const displayCurrency = useStore((s) => s.displayCurrency)
|
||||
|
@ -3,8 +3,8 @@ import { getTokenValueFromCoins } from 'functions/fields'
|
||||
import { formatUnlockDate } from 'libs/parse'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import useStore from 'store'
|
||||
import { VaultClient } from 'types/classes'
|
||||
import { QUERY_KEYS } from 'types/enums/queryKeys'
|
||||
import { MarsMockVaultClient } from 'types/generated/mars-mock-vault/MarsMockVault.client'
|
||||
|
||||
interface Props {
|
||||
vault?: ActiveVault
|
||||
@ -23,15 +23,19 @@ export const useUnlockMessages = (props: Props) => {
|
||||
async () => {
|
||||
if (!client || !userWalletAddress || !props.vault || !creditManagerClient) return null
|
||||
|
||||
const vaultClient = new MarsMockVaultClient(client, userWalletAddress, props.vault.address)
|
||||
const lpTokenAmount = await vaultClient.previewRedeem({
|
||||
amount: props.vaultTokenAmount,
|
||||
const vaultClient = new VaultClient(props.vault.address, client)
|
||||
const lpTokenAmount = await vaultClient.query({
|
||||
preview_redeem: {
|
||||
amount: props.vaultTokenAmount,
|
||||
},
|
||||
})
|
||||
|
||||
const lpToken = { denom: props.vault.denoms.lpToken, amount: lpTokenAmount }
|
||||
|
||||
const coins = await creditManagerClient.estimateWithdrawLiquidity({
|
||||
lpToken,
|
||||
const coins = await creditManagerClient.query({
|
||||
estimate_withdraw_liquidity: {
|
||||
lp_token: lpToken,
|
||||
},
|
||||
})
|
||||
|
||||
return [
|
||||
|
@ -3,6 +3,7 @@ import { useQuery } from '@tanstack/react-query'
|
||||
import { gql, request } from 'graphql-request'
|
||||
import { useMemo } from 'react'
|
||||
import useStore from 'store'
|
||||
import { QUERY_KEYS } from 'types/enums/queryKeys'
|
||||
|
||||
export interface UserBalanceData {
|
||||
balance: {
|
||||
@ -16,7 +17,7 @@ export const useUserBalance = () => {
|
||||
const processUserBalanceQuery = useStore((s) => s.processUserBalanceQuery)
|
||||
|
||||
const result = useQuery<UserBalanceData>(
|
||||
[],
|
||||
[QUERY_KEYS.USER_BALANCE],
|
||||
async () => {
|
||||
return await request(
|
||||
hiveUrl!,
|
||||
|
54
src/hooks/queries/useUserIcns.tsx
Normal file
54
src/hooks/queries/useUserIcns.tsx
Normal file
@ -0,0 +1,54 @@
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { gql, request } from 'graphql-request'
|
||||
import { useMemo } from 'react'
|
||||
import useStore from 'store'
|
||||
import { QUERY_KEYS } from 'types/enums/queryKeys'
|
||||
|
||||
export interface UserIcnsData {
|
||||
wasm: {
|
||||
contractQuery: {
|
||||
names: string[]
|
||||
primary_name: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const useUserIcns = () => {
|
||||
/* only possible to query on mainnet */
|
||||
const hiveUrl = 'https://osmosis-mars-frontend.simply-vc.com.mt/GGSFGSFGFG34/osmosis-hive/graphql'
|
||||
const resolverContract = 'osmo1xk0s8xgktn9x5vwcgtjdxqzadg88fgn33p8u9cnpdxwemvxscvast52cdd'
|
||||
|
||||
const userWalletAddress = useStore((s) => s.userWalletAddress)
|
||||
const setUserIcns = useStore((s) => s.setUserIcns)
|
||||
|
||||
const result = useQuery<UserIcnsData>(
|
||||
[QUERY_KEYS.USER_ICNS],
|
||||
async () => {
|
||||
return await request(
|
||||
hiveUrl!,
|
||||
gql`
|
||||
query UserIcnsQuery {
|
||||
wasm {
|
||||
contractQuery(contractAddress:"${resolverContract}", query: {
|
||||
icns_names:{
|
||||
address: "${userWalletAddress}"
|
||||
}
|
||||
})
|
||||
}
|
||||
}`,
|
||||
)
|
||||
},
|
||||
{
|
||||
enabled: !!userWalletAddress || false,
|
||||
onSuccess: (data) => {
|
||||
const icns = data.wasm.contractQuery.primary_name
|
||||
if (icns !== '') setUserIcns(icns)
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
return {
|
||||
...result,
|
||||
data: useMemo(() => result.data, [result.data]),
|
||||
}
|
||||
}
|
@ -3,6 +3,12 @@ import LanguageDetector from 'i18next-browser-languagedetector'
|
||||
import HttpApi from 'i18next-http-backend'
|
||||
import { initReactI18next } from 'react-i18next'
|
||||
|
||||
declare module 'i18next' {
|
||||
interface CustomTypeOptions {
|
||||
returnNull: false
|
||||
}
|
||||
}
|
||||
|
||||
i18next
|
||||
.use(HttpApi)
|
||||
.use(LanguageDetector)
|
||||
@ -11,7 +17,7 @@ i18next
|
||||
backend: {
|
||||
crossDomain: true,
|
||||
loadPath() {
|
||||
return 'https://raw.githubusercontent.com/mars-protocol/translations/develop/{{lng}}.json'
|
||||
return 'https://raw.githubusercontent.com/mars-protocol/translations/main/{{lng}}.json'
|
||||
},
|
||||
},
|
||||
react: {
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 7.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.2 KiB |
@ -1,4 +1,4 @@
|
||||
import { ExecuteResult } from '@cosmjs/cosmwasm-stargate'
|
||||
import { TxBroadcastResult } from '@marsprotocol/wallet-connector'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import { DAY_IN_SECONDS, HOUR_IN_SECONDS, MINUTE_IN_SECONDS } from 'constants/timeConstants'
|
||||
import moment from 'moment'
|
||||
@ -282,21 +282,31 @@ export const extractCoinFromLog = (text: string) => {
|
||||
return { amount: arr[0], denom: arr[1] }
|
||||
}
|
||||
|
||||
export const parseActionMessages = (data: ExecuteResult) => {
|
||||
const wasmEvents = data.logs[0].events.find((object) => object.type === 'wasm')
|
||||
if (wasmEvents) {
|
||||
return wasmEvents.attributes.reduce((prev: {}[], curr) => {
|
||||
if (curr.key === '_contract_address') {
|
||||
export const parseActionMessages = (data: TxBroadcastResult) => {
|
||||
const wasmEvents: [] = data.response.events
|
||||
.filter((object: Record<string, string>) => object.type === 'wasm')
|
||||
.map((event: Record<string, string>) => event?.attributes)
|
||||
.flat()
|
||||
|
||||
if (wasmEvents.length) {
|
||||
return wasmEvents.reduce((prev: {}[], curr: any) => {
|
||||
if (curr.key === 'action') {
|
||||
prev.push({ [curr.key]: curr.value })
|
||||
return prev
|
||||
} else {
|
||||
Object.assign(prev[prev.length - 1], { [curr.key]: curr.value })
|
||||
if (prev.length) {
|
||||
Object.assign(prev[prev.length - 1], { [curr.key]: curr.value })
|
||||
}
|
||||
return prev
|
||||
}
|
||||
}, [])
|
||||
}
|
||||
}
|
||||
|
||||
export const toBase64 = (obj: object) => {
|
||||
return Buffer.from(JSON.stringify(obj)).toString('base64')
|
||||
}
|
||||
|
||||
export const ltvToLeverage = (ltv: number) => {
|
||||
const leverage = 1 / (1 - ltv)
|
||||
return new BigNumber(leverage).decimalPlaces(2).toNumber()
|
||||
|
@ -19,7 +19,11 @@ export const position: Position = {
|
||||
total: 0,
|
||||
net: 0,
|
||||
},
|
||||
apy: 0,
|
||||
apy: {
|
||||
borrow: 5.2,
|
||||
net: 7.7,
|
||||
total: 19,
|
||||
},
|
||||
ltv: 0.5,
|
||||
currentLeverage: 1,
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import {
|
||||
} from 'components/fields'
|
||||
import { FIELDS_FEATURE } from 'constants/appConstants'
|
||||
import { useRouter } from 'next/router'
|
||||
import React, { useEffect } from 'react'
|
||||
import { useEffect } from 'react'
|
||||
import useStore from 'store'
|
||||
|
||||
import styles from './Fields.module.scss'
|
||||
@ -23,7 +23,8 @@ const Fields = () => {
|
||||
const userWalletAddress = useStore((s) => s.userWalletAddress)
|
||||
|
||||
useEffect(() => {
|
||||
if (!getVaults || !accountNftClient || !client || !creditManagerClient) return
|
||||
if (!getVaults || !accountNftClient || !client || !creditManagerClient || !userWalletAddress)
|
||||
return
|
||||
if (userWalletAddress && prefUserWalletAddress !== userWalletAddress) {
|
||||
prefUserWalletAddress = userWalletAddress
|
||||
getVaults({ refetch: true })
|
||||
|
@ -25,7 +25,9 @@ const CloseVaultPosition = () => {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!closeFee || !closeActions || !activeVault || isLoading || data || error) return
|
||||
if (!closeFee || !closeActions || !activeVault || isLoading || data?.error || data?.result)
|
||||
return
|
||||
|
||||
mutate({
|
||||
accountId: activeVault.position.accountId,
|
||||
actions: closeActions,
|
||||
@ -46,7 +48,6 @@ const CloseVaultPosition = () => {
|
||||
return (
|
||||
<ClosePositionResponse
|
||||
data={data}
|
||||
error={error}
|
||||
isLoading={isLoading}
|
||||
accountId={ref.current.position.accountId}
|
||||
/>
|
||||
|
@ -4,7 +4,6 @@ import { useCreateCreditAccount, useUpdateAccount } from 'hooks/mutations'
|
||||
import { useEditPosition, useEstimateFarmFee } from 'hooks/queries'
|
||||
import { getTimeAndUnit } from 'libs/parse'
|
||||
import router from 'next/router'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import styles from './SetupPosition.module.scss'
|
||||
@ -22,7 +21,6 @@ const SetupPosition = (props: Props) => {
|
||||
data: accountId,
|
||||
isLoading: isLoadingCreate,
|
||||
} = useCreateCreditAccount()
|
||||
|
||||
const {
|
||||
mutate: enterVault,
|
||||
data: enterVaultData,
|
||||
@ -57,11 +55,10 @@ const SetupPosition = (props: Props) => {
|
||||
enterVault({ accountId, actions: editActions, fee: editFee, funds: editFunds })
|
||||
}
|
||||
|
||||
if (isLoadingEnterVault || enterVaultError || enterVaultData) {
|
||||
if (isLoadingEnterVault || enterVaultData) {
|
||||
return (
|
||||
<SetUpResponse
|
||||
data={enterVaultData}
|
||||
error={enterVaultError}
|
||||
isLoading={isLoadingEnterVault}
|
||||
accountId={accountId || ''}
|
||||
/>
|
||||
|
@ -162,31 +162,18 @@ const EditVault = (props: Props) => {
|
||||
|
||||
if (isLoadingEdit || editData || editError) {
|
||||
return (
|
||||
<EditResponse
|
||||
data={editData}
|
||||
error={editError}
|
||||
isLoading={isLoadingEdit}
|
||||
activeVault={props.activeVault}
|
||||
/>
|
||||
<EditResponse data={editData} isLoading={isLoadingEdit} activeVault={props.activeVault} />
|
||||
)
|
||||
}
|
||||
|
||||
if (isLoadingRepay || repayData || repayError) {
|
||||
return (
|
||||
<RepayResponse
|
||||
data={repayData}
|
||||
error={repayError}
|
||||
isLoading={isLoadingRepay}
|
||||
vault={props.activeVault}
|
||||
/>
|
||||
)
|
||||
return <RepayResponse data={repayData} isLoading={isLoadingRepay} vault={props.activeVault} />
|
||||
}
|
||||
|
||||
if (isLoadingUnlock || unlockData || unlockError) {
|
||||
return (
|
||||
<UnlockResponse
|
||||
data={unlockData}
|
||||
error={unlockError}
|
||||
isLoading={isLoadingUnlock}
|
||||
activeVault={props.activeVault}
|
||||
/>
|
||||
|
@ -49,14 +49,7 @@ const RepayVault = (props: Props) => {
|
||||
}
|
||||
|
||||
if (isLoadingRepay || repayData || repayError) {
|
||||
return (
|
||||
<RepayResponse
|
||||
data={repayData}
|
||||
error={repayError}
|
||||
isLoading={isLoadingRepay}
|
||||
vault={props.activeVault}
|
||||
/>
|
||||
)
|
||||
return <RepayResponse data={repayData} isLoading={isLoadingRepay} vault={props.activeVault} />
|
||||
}
|
||||
|
||||
const isSameAmounts = isEqual(prevPosition.amounts, repayPosition.amounts)
|
||||
|
@ -5,7 +5,6 @@ import { useActiveVault } from 'hooks/data'
|
||||
import { useUpdateAccount } from 'hooks/mutations'
|
||||
import { useRequestUnlockPosition } from 'hooks/queries/useRequestUnlockPosition'
|
||||
import { useRouter } from 'next/router'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import styles from './UnlockDisclaimer.module.scss'
|
||||
@ -49,12 +48,7 @@ const Unlock = () => {
|
||||
|
||||
if (unlockData || unlockError || isLoadingUnlock) {
|
||||
return (
|
||||
<UnlockResponse
|
||||
data={unlockData}
|
||||
error={unlockError}
|
||||
isLoading={isLoadingUnlock}
|
||||
activeVault={activeVault}
|
||||
/>
|
||||
<UnlockResponse data={unlockData} isLoading={isLoadingUnlock} activeVault={activeVault} />
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,15 @@
|
||||
import { ExecuteResult } from '@cosmjs/cosmwasm-stargate'
|
||||
import { LcdClient } from '@cosmjs/launchpad'
|
||||
import { Coin, StdFee } from '@cosmjs/stargate'
|
||||
import { WalletChainInfo, WalletSigningCosmWasmClient } from '@marsprotocol/wallet-connector'
|
||||
import {
|
||||
SimplifiedChainInfo,
|
||||
TxBroadcastResult,
|
||||
WalletClient,
|
||||
} from '@marsprotocol/wallet-connector'
|
||||
import { BlockHeightData } from 'hooks/queries/useBlockHeight'
|
||||
import { MarketDepositsData } from 'hooks/queries/useMarketDeposits'
|
||||
import { SafetyFundBalanceData } from 'hooks/queries/useSafetyFundBalance'
|
||||
import { UserBalanceData } from 'hooks/queries/useUserBalance'
|
||||
import { UserIcnsData } from 'hooks/queries/useUserIcns'
|
||||
import { Network } from 'types/enums/network'
|
||||
import { ContractMsg } from 'types/types'
|
||||
|
||||
@ -22,8 +26,8 @@ export interface CommonSlice {
|
||||
decimals: number
|
||||
}
|
||||
baseToDisplayCurrencyRatio?: number
|
||||
chainInfo?: WalletChainInfo
|
||||
client?: WalletSigningCosmWasmClient
|
||||
chainInfo?: SimplifiedChainInfo
|
||||
client?: WalletClient
|
||||
currentNetwork: Network
|
||||
displayCurrency: {
|
||||
denom: string
|
||||
@ -51,7 +55,7 @@ export interface CommonSlice {
|
||||
userUnclaimedRewards: string
|
||||
userMarsTokenBalances: Coin[]
|
||||
userWalletAddress: string
|
||||
userWalletName: string
|
||||
userIcns?: string
|
||||
vaultConfigs: Vault[]
|
||||
whitelistedAssets: Asset[]
|
||||
// ------------------
|
||||
@ -65,7 +69,7 @@ export interface CommonSlice {
|
||||
contract: string
|
||||
fee: StdFee
|
||||
sender?: string
|
||||
}) => Promise<ExecuteResult | undefined>
|
||||
}) => Promise<TxBroadcastResult | undefined>
|
||||
loadNetworkConfig: () => void
|
||||
queryContract: <T>(
|
||||
contractAddress: string,
|
||||
@ -76,22 +80,23 @@ export interface CommonSlice {
|
||||
// ------------------
|
||||
// SETTERS
|
||||
// ------------------
|
||||
setChainInfo: (chainInfo: WalletChainInfo) => void
|
||||
setChainInfo: (chainInfo: SimplifiedChainInfo) => void
|
||||
setCurrentNetwork: (network: Network) => void
|
||||
setTutorialStep: (type: 'fields' | 'redbank', step?: number) => void
|
||||
setLcdClient: (rpc: string, chainID: string) => void
|
||||
setNetworkError: (isError: boolean) => void
|
||||
setClient: (client: WalletSigningCosmWasmClient) => void
|
||||
setClient: (client: WalletClient) => void
|
||||
setQueryError: (name: string, isError: boolean) => void
|
||||
setServerError: (isError: boolean) => void
|
||||
setUserIcns: (icns: string) => void
|
||||
setUserWalletAddress: (address: string) => void
|
||||
setUserWalletName: (name: string) => void
|
||||
// ------------------
|
||||
// QUERY RELATED
|
||||
// ------------------
|
||||
previousBlockHeightQueryData?: BlockHeightData
|
||||
previousSafetyFundBalanceQueryData?: SafetyFundBalanceData
|
||||
previousUserBalanceQueryData?: UserBalanceData
|
||||
previousUserIcnsQueryData?: UserIcnsData
|
||||
previousUserUnclaimedBalanceQueryData?: number
|
||||
processMarketDepositsQuery: (data: MarketDepositsData) => void
|
||||
processUserBalanceQuery: (data: UserBalanceData) => void
|
||||
|
@ -1,16 +1,12 @@
|
||||
import { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'
|
||||
import { MarsAccountNftInterface } from 'types/generated/mars-account-nft/MarsAccountNft.client'
|
||||
import { MarsCreditManagerClient } from 'types/generated/mars-credit-manager/MarsCreditManager.client'
|
||||
import { AccountNftClient, CreditManagerClient } from 'types/classes'
|
||||
import { MarsCreditManagerMessageComposer } from 'types/generated/mars-credit-manager/MarsCreditManager.message-composer'
|
||||
|
||||
export interface FieldsSlice {
|
||||
accountNftClient?: MarsAccountNftInterface
|
||||
creditManagerClient?: MarsCreditManagerClient
|
||||
accountNftClient?: AccountNftClient
|
||||
creditManagerClient?: CreditManagerClient
|
||||
creditManagerMsgComposer?: MarsCreditManagerMessageComposer
|
||||
isRepay: boolean
|
||||
position?: Position
|
||||
setAccountNftClient: (client: SigningCosmWasmClient) => void
|
||||
setCreditManagerClient: (client: SigningCosmWasmClient) => void
|
||||
setCreditManagerMsgComposer: (address: string, contract: string) => void
|
||||
setIsRepay: (isRepay: boolean) => void
|
||||
setPosition: (position?: Position) => void
|
||||
|
@ -1,7 +1,11 @@
|
||||
import { ExecuteResult } from '@cosmjs/cosmwasm-stargate'
|
||||
import { LcdClient } from '@cosmjs/launchpad'
|
||||
import { Coin } from '@cosmjs/stargate'
|
||||
import { WalletChainInfo, WalletSigningCosmWasmClient } from '@marsprotocol/wallet-connector'
|
||||
import {
|
||||
MsgExecuteContract,
|
||||
SimplifiedChainInfo,
|
||||
TxBroadcastResult,
|
||||
WalletClient,
|
||||
} from '@marsprotocol/wallet-connector'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import { BlockHeightData } from 'hooks/queries/useBlockHeight'
|
||||
import { MarketDepositsData } from 'hooks/queries/useMarketDeposits'
|
||||
@ -46,7 +50,6 @@ const commonSlice = (
|
||||
queryErrors: [],
|
||||
slippage: 0.02,
|
||||
tutorialSteps: { redbank: 1, fields: 1 },
|
||||
userWalletName: '',
|
||||
userBalances: [],
|
||||
userMarsTokenBalances: [],
|
||||
userUnclaimedRewards: '0',
|
||||
@ -80,20 +83,30 @@ const commonSlice = (
|
||||
|
||||
return new BigNumber(coin.amount).div(exchangeRate).toNumber()
|
||||
},
|
||||
executeMsg: async (options: StrategyExecuteMsgOptions): Promise<ExecuteResult | undefined> => {
|
||||
executeMsg: async (
|
||||
options: StrategyExecuteMsgOptions,
|
||||
): Promise<TxBroadcastResult | undefined> => {
|
||||
const client = get().client!
|
||||
|
||||
if (!options.sender) options.sender = get().userWalletAddress
|
||||
|
||||
const broadcastOptions = {
|
||||
messages: [
|
||||
new MsgExecuteContract({
|
||||
sender: options.sender,
|
||||
contract: options.contract,
|
||||
msg: options.msg,
|
||||
funds: options.funds,
|
||||
}),
|
||||
],
|
||||
feeAmount: options.fee.amount[0].amount,
|
||||
gasLimit: options.fee.gas,
|
||||
memo: undefined,
|
||||
wallet: client.recentWallet,
|
||||
}
|
||||
|
||||
try {
|
||||
return client.execute(
|
||||
options.sender,
|
||||
options.contract,
|
||||
options.msg as Record<string, unknown>,
|
||||
options.fee,
|
||||
undefined,
|
||||
options.funds,
|
||||
)
|
||||
return client.broadcast(broadcastOptions)
|
||||
} catch (e) {}
|
||||
},
|
||||
loadNetworkConfig: async () => {
|
||||
@ -133,7 +146,7 @@ const commonSlice = (
|
||||
lcdClient: new LcdClient(rpc),
|
||||
})
|
||||
},
|
||||
setChainInfo: (chainInfo: WalletChainInfo) => set({ chainInfo }),
|
||||
setChainInfo: (chainInfo: SimplifiedChainInfo) => set({ chainInfo }),
|
||||
setCurrentNetwork: (network: Network) => set({ currentNetwork: network }),
|
||||
setNetworkError: (isError: boolean) => {
|
||||
const errors = get().errors
|
||||
@ -142,7 +155,7 @@ const commonSlice = (
|
||||
set({ errors })
|
||||
}
|
||||
},
|
||||
setClient: (client: WalletSigningCosmWasmClient) => set({ client }),
|
||||
setClient: (client: WalletClient) => set({ client }),
|
||||
setQueryError: (name: string, isError: boolean) => {
|
||||
const errors = get().errors
|
||||
const queryErrors = get().queryErrors
|
||||
@ -171,7 +184,7 @@ const commonSlice = (
|
||||
set({ tutorialSteps })
|
||||
},
|
||||
setUserWalletAddress: (address: string) => set({ userWalletAddress: address }),
|
||||
setUserWalletName: (name: string) => set({ userWalletName: name }),
|
||||
setUserIcns: (icns: string) => set({ userIcns: icns }),
|
||||
// -------------------
|
||||
// QUERY RELATED
|
||||
// -------------------
|
||||
|
@ -1,38 +1,11 @@
|
||||
import { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'
|
||||
import { FieldsSlice } from 'store/interfaces/fields.interface'
|
||||
import { Store } from 'store/interfaces/store.interface'
|
||||
import { MarsAccountNftClient } from 'types/generated/mars-account-nft/MarsAccountNft.client'
|
||||
import { MarsCreditManagerClient } from 'types/generated/mars-credit-manager/MarsCreditManager.client'
|
||||
import { MarsCreditManagerMessageComposer } from 'types/generated/mars-credit-manager/MarsCreditManager.message-composer'
|
||||
import { GetState } from 'zustand'
|
||||
import { NamedSet } from 'zustand/middleware'
|
||||
|
||||
const fieldsSlice = (set: NamedSet<Store>, get: GetState<Store>): FieldsSlice => ({
|
||||
isRepay: false,
|
||||
setAccountNftClient: (client: SigningCosmWasmClient) => {
|
||||
const contracts = get().networkConfig?.contracts
|
||||
const userWalletAddress = get().userWalletAddress
|
||||
|
||||
if (contracts?.accountNft) {
|
||||
set({
|
||||
accountNftClient: new MarsAccountNftClient(client, userWalletAddress, contracts.accountNft),
|
||||
})
|
||||
}
|
||||
},
|
||||
setCreditManagerClient: (client: SigningCosmWasmClient) => {
|
||||
const contracts = get().networkConfig?.contracts
|
||||
const userWalletAddress = get().userWalletAddress
|
||||
|
||||
if (contracts?.accountNft && userWalletAddress) {
|
||||
set({
|
||||
creditManagerClient: new MarsCreditManagerClient(
|
||||
client,
|
||||
userWalletAddress,
|
||||
contracts.creditManager,
|
||||
),
|
||||
})
|
||||
}
|
||||
},
|
||||
setCreditManagerMsgComposer: (sender: string, contract: string) => {
|
||||
set({ creditManagerMsgComposer: new MarsCreditManagerMessageComposer(sender, contract) })
|
||||
},
|
||||
|
@ -90,7 +90,7 @@ const oraclesSlice = (set: NamedSet<Store>, get: GetState<Store>): OraclesSlice
|
||||
const denom = asset.denom
|
||||
|
||||
if (denom === get().baseCurrency.denom) {
|
||||
updateExchangeRate({ denom, amount: '1' }, exchangeRates)
|
||||
exchangeRates.push({ denom, amount: '1' })
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -5,12 +5,13 @@ import { convertAprToApy, leverageToLtv } from 'libs/parse'
|
||||
import moment from 'moment'
|
||||
import { Store } from 'store/interfaces/store.interface'
|
||||
import { Options, VaultsSlice } from 'store/interfaces/vaults.interface.'
|
||||
import { VaultClient } from 'types/classes'
|
||||
import {
|
||||
ArrayOfVaultInfoResponse,
|
||||
LockingVaultAmount,
|
||||
Positions,
|
||||
} from 'types/generated/mars-credit-manager/MarsCreditManager.types'
|
||||
import { VaultBaseForString } from 'types/generated/mars-mock-credit-manager/MarsMockCreditManager.types'
|
||||
import { MarsMockVaultClient } from 'types/generated/mars-mock-vault/MarsMockVault.client'
|
||||
import { GetState } from 'zustand'
|
||||
import { NamedSet } from 'zustand/middleware'
|
||||
|
||||
@ -25,12 +26,14 @@ export const vaultsSlice = (set: NamedSet<Store>, get: GetState<Store>): VaultsS
|
||||
const nftClient = get().accountNftClient!
|
||||
const address = get().userWalletAddress
|
||||
|
||||
const accountIds = await nftClient
|
||||
.tokens({ owner: address, limit: 100 })
|
||||
.then((result) => result.tokens)
|
||||
const accountIds: string[] = await nftClient
|
||||
.query({ tokens: { owner: address, limit: 100 } })
|
||||
.then((result: { tokens: string[] }) => result.tokens)
|
||||
|
||||
const creditManagerClient = get().creditManagerClient
|
||||
const promises = accountIds?.map((id) => creditManagerClient?.positions({ accountId: id }))
|
||||
const promises = accountIds?.map((id) =>
|
||||
creditManagerClient?.query({ positions: { account_id: id } }),
|
||||
)
|
||||
|
||||
const newCreditAccounts = await Promise.all(promises).then((result) =>
|
||||
result.map((value) => value as Positions).filter((positions) => positions.vaults.length),
|
||||
@ -58,10 +61,12 @@ export const vaultsSlice = (set: NamedSet<Store>, get: GetState<Store>): VaultsS
|
||||
.toString()
|
||||
|
||||
return {
|
||||
coins: await creditManagerClient.estimateWithdrawLiquidity({
|
||||
lpToken: {
|
||||
amount: amount,
|
||||
denom: lpToken.denom,
|
||||
coins: await creditManagerClient.query({
|
||||
estimate_withdraw_liquidity: {
|
||||
lp_token: {
|
||||
amount: amount,
|
||||
denom: lpToken.denom,
|
||||
},
|
||||
},
|
||||
}),
|
||||
vaultAddress: lpToken.vaultAddress,
|
||||
@ -91,11 +96,14 @@ export const vaultsSlice = (set: NamedSet<Store>, get: GetState<Store>): VaultsS
|
||||
?.unlocking[0]?.id
|
||||
|
||||
if (!client || !vault || isNaN(lockupId)) return null
|
||||
|
||||
const vaultClient = new VaultClient(vault.address, client)
|
||||
|
||||
return {
|
||||
unlockAtTimestamp: Math.round(
|
||||
Number(
|
||||
(
|
||||
await client.queryContractSmart(vault.address, {
|
||||
await vaultClient.query({
|
||||
vault_extension: { lockup: { unlocking_position: { lockup_id: lockupId } } },
|
||||
})
|
||||
).release_at?.at_time,
|
||||
@ -152,7 +160,9 @@ export const vaultsSlice = (set: NamedSet<Store>, get: GetState<Store>): VaultsS
|
||||
let data: VaultCapData[] = []
|
||||
|
||||
const getBatch = async (startAfter?: VaultBaseForString): Promise<void> => {
|
||||
const batch = await creditManagerClient?.vaultsInfo({ limit: 5, startAfter })
|
||||
const batch: ArrayOfVaultInfoResponse = await creditManagerClient.query({
|
||||
vaults_info: { limit: 5, start_after: startAfter },
|
||||
})
|
||||
|
||||
const batchProcessed = batch?.map(
|
||||
(vaultInfo) =>
|
||||
@ -184,19 +194,20 @@ export const vaultsSlice = (set: NamedSet<Store>, get: GetState<Store>): VaultsS
|
||||
|
||||
const creditAccounts = await get().getCreditAccounts(options)
|
||||
const client = get().client!
|
||||
const userWalletAddress = get().userWalletAddress
|
||||
|
||||
const promises = creditAccounts.map(async (creditAccount) => {
|
||||
const vaultAddress = creditAccount.vaults[0].vault.address
|
||||
const vault = get().vaultConfigs.find((vault) => vault.address === vaultAddress)
|
||||
|
||||
const vaultClient = new MarsMockVaultClient(client, userWalletAddress, vaultAddress)
|
||||
const vaultClient = new VaultClient(vaultAddress, client)
|
||||
|
||||
const amounts = getAmountsFromActiveVault(creditAccount.vaults[0].amount)
|
||||
return {
|
||||
locked: Number(
|
||||
await vaultClient.previewRedeem({
|
||||
amount: amounts.locked,
|
||||
await vaultClient.query({
|
||||
preview_redeem: {
|
||||
amount: amounts.locked,
|
||||
},
|
||||
}),
|
||||
),
|
||||
unlocking: amounts.unlocking,
|
||||
@ -206,7 +217,7 @@ export const vaultsSlice = (set: NamedSet<Store>, get: GetState<Store>): VaultsS
|
||||
}
|
||||
})
|
||||
|
||||
const newLpTokens = await Promise.all(promises)
|
||||
const newLpTokens = (await Promise.all(promises)).filter((lpToken) => !!lpToken.denom)
|
||||
set({ lpTokens: newLpTokens })
|
||||
|
||||
return newLpTokens
|
||||
@ -378,7 +389,11 @@ export const vaultsSlice = (set: NamedSet<Store>, get: GetState<Store>): VaultsS
|
||||
vault: vaultTokenAmounts.locked,
|
||||
},
|
||||
values,
|
||||
apy: apy,
|
||||
apy: {
|
||||
total: curr.apy,
|
||||
borrow: trueBorrowRate,
|
||||
net: apy,
|
||||
},
|
||||
currentLeverage: leverage,
|
||||
ltv: leverageToLtv(leverage),
|
||||
...(unlockTime ? { unlockAtTimestamp: unlockTime } : {}),
|
||||
|
@ -49,6 +49,14 @@ a {
|
||||
color: $colorPrimaryHighlight;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
&:has(button) {
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b,
|
||||
|
@ -1,35 +1,35 @@
|
||||
@use 'sass:math';
|
||||
$rem-base: 16px;
|
||||
$rem-base: 15px;
|
||||
|
||||
/* Colors */
|
||||
$colorWhite: #f5f5f5;
|
||||
$colorGrey: #bdbdbd;
|
||||
$colorGreyLight: #e0e0e0;
|
||||
$colorGreyHighlight: #efefef;
|
||||
$colorGreyMedium: #9e9e9e;
|
||||
$colorGreyDark: #616161;
|
||||
$colorWhite: #ffffff;
|
||||
$colorGrey: #3a3c49;
|
||||
$colorGreyLight: #bfbfbf;
|
||||
$colorGreyHighlight: #4c4c4c;
|
||||
$colorGreyMedium: #5f697a;
|
||||
$colorGreyDark: #1a1c25;
|
||||
|
||||
/* CI Colors */
|
||||
$colorPrimary: #0000ff;
|
||||
$colorPrimaryHighlight: #6962cc;
|
||||
$colorPrimaryAlpha: rgba(0, 0, 255, 0.05);
|
||||
$colorSecondary: #212121;
|
||||
$colorSecondaryHighlight: #424242;
|
||||
$colorSecondaryDark: #111111;
|
||||
$colorSecondaryAlpha: rgba(17, 17, 17, 0.15);
|
||||
$colorAccent: $colorGreyMedium;
|
||||
$colorAccentHighlight: $colorGreyMedium;
|
||||
$colorAccentDark: $colorGreyDark;
|
||||
$colorAccentInverted: $colorGreyLight;
|
||||
$colorPrimary: #14a693;
|
||||
$colorPrimaryHighlight: #15bfa9;
|
||||
$colorPrimaryAlpha: rgba(20, 166, 147, 0.15);
|
||||
$colorSecondary: #524bb1;
|
||||
$colorSecondaryHighlight: #6962cc;
|
||||
$colorSecondaryDark: #440b37;
|
||||
$colorSecondaryAlpha: rgba(68, 11, 55, 0.7);
|
||||
$colorAccent: #2c1b2f;
|
||||
$colorAccentHighlight: #421f32;
|
||||
$colorAccentDark: #341a2a;
|
||||
$colorAccentInverted: #345dff;
|
||||
|
||||
/* Info Colors */
|
||||
$colorInfoProfit: #c4e7e9;
|
||||
$colorInfoLoss: #c8aaaa;
|
||||
$colorInfoWarning: #ffb5b5;
|
||||
$colorInfoVoteAgainst: #6c5a46;
|
||||
$colorInfoProfit: #41a4a9;
|
||||
$colorInfoLoss: #f96363;
|
||||
$colorInfoWarning: #c83333;
|
||||
$colorInfoVoteAgainst: #eb9e49;
|
||||
|
||||
/* Token Colors */
|
||||
$colorTokenMARS: #dd5b65;
|
||||
$colorTokenMARS: #a03b45;
|
||||
$colorTokenOSMO: #9f1ab9;
|
||||
$colorTokenATOM: #6f7390;
|
||||
$colorTokenAxlUSDC: #478edc;
|
||||
@ -60,29 +60,32 @@ $alphaBlack80: rgba(0, 0, 0, 0.8);
|
||||
$alphaBlack90: rgba(0, 0, 0, 0.9);
|
||||
|
||||
/* Background Colors */
|
||||
$backgroundBody: $colorGrey;
|
||||
$backgroundBodyDark: $backgroundBody;
|
||||
$backgroundInTile: transparent;
|
||||
$backgroundFooter: transparent;
|
||||
$backgroundBody: #562a3b;
|
||||
$backgroundBodyDark: #141621;
|
||||
$backgroundInTile: $alphaBlack30;
|
||||
$backgroundFooter: $alphaBlack20;
|
||||
|
||||
/* Slider Colors */
|
||||
$sliderThumb: $colorGreyDark;
|
||||
$sliderMark: $colorGreyDark;
|
||||
$sliderThumb: $colorWhite;
|
||||
$sliderMark: $colorGreyLight;
|
||||
|
||||
/* Tooltip Colors */
|
||||
$tooltipIconColor: $alphaBlack60;
|
||||
$tooltipIconColor: $alphaWhite20;
|
||||
$tableSort: $alphaWhite20;
|
||||
$tableSortActive: $colorWhite;
|
||||
$tableHeader: $alphaWhite50;
|
||||
|
||||
/* Table Colors */
|
||||
$tableBorder: $alphaBlack30;
|
||||
$tableBorderEnd: $alphaBlack80;
|
||||
$tableSort: $alphaBlack20;
|
||||
$tableSortActive: $alphaBlack90;
|
||||
$tableHeader: $alphaBlack40;
|
||||
$tableLabel: $colorSecondaryDark;
|
||||
$tableBorder: $alphaWhite10;
|
||||
$tableBorderEnd: $alphaWhite80;
|
||||
$tableSort: $alphaWhite20;
|
||||
$tableSortActive: $colorWhite;
|
||||
$tableHeader: $alphaWhite40;
|
||||
$tableLabel: $alphaWhite60;
|
||||
|
||||
/* Graph Colors */
|
||||
$graphLiquidationsLine: $alphaBlack70;
|
||||
$graphAxis: $alphaBlack40;
|
||||
$graphLiquidationsLine: $alphaWhite70;
|
||||
$graphAxis: $alphaWhite40;
|
||||
|
||||
/* Shadows */
|
||||
$shadowInset: inset 0px 2px 2px rgba(0, 0, 0, 0.25);
|
||||
@ -93,40 +96,43 @@ $shadowInset: inset 0px 2px 2px rgba(0, 0, 0, 0.25);
|
||||
|
||||
/* Devider */
|
||||
@mixin devider10 {
|
||||
border-bottom: 1px solid $alphaBlack10;
|
||||
border-bottom: 1px solid $alphaWhite10;
|
||||
}
|
||||
|
||||
@mixin devider20 {
|
||||
border-bottom: 1px solid $alphaBlack20;
|
||||
border-bottom: 1px solid $alphaWhite20;
|
||||
}
|
||||
|
||||
@mixin devider40 {
|
||||
border-bottom: 1px solid $alphaBlack40;
|
||||
border-bottom: 1px solid $alphaWhite40;
|
||||
}
|
||||
|
||||
@mixin devider60 {
|
||||
border-bottom: 1px solid $alphaBlack60;
|
||||
border-bottom: 1px solid $alphaWhite60;
|
||||
}
|
||||
|
||||
/* Backgrounds */
|
||||
@mixin bgBody {
|
||||
background-color: $backgroundBody;
|
||||
}
|
||||
|
||||
@mixin bgTableHover {
|
||||
background-color: transparent;
|
||||
background-size: 100% auto;
|
||||
background-image: url('../images/bg.svg');
|
||||
background-position: center top;
|
||||
}
|
||||
|
||||
@mixin bgBodyDark {
|
||||
background-color: $backgroundBodyDark;
|
||||
}
|
||||
|
||||
@mixin bgTableHover {
|
||||
background-color: rgba($colorPrimary, 0.2);
|
||||
}
|
||||
|
||||
@mixin bgProposalActive {
|
||||
background: linear-gradient(90deg, #10aa93 2.6%, #248aa9 97.92%);
|
||||
}
|
||||
|
||||
@mixin bgProposalHover {
|
||||
background-color: $colorGreyMedium;
|
||||
background-color: #05252f;
|
||||
}
|
||||
|
||||
@mixin bgTile($deg: 99.79) {
|
||||
@ -138,7 +144,7 @@ $shadowInset: inset 0px 2px 2px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
@mixin bgInTile {
|
||||
background: $backgroundInTile;
|
||||
background: $alphaBlack30;
|
||||
}
|
||||
|
||||
@mixin bgOverlay {
|
||||
@ -155,11 +161,11 @@ $shadowInset: inset 0px 2px 2px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
@mixin bgTileDevider {
|
||||
background-color: $alphaBlack60;
|
||||
background-color: $alphaWhite60;
|
||||
}
|
||||
|
||||
@mixin bgDevider {
|
||||
background-color: $alphaBlack20;
|
||||
background-color: $alphaWhite20;
|
||||
}
|
||||
|
||||
@mixin bgInput {
|
||||
@ -168,60 +174,68 @@ $shadowInset: inset 0px 2px 2px rgba(0, 0, 0, 0.25);
|
||||
|
||||
@mixin bgPrimary {
|
||||
background-color: $colorPrimary;
|
||||
color: $colorWhite;
|
||||
}
|
||||
|
||||
@mixin bgSecondary {
|
||||
background-color: $colorSecondary;
|
||||
color: $colorWhite;
|
||||
}
|
||||
|
||||
@mixin bgTertiary {
|
||||
background-color: $alphaBlack60;
|
||||
color: $colorWhite;
|
||||
background-color: rgba(82, 75, 177, 0.5);
|
||||
}
|
||||
|
||||
@mixin bgLimit {
|
||||
background: $colorPrimary;
|
||||
background: linear-gradient(
|
||||
to right,
|
||||
#15bfa9 20.9%,
|
||||
#5e4bb1 49.68%,
|
||||
#382685 82.55%,
|
||||
#c83333 100%
|
||||
);
|
||||
}
|
||||
|
||||
@mixin bgLimitOpacity {
|
||||
background: $colorPrimary;
|
||||
background: linear-gradient(
|
||||
to right,
|
||||
#15bfa830 20.9%,
|
||||
#5e4bb130 49.68%,
|
||||
#38268530 82.55%,
|
||||
#c8333330 100%
|
||||
);
|
||||
}
|
||||
|
||||
@mixin bgHatched {
|
||||
background-image: linear-gradient(
|
||||
135deg,
|
||||
#1a1c25 33.33%,
|
||||
rgba(255, 255, 255, 0.2) 33.33%,
|
||||
rgba(255, 255, 255, 0.2) 50%,
|
||||
#1a1c25 50%,
|
||||
#1a1c25 83.33%,
|
||||
rgba(255, 255, 255, 0.2) 83.33%,
|
||||
rgba(255, 255, 255, 0.2) 100%
|
||||
transparent 33.33%,
|
||||
#826d6b 33.33%,
|
||||
#826d6b 50%,
|
||||
transparent 50%,
|
||||
transparent 83.33%,
|
||||
#826d6b 83.33%,
|
||||
#826d6b 100%
|
||||
);
|
||||
background-size: 5px 5px;
|
||||
}
|
||||
|
||||
/* GLOWS */
|
||||
/* GLOWS */
|
||||
@mixin glowXS {
|
||||
display: none;
|
||||
filter: blur(1px);
|
||||
}
|
||||
@mixin glowS {
|
||||
display: none;
|
||||
filter: blur(3px);
|
||||
}
|
||||
@mixin glowM {
|
||||
display: none;
|
||||
filter: blur(4px);
|
||||
}
|
||||
@mixin glowL {
|
||||
display: none;
|
||||
filter: blur(5px);
|
||||
}
|
||||
@mixin glowXL {
|
||||
display: none;
|
||||
filter: blur(8px);
|
||||
}
|
||||
@mixin glowXXL {
|
||||
display: none;
|
||||
filter: blur(24px);
|
||||
}
|
||||
|
||||
/* Typography */
|
||||
@ -229,11 +243,11 @@ $fontWeightLight: 300;
|
||||
$fontWeightRegular: 400;
|
||||
$fontWeightSemibold: 600;
|
||||
|
||||
$fontColorDarkPrimary: $colorWhite;
|
||||
$fontColorDarkSecondary: $colorSecondaryDark;
|
||||
$fontColorLightPrimary: $colorSecondaryDark;
|
||||
$fontColorLightSecondary: $alphaBlack30;
|
||||
$fontColorLightTertiary: $colorSecondaryDark;
|
||||
$fontColorDarkPrimary: $colorSecondaryDark;
|
||||
$fontColorDarkSecondary: rgba(68, 8, 55, 0.7);
|
||||
$fontColorLightPrimary: $colorWhite;
|
||||
$fontColorLightSecondary: $alphaWhite60;
|
||||
$fontColorLightTertiary: rgba(255, 255, 255, 0.4);
|
||||
$fontColorLtv: $colorWhite;
|
||||
|
||||
@mixin typoH1 {
|
||||
@ -249,6 +263,8 @@ $fontColorLtv: $colorWhite;
|
||||
|
||||
@mixin typoH2caps {
|
||||
@include typoH2;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: rem-calc(9);
|
||||
}
|
||||
|
||||
@mixin typoH3 {
|
||||
@ -258,6 +274,8 @@ $fontColorLtv: $colorWhite;
|
||||
|
||||
@mixin typoH3caps {
|
||||
font-size: rem-calc(30.42);
|
||||
line-height: space(10);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
@mixin typoH4 {
|
||||
@ -268,6 +286,8 @@ $fontColorLtv: $colorWhite;
|
||||
|
||||
@mixin typoH4caps {
|
||||
@include typoH4;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: rem-calc(3);
|
||||
}
|
||||
|
||||
@mixin typoXXL {
|
||||
@ -277,7 +297,9 @@ $fontColorLtv: $colorWhite;
|
||||
|
||||
@mixin typoXXLcaps {
|
||||
@include typoXXL;
|
||||
font-weight: $fontWeightLight;
|
||||
font-weight: $fontWeightRegular;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: rem-calc(3);
|
||||
}
|
||||
|
||||
@mixin typoXL {
|
||||
@ -287,6 +309,8 @@ $fontColorLtv: $colorWhite;
|
||||
|
||||
@mixin typoXLcaps {
|
||||
@include typoXL;
|
||||
letter-spacing: rem-calc(5);
|
||||
text-transform: uppercase;
|
||||
font-weight: $fontWeightLight;
|
||||
}
|
||||
|
||||
@ -298,6 +322,8 @@ $fontColorLtv: $colorWhite;
|
||||
@mixin typoLcaps {
|
||||
@include typoL;
|
||||
font-weight: $fontWeightSemibold;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: rem-calc(3);
|
||||
}
|
||||
|
||||
@mixin typoM {
|
||||
@ -307,6 +333,7 @@ $fontColorLtv: $colorWhite;
|
||||
|
||||
@mixin typoMcaps {
|
||||
@include typoM;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
@mixin typoS {
|
||||
@ -317,6 +344,8 @@ $fontColorLtv: $colorWhite;
|
||||
@mixin typoScaps {
|
||||
@include typoS;
|
||||
font-weight: $fontWeightSemibold;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: rem-calc(3);
|
||||
}
|
||||
|
||||
@mixin typoXS {
|
||||
@ -327,6 +356,8 @@ $fontColorLtv: $colorWhite;
|
||||
@mixin typoXScaps {
|
||||
@include typoXS;
|
||||
font-weight: $fontWeightSemibold;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: rem-calc(3);
|
||||
}
|
||||
|
||||
@mixin typoXXS {
|
||||
@ -337,6 +368,8 @@ $fontColorLtv: $colorWhite;
|
||||
@mixin typoXXScaps {
|
||||
@include typoXXS;
|
||||
font-weight: $fontWeightSemibold;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: rem-calc(2);
|
||||
}
|
||||
|
||||
@mixin typoXXXS {
|
||||
@ -347,15 +380,20 @@ $fontColorLtv: $colorWhite;
|
||||
@mixin typoXXXScaps {
|
||||
@include typoXXXS;
|
||||
font-weight: $fontWeightSemibold;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: rem-calc(2);
|
||||
}
|
||||
|
||||
@mixin typoButton {
|
||||
font-family: Inter, sans-serif;
|
||||
@include typoS;
|
||||
font-weight: $fontWeightSemibold;
|
||||
}
|
||||
|
||||
@mixin typoNav {
|
||||
@include typoL;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: rem-calc(5);
|
||||
}
|
||||
|
||||
@mixin typoNetwork {
|
||||
@ -429,70 +467,100 @@ $spacingBase: 4;
|
||||
|
||||
/* LAYOUTS */
|
||||
@mixin layoutTile {
|
||||
padding: space(1);
|
||||
background: $colorGreyHighlight;
|
||||
border: 2px solid $colorWhite;
|
||||
box-shadow: 0 0 0 3px $colorGreyHighlight, 12px 12px 0 0 rgb(0 0 0 / 50%) !important;
|
||||
@include bgTile;
|
||||
border: rem-calc(7) solid $colorAccentHighlight;
|
||||
border-radius: $borderRadiusXL;
|
||||
height: fit-content;
|
||||
}
|
||||
|
||||
@mixin layoutTooltip {
|
||||
padding: space(3);
|
||||
background: $colorGreyLight;
|
||||
border: 1px solid $colorSecondaryDark;
|
||||
@include padding(2, 4);
|
||||
@include bgTooltip;
|
||||
@include typoS;
|
||||
box-shadow: 0 rem-calc(3) rem-calc(4) rgba(0, 0, 0, 0.14),
|
||||
0 rem-calc(3) rem-calc(3) rgba(0, 0, 0, 0.12), 0 rem-calc(1) rem-calc(8) rgba(0, 0, 0, 0.2);
|
||||
border-radius: $borderRadiusL;
|
||||
max-width: rem-calc(350);
|
||||
}
|
||||
|
||||
@mixin layoutPopover {
|
||||
padding: space(3);
|
||||
background: $colorGreyLight;
|
||||
border: 1px solid $colorSecondaryDark;
|
||||
@include bgPopover;
|
||||
box-shadow: 0 rem-calc(2) rem-calc(2) rgba(0, 0, 0, 0.14),
|
||||
0 rem-calc(1) rem-calc(5) rgba(0, 0, 0, 0.2);
|
||||
border-radius: $borderRadiusL;
|
||||
}
|
||||
|
||||
@mixin layoutIncentiveButton {
|
||||
--border-width: 3px;
|
||||
background-color: #946582;
|
||||
position: relative;
|
||||
border: none;
|
||||
margin: rem-calc(3) rem-calc(11) 0 0;
|
||||
height: rem-calc(28);
|
||||
|
||||
&:hover {
|
||||
border: none;
|
||||
background-color: darken(#946582, 10%);
|
||||
}
|
||||
|
||||
&::after {
|
||||
border-radius: $borderRadiusXXL;
|
||||
position: absolute;
|
||||
content: '';
|
||||
top: calc(-1 * var(--border-width));
|
||||
left: calc(-1 * var(--border-width));
|
||||
z-index: -1;
|
||||
width: calc(100% + var(--border-width) * 2);
|
||||
height: calc(100% + var(--border-width) * 2);
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
rgba(105, 98, 204, 0.8) 0%,
|
||||
rgba(105, 98, 204, 1) 40%,
|
||||
rgba(255, 255, 255, 1) 50%,
|
||||
rgba(105, 98, 204, 1) 60%,
|
||||
rgba(105, 98, 204, 0.8) 100%
|
||||
);
|
||||
background-size: 300% 300%;
|
||||
background-position: 0 50%;
|
||||
animation: moveGradient 6s alternate infinite;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin layoutLogo {
|
||||
> svg {
|
||||
width: rem-calc(57);
|
||||
height: rem-calc(57);
|
||||
|
||||
path {
|
||||
stroke: $fontColorLightPrimary;
|
||||
}
|
||||
width: rem-calc(50);
|
||||
height: rem-calc(50);
|
||||
}
|
||||
}
|
||||
|
||||
@mixin layoutGlobal {
|
||||
opacity: 1 !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
$buttonBorder: $alphaBlack40;
|
||||
$buttonBorderHover: $colorSecondaryDark;
|
||||
$buttonBorder: $alphaWhite40;
|
||||
$buttonBorderHover: $colorWhite;
|
||||
|
||||
@mixin buttonS {
|
||||
@include typoS;
|
||||
@include padding(1.5, 5);
|
||||
height: rem-calc(32);
|
||||
min-height: rem-calc(32);
|
||||
}
|
||||
|
||||
@mixin buttonM {
|
||||
@include typoM;
|
||||
@include padding(2.5, 6);
|
||||
height: rem-calc(40);
|
||||
min-height: rem-calc(40);
|
||||
}
|
||||
|
||||
@mixin buttonL {
|
||||
@include typoL;
|
||||
@include padding(2.5, 6);
|
||||
height: rem-calc(56);
|
||||
min-height: rem-calc(56);
|
||||
}
|
||||
|
||||
@mixin buttonSolidPrimary {
|
||||
&.primary {
|
||||
background-color: $colorPrimary;
|
||||
color: $colorWhite;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
@ -508,7 +576,6 @@ $buttonBorderHover: $colorSecondaryDark;
|
||||
@mixin buttonSolidSecondary {
|
||||
&.secondary {
|
||||
background-color: $colorSecondary;
|
||||
color: $colorWhite;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
@ -523,33 +590,34 @@ $buttonBorderHover: $colorSecondaryDark;
|
||||
|
||||
@mixin buttonSolidTertiary {
|
||||
&.tertiary {
|
||||
background-color: $colorSecondaryDark;
|
||||
color: $colorWhite;
|
||||
border: 1px solid $alphaBlack30;
|
||||
background-color: $colorSecondaryAlpha;
|
||||
border: 1px solid $alphaWhite60;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
border: 1px solid $alphaBlack20;
|
||||
border: 1px solid $fontColorLightPrimary;
|
||||
background-color: $colorSecondaryDark;
|
||||
}
|
||||
|
||||
&:active {
|
||||
border: 1px solid $fontColorLightPrimary;
|
||||
background-color: lighten($colorSecondaryDark, 10%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Border Radius */
|
||||
$borderRadiusXXXS: 0;
|
||||
$borderRadiusXXS: 0;
|
||||
$borderRadiusXS: 0;
|
||||
$borderRadiusS: 0;
|
||||
$borderRadiusM: 0;
|
||||
$borderRadiusL: 0;
|
||||
$borderRadiusXL: 0;
|
||||
$borderRadiusXXL: 0;
|
||||
$borderRadiusXXXL: 0;
|
||||
$borderRadiusXXXXL: 0;
|
||||
$borderRadiusRound: 0;
|
||||
$borderRadiusXXXS: rem-calc(3);
|
||||
$borderRadiusXXS: rem-calc(4);
|
||||
$borderRadiusXS: rem-calc(5);
|
||||
$borderRadiusS: rem-calc(8);
|
||||
$borderRadiusM: rem-calc(9);
|
||||
$borderRadiusL: rem-calc(12);
|
||||
$borderRadiusXL: rem-calc(16);
|
||||
$borderRadiusXXL: rem-calc(20);
|
||||
$borderRadiusXXXL: rem-calc(30);
|
||||
$borderRadiusXXXXL: rem-calc(100);
|
||||
$borderRadiusRound: 50%;
|
||||
|
||||
/* Dimensions */
|
||||
$headerHeight: rem-calc(86);
|
||||
|
@ -1,6 +1,62 @@
|
||||
import { Coin } from '@cosmjs/stargate'
|
||||
import { WalletClient } from '@marsprotocol/wallet-connector'
|
||||
import {
|
||||
ArrayOfCoin,
|
||||
QueryMsg as CreditQueryMsg,
|
||||
} from 'types/generated/mars-credit-manager/MarsCreditManager.types'
|
||||
|
||||
import { QueryMsg as AccountQueryMsg } from './generated/mars-account-nft/MarsAccountNft.types'
|
||||
import { QueryMsg as VaultQueryMsg } from './generated/mars-mock-vault/MarsMockVault.types'
|
||||
|
||||
export class SetupError extends Error {
|
||||
constructor(name: string, message: string) {
|
||||
super(message)
|
||||
this.name = name
|
||||
}
|
||||
}
|
||||
|
||||
export class CreditManagerClient {
|
||||
address: string
|
||||
client: WalletClient
|
||||
|
||||
constructor(address: string, client: WalletClient) {
|
||||
this.address = address
|
||||
this.client = client
|
||||
}
|
||||
|
||||
query(message: CreditQueryMsg) {
|
||||
return this.client.cosmWasmClient.queryContractSmart(this.address, message)
|
||||
}
|
||||
|
||||
estimateWithdrawLiquidity({ lpToken }: { lpToken: Coin }) {
|
||||
return Promise<ArrayOfCoin>
|
||||
}
|
||||
}
|
||||
|
||||
export class AccountNftClient {
|
||||
address: string
|
||||
client: WalletClient
|
||||
|
||||
constructor(address: string, client: WalletClient) {
|
||||
this.address = address
|
||||
this.client = client
|
||||
}
|
||||
|
||||
query(message: AccountQueryMsg) {
|
||||
return this.client.cosmWasmClient.queryContractSmart(this.address, message)
|
||||
}
|
||||
}
|
||||
|
||||
export class VaultClient {
|
||||
address: string
|
||||
client: WalletClient
|
||||
|
||||
constructor(address: string, client: WalletClient) {
|
||||
this.address = address
|
||||
this.client = client
|
||||
}
|
||||
|
||||
query(message: VaultQueryMsg) {
|
||||
return this.client.cosmWasmClient.queryContractSmart(this.address, message)
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ export enum QUERY_KEYS {
|
||||
USER_BALANCE = 'userBalance',
|
||||
USER_DEBT = 'userDebt',
|
||||
USER_DEPOSIT = 'userDeposits',
|
||||
USER_ICNS = 'userIcns',
|
||||
ATOM_PRICE = 'atomPrice',
|
||||
SAFETY_FUND_BALANCE = 'safetyFundBalance',
|
||||
MARKET_DEPOSITS = 'marketDeposits',
|
||||
|
@ -13,11 +13,11 @@ import {
|
||||
ApprovalResponse,
|
||||
ApprovalsResponse,
|
||||
Binary,
|
||||
ConfigBaseForString,
|
||||
ConfigUpdates,
|
||||
ContractInfoResponse,
|
||||
Expiration,
|
||||
MinterResponse,
|
||||
NftConfigBaseForString,
|
||||
NftConfigUpdates,
|
||||
NftInfoResponseForEmpty,
|
||||
NumTokensResponse,
|
||||
OperatorsResponse,
|
||||
@ -27,7 +27,7 @@ import {
|
||||
} from './MarsAccountNft.types'
|
||||
export interface MarsAccountNftReadOnlyInterface {
|
||||
contractAddress: string
|
||||
config: () => Promise<ConfigBaseForString>
|
||||
config: () => Promise<NftConfigBaseForString>
|
||||
nextId: () => Promise<Uint64>
|
||||
ownerOf: ({
|
||||
includeExpired,
|
||||
@ -113,7 +113,7 @@ export class MarsAccountNftQueryClient implements MarsAccountNftReadOnlyInterfac
|
||||
this.minter = this.minter.bind(this)
|
||||
}
|
||||
|
||||
config = async (): Promise<ConfigBaseForString> => {
|
||||
config = async (): Promise<NftConfigBaseForString> => {
|
||||
return this.client.queryContractSmart(this.contractAddress, {
|
||||
config: {},
|
||||
})
|
||||
@ -263,7 +263,7 @@ export interface MarsAccountNftInterface extends MarsAccountNftReadOnlyInterface
|
||||
{
|
||||
updates,
|
||||
}: {
|
||||
updates: ConfigUpdates
|
||||
updates: NftConfigUpdates
|
||||
},
|
||||
fee?: number | StdFee | 'auto',
|
||||
memo?: string,
|
||||
@ -398,7 +398,7 @@ export class MarsAccountNftClient
|
||||
{
|
||||
updates,
|
||||
}: {
|
||||
updates: ConfigUpdates
|
||||
updates: NftConfigUpdates
|
||||
},
|
||||
fee: number | StdFee | 'auto' = 'auto',
|
||||
memo?: string,
|
||||
|
@ -10,7 +10,7 @@ import { toUtf8 } from '@cosmjs/encoding'
|
||||
import { MsgExecuteContract } from 'cosmjs-types/cosmwasm/wasm/v1/tx'
|
||||
import { MsgExecuteContractEncodeObject } from 'cosmwasm'
|
||||
|
||||
import { Binary, ConfigUpdates, Expiration } from './MarsAccountNft.types'
|
||||
import { Binary, Expiration, NftConfigUpdates } from './MarsAccountNft.types'
|
||||
export interface MarsAccountNftMessage {
|
||||
contractAddress: string
|
||||
sender: string
|
||||
@ -18,7 +18,7 @@ export interface MarsAccountNftMessage {
|
||||
{
|
||||
updates,
|
||||
}: {
|
||||
updates: ConfigUpdates
|
||||
updates: NftConfigUpdates
|
||||
},
|
||||
funds?: Coin[],
|
||||
) => MsgExecuteContractEncodeObject
|
||||
@ -125,7 +125,7 @@ export class MarsAccountNftMessageComposer implements MarsAccountNftMessage {
|
||||
{
|
||||
updates,
|
||||
}: {
|
||||
updates: ConfigUpdates
|
||||
updates: NftConfigUpdates
|
||||
},
|
||||
funds?: Coin[],
|
||||
): MsgExecuteContractEncodeObject => {
|
||||
|
@ -15,11 +15,11 @@ import {
|
||||
ApprovalResponse,
|
||||
ApprovalsResponse,
|
||||
Binary,
|
||||
ConfigBaseForString,
|
||||
ConfigUpdates,
|
||||
ContractInfoResponse,
|
||||
Expiration,
|
||||
MinterResponse,
|
||||
NftConfigBaseForString,
|
||||
NftConfigUpdates,
|
||||
NftInfoResponseForEmpty,
|
||||
NumTokensResponse,
|
||||
OperatorsResponse,
|
||||
@ -329,12 +329,12 @@ export function useMarsAccountNftNextIdQuery<TData = Uint64>({
|
||||
)
|
||||
}
|
||||
export interface MarsAccountNftConfigQuery<TData>
|
||||
extends MarsAccountNftReactQuery<ConfigBaseForString, TData> {}
|
||||
export function useMarsAccountNftConfigQuery<TData = ConfigBaseForString>({
|
||||
extends MarsAccountNftReactQuery<NftConfigBaseForString, TData> {}
|
||||
export function useMarsAccountNftConfigQuery<TData = NftConfigBaseForString>({
|
||||
client,
|
||||
options,
|
||||
}: MarsAccountNftConfigQuery<TData>) {
|
||||
return useQuery<ConfigBaseForString, Error, TData>(
|
||||
return useQuery<NftConfigBaseForString, Error, TData>(
|
||||
marsAccountNftQueryKeys.config(client?.contractAddress),
|
||||
() => (client ? client.config() : Promise.reject(new Error('Invalid client'))),
|
||||
{ ...options, enabled: !!client && (options?.enabled != undefined ? options.enabled : true) },
|
||||
@ -545,7 +545,7 @@ export function useMarsAccountNftAcceptMinterRoleMutation(
|
||||
export interface MarsAccountNftUpdateConfigMutation {
|
||||
client: MarsAccountNftClient
|
||||
msg: {
|
||||
updates: ConfigUpdates
|
||||
updates: NftConfigUpdates
|
||||
}
|
||||
args?: {
|
||||
fee?: number | StdFee | 'auto'
|
||||
|
@ -15,7 +15,7 @@ export interface InstantiateMsg {
|
||||
export type ExecuteMsg =
|
||||
| {
|
||||
update_config: {
|
||||
updates: ConfigUpdates
|
||||
updates: NftConfigUpdates
|
||||
}
|
||||
}
|
||||
| {
|
||||
@ -81,7 +81,7 @@ export type Expiration =
|
||||
}
|
||||
export type Timestamp = Uint64
|
||||
export type Uint64 = string
|
||||
export interface ConfigUpdates {
|
||||
export interface NftConfigUpdates {
|
||||
max_value_for_burn?: Uint128 | null
|
||||
proposed_new_minter?: string | null
|
||||
}
|
||||
@ -183,7 +183,7 @@ export interface ApprovalResponse {
|
||||
export interface ApprovalsResponse {
|
||||
approvals: Approval[]
|
||||
}
|
||||
export interface ConfigBaseForString {
|
||||
export interface NftConfigBaseForString {
|
||||
max_value_for_burn: Uint128
|
||||
proposed_new_minter?: string | null
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import {
|
||||
ArrayOfCoin,
|
||||
ArrayOfCoinBalanceResponseItem,
|
||||
ArrayOfDebtShares,
|
||||
ArrayOfLentShares,
|
||||
ArrayOfSharesResponseItem,
|
||||
ArrayOfString,
|
||||
ArrayOfVaultInfoResponse,
|
||||
@ -23,6 +24,8 @@ import {
|
||||
ConfigUpdates,
|
||||
DebtShares,
|
||||
HealthResponse,
|
||||
LentShares,
|
||||
NftConfigUpdates,
|
||||
Positions,
|
||||
Uint128,
|
||||
VaultBaseForString,
|
||||
@ -68,6 +71,21 @@ export interface MarsCreditManagerReadOnlyInterface {
|
||||
limit?: number
|
||||
startAfter?: string
|
||||
}) => Promise<ArrayOfDebtShares>
|
||||
allLentShares: ({
|
||||
limit,
|
||||
startAfter,
|
||||
}: {
|
||||
limit?: number
|
||||
startAfter?: string[][]
|
||||
}) => Promise<ArrayOfSharesResponseItem>
|
||||
totalLentShares: () => Promise<LentShares>
|
||||
allTotalLentShares: ({
|
||||
limit,
|
||||
startAfter,
|
||||
}: {
|
||||
limit?: number
|
||||
startAfter?: string
|
||||
}) => Promise<ArrayOfLentShares>
|
||||
allVaultPositions: ({
|
||||
limit,
|
||||
startAfter,
|
||||
@ -108,6 +126,9 @@ export class MarsCreditManagerQueryClient implements MarsCreditManagerReadOnlyIn
|
||||
this.allDebtShares = this.allDebtShares.bind(this)
|
||||
this.totalDebtShares = this.totalDebtShares.bind(this)
|
||||
this.allTotalDebtShares = this.allTotalDebtShares.bind(this)
|
||||
this.allLentShares = this.allLentShares.bind(this)
|
||||
this.totalLentShares = this.totalLentShares.bind(this)
|
||||
this.allTotalLentShares = this.allTotalLentShares.bind(this)
|
||||
this.allVaultPositions = this.allVaultPositions.bind(this)
|
||||
this.totalVaultCoinBalance = this.totalVaultCoinBalance.bind(this)
|
||||
this.allTotalVaultCoinBalances = this.allTotalVaultCoinBalances.bind(this)
|
||||
@ -209,6 +230,39 @@ export class MarsCreditManagerQueryClient implements MarsCreditManagerReadOnlyIn
|
||||
},
|
||||
})
|
||||
}
|
||||
allLentShares = async ({
|
||||
limit,
|
||||
startAfter,
|
||||
}: {
|
||||
limit?: number
|
||||
startAfter?: string[][]
|
||||
}): Promise<ArrayOfSharesResponseItem> => {
|
||||
return this.client.queryContractSmart(this.contractAddress, {
|
||||
all_lent_shares: {
|
||||
limit,
|
||||
start_after: startAfter,
|
||||
},
|
||||
})
|
||||
}
|
||||
totalLentShares = async (): Promise<LentShares> => {
|
||||
return this.client.queryContractSmart(this.contractAddress, {
|
||||
total_lent_shares: {},
|
||||
})
|
||||
}
|
||||
allTotalLentShares = async ({
|
||||
limit,
|
||||
startAfter,
|
||||
}: {
|
||||
limit?: number
|
||||
startAfter?: string
|
||||
}): Promise<ArrayOfLentShares> => {
|
||||
return this.client.queryContractSmart(this.contractAddress, {
|
||||
all_total_lent_shares: {
|
||||
limit,
|
||||
start_after: startAfter,
|
||||
},
|
||||
})
|
||||
}
|
||||
allVaultPositions = async ({
|
||||
limit,
|
||||
startAfter,
|
||||
@ -288,9 +342,9 @@ export interface MarsCreditManagerInterface extends MarsCreditManagerReadOnlyInt
|
||||
) => Promise<ExecuteResult>
|
||||
updateConfig: (
|
||||
{
|
||||
newConfig,
|
||||
updates,
|
||||
}: {
|
||||
newConfig: ConfigUpdates
|
||||
updates: ConfigUpdates
|
||||
},
|
||||
fee?: number | StdFee | 'auto',
|
||||
memo?: string,
|
||||
@ -301,6 +355,16 @@ export interface MarsCreditManagerInterface extends MarsCreditManagerReadOnlyInt
|
||||
memo?: string,
|
||||
funds?: Coin[],
|
||||
) => Promise<ExecuteResult>
|
||||
updateNftConfig: (
|
||||
{
|
||||
updates,
|
||||
}: {
|
||||
updates: NftConfigUpdates
|
||||
},
|
||||
fee?: number | StdFee | 'auto',
|
||||
memo?: string,
|
||||
funds?: Coin[],
|
||||
) => Promise<ExecuteResult>
|
||||
callback: (
|
||||
fee?: number | StdFee | 'auto',
|
||||
memo?: string,
|
||||
@ -324,6 +388,7 @@ export class MarsCreditManagerClient
|
||||
this.updateCreditAccount = this.updateCreditAccount.bind(this)
|
||||
this.updateConfig = this.updateConfig.bind(this)
|
||||
this.updateOwner = this.updateOwner.bind(this)
|
||||
this.updateNftConfig = this.updateNftConfig.bind(this)
|
||||
this.callback = this.callback.bind(this)
|
||||
}
|
||||
|
||||
@ -371,9 +436,9 @@ export class MarsCreditManagerClient
|
||||
}
|
||||
updateConfig = async (
|
||||
{
|
||||
newConfig,
|
||||
updates,
|
||||
}: {
|
||||
newConfig: ConfigUpdates
|
||||
updates: ConfigUpdates
|
||||
},
|
||||
fee: number | StdFee | 'auto' = 'auto',
|
||||
memo?: string,
|
||||
@ -384,7 +449,7 @@ export class MarsCreditManagerClient
|
||||
this.contractAddress,
|
||||
{
|
||||
update_config: {
|
||||
new_config: newConfig,
|
||||
updates,
|
||||
},
|
||||
},
|
||||
fee,
|
||||
@ -408,6 +473,29 @@ export class MarsCreditManagerClient
|
||||
funds,
|
||||
)
|
||||
}
|
||||
updateNftConfig = async (
|
||||
{
|
||||
updates,
|
||||
}: {
|
||||
updates: NftConfigUpdates
|
||||
},
|
||||
fee: number | StdFee | 'auto' = 'auto',
|
||||
memo?: string,
|
||||
funds?: Coin[],
|
||||
): Promise<ExecuteResult> => {
|
||||
return await this.client.execute(
|
||||
this.sender,
|
||||
this.contractAddress,
|
||||
{
|
||||
update_nft_config: {
|
||||
updates,
|
||||
},
|
||||
},
|
||||
fee,
|
||||
memo,
|
||||
funds,
|
||||
)
|
||||
}
|
||||
callback = async (
|
||||
fee: number | StdFee | 'auto' = 'auto',
|
||||
memo?: string,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user