antd#Space JavaScript Examples
The following examples show how to use
antd#Space.
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: utils.js From the-eye-knows-the-garbage with MIT License | 7 votes |
renderForeignKey = (text, VerboseNameMap) => {
console.log(text);
console.log(VerboseNameMap);
let items = [];
for (let key in text) {
if (key !== 'ty_options_display_txt') {
let one = <Descriptions.Item label={VerboseNameMap[key]}>{text[key]}</Descriptions.Item>;
items.push(one);
}
}
return <Space>
<span>{text.ty_options_display_txt}</span>
<Popover trigger="click" content={<Descriptions>
{items}
</Descriptions>} title="外键数据">
<InfoCircleTwoTone size="small" />
</Popover>
</Space>;
}
Example #2
Source File: Loader.js From Cowin-Notification-System with MIT License | 6 votes |
Loader = (props) => {
return (
<div className='center' style={props.style || {}}>
<Space size="middle" className='center'>
<Spin size="large" />
</Space>
</div>
)
}
Example #3
Source File: SelectWalletModal.js From bonded-stablecoin-ui with MIT License | 6 votes |
SelectWalletModal = ({ visible, onCancel }) => {
const { t } = useTranslation();
return (
<Modal
visible={visible}
onCancel={onCancel}
title={t("modals.select_wallet.title", "Select wallet")}
footer={
<Space>
<Button key="Cancel" onClick={onCancel}>
{t("modals.common.done", "Done")}
</Button>
</Space>
}
>
<SelectWallet width="100%" size="large" />
</Modal>
);
}
Example #4
Source File: MySkeleton.jsx From react-sendbird-messenger with GNU General Public License v3.0 | 6 votes |
export function MySkeleton({
loading = false,
rows = 1,
children,
size = 'default',
avatar,
avatarShape = 'circle',
}) {
if (loading) {
return [...Array(rows).keys()].map((i) => (
<Fragment key={i}>
<Space style={{ padding: 12, height: 60 }}>
{!!avatar && (
<Skeleton.Avatar
active={true}
size={size}
shape={avatarShape}
/>
)}
<Skeleton.Input
style={{ minWidth: 308, width: 355 }}
active={true}
size={size}
/>
</Space>
</Fragment>
))
}
return children
}
Example #5
Source File: Header.jsx From ui with MIT License | 6 votes |
Header = (props) => {
const {
experimentId, experimentData, title, extra,
} = props;
const experiment = useSelector((state) => state?.experiments[experimentId]);
const experimentName = experimentData?.experimentName || experiment?.name;
const truncateText = (text) => (
(text && text.length > 28) ? `${text.substr(0, 27)}…` : text
);
return (
<>
<NextSeo
title={experimentData ? `${title} · ${truncateText(experimentName)}` : title}
/>
<PageHeader
className={integrationTestConstants.classes.PAGE_HEADER}
title={title}
style={{ width: '100%', paddingTop: '10px', paddingBottom: '10px' }}
extra={(
<Space size='large'>
<Space>
<HelpButton />
<FeedbackButton />
<ReferralButton />
{extra}
</Space>
<UserButton />
</Space>
)}
/>
</>
);
}
Example #6
Source File: Footer.js From 4IZ268-2021-2022-ZS with MIT License | 6 votes |
Footer = () => {
return (
<div className={'footer-container'}>
<img width={164} height={50} src={logo} alt='Logo SKOB'/>
<Space direction='vertical' style={{ justifyContent: 'flex-end' }}>
<Space>
<Text italic>Follow: </Text>
<a href='https://www.facebook.com/skobroudnice' target='_blank' rel="noreferrer">
<FacebookOutlined style={{ fontSize: '1.5rem' }} />
</a>
<a href='https://obroudnice.cz/' target='_blank' rel="noreferrer">
<ChromeOutlined style={{ fontSize: '1.5rem' }} />
</a>
</Space>
<Text italic>Design made by © <a href='mailto: [email protected]'>Petr Buk</a></Text>
</Space>
</div>
)
}
Example #7
Source File: index.js From quick_redis_blog with MIT License | 6 votes |
render() {
return (
<div>
<Row>
<Space direction="vertical" style={{ width: "100%" }}>
<Col span={24}>
<Space direction="horizontal">
<Button onClick={this.formatJson.bind(this)}>
{intl.get("QuickMonacoEditor.format")}
</Button>
<Button onClick={this.delBlankJson.bind(this)}>
{intl.get("QuickMonacoEditor.delformat")}
</Button>
</Space>
</Col>
<Col span={24}>
<div style={{ border: "1px solid #eee" }}>
<MonacoEditor
ref="monacoEditor"
height={this.props.height}
language="json"
theme="vs"
value={this.props.value}
defaultValue=""
options={this.MONACO_EDITOR_OPTIONS}
onChange={(value) => {
this.props.onChange(value);
}}
editorDidMount={this.editorDidMount.bind(
this
)}
/>
</div>
</Col>
</Space>
</Row>
</div>
);
}
Example #8
Source File: loan.js From credit with Apache License 2.0 | 6 votes |
render() {
return (
<Descriptions title="个人信用及贷款记录" bordered>
<Descriptions.Item label="客户">李明</Descriptions.Item>
<Descriptions.Item label="信用分">85</Descriptions.Item>
<Descriptions.Item label="上次评估日期">2021/1/26</Descriptions.Item>
<Descriptions.Item label="目前信用状况" span={3}>
<Badge status="processing" text="良好" />
</Descriptions.Item>
<Descriptions.Item label="最大贷款金额">¥80000</Descriptions.Item>
<Descriptions.Item label="目前贷款金额">¥40000</Descriptions.Item>
<Descriptions.Item label="可用贷款金额">¥40000</Descriptions.Item>
<Descriptions.Item label="贷款记录">
1.日期:2020/2/15 金额:¥50000
<br />
状况:还款完毕
<br />
<br />
2.日期:2020/11/13 金额:¥40000
<br />
状况:未还款
<br />
<br />
</Descriptions.Item>
<Space direction="vertical">
<Search placeholder="输入贷款金额" enterButton="确认" onSearch={this.addLoan} style={{ width: 500 }} />
</Space>
</Descriptions>
)
}
Example #9
Source File: no-wrapper.jsx From virtuoso-design-system with MIT License | 6 votes |
Demo = () => {
const [show, setShow] = React.useState(true);
return (
<Space>
<Switch
checked={show}
onChange={() => {
setShow(!show);
}}
/>
<Badge count={show ? 25 : 0} />
<Badge count={show ? <ClockCircleOutlined style={{ color: '#f5222d' }} /> : 0} />
<Badge count={show ? 4 : 0} className="site-badge-count-4" />
<Badge
className="site-badge-count-109"
count={show ? 109 : 0}
style={{ backgroundColor: '#52c41a' }}
/>
</Space>
);
}
Example #10
Source File: adminUsers.js From ctf_platform with MIT License | 5 votes |
SelectParticipantCategoryForm = (props) => {
const [form] = Form.useForm();
const [loading, setLoading] = React.useState(false);
const [options, setOptions] = React.useState("")
useEffect(() => {
let optionList = props.categoryList.map((currentCat) => {
return <Radio value={currentCat}>{currentCat}</Radio>
})
optionList.push(<Radio value="none"><b>No Category</b></Radio>)
setOptions(optionList)
form.setFieldsValue({ category: props.participantCategory })
}, [props.username])
return (
<Form
form={form}
onFinish={async (values) => {
setLoading(true)
await fetch(window.ipAddress + "/v1/account/change/category", {
method: 'post',
headers: { 'Content-Type': 'application/json', "Authorization": window.IRSCTFToken },
body: JSON.stringify({
"username": props.username,
"category": values.category,
})
}).then((results) => {
return results.json(); //return data in JSON (since its JSON data)
}).then((data) => {
if (data.success === true) {
message.success({ content: "Category for '" + props.username + "' successfully changed to '" + values.category + "'." })
form.setFieldsValue({
category: values.category
})
props.fillTableData()
}
else if (data.error === "email-taken") {
message.error({ content: "Email is already taken, please try another email." })
}
else if (data.error === "wrong-password") {
message.error({ content: "Password is incorrect. Please try again." })
}
else if (data.error === "switching-disabled") {
message.error("Category switching is currently disabled by the admins.")
}
else {
message.error({ content: "Oops. Unknown error." })
}
}).catch((error) => {
console.log(error)
message.error({ content: "Oops. There was an issue connecting with the server" });
})
setLoading(false)
}}
style={{ display: "flex", flexDirection: "column", justifyContent: "center", width: "100%", marginBottom: "2vh" }}
>
<h3>Category:</h3>
<Form.Item
name="category"
rules={[{ required: true, message: 'Please select a category', }]}>
<Radio.Group>
<Space direction="vertical">
{options}
</Space>
</Radio.Group>
</Form.Item>
<span>Select a category to compete and be eligible for prizes of that category. Verification will be required after the CTF before claiming your prizes.</span>
<Form.Item>
<Button type="primary" htmlType="submit" icon={<ApartmentOutlined />} loading={loading} style={{ marginTop: "2ch" }}>Change Category</Button>
</Form.Item>
</Form>
);
}
Example #11
Source File: index.js From QiskitFlow with Apache License 2.0 | 5 votes |
expandedRowRender(experiment) {
let runs = experiment.runs.map((run, i) => {
return {
key: i,
date: run.created_at,
name: run.uuid,
operation: run
}
})
const runColumns = [
{ title: 'Date', dataIndex: 'date', key: 'date' },
{ title: 'Run', dataIndex: 'name', key: 'name' },
{
title: 'Status',
key: 'state',
render: () => (
<span>
<Badge status="success" />
Finished
</span>
),
},
{ title: 'Tags', dataIndex: 'tags', key: 'tags', render: () => <Tag>Qiskit</Tag> },
{
title: 'Action',
dataIndex: 'operation',
key: 'operation',
render: (run) => (
<Space size="middle">
<a onClick={() => {
this.setState({...this.state, run: run})
}}>View</a>
<a>Rerun</a>
</Space>
),
},
];
return <Table
columns={runColumns}
dataSource={runs}
pagination={false} />;
}
Example #12
Source File: MessageSkeleton.jsx From react-sendbird-messenger with GNU General Public License v3.0 | 5 votes |
export function MessageSkeleton({
loading = false,
rows = 1,
children,
size = 'default',
avatar,
avatarShape = 'circle',
}) {
if (loading) {
return [...Array(rows).keys()].map((i) => (
<Fragment key={i}>
<div
style={{
width: '100%',
display: 'flex',
justifyContent: i % 2 === 0 && 'flex-end',
}}
>
<Space
style={{
padding: 12,
height: 60,
flexDirection: i % 2 === 0 && 'row-reverse',
}}
>
{!!avatar && (
<Skeleton.Avatar
style={{
marginLeft: i % 2 === 0 && 8,
}}
active={true}
size={size}
shape={avatarShape}
/>
)}
<Skeleton.Input
style={{ minWidth: 308, width: 355 }}
active={true}
size={size}
/>
</Space>
</div>
</Fragment>
))
}
return children
}
Example #13
Source File: Edit.js From Peppermint with GNU General Public License v3.0 | 5 votes |
Edit = (props) => {
const [visible, setVisible] = useState(false);
const [isActive, setIsActive] = useState(props.n.active);
const [title, setTitle] = useState(props.n.title);
const [text, setText] = useState(props.n.text);
const onClose = async (e) => {
e.stopPropagation();
setVisible(false);
await postData();
};
const postData = async () => {
await fetch(`/api/v1/newsletter/update`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + localStorage.getItem("jwt"),
},
body: JSON.stringify({
id: props.n._id,
text,
title,
active: isActive,
}),
}).then((res) => res.json());
};
return (
<div>
<Button onClick={() => setVisible(true)}>
Edit
<Drawer
width={640}
placement="right"
onClose={onClose}
visible={visible}
>
<h4>Active : {props.n.active.toString()}</h4>
<h4>Created By : {props.n.createdBy.name}</h4>
<Divider />
<h4>
Title :{" "}
<Input
style={{ width: 300 }}
onChange={(e) => setTitle(e.target.value)}
/>
</h4>
<Divider />
<h5>Detail</h5>
<Input.TextArea
defaultValue={props.n.text}
rows={10}
onChange={(e) => setText(e.target.value)}
/>
<Divider />
<h5>Select the button below to change visability </h5>
<Radio.Group
buttonStyle="solid"
value={isActive}
onChange={(e) => setIsActive(e.target.value)}
style={{ textAlign: "center" }}
>
<Space>
<Radio.Button value={true}>Active</Radio.Button>
<Radio.Button value={false}>Hidden</Radio.Button>
</Space>
</Radio.Group>
</Drawer>
</Button>
</div>
);
}
Example #14
Source File: ExampleExperimentsSpace.jsx From ui with MIT License | 5 votes |
ExampleExperimentsSpace = ({ introductionText, imageStyle }) => {
const dispatch = useDispatch();
const environment = useSelector((state) => state?.networkResources?.environment);
const [exampleExperiments, setExampleExperiments] = useState([]);
useEffect(() => {
if (!environment) return;
fetchAPI('/v2/experiments/examples').then((experiments) => {
setExampleExperiments(experiments);
}).catch(() => { });
}, [environment]);
const cloneIntoCurrentExperiment = async (exampleExperimentId) => {
const url = `/v2/experiments/${exampleExperimentId}/clone`;
const newExperimentId = await fetchAPI(
url,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
},
);
await dispatch(loadExperiments());
await dispatch(setActiveExperiment(newExperimentId));
};
return (
<Empty
imageStyle={imageStyle}
description={(
<Space size='middle' direction='vertical'>
<Paragraph>
{introductionText}
</Paragraph>
{
exampleExperiments.length > 0 && (
<>
<Text>
Don't have data? Get started using one of our example datasets:
</Text>
<div style={{ width: 'auto', textAlign: 'left' }}>
<ul>
{
exampleExperiments.map(({ id, name }) => (
<li key={name}>
<Button
type='link'
size='small'
onClick={() => cloneIntoCurrentExperiment(id)}
>
{name}
</Button>
</li>
))
}
</ul>
</div>
</>
)
}
</Space>
)}
/>
);
}
Example #15
Source File: Backup.js From network-rc with Apache License 2.0 | 5 votes |
export default function Backup({
serverConfig,
resetServerConfig,
saveServerConfig,
updateVersion,
updateStaus,
}) {
const save = () => {
var blob = new Blob([JSON.stringify(serverConfig)], {
type: "text/plain;charset=utf-8",
});
saveAs(
blob,
`network-rc-config-backgup-${dayjs().format("YYYYMMDDTHHmmss")}.json`
);
};
const load = (file) => {
var reader = new FileReader();
reader.onload = function (e) {
if (reader.result) {
saveServerConfig(JSON.parse(reader.result));
}
};
reader.onerror = function (e) {
console.error(e);
message.error("读取备份错误");
};
reader.readAsText(file);
return false;
};
return (
<Form {...layout}>
<Form.Item>
<Space>
<Button icon={<DownloadOutlined />} type="primary" onClick={save}>
备份当前设置
</Button>
<Upload accept=".json" beforeUpload={load} showUploadList={false}>
<Button icon={<UploadOutlined />}>恢复已保存的设置</Button>
</Upload>
<Button icon={<ReloadOutlined />} danger onClick={resetServerConfig}>
恢复默认设置(所有设置)
</Button>
</Space>
</Form.Item>
<Form.Item >
<Button
onClick={(e) => {
e.preventDefault();
updateVersion();
}}
loading={updateStaus ? true : false}
>
{updateStaus || "更新版本"}
</Button>
</Form.Item>
</Form>
);
}
Example #16
Source File: Card.jsx From open-source with MIT License | 5 votes |
IconText = ({ icon, text }) => (
<Space>
{React.createElement(icon)}
{text}
</Space>
)
Example #17
Source File: index.js From ant-simple-pro with MIT License | 5 votes |
Globalization = memo(function Globalization(props) {
const { t, i18n } = useTranslation();
let listData = [];
for (let i = 0; i < 3; i++) {
listData.push({
index: i,
title: `Ant Simple Pro`,
avatar: <SvgIcon iconClass='logon' fontSize='30px' />,
description: t('description'),
content: t('content')
});
}
const IconText = ({ icon, text }) => (
<Space>
{React.createElement(icon)}
{text}
</Space>
);
const change = (val) => {
const lang = val.target.value;
i18n.changeLanguage(lang);
}
return (
<div className='bgW padding-10px'>
<div>
<Radio.Group defaultValue="en" buttonStyle="solid" onChange={change}>
<Radio.Button value="en">英文</Radio.Button>
<Radio.Button value="zh">中文</Radio.Button>
<Radio.Button value="ja">日文</Radio.Button>
</Radio.Group>
<a href="https://react.i18next.com/" style={{ padding: '0 10px' }} target='_blank'>了解过多react-i18next信息</a>
</div>
<List
itemLayout="vertical"
size="large"
dataSource={listData}
renderItem={item => (
<List.Item
key={item.index}
actions={[
<IconText icon={StarOutlined} text="156" key="list-vertical-star-o" />,
<IconText icon={LikeOutlined} text="156" key="list-vertical-like-o" />,
<IconText icon={MessageOutlined} text="2" key="list-vertical-message" />,
]}
extra={
<img
width={272}
alt="logo"
src="https://gw.alipayobjects.com/zos/rmsportal/mqaQswcyDLcXyDKnZfES.png"
/>
}
>
<List.Item.Meta
avatar={item.avatar}
title={<a href={item.href}>{item.title}</a>}
description={item.description}
/>
{item.content}
</List.Item>
)}
/>
</div>
)
})
Example #18
Source File: index.js From quick_redis_blog with MIT License | 5 votes |
render() {
return (
<div>
<Form initialValues={{ ...this.initValues }} ref="form">
<Row gutter={8}>
<Col span={14}>
<Form.Item
name="redisKey"
rules={[
{
required: true,
},
]}
style={{ marginBottom: "1px" }}
>
<Search
prefix="key :"
enterButton={
<Button
icon={<EditOutlined />}
></Button>
}
size="middle"
onSearch={this.renameKey.bind(this)}
/>
</Form.Item>
</Col>
<Col span={5}>
<Form.Item
name="ttl"
rules={[
{
required: true,
},
]}
style={{ marginBottom: "1px" }}
>
<Search
prefix="ttl :"
enterButton={
<Button
icon={<EditOutlined />}
></Button>
}
size="middle"
onSearch={this.updateTtl.bind(this)}
/>
</Form.Item>
</Col>
<Col span={5}>
<Space>
<Form.Item style={{ marginBottom: "1px" }}>
<Popconfirm
title={intl.get(
"HostKey.header.key.delete.notice"
)}
onConfirm={() => {
this.deleteKey();
}}
>
<Button
icon={<DeleteOutlined />}
></Button>
</Popconfirm>
</Form.Item>
<Form.Item style={{ marginBottom: "1px" }}>
<Button
icon={<ReloadOutlined />}
onClick={this.refreshAll.bind(this)}
></Button>
</Form.Item>
</Space>
</Col>
</Row>
</Form>
</div>
);
}
Example #19
Source File: settings.js From hashcat.launcher with MIT License | 5 votes |
render() {
return (
<>
<PageHeader
title="Settings"
/>
<Content style={{ padding: '16px 24px' }}>
<Row gutter={[16, 14]}>
<Col span={12}>
<Statistic title="Hashes" value={this.state._hashes.length} />
</Col>
<Col span={12}>
<Statistic title="Algorithms" value={Object.keys(this.state._algorithms).length} />
</Col>
<Col span={12}>
<Statistic title="Dictionaries" value={this.state._dictionaries.length} />
</Col>
<Col span={12}>
<Statistic title="Rules" value={this.state._rules.length} />
</Col>
<Col span={12}>
<Statistic title="Masks" value={this.state._masks.length} />
</Col>
<Col span={24}>
<Button
icon={<SyncOutlined />}
type="primary"
onClick={this.onClickRescan}
loading={this.state.isLoadingRescan}
>
Rescan
</Button>
</Col>
</Row>
<Row style={{ marginTop: "2rem" }} gutter={[16, 14]}>
<Col span={24}>
<Statistic
title="Task counter"
value={this.state.taskCounter}
/>
<Space>
<Button
style={{ marginTop: 16 }}
type="default"
onClick={this.onClickRefreshTaskCounter}
loading={this.state.isLoadingRefreshTaskCounter}
>
Refresh
</Button>
<Popconfirm
placement="topRight"
title="Are you sure you want to reset the task counter?"
onConfirm={this.onClickResetTaskCounter}
okText="Yes"
cancelText="No"
>
<Button
style={{ marginTop: 16 }}
type="danger"
loading={this.state.isLoadingResetTaskCounter}
>
Reset counter
</Button>
</Popconfirm>
</Space>
</Col>
</Row>
</Content>
</>
)
}
Example #20
Source File: certificateApprove.js From credit with Apache License 2.0 | 5 votes |
render() {
const data1 = [{
hash: randomHash(),
addr : "0x8a0Bc5Db7E852d0A3184A03AEA525Ef91FbEB5fE",
time: mockTime(1000000),
name: "David"
}]
const columns1 = [
{
title: '交易哈希',
dataIndex: 'hash',
key: 'hash',
render: text => {
if (text.length > 18) {
return <a>{text.substr(0, 18) + '...'}</a>
}
},
},
{
title: '申请方地址',
dataIndex: 'addr',
key: 'addr',
render: text => {
if (text.length > 18) {
return <a>{text.substr(0, 18) + '...'}</a>
}
},
},
{
title: '用户名',
dataIndex: 'name',
key: 'name',
},
{
title: '请求时间',
dataIndex: 'time',
key: 'time',
},
{
title: '操作',
key: 'action',
render: (text, record) => (
<Space size="middle">
<Button type="primary">发布证书</Button>
</Space>
),
},
];
return (
<div>
<Card title="签发证书" style={{width:1200}}>
<Table columns={columns1} dataSource={data1} pagination={{ pageSize: 5 }} />
</Card>
</div>
)
}
Example #21
Source File: mode.jsx From virtuoso-design-system with MIT License | 5 votes |
storiesOf('antd/date-picker', module).add('mode', () =>
<Space direction="vertical" size={12}>
<ControlledDatePicker />
<ControlledRangePicker />
</Space>,
{ docs: { page: () => (<><h1 id="enus">en-US</h1>
<p>Determing which panel to show with <code>mode</code> and <code>onPanelChange</code>.</p></>) } });
Example #22
Source File: QuestionGen.js From official-website-backend with MIT License | 4 votes |
QuestionGen = ({ onRemove, id }) => {
const { TextArea } = Input;
const makeAnswerField = (t) => {
if (t === "TextArea")
return (
<Form.Item
label="Placeholder ::"
name={`field_${id}_placeholder`}
rules={[
{
required: true,
message: "field required",
},
]}
>
<TextArea
style={{ maxWidth: "60%" }}
rows={4}
placeholder="write a placeholder"
/>
</Form.Item>
);
if (t === "Selection")
return (
<Form.List name={`field_${id}_selection`}>
{(fields, { add, remove }) => (
<>
{fields.map(({ key, name, fieldKey, ...restField }, index) => (
<Space
key={key}
style={{ display: "flex", marginBottom: 8 }}
align="baseline"
>
<Form.Item
{...restField}
name={[name, `selectionItem_${key}`]}
fieldKey={[fieldKey, `selectionItem_${key}`]}
label={`Option #${index + 1}`}
rules={[
{ required: true, message: "Missing Selection Item" },
]}
>
<Input
placeholder="write a Selection Item"
style={{ marginLeft: "1em" }}
/>
</Form.Item>
<span
className="menu-close"
onClick={() => remove(name)}
style={{ cursor: "pointer", marginLeft: "2em" }}
>
<FontAwesomeIcon
icon={faTimes}
color={"white"}
title="Erase option"
/>
</span>
</Space>
))}
<Form.Item>
<Button
type="ghost"
style={{ color: "white", marginLeft: "3em" }}
shape="round"
onClick={() => add()}
block
className={"col-3"}
>
+ Add field
</Button>
</Form.Item>
</>
)}
</Form.List>
);
if (t === "Text" || t === "Email")
return (
<Form.Item label="Placeholder ::" name={`field_${id}_placeholder`}>
<Input
style={{ maxWidth: "60%" }}
placeholder="write a placeholder"
/>
</Form.Item>
);
};
const [answer, setAnswer] = useState();
const handleAnswer = (type) => {
const a = makeAnswerField(type);
setAnswer(a);
};
return (
<div
style={{
boxShadow:
"0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19)",
borderRadius: "1em",
padding: "1em",
margin: "1em",
}}
>
<Form.Item noStyle>
<span
className="menu-close"
onClick={() => onRemove(id)}
style={{
cursor: "pointer",
float: "right",
margin: "1em",
marginTop: "5px",
}}
>
<FontAwesomeIcon icon={faTimes} color={"white"} title="Erase Field" />
</span>
<br />
<Form.Item
rules={[
{
required: true,
message: "field required",
},
]}
label="Label ::"
name={`field_${id}_label`}
>
<Input
placeholder="Please enter a label for the field"
style={{ maxWidth: "60%", marginLeft: "2.7em" }}
/>
</Form.Item>
<Form.Item
rules={[
{
required: true,
message: "field required",
},
]}
label="Answer Type ::"
name={`field_${id}_answerType`}
>
<Radio.Group
onChange={(e) => {
handleAnswer(e.target.value);
}}
>
<Radio.Button value="Text" style={{ background: "transparent" }}>
Text
</Radio.Button>
<Radio.Button value="Email" style={{ background: "transparent" }}>
Email
</Radio.Button>
<Radio.Button
value="TextArea"
style={{ background: "transparent" }}
>
TextArea
</Radio.Button>
<Radio.Button
value="Selection"
style={{ background: "transparent" }}
>
Selection
</Radio.Button>
</Radio.Group>
</Form.Item>
{answer}
<Form.Item
rules={[
{
required: true,
message: "field required",
},
]}
label="Is it required ::"
name={`field_${id}_isRequired`}
>
<Radio.Group>
<Radio.Button value={true} style={{ background: "transparent" }}>
Yes
</Radio.Button>
<Radio.Button value={false} style={{ background: "transparent" }}>
No
</Radio.Button>
</Radio.Group>
</Form.Item>
</Form.Item>
</div>
);
}
Example #23
Source File: adminChallengeCreate.js From ctf_platform with MIT License | 4 votes |
CreateChallengeForm = (props) => {
const [form] = Form.useForm();
const [editorValue, setEditorValue] = React.useState("")
const [existingCats, setExistingCats] = React.useState([])
const [finalSortedChalls, setfinalSortedChalls] = React.useState([])
useEffect(() => {
var currentValues = form.getFieldsValue()
currentValues.flags = [""]
form.setFieldsValue(currentValues)
//Render existing categories select options
let existCats = []
for (let i = 0; i < props.allCat.length; i++) {
existCats.push(<Option key={props.allCat[i].key} value={props.allCat[i].key}>{props.allCat[i].key}</Option>)
}
setExistingCats(existCats)
//Render existing challenges select options
let existChalls = {}
for (let i = 0; i < props.challenges.length; i++) {
if (!(props.challenges[i].category in existChalls)) existChalls[props.challenges[i].category] = []
existChalls[props.challenges[i].category].push({
value: props.challenges[i]._id,
label: props.challenges[i].name
})
}
let finalChalls = []
for (const category in existChalls) {
finalChalls.push({
value: category,
label: category,
children: existChalls[category]
})
}
setfinalSortedChalls(finalChalls)
}, [])
return (
<Form
form={form}
name="create_challenge_form"
className="create_challenge_form"
onValuesChange={() => { if (props.state.edited === false) props.setState({ edited: true }) }}
onFinish={async (values) => {
props.setState({ edited: false })
if (typeof values.flags === "undefined") {
message.warn("Please enter at least 1 flag")
}
else {
//console.log(values)
props.setState({ loading: true })
if (values.visibility === "false") {
values.visibility = false
}
else {
values.visibility = true
}
if (values.dynamic === "false") {
values.dynamic = false
}
else {
values.dynamic = true
}
if (typeof values.writeup !== "undefined") {
if (typeof values.writeupComplete === "undefined") {
values.writeupComplete = true
}
}
const category = (typeof values.category1 !== "undefined") ? values.category1 : values.category2
let requires = undefined
if (values.requires && values.requires.length > 0) requires = values.requires[1]
await fetch(window.ipAddress + "/v1/challenge/new", {
method: 'post',
headers: { 'Content-Type': 'application/json', "Authorization": window.IRSCTFToken },
body: JSON.stringify({
"name": values.name,
"category": category,
"description": values.description,
"points": values.points,
"flags": values.flags,
"tags": values.tags,
"hints": values.hints,
"max_attempts": values.max_attempts,
"visibility": values.visibility,
"writeup": values.writeup,
"writeupComplete": values.writeupComplete,
"requires": requires,
"dynamic": values.dynamic,
"initial": values.initial,
"minSolves": values.minSolves,
"minimum": values.minimum
})
}).then((results) => {
return results.json(); //return data in JSON (since its JSON data)
}).then((data) => {
//console.log(data)
if (data.success === true) {
message.success({ content: "Created challenge " + values.name + " successfully!" })
form.resetFields()
props.handleCreateBack()
}
else if (data.error === "exists") {
message.warn("A challenge with an existing name exists")
}
else {
message.error({ content: "Oops. Unknown error, please contact an admin." })
}
}).catch((error) => {
console.log(error)
message.error({ content: "Oops. Issue connecting with the server or client error, please check console and report the error. " });
})
props.setState({ loading: false })
}
}}
>
<Prompt
when={props.state.edited}
message='The challenge details you entered have not been saved. Are you sure you want to leave?'
/>
<h1>Challenge Name:</h1>
<Form.Item
name="name"
rules={[{ required: true, message: 'Please enter a challenge name' }]}
>
<Input allowClear placeholder="Challenge name" />
</Form.Item>
<Divider />
<h1>Challenge Category:</h1>
<h4>Select an Existing Category: </h4>
<Form.Item
name="category1"
rules={[{ required: !props.state.selectCatDisabled, message: 'Please enter a challenge category' }]}
>
<Select
disabled={props.state.selectCatDisabled}
allowClear
showSearch
placeholder="Select an existing Category"
onChange={(value) => {
if (value) {
props.setState({ inputCatDisabled: true })
}
else {
props.setState({ inputCatDisabled: false })
}
}}
>
{existingCats}
</Select>
</Form.Item>
<h4>Enter a New Category</h4>
<Form.Item
name="category2"
rules={[{ required: !props.state.inputCatDisabled, message: 'Please enter a challenge category' }]}
>
<Input onChange={(e) => {
e.target.value.length > 0 ? props.setState({ selectCatDisabled: true }) : props.setState({ selectCatDisabled: false })
}} disabled={props.state.inputCatDisabled} allowClear placeholder="Enter a new challenge category" />
</Form.Item>
<Divider />
<Suspense fallback={<div style={{ height: "100%", width: "100%", display: "flex", justifyContent: "center", alignItems: "center", zIndex: 15 }}>
<Ellipsis color="#177ddc" size={120} ></Ellipsis>
</div>}>
<h1>Challenge Description (Supports <a href="https://guides.github.com/features/mastering-markdown/" target="_blank" rel="noreferrer">Markdown</a> and <a href="https://github.com/rehypejs/rehype-raw" target="_blank" rel="noreferrer">HTML</a>):</h1>
<Form.Item
name="description"
rules={[{ required: true, message: 'Please enter a description' }]}
valuePropName={editorValue}
>
<MDEditor value={editorValue} onChange={(value) => { setEditorValue(value) }} preview="edit" />
</Form.Item>
<h3>Challenge Description Preview</h3>
<Card
type="inner"
bordered={true}
bodyStyle={{ backgroundColor: "#262626", textAlign: "center" }}
className="challengeModal"
>
<MarkdownRender>{editorValue}</MarkdownRender>
</Card>
</Suspense>
<Divider />
<div className="settings-responsive2" style={{ display: "flex", justifyContent: "space-around" }}>
<div style={{ display: "flex", flexDirection: "column", justifyContent: "center" }}>
<Card>
<h1>Challenge Points:</h1>
<Form.Item
name="points"
rules={[{ required: true, message: 'Please enter challenge points' }, {
type: 'integer',
message: "Please enter a valid integer between 0-100000",
},]}
initialValue={0}
>
<InputNumber disabled={props.state.dynamic} min={0} max={100000} style={{ width: "30ch" }} ></InputNumber>
</Form.Item>
</Card>
<Card>
<h1>Maximum Number of Attempts (Set to 0 for unlimited)</h1>
<Form.Item
name="max_attempts"
rules={[{ required: true, message: 'Please enter the maximum number of attempts' }, {
type: 'integer',
message: "Please enter a valid integer between 0-10000",
},]}
style={{ alignText: 'center' }}
initialValue={0}
>
<InputNumber min={0} max={10000} style={{ width: "30ch" }}></InputNumber>
</Form.Item>
</Card>
</div>
<Divider type="vertical" style={{ height: "inherit" }} />
<div style={{ display: "flex", flexDirection: "column" }}>
<Form.List name="flags" >
{(fields, { add, remove }) => {
return (
<Card>
<h1>Flags</h1>
{fields.map(field => (
<Space key={field.key} style={{ display: 'flex', marginBottom: 8 }} align="start">
<Form.Item
{...field}
name={[field.name]}
fieldKey={[field.fieldKey]}
rules={[{ required: true, message: 'Missing flag' }, { message: "Please enter a flag that is < 1000 characters", pattern: /^.{1,1000}$/ }]}
>
<Input style={{ width: "50ch" }} placeholder="Flag" />
</Form.Item>
{fields.length > 1 ? (
<MinusCircleOutlined
className="dynamic-delete-button"
style={{ margin: '0 8px', color: "red" }}
onClick={() => {
remove(field.name);
}}
/>
) : null}
</Space>
))}
<Form.Item>
<Button
type="dashed"
onLoad={() => { if (fields.length < 1) add() }}
onClick={() => {
add();
}}
block
style={{ width: "50ch" }}
>
<PlusOutlined /> Add Flag
</Button>
</Form.Item>
</Card>
);
}}
</Form.List>
<Form.List name="tags">
{(fields, { add, remove }) => {
return (
<Card>
<h1>Tags</h1>
{fields.map(field => (
<Space key={field.key} style={{ display: 'flex', marginBottom: 8 }} align="start">
<Form.Item
{...field}
name={[field.name]}
fieldKey={[field.fieldKey]}
rules={[{ required: true, message: 'Missing tag' }]}
>
<Input placeholder="Tag" style={{ width: "50ch" }} />
</Form.Item>
<MinusCircleOutlined
className="dynamic-delete-button"
style={{ margin: '0 8px', color: "red" }}
onClick={() => {
remove(field.name);
}}
/>
</Space>
))}
<Form.Item>
<Button
type="dashed"
onClick={() => {
add();
}}
block
style={{ width: "50ch" }}
>
<PlusOutlined /> Add Tag
</Button>
</Form.Item>
</Card>
);
}}
</Form.List>
</div>
</div>
<Divider />
<div className="settings-responsive2" style={{ display: "flex", justifyContent: "space-around" }}>
<div style={{ display: "flex", flexDirection: "column" }}>
<Form.List name="hints" >
{(fields, { add, remove }) => {
return (
<Card>
<h1>Hints</h1>
{fields.map(field => (
<Space key={field.key} style={{ display: 'flex', marginBottom: 8 }} align="start">
<Form.Item
{...field}
name={[field.name, "hint"]}
fieldKey={[field.fieldKey, "hint"]}
rules={[{ required: true, message: 'Missing hint' }]}
>
<Input placeholder="Hint" style={{ width: "20vw" }} />
</Form.Item>
<Form.Item
{...field}
name={[field.name, "cost"]}
fieldKey={[field.fieldKey, "cost"]}
rules={[{ required: true, message: 'Missing cost for hint' }, {
type: 'integer',
message: "Please enter a valid integer between 0-10000",
},]}
>
<InputNumber min={0} max={10000} placeholder="Cost"></InputNumber>
</Form.Item>
<MinusCircleOutlined
style={{ color: "red" }}
onClick={() => {
remove(field.name);
}}
/>
</Space>
))}
<Form.Item>
<Button
type="dashed"
onClick={() => {
add();
}}
block
style={{ width: "50ch" }}
>
<PlusOutlined /> Add Hint
</Button>
</Form.Item>
</Card>
);
}}
</Form.List>
<Card>
<h1>Writeup Link (Optional)</h1>
<Form.Item
name="writeup"
rules={[
{
type: 'url',
message: "Please enter a valid link",
}]}
>
<Input allowClear style={{ width: "50ch" }} placeholder="Enter a writeup link for this challenge" />
</Form.Item>
<div style={{ display: "flex", alignContent: "center" }}>
<h4 style={{ marginRight: "2ch" }}>Release Writeup Only After Completion: </h4>
<Form.Item
name="writeupComplete"
>
<Switch defaultChecked />
</Form.Item>
</div>
</Card>
<Card>
<h1>Visibility</h1>
<Form.Item
name="visibility"
rules={[{ required: true, message: 'Please set the challenge visibility' }]}
initialValue="false"
>
<Select style={{ width: "20ch" }}>
<Option value="false"><span style={{ color: "#d32029" }}>Hidden <EyeInvisibleOutlined /></span></Option>
<Option value="true"><span style={{ color: "#49aa19" }}>Visible <EyeOutlined /></span></Option>
</Select>
</Form.Item>
</Card>
</div>
<Divider type="vertical" style={{ height: "inherit" }} />
<div style={{ display: "flex", flexDirection: "column" }}>
<Card>
<h1>Challenge Required: </h1>
<Form.Item
name="requires"
>
<Cascader
options={finalSortedChalls}
allowClear
showSearch
placeholder="Select an existing challenge" />
</Form.Item>
<p>Locks this challenge until the provided challenge above has been solved.</p>
</Card>
<Card>
<h1>Dynamic Scoring</h1>
<Form.Item
name="dynamic"
rules={[{ required: true, message: 'Please set whether the challenge uses dynamic scoring' }]}
initialValue="false"
>
<Select onSelect={(option) => { option === "false" ? props.setState({ dynamic: false }) : props.setState({ dynamic: true }) }} style={{ width: "20ch" }}>
<Option value="false"><span style={{ color: "#d32029" }}>Disabled</span></Option>
<Option value="true"><span style={{ color: "#49aa19" }}>Enabled</span></Option>
</Select>
</Form.Item>
<h1>Initial Points:</h1>
<Form.Item
name="initial"
rules={[{ required: props.state.dynamic, message: 'Please enter the initial challenge points' }, {
type: 'integer',
message: "Please enter a valid integer between 1-100000",
},]}
initialValue={500}
>
<InputNumber disabled={!props.state.dynamic} min={1} max={100000} ></InputNumber>
</Form.Item>
<p>Initial number of points when there are 0/1 solves on a challenge</p>
<h1>Minimum Points:</h1>
<Form.Item
name="minimum"
rules={[{ required: props.state.dynamic, message: 'Please enter the minimum challenge points' }, {
type: 'integer',
message: "Please enter a valid integer between 0-100000",
},]}
initialValue={100}
>
<InputNumber disabled={!props.state.dynamic} min={0} max={100000} ></InputNumber>
</Form.Item>
<p>Minimum amount of points that the challenge can decay too</p>
<h1>Solves to Minimum:</h1>
<Form.Item
name="minSolves"
rules={[{ required: props.state.dynamic, message: 'Please enter the solves to minimum' }, {
type: 'integer',
message: "Please enter a valid integer between 1-100000",
},]}
initialValue={50}
>
<InputNumber disabled={!props.state.dynamic} min={1} max={100000} ></InputNumber>
</Form.Item>
<p>Number of solves on the challenge till it decays to the minimum point.</p>
</Card>
</div>
</div>
<Form.Item>
<div style={{ display: "flex", justifyContent: "space-between", flexDirection: "row", marginTop: "2vh" }}>
<div>
<Button style={{ marginBottom: "1.5vh", marginRight: "2vw", backgroundColor: "#d4b106", borderColor: "", color: "white" }} onClick={() => { props.previewChallenge(form.getFieldsValue()); }}>Preview</Button>
<Button loading={props.loadingStatus} type="primary" htmlType="submit" className="login-form-button" style={{ marginBottom: "1.5vh" }}>Create Challenge</Button>
</div>
<div>
<Button style={{ marginRight: "2vw" }} type="primary" danger onClick={() => { form.resetFields() }}>Clear</Button>
</div>
</div>
</Form.Item>
</Form>
);
}
Example #24
Source File: Swap.jsx From Tai-Shang-NFT-Wallet with MIT License | 4 votes |
function Swap({ selectedProvider, tokenListURI }) {
const [tokenIn, setTokenIn] = useState(defaultToken);
const [tokenOut, setTokenOut] = useState(defaultTokenOut);
const [exact, setExact] = useState();
const [amountIn, setAmountIn] = useState();
const [amountInMax, setAmountInMax] = useState();
const [amountOut, setAmountOut] = useState();
const [amountOutMin, setAmountOutMin] = useState();
const [trades, setTrades] = useState();
const [routerAllowance, setRouterAllowance] = useState();
const [balanceIn, setBalanceIn] = useState();
const [balanceOut, setBalanceOut] = useState();
const [slippageTolerance, setSlippageTolerance] = useState(
new Percent(Math.round(defaultSlippage * 100).toString(), "10000"),
);
const [timeLimit, setTimeLimit] = useState(defaultTimeLimit);
const [swapping, setSwapping] = useState(false);
const [approving, setApproving] = useState(false);
const [settingsVisible, setSettingsVisible] = useState(false);
const [swapModalVisible, setSwapModalVisible] = useState(false);
const [tokenList, setTokenList] = useState([]);
const [tokens, setTokens] = useState();
const [invertPrice, setInvertPrice] = useState(false);
const blockNumber = useBlockNumber(selectedProvider, 3000);
const signer = selectedProvider.getSigner();
const routerContract = new ethers.Contract(ROUTER_ADDRESS, IUniswapV2Router02ABI, signer);
const _tokenListUri = tokenListURI || "https://gateway.ipfs.io/ipns/tokens.uniswap.org";
const debouncedAmountIn = useDebounce(amountIn, 500);
const debouncedAmountOut = useDebounce(amountOut, 500);
const activeChainId = process.env.REACT_APP_NETWORK === "kovan" ? ChainId.KOVAN : ChainId.MAINNET;
useEffect(() => {
const getTokenList = async () => {
console.log(_tokenListUri);
try {
const tokenList = await fetch(_tokenListUri);
const tokenListJson = await tokenList.json();
const filteredTokens = tokenListJson.tokens.filter(function (t) {
return t.chainId === activeChainId;
});
const ethToken = WETH[activeChainId];
ethToken.name = "Ethereum";
ethToken.symbol = "ETH";
ethToken.logoURI =
"https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png";
const _tokenList = [ethToken, ...filteredTokens];
setTokenList(_tokenList);
const _tokens = tokenListToObject(_tokenList);
setTokens(_tokens);
} catch (e) {
console.log(e);
}
};
getTokenList();
}, [tokenListURI]);
const getTrades = async () => {
if (tokenIn && tokenOut && (amountIn || amountOut)) {
const pairs = arr => arr.map((v, i) => arr.slice(i + 1).map(w => [v, w])).flat();
const baseTokens = tokenList
.filter(function (t) {
return ["DAI", "USDC", "USDT", "COMP", "ETH", "MKR", "LINK", tokenIn, tokenOut].includes(t.symbol);
})
.map(el => {
return new Token(el.chainId, el.address, el.decimals, el.symbol, el.name);
});
const listOfPairwiseTokens = pairs(baseTokens);
const getPairs = async list => {
const listOfPromises = list.map(item => Fetcher.fetchPairData(item[0], item[1], selectedProvider));
return Promise.all(listOfPromises.map(p => p.catch(() => undefined)));
};
const listOfPairs = await getPairs(listOfPairwiseTokens);
let bestTrade;
if (exact === "in") {
setAmountInMax();
bestTrade = Trade.bestTradeExactIn(
listOfPairs.filter(item => item),
new TokenAmount(tokens[tokenIn], ethers.utils.parseUnits(amountIn.toString(), tokens[tokenIn].decimals)),
tokens[tokenOut],
{ maxNumResults: 3, maxHops: 1 },
);
if (bestTrade[0]) {
setAmountOut(bestTrade[0].outputAmount.toSignificant(6));
} else {
setAmountOut();
}
} else if (exact === "out") {
setAmountOutMin();
bestTrade = Trade.bestTradeExactOut(
listOfPairs.filter(item => item),
tokens[tokenIn],
new TokenAmount(tokens[tokenOut], ethers.utils.parseUnits(amountOut.toString(), tokens[tokenOut].decimals)),
{ maxNumResults: 3, maxHops: 1 },
);
if (bestTrade[0]) {
setAmountIn(bestTrade[0].inputAmount.toSignificant(6));
} else {
setAmountIn();
}
}
setTrades(bestTrade);
console.log(bestTrade);
}
};
useEffect(() => {
getTrades();
}, [tokenIn, tokenOut, debouncedAmountIn, debouncedAmountOut, slippageTolerance, selectedProvider]);
useEffect(() => {
if (trades && trades[0]) {
if (exact === "in") {
setAmountOutMin(trades[0].minimumAmountOut(slippageTolerance));
} else if (exact === "out") {
setAmountInMax(trades[0].maximumAmountIn(slippageTolerance));
}
}
}, [slippageTolerance, amountIn, amountOut, trades]);
const getBalance = async (_token, _account, _contract) => {
let newBalance;
if (_token === "ETH") {
newBalance = await selectedProvider.getBalance(_account);
} else {
newBalance = await makeCall("balanceOf", _contract, [_account]);
}
return newBalance;
};
const getAccountInfo = async () => {
if (tokens) {
const accountList = await selectedProvider.listAccounts();
if (tokenIn) {
const tempContractIn = new ethers.Contract(tokens[tokenIn].address, erc20Abi, selectedProvider);
const newBalanceIn = await getBalance(tokenIn, accountList[0], tempContractIn);
setBalanceIn(newBalanceIn);
let allowance;
if (tokenIn === "ETH") {
setRouterAllowance();
} else {
allowance = await makeCall("allowance", tempContractIn, [accountList[0], ROUTER_ADDRESS]);
setRouterAllowance(allowance);
}
}
if (tokenOut) {
const tempContractOut = new ethers.Contract(tokens[tokenOut].address, erc20Abi, selectedProvider);
const newBalanceOut = await getBalance(tokenOut, accountList[0], tempContractOut);
setBalanceOut(newBalanceOut);
}
}
};
usePoller(getAccountInfo, 6000);
const route = trades
? trades.length > 0
? trades[0].route.path.map(function (item) {
return item.symbol;
})
: []
: [];
const updateRouterAllowance = async newAllowance => {
setApproving(true);
try {
const tempContract = new ethers.Contract(tokens[tokenIn].address, erc20Abi, signer);
const result = await makeCall("approve", tempContract, [ROUTER_ADDRESS, newAllowance]);
console.log(result);
setApproving(false);
return true;
} catch (e) {
notification.open({
message: "Approval unsuccessful",
description: `Error: ${e.message}`,
});
}
};
const approveRouter = async () => {
const approvalAmount =
exact === "in"
? ethers.utils.hexlify(ethers.utils.parseUnits(amountIn.toString(), tokens[tokenIn].decimals))
: amountInMax.raw.toString();
console.log(approvalAmount);
const approval = updateRouterAllowance(approvalAmount);
if (approval) {
notification.open({
message: "Token transfer approved",
description: `You can now swap up to ${amountIn} ${tokenIn}`,
});
}
};
const removeRouterAllowance = async () => {
const approvalAmount = ethers.utils.hexlify(0);
console.log(approvalAmount);
const removal = updateRouterAllowance(approvalAmount);
if (removal) {
notification.open({
message: "Token approval removed",
description: `The router is no longer approved for ${tokenIn}`,
});
}
};
const executeSwap = async () => {
setSwapping(true);
try {
let args;
const metadata = {};
let call;
const deadline = Math.floor(Date.now() / 1000) + timeLimit;
const path = trades[0].route.path.map(function (item) {
return item.address;
});
console.log(path);
const accountList = await selectedProvider.listAccounts();
const address = accountList[0];
if (exact === "in") {
const _amountIn = ethers.utils.hexlify(ethers.utils.parseUnits(amountIn.toString(), tokens[tokenIn].decimals));
const _amountOutMin = ethers.utils.hexlify(ethers.BigNumber.from(amountOutMin.raw.toString()));
if (tokenIn === "ETH") {
call = "swapExactETHForTokens";
args = [_amountOutMin, path, address, deadline];
metadata.value = _amountIn;
} else {
call = tokenOut === "ETH" ? "swapExactTokensForETH" : "swapExactTokensForTokens";
args = [_amountIn, _amountOutMin, path, address, deadline];
}
} else if (exact === "out") {
const _amountOut = ethers.utils.hexlify(
ethers.utils.parseUnits(amountOut.toString(), tokens[tokenOut].decimals),
);
const _amountInMax = ethers.utils.hexlify(ethers.BigNumber.from(amountInMax.raw.toString()));
if (tokenIn === "ETH") {
call = "swapETHForExactTokens";
args = [_amountOut, path, address, deadline];
metadata.value = _amountInMax;
} else {
call = tokenOut === "ETH" ? "swapTokensForExactETH" : "swapTokensForExactTokens";
args = [_amountOut, _amountInMax, path, address, deadline];
}
}
console.log(call, args, metadata);
const result = await makeCall(call, routerContract, args, metadata);
console.log(result);
notification.open({
message: "Swap complete ?",
description: (
<>
<Text>{`Swapped ${tokenIn} for ${tokenOut}, transaction: `}</Text>
<Text copyable>{result.hash}</Text>
</>
),
});
setSwapping(false);
} catch (e) {
console.log(e);
setSwapping(false);
notification.open({
message: "Swap unsuccessful",
description: `Error: ${e.message}`,
});
}
};
const showSwapModal = () => {
setSwapModalVisible(true);
};
const handleSwapModalOk = () => {
setSwapModalVisible(false);
executeSwap();
};
const handleSwapModalCancel = () => {
setSwapModalVisible(false);
};
const insufficientBalance = balanceIn
? parseFloat(ethers.utils.formatUnits(balanceIn, tokens[tokenIn].decimals)) < amountIn
: null;
const inputIsToken = tokenIn !== "ETH";
const insufficientAllowance = !inputIsToken
? false
: routerAllowance
? parseFloat(ethers.utils.formatUnits(routerAllowance, tokens[tokenIn].decimals)) < amountIn
: null;
const formattedBalanceIn = balanceIn
? parseFloat(ethers.utils.formatUnits(balanceIn, tokens[tokenIn].decimals)).toPrecision(6)
: null;
const formattedBalanceOut = balanceOut
? parseFloat(ethers.utils.formatUnits(balanceOut, tokens[tokenOut].decimals)).toPrecision(6)
: null;
const metaIn =
tokens && tokenList && tokenIn
? tokenList.filter(function (t) {
return t.address === tokens[tokenIn].address;
})[0]
: null;
const metaOut =
tokens && tokenList && tokenOut
? tokenList.filter(function (t) {
return t.address === tokens[tokenOut].address;
})[0]
: null;
const cleanIpfsURI = uri => {
try {
return uri.replace("ipfs://", "https://ipfs.io/ipfs/");
} catch (e) {
console.log(e, uri);
return uri;
}
};
const logoIn = metaIn ? cleanIpfsURI(metaIn.logoURI) : null;
const logoOut = metaOut ? cleanIpfsURI(metaOut.logoURI) : null;
const rawPrice = trades && trades[0] ? trades[0].executionPrice : null;
const price = rawPrice ? rawPrice.toSignificant(7) : null;
const priceDescription = rawPrice
? invertPrice
? `${rawPrice.invert().toSignificant(7)} ${tokenIn} per ${tokenOut}`
: `${price} ${tokenOut} per ${tokenIn}`
: null;
const priceWidget = (
<Space>
<Text type="secondary">{priceDescription}</Text>
<Button
type="text"
onClick={() => {
setInvertPrice(!invertPrice);
}}
>
<RetweetOutlined />
</Button>
</Space>
);
const swapModal = (
<Modal title="Confirm swap" visible={swapModalVisible} onOk={handleSwapModalOk} onCancel={handleSwapModalCancel}>
<Row>
<Space>
<img src={logoIn} alt={tokenIn} width="30" />
{amountIn}
{tokenIn}
</Space>
</Row>
<Row justify="center" align="middle" style={{ width: 30 }}>
<span>↓</span>
</Row>
<Row>
<Space>
<img src={logoOut} alt={tokenOut} width="30" />
{amountOut}
{tokenOut}
</Space>
</Row>
<Divider />
<Row>{priceWidget}</Row>
<Row>
{trades && ((amountOutMin && exact === "in") || (amountInMax && exact === "out"))
? exact === "in"
? `Output is estimated. You will receive at least ${amountOutMin.toSignificant(
6,
)} ${tokenOut} or the transaction will revert.`
: `Input is estimated. You will sell at most ${amountInMax.toSignificant(
6,
)} ${tokenIn} or the transaction will revert.`
: null}
</Row>
</Modal>
);
return (
<Card
title={
<Space>
<img src="https://ipfs.io/ipfs/QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg" width="40" alt="uniswapLogo" />
<Typography>Uniswapper</Typography>
</Space>
}
extra={
<Button
type="text"
onClick={() => {
setSettingsVisible(true);
}}
>
<SettingOutlined />
</Button>
}
>
<Space direction="vertical">
<Row justify="center" align="middle">
<Card
size="small"
type="inner"
title={`From${exact === "out" && tokenIn && tokenOut ? " (estimate)" : ""}`}
extra={
<>
<img src={logoIn} alt={tokenIn} width="30" />
<Button
type="link"
onClick={() => {
setAmountOut();
setAmountIn(ethers.utils.formatUnits(balanceIn, tokens[tokenIn].decimals));
setAmountOutMin();
setAmountInMax();
setExact("in");
}}
>
{formattedBalanceIn}
</Button>
</>
}
style={{ width: 400, textAlign: "left" }}
>
<InputNumber
style={{ width: "160px" }}
min={0}
size="large"
value={amountIn}
onChange={e => {
setAmountOut();
setTrades();
setAmountIn(e);
setExact("in");
}}
/>
<Select
showSearch
value={tokenIn}
style={{ width: "120px" }}
size="large"
bordered={false}
defaultValue={defaultToken}
onChange={value => {
console.log(value);
if (value === tokenOut) {
console.log("switch!", tokenIn);
setTokenOut(tokenIn);
setAmountOut(amountIn);
setBalanceOut(balanceIn);
}
setTokenIn(value);
setTrades();
setAmountIn();
setExact("out");
setBalanceIn();
}}
filterOption={(input, option) => option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
optionFilterProp="children"
>
{tokenList.map(token => (
<Option key={token.symbol} value={token.symbol}>
{token.symbol}
</Option>
))}
</Select>
</Card>
</Row>
<Row justify="center" align="middle">
<Tooltip title={route.join("->")}>
<span>↓</span>
</Tooltip>
</Row>
<Row justify="center" align="middle">
<Card
size="small"
type="inner"
title={`To${exact === "in" && tokenIn && tokenOut ? " (estimate)" : ""}`}
extra={
<>
<img src={logoOut} width="30" alt={tokenOut} />
<Button type="text">{formattedBalanceOut}</Button>
</>
}
style={{ width: 400, textAlign: "left" }}
>
<InputNumber
style={{ width: "160px" }}
size="large"
min={0}
value={amountOut}
onChange={e => {
setAmountOut(e);
setAmountIn();
setTrades();
setExact("out");
}}
/>
<Select
showSearch
value={tokenOut}
style={{ width: "120px" }}
size="large"
bordered={false}
onChange={value => {
console.log(value, tokenIn, tokenOut);
if (value === tokenIn) {
console.log("switch!", tokenOut);
setTokenIn(tokenOut);
setAmountIn(amountOut);
setBalanceIn(balanceOut);
}
setTokenOut(value);
setExact("in");
setAmountOut();
setTrades();
setBalanceOut();
}}
filterOption={(input, option) => option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
optionFilterProp="children"
>
{tokenList.map(token => (
<Option key={token.symbol} value={token.symbol}>
{token.symbol}
</Option>
))}
</Select>
</Card>
</Row>
<Row justify="center" align="middle">
{priceDescription ? priceWidget : null}
</Row>
<Row justify="center" align="middle">
<Space>
{inputIsToken ? (
<Button size="large" loading={approving} disabled={!insufficientAllowance} onClick={approveRouter}>
{!insufficientAllowance && amountIn && amountOut ? "Approved" : "Approve"}
</Button>
) : null}
<Button
size="large"
loading={swapping}
disabled={insufficientAllowance || insufficientBalance || !amountIn || !amountOut}
onClick={showSwapModal}
>
{insufficientBalance ? "Insufficient balance" : "Swap!"}
</Button>
{swapModal}
</Space>
</Row>
</Space>
<Drawer
visible={settingsVisible}
onClose={() => {
setSettingsVisible(false);
}}
width={500}
>
<Descriptions title="Details" column={1} style={{ textAlign: "left" }}>
<Descriptions.Item label="blockNumber">{blockNumber}</Descriptions.Item>
<Descriptions.Item label="routerAllowance">
<Space>
{routerAllowance ? ethers.utils.formatUnits(routerAllowance, tokens[tokenIn].decimals) : null}
{routerAllowance > 0 ? <Button onClick={removeRouterAllowance}>Remove Allowance</Button> : null}
</Space>
</Descriptions.Item>
<Descriptions.Item label="route">{route.join("->")}</Descriptions.Item>
<Descriptions.Item label="exact">{exact}</Descriptions.Item>
<Descriptions.Item label="bestPrice">
{trades ? (trades.length > 0 ? trades[0].executionPrice.toSignificant(6) : null) : null}
</Descriptions.Item>
<Descriptions.Item label="nextMidPrice">
{trades ? (trades.length > 0 ? trades[0].nextMidPrice.toSignificant(6) : null) : null}
</Descriptions.Item>
<Descriptions.Item label="priceImpact">
{trades ? (trades.length > 0 ? trades[0].priceImpact.toSignificant(6) : null) : null}
</Descriptions.Item>
<Descriptions.Item label="slippageTolerance">
<InputNumber
defaultValue={defaultSlippage}
min={0}
max={100}
precision={2}
formatter={value => `${value}%`}
parser={value => value.replace("%", "")}
onChange={value => {
console.log(value);
const slippagePercent = new Percent(Math.round(value * 100).toString(), "10000");
setSlippageTolerance(slippagePercent);
}}
/>
</Descriptions.Item>
<Descriptions.Item label="amountInMax">{amountInMax ? amountInMax.toExact() : null}</Descriptions.Item>
<Descriptions.Item label="amountOutMin">{amountOutMin ? amountOutMin.toExact() : null}</Descriptions.Item>
<Descriptions.Item label="timeLimitInSeconds">
<InputNumber
min={0}
max={3600}
defaultValue={defaultTimeLimit}
onChange={value => {
console.log(value);
setTimeLimit(value);
}}
/>
</Descriptions.Item>
</Descriptions>
</Drawer>
</Card>
);
}
Example #25
Source File: Swap.jsx From moonshot with MIT License | 4 votes |
function Swap({ selectedProvider, tokenListURI }) {
const [tokenIn, setTokenIn] = useState(defaultToken)
const [tokenOut, setTokenOut] = useState(defaultTokenOut)
const [exact, setExact] = useState()
const [amountIn, setAmountIn] = useState()
const [amountInMax, setAmountInMax] = useState()
const [amountOut, setAmountOut] = useState()
const [amountOutMin, setAmountOutMin] = useState()
const [trades, setTrades] = useState()
const [routerAllowance, setRouterAllowance] = useState()
const [balanceIn, setBalanceIn] = useState()
const [balanceOut, setBalanceOut] = useState()
const [slippageTolerance, setSlippageTolerance] = useState(new Percent(Math.round(defaultSlippage*100).toString(), "10000"))
const [timeLimit, setTimeLimit] = useState(defaultTimeLimit)
const [swapping, setSwapping] = useState(false)
const [approving, setApproving] = useState(false)
const [settingsVisible, setSettingsVisible] = useState(false)
const [swapModalVisible, setSwapModalVisible] = useState(false)
const [tokenList, setTokenList] = useState([])
const [tokens, setTokens] = useState()
const [invertPrice, setInvertPrice] = useState(false)
let blockNumber = useBlockNumber(selectedProvider, 3000)
let signer = selectedProvider.getSigner()
let routerContract = new ethers.Contract(ROUTER_ADDRESS, IUniswapV2Router02ABI, signer);
let _tokenListUri = tokenListURI ? tokenListURI : 'https://gateway.ipfs.io/ipns/tokens.uniswap.org'
const debouncedAmountIn = useDebounce(amountIn, 500);
const debouncedAmountOut = useDebounce(amountOut, 500);
const activeChainId = (process.env.REACT_APP_NETWORK === 'kovan' ? ChainId.KOVAN : ChainId.MAINNET)
useEffect(() => {
const getTokenList = async () => {
console.log(_tokenListUri)
try {
let tokenList = await fetch(_tokenListUri)
let tokenListJson = await tokenList.json()
let filteredTokens = tokenListJson.tokens.filter(function (t) {
return t.chainId === activeChainId
})
let ethToken = WETH[activeChainId]
ethToken.name = 'Ethereum'
ethToken.symbol = 'ETH'
ethToken.logoURI = "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"
let _tokenList = [ethToken, ...filteredTokens]
setTokenList(_tokenList)
let _tokens = tokenListToObject(_tokenList)
setTokens(_tokens)
} catch (e) {
console.log(e)
}
}
getTokenList()
},[tokenListURI])
const getTrades = async () => {
if(tokenIn && tokenOut && (amountIn || amountOut)) {
let pairs = (arr) => arr.map( (v, i) => arr.slice(i + 1).map(w => [v,w]) ).flat();
let baseTokens = tokenList.filter(function (t) {
return ['DAI', 'USDC', 'USDT', 'COMP', 'ETH', 'MKR', 'LINK', tokenIn, tokenOut].includes(t.symbol)
}).map((el) => {
return new Token(el.chainId, el.address, el.decimals, el.symbol, el.name)
})
let listOfPairwiseTokens = pairs(baseTokens)
const getPairs = async (list) => {
let listOfPromises = list.map(item => Fetcher.fetchPairData(item[0], item[1], selectedProvider))
return Promise.all(listOfPromises.map(p => p.catch(() => undefined)));
}
let listOfPairs = await getPairs(listOfPairwiseTokens)
let bestTrade
if(exact === 'in') {
setAmountInMax()
bestTrade = Trade.bestTradeExactIn(
listOfPairs.filter(item => item),
new TokenAmount(tokens[tokenIn], parseUnits(amountIn.toString(), tokens[tokenIn].decimals)),
tokens[tokenOut], { maxNumResults: 3, maxHops: 1 })
if(bestTrade[0]) {
setAmountOut(bestTrade[0].outputAmount.toSignificant(6))
} else { setAmountOut() }
} else if (exact === 'out') {
setAmountOutMin()
bestTrade = Trade.bestTradeExactOut(
listOfPairs.filter(item => item),
tokens[tokenIn],
new TokenAmount(tokens[tokenOut], parseUnits(amountOut.toString(), tokens[tokenOut].decimals)),
{ maxNumResults: 3, maxHops: 1 })
if(bestTrade[0]) {
setAmountIn(bestTrade[0].inputAmount.toSignificant(6))
} else { setAmountIn() }
}
setTrades(bestTrade)
console.log(bestTrade)
}
}
useEffect(() => {
getTrades()
},[tokenIn, tokenOut, debouncedAmountIn, debouncedAmountOut, slippageTolerance, selectedProvider])
useEffect(() => {
if(trades && trades[0]) {
if(exact === 'in') {
setAmountOutMin(trades[0].minimumAmountOut(slippageTolerance))
} else if (exact === 'out') {
setAmountInMax(trades[0].maximumAmountIn(slippageTolerance))
}
}
}, [slippageTolerance, amountIn, amountOut, trades])
const getBalance = async (_token, _account, _contract) => {
let newBalance
if(_token === 'ETH') {
newBalance = await selectedProvider.getBalance(_account)
} else {
newBalance = await makeCall('balanceOf', _contract, [_account])
}
return newBalance
}
const getAccountInfo = async () => {
if(tokens) {
let accountList = await selectedProvider.listAccounts()
if(tokenIn) {
let tempContractIn = new ethers.Contract(tokens[tokenIn].address, erc20Abi, selectedProvider);
let newBalanceIn = await getBalance(tokenIn, accountList[0], tempContractIn)
setBalanceIn(newBalanceIn)
let allowance
if(tokenIn === 'ETH') {
setRouterAllowance()
} else {
allowance = await makeCall('allowance',tempContractIn,[accountList[0],ROUTER_ADDRESS])
setRouterAllowance(allowance)
}
}
if(tokenOut) {
let tempContractOut = new ethers.Contract(tokens[tokenOut].address, erc20Abi, selectedProvider);
let newBalanceOut = await getBalance(tokenOut, accountList[0], tempContractOut)
setBalanceOut(newBalanceOut)
}
}
}
usePoller(getAccountInfo, 6000)
let route = trades ? (trades.length > 0 ? trades[0].route.path.map(function(item) {
return item['symbol'];
}) : []) : []
const updateRouterAllowance = async (newAllowance) => {
setApproving(true)
try {
let tempContract = new ethers.Contract(tokens[tokenIn].address, erc20Abi, signer);
let result = await makeCall('approve', tempContract, [ROUTER_ADDRESS, newAllowance])
console.log(result)
setApproving(false)
return true
} catch(e) {
notification.open({
message: 'Approval unsuccessful',
description:
`Error: ${e.message}`,
});
}
}
const approveRouter = async () => {
let approvalAmount = exact === 'in' ? ethers.utils.hexlify(parseUnits(amountIn.toString(), tokens[tokenIn].decimals)) : amountInMax.raw.toString()
console.log(approvalAmount)
let approval = updateRouterAllowance(approvalAmount)
if(approval) {
notification.open({
message: 'Token transfer approved',
description:
`You can now swap up to ${amountIn} ${tokenIn}`,
});
}
}
const removeRouterAllowance = async () => {
let approvalAmount = ethers.utils.hexlify(0)
console.log(approvalAmount)
let removal = updateRouterAllowance(approvalAmount)
if(removal) {
notification.open({
message: 'Token approval removed',
description:
`The router is no longer approved for ${tokenIn}`,
});
}
}
const executeSwap = async () => {
setSwapping(true)
try {
let args
let metadata = {}
let call
let deadline = Math.floor(Date.now() / 1000) + timeLimit
let path = trades[0].route.path.map(function(item) {
return item['address'];
})
console.log(path)
let accountList = await selectedProvider.listAccounts()
let address = accountList[0]
if (exact === 'in') {
let _amountIn = ethers.utils.hexlify(parseUnits(amountIn.toString(), tokens[tokenIn].decimals))
let _amountOutMin = ethers.utils.hexlify(ethers.BigNumber.from(amountOutMin.raw.toString()))
if (tokenIn === 'ETH') {
call = 'swapExactETHForTokens'
args = [_amountOutMin, path, address, deadline]
metadata['value'] = _amountIn
} else {
call = tokenOut === 'ETH' ? 'swapExactTokensForETH' : 'swapExactTokensForTokens'
args = [_amountIn, _amountOutMin, path, address, deadline]
}
} else if (exact === 'out') {
let _amountOut = ethers.utils.hexlify(parseUnits(amountOut.toString(), tokens[tokenOut].decimals))
let _amountInMax = ethers.utils.hexlify(ethers.BigNumber.from(amountInMax.raw.toString()))
if (tokenIn === 'ETH') {
call = 'swapETHForExactTokens'
args = [_amountOut, path, address, deadline]
metadata['value'] = _amountInMax
} else {
call = tokenOut === 'ETH' ? 'swapTokensForExactETH' : 'swapTokensForExactTokens'
args = [_amountOut, _amountInMax, path, address, deadline]
}
}
console.log(call, args, metadata)
let result = await makeCall(call, routerContract, args, metadata)
console.log(result)
notification.open({
message: 'Swap complete ?',
description:
<><Text>{`Swapped ${tokenIn} for ${tokenOut}, transaction: `}</Text><Text copyable>{result.hash}</Text></>,
});
setSwapping(false)
} catch (e) {
console.log(e)
setSwapping(false)
notification.open({
message: 'Swap unsuccessful',
description:
`Error: ${e.message}`,
});
}
}
const showSwapModal = () => {
setSwapModalVisible(true);
};
const handleSwapModalOk = () => {
setSwapModalVisible(false);
executeSwap()
};
const handleSwapModalCancel = () => {
setSwapModalVisible(false);
};
let insufficientBalance = balanceIn ? parseFloat(formatUnits(balanceIn,tokens[tokenIn].decimals)) < amountIn : null
let inputIsToken = tokenIn !== 'ETH'
let insufficientAllowance = !inputIsToken ? false : routerAllowance ? parseFloat(formatUnits(routerAllowance,tokens[tokenIn].decimals)) < amountIn : null
let formattedBalanceIn = balanceIn?parseFloat(formatUnits(balanceIn,tokens[tokenIn].decimals)).toPrecision(6):null
let formattedBalanceOut = balanceOut?parseFloat(formatUnits(balanceOut,tokens[tokenOut].decimals)).toPrecision(6):null
let metaIn = tokens && tokenList && tokenIn ? tokenList.filter(function (t) {
return t.address === tokens[tokenIn].address
})[0] : null
let metaOut = tokens && tokenList && tokenOut ? tokenList.filter(function (t) {
return t.address === tokens[tokenOut].address
})[0] : null
const cleanIpfsURI = (uri) => {
try {
return (uri).replace('ipfs://','https://ipfs.io/ipfs/')
} catch(e) {
console.log(e, uri)
return uri
}
}
let logoIn = metaIn?cleanIpfsURI(metaIn.logoURI):null
let logoOut = metaOut?cleanIpfsURI(metaOut.logoURI):null
let rawPrice = trades&&trades[0]?trades[0].executionPrice:null
let price = rawPrice?rawPrice.toSignificant(7):null
let priceDescription = rawPrice ? (invertPrice ? `${(rawPrice.invert()).toSignificant(7)} ${tokenIn} per ${tokenOut}` : `${price} ${tokenOut} per ${tokenIn}`) : null
let priceWidget = (
<Space>
<Text type="secondary">{priceDescription}</Text>
<Button type="text" onClick={() => {setInvertPrice(!invertPrice)}}><RetweetOutlined /></Button>
</Space>
)
let swapModal = (
<Modal title="Confirm swap" visible={swapModalVisible} onOk={handleSwapModalOk} onCancel={handleSwapModalCancel}>
<Row><Space><img src={logoIn} alt={tokenIn} width='30'/>{amountIn}{tokenIn}</Space></Row>
<Row justify='center' align='middle' style={{width:30}}><span>↓</span></Row>
<Row><Space><img src={logoOut} alt={tokenOut} width='30'/>{amountOut}{tokenOut}</Space></Row>
<Divider/>
<Row>{priceWidget}</Row>
<Row>{trades&&((amountOutMin && exact==='in') || (amountInMax && exact==='out'))?(exact==='in'?`Output is estimated. You will receive at least ${amountOutMin.toSignificant(6)} ${tokenOut} or the transaction will revert.`:`Input is estimated. You will sell at most ${amountInMax.toSignificant(6)} ${tokenIn} or the transaction will revert.`):null}</Row>
</Modal>
)
return (
<Card title={<Space><img src="https://ipfs.io/ipfs/QmXttGpZrECX5qCyXbBQiqgQNytVGeZW5Anewvh2jc4psg" width='40' alt='uniswapLogo'/><Typography>Uniswapper</Typography></Space>} extra={<Button type="text" onClick={() => {setSettingsVisible(true)}}><SettingOutlined /></Button>}>
<Space direction="vertical">
<Row justify="center" align="middle">
<Card size="small" type="inner" title={`From${exact==='out' && tokenIn && tokenOut?' (estimate)':''}`} extra={<><img src={logoIn} alt={tokenIn} width='30'/><Button type="link" onClick={() => {
setAmountOut()
setAmountIn(formatUnits(balanceIn,tokens[tokenIn].decimals))
setAmountOutMin()
setAmountInMax()
setExact('in')
}}>{formattedBalanceIn}</Button></>} style={{ width: 400, textAlign: 'left' }}>
<InputNumber style={{width: '160px'}} min={0} size={'large'} value={amountIn} onChange={(e) => {
setAmountOut()
setTrades()
setAmountIn(e)
setExact('in')
}}/>
<Select showSearch value={tokenIn} style={{width: '120px'}} size={'large'} bordered={false} defaultValue={defaultToken} onChange={(value) => {
console.log(value)
if(value===tokenOut) {
console.log('switch!', tokenIn)
setTokenOut(tokenIn)
setAmountOut(amountIn)
setBalanceOut(balanceIn)
}
setTokenIn(value)
setTrades()
setAmountIn()
setExact('out')
setBalanceIn()
}} filterOption={(input, option) =>
option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
} optionFilterProp="children">
{tokenList.map(token => (
<Option key={token.symbol} value={token.symbol}>{token.symbol}</Option>
))}
</Select>
</Card>
</Row>
<Row justify="center" align="middle">
<Tooltip title={route.join("->")}><span>↓</span></Tooltip>
</Row>
<Row justify="center" align="middle">
<Card size="small" type="inner" title={`To${exact==='in' && tokenIn && tokenOut?' (estimate)':''}`} extra={<><img src={logoOut} width='30' alt={tokenOut}/><Button type="text">{formattedBalanceOut}</Button></>} style={{ width: 400, textAlign: 'left' }}>
<InputNumber style={{width: '160px'}} size={'large'} min={0} value={amountOut} onChange={(e) => {
setAmountOut(e)
setAmountIn()
setTrades()
setExact('out')
}}/>
<Select showSearch value={tokenOut} style={{width: '120px'}} size={'large'} bordered={false} onChange={(value) => {
console.log(value, tokenIn, tokenOut)
if(value===tokenIn) {
console.log('switch!', tokenOut)
setTokenIn(tokenOut)
setAmountIn(amountOut)
setBalanceIn(balanceOut)
}
setTokenOut(value)
setExact('in')
setAmountOut()
setTrades()
setBalanceOut()
}} filterOption={(input, option) =>
option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
} optionFilterProp="children">
{tokenList.map(token => (
<Option key={token.symbol} value={token.symbol}>{token.symbol}</Option>
))}
</Select>
</Card>
</Row>
<Row justify="center" align="middle">
{priceDescription?priceWidget:null}
</Row>
<Row justify="center" align="middle">
<Space>
{inputIsToken?<Button size="large" loading={approving} disabled={!insufficientAllowance} onClick={approveRouter}>{(!insufficientAllowance&&amountIn&&amountOut)?'Approved':'Approve'}</Button>:null}
<Button size="large" loading={swapping} disabled={insufficientAllowance || insufficientBalance || !amountIn || !amountOut} onClick={showSwapModal}>{insufficientBalance?'Insufficient balance':'Swap!'}</Button>
{swapModal}
</Space>
</Row>
</Space>
<Drawer visible={settingsVisible} onClose={() => { setSettingsVisible(false) }} width={500}>
<Descriptions title="Details" column={1} style={{textAlign: 'left'}}>
<Descriptions.Item label="blockNumber">{blockNumber}</Descriptions.Item>
<Descriptions.Item label="routerAllowance"><Space>{routerAllowance?formatUnits(routerAllowance,tokens[tokenIn].decimals):null}{routerAllowance>0?<Button onClick={removeRouterAllowance}>Remove Allowance</Button>:null}</Space></Descriptions.Item>
<Descriptions.Item label="route">{route.join("->")}</Descriptions.Item>
<Descriptions.Item label="exact">{exact}</Descriptions.Item>
<Descriptions.Item label="bestPrice">{trades ? (trades.length > 0 ? trades[0].executionPrice.toSignificant(6) : null) : null}</Descriptions.Item>
<Descriptions.Item label="nextMidPrice">{trades ? (trades.length > 0 ? trades[0].nextMidPrice.toSignificant(6) : null) : null}</Descriptions.Item>
<Descriptions.Item label="priceImpact">{trades ? (trades.length > 0 ? trades[0].priceImpact.toSignificant(6) : null) : null}</Descriptions.Item>
<Descriptions.Item label="slippageTolerance">{<InputNumber
defaultValue={defaultSlippage}
min={0}
max={100}
precision={2}
formatter={value => `${value}%`}
parser={value => value.replace('%', '')}
onChange={(value) => {
console.log(value)
let slippagePercent = new Percent(Math.round(value*100).toString(), "10000")
setSlippageTolerance(slippagePercent)
}}
/>}</Descriptions.Item>
<Descriptions.Item label="amountInMax">{amountInMax?amountInMax.toExact():null}</Descriptions.Item>
<Descriptions.Item label="amountOutMin">{amountOutMin?amountOutMin.toExact():null}</Descriptions.Item>
<Descriptions.Item label="timeLimitInSeconds">{<InputNumber
min={0}
max={3600}
defaultValue={defaultTimeLimit}
onChange={(value) => {
console.log(value)
setTimeLimit(value)
}}
/>}</Descriptions.Item>
</Descriptions>
</Drawer>
</Card>
)
}
Example #26
Source File: AddProtectionModal.js From bonded-stablecoin-ui with MIT License | 4 votes |
AddProtectionModal = ({
visible,
setVisible,
activeWallet,
deposit = {},
}) => {
const { params, deposit_aa, reserve_asset_symbol } = useSelector((state) => state.active);
const [amount, setAmount] = useState({
value: undefined,
valid: undefined,
});
const amountInputRef = useRef(null);
const addBtnRef = useRef(null);
const { t } = useTranslation();
const { id, amount: currentAmount, protection } = deposit;
const { reserve_asset, reserve_asset_decimals, decimals2 } = params;
const handleChangeAmount = (ev) => {
const value = ev.target.value;
const reg = /^[0-9.]+$/;
if (value === "" || value === "0" || Number(value) === 0) {
setAmount({ value, valid: undefined });
} else {
if (
(~(value + "").indexOf(".") ? (value + "").split(".")[1].length : 0) <=
reserve_asset_decimals
) {
if (reg.test(String(value))) {
setAmount({ value, valid: true });
} else {
setAmount({ value, valid: false });
}
}
}
};
useEffect(() => {
if (amountInputRef.current) {
setAmount({ value: undefined, valid: false });
amountInputRef.current.focus();
}
}, [visible]);
const totalProtectionRatio = (((protection || 0) / 10 ** reserve_asset_decimals + (amount.valid ? Number(amount.value) : 0))) / (currentAmount / 10 ** decimals2);
return (
<Modal
visible={visible}
title={t("modals.add_protection.title", "Add protection to deposit")}
onCancel={setVisible}
style={{ zIndex: -1 }}
footer={
<Space>
<QRButton
type="primary"
disabled={!amount.valid}
ref={addBtnRef}
onClick={() =>
setTimeout(() => {
setVisible();
}, 100)
}
href={generateLink(
amount.value * 10 ** reserve_asset_decimals,
{ add_protection: 1, id },
activeWallet,
deposit_aa,
reserve_asset,
true
)}
>
{t("modals.add_protection.btn", "Add protection")}
</QRButton>
<Button type="default" onClick={setVisible}>
{t("modals.common.close", "Close")}
</Button>
</Space>
}
>
<Form size="large">
<Form.Item>
<Input
placeholder={t("modals.common.amount", "Amount")}
onChange={handleChangeAmount}
value={amount.value}
ref={amountInputRef}
suffix={
reserve_asset in config.reserves
? config.reserves[reserve_asset].name
: reserve_asset_symbol || "reserve token"
}
onKeyPress={(ev) => {
if (ev.key === "Enter") {
if (amount.valid) {
addBtnRef.current.click();
}
}
}}
autoFocus={true}
/>
</Form.Item>
</Form>
<div>
<b>{t("modals.add_protection.ratio", "Protection ratio")}:</b> {+Number(totalProtectionRatio).toPrecision(3)}
</div>
</Modal>
);
}
Example #27
Source File: Account.jsx From quadratic-diplomacy with MIT License | 4 votes |
/*
~ What it does? ~
Displays an Address, Balance, and Wallet as one Account component,
also allows users to log in to existing accounts and log out
~ How can I use? ~
<Account
address={address}
localProvider={localProvider}
userProvider={userProvider}
mainnetProvider={mainnetProvider}
price={price}
web3Modal={web3Modal}
loadWeb3Modal={loadWeb3Modal}
logoutOfWeb3Modal={logoutOfWeb3Modal}
blockExplorer={blockExplorer}
/>
~ Features ~
- Provide address={address} and get balance corresponding to the given address
- Provide localProvider={localProvider} to access balance on local network
- Provide userProvider={userProvider} to display a wallet
- Provide mainnetProvider={mainnetProvider} and your address will be replaced by ENS name
(ex. "0xa870" => "user.eth")
- Provide price={price} of ether and get your balance converted to dollars
- Provide web3Modal={web3Modal}, loadWeb3Modal={loadWeb3Modal}, logoutOfWeb3Modal={logoutOfWeb3Modal}
to be able to log in/log out to/from existing accounts
- Provide blockExplorer={blockExplorer}, click on address and get the link
(ex. by default "https://etherscan.io/" or for xdai "https://blockscout.com/poa/xdai/")
*/
export default function Account({
address,
userSigner,
localProvider,
mainnetProvider,
price,
minimized,
web3Modal,
loadWeb3Modal,
logoutOfWeb3Modal,
blockExplorer,
isAdmin,
isVoter,
}) {
const modalButtons = [];
if (web3Modal) {
if (web3Modal.cachedProvider) {
modalButtons.push(
<Button
key="logoutbutton"
style={{ verticalAlign: "top", marginLeft: 8, marginTop: 4 }}
shape="round"
size="large"
onClick={logoutOfWeb3Modal}
>
logout
</Button>,
);
} else {
modalButtons.push(
<Button
key="loginbutton"
style={{ verticalAlign: "top", marginLeft: 8, marginTop: 4 }}
shape="round"
size="large"
/* type={minimized ? "default" : "primary"} too many people just defaulting to MM and having a bad time */
onClick={loadWeb3Modal}
>
connect
</Button>,
);
}
}
const { currentTheme } = useThemeSwitcher();
const display = minimized ? (
""
) : (
<Space>
{isAdmin && <Badge count={"admin"} />}
{isVoter && <Badge count={"voter"} style={{ backgroundColor: "#52c41a" }} />}
{address ? (
<Address address={address} ensProvider={mainnetProvider} blockExplorer={blockExplorer} />
) : (
"Connecting..."
)}
<Balance address={address} provider={localProvider} price={price} />
<Wallet
address={address}
provider={localProvider}
signer={userSigner}
ensProvider={mainnetProvider}
price={price}
color={currentTheme === "light" ? "#1890ff" : "#2caad9"}
/>
</Space>
);
return (
<div>
{display}
{modalButtons}
</div>
);
}
Example #28
Source File: SubmissionList.js From codeclannigeria-frontend with MIT License | 4 votes |
function SubmissionList({
mentorTasks,
loading,
getUserMenteesProfileApi,
getAllMentorSubmissions,
gradeTaskAction,
}) {
const [visible, setVisible] = useState();
const [currentRecord, setCurrentRecord] = useState();
const dispatch = useDispatch();
console.log(mentorTasks);
const onCreate = (values, initialData) => {
values.id = initialData.id;
gradeTaskAction(values);
};
const [form] = Form.useForm();
const onCancel = () => {
setCurrentRecord(null);
};
useEffect(() => {
if (currentRecord) {
form.setFieldsValue({ ...currentRecord });
setVisible(true);
// setCurrentRecord(null);
} else {
setVisible(false);
}
}, [currentRecord, form]);
const handleModalVisibility = record => {
dispatch({ type: 'TASKS_RESET' });
setCurrentRecord(record);
};
useEffect(() => {
getAllMentorSubmissions();
}, [getAllMentorSubmissions]);
const columns = [
// {
// title: 'Id',
// dataIndex: 'id',
// visible: false,
// },
{
title: 'Name',
dataIndex: 'mentee',
sorter: (a, b) => a.mentee.firstName > b.mentee.firstName,
render: (_, { mentee }) => mentee.firstName,
},
{
title: 'Surname',
dataIndex: 'mentee',
sorter: (a, b) => a.mentee.lastName.length > b.mentee.lastName,
render: (_, { mentee }) => mentee.lastName,
},
{
title: 'Task',
dataIndex: 'task',
// sorter: (a, b) => a.task.title > b.task.title,
render: (_, { task }) => task ? task.title: null,
},
{
title: 'Updated',
render: (_, { updatedAt }) => updatedAt,
sorter: (a, b) => a.updatedAt > b.updatedAt,
},
{
title: 'Grade %',
dataIndex: 'gradePercentage',
filters: [
{
text: 'Not Graded',
value: 'notGraded',
},
{
text: 'Graded',
value: 'graded',
},
],
// specify the condition of filtering result
// here is that finding the name started with `value`
onFilter: (value, record) =>
value === 'graded'
? record.gradePercentage > 0
: record.gradePercentage <= 0,
},
{
title: 'Grade',
key: 'action',
render: (text, record) => (
<Space size="middle">
<Button
type="primary"
//ref
onClick={() => handleModalVisibility(record)}
>
Grade
</Button>
</Space>
),
},
];
return (
<div>
<h2 className="ml-4">Mentees Task Submissions</h2>
<Table
className="mentee-table ml-4"
columns={columns}
dataSource={mentorTasks}
size="small"
rowKey="id"
pagination={{ pageSize: 10 }}
// scroll={{ y: 240 }}
/>
<TaskForm
initialData={currentRecord}
visible={visible}
onCreate={onCreate}
onCancel={onCancel}
loadiing={loading}
form={form}
/>
</div>
);
}
Example #29
Source File: EditInfo.js From Peppermint with GNU General Public License v3.0 | 4 votes |
EditInfo = (props) => {
// eslint-disable-next-line
const [users, setUsers] = useState(props.user);
const [name, setName] = useState(props.user.name);
const [email, setEmail] = useState(props.user.email);
const [role, setRole] = useState(props.user.role);
const [visible, setVisible] = useState(false);
const postData = async () => {
await fetch(`/api/v1/auth/edit`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + localStorage.getItem("jwt"),
},
body: JSON.stringify({
id: users._id,
name,
email,
role,
}),
}).then((res) => res.json);
};
const onCreate = async () => {
setVisible(false);
email.toString(email);
await postData();
};
const onCancel = () => {
setVisible(false);
};
return (
<div>
<p
type="primary"
onClick={() => {
setVisible(true);
}}
>
Edit User info & Role
</p>
<Modal
visible={visible}
title="Edit a users info"
okText="Update"
cancelText="Cancel"
onCancel={onCancel}
onOk={onCreate}
>
<Row>
<h5>
Edit Name :{" "}
<Input
defaultValue={users.name}
onChange={(e) => setName(e.target.value)}
style={{ width: 300 }}
/>
</h5>
</Row>
<Row>
<h5>
Edit Email :{" "}
<Input
defaultValue={users.email}
onChange={(e) => setEmail(e.target.value)}
style={{ width: 300, marginLeft: 5 }}
/>
</h5>
</Row>
<Row>
<h5>Edit Role : </h5>
<Radio.Group
buttonStyle="solid"
defaultValue={users.role}
onChange={(e) => setRole(e.target.value)}
style={{ marginLeft: 20 }}
>
<Space>
<Radio.Button value="user">User</Radio.Button>
<Radio.Button value="admin">Admin</Radio.Button>
</Space>
</Radio.Group>
</Row>
</Modal>
</div>
);
}