Add Pool page UI development
Author of this section: @Fish
in this talk, we will implement the UI of Wtfswap adding transaction pop-up window.
Add pop-up window
we refer to the following design draft:
the design draft is a design draft that adds fluidity. This is only for reference. Because it is a course, we will not fully realize the effect in the design draft, but only realize the necessary functions through the necessary code.
We will mainly use Ant Design Modal component and Form component to implement a pop-up window and a form in the pop-up window. We first create a component WtfAddPoolModal
defining its component properties. This component collects information about the trading pool entered by LP through a pop-up window form and passes the field that creates the trading pool to the page through the callback function provided in the parameter.
import { Modal } from "antd";
interface CreatePoolParams {
token0: string;
token1: string;
fee: number;
tickLower: number;
tickUpper: number;
sqrtPriceX96: BigInt;
}
interface AddPoolModalProps {
open: boolean;
onCancel: () => void;
onCreatePool: (params: CreatePoolParams) => void;
}
export default function AddPoolModal(props: AddPoolModalProps) {
const { open, onCancel, onCreatePool } = props;
const [form] = Form.useForm();
return (
<Modal
title="Add Pool"
open={open}
onCancel={onCancel}
okText="Create"
onOk={() => {
// TODO
}}
></Modal>
);
}
Then we introduce the list of trading pools implemented in the previous talk UI. AddPoolModal
:
import React from "react";
import { Flex, Table, Space, Typography, Button } from "antd";
import type { TableProps } from "antd";
import WtfLayout from "@/components/WtfLayout";
+ import AddPoolModal from "@/components/AddPoolModal";
import Link from "next/link";
import styles from "./pool.module.css";
//...
const PoolListTable: React.FC = () => {
+ const [openAddPoolModal, setOpenAddPoolModal] = React.useState(false);
const data = [
{
token0: "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984",
token1: "0xEcd0D12E21805803f70de03B72B1C162dB0898d9",
index: 0,
fee: 3000,
tickLower: -100000,
tickUpper: 100000,
tick: 1000,
sqrtPriceX96: BigInt("7922737261735934252089901697281"),
},
];
return (
<>
<Table
rowKey="token0"
title={() => (
<Flex justify="space-between">
<div>Pool List</div>
<Space>
<Link href="/wtfswap/positions">
<Button>My Positions</Button>
</Link>
<Button
type="primary"
onClick={() => {
+ setOpenAddPoolModal(true);
}}
>
Add Pool
</Button>
</Space>
</Flex>
)}
columns={columns}
dataSource={data}
/>
+ <AddPoolModal
+ open={openAddPoolModal}
+ onCancel={() => {
+ setOpenAddPoolModal(false);
+ }}
+ onCreatePool={(createPram) => {
+ console.log("get createPram", createPram);
+ setOpenAddPoolModal(false);
+ }}
+ />
</>
);
};
we pass the state in the component openAddPoolModal
to control the opening and closing of the pop-up window, in addition onCreatePool
the creation of transaction pools is handled in, and the logic of the creation will be supplemented in subsequent and chain interaction courses.
Add Form
we continue in CreatePoolModal
add relevant code to the component, mainly using Ant Design's Form
components and Input
, InputNumber
components.
The relevant new component code is as follows:
<Form layout="vertical">
<Form.Item required label="Token 0" name="token0">
<Input />
</Form.Item>
<Form.Item required label="Token 1" name="token1">
<Input />
</Form.Item>
<Form.Item required label="Fee" name="fee">
<Select>
<Select.Option value={3000}>0.3%</Select.Option>
<Select.Option value={500}>0.05%</Select.Option>
<Select.Option value={10000}>1%</Select.Option>
</Select>
</Form.Item>
<Form.Item required label="Tick Lower" name="tickLower">
<InputNumber />
</Form.Item>
<Form.Item required label="Tick Upper" name="tickUpper">
<InputNumber />
</Form.Item>
<Form.Item required label="Init Price(token1/token0)" name="price">
<InputNumber min={0.000001} max={1000000} />
</Form.Item>
</Form>
among them required
means that the form item is required, label
is the name of the form item displayed on the UI, and, name
is the value of the field. For specific usage, please refer to Ant Design's documentation these are properties defined by Ant Design.
Finally, we need to click on the pop-up window Create
called when the button onCreatePool
function, before calling, you also need to process the next price, will. price
convert sqrtPriceX96
. In addition, we will enter the user's price
limiting to a range is easy to calculate (avoiding exceeding the Number size range of JavaScript), you should be careful to handle this yourself in actual business requirements.
Price conversion we need to introduce @uniswap/sdk
this npm package, first you need to pass npm I @uniswap/sdk
install it, and then we create a new file. utils/common.ts
, create a tool method parsePriceToSqrtPriceX96
:
import { encodeSqrtRatioX96 } from "@uniswap/v3-sdk";
export const parsePriceToSqrtPriceX96 = (price: number): BigInt => {
return BigInt(encodeSqrtRatioX96(price * 1000000, 1000000).toString());
};
then in AddPoolModal
add related logic to the component
import { Modal, Form, Input, InputNumber, Select } from "antd";
+ import { parsePriceToSqrtPriceX96 } from "@/utils/common";
interface CreatePoolParams {
token0: string;
token1: string;
fee: number;
tickLower: number;
tickUpper: number;
sqrtPriceX96: BigInt;
}
interface AddPoolModalProps {
open: boolean;
onCancel: () => void;
onCreatePool: (params: CreatePoolParams) => void;
}
export default function AddPoolModal(props: AddPoolModalProps) {
const { open, onCancel, onCreatePool } = props;
+ const [form] = Form.useForm();
return (
<Modal
title="Add Pool"
open={open}
onCancel={onCancel}
okText="Create"
onOk={() => {
+ form.validateFields().then((values) => {
+ onCreatePool({
+ ...values,
+ sqrtPriceX96: parsePriceToSqrtPriceX96(values.price),
+ });
+ });
}}
>
+ <Form layout="vertical" form={form}>
- <Form layout="vertical">
<Form.Item required label="Token 0" name="token0">
<Input />
</Form.Item>
<Form.Item required label="Token 1" name="token1">
<Input />
</Form.Item>
<Form.Item required label="Fee" name="fee">
<Select>
<Select.Option value={3000}>0.3%</Select.Option>
<Select.Option value={500}>0.05%</Select.Option>
<Select.Option value={10000}>1%</Select.Option>
</Select>
</Form.Item>
<Form.Item required label="Tick Lower" name="tickLower">
<InputNumber />
</Form.Item>
<Form.Item required label="Tick Upper" name="tickUpper">
<InputNumber />
</Form.Item>
<Form.Item required label="Init Price(token1/token0)" name="price">
<InputNumber min={0.000001} max={1000000} />
</Form.Item>
</Form>
</Modal>
);
}
in this way, our UI part of creating the trading pool is completed, and the final effect is:
please refer to the complete code: AddPoolModal/index.tsx
we'll refine the code in a later lesson and add logic for calling the contract interface to create a trading pool.