@material-ui/core#OutlinedInput TypeScript Examples
The following examples show how to use
@material-ui/core#OutlinedInput.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: path_setup.tsx From jupyter-extensions with Apache License 2.0 | 6 votes |
render(): React.ReactElement {
return (
<FormControl
className={classes(setupItemClass)}
disabled
variant="outlined"
>
<FormHelperText className={setupHelperTextClass}>
Repository
</FormHelperText>
<OutlinedInput
className={classes(setupItemInnerClass)}
value={this.state.path}
style={{ color: 'var(--jp-ui-font-color0)' }}
/>
</FormControl>
);
}
Example #2
Source File: FilterInput.tsx From ow-mod-manager with MIT License | 6 votes |
FilterInput: React.FunctionComponent<Props> = ({
value,
onChange,
label,
}) => {
const [filterText, setFilterText] = useState(value);
const debouncedFilterText = useDebounce(filterText, 200);
useEffect(() => {
onChange(debouncedFilterText);
}, [debouncedFilterText, onChange]);
return (
<OutlinedInput
margin="dense"
onChange={({ currentTarget }) => {
setFilterText(currentTarget.value);
}}
value={filterText}
placeholder={label}
color="secondary"
startAdornment={
<InputAdornment position="start">
<SearchIcon />
</InputAdornment>
}
endAdornment={
filterText !== '' && (
<InputAdornment position="end">
<IconButton onClick={() => setFilterText('')} size="small">
<CloseIcon fontSize="small" />
</IconButton>
</InputAdornment>
)
}
/>
);
}
Example #3
Source File: AdvancedSettings.tsx From lobis-frontend with MIT License | 5 votes |
function AdvancedSettings({ open, handleClose, slippage, recipientAddress, onRecipientAddressChange, onSlippageChange }: IAdvancedSettingsProps) {
return (
<Modal id="hades" open={open} onClose={handleClose} hideBackdrop>
<Paper className="ohm-card ohm-popover">
<div className="cross-wrap">
<IconButton onClick={handleClose}>
<SvgIcon color="primary" component={XIcon} />
</IconButton>
</div>
<Box className="card-content">
<InputLabel htmlFor="slippage">
<p className="input-lable">Slippage</p>
</InputLabel>
<FormControl variant="outlined" color="primary" fullWidth>
<OutlinedInput
id="slippage"
value={slippage}
onChange={onSlippageChange}
fullWidth
type="number"
//@ts-ignore
max="100"
min="100"
className="bond-input"
endAdornment={
<InputAdornment position="end">
<p className="percent">%</p>
</InputAdornment>
}
/>
<div className="help-text">
<p className="text-bond-desc">Transaction may revert if price changes by more than slippage %</p>
</div>
</FormControl>
</Box>
</Paper>
</Modal>
);
}
Example #4
Source File: AdvancedSettings.tsx From rugenerous-frontend with MIT License | 5 votes |
function AdvancedSettings({
open,
handleClose,
slippage,
recipientAddress,
onRecipientAddressChange,
onSlippageChange,
}: IAdvancedSettingsProps) {
const [value, setValue] = useState(slippage);
useEffect(() => {
let timeount: any = null;
clearTimeout(timeount);
timeount = setTimeout(() => onSlippageChange(value), 1000);
return () => clearTimeout(timeount);
}, [value]);
return (
<Modal id="hades" open={open} onClose={handleClose} hideBackdrop>
<Paper className="ohm-card ohm-popover">
<div className="cross-wrap">
<IconButton onClick={handleClose}>
<SvgIcon color="primary" component={XIcon} />
</IconButton>
</div>
<p className="hades-title">Settings</p>
<Box className="card-content">
<InputLabel htmlFor="slippage">
<p className="input-lable">Slippage</p>
</InputLabel>
<FormControl variant="outlined" color="primary" fullWidth>
<OutlinedInput
id="slippage"
value={value}
onChange={(e: any) => setValue(e.target.value)}
fullWidth
type="number"
className="bond-input"
endAdornment={
<InputAdornment position="end">
<p className="percent">%</p>
</InputAdornment>
}
/>
<div className="help-text">
<p className="text-bond-desc">Transaction may revert if price changes by more than slippage %</p>
</div>
</FormControl>
<InputLabel htmlFor="recipient">
<p className="input-lable">Recipient Address</p>
</InputLabel>
<FormControl variant="outlined" color="primary" fullWidth>
<OutlinedInput
className="bond-input"
id="recipient"
value={recipientAddress}
onChange={onRecipientAddressChange}
type="text"
/>
<div className="help-text">
<p className="text-bond-desc">
Choose recipient address. By default, this is your currently connected address
</p>
</div>
</FormControl>
</Box>
</Paper>
</Modal>
);
}
Example #5
Source File: index.tsx From rugenerous-frontend with MIT License | 5 votes |
function ChooseToken({ open, handleClose, handleSelect, bond }: IChooseTokenProps) {
const { tokens, loading } = useTokens();
const [quantity, setQuantity] = useState("");
const filtredTokens = tokens.filter(({ name, address, isAvax }) => {
let addressTest = true;
if (quantity && quantity.length === 42) {
addressTest = address.toLocaleLowerCase() === quantity.toLowerCase();
}
let nameTest = true;
if (quantity && quantity.length < 10) {
nameTest = name.toLowerCase().includes(quantity.toLowerCase());
}
let lpFilter = true;
if (bond.name === mim.name) {
lpFilter = mimToken.address !== address;
}
// if (bond.name === wavax.name) {
// lpFilter = isAvax ? false : wavaxToken.address !== address;
// }
return nameTest && addressTest && lpFilter;
});
return (
<Modal id="hades" open={open} onClose={handleClose} hideBackdrop>
<Paper className="ohm-card ohm-popover choose-token-poper">
<div className="cross-wrap">
<IconButton onClick={handleClose}>
<SvgIcon color="primary" component={XIcon} />
</IconButton>
</div>
<Box>
<div className="choose-token-poper-header">
<p className="choose-token-poper-header-title">Choose token</p>
<OutlinedInput
placeholder="Search name or paste address"
className="choose-token-poper-header-input"
value={quantity}
onChange={e => setQuantity(e.target.value)}
labelWidth={0}
startAdornment={
<InputAdornment position="start">
<Box display="flex" alignItems="center" justifyContent="center" width={"24px"}>
<img src={IconsSearch} style={{ height: "24px", width: "24px" }} />
</Box>
</InputAdornment>
}
/>
</div>
<div className="choose-token-poper-body">
{filtredTokens.map(token => (
<div onClick={() => handleSelect(token)} key={token.address} className="choose-token-poper-body-item">
<img className="choose-token-poper-body-item-img" src={token.img} alt="" />
<div className="choose-token-poper-body-item-desc">
<p className="choose-token-poper-body-item-name">{token.name}</p>
<div className="choose-token-poper-body-item-balance">
{loading ? <Skeleton width="50px" /> : <p>{trim(token.balance, 6)}</p>}
</div>
</div>
</div>
))}
</div>
</Box>
</Paper>
</Modal>
);
}
Example #6
Source File: MaxDepthFilter.tsx From backstage with Apache License 2.0 | 5 votes |
MaxDepthFilter = ({ value, onChange }: Props) => {
const classes = useStyles();
const handleChange = useCallback(
(event: React.ChangeEvent<HTMLInputElement>) => {
const v = Number(event.target.value);
onChange(v <= 0 ? Number.POSITIVE_INFINITY : v);
},
[onChange],
);
const reset = useCallback(() => {
onChange(Number.POSITIVE_INFINITY);
}, [onChange]);
return (
<Box pb={1} pt={1}>
<FormControl variant="outlined" className={classes.formControl}>
<Typography variant="button">Max Depth</Typography>
<OutlinedInput
type="number"
placeholder="∞ Infinite"
value={isFinite(value) ? value : ''}
onChange={handleChange}
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="clear max depth"
onClick={reset}
edge="end"
>
<ClearIcon />
</IconButton>
</InputAdornment>
}
inputProps={{
'aria-label': 'maxp',
}}
labelWidth={0}
/>
</FormControl>
</Box>
);
}
Example #7
Source File: index.tsx From wonderland-frontend with MIT License | 5 votes |
function ChooseToken({ open, handleClose, handleSelect, bond }: IChooseTokenProps) {
const { tokens, loading } = useTokens();
const [quantity, setQuantity] = useState("");
const filtredTokens = tokens.filter(({ name, address, isAvax }) => {
let addressTest = true;
if (quantity && quantity.length === 42) {
addressTest = address.toLocaleLowerCase() === quantity.toLowerCase();
}
let nameTest = true;
if (quantity && quantity.length < 10) {
nameTest = name.toLowerCase().includes(quantity.toLowerCase());
}
let lpFilter = true;
if (bond.name === mim.name) {
lpFilter = mimToken.address !== address;
}
if (bond.name === wavax.name) {
lpFilter = isAvax ? false : wavaxToken.address !== address;
}
return nameTest && addressTest && lpFilter;
});
return (
<Modal id="hades" open={open} onClose={handleClose} hideBackdrop>
<Paper className="ohm-card ohm-popover choose-token-poper">
<div className="cross-wrap">
<IconButton onClick={handleClose}>
<SvgIcon color="primary" component={XIcon} />
</IconButton>
</div>
<Box>
<div className="choose-token-poper-header">
<p className="choose-token-poper-header-title">Choose token</p>
<OutlinedInput
placeholder="Search name or paste address"
className="choose-token-poper-header-input"
value={quantity}
onChange={e => setQuantity(e.target.value)}
labelWidth={0}
startAdornment={
<InputAdornment position="start">
<Box display="flex" alignItems="center" justifyContent="center" width={"24px"}>
<img src={IconsSearch} style={{ height: "24px", width: "24px" }} />
</Box>
</InputAdornment>
}
/>
</div>
<div className="choose-token-poper-body">
{filtredTokens.map(token => (
<div onClick={() => handleSelect(token)} key={token.address} className="choose-token-poper-body-item">
<img className="choose-token-poper-body-item-img" src={token.img} alt="" />
<div className="choose-token-poper-body-item-desc">
<p className="choose-token-poper-body-item-name">{token.name}</p>
<div className="choose-token-poper-body-item-balance">{loading ? <Skeleton width="50px" /> : <p>{trim(token.balance, 6)}</p>}</div>
</div>
</div>
))}
</div>
</Box>
</Paper>
</Modal>
);
}
Example #8
Source File: AdvancedSettings.tsx From wonderland-frontend with MIT License | 5 votes |
function AdvancedSettings({ open, handleClose, slippage, onSlippageChange }: IAdvancedSettingsProps) {
const [value, setValue] = useState(slippage);
useEffect(() => {
let timeount: any = null;
clearTimeout(timeount);
timeount = setTimeout(() => onSlippageChange(value), 1000);
return () => clearTimeout(timeount);
}, [value]);
return (
<Modal id="hades" open={open} onClose={handleClose} hideBackdrop>
<Paper className="ohm-card ohm-popover">
<div className="cross-wrap">
<IconButton onClick={handleClose}>
<SvgIcon color="primary" component={XIcon} />
</IconButton>
</div>
<p className="hades-title">Settings</p>
<Box className="card-content">
<InputLabel htmlFor="slippage">
<p className="input-lable">Slippage</p>
</InputLabel>
<FormControl variant="outlined" color="primary" fullWidth>
<OutlinedInput
id="slippage"
value={value}
onChange={(e: any) => setValue(e.target.value)}
fullWidth
type="number"
className="bond-input"
endAdornment={
<InputAdornment position="end">
<p className="percent">%</p>
</InputAdornment>
}
/>
<div className="help-text">
<p className="text-bond-desc">Transaction may revert if price changes by more than slippage %</p>
</div>
</FormControl>
</Box>
</Paper>
</Modal>
);
}
Example #9
Source File: App.tsx From isitworththecost with MIT License | 4 votes |
function App() {
const classes = useStyles()
const [values, setValues] = React.useState({
timeCost: { value: 25, unit: 'dollars', period: 'hour' },
serviceCost: { value: 125, unit: 'dollars', period: 'month' },
trainingTime: { value: 2, unit: 'hour', period: null },
timeSavings: { value: 60, unit: 'min', period: 'day' },
peopleCount: { value: 1, unit: null, period: null },
savingPeriodCost: 'year',
savingPeriodPeople: 'day',
paybackPeriod: 'day',
})
const [costs, setCosts] = React.useState({
employeePerYear: 0,
servicePerYear: 0,
trainingPerYear: 0,
savingsPerYear: 0,
freeTimePerYear: 0,
paybackTimePerYear: 0,
})
const handleChange = (prop: string, key: string | null = null) => (
event: ChangeEvent<HTMLInputElement | { value: unknown }>,
): void => {
let val: any = event.target.value
if (key === null) {
setValues({
...values,
[prop]: val,
})
} else {
if (key === 'value' && (val < 0 || isNaN(val))) {
val = 0
}
setValues({
...values,
[prop]: {
//@ts-ignore
value: values[prop].value,
//@ts-ignore
unit: values[prop].unit,
//@ts-ignore
period: values[prop].period,
//@ts-ignore
[key]: val,
},
})
}
}
useEffect(() => {
// save this to state for now for ease of visibility
const employeePerYear =
values.timeCost.value * periodToYear(values.timeCost.period, 1)
const servicePerYear =
values.serviceCost.value *
periodToYear(values.serviceCost.period, 1)
// assumes amortisation period of 1 year
const trainingPerYear =
unitToYear(values.trainingTime.unit, values.trainingTime.value) *
employeePerYear *
values.peopleCount.value
const freeTimePerYear =
periodToYear(
values.timeSavings.period,
unitToYear(values.timeSavings.unit, values.timeSavings.value),
) * values.peopleCount.value
const savingsPerYear =
employeePerYear * freeTimePerYear - servicePerYear - trainingPerYear
const paybackTimePerYear =
(trainingPerYear + servicePerYear) / employeePerYear
setCosts({
employeePerYear,
servicePerYear,
trainingPerYear,
savingsPerYear,
freeTimePerYear,
paybackTimePerYear,
})
}, [values])
return (
<Container maxWidth={'md'}>
<Paper className={classes.root} variant={'outlined'}>
<div className={classes.heading}>
<TopControls />
<Typography variant="h2" component="h1">
Is it worth the cost?
</Typography>
<Typography variant="h5" component="p" gutterBottom>
A simple check on whether purchasing a service is worth
the cost.
</Typography>
</div>
<Grid container>
<Grid item xs={12} md={6}>
<h2>Basics</h2>
<p>1. Cost of your time or an employees time.</p>
<FormControl
className={clsx(classes.margin, classes.textField)}
variant="outlined"
>
<InputLabel htmlFor="time-cost">
Time Cost
</InputLabel>
<OutlinedInput
id="time-cost"
value={values.timeCost.value}
type="number"
onChange={handleChange('timeCost', 'value')}
startAdornment={
<InputAdornment position="start">
<AttachMoneyIcon />
</InputAdornment>
}
labelWidth={80}
/>
</FormControl>
<FormControl
variant="outlined"
className={classes.margin}
>
<InputLabel htmlFor="time-cost-unit">
per
</InputLabel>
<Select
native
value={values.timeCost.period}
onChange={handleChange('timeCost', 'period')}
labelWidth={40}
inputProps={{
name: 'per',
id: 'time-cost-unit',
}}
>
<option value={'hour'}>hour</option>
<option value={'day'}>day</option>
<option value={'week'}>week</option>
<option value={'month'}>month</option>
<option value={'year'}>year</option>
</Select>
</FormControl>
<p>2. Cost of the service under consideration.</p>
<FormControl
className={clsx(classes.margin, classes.textField)}
variant="outlined"
>
<InputLabel htmlFor="service-cost">
Service Cost
</InputLabel>
<OutlinedInput
id="service-cost"
value={values.serviceCost.value}
type="number"
onChange={handleChange('serviceCost', 'value')}
startAdornment={
<InputAdornment position="start">
<AttachMoneyIcon />
</InputAdornment>
}
labelWidth={95}
/>
</FormControl>
<FormControl
variant="outlined"
className={classes.margin}
>
<InputLabel htmlFor="service-cost-period">
per
</InputLabel>
<Select
native
value={values.serviceCost.period}
onChange={handleChange('serviceCost', 'period')}
labelWidth={40}
inputProps={{
name: 'per',
id: 'service-cost-period',
}}
>
{/*<option value={'hour'}>hour</option>*/}
<option value={'day'}>day</option>
<option value={'week'}>week</option>
<option value={'month'}>month</option>
<option value={'year'}>year</option>
</Select>
</FormControl>
<p>
3. Estimate the training time required (one person).
</p>
<FormControl
fullWidth
className={clsx(classes.margin, classes.textField)}
variant="outlined"
>
<InputLabel htmlFor="training-time">
Training Time
</InputLabel>
<OutlinedInput
id="training-time"
value={values.trainingTime.value}
type="number"
onChange={handleChange('trainingTime', 'value')}
startAdornment={
<InputAdornment position="start">
<AccessTimeIcon />
</InputAdornment>
}
labelWidth={105}
/>
</FormControl>
<FormControl
variant="outlined"
className={classes.margin}
>
<Select
native
value={values.trainingTime.unit}
onChange={handleChange('trainingTime', 'unit')}
inputProps={{
name: 'per',
id: 'training-time-unit',
}}
>
<option value={'hour'}>hours</option>
<option value={'day'}>days</option>
<option value={'week'}>weeks</option>
<option value={'month'}>months</option>
{/*<option value={'year'}>years</option>*/}
</Select>
</FormControl>
<p>
4. Estimate the time this service will save (one
person).
</p>
<FormControl
className={clsx(classes.margin, classes.textField)}
variant="outlined"
>
<InputLabel htmlFor="time-savings">
Time Saved
</InputLabel>
<OutlinedInput
id="time-savings"
type="number"
value={values.timeSavings.value}
onChange={handleChange('timeSavings', 'value')}
startAdornment={
<InputAdornment position="start">
<AccessTimeIcon />
</InputAdornment>
}
labelWidth={80}
/>
</FormControl>
<FormControl
variant="outlined"
className={classes.margin}
>
<Select
native
value={values.timeSavings.unit}
onChange={handleChange('timeSavings', 'unit')}
>
<option value={'minute'}>minutes</option>
<option value={'hour'}>hours</option>
<option value={'day'}>days</option>
<option value={'week'}>weeks</option>
<option value={'month'}>months</option>
</Select>
</FormControl>
<FormControl
variant="outlined"
className={classes.margin}
>
<InputLabel htmlFor="time-savings-period">
per
</InputLabel>
<Select
id={'time-savings-period'}
native
value={values.timeSavings.period}
onChange={handleChange('timeSavings', 'period')}
labelWidth={40}
>
<option value={'hour'}>hour</option>
<option value={'day'}>day</option>
<option value={'week'}>week</option>
<option value={'month'}>month</option>
<option value={'year'}>year</option>
</Select>
</FormControl>
<p>5. Number of people using the service.</p>
<FormControl
className={clsx(classes.margin, classes.textField)}
variant="outlined"
>
<InputLabel htmlFor="people-count">
People
</InputLabel>
<OutlinedInput
id="people-count"
type="number"
value={values.peopleCount.value}
onChange={handleChange('peopleCount', 'value')}
startAdornment={
<InputAdornment position="start">
<EmojiPeopleIcon />
</InputAdornment>
}
labelWidth={50}
/>
</FormControl>
</Grid>
<Grid item xs={12} md={6}>
<Breakdown
values={values}
costs={costs}
handleChange={handleChange}
/>
</Grid>
</Grid>
</Paper>
</Container>
)
}
Example #10
Source File: OrganizationList.tsx From glific-frontend with GNU Affero General Public License v3.0 | 4 votes |
OrganizationList: React.SFC<OrganizationListProps> = ({
match,
openExtensionModal,
openCustomerModal,
}) => {
const { t } = useTranslation();
const [orgName, setOrgName] = useState('');
const history = useHistory();
const columnNames = ['NAME', 'STATUS', 'ACTIONS'];
const getName = (label: string, insertedAt: any) => (
<div className={styles.LabelContainer}>
<p className={styles.LabelText}>
{label}
<br />
<span className={styles.SubLabelText}>{moment(insertedAt).format('DD MMM YYYY')}</span>
</p>
</div>
);
const [updateOrganizationStatus] = useMutation(UPDATE_ORGANIZATION_STATUS, {
onCompleted: () => {
setNotification('Organization updated successfully');
},
});
const getStatus = (id: any, status: string) => {
const options = [
{ id: 'INACTIVE', label: <div className={styles.Inactive}>Inactive</div> },
{ id: 'APPROVED', label: 'Approved' },
{ id: 'ACTIVE', label: 'Active' },
{ id: 'SUSPENDED', label: 'Suspended' },
{ id: 'READY_TO_DELETE', label: <div className={styles.Delete}>Ready to delete</div> },
];
const statusField = {
onChange: (event: any) => {
updateOrganizationStatus({
variables: {
updateOrganizationId: id,
status: event.target.value,
},
});
},
value: status,
style: { width: '187px' },
};
return <Dropdown options={options} placeholder="" field={statusField} />;
};
const columnStyles: any = [styles.Label, styles.Status, styles.Actions];
const getColumns = ({ id, name, insertedAt, status }: any) => ({
name: getName(name, insertedAt),
isApproves: getStatus(id, status),
});
const columnAttributes = {
columnNames,
columns: getColumns,
columnStyles,
};
const listIcon = <OrganisationIcon className={styles.OrgIcon} />;
const extensionIcon = <ExtensionIcon className={styles.ExtensionIcon} />;
const customerDetailsIcon = <CustomerDetailsIcon />;
const [deleteInActiveOrg] = useMutation(DELETE_INACTIVE_ORGANIZATIONS);
const handleDeleteInActiveOrg = ({ payload, refetch, setDeleteItemID }: any) => {
deleteInActiveOrg({ variables: payload, refetchQueries: refetch });
// Setting delete item id to null to prevent showing dialogue again
setDeleteItemID(null);
setNotification('Organization deleted successfully');
};
const deleteDialogue = (id: any, name: any) => {
const component = (
<div>
<p className={styles.DialogSubText}>
This action cannot be undone. Please enter the name of organization to proceed
</p>
<OutlinedInput
fullWidth
placeholder="Organization name"
onChange={(event: any) => setOrgName(event.target.value)}
className={styles.DialogSubInput}
/>
</div>
);
const isConfirmed = orgName === name;
const payload = {
isConfirmed,
deleteOrganizationID: id,
};
return {
component,
handleOkCallback: (val: any) => handleDeleteInActiveOrg({ payload, ...val }),
isConfirmed,
};
};
const addExtension = (id: any) => {
history.push({ pathname: `/organizations/${id}/extensions` });
};
const addCustomer = (id: any) => {
history.push({ pathname: `/organizations/${id}/customer` });
};
const dialogMessage = deleteDialogue;
const additionalActions = [
{
icon: extensionIcon,
parameter: 'id',
label: t('Extension code'),
dialog: addExtension,
},
{
icon: customerDetailsIcon,
parameter: 'id',
label: t('Add/View Customer'),
dialog: addCustomer,
},
];
const addNewButton = { show: false, label: 'Add New' };
const restrictedAction = (listItem: any) => {
if (listItem.status === 'READY_TO_DELETE') {
return { delete: true, edit: false };
}
return { delete: false, edit: false };
};
return (
<>
<List
title={t('Organizations')}
listItem="organizations"
listItemName="organization"
pageLink="organization"
listIcon={listIcon}
dialogMessage={dialogMessage}
additionalAction={additionalActions}
button={addNewButton}
restrictedAction={restrictedAction}
searchParameter={['name']}
editSupport={false}
{...queries}
{...columnAttributes}
/>
<Extensions openDialog={!!openExtensionModal} match={match} />
<OrganizationCustomer openDialog={!!openCustomerModal} match={match} />
</>
);
}
Example #11
Source File: AddToMessageTemplate.tsx From glific-frontend with GNU Affero General Public License v3.0 | 4 votes |
AddToMessageTemplate: React.SFC<AddToMessageTemplateProps> = ({
id,
message,
changeDisplay,
}) => {
const [messageTemplate, setMessageTemplate] = useState<string | null>('');
const [required, setRequired] = useState(false);
const { t } = useTranslation();
const [saveTemplate] = useMutation(SAVE_MESSAGE_TEMPLATE_MUTATION, {
onCompleted: () => {
setNotification(t('Message has been successfully added to speed sends.'));
},
refetchQueries: [
{
query: FILTER_TEMPLATES,
variables: setVariables({ term: '' }),
},
],
});
const onChange = (event: any) => {
setMessageTemplate(event.target.value);
if (required) {
setRequired(false);
}
};
const textField = (
<div className={styles.DialogContainer} data-testid="templateContainer">
<FormControl fullWidth error={required}>
<InputLabel variant="outlined">Enter title</InputLabel>
<OutlinedInput
error={required}
classes={{
notchedOutline: styles.InputBorder,
}}
className={styles.Label}
label={t('Enter title')}
fullWidth
data-testid="templateInput"
onChange={onChange}
/>
{required ? <FormHelperText>{t('Required')}</FormHelperText> : null}
</FormControl>
<div className={styles.Message}>{WhatsAppToJsx(message)}</div>
</div>
);
const handleCloseButton = () => {
changeDisplay(false);
setMessageTemplate(null);
};
const handleOKButton = () => {
if (messageTemplate === '') {
setRequired(true);
} else {
saveTemplate({
variables: {
messageId: id,
templateInput: {
label: messageTemplate,
shortcode: messageTemplate,
languageId: '2',
},
},
});
changeDisplay(false);
setMessageTemplate(null);
}
};
return (
<div>
<DialogBox
handleCancel={handleCloseButton}
handleOk={handleOKButton}
title={t('Add message to speed sends')}
buttonOk={t('Save')}
>
{textField}
</DialogBox>
</div>
);
}
Example #12
Source File: Input.tsx From glific-frontend with GNU Affero General Public License v3.0 | 4 votes |
Input: React.SFC<InputProps> = ({ textArea = false, disabled = false, ...props }) => {
const {
field,
form,
helperText,
type,
togglePassword,
endAdornmentCallback,
emojiPicker,
placeholder,
editor,
rows,
endAdornment,
inputProp,
translation,
} = props;
let fieldType = type;
let fieldEndAdorment = null;
if (type === 'password') {
// we should change the type to text if user has clicked on show password
if (togglePassword) {
fieldType = 'text';
}
fieldEndAdorment = (
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
data-testid="passwordToggle"
onClick={endAdornmentCallback}
edge="end"
>
{togglePassword ? (
<Visibility classes={{ root: styles.Visibility }} />
) : (
<VisibilityOff classes={{ root: styles.Visibility }} />
)}
</IconButton>
</InputAdornment>
);
} else if (emojiPicker) {
fieldEndAdorment = emojiPicker;
} else if (type === 'otp') {
fieldType = 'text';
fieldEndAdorment = (
<InputAdornment position="end">
<IconButton
aria-label="resend otp"
data-testid="resendOtp"
onClick={endAdornmentCallback}
edge="end"
>
<p className={styles.Resend}>resend</p>{' '}
<RefreshIcon classes={{ root: styles.ResendButton }} />
</IconButton>
</InputAdornment>
);
}
let showError = false;
if (form && form.errors[field.name] && form.touched[field.name]) {
showError = true;
}
return (
<>
{translation && <div className={styles.Translation}>{translation}</div>}
<div className={styles.Input} data-testid="input">
<FormControl fullWidth error={showError}>
<InputLabel variant="outlined" className={styles.Label} data-testid="inputLabel">
{placeholder}
</InputLabel>
<OutlinedInput
data-testid="outlinedInput"
inputComponent={editor ? editor.inputComponent : undefined}
inputProps={editor ? editor.inputProps : inputProp}
type={fieldType}
classes={{ multiline: styles.Multiline }}
disabled={disabled}
error={showError}
multiline={textArea}
rows={rows}
className={styles.OutlineInput}
label={placeholder}
fullWidth
{...field}
endAdornment={endAdornment || fieldEndAdorment}
/>
{form && form.errors[field.name] && form.touched[field.name] ? (
<FormHelperText className={styles.DangerText}>{form.errors[field.name]}</FormHelperText>
) : null}
{helperText && (
<div id="helper-text" className={styles.HelperText}>
{helperText}
</div>
)}
</FormControl>
</div>
</>
);
}
Example #13
Source File: index.tsx From wonderland-frontend with MIT License | 4 votes |
function Stake() {
const dispatch = useDispatch();
const { provider, address, connect, chainID, checkWrongNetwork } = useWeb3Context();
const [view, setView] = useState(0);
const [quantity, setQuantity] = useState<string>("");
const isAppLoading = useSelector<IReduxState, boolean>(state => state.app.loading);
const currentIndex = useSelector<IReduxState, string>(state => {
return state.app.currentIndex;
});
const fiveDayRate = useSelector<IReduxState, number>(state => {
return state.app.fiveDayRate;
});
const timeBalance = useSelector<IReduxState, string>(state => {
return state.account.balances && state.account.balances.time;
});
const memoBalance = useSelector<IReduxState, string>(state => {
return state.account.balances && state.account.balances.memo;
});
const stakeAllowance = useSelector<IReduxState, number>(state => {
return state.account.staking && state.account.staking.time;
});
const unstakeAllowance = useSelector<IReduxState, number>(state => {
return state.account.staking && state.account.staking.memo;
});
const stakingRebase = useSelector<IReduxState, number>(state => {
return state.app.stakingRebase;
});
const stakingAPY = useSelector<IReduxState, number>(state => {
return state.app.stakingAPY;
});
const stakingTVL = useSelector<IReduxState, number>(state => {
return state.app.stakingTVL;
});
const pendingTransactions = useSelector<IReduxState, IPendingTxn[]>(state => {
return state.pendingTransactions;
});
const setMax = () => {
if (view === 0) {
setQuantity(timeBalance);
} else {
setQuantity(memoBalance);
}
};
const onSeekApproval = async (token: string) => {
if (await checkWrongNetwork()) return;
await dispatch(changeApproval({ address, token, provider, networkID: chainID }));
};
const onChangeStake = async (action: string) => {
if (await checkWrongNetwork()) return;
if (quantity === "" || parseFloat(quantity) === 0) {
dispatch(warning({ text: action === "stake" ? messages.before_stake : messages.before_unstake }));
} else {
await dispatch(changeStake({ address, action, value: String(quantity), provider, networkID: chainID }));
setQuantity("");
}
};
const hasAllowance = useCallback(
token => {
if (token === "time") return stakeAllowance > 0;
if (token === "memo") return unstakeAllowance > 0;
return 0;
},
[stakeAllowance],
);
const changeView = (newView: number) => () => {
setView(newView);
setQuantity("");
};
const trimmedMemoBalance = trim(Number(memoBalance), 6);
const trimmedStakingAPY = trim(stakingAPY * 100, 1);
const stakingRebasePercentage = trim(stakingRebase * 100, 4);
const nextRewardValue = trim((Number(stakingRebasePercentage) / 100) * Number(trimmedMemoBalance), 6);
return (
<div className="stake-view">
<Zoom in={true}>
<div className="stake-card">
<Grid className="stake-card-grid" container direction="column" spacing={2}>
<Grid item>
<div className="stake-card-header">
<p className="stake-card-header-title">TIME Staking (?, ?)</p>
<RebaseTimer />
</div>
</Grid>
<Grid item>
<div className="stake-card-metrics">
<Grid container spacing={2}>
<Grid item xs={12} sm={4} md={4} lg={4}>
<div className="stake-card-apy">
<p className="stake-card-metrics-title">APY</p>
<p className="stake-card-metrics-value">
{stakingAPY ? <>{new Intl.NumberFormat("en-US").format(Number(trimmedStakingAPY))}%</> : <Skeleton width="150px" />}
</p>
</div>
</Grid>
<Grid item xs={6} sm={4} md={4} lg={4}>
<div className="stake-card-tvl">
<p className="stake-card-metrics-title">TVL</p>
<p className="stake-card-metrics-value">
{stakingTVL ? (
new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
maximumFractionDigits: 0,
minimumFractionDigits: 0,
}).format(stakingTVL)
) : (
<Skeleton width="150px" />
)}
</p>
</div>
</Grid>
<Grid item xs={6} sm={4} md={4} lg={4}>
<div className="stake-card-index">
<p className="stake-card-metrics-title">Current Index</p>
<p className="stake-card-metrics-value">{currentIndex ? <>{trim(Number(currentIndex), 2)} TIME</> : <Skeleton width="150px" />}</p>
</div>
</Grid>
</Grid>
</div>
</Grid>
<div className="stake-card-area">
{!address && (
<div className="stake-card-wallet-notification">
<div className="stake-card-wallet-connect-btn" onClick={connect}>
<p>Connect Wallet</p>
</div>
<p className="stake-card-wallet-desc-text">Connect your wallet to stake TIME tokens!</p>
</div>
)}
{address && (
<div>
<div className="stake-card-action-area">
<div className="stake-card-action-stage-btns-wrap">
<div onClick={changeView(0)} className={classnames("stake-card-action-stage-btn", { active: !view })}>
<p>Stake</p>
</div>
<div onClick={changeView(1)} className={classnames("stake-card-action-stage-btn", { active: view })}>
<p>Unstake</p>
</div>
</div>
<div className="stake-card-action-row">
<OutlinedInput
type="number"
placeholder="Amount"
className="stake-card-action-input"
value={quantity}
onChange={e => setQuantity(e.target.value)}
labelWidth={0}
endAdornment={
<InputAdornment position="end">
<div onClick={setMax} className="stake-card-action-input-btn">
<p>Max</p>
</div>
</InputAdornment>
}
/>
{view === 0 && (
<div className="stake-card-tab-panel">
{address && hasAllowance("time") ? (
<div
className="stake-card-tab-panel-btn"
onClick={() => {
if (isPendingTxn(pendingTransactions, "staking")) return;
onChangeStake("stake");
}}
>
<p>{txnButtonText(pendingTransactions, "staking", "Stake TIME")}</p>
</div>
) : (
<div
className="stake-card-tab-panel-btn"
onClick={() => {
if (isPendingTxn(pendingTransactions, "approve_staking")) return;
onSeekApproval("time");
}}
>
<p>{txnButtonText(pendingTransactions, "approve_staking", "Approve")}</p>
</div>
)}
</div>
)}
{view === 1 && (
<div className="stake-card-tab-panel">
{address && hasAllowance("memo") ? (
<div
className="stake-card-tab-panel-btn"
onClick={() => {
if (isPendingTxn(pendingTransactions, "unstaking")) return;
onChangeStake("unstake");
}}
>
<p>{txnButtonText(pendingTransactions, "unstaking", "Unstake TIME")}</p>
</div>
) : (
<div
className="stake-card-tab-panel-btn"
onClick={() => {
if (isPendingTxn(pendingTransactions, "approve_unstaking")) return;
onSeekApproval("memo");
}}
>
<p>{txnButtonText(pendingTransactions, "approve_unstaking", "Approve")}</p>
</div>
)}
</div>
)}
</div>
<div className="stake-card-action-help-text">
{address && ((!hasAllowance("time") && view === 0) || (!hasAllowance("memo") && view === 1)) && (
<p>
Note: The "Approve" transaction is only needed when staking/unstaking for the first time; subsequent staking/unstaking only
requires you to perform the "Stake" or "Unstake" transaction.
</p>
)}
</div>
</div>
<div className="stake-user-data">
<div className="data-row">
<p className="data-row-name">Your Balance</p>
<p className="data-row-value">{isAppLoading ? <Skeleton width="80px" /> : <>{trim(Number(timeBalance), 4)} TIME</>}</p>
</div>
<div className="data-row">
<p className="data-row-name">Your Staked Balance</p>
<p className="data-row-value">{isAppLoading ? <Skeleton width="80px" /> : <>{trimmedMemoBalance} MEMO</>}</p>
</div>
<div className="data-row">
<p className="data-row-name">Next Reward Amount</p>
<p className="data-row-value">{isAppLoading ? <Skeleton width="80px" /> : <>{nextRewardValue} MEMO</>}</p>
</div>
<div className="data-row">
<p className="data-row-name">Next Reward Yield</p>
<p className="data-row-value">{isAppLoading ? <Skeleton width="80px" /> : <>{stakingRebasePercentage}%</>}</p>
</div>
<div className="data-row">
<p className="data-row-name">ROI (5-Day Rate)</p>
<p className="data-row-value">{isAppLoading ? <Skeleton width="80px" /> : <>{trim(Number(fiveDayRate) * 100, 4)}%</>}</p>
</div>
</div>
</div>
)}
</div>
</Grid>
</div>
</Zoom>
</div>
);
}
Example #14
Source File: index.tsx From wonderland-frontend with MIT License | 4 votes |
function Calculator() {
const isAppLoading = useSelector<IReduxState, boolean>(state => state.app.loading);
const marketPrice = useSelector<IReduxState, number>(state => {
return state.app.marketPrice;
});
const stakingAPY = useSelector<IReduxState, number>(state => {
return state.app.stakingAPY;
});
const memoBalance = useSelector<IReduxState, string>(state => {
return state.account.balances && state.account.balances.memo;
});
const trimmedStakingAPY = trim(stakingAPY * 100, 1);
const trimmedMemoBalance = trim(Number(memoBalance), 6);
const trimeMarketPrice = trim(marketPrice, 2);
const [memoAmount, setMemoAmount] = useState(trimmedMemoBalance);
const [rewardYield, setRewardYield] = useState(trimmedStakingAPY);
const [priceAtPurchase, setPriceAtPurchase] = useState(trimeMarketPrice);
const [futureMarketPrice, setFutureMarketPrice] = useState(trimeMarketPrice);
const [days, setDays] = useState(30);
const [rewardsEstimation, setRewardsEstimation] = useState("0");
const [potentialReturn, setPotentialReturn] = useState("0");
const calcInitialInvestment = () => {
const memo = Number(memoAmount) || 0;
const price = parseFloat(priceAtPurchase) || 0;
const amount = memo * price;
return trim(amount, 2);
};
const calcCurrentWealth = () => {
const memo = Number(memoAmount) || 0;
const price = parseFloat(trimeMarketPrice);
const amount = memo * price;
return trim(amount, 2);
};
const [initialInvestment, setInitialInvestment] = useState(calcInitialInvestment());
useEffect(() => {
const newInitialInvestment = calcInitialInvestment();
setInitialInvestment(newInitialInvestment);
}, [memoAmount, priceAtPurchase]);
const calcNewBalance = () => {
let value = parseFloat(rewardYield) / 100;
value = Math.pow(value - 1, 1 / (365 * 3)) - 1 || 0;
let balance = Number(memoAmount);
for (let i = 0; i < days * 3; i++) {
balance += balance * value;
}
return balance;
};
useEffect(() => {
const newBalance = calcNewBalance();
setRewardsEstimation(trim(newBalance, 6));
const newPotentialReturn = newBalance * (parseFloat(futureMarketPrice) || 0);
setPotentialReturn(trim(newPotentialReturn, 2));
}, [days, rewardYield, futureMarketPrice, memoAmount]);
return (
<div className="calculator-view">
<Zoom in={true}>
<div className="calculator-card">
<Grid className="calculator-card-grid" container direction="column" spacing={2}>
<Grid item>
<div className="calculator-card-header">
<p className="calculator-card-header-title">Calculator</p>
<p className="calculator-card-header-subtitle">Estimate your returns</p>
</div>
</Grid>
<Grid item>
<div className="calculator-card-metrics">
<Grid container spacing={2}>
<Grid item xs={12} sm={4} md={4} lg={4}>
<div className="calculator-card-apy">
<p className="calculator-card-metrics-title">TIME Price</p>
<p className="calculator-card-metrics-value">{isAppLoading ? <Skeleton width="100px" /> : `$${trimeMarketPrice}`}</p>
</div>
</Grid>
<Grid item xs={6} sm={4} md={4} lg={4}>
<div className="calculator-card-tvl">
<p className="calculator-card-metrics-title">Current APY</p>
<p className="calculator-card-metrics-value">
{isAppLoading ? <Skeleton width="100px" /> : <>{new Intl.NumberFormat("en-US").format(Number(trimmedStakingAPY))}%</>}
</p>
</div>
</Grid>
<Grid item xs={6} sm={4} md={4} lg={4}>
<div className="calculator-card-index">
<p className="calculator-card-metrics-title">Your MEMO Balance</p>
<p className="calculator-card-metrics-value">{isAppLoading ? <Skeleton width="100px" /> : <>{trimmedMemoBalance} MEMO</>}</p>
</div>
</Grid>
</Grid>
</div>
</Grid>
<div className="calculator-card-area">
<div>
<div className="calculator-card-action-area">
<Grid container spacing={3}>
<Grid item xs={12} sm={6}>
<div className="calculator-card-action-area-inp-wrap">
<p className="calculator-card-action-area-inp-wrap-title">MEMO Amount</p>
<OutlinedInput
type="number"
placeholder="Amount"
className="calculator-card-action-input"
value={memoAmount}
onChange={e => setMemoAmount(e.target.value)}
labelWidth={0}
endAdornment={
<InputAdornment position="end">
<div onClick={() => setMemoAmount(trimmedMemoBalance)} className="stake-card-action-input-btn">
<p>Max</p>
</div>
</InputAdornment>
}
/>
</div>
</Grid>
<Grid item xs={12} sm={6}>
<div className="calculator-card-action-area-inp-wrap">
<p className="calculator-card-action-area-inp-wrap-title">APY (%)</p>
<OutlinedInput
type="number"
placeholder="Amount"
className="calculator-card-action-input"
value={rewardYield}
onChange={e => setRewardYield(e.target.value)}
labelWidth={0}
endAdornment={
<InputAdornment position="end">
<div onClick={() => setRewardYield(trimmedStakingAPY)} className="stake-card-action-input-btn">
<p>Current</p>
</div>
</InputAdornment>
}
/>
</div>
</Grid>
<Grid item xs={12} sm={6}>
<div className="calculator-card-action-area-inp-wrap">
<p className="calculator-card-action-area-inp-wrap-title">TIME price at purchase ($)</p>
<OutlinedInput
type="number"
placeholder="Amount"
className="calculator-card-action-input"
value={priceAtPurchase}
onChange={e => setPriceAtPurchase(e.target.value)}
labelWidth={0}
endAdornment={
<InputAdornment position="end">
<div onClick={() => setPriceAtPurchase(trimeMarketPrice)} className="stake-card-action-input-btn">
<p>Current</p>
</div>
</InputAdornment>
}
/>
</div>
</Grid>
<Grid item xs={12} sm={6}>
<div className="calculator-card-action-area-inp-wrap">
<p className="calculator-card-action-area-inp-wrap-title">Future TIME market price ($)</p>
<OutlinedInput
type="number"
placeholder="Amount"
className="calculator-card-action-input"
value={futureMarketPrice}
onChange={e => setFutureMarketPrice(e.target.value)}
labelWidth={0}
endAdornment={
<InputAdornment position="end">
<div onClick={() => setFutureMarketPrice(trimeMarketPrice)} className="stake-card-action-input-btn">
<p>Current</p>
</div>
</InputAdornment>
}
/>
</div>
</Grid>
</Grid>
</div>
<div className="calculator-days-slider-wrap">
<p className="calculator-days-slider-wrap-title">{`${days} day${days > 1 ? "s" : ""}`}</p>
<Slider className="calculator-days-slider" min={1} max={365} value={days} onChange={(e, newValue: any) => setDays(newValue)} />
</div>
<div className="calculator-user-data">
<div className="data-row">
<p className="data-row-name">Your initial investment</p>
<p className="data-row-value">{isAppLoading ? <Skeleton width="80px" /> : <>${initialInvestment}</>}</p>
</div>
<div className="data-row">
<p className="data-row-name">Current wealth</p>
<p className="data-row-value">{isAppLoading ? <Skeleton width="80px" /> : <>${calcCurrentWealth()}</>}</p>
</div>
<div className="data-row">
<p className="data-row-name">TIME rewards estimation</p>
<p className="data-row-value">{isAppLoading ? <Skeleton width="80px" /> : <>{rewardsEstimation} TIME</>}</p>
</div>
<div className="data-row">
<p className="data-row-name">Potential return</p>
<p className="data-row-value">{isAppLoading ? <Skeleton width="80px" /> : <>${potentialReturn}</>}</p>
</div>
<div className="data-row">
<p className="data-row-name">Potential number of lambos</p>
<p className="data-row-value">{isAppLoading ? <Skeleton width="80px" /> : <>{Math.floor(Number(potentialReturn) / 220000)}</>}</p>
</div>
</div>
</div>
</div>
</Grid>
</div>
</Zoom>
</div>
);
}
Example #15
Source File: index.tsx From wonderland-frontend with MIT License | 4 votes |
function Zapin({ open, handleClose, bond }: IZapinProps) {
const { tokens } = useTokens();
const { provider, address, chainID, checkWrongNetwork } = useWeb3Context();
const dispatch = useDispatch();
const isBondLoading = useSelector<IReduxState, boolean>(state => state.bonding.loading ?? true);
const pendingTransactions = useSelector<IReduxState, IPendingTxn[]>(state => {
return state.pendingTransactions;
});
let defaultToken = tokens.find(token => token.name === avax.name);
if (bond.name === wavax.name) {
defaultToken = tokens.find(token => token.name === mim.name);
}
const [quantity, setQuantity] = useState<string>("");
//@ts-ignore
const [token, setToken] = useState<IAllTokenData>(defaultToken);
const [chooseTokenOpen, setChooseTokenOpen] = useState(false);
const [settingsOpen, setSettingsOpen] = useState(false);
const [slippage, setSlippage] = useState(2);
const [swapInfo, setSwapInfo] = useState<ITokenZapinResponse>({ swapData: "", swapTarget: "", amount: "", value: "0" });
const [priceToken, setPriceToken] = useState<number>(0);
const [loading, setLoading] = useState(false);
const hasAllowance = useCallback(() => {
return token.allowance > 0;
}, [token.allowance]);
const onSeekApproval = async () => {
if (await checkWrongNetwork()) return;
dispatch(changeApproval({ address, token, provider, networkID: chainID }));
};
const onMint = async () => {
if (await checkWrongNetwork()) return;
if (!swapInfo.amount || !swapInfo.swapData || !swapInfo.swapTarget || swapInfo.value !== quantity) {
return dispatch(warning({ text: messages.something_wrong }));
}
dispatch(
zapinMint({
provider,
networkID: chainID,
bond,
token,
value: quantity,
minReturnAmount: swapInfo.amount,
swapTarget: swapInfo.swapTarget,
swapData: swapInfo.swapData,
slippage,
address,
}),
);
};
const onSlippageChange = (value: any) => {
return setSlippage(value);
};
const setMax = () => {
const maxBondPriceToken = bond.maxBondPriceToken / priceToken;
let amount: any = Math.min(maxBondPriceToken, token.isAvax ? token.balance * 0.99 : token.balance);
if (amount) {
amount = trim(amount);
}
setQuantity((amount || "").toString());
};
useEffect(() => {
let timeount: any = null;
clearTimeout(timeount);
if (Number(quantity) > 0) {
setSwapInfo({ swapData: "", swapTarget: "", amount: "", value: "0" });
setLoading(true);
timeount = setTimeout(async () => {
const info = await calcZapinDetails({ token, provider, networkID: chainID, bond, value: quantity, slippage, dispatch });
if (info.amount) {
const amount = utils.formatEther(info.amount);
dispatch(calcBondDetails({ bond, value: amount, provider, networkID: chainID }));
} else {
dispatch(calcBondDetails({ bond, value: "0", provider, networkID: chainID }));
}
setSwapInfo(info);
setLoading(false);
}, 1000);
} else {
setSwapInfo({ swapData: "", swapTarget: "", amount: "", value: "0" });
dispatch(calcBondDetails({ bond, value: "0", provider, networkID: chainID }));
setLoading(false);
}
return () => clearTimeout(timeount);
}, [quantity, slippage]);
useEffect(() => {
setTimeout(async () => {
const { amount } = await calcZapinDetails({ token, provider, networkID: chainID, bond, value: "1", slippage, dispatch });
if (amount) {
const amountValue = utils.formatEther(amount);
setPriceToken(Number(amountValue));
}
}, 500);
}, [token, slippage]);
let minimumReceivedAmount = "0";
if (swapInfo.amount) {
const minimumReceivedAmountValue = utils.formatEther(swapInfo.amount);
minimumReceivedAmount = trim(Number(minimumReceivedAmountValue), 6);
}
const handleChooseTokenOpen = () => {
setChooseTokenOpen(true);
};
const handleChooseTokenClose = () => {
setChooseTokenOpen(false);
};
const handleChooseTokenSelect = (token: IAllTokenData) => {
setQuantity("");
setToken(token);
setChooseTokenOpen(false);
setSwapInfo({ swapData: "", swapTarget: "", amount: "", value: "0" });
};
const handleSettingsOpen = () => {
setSettingsOpen(true);
};
const handleSettingsClose = () => {
setSettingsOpen(false);
};
const isLoading = isBondLoading || loading;
return (
<Modal id="hades" open={open} onClose={handleClose} hideBackdrop>
<Paper className="ohm-card ohm-popover zapin-poper">
<div className="cross-wrap">
<IconButton onClick={handleClose}>
<SvgIcon color="primary" component={XIcon} />
</IconButton>
<IconButton style={{ marginLeft: "auto" }} onClick={handleSettingsOpen}>
<SvgIcon color="primary" component={SettingsIcon} />
</IconButton>
</div>
<Box className="card-content">
<div className="zapin-header">
<div className="zapin-header-token-select-wrap">
<p className="zapin-header-token-select-title">Zapin & Mint</p>
<OutlinedInput
type="number"
placeholder="Amount"
className="zapin-header-token-select-input"
value={quantity}
onChange={e => setQuantity(e.target.value)}
labelWidth={0}
startAdornment={
<InputAdornment position="start">
<div onClick={handleChooseTokenOpen} className="zapin-header-token-select-input-token-select">
<img className="zapin-header-token-select-input-token-select-logo" src={token.img} alt="" />
<p>{token.name}</p>
<Box display="flex" alignItems="center" justifyContent="center" width={"16px"}>
<img src={ArrowUpImg} style={{ height: "16px", width: "16px" }} />
</Box>
</div>
</InputAdornment>
}
endAdornment={
<InputAdornment position="end">
<div className="zapin-header-token-select-input-btn" onClick={setMax}>
<p>Max</p>
</div>
</InputAdornment>
}
/>
{hasAllowance() || token.isAvax ? (
<div
className="zapin-header-token-select-btn"
onClick={async () => {
if (isPendingTxn(pendingTransactions, "zapin_" + token.name + "_" + bond.name)) return;
await onMint();
}}
>
<p>{txnButtonText(pendingTransactions, "zapin_" + token.name + "_" + bond.name, "Mint")}</p>
</div>
) : (
<div
className="zapin-header-token-select-btn"
onClick={async () => {
if (isPendingTxn(pendingTransactions, "approve_" + token.address)) return;
await onSeekApproval();
}}
>
<p>{txnButtonText(pendingTransactions, "approve_" + token.address, "Approve")}</p>
</div>
)}
</div>
{!hasAllowance() && !token.isAvax && (
<div className="zapin-header-help-text">
<p>Note: The "Approve" transaction is only needed when bonding for the first time</p>
<p>for each token; subsequent bonding only requires you to perform the</p>
<p>"zapin&mint" transaction.</p>
</div>
)}
</div>
<div className="zapin-body">
<div className="zapin-body-header">
<BondLogo bond={bond} />
<div className="zapin-body-header-name">
<p>TX settings</p>
</div>
</div>
<div className="zapin-body-params">
<div className="data-row">
<p className="data-row-name">Destination token </p>
<p className="data-row-value">{bond.displayName}</p>
</div>
<div className="data-row">
<p className="data-row-name">Slippage Tolerance</p>
<p className="data-row-value">{trim(slippage)}%</p>
</div>
<div className="data-row">
<p className="data-row-name">Your Balance</p>
<p className="data-row-value">{`${trim(token.balance, 6)} ${token.name}`}</p>
</div>
<div className="data-row">
<p className="data-row-name">Minimum Received Amount</p>
<p className="data-row-value">{isLoading ? <Skeleton width="100px" /> : `${minimumReceivedAmount} ${bond.displayUnits}`}</p>
</div>
<div className="data-row">
<p className="data-row-name">Approximately you will get</p>
<p className="data-row-value">{isLoading ? <Skeleton width="100px" /> : `~ ${trim(bond.bondQuote, 4)} TIME`}</p>
</div>
<div className="data-row">
<p className="data-row-name">Max You Can Buy</p>
<p className="data-row-value">{isLoading ? <Skeleton width="100px" /> : `${trim(bond.maxBondPrice, 4)} TIME`}</p>
</div>
<div className="data-row">
<p className="data-row-name">ROI</p>
<p className="data-row-value">{isLoading ? <Skeleton width="100px" /> : `${trim(bond.bondDiscount * 100, 2)}%`}</p>
</div>
<div className="data-row">
<p className="data-row-name">Minimum purchase</p>
<p className="data-row-value">0.01 TIME</p>
</div>
</div>
</div>
<ChooseToken open={chooseTokenOpen} handleClose={handleChooseTokenClose} handleSelect={handleChooseTokenSelect} bond={bond} />
<AdvancedSettings open={settingsOpen} handleClose={handleSettingsClose} slippage={slippage} onSlippageChange={onSlippageChange} />
</Box>
</Paper>
</Modal>
);
}
Example #16
Source File: BondPurchase.tsx From wonderland-frontend with MIT License | 4 votes |
function BondPurchase({ bond, slippage }: IBondPurchaseProps) {
const dispatch = useDispatch();
const { provider, address, chainID, checkWrongNetwork } = useWeb3Context();
const [quantity, setQuantity] = useState("");
const [useAvax, setUseAvax] = useState(false);
const isBondLoading = useSelector<IReduxState, boolean>(state => state.bonding.loading ?? true);
const [zapinOpen, setZapinOpen] = useState(false);
const pendingTransactions = useSelector<IReduxState, IPendingTxn[]>(state => {
return state.pendingTransactions;
});
const vestingPeriod = () => {
return prettifySeconds(bond.vestingTerm, "day");
};
async function onBond() {
if (await checkWrongNetwork()) return;
if (quantity === "") {
dispatch(warning({ text: messages.before_minting }));
//@ts-ignore
} else if (isNaN(quantity)) {
dispatch(warning({ text: messages.before_minting }));
} else if (bond.interestDue > 0 || bond.pendingPayout > 0) {
const shouldProceed = window.confirm(messages.existing_mint);
if (shouldProceed) {
const trimBalance = trim(Number(quantity), 10);
await dispatch(
bondAsset({
value: trimBalance,
slippage,
bond,
networkID: chainID,
provider,
address,
useAvax,
}),
);
clearInput();
}
} else {
const trimBalance = trim(Number(quantity), 10);
await dispatch(
//@ts-ignore
bondAsset({
value: trimBalance,
slippage,
bond,
networkID: chainID,
provider,
address,
useAvax,
}),
);
clearInput();
}
}
const clearInput = () => {
setQuantity("");
};
const hasAllowance = useCallback(() => {
return bond.allowance > 0;
}, [bond.allowance]);
const setMax = () => {
let amount: any = Math.min(bond.maxBondPriceToken * 0.9999, useAvax ? bond.avaxBalance * 0.99 : bond.balance);
if (amount) {
amount = trim(amount);
}
setQuantity((amount || "").toString());
};
const bondDetailsDebounce = useDebounce(quantity, 1000);
useEffect(() => {
dispatch(calcBondDetails({ bond, value: quantity, provider, networkID: chainID }));
}, [bondDetailsDebounce]);
const onSeekApproval = async () => {
if (await checkWrongNetwork()) return;
dispatch(changeApproval({ address, bond, provider, networkID: chainID }));
};
const handleZapinOpen = () => {
dispatch(calcBondDetails({ bond, value: "0", provider, networkID: chainID }));
setZapinOpen(true);
};
const handleZapinClose = () => {
dispatch(calcBondDetails({ bond, value: quantity, provider, networkID: chainID }));
setZapinOpen(false);
};
const displayUnits = useAvax ? "AVAX" : bond.displayUnits;
return (
<Box display="flex" flexDirection="column">
<Box display="flex" justifyContent="space-around" flexWrap="wrap">
{bond.name === "wavax" && (
<FormControl className="ohm-input" variant="outlined" color="primary" fullWidth>
<div className="avax-checkbox">
<input type="checkbox" checked={useAvax} onClick={() => setUseAvax(!useAvax)} />
<p>Use AVAX</p>
</div>
</FormControl>
)}
<FormControl className="bond-input-wrap" variant="outlined" color="primary" fullWidth>
<OutlinedInput
placeholder="Amount"
type="number"
value={quantity}
onChange={e => setQuantity(e.target.value)}
labelWidth={0}
className="bond-input"
endAdornment={
<InputAdornment position="end">
<div className="stake-input-btn" onClick={setMax}>
<p>Max</p>
</div>
</InputAdornment>
}
/>
</FormControl>
{hasAllowance() || useAvax ? (
<div
className="transaction-button bond-approve-btn"
onClick={async () => {
if (isPendingTxn(pendingTransactions, "bond_" + bond.name)) return;
await onBond();
}}
>
<p>{txnButtonText(pendingTransactions, "bond_" + bond.name, "Mint")}</p>
</div>
) : (
<div
className="transaction-button bond-approve-btn"
onClick={async () => {
if (isPendingTxn(pendingTransactions, "approve_" + bond.name)) return;
await onSeekApproval();
}}
>
<p>{txnButtonText(pendingTransactions, "approve_" + bond.name, "Approve")}</p>
</div>
)}
<div className="transaction-button bond-approve-btn" onClick={handleZapinOpen}>
<p>Zap</p>
</div>
{!hasAllowance() && !useAvax && (
<div className="help-text">
<p className="help-text-desc">
Note: The "Approve" transaction is only needed when minting for the first time; subsequent minting only requires you to perform the "Mint" transaction.
</p>
</div>
)}
</Box>
<Slide direction="left" in={true} mountOnEnter unmountOnExit {...{ timeout: 533 }}>
<Box className="bond-data">
<div className="data-row">
<p className="bond-balance-title">Your Balance</p>
<p className="bond-balance-title">
{isBondLoading ? (
<Skeleton width="100px" />
) : (
<>
{trim(useAvax ? bond.avaxBalance : bond.balance, 4)} {displayUnits}
</>
)}
</p>
</div>
<div className="data-row">
<p className="bond-balance-title">You Will Get</p>
<p className="price-data bond-balance-title">{isBondLoading ? <Skeleton width="100px" /> : `${trim(bond.bondQuote, 4)} TIME`}</p>
</div>
<div className={`data-row`}>
<p className="bond-balance-title">Max You Can Buy</p>
<p className="price-data bond-balance-title">{isBondLoading ? <Skeleton width="100px" /> : `${trim(bond.maxBondPrice, 4)} TIME`}</p>
</div>
<div className="data-row">
<p className="bond-balance-title">ROI</p>
<p className="bond-balance-title">{isBondLoading ? <Skeleton width="100px" /> : `${trim(bond.bondDiscount * 100, 2)}%`}</p>
</div>
<div className="data-row">
<p className="bond-balance-title">Vesting Term</p>
<p className="bond-balance-title">{isBondLoading ? <Skeleton width="100px" /> : vestingPeriod()}</p>
</div>
<div className="data-row">
<p className="bond-balance-title">Minimum purchase</p>
<p className="bond-balance-title">0.01 TIME</p>
</div>
</Box>
</Slide>
<Zapin open={zapinOpen} handleClose={handleZapinClose} bond={bond} />
</Box>
);
}
Example #17
Source File: index.tsx From wonderland-frontend with MIT License | 4 votes |
function Wrap({ open, handleClose }: IAdvancedSettingsProps) {
const dispatch = useDispatch();
const { provider, address, chainID, checkWrongNetwork } = useWeb3Context();
const [value, setValue] = useState("");
const isAppLoading = useSelector<IReduxState, boolean>(state => state.app.loading);
const memoBalance = useSelector<IReduxState, string>(state => {
return state.account.balances && state.account.balances.memo;
});
const wmemoBalance = useSelector<IReduxState, string>(state => {
return state.account.balances && state.account.balances.wmemo;
});
const wrapValue = useSelector<IReduxState, string>(state => {
return state.wrapping && state.wrapping.wrapValue;
});
const wrapPrice = useSelector<IReduxState, number>(state => {
return state.wrapping && state.wrapping.wrapPrice;
});
const pendingTransactions = useSelector<IReduxState, IPendingTxn[]>(state => {
return state.pendingTransactions;
});
const memoAllowance = useSelector<IReduxState, number>(state => {
return state.account.wrapping && state.account.wrapping.memo;
});
const [isWrap, setIsWrap] = useState(true);
const [isWrapPrice, setIsWrapPrice] = useState(true);
const setMax = () => {
if (isWrap) {
setValue(memoBalance);
} else {
setValue(wmemoBalance);
}
};
const handleSwap = () => {
setValue("");
const value = !isWrap;
setIsWrap(value);
setIsWrapPrice(value);
};
const handleValueChange = (e: any) => {
const value = e.target.value;
setValue(value);
};
useEffect(() => {
dispatch(calcWrapDetails({ isWrap, provider, value, networkID: chainID }));
}, [value]);
useEffect(() => {
dispatch(calcWrapPrice({ isWrap: isWrapPrice, provider, networkID: chainID }));
}, [isWrapPrice]);
const onClose = () => {
setValue("");
setIsWrap(true);
setIsWrapPrice(true);
dispatch(calcWrapDetails({ isWrap, provider, value: "", networkID: chainID }));
handleClose();
};
const hasAllowance = useCallback(() => memoAllowance > 0, [memoAllowance]);
const trimmedMemoBalance = trim(Number(memoBalance), 6);
const trimmedWmemoBalance = trim(Number(wmemoBalance), 6);
const getBalance = () => (isWrap ? `${trimmedMemoBalance} MEMO` : `${trimmedWmemoBalance} wMEMO`);
const handleOnWrap = async () => {
if (await checkWrongNetwork()) return;
if (value === "" || parseFloat(value) === 0) {
dispatch(warning({ text: isWrap ? messages.before_wrap : messages.before_unwrap }));
} else {
await dispatch(changeWrap({ isWrap, value, provider, networkID: chainID, address }));
setValue("");
}
};
const onSeekApproval = async () => {
if (await checkWrongNetwork()) return;
await dispatch(changeApproval({ address, provider, networkID: chainID }));
};
return (
<Modal id="hades" open={open} onClose={onClose} hideBackdrop>
<Paper className="ohm-card ohm-popover wrap-token-poper">
<div className="cross-wrap wrap-cros-wrap">
<IconButton onClick={onClose}>
<SvgIcon color="primary" component={XIcon} />
</IconButton>
<div className="wrap-price" onClick={() => setIsWrapPrice(!isWrapPrice)}>
<p>
1 {isWrapPrice ? "MEMO" : "wMEMO"} = {`${trim(wrapPrice, 4)} ${isWrapPrice ? "wMEMO" : "MEMO"}`}
</p>
</div>
</div>
<div className="wrap-header-conteiner">
<p className="wrap-header-title">{isWrap ? "Wrap" : "Unwrap"}</p>
<p className="wrap-header-balance">Balance: {isAppLoading ? <Skeleton width="80px" /> : <>{getBalance()}</>}</p>
</div>
<div className="wrap-container">
<OutlinedInput
placeholder="Amount"
value={value}
onChange={handleValueChange}
fullWidth
type="number"
className="bond-input wrap-input"
startAdornment={
<InputAdornment position="start">
<div className="wrap-action-input-text">
<p>{isWrap ? "MEMO" : "wMEMO"}</p>
</div>
</InputAdornment>
}
endAdornment={
<InputAdornment position="end">
<div onClick={setMax} className="wrap-action-input-btn">
<p>Max</p>
</div>
</InputAdornment>
}
/>
<div className="wrap-toggle">
<IconButton onClick={handleSwap}>
<SvgIcon color="primary" component={ArrowsIcon} />
</IconButton>
</div>
<OutlinedInput
placeholder="Amount"
value={wrapValue}
disabled
fullWidth
type="number"
className="bond-input wrap-input"
startAdornment={
<InputAdornment position="start">
<div className="wrap-action-input-text">
<p>{isWrap ? "wMEMO" : "MEMO"}</p>
</div>
</InputAdornment>
}
/>
{hasAllowance() ? (
<div
className="wrap-btn"
onClick={() => {
const inPending = isWrap ? isPendingTxn(pendingTransactions, "wrapping") : isPendingTxn(pendingTransactions, "unwrapping");
if (inPending) return;
handleOnWrap();
}}
>
<p>{isWrap ? txnButtonText(pendingTransactions, "wrapping", "Wrap") : txnButtonText(pendingTransactions, "unwrapping", "Unwrap")}</p>
</div>
) : (
<div
className="wrap-btn"
onClick={() => {
if (isPendingTxn(pendingTransactions, "approve_wrapping")) return;
onSeekApproval();
}}
>
<p>{txnButtonText(pendingTransactions, "approve_wrapping", "Approve")}</p>
</div>
)}
{!hasAllowance() && (
<div className="wrap-help-text">
<p>Note: The "Approve" transaction is only needed when</p>
<p>wrapping for the first time; subsequent wrapping only</p>
<p>requires you to perform the "Wrap" transaction.</p>
</div>
)}
</div>
</Paper>
</Modal>
);
}
Example #18
Source File: index.tsx From rugenerous-frontend with MIT License | 4 votes |
function Stake() {
const [anchorEl, setAnchorEl] = useState(null);
const dispatch = useDispatch();
const { provider, address, connect, chainID, checkWrongNetwork } = useWeb3Context();
const [view, setView] = useState(0);
const [quantity, setQuantity] = useState<string>("");
const isAppLoading = useSelector<IReduxState, boolean>(state => state.app.loading);
const app = useSelector<IReduxState, IAppSlice>(state => state.app);
const currentIndex = useSelector<IReduxState, string>(state => {
return state.app.currentIndex;
});
const fiveDayRate = useSelector<IReduxState, number>(state => {
return state.app.fiveDayRate;
});
const timeBalance = useSelector<IReduxState, string>(state => {
return state.account.balances && state.account.balances.rug;
});
const warmupBalance = useSelector<IReduxState, string>(state => {
return state.account.warmupInfo && state.account.warmupInfo.deposit;
});
const gonsBalance = useSelector<IReduxState, string>(state => {
return state.account.warmupInfo && state.account.warmupInfo.gonsBalance;
});
const warmupExpiry = useSelector<IReduxState, string>(state => {
return state.account.warmupInfo && state.account.warmupInfo.expiry;
});
const currentEpoch = useSelector<IReduxState, string>(state => {
return state.account.warmupInfo && state.account.warmupInfo.epoch;
});
const memoBalance = useSelector<IReduxState, string>(state => {
return state.account.balances && state.account.balances.srug;
});
//Adding Durag - KM
const duragBalance = useSelector<IReduxState, string>(state => {
return state.account.balances && state.account.balances.durag;
});
const stakeAllowance = useSelector<IReduxState, number>(state => {
return state.account.staking && state.account.staking.rug;
});
const unstakeAllowance = useSelector<IReduxState, number>(state => {
return state.account.staking && state.account.staking.srug;
});
const stakingRebase = useSelector<IReduxState, number>(state => {
return state.app.stakingRebase;
});
const stakingAPY = useSelector<IReduxState, number>(state => {
return state.app.stakingAPY;
});
const stakingTVL = useSelector<IReduxState, number>(state => {
return state.app.stakingTVL;
});
const pendingTransactions = useSelector<IReduxState, IPendingTxn[]>(state => {
return state.pendingTransactions;
});
const setMax = () => {
if (view === 0) {
const fullBalance = Number(timeBalance);
setQuantity(trim(fullBalance, 4));
console.log(quantity);
} else {
setQuantity(memoBalance);
}
};
const onSeekApproval = async (token: string) => {
if (await checkWrongNetwork()) return;
await dispatch(changeApproval({ address, token, provider, networkID: chainID }));
};
const onChangeStake = async (action: string) => {
if (await checkWrongNetwork()) return;
if (quantity === "" || parseFloat(quantity) === 0) {
dispatch(warning({ text: action === "stake" ? messages.before_stake : messages.before_unstake }));
} else {
await dispatch(
changeStake({
address,
action,
value: String(quantity),
provider,
networkID: chainID,
warmUpBalance: Number(warmupBalance),
}),
);
setQuantity("");
}
};
const onChangeWarmup = async (action: string) => {
if (await checkWrongNetwork()) return;
await dispatch(
forfeitOrClaim({
address,
action,
provider,
networkID: chainID,
}),
);
};
const hasAllowance = useCallback(
token => {
if (token === "rug") return stakeAllowance > 0;
if (token === "srug") return unstakeAllowance > 0;
return 0;
},
[stakeAllowance],
);
const changeView = (newView: number) => () => {
setView(newView);
setQuantity("");
};
const trimmedMemoBalance = trim(Number(memoBalance), 6);
const trimmedMemoBalanceInUSD = trim(Number(memoBalance) * app.marketPrice, 2);
const trimmedStakingAPY = trim(stakingAPY * 100, 1);
const stakingRebasePercentage = trim(stakingRebase * 100, 4);
const nextRewardValue = trim((Number(stakingRebasePercentage) / 100) * Number(trimmedMemoBalance), 6);
const nextRewardInUSD = Number(nextRewardValue) * app.marketPrice;
const trimmedEarningsPerDay = trim(nextRewardInUSD * 3, 2);
const handleClick = (event: any) => {
setAnchorEl(anchorEl ? null : event.currentTarget);
};
const open = Boolean(anchorEl);
return (
<div className="stake-view">
<Zoom in={true}>
<div className="stake-card">
<Grid className="stake-card-grid" container direction="column" spacing={2}>
<Grid item>
<div className="stake-card-header">
<p className="stake-card-header-title">RUG Staking (?, ?)</p>
<RebaseTimer />
</div>
</Grid>
<Grid item>
<div className="stake-card-metrics">
<Grid container spacing={2}>
<Grid item xs={12} sm={4} md={4} lg={4}>
<div className="stake-card-apy">
<p className="stake-card-metrics-title">APY</p>
<>
{stakingAPY ? (
<div>
<p
className="stake-card-metrics-value"
onMouseEnter={e => handleClick(e)}
onMouseLeave={e => handleClick(e)}
>
`'Big' - trust me bro...`
</p>
<Popper className="rug-menu-popper tooltip" open={open} anchorEl={anchorEl} transition>
{({ TransitionProps }) => (
<Fade {...TransitionProps} timeout={200}>
<p className="tooltip-item">
{new Intl.NumberFormat("en-US").format(Number(trimmedStakingAPY))}%
</p>
</Fade>
)}
</Popper>
</div>
) : (
<p className="stake-card-metrics-value">
<Skeleton width="150px" />
</p>
)}
</>
</div>
</Grid>
<Grid item xs={6} sm={4} md={4} lg={4}>
<div className="stake-card-index">
<p className="stake-card-metrics-title">Current Index</p>
<p className="stake-card-metrics-value">
{currentIndex ? <>{trim(Number(currentIndex), 2)} RUG</> : <Skeleton width="150px" />}
</p>
</div>
</Grid>
<Grid item xs={6} sm={4} md={4} lg={4}>
<div className="stake-card-index">
<p className="stake-card-metrics-title">Earnings per Day</p>
<p className="stake-card-metrics-value">
{currentIndex ? <>${trimmedEarningsPerDay}</> : <Skeleton width="150px" />}
</p>
</div>
</Grid>
</Grid>
</div>
</Grid>
<div className="stake-card-area">
{!address && (
<div className="stake-card-wallet-notification">
<div className="stake-card-wallet-connect-btn" onClick={connect}>
<p>Connect Wallet</p>
</div>
<p className="stake-card-wallet-desc-text">Connect your wallet to stake RUG tokens!</p>
</div>
)}
{address && (
<div>
<div className="stake-card-action-area">
<div className="stake-card-action-stage-btns-wrap">
<div
onClick={changeView(0)}
className={classnames("stake-card-action-stage-btn", { active: !view })}
>
<p>Stake</p>
</div>
<div
onClick={changeView(1)}
className={classnames("stake-card-action-stage-btn", { active: view })}
>
<p>Unstake</p>
</div>
</div>
<div className="stake-card-action-row">
<OutlinedInput
type="number"
placeholder="Amount"
className="stake-card-action-input"
value={quantity}
onChange={e => setQuantity(e.target.value)}
labelWidth={0}
endAdornment={
<InputAdornment position="end">
<div onClick={setMax} className="stake-card-action-input-btn">
<p>Max</p>
</div>
</InputAdornment>
}
/>
{view === 0 && (
<div className="stake-card-tab-panel">
{address && hasAllowance("rug") ? (
<div
className="stake-card-tab-panel-btn"
onClick={() => {
if (isPendingTxn(pendingTransactions, "staking")) return;
onChangeStake("stake");
}}
>
<p>{txnButtonText(pendingTransactions, "staking", "Stake RUG")}</p>
</div>
) : (
<div
className="stake-card-tab-panel-btn"
onClick={() => {
if (isPendingTxn(pendingTransactions, "approve_staking")) return;
onSeekApproval("rug");
}}
>
<p>{txnButtonText(pendingTransactions, "approve_staking", "Approve")}</p>
</div>
)}
</div>
)}
{view === 1 && (
<div className="stake-card-tab-panel">
{address && hasAllowance("srug") ? (
<div
className="stake-card-tab-panel-btn"
onClick={() => {
if (isPendingTxn(pendingTransactions, "unstaking")) return;
onChangeStake("unstake");
}}
>
<p>{txnButtonText(pendingTransactions, "unstaking", "Unstake RUG")}</p>
</div>
) : (
<div
className="stake-card-tab-panel-btn"
onClick={() => {
if (isPendingTxn(pendingTransactions, "approve_unstaking")) return;
onSeekApproval("srug");
}}
>
<p>{txnButtonText(pendingTransactions, "approve_unstaking", "Approve")}</p>
</div>
)}
</div>
)}
</div>
<div className="stake-card-action-help-text">
{address && ((!hasAllowance("rug") && view === 0) || (!hasAllowance("srug") && view === 1)) && (
<p>
Note: The "Approve" transaction is only needed when staking/unstaking for the first rug;
subsequent staking/unstaking only requires you to perform the "Stake" or "Unstake"
transaction.
</p>
)}
</div>
</div>
<div className="stake-user-data">
<div className="data-row">
<p className="data-row-name">Your Balance</p>
<p className="data-row-value">
{isAppLoading ? <Skeleton width="80px" /> : <>{trim(Number(timeBalance), 4)} RUG</>}
</p>
</div>
<div className="data-row">
<p className="data-row-name">Your Durag Balance</p>
<p className="data-row-value">
{isAppLoading ? <Skeleton width="80px" /> : <>{trim(Number(duragBalance), 4)} DURAG</>}
</p>
</div>
{Number(warmupBalance) > 0 && (
<>
<br />
<div className="data-row">
<p className="data-row-name">Your Warm Up Balance</p>
<p className="data-row-value">
{isAppLoading ? <Skeleton width="80px" /> : <>{trim(Number(warmupBalance), 4)} RUG</>}
</p>
</div>
{Number(warmupBalance) < Number(gonsBalance) && (
<>
<div className="data-row">
<p className="data-row-name">Warm Up Balance with Rebase Rewards</p>
<p className="data-row-value">
{isAppLoading ? <Skeleton width="80px" /> : <>{trim(Number(gonsBalance), 4)} RUG</>}
</p>
</div>
</>
)}
<div className="data-row">
<p className="data-row-name">Pending Warm Up Till Release</p>
<p className="data-row-value">
{isAppLoading ? (
<Skeleton width="80px" />
) : Number(warmupExpiry) <= Number(currentEpoch) ? (
<>
<div
className="claim-btn"
onClick={() => {
if (isPendingTxn(pendingTransactions, "claim")) return;
onChangeWarmup("claim");
}}
>
<p>{txnButtonText(pendingTransactions, "claim", "Claim SRUG")}</p>
</div>
<br />
</>
) : (
<div className="warmup-text">
{" "}
{Number(warmupExpiry) - Number(currentEpoch)} Rebase(s) left till claimable
<div className="forfeit-btn">{BasicModal(onChangeWarmup)}</div>
</div>
)}
</p>
</div>
</>
)}
<div className="data-row">
<p className="data-row-name">Your Staked Balance</p>
<p className="data-row-value">
{isAppLoading ? (
<Skeleton width="80px" />
) : (
<>
{trimmedMemoBalance} sRUG (${trimmedMemoBalanceInUSD})
</>
)}
</p>
</div>
<div className="data-row">
<p className="data-row-name">Next Reward Amount</p>
<p className="data-row-value">
{isAppLoading ? (
<Skeleton width="80px" />
) : (
<>
{nextRewardValue} sRUG (${trim(nextRewardInUSD, 2)})
</>
)}
</p>
</div>
<div className="data-row">
<p className="data-row-name">Next Reward Yield</p>
<p className="data-row-value">
{isAppLoading ? <Skeleton width="80px" /> : <>{stakingRebasePercentage}%</>}
</p>
</div>
<div className="data-row">
<p className="data-row-name">ROI (5-Day Rate)</p>
<p className="data-row-value">
{isAppLoading ? <Skeleton width="80px" /> : <>{trim(Number(fiveDayRate) * 100, 4)}%</>}
</p>
</div>
<div className="stake-card-action-help-text">
<br />
<p>
Please Note: there is a two-epoch warm-up period when staking. One epoch is eight hours (one
rebase window). During warm-up, your staked tokens are held by the warm-up contract. Exiting the
warm-up early will return your original deposit to your wallet.
<br />
<br />
Your staked tokens and their accrued rebase rewards will be available to claim at the start of
the third epoch after you originally staked. Once claimed, the tokens move to your staked token
balance, where they will continue to earn rebase rewards and can be unstaked at any time without
penalty.
</p>
</div>
</div>
</div>
)}
</div>
</Grid>
</div>
</Zoom>
</div>
);
}
Example #19
Source File: index.tsx From rugenerous-frontend with MIT License | 4 votes |
function Redemption() {
const [anchorEl, setAnchorEl] = useState(null);
const dispatch = useDispatch();
const { provider, address, connect, chainID, checkWrongNetwork } = useWeb3Context();
const [view, setView] = useState(0);
const [quantity, setQuantity] = useState<string>("");
const isAppLoading = useSelector<IReduxState, boolean>(state => state.app.loading);
const app = useSelector<IReduxState, IAppSlice>(state => state.app);
const currentIndex = useSelector<IReduxState, number>(state => {
return state.app.rfv;
});
const setRFV = useSelector<IReduxState, number>(state => {
return state.app.setRFV;
});
const timeBalance = useSelector<IReduxState, string>(state => {
return state.account.balances && state.account.balances.rug;
});
const timeBalanceValue = (Number(timeBalance) * setRFV) / 100;
//Adding Durag - KM
const redeemAllowance = useSelector<IReduxState, number>(state => {
return state.account.redeem && state.account.redeem.rug;
});
const pendingTransactions = useSelector<IReduxState, IPendingTxn[]>(state => {
return state.pendingTransactions;
});
const setMax = () => {
const fullBalance = Number(timeBalance);
setQuantity(trim(fullBalance, 4));
console.log(quantity);
};
const onSeekApproval = async (token: string) => {
if (await checkWrongNetwork()) return;
await dispatch(changeApproval({ address, token, provider, networkID: chainID }));
};
const onRedeem = async (action: string) => {
if (await checkWrongNetwork()) return;
if (quantity === "" || parseFloat(quantity) === 0) {
dispatch(warning({ text: action === "redeem" ? messages.before_redeem : "" }));
} else {
await dispatch(
redeemFromRUG({
address,
action,
value: String(quantity),
provider,
networkID: chainID,
}),
);
setQuantity("");
}
};
const hasAllowance = useCallback(
token => {
if (token === "rug") return redeemAllowance > 0;
return 0;
},
[redeemAllowance],
);
const changeView = (newView: number) => () => {
setView(newView);
setQuantity("");
};
const handleClick = (event: any) => {
setAnchorEl(anchorEl ? null : event.currentTarget);
};
return (
<div className="redeem-view">
<Zoom in={true}>
<div className="redeem-card">
<Grid className="redeem-card-grid" container direction="column" spacing={2}>
<Grid item>
<div className="redeem-card-header">
<p className="redeem-card-header-title">The RUG Redemption (?, ?)</p>
</div>
</Grid>
<Grid item>
<div className="redeem-card-metrics">
<Grid container spacing={2}>
<Grid item xs={6} sm={4} md={4} lg={4}>
<div className="redeem-card-index">
<p className="redeem-card-metrics-title">Approximate RFV</p>
<p className="redeem-card-metrics-value">
{currentIndex ? <>${trim(Number(currentIndex), 2)}</> : <Skeleton width="150px" />}
</p>
</div>
</Grid>
<Grid item xs={6} sm={4} md={4} lg={4}>
<div className="redeem-card-index">
<p className="redeem-card-metrics-title">Applied Risk Free Value</p>
<p className="redeem-card-metrics-value">
{currentIndex ? <>${trim(Number(setRFV / 100), 2)}</> : <Skeleton width="150px" />}
</p>
</div>
</Grid>
</Grid>
</div>
</Grid>
<div className="redeem-card-area">
{!address && (
<div className="redeem-card-wallet-notification">
<div className="redeem-card-wallet-connect-btn" onClick={connect}>
<p>Connect Wallet</p>
</div>
<p className="redeem-card-wallet-desc-text">
Connect your wallet to Redeem USDC for your RUG tokens!
</p>
</div>
)}
{address && (
<div>
<div className="redeem-card-action-area">
<div className="redeem-card-action-stage-btns-wrap">
<div
onClick={changeView(0)}
className={classnames("redeem-card-action-stage-btn", { active: !view })}
>
<p>Redeem</p>
</div>
</div>
<div className="redeem-card-action-row">
<OutlinedInput
type="number"
placeholder="Amount"
className="redeem-card-action-input"
value={quantity}
onChange={e => setQuantity(e.target.value)}
labelWidth={0}
endAdornment={
<InputAdornment position="end">
<div onClick={setMax} className="redeem-card-action-input-btn">
<p>Max</p>
</div>
</InputAdornment>
}
/>
<div className="redeem-card-tab-panel">
{address && hasAllowance("rug") ? (
<div
className="redeem-card-tab-panel-btn"
onClick={() => {
if (isPendingTxn(pendingTransactions, "redeem")) return;
onRedeem("redeem");
}}
>
<p>{txnButtonText(pendingTransactions, "redeem", "Redeem USDC")}</p>
</div>
) : (
<div
className="redeem-card-tab-panel-btn"
onClick={() => {
if (isPendingTxn(pendingTransactions, "approve_redeem")) return;
onSeekApproval("rug");
}}
>
<p>{txnButtonText(pendingTransactions, "approve_redeem", "Approve")}</p>
</div>
)}
</div>
</div>
<div className="redeem-card-action-help-text">
{address && !hasAllowance("rug") && view === 0 && (
<p>
Note: The "Approve" transaction is only needed when redeeming for the first time, subsequent
redemptions only requires you to perform the "Redeem" transaction.
</p>
)}
</div>
</div>
<div className="redeem-user-data">
<div className="data-row">
<p className="data-row-name">Your Balance</p>
<p className="data-row-value">
{isAppLoading ? <Skeleton width="80px" /> : <>{trim(Number(timeBalance), 4)} RUG</>}
</p>
</div>
<div className="data-row">
<p className="data-row-name">Your Balance Value</p>
<p className="data-row-value">
{isAppLoading ? <Skeleton width="80px" /> : <>${trim(timeBalanceValue, 4)}</>}
</p>
</div>
</div>
</div>
)}
</div>
</Grid>
</div>
</Zoom>
</div>
);
}
Example #20
Source File: index.tsx From rugenerous-frontend with MIT License | 4 votes |
function Calculator() {
const isAppLoading = useSelector<IReduxState, boolean>(state => state.app.loading);
const marketPrice = useSelector<IReduxState, number>(state => {
return state.app.marketPrice;
});
const stakingAPY = useSelector<IReduxState, number>(state => {
return state.app.stakingAPY;
});
const memoBalance = useSelector<IReduxState, string>(state => {
return state.account.balances && state.account.balances.srug;
});
const trimmedStakingAPY = trim(stakingAPY * 100, 1);
const trimmedMemoBalance = trim(Number(memoBalance), 6);
const trimeMarketPrice = trim(marketPrice, 2);
const [memoAmount, setMemoAmount] = useState(trimmedMemoBalance);
const [rewardYield, setRewardYield] = useState(trimmedStakingAPY);
const [priceAtPurchase, setPriceAtPurchase] = useState(trimeMarketPrice);
const [futureMarketPrice, setFutureMarketPrice] = useState(trimeMarketPrice);
const [days, setDays] = useState(30);
const [rewardsEstimation, setRewardsEstimation] = useState("0");
const [potentialReturn, setPotentialReturn] = useState("0");
const calcInitialInvestment = () => {
const srug = Number(memoAmount) || 0;
const price = parseFloat(priceAtPurchase) || 0;
const amount = srug * price;
return trim(amount, 2);
};
const calcCurrentWealth = () => {
const srug = Number(memoAmount) || 0;
const price = parseFloat(trimeMarketPrice);
const amount = srug * price;
return trim(amount, 2);
};
const [initialInvestment, setInitialInvestment] = useState(calcInitialInvestment());
useEffect(() => {
const newInitialInvestment = calcInitialInvestment();
setInitialInvestment(newInitialInvestment);
}, [memoAmount, priceAtPurchase]);
const calcNewBalance = () => {
let value = parseFloat(rewardYield) / 100;
value = Math.pow(value - 1, 1 / (365 * 3)) - 1 || 0;
let balance = Number(memoAmount);
for (let i = 0; i < days * 3; i++) {
balance += balance * value;
}
return balance;
};
useEffect(() => {
const newBalance = calcNewBalance();
setRewardsEstimation(trim(newBalance, 6));
const newPotentialReturn = newBalance * (parseFloat(futureMarketPrice) || 0);
setPotentialReturn(trim(newPotentialReturn, 2));
}, [days, rewardYield, futureMarketPrice, memoAmount]);
return (
<div className="calculator-view">
<Zoom in={true}>
<div className="calculator-card">
<Grid className="calculator-card-grid" container direction="column" spacing={2}>
<Grid item>
<div className="calculator-card-header">
<p className="calculator-card-header-title">Super Accurate Calculator</p>
<p className="calculator-card-header-subtitle">Estimate how much you get rugged...</p>
</div>
</Grid>
<Grid item>
<div className="calculator-card-metrics">
<Grid container spacing={2}>
<Grid item xs={12} sm={4} md={4} lg={4}>
<div className="calculator-card-apy">
<p className="calculator-card-metrics-title">RUG Price</p>
<p className="calculator-card-metrics-value">
{isAppLoading ? <Skeleton width="100px" /> : `$${trimeMarketPrice}`}
</p>
</div>
</Grid>
<Grid item xs={6} sm={4} md={4} lg={4}>
<div className="calculator-card-tvl">
<p className="calculator-card-metrics-title">Current APY</p>
<p className="calculator-card-metrics-value">
{isAppLoading ? (
<Skeleton width="100px" />
) : (
<>{new Intl.NumberFormat("en-US").format(Number(trimmedStakingAPY))}%</>
)}
</p>
</div>
</Grid>
<Grid item xs={6} sm={4} md={4} lg={4}>
<div className="calculator-card-index">
<p className="calculator-card-metrics-title">Your RUGGED Balance</p>
<p className="calculator-card-metrics-value">
{isAppLoading ? <Skeleton width="100px" /> : <>{trimmedMemoBalance} RUGGED</>}
</p>
</div>
</Grid>
</Grid>
</div>
</Grid>
<div className="calculator-card-area">
<div>
<div className="calculator-card-action-area">
<Grid container spacing={3}>
<Grid item xs={12} sm={6}>
<div className="calculator-card-action-area-inp-wrap">
<p className="calculator-card-action-area-inp-wrap-title">RUGGED Amount</p>
<OutlinedInput
type="number"
placeholder="Amount"
className="calculator-card-action-input"
value={memoAmount}
onChange={e => setMemoAmount(e.target.value)}
labelWidth={0}
endAdornment={
<InputAdornment position="end">
<div
onClick={() => setMemoAmount(trimmedMemoBalance)}
className="stake-card-action-input-btn"
>
<p>Max</p>
</div>
</InputAdornment>
}
/>
</div>
</Grid>
<Grid item xs={12} sm={6}>
<div className="calculator-card-action-area-inp-wrap">
<p className="calculator-card-action-area-inp-wrap-title">APY (%)</p>
<OutlinedInput
type="number"
placeholder="Amount"
className="calculator-card-action-input"
value={rewardYield}
onChange={e => setRewardYield(e.target.value)}
labelWidth={0}
endAdornment={
<InputAdornment position="end">
<div
onClick={() => setRewardYield(trimmedStakingAPY)}
className="stake-card-action-input-btn"
>
<p>Current</p>
</div>
</InputAdornment>
}
/>
</div>
</Grid>
<Grid item xs={12} sm={6}>
<div className="calculator-card-action-area-inp-wrap">
<p className="calculator-card-action-area-inp-wrap-title">RUG price at purchase ($)</p>
<OutlinedInput
type="number"
placeholder="Amount"
className="calculator-card-action-input"
value={priceAtPurchase}
onChange={e => setPriceAtPurchase(e.target.value)}
labelWidth={0}
endAdornment={
<InputAdornment position="end">
<div
onClick={() => setPriceAtPurchase(trimeMarketPrice)}
className="stake-card-action-input-btn"
>
<p>Current</p>
</div>
</InputAdornment>
}
/>
</div>
</Grid>
<Grid item xs={12} sm={6}>
<div className="calculator-card-action-area-inp-wrap">
<p className="calculator-card-action-area-inp-wrap-title">Future RUG market price ($)</p>
<OutlinedInput
type="number"
placeholder="Amount"
className="calculator-card-action-input"
value={futureMarketPrice}
onChange={e => setFutureMarketPrice(e.target.value)}
labelWidth={0}
endAdornment={
<InputAdornment position="end">
<div
onClick={() => setFutureMarketPrice(trimeMarketPrice)}
className="stake-card-action-input-btn"
>
<p>Current</p>
</div>
</InputAdornment>
}
/>
</div>
</Grid>
</Grid>
</div>
<div className="calculator-days-slider-wrap">
<p className="calculator-days-slider-wrap-title">{`${days} day${days > 1 ? "s" : ""}`}</p>
<Slider
className="calculator-days-slider"
min={1}
max={365}
value={days}
onChange={(e, newValue: any) => setDays(newValue)}
/>
</div>
<div className="calculator-user-data">
<div className="data-row">
<p className="data-row-name">Your initial investment</p>
<p className="data-row-value">
{isAppLoading ? <Skeleton width="80px" /> : <>${initialInvestment}</>}
</p>
</div>
<div className="data-row">
<p className="data-row-name">Current wealth</p>
<p className="data-row-value">
{isAppLoading ? <Skeleton width="80px" /> : <>${calcCurrentWealth()}</>}
</p>
</div>
<div className="data-row">
<p className="data-row-name">RUG rewards estimation</p>
<p className="data-row-value">
{isAppLoading ? <Skeleton width="80px" /> : <>{rewardsEstimation} RUG</>}
</p>
</div>
<div className="data-row">
<p className="data-row-name">Potential return</p>
<p className="data-row-value">
{isAppLoading ? <Skeleton width="80px" /> : <>${potentialReturn}</>}
</p>
</div>
<div className="data-row">
<p className="data-row-name">Potential number of lambos</p>
<p className="data-row-value">
{isAppLoading ? <Skeleton width="80px" /> : <>{Math.floor(Number(potentialReturn) / 220000)}</>}
</p>
</div>
</div>
</div>
</div>
</Grid>
</div>
</Zoom>
</div>
);
}
Example #21
Source File: index.tsx From rugenerous-frontend with MIT License | 4 votes |
function Zapin({ open, handleClose, bond }: IZapinProps) {
const { tokens } = useTokens();
const { provider, address, chainID, checkWrongNetwork } = useWeb3Context();
const dispatch = useDispatch();
const isBondLoading = useSelector<IReduxState, boolean>(state => state.bonding.loading ?? true);
const pendingTransactions = useSelector<IReduxState, IPendingTxn[]>(state => {
return state.pendingTransactions;
});
let defaultToken = tokens.find(token => token.name === avax.name);
// if (bond.name === wavax.name) {
// defaultToken = tokens.find(token => token.name === mim.name);
// }
const [quantity, setQuantity] = useState<string>("");
//@ts-ignore
const [token, setToken] = useState<IAllTokenData>(defaultToken);
const [chooseTokenOpen, setChooseTokenOpen] = useState(false);
const [settingsOpen, setSettingsOpen] = useState(false);
const [slippage, setSlippage] = useState(2);
const [recipientAddress, setRecipientAddress] = useState(address);
const [swapInfo, setSwapInfo] = useState<ITokenZapinResponse>({ swapData: "", swapTarget: "", amount: "" });
const [priceToken, setPriceToken] = useState<number>(0);
const [loading, setLoading] = useState(false);
const hasAllowance = useCallback(() => {
return token.allowance > 0;
}, [token.allowance]);
const onSeekApproval = async () => {
if (await checkWrongNetwork()) return;
dispatch(changeApproval({ address, token, provider, networkID: chainID }));
};
const onMint = async () => {
if (await checkWrongNetwork()) return;
if (!swapInfo.amount || !swapInfo.swapData || !swapInfo.swapTarget) {
return dispatch(warning({ text: messages.something_wrong }));
}
dispatch(
zapinMint({
provider,
networkID: chainID,
bond,
token,
value: quantity,
minReturnAmount: swapInfo.amount,
swapTarget: swapInfo.swapTarget,
swapData: swapInfo.swapData,
slippage,
address,
}),
);
};
const onRecipientAddressChange = (value: any) => {
return setRecipientAddress(value);
};
const onSlippageChange = (value: any) => {
return setSlippage(value);
};
const setMax = () => {
const maxBondPriceToken = bond.maxBondPriceToken / priceToken;
let amount: any = Math.min(maxBondPriceToken, token.isAvax ? token.balance * 0.99 : token.balance);
if (amount) {
amount = trim(amount);
}
setQuantity((amount || "").toString());
};
useEffect(() => {
if (address) setRecipientAddress(address);
}, [provider, address]);
useEffect(() => {
let timeount: any = null;
clearTimeout(timeount);
if (Number(quantity) > 0) {
setLoading(true);
timeount = setTimeout(async () => {
const info = await calcZapinDetails({
token,
provider,
networkID: chainID,
bond,
value: quantity,
slippage,
dispatch,
});
if (info.amount) {
const amount = utils.formatEther(info.amount);
dispatch(calcBondDetails({ bond, value: amount, provider, networkID: chainID }));
} else {
dispatch(calcBondDetails({ bond, value: "0", provider, networkID: chainID }));
}
setSwapInfo(info);
setLoading(false);
}, 1000);
} else {
setSwapInfo({ swapData: "", swapTarget: "", amount: "" });
dispatch(calcBondDetails({ bond, value: "0", provider, networkID: chainID }));
setLoading(false);
}
return () => clearTimeout(timeount);
}, [quantity, slippage]);
useEffect(() => {
setTimeout(async () => {
const { amount } = await calcZapinDetails({
token,
provider,
networkID: chainID,
bond,
value: "1",
slippage,
dispatch,
});
if (amount) {
const amountValue = utils.formatEther(amount);
setPriceToken(Number(amountValue));
}
}, 500);
}, [token, slippage]);
let minimumReceivedAmount = "0";
if (swapInfo.amount) {
const minimumReceivedAmountValue = utils.formatEther(swapInfo.amount);
minimumReceivedAmount = trim(Number(minimumReceivedAmountValue), 6);
}
const handleChooseTokenOpen = () => {
setChooseTokenOpen(true);
};
const handleChooseTokenClose = () => {
setChooseTokenOpen(false);
};
const handleChooseTokenSelect = (token: IAllTokenData) => {
setQuantity("");
setToken(token);
setChooseTokenOpen(false);
};
const handleSettingsOpen = () => {
setSettingsOpen(true);
};
const handleSettingsClose = () => {
setSettingsOpen(false);
};
const isLoading = isBondLoading || loading;
return (
<Modal id="hades" open={open} onClose={handleClose} hideBackdrop>
<Paper className="ohm-card ohm-popover zapin-poper">
<div className="cross-wrap">
<IconButton onClick={handleClose}>
<SvgIcon color="primary" component={XIcon} />
</IconButton>
<IconButton style={{ marginLeft: "auto" }} onClick={handleSettingsOpen}>
<SvgIcon color="primary" component={SettingsIcon} />
</IconButton>
</div>
<Box className="card-content">
<div className="zapin-header">
<div className="zapin-header-token-select-wrap">
<p className="zapin-header-token-select-title">Zapin & Mint</p>
<OutlinedInput
type="number"
placeholder="Amount"
className="zapin-header-token-select-input"
value={quantity}
onChange={e => setQuantity(e.target.value)}
labelWidth={0}
startAdornment={
<InputAdornment position="start">
<div onClick={handleChooseTokenOpen} className="zapin-header-token-select-input-token-select">
<img className="zapin-header-token-select-input-token-select-logo" src={token.img} alt="" />
<p>{token.name}</p>
<Box display="flex" alignItems="center" justifyContent="center" width={"16px"}>
<img src={ArrowUpImg} style={{ height: "16px", width: "16px" }} />
</Box>
</div>
</InputAdornment>
}
endAdornment={
<InputAdornment position="end">
<div className="zapin-header-token-select-input-btn" onClick={setMax}>
<p>Max</p>
</div>
</InputAdornment>
}
/>
{hasAllowance() || token.isAvax ? (
<div
className="zapin-header-token-select-btn"
onClick={async () => {
if (isPendingTxn(pendingTransactions, "zapin_" + token.name + "_" + bond.name)) return;
await onMint();
}}
>
<p>{txnButtonText(pendingTransactions, "zapin_" + token.name + "_" + bond.name, "Mint")}</p>
</div>
) : (
<div
className="zapin-header-token-select-btn"
onClick={async () => {
if (isPendingTxn(pendingTransactions, "approve_" + token.address)) return;
await onSeekApproval();
}}
>
<p>{txnButtonText(pendingTransactions, "approve_" + token.address, "Approve")}</p>
</div>
)}
</div>
{!hasAllowance() && !token.isAvax && (
<div className="zapin-header-help-text">
<p>Note: The "Approve" transaction is only needed when bonding for the first rug</p>
<p>for each token; subsequent bonding only requires you to perform the</p>
<p>"zapin&mint" transaction.</p>
</div>
)}
</div>
<div className="zapin-body">
<div className="zapin-body-header">
<BondLogo bond={bond} />
<div className="zapin-body-header-name">
<p>TX settings</p>
</div>
</div>
<div className="zapin-body-params">
<div className="data-row">
<p className="data-row-name">Destination token </p>
<p className="data-row-value">{bond.displayName}</p>
</div>
<div className="data-row">
<p className="data-row-name">Slippage Tolerance</p>
<p className="data-row-value">{trim(slippage)}%</p>
</div>
<div className="data-row">
<p className="data-row-name">Your Balance</p>
<p className="data-row-value">{`${trim(token.balance, 6)} ${token.name}`}</p>
</div>
<div className="data-row">
<p className="data-row-name">Minimum Received Amount</p>
<p className="data-row-value">
{isLoading ? <Skeleton width="100px" /> : `${minimumReceivedAmount} ${bond.displayUnits}`}
</p>
</div>
<div className="data-row">
<p className="data-row-name">Approximately you will get</p>
<p className="data-row-value">
{isLoading ? <Skeleton width="100px" /> : `~ ${trim(bond.bondQuote, 4)} RUG`}
</p>
</div>
<div className="data-row">
<p className="data-row-name">Max You Can Buy</p>
<p className="data-row-value">
{isLoading ? <Skeleton width="100px" /> : `${trim(bond.maxBondPrice, 4)} RUG`}
</p>
</div>
<div className="data-row">
<p className="data-row-name">ROI</p>
<p className="data-row-value">
{isLoading ? <Skeleton width="100px" /> : `${trim(bond.bondDiscount * 100, 2)}%`}
</p>
</div>
<div className="data-row">
<p className="data-row-name">Minimum purchase</p>
<p className="data-row-value">0.01 RUG</p>
</div>
{recipientAddress !== address && (
<div className="data-row">
<p className="data-row-name">Recipient</p>
<p className="data-row-value">{shorten(recipientAddress)}</p>
</div>
)}
</div>
</div>
<ChooseToken
open={chooseTokenOpen}
handleClose={handleChooseTokenClose}
handleSelect={handleChooseTokenSelect}
bond={bond}
/>
<AdvancedSettings
open={settingsOpen}
handleClose={handleSettingsClose}
slippage={slippage}
recipientAddress={recipientAddress}
onRecipientAddressChange={onRecipientAddressChange}
onSlippageChange={onSlippageChange}
/>
</Box>
</Paper>
</Modal>
);
}
Example #22
Source File: BondPurchase.tsx From rugenerous-frontend with MIT License | 4 votes |
function BondPurchase({ bond, slippage, recipientAddress }: IBondPurchaseProps) {
const dispatch = useDispatch();
const { provider, address, chainID, checkWrongNetwork } = useWeb3Context();
const [quantity, setQuantity] = useState("");
const [useAvax, setUseAvax] = useState(false);
const isBondLoading = useSelector<IReduxState, boolean>(state => state.bonding.loading ?? true);
const [zapinOpen, setZapinOpen] = useState(false);
const pendingTransactions = useSelector<IReduxState, IPendingTxn[]>(state => {
return state.pendingTransactions;
});
const vestingPeriod = () => {
return prettifySeconds(bond.vestingTerm, "day");
};
async function onBond() {
if (await checkWrongNetwork()) return;
if (quantity === "") {
dispatch(warning({ text: messages.before_minting }));
//@ts-ignore
} else if (isNaN(quantity)) {
dispatch(warning({ text: messages.before_minting }));
} else if (bond.interestDue > 0 || bond.pendingPayout > 0) {
const shouldProceed = window.confirm(messages.existing_mint);
if (shouldProceed) {
const trimBalance = trim(Number(quantity), 10);
await dispatch(
bondAsset({
value: trimBalance,
slippage,
bond,
networkID: chainID,
provider,
address: recipientAddress || address,
useAvax,
}),
);
clearInput();
}
} else {
const trimBalance = trim(Number(quantity), 10);
await dispatch(
//@ts-ignore
bondAsset({
value: trimBalance,
slippage,
bond,
networkID: chainID,
provider,
address: recipientAddress || address,
useAvax,
}),
);
clearInput();
}
}
const clearInput = () => {
setQuantity("");
};
const hasAllowance = useCallback(() => {
return bond.allowance > 0;
}, [bond.allowance]);
const setMax = () => {
let amount: any = Math.min(bond.maxBondPriceToken * 0.9999, useAvax ? bond.avaxBalance * 0.99 : bond.balance);
if (amount) {
amount = trim(amount);
}
setQuantity((amount || "").toString());
};
const bondDetailsDebounce = useDebounce(quantity, 1000);
useEffect(() => {
dispatch(calcBondDetails({ bond, value: quantity, provider, networkID: chainID }));
}, [bondDetailsDebounce]);
const onSeekApproval = async () => {
if (await checkWrongNetwork()) return;
dispatch(changeApproval({ address, bond, provider, networkID: chainID }));
};
const handleZapinOpen = () => {
dispatch(calcBondDetails({ bond, value: "0", provider, networkID: chainID }));
setZapinOpen(true);
};
const handleZapinClose = () => {
dispatch(calcBondDetails({ bond, value: quantity, provider, networkID: chainID }));
setZapinOpen(false);
};
const displayUnits = useAvax ? "AVAX" : bond.displayUnits;
return (
<Box display="flex" flexDirection="column">
<Box display="flex" justifyContent="space-around" flexWrap="wrap">
{bond.name === "wavax" && (
<FormControl className="ohm-input" variant="outlined" color="primary" fullWidth>
<div className="avax-checkbox">
<input type="checkbox" checked={useAvax} onClick={() => setUseAvax(!useAvax)} />
<p>Use AVAX</p>
</div>
</FormControl>
)}
<FormControl className="bond-input-wrap" variant="outlined" color="primary" fullWidth>
<OutlinedInput
placeholder="Amount"
type="number"
value={quantity}
onChange={e => setQuantity(e.target.value)}
labelWidth={0}
className="bond-input"
endAdornment={
<InputAdornment position="end">
<div className="stake-input-btn" onClick={setMax}>
<p>Max</p>
</div>
</InputAdornment>
}
/>
</FormControl>
{hasAllowance() || useAvax ? (
<div
className="transaction-button bond-approve-btn"
onClick={async () => {
if (isPendingTxn(pendingTransactions, "bond_" + bond.name)) return;
await onBond();
}}
>
<p>{txnButtonText(pendingTransactions, "bond_" + bond.name, "Rug Me")}</p>
</div>
) : (
<div
className="transaction-button bond-approve-btn"
onClick={async () => {
if (isPendingTxn(pendingTransactions, "approve_" + bond.name)) return;
await onSeekApproval();
}}
>
<p>{txnButtonText(pendingTransactions, "approve_" + bond.name, "Approve")}</p>
</div>
)}
{/* <div className="transaction-button bond-approve-btn" onClick={handleZapinOpen}>
<p>Zap</p>
</div> */}
{!hasAllowance() && !useAvax && (
<div className="help-text">
<p className="help-text-desc">
Note: The "Approve" transaction is only needed when rugging yourself for the first rug; subsequent rugs
only requires you to perform the "Rug Me" transaction.
</p>
</div>
)}
</Box>
<Slide direction="left" in={true} mountOnEnter unmountOnExit {...{ timeout: 533 }}>
<Box className="bond-data">
<div className="data-row">
<p className="bond-balance-title">Your Balance</p>
<p className="bond-balance-title">
{isBondLoading ? (
<Skeleton width="100px" />
) : (
<>
{trim(useAvax ? bond.avaxBalance : bond.balance, 4)} {displayUnits}
</>
)}
</p>
</div>
<div className="data-row">
<p className="bond-balance-title">You Will Get</p>
<p className="price-data bond-balance-title">
{isBondLoading ? <Skeleton width="100px" /> : `${trim(bond.bondQuote, 4)} RUG`}
</p>
</div>
<div className={`data-row`}>
<p className="bond-balance-title">Max You Can Buy</p>
<p className="price-data bond-balance-title">
{isBondLoading ? <Skeleton width="100px" /> : `${trim(bond.maxBondPrice, 4)} RUG`}
</p>
</div>
<div className="data-row">
<p className="bond-balance-title">ROI</p>
<p className="bond-balance-title">
{isBondLoading ? <Skeleton width="100px" /> : `${trim(bond.bondDiscount * 100, 2)}%`}
</p>
</div>
<div className="data-row">
<p className="bond-balance-title">Vesting Term</p>
<p className="bond-balance-title">{isBondLoading ? <Skeleton width="100px" /> : vestingPeriod()}</p>
</div>
<div className="data-row">
<p className="bond-balance-title">Minimum purchase</p>
<p className="bond-balance-title">0.01 RUG</p>
</div>
{recipientAddress !== address && (
<div className="data-row">
<p className="bond-balance-title">Recipient</p>
<p className="bond-balance-title">
{isBondLoading ? <Skeleton width="100px" /> : shorten(recipientAddress)}
</p>
</div>
)}
</Box>
</Slide>
{/* <Zapin open={zapinOpen} handleClose={handleZapinClose} bond={bond} /> */}
</Box>
);
}
Example #23
Source File: index.tsx From lobis-frontend with MIT License | 4 votes |
function Stake() {
const dispatch = useDispatch();
const { provider, address, connect, chainID, checkWrongNetwork } = useWeb3Context();
const [view, setView] = useState(0);
const [quantity, setQuantity] = useState<string>("");
const isAppLoading = useSelector<IReduxState, boolean>(state => state.app.loading);
const currentIndex = useSelector<IReduxState, string>(state => {
return state.app.currentIndex;
});
const fiveDayRate = useSelector<IReduxState, number>(state => {
return state.app.fiveDayRate;
});
const lobiBalance = useSelector<IReduxState, string>(state => {
return state.account.balances && state.account.balances.lobi;
});
const sTokenBalance = useSelector<IReduxState, string>(state => {
return state.account.balances && state.account.balances.sLobi;
});
const stakeAllowance = useSelector<IReduxState, number>(state => {
return state.account.staking && state.account.staking.lobi;
});
const unstakeAllowance = useSelector<IReduxState, number>(state => {
return state.account.staking && state.account.staking.sLobi;
});
const stakingRebase = useSelector<IReduxState, number>(state => {
return state.app.stakingRebase;
});
const stakingAPY = useSelector<IReduxState, number>(state => {
return state.app.stakingAPY;
});
const stakingTVL = useSelector<IReduxState, number>(state => {
return state.app.stakingTVL;
});
const lobiPrice = useSelector<IReduxState, number>(state => {
return state.app.marketPrice;
});
const pendingTransactions = useSelector<IReduxState, IPendingTxn[]>(state => {
return state.pendingTransactions;
});
const setMax = () => {
if (view === 0) {
setQuantity(lobiBalance);
} else {
setQuantity(sTokenBalance);
}
};
const onSeekApproval = async (token: string) => {
if (await checkWrongNetwork()) return;
await dispatch(changeApproval({ address, token, provider, networkID: chainID }));
};
const onChangeStake = async (action: string) => {
if (await checkWrongNetwork()) return;
if (quantity === "" || parseFloat(quantity) === 0) {
dispatch(warning({ text: action === "stake" ? messages.before_stake : messages.before_unstake }));
} else {
await dispatch(changeStake({ address, action, value: String(quantity), provider, networkID: chainID }));
setQuantity("");
}
};
const hasAllowance = useCallback(
token => {
if (token === "lobi") {
return stakeAllowance > 0;
} else if (token === "sLobi") {
return unstakeAllowance > 0;
}
return 0;
},
[stakeAllowance, unstakeAllowance],
);
const changeView = (newView: number) => () => {
setView(newView);
setQuantity("");
};
const trimmedSLobiBalance = trim(Number(sTokenBalance), 6);
const trimmedStakingAPY = trim(stakingAPY * 100, 1);
const stakingRebasePercentage = trim(stakingRebase * 100, 4);
const nextRewardValue = trim((Number(stakingRebasePercentage) / 100) * Number(trimmedSLobiBalance), 6);
const stakingAmountInUSD = Number(sTokenBalance) * lobiPrice;
const nextRewardValueInUSD = (Number(stakingRebasePercentage) / 100) * Number(trimmedSLobiBalance) * lobiPrice;
return (
<div className="stake-view">
<Zoom in={true}>
<div className="stake-card">
<Grid className="stake-card-grid" container direction="column" spacing={2}>
<Grid item>
<div className="stake-card-header">
<p className="stake-card-header-title">{TOKEN_NAME} Staking ( III , III )</p>
<RebaseTimer />
</div>
</Grid>
<Grid item>
<div className="stake-card-metrics">
<Grid container spacing={2}>
<Grid item xs={12} sm={4} md={4} lg={4}>
<div className="stake-card-apy">
<p className="stake-card-metrics-title">APY</p>
<p className="stake-card-metrics-value">
{stakingAPY ? (
<>
{parseFloat(trimmedStakingAPY) > 1000000000
? "100,000,000% +"
: `${new Intl.NumberFormat("en-US").format(Number(trimmedStakingAPY))}%`}
</>
) : (
<Skeleton width="150px" />
)}
</p>
</div>
</Grid>
<Grid item xs={6} sm={4} md={4} lg={4}>
<div className="stake-card-tvl">
<p className="stake-card-metrics-title">TVL</p>
<p className="stake-card-metrics-value">
{stakingTVL ? (
new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
maximumFractionDigits: 0,
minimumFractionDigits: 0,
}).format(stakingTVL)
) : (
<Skeleton width="150px" />
)}
</p>
</div>
</Grid>
<Grid item xs={6} sm={4} md={4} lg={4}>
<div className="stake-card-index">
<p className="stake-card-metrics-title">Current Index</p>
<p className="stake-card-metrics-value">
{currentIndex ? (
<>
{trim(Number(currentIndex), 4)} {TOKEN_NAME}
</>
) : (
<Skeleton width="150px" />
)}
</p>
</div>
</Grid>
</Grid>
</div>
</Grid>
<div className="stake-card-area">
{!address && (
<div className="stake-card-wallet-notification">
<div className="stake-card-wallet-connect-btn" onClick={connect}>
<p>Connect Wallet</p>
</div>
<p className="stake-card-wallet-desc-text">Connect your wallet to stake {TOKEN_NAME} tokens!</p>
</div>
)}
{address && (
<div>
<div className="stake-card-action-area">
<div className="stake-card-action-stage-btns-wrap">
<div onClick={changeView(0)} className={classnames("stake-card-action-stage-btn", { active: !view })}>
<p>Stake</p>
</div>
<div onClick={changeView(1)} className={classnames("stake-card-action-stage-btn", { active: view })}>
<p>Unstake</p>
</div>
</div>
<div className="stake-card-action-row">
<OutlinedInput
type="number"
placeholder="Amount"
className="stake-card-action-input"
value={quantity}
onChange={e => setQuantity(e.target.value)}
labelWidth={0}
endAdornment={
<InputAdornment position="end">
<div onClick={setMax} className="stake-card-action-input-btn">
<p>Max</p>
</div>
</InputAdornment>
}
/>
{view === 0 && (
<div className="stake-card-tab-panel">
{address && hasAllowance("lobi") ? (
<div
className="stake-card-tab-panel-btn"
onClick={() => {
if (isPendingTxn(pendingTransactions, "staking")) return;
onChangeStake("stake");
}}
>
<p>{txnButtonText(pendingTransactions, "staking", `Stake ${TOKEN_NAME}`)}</p>
</div>
) : (
<div
className="stake-card-tab-panel-btn"
onClick={() => {
if (isPendingTxn(pendingTransactions, "approve_staking")) return;
onSeekApproval("lobi");
}}
>
<p>{txnButtonText(pendingTransactions, "approve_staking", "Approve")}</p>
</div>
)}
</div>
)}
{view === 1 && (
<div className="stake-card-tab-panel">
{address && hasAllowance("sLobi") ? (
<div
className="stake-card-tab-panel-btn"
onClick={() => {
if (isPendingTxn(pendingTransactions, "unstaking")) return;
onChangeStake("unstake");
}}
>
<p>{txnButtonText(pendingTransactions, "unstaking", `Unstake ${TOKEN_NAME}`)}</p>
</div>
) : (
<div
className="stake-card-tab-panel-btn"
onClick={() => {
if (isPendingTxn(pendingTransactions, "approve_unstaking")) return;
onSeekApproval("sLobi");
}}
>
<p>{txnButtonText(pendingTransactions, "approve_unstaking", "Approve")}</p>
</div>
)}
</div>
)}
</div>
<div className="stake-card-action-help-text">
{address && ((!hasAllowance("lobi") && view === 0) || (!hasAllowance("sLobi") && view === 1)) && (
<p>
Note: The "Approve" transaction is only needed when staking/unstaking for the first lobi; subsequent staking/unstaking only
requires you to perform the "Stake" or "Unstake" transaction.
</p>
)}
</div>
</div>
<div className="stake-user-data">
<div className="data-row">
<p className="data-row-name">Your Balance</p>
<p className="data-row-value">
{isAppLoading ? (
<Skeleton width="80px" />
) : (
<>
{trim(Number(lobiBalance), 4)} {TOKEN_NAME}
</>
)}
</p>
</div>
<div className="data-row">
<p className="data-row-name">Your Staked Balance</p>
<p className="data-row-value">
{isAppLoading ? (
<Skeleton width="80px" />
) : (
<>
{trimmedSLobiBalance} {STAKING_TOKEN_NAME}
</>
)}
</p>
</div>
<div className="data-row">
<p className="data-row-name">$ Amount</p>
<p className="data-row-value">
{isAppLoading ? (
<Skeleton width="80px" />
) : (
<>
{new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
maximumFractionDigits: 0,
minimumFractionDigits: 0,
}).format(stakingAmountInUSD)}
</>
)}
</p>
</div>
<div className="data-row">
<p className="data-row-name">Next Reward Amount</p>
<p className="data-row-value">
{isAppLoading ? (
<Skeleton width="80px" />
) : (
<>
{nextRewardValue} {STAKING_TOKEN_NAME}
</>
)}
</p>
</div>
<div className="data-row">
<p className="data-row-name">Next Reward Amount in $</p>
<p className="data-row-value">
{isAppLoading ? (
<Skeleton width="80px" />
) : (
<>
{new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
maximumFractionDigits: 0,
minimumFractionDigits: 0,
}).format(nextRewardValueInUSD)}
</>
)}
</p>
</div>
<div className="data-row">
<p className="data-row-name">Next Reward Yield</p>
<p className="data-row-value">{isAppLoading ? <Skeleton width="80px" /> : <>{stakingRebasePercentage}%</>}</p>
</div>
<div className="data-row">
<p className="data-row-name">ROI (5-Day Rate)</p>
<p className="data-row-value">{isAppLoading ? <Skeleton width="80px" /> : <>{trim(Number(fiveDayRate) * 100, 4)}%</>}</p>
</div>
</div>
</div>
)}
</div>
</Grid>
</div>
</Zoom>
</div>
);
}
Example #24
Source File: index.tsx From lobis-frontend with MIT License | 4 votes |
function LobisMeter() {
const dispatch = useDispatch();
const { provider, address, connect, chainID, checkWrongNetwork } = useWeb3Context();
const [view, setView] = useState(0);
const [quantity, setQuantity] = useState<string>("");
const [rewardYield, setRewardYield] = useState<string>("");
const [lobiPrice, setLobiPrice] = useState<string>("");
const [days, setDays] = useState<number>(30);
const [futureLobiPrice, setFutureLobiPrice] = useState<string>("");
const [apy, setApy] = useState<string>("");
const isAppLoading = useSelector<IReduxState, boolean>(state => state.app.loading);
const sLobiBalance = useSelector<IReduxState, string>(state => {
return state.account.balances && state.account.balances.sLobi;
});
const stakingRebase = useSelector<IReduxState, number>(state => {
return state.app.stakingRebase;
});
const stakingAPY = useSelector<IReduxState, number>(state => {
return state.app.stakingAPY;
});
const marketPrice = useSelector<IReduxState, number>(state => {
return state.app.marketPrice;
});
const epoch = useSelector<IReduxState, any[]>(state => {
return state.app.epoch;
});
const handleDays = (newValue: number | number[]) => {
setDays(newValue as number);
};
const setMax = () => {
setQuantity(sLobiBalance);
};
const handleAPY = (value: string) => {
setApy(value);
const newRewardYield = (Math.pow(Number(value) / 100, 1 / (365 * dailyRebaseAmounts)) - 1) * 100;
setRewardYield(trim(newRewardYield, 4).toString());
if (value === "") {
setRewardYield("");
}
};
const handleRewardYield = (value: string) => {
setRewardYield(value);
const newAPY = (Math.pow(1 + Number(value) / 100, 365 * dailyRebaseAmounts) - 1) * 100;
setApy(trim(newAPY, 4).toString());
if (value === "") {
setApy("");
}
};
const setCurrent = (type: string) => {
switch (type) {
case "rewardYield":
setRewardYield(stakingRebasePercentage);
const newAPY = (Math.pow(1 + Number(stakingRebasePercentage) / 100, 365 * dailyRebaseAmounts) - 1) * 100;
setApy(trim(newAPY, 4).toString());
break;
case "setPrice":
setLobiPrice(marketPrice.toString());
break;
case "futurePrice":
setFutureLobiPrice(marketPrice.toString());
break;
}
};
const trimmedSLobiBalance = trim(Number(sLobiBalance), 6);
const stakingRebasePercentage = trim(stakingRebase * 100, 4);
const blockSecondLength = 13;
const rebaseTimeInSeconds = epoch ? epoch[0] * blockSecondLength : 28800;
const dailyRebaseAmounts = 86400 / rebaseTimeInSeconds;
const totalReturn = (Math.pow(1 + Number(rewardYield) / 100, days * dailyRebaseAmounts) - 1) * Number(quantity);
const initialInvestment = parseFloat(lobiPrice) * parseFloat(quantity);
const potentialReturn = parseFloat(futureLobiPrice) * (totalReturn + Number(quantity)) - initialInvestment;
const daysUntilTwoTimes = Math.log(2) / Math.log(1 + Number(rewardYield) / 100) / dailyRebaseAmounts;
const daysUntilFiveTimes = Math.log(5) / Math.log(1 + Number(rewardYield) / 100) / dailyRebaseAmounts;
const daysUntilTenTimes = Math.log(10) / Math.log(1 + Number(rewardYield) / 100) / dailyRebaseAmounts;
return (
<div className="stake-view">
<Zoom in={true}>
<div className="stake-card">
<Grid className="stake-card-grid" container direction="column" spacing={2}>
<Grid item>
<div className="stake-card-header">
<p className="stake-card-header-title">Calculator</p>
<p className="stake-card-header-description">Please fill the inputs to simulate your rewards</p>
</div>
</Grid>
<Grid item>
<div className="stake-card-metrics">
<Grid container spacing={2}>
<Grid item lg={4} md={4} sm={4} xs={12}>
<div className="stake-card-apy">
<p className="stake-card-metrics-title">{TOKEN_NAME} Price</p>
<p className="stake-card-metrics-value">{isAppLoading ? <Skeleton width="100px" /> : `$${trim(marketPrice, 2)}`}</p>
</div>
</Grid>
<Grid item xs={12} sm={4} md={4} lg={4}>
<div className="stake-card-tvl">
<p className="stake-card-metrics-title">Current Reward Yield</p>
<p className="stake-card-metrics-value">{isAppLoading ? <Skeleton width="80px" /> : <>{stakingRebasePercentage}%</>}</p>
</div>
</Grid>
<Grid item xs={12} sm={4} md={4} lg={4}>
<div className="stake-card-index">
<p className="stake-card-metrics-title">Your {STAKING_TOKEN_NAME} Balance</p>
<p className="stake-card-metrics-value">
{isAppLoading ? (
<Skeleton width="80px" />
) : (
<>
{trimmedSLobiBalance} {STAKING_TOKEN_NAME}
</>
)}
</p>
</div>
</Grid>
</Grid>
</div>
</Grid>
<div className="stake-card-area">
{address && (
<div>
<div className="stake-card-action-area">
<div className="stake-card-action-row">
<OutlinedInput
type="number"
placeholder={`${STAKING_TOKEN_NAME} amount`}
className="stake-card-action-input"
value={quantity}
onChange={e => setQuantity(e.target.value)}
labelWidth={0}
endAdornment={
<InputAdornment position="end">
<div onClick={setMax} className="stake-card-action-input-btn">
<p>Max</p>
</div>
</InputAdornment>
}
/>
</div>
<div className="stake-card-action-row">
<OutlinedInput
type="number"
placeholder={`APY (%)`}
className="stake-card-action-input"
value={apy}
onChange={e => handleAPY(e.target.value)}
labelWidth={0}
endAdornment={<InputAdornment position="end"></InputAdornment>}
/>
</div>
<div className="stake-card-action-row">
<OutlinedInput
type="number"
placeholder={`Reward yield each rebase (%)`}
className="stake-card-action-input"
value={rewardYield}
onChange={e => handleRewardYield(e.target.value)}
labelWidth={0}
endAdornment={
<InputAdornment position="end">
<div onClick={() => setCurrent("rewardYield")} className="stake-card-action-input-btn">
<p>Current</p>
</div>
</InputAdornment>
}
/>
</div>
<div className="stake-card-action-row">
<OutlinedInput
type="number"
placeholder={`${TOKEN_NAME} price at purchase ($) `}
className="stake-card-action-input"
value={lobiPrice}
onChange={e => setLobiPrice(e.target.value)}
labelWidth={0}
endAdornment={
<InputAdornment position="end">
<div onClick={() => setCurrent("setPrice")} className="stake-card-action-input-btn">
<p>Current</p>
</div>
</InputAdornment>
}
/>
</div>
<div className="stake-card-action-row">
<OutlinedInput
type="number"
placeholder={`Future ${TOKEN_NAME} market price ($)`}
className="stake-card-action-input"
value={futureLobiPrice}
onChange={e => setFutureLobiPrice(e.target.value)}
labelWidth={0}
endAdornment={
<InputAdornment position="end">
<div onClick={() => setCurrent("futurePrice")} className="stake-card-action-input-btn">
<p>Current</p>
</div>
</InputAdornment>
}
/>
</div>
<div className="stake-card-action-row">
<Slider className="slider" min={1} max={365} onChange={(e, val) => handleDays(val)} value={days} />{" "}
<p className="days-text">
{days} {days === 1 ? "Day" : "Days"}
</p>
</div>
</div>
<div className="stake-user-data">
<div className="data-row">
<p className="data-row-name">Your Initial Investment</p>
<p className="data-row-value">
{isAppLoading ? (
<Skeleton width="80px" />
) : (
<>
{initialInvestment > 0
? new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
maximumFractionDigits: 5,
minimumFractionDigits: 0,
}).format(initialInvestment)
: new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
maximumFractionDigits: 0,
minimumFractionDigits: 0,
}).format(0)}
</>
)}
</p>
</div>
{/*<div className="data-row">
<p className="data-row-name">Current Wealth</p>
<p className="data-row-value">
{
<>
{marketPrice * parseFloat(trimmedSLobiBalance) > 0
? new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
maximumFractionDigits: 5,
minimumFractionDigits: 0,
}).format(marketPrice * parseFloat(trimmedSLobiBalance))
: new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
maximumFractionDigits: 0,
minimumFractionDigits: 0,
}).format(0)}
</>
}
</p>
</div>*/}
<div className="data-row">
<p className="data-row-name">{`${TOKEN_NAME} rewards estimation`}</p>
<p className="data-row-value">{totalReturn > 0 ? `${trim(totalReturn, 4)} ${TOKEN_NAME}` : `0 ${TOKEN_NAME}`}</p>
</div>
<div className="data-row">
<p className="data-row-name">Total return</p>
<p className="data-row-value">
{!isNaN(potentialReturn)
? new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
maximumFractionDigits: 5,
minimumFractionDigits: 0,
}).format(potentialReturn)
: "--"}
</p>
</div>
{rewardYield !== "" && (
<div style={{ width: "100%" }}>
<Divider style={{ backgroundColor: " rgba(255, 255, 255, 0.2)" }} />
</div>
)}
</div>
</div>
)}
{rewardYield !== "" && (
<div className="stake-user-data">
<div className="data-row">
<p className="data-row-name">Amount of days Until...</p>
<p className="data-row-value"></p>
</div>
<div className="data-row">
<p className="data-row-name">2x {STAKING_TOKEN_NAME}</p>
<p className="data-row-value">
{daysUntilTwoTimes.toFixed(1)} {daysUntilTwoTimes > 1 ? "Days" : "Day"}
</p>
</div>
<div className="data-row">
<p className="data-row-name">5x {STAKING_TOKEN_NAME}</p>
<p className="data-row-value">
{daysUntilFiveTimes.toFixed(1)} {daysUntilTwoTimes > 1 ? "Days" : "Day"}
</p>
</div>
<div className="data-row">
<p className="data-row-name">10x {STAKING_TOKEN_NAME}</p>
<p className="data-row-value">
{daysUntilTenTimes.toFixed(1)} {daysUntilTwoTimes > 1 ? "Days" : "Day"}
</p>
</div>
</div>
)}
</div>
</Grid>
</div>
</Zoom>
</div>
);
}
Example #25
Source File: BondPurchase.tsx From lobis-frontend with MIT License | 4 votes |
function BondPurchase({ bond, slippage, recipientAddress }: IBondPurchaseProps) {
const SECONDS_TO_REFRESH = 60;
const dispatch = useDispatch();
const { provider, address, chainID, checkWrongNetwork } = useWeb3Context();
const [quantity, setQuantity] = useState("");
const [secondsToRefresh, setSecondsToRefresh] = useState(SECONDS_TO_REFRESH);
const isBondLoading = useSelector<IReduxState, boolean>(state => state.bonding.loading ?? true);
const pendingTransactions = useSelector<IReduxState, IPendingTxn[]>(state => {
return state.pendingTransactions;
});
const vestingPeriod = () => {
return prettifySeconds(bond.vestingTerm * 13.01, "day");
};
async function onBond() {
if (await checkWrongNetwork()) return;
if (quantity === "") {
dispatch(warning({ text: messages.before_minting }));
//@ts-ignore
} else if (isNaN(quantity)) {
dispatch(warning({ text: messages.before_minting }));
} else if (bond.interestDue > 0 || bond.pendingPayout > 0) {
const shouldProceed = window.confirm(messages.existing_mint);
if (shouldProceed) {
await dispatch(
bondAsset({
value: quantity,
slippage,
bond,
networkID: chainID,
provider,
address: recipientAddress || address,
}),
);
clearInput();
}
} else {
await dispatch(
//@ts-ignore
bondAsset({
value: quantity,
slippage,
bond,
networkID: chainID,
provider,
address: recipientAddress || address,
}),
);
clearInput();
}
}
const clearInput = () => {
setQuantity("");
};
const hasAllowance = useCallback(() => {
return bond.allowance > 0;
}, [bond.allowance]);
const setMax = () => {
const amount = Math.min(bond.maxBondPriceToken, bond.balance);
const am = fromExponential(amount);
setQuantity((am || "").toString());
};
const bondDetailsDebounce = useDebounce(quantity, 1000);
useEffect(() => {
dispatch(calcBondDetails({ bond, value: quantity, provider, networkID: chainID }));
}, [bondDetailsDebounce]);
useEffect(() => {
let interval: any = null;
if (secondsToRefresh > 0) {
interval = setInterval(() => {
setSecondsToRefresh(secondsToRefresh => secondsToRefresh - 1);
}, 1000);
} else {
clearInterval(interval);
dispatch(calcBondDetails({ bond, value: quantity, provider, networkID: chainID }));
setSecondsToRefresh(SECONDS_TO_REFRESH);
}
return () => clearInterval(interval);
}, [secondsToRefresh, quantity]);
const onSeekApproval = async () => {
if (await checkWrongNetwork()) return;
dispatch(changeApproval({ address, bond, provider, networkID: chainID }));
};
const displayUnits = bond.displayUnits;
return (
<Box display="flex" flexDirection="column">
<Box display="flex" justifyContent="space-around" flexWrap="wrap">
<FormControl className="bond-input-wrap" variant="outlined" color="primary" fullWidth>
<OutlinedInput
placeholder="Amount"
type="number"
value={quantity}
onChange={e => setQuantity(e.target.value)}
labelWidth={0}
className="bond-input"
disabled={bond.name === lobiOHMBond.name}
endAdornment={
<InputAdornment position="end">
<div className="stake-input-btn" onClick={setMax}>
<p>Max</p>
</div>
</InputAdornment>
}
/>
</FormControl>
{bond.name === lobiOHMBond.name ? (
<div className="transaction-button bond-disabled-btn">
<p>{txnButtonText(pendingTransactions, "bond_" + bond.name, "Disabled Bond")}</p>
</div>
) : hasAllowance() ? (
Number(quantity) > bond.balance ? (
<div className="transaction-button bond-disabled-btn">
<p>{txnButtonText(pendingTransactions, "bond_" + bond.name, "Not Enough Balance")}</p>
</div>
) : (
<div
className="transaction-button bond-approve-btn"
onClick={async () => {
if (isPendingTxn(pendingTransactions, "bond_" + bond.name)) return;
await onBond();
}}
>
<p>{txnButtonText(pendingTransactions, "bond_" + bond.name, "Mint")}</p>
</div>
)
) : (
<div
className="transaction-button bond-approve-btn"
onClick={async () => {
if (isPendingTxn(pendingTransactions, "approve_" + bond.name)) return;
await onSeekApproval();
}}
>
<p>{txnButtonText(pendingTransactions, "approve_" + bond.name, "Approve")}</p>
</div>
)}
{!hasAllowance() && (
<div className="help-text">
<p className="help-text-desc">
Note: The "Approve" transaction is only needed when minting for the first time; subsequent minting only requires you to perform the "Mint" transaction.
</p>
</div>
)}
</Box>
<Slide direction="left" in={true} mountOnEnter unmountOnExit {...{ timeout: 0 }}>
<Box className="bond-data">
<div className="data-row">
<p className="bond-balance-title">Your Balance</p>
<p className="bond-balance-title">
{isBondLoading ? (
<Skeleton width="100px" />
) : (
<>
{trim(bond.balance, 10)} {displayUnits}
</>
)}
</p>
</div>
<div className="data-row">
<p className="bond-balance-title">You Will Get</p>
<p className="price-data bond-balance-title">{isBondLoading ? <Skeleton width="100px" /> : `${trim(bond.bondQuote, 4)} ${TOKEN_NAME}`}</p>
</div>
<div className={`data-row`}>
<p className="bond-balance-title">Max You Can Buy</p>
<p className="price-data bond-balance-title">{isBondLoading ? <Skeleton width="100px" /> : `${trim(bond.maxBondPrice, 4)} ${TOKEN_NAME}`}</p>
</div>
<div className="data-row">
<p className="bond-balance-title">ROI</p>
<p className="bond-balance-title">{isBondLoading ? <Skeleton width="100px" /> : `${trim(bond.bondDiscount * 100, 2)}%`}</p>
</div>
<div className="data-row">
<p className="bond-balance-title">Vesting Term</p>
<p className="bond-balance-title">{isBondLoading ? <Skeleton width="100px" /> : vestingPeriod()}</p>
</div>
<div className="data-row">
<p className="bond-balance-title">Minimum purchase</p>
<p className="bond-balance-title">0.01 {TOKEN_NAME}</p>
</div>
{recipientAddress !== address && (
<div className="data-row">
<p className="bond-balance-title">Recipient</p>
<p className="bond-balance-title">{isBondLoading ? <Skeleton width="100px" /> : shorten(recipientAddress)}</p>
</div>
)}
</Box>
</Slide>
</Box>
);
}