Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ jobs:
npm ci
npm run build
npm test
- name: "Build React UI"
working-directory: src/ui
run: |
npm ci
npm test -- --watchAll=false
npm run build
- name: "Build post-deployment package"
working-directory: postdeploy
run: |
Expand Down
1 change: 0 additions & 1 deletion src/ui/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ const App = () => {

useEffect(() => {
const doMarketAction = () => {
console.log('doMarketAction');
dispatch(marketAction(comptroller, protocolAddresses, server));
};
doMarketAction();
Expand Down
37 changes: 32 additions & 5 deletions src/ui/src/App.test.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,35 @@
import { render, screen } from '@testing-library/react';
import App from './App';
import { createTheme, ThemeProvider } from '@mui/material/styles';
import Switch from './components/Switch';
import { isRecoveryMode } from './components/Constants';

test('renders learn react link', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
const originalEnvironment = process.env.REACT_APP_ENV;
const theme = createTheme();

const renderSwitch = () => render(
<ThemeProvider theme={theme}>
<Switch data={{ collateral: true }} />
</ThemeProvider>
);

afterEach(() => {
process.env.REACT_APP_ENV = originalEnvironment;
});

test('disables collateral controls in Guard recovery mode', () => {
process.env.REACT_APP_ENV = 'mainnet';

renderSwitch();

expect(isRecoveryMode()).toBe(true);
expect(screen.getByRole('checkbox')).toBeDisabled();
});

test('enables collateral controls outside Guard recovery mode', () => {
process.env.REACT_APP_ENV = 'tezosx-previewnet';

renderSwitch();

expect(isRecoveryMode()).toBe(false);
expect(screen.getByRole('checkbox')).toBeEnabled();
});
14 changes: 11 additions & 3 deletions src/ui/src/components/AllMarketModal/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ const AllMarketModal = (props) => {
const classes = useStyles();
const dispatch = useDispatch();

const { open, close, tokenDetails, tab} = props;
const {
open, close, tokenDetails, tab
} = props;

const { account } = useSelector((state) => state.addWallet);
const { protocolAddresses, comptroller } = useSelector((state) => state.nodes);
Expand Down Expand Up @@ -52,7 +54,7 @@ const AllMarketModal = (props) => {
const [pendingLimit, setPendingLimit] = useState('');
const [pendingLimitUsed, setPendingLimitUsed] = useState('');

const buttonOne = useSupplyErrorText(tokenValue, useMaxAmount);
const buttonOne = useSupplyErrorText(tokenValue, useMaxAmount, tokenDetails);
const buttonTwo = useBorrowErrorText(tokenValue, borrowLimit, tokenDetails);

const handleOpenInitialize = () => setInitializeModal(true);
Expand All @@ -62,13 +64,19 @@ const AllMarketModal = (props) => {
const handleCloseError = () => setErrorModal(false);

const supplyToken = async () => {
if (!tokenDetails.isListed || tokenDetails.mintPaused) {
return;
}
// eslint-disable-next-line no-shadow
const { opGroup, error } = await supplyTokenAction(tokenDetails, amount, close, setTokenText, handleOpenInitialize, protocolAddresses, publicKeyHash);
setOpGroup(opGroup);
setEvaluationError(error);
};

const borrowToken = async () => {
if (!tokenDetails.isListed || tokenDetails.borrowPaused) {
return;
}
// eslint-disable-next-line no-shadow
const { opGroup, error } = await borrowTokenAction(tokenDetails, amount, close, setTokenText, handleOpenInitialize, protocolAddresses, publicKeyHash);
setOpGroup(opGroup);
Expand Down Expand Up @@ -171,7 +179,7 @@ const AllMarketModal = (props) => {
APYTextTwo="Borrow APY"
CurrentStateText= "Currently Supplying"
CurrentStateTextTwo= "Currently Borrowing"
tab={tab ? tab : "one"}
tab={tab || 'one'}
open={open}
close={close}
tokenDetails={tokenDetails}
Expand Down
13 changes: 9 additions & 4 deletions src/ui/src/components/BorrowModal/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ import { useStyles } from './style';
const BorrowModal = (props) => {
const classes = useStyles();
const dispatch = useDispatch();
const { open, close, tokenDetails, tab } = props;
const {
open, close, tokenDetails, tab
} = props;

const { account } = useSelector((state) => state.addWallet);
const { protocolAddresses, comptroller } = useSelector((state) => state.nodes);
Expand Down Expand Up @@ -61,6 +63,9 @@ const BorrowModal = (props) => {
const handleCloseError = () => setErrorModal(false);

const borrowToken = async () => {
if (!tokenDetails.isListed || tokenDetails.borrowPaused) {
return;
}
// eslint-disable-next-line no-shadow
const { opGroup, error } = await borrowTokenAction(
tokenDetails,
Expand All @@ -69,7 +74,7 @@ const BorrowModal = (props) => {
setTokenText,
handleOpenInitialize,
protocolAddresses,
publicKeyHash,
publicKeyHash
);
setOpGroup(opGroup);
setEvaluationError(error);
Expand All @@ -84,7 +89,7 @@ const BorrowModal = (props) => {
setTokenText,
handleOpenInitialize,
protocolAddresses,
publicKeyHash,
publicKeyHash
);
setOpGroup(opGroup);
setEvaluationError(error);
Expand Down Expand Up @@ -174,7 +179,7 @@ const BorrowModal = (props) => {
const pendingBorrowLimit = totalCollateral - pendingBorrowing;
setPendingLimit(pendingBorrowLimit);
setPendingLimitUsed(
new BigNumber(pendingBorrowing).dividedBy(new BigNumber(totalCollateral)).multipliedBy(100),
new BigNumber(pendingBorrowing).dividedBy(new BigNumber(totalCollateral)).multipliedBy(100)
);
}

Expand Down
2 changes: 2 additions & 0 deletions src/ui/src/components/Constants/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ export const getAddresses = () => {
}
};

export const isRecoveryMode = () => Boolean(getAddresses().comptrollerDataSource);

const addresses = getAddresses();

export const tokens = [
Expand Down
77 changes: 46 additions & 31 deletions src/ui/src/components/Dashboard/BorrowMarketTokenTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,21 @@ import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
import { Button, Typography } from '@mui/material';

import { decimalify, getExplorerLink, nFormatter, roundValue } from '../../util';
import {
decimalify, getExplorerLink, nFormatter, roundValue
} from '../../util';

import AllMarketModal from '../AllMarketModal';
import TableSkeleton from '../Skeleton';

import { useStyles } from './style';
import { getAddresses } from '../Constants';
import { getAddresses, isRecoveryMode } from '../Constants';

const BorrowMarketTokenTable = (props) => {
const classes = useStyles();
const { tableData } = props;
const { address } = useSelector((state: any) => state.addWallet.account);
const recoveryMode = isRecoveryMode();

const [tokenDetails, setTokenDetails] = useState();
const [openMktModal, setMktModal] = useState(false);
Expand All @@ -47,6 +50,15 @@ const BorrowMarketTokenTable = (props) => {
setMktModal(true);
};

const formatBorrowRate = (borrowRate) => {
if (borrowRate <= 0) {
return '0';
}
return new BigNumber(borrowRate).gt(new BigNumber(10000000000000000))
? roundValue(decimalify(borrowRate, 18))
: '<0.01';
};

return (
<TableContainer className={`${classes.root} ${classes.tableCon}`}>
{tokenDetails && (
Expand Down Expand Up @@ -87,21 +99,23 @@ const BorrowMarketTokenTable = (props) => {
</div>
</TableCell>
<TableCell align="center">
<span className={classes.clearFont}>
{recoveryMode ? (
<span className={classes.faintFont}>Unavailable</span>
) : <><span className={classes.clearFont}>
{data.marketSize > 0
? decimalify(
data.available.toString(),
decimals[data.title],
decimals[data.title],
) < 0.01
data.available.toString(),
decimals[data.title],
decimals[data.title]
) < 0.01
? '>0.00'
: nFormatter(
decimalify(
data.available.toString(),
decimals[data.title],
decimals[data.title],
),
)
decimalify(
data.available.toString(),
decimals[data.title],
decimals[data.title]
)
)
: '0'}{' '}
{data.title}
</span>{' '}
Expand All @@ -110,26 +124,21 @@ const BorrowMarketTokenTable = (props) => {
$
{data.marketSize > 0
? nFormatter(
decimalify(
(
(data.marketSize - data.totalBorrowed) *
data.usdPrice
).toString(),
decimals[data.title],
decimals[data.title],
),
)
decimalify(
(
(data.marketSize - data.totalBorrowed)
* data.usdPrice
).toString(),
decimals[data.title],
decimals[data.title]
)
)
: '0.00'}
</span>
</span></>}
</TableCell>
<TableCell align="center" className={classes.clearFont}>
<span>
{data.borrowRate > 0
? // checks if rate is lower than 0.1% (all rates lower than 0.01% is shown as <0.01%)
new BigNumber(data.borrowRate).gt(new BigNumber(10000000000000000))
? roundValue(decimalify(data.borrowRate, 18))
: '<0.01'
: '0'}
{formatBorrowRate(data.borrowRate)}
%
</span>
</TableCell>
Expand All @@ -139,6 +148,12 @@ const BorrowMarketTokenTable = (props) => {
size="medium"
className={classes.borrowButton}
onClick={() => handleClickMktModal(data)}
disabled={!data.isListed || data.borrowPaused}
title={
!data.isListed || data.borrowPaused
? 'Borrowing is temporarily disabled for this market.'
: undefined
}
sx={{ textTransform: 'capitalize' }}
>
Borrow
Expand All @@ -148,11 +163,11 @@ const BorrowMarketTokenTable = (props) => {
<Button
variant="contained"
size="medium"
className={classes.detailsButton}
className={classes.detailsButton}
onClick={() => handleClickDetails(data.assetType)}
sx={{ textTransform: 'capitalize' }}
>
Details
Details
</Button>
</TableCell>
</TableRow>
Expand Down
Loading
Loading