Add pools landing page
This commit is contained in:
parent
9af5bbb66c
commit
28ae0d3336
|
@ -7,6 +7,19 @@ const Wrapper = styled.div`
|
|||
background-color: #1a2029;
|
||||
`;
|
||||
|
||||
export default function FloatingElement({ style = undefined, children }) {
|
||||
return <Wrapper style={{ ...style }}>{children}</Wrapper>;
|
||||
export default function FloatingElement({
|
||||
style = undefined,
|
||||
children,
|
||||
stretchVertical = false,
|
||||
}) {
|
||||
return (
|
||||
<Wrapper
|
||||
style={{
|
||||
height: stretchVertical ? 'calc(100% - 10px)' : undefined,
|
||||
...style,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
import styled from 'styled-components';
|
||||
import FloatingElement from '../../components/layout/FloatingElement';
|
||||
import React, { useState } from 'react';
|
||||
import { Button, Input, Typography } from 'antd';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import Link from '../../components/Link';
|
||||
|
||||
const { Title } = Typography;
|
||||
|
||||
const Wrapper = styled.div`
|
||||
max-width: 700px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-top: 24px;
|
||||
margin-bottom: 24px;
|
||||
`;
|
||||
|
||||
const Form = styled.form`
|
||||
display: flex;
|
||||
margin-top: 16px;
|
||||
margin-bottom: 48px;
|
||||
`;
|
||||
|
||||
export default function PoolListPage() {
|
||||
const [poolAddress, setPoolAddress] = useState('');
|
||||
const history = useHistory();
|
||||
|
||||
function onSubmit(e) {
|
||||
e.preventDefault();
|
||||
history.push(`/pools/${poolAddress}`);
|
||||
}
|
||||
return (
|
||||
<Wrapper>
|
||||
<FloatingElement>
|
||||
<Title level={3}>Pools</Title>
|
||||
<Form onSubmit={onSubmit}>
|
||||
<Input
|
||||
value={poolAddress}
|
||||
onChange={(e) => setPoolAddress(e.target.value.trim())}
|
||||
placeholder="Pool address"
|
||||
/>
|
||||
<Button type="primary" htmlType="submit">
|
||||
Go
|
||||
</Button>
|
||||
</Form>
|
||||
<Link to="/pools/new">Create new pool</Link>
|
||||
</FloatingElement>
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
|
@ -27,7 +27,7 @@ export default function PoolCreateRedeemPanel({
|
|||
mintInfo,
|
||||
}: PoolCreateRedeemPanel) {
|
||||
return (
|
||||
<FloatingElement>
|
||||
<FloatingElement stretchVertical>
|
||||
<Tabs>
|
||||
<TabPane tab="Create" key="create">
|
||||
<CreateRedeemTab
|
||||
|
|
|
@ -5,11 +5,10 @@ import { Spin, Typography } from 'antd';
|
|||
import { MintInfo } from '../../../utils/tokens';
|
||||
import { useAsyncData } from '../../../utils/fetch-loop';
|
||||
import { useConnection } from '../../../utils/connection';
|
||||
import { PublicKey } from '@solana/web3.js';
|
||||
import tuple from 'immutable-tuple';
|
||||
import PoolBasketDisplay from './PoolBasketDisplay';
|
||||
|
||||
const { Text, Title, Paragraph } = Typography;
|
||||
const { Text, Paragraph } = Typography;
|
||||
|
||||
interface PoolInfoProps {
|
||||
poolInfo: PoolInfo;
|
||||
|
@ -31,11 +30,14 @@ export default function PoolInfoPanel({ poolInfo, mintInfo }: PoolInfoProps) {
|
|||
);
|
||||
|
||||
return (
|
||||
<FloatingElement>
|
||||
<Title level={4}>Pool {poolInfo.address.toBase58()}</Title>
|
||||
<FloatingElement stretchVertical>
|
||||
<Paragraph>Name: {poolInfo.state.name}</Paragraph>
|
||||
<Paragraph>
|
||||
Pool token mint address: {poolInfo.state.poolTokenMint.toBase58()}
|
||||
Address: <Text copyable>{poolInfo.address.toBase58()}</Text>
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
Pool token mint address:{' '}
|
||||
<Text copyable>{poolInfo.state.poolTokenMint.toBase58()}</Text>
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
Total supply: {mintInfo.supply.toNumber() / 10 ** mintInfo.decimals}
|
||||
|
|
|
@ -1,31 +1,24 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { Col, Row, Spin, Typography } from 'antd';
|
||||
import { Col, PageHeader, Row, Spin, Typography } from 'antd';
|
||||
import { PublicKey } from '@solana/web3.js';
|
||||
import { useAccountInfo } from '../../../utils/connection';
|
||||
import FloatingElement from '../../../components/layout/FloatingElement';
|
||||
import styled from 'styled-components';
|
||||
import { decodePoolState, PoolInfo } from '@project-serum/pool';
|
||||
import PoolInfoPanel from './PoolInfoPanel';
|
||||
import { parseTokenMintData } from '../../../utils/tokens';
|
||||
import PoolCreateRedeemPanel from './PoolCreateRedeemPanel';
|
||||
import PoolBalancesPanel from './PoolBalancesPanel';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
|
||||
const { Text, Title } = Typography;
|
||||
|
||||
const Wrapper = styled.div`
|
||||
max-width: 700px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-top: 24px;
|
||||
margin-bottom: 24px;
|
||||
`;
|
||||
const { Text } = Typography;
|
||||
|
||||
export default function PoolPage() {
|
||||
const { poolAddress } = useParams();
|
||||
const [poolAccountInfo, poolAccountLoaded] = useAccountInfo(
|
||||
isPublicKey(poolAddress) ? new PublicKey(poolAddress) : null,
|
||||
);
|
||||
const history = useHistory();
|
||||
|
||||
const poolInfo: PoolInfo | null = useMemo(() => {
|
||||
if (!poolAccountInfo) {
|
||||
|
@ -41,30 +34,51 @@ export default function PoolPage() {
|
|||
return null;
|
||||
}
|
||||
}, [poolAddress, poolAccountInfo]);
|
||||
const [poolTokenMintInfo, poolTokenMintInfoLoaded] = useAccountInfo(
|
||||
const [mintAccountInfo, mintAccountInfoLoaded] = useAccountInfo(
|
||||
poolInfo?.state.poolTokenMint,
|
||||
);
|
||||
const poolTokenMintParsed = useMemo(
|
||||
() =>
|
||||
poolTokenMintInfo ? parseTokenMintData(poolTokenMintInfo.data) : null,
|
||||
[poolTokenMintInfo],
|
||||
const mintInfo = useMemo(
|
||||
() => (mintAccountInfo ? parseTokenMintData(mintAccountInfo.data) : null),
|
||||
[mintAccountInfo],
|
||||
);
|
||||
|
||||
if (poolInfo && poolTokenMintParsed) {
|
||||
return <PoolPageInner poolInfo={poolInfo} mintInfo={poolTokenMintParsed} />;
|
||||
if (poolInfo && mintInfo) {
|
||||
return (
|
||||
<>
|
||||
<PageHeader
|
||||
title={<>Pool {poolInfo.address.toBase58()}</>}
|
||||
onBack={() => history.push('/pools')}
|
||||
subTitle={poolInfo.state.name}
|
||||
/>
|
||||
<Row>
|
||||
<Col xs={24} lg={12}>
|
||||
<PoolInfoPanel poolInfo={poolInfo} mintInfo={mintInfo} />
|
||||
</Col>
|
||||
<Col xs={24} lg={12}>
|
||||
<PoolCreateRedeemPanel poolInfo={poolInfo} mintInfo={mintInfo} />
|
||||
</Col>
|
||||
<Col xs={24}>
|
||||
<PoolBalancesPanel poolInfo={poolInfo} />
|
||||
</Col>
|
||||
</Row>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<>
|
||||
<PageHeader
|
||||
title={<>Pool {poolAddress}</>}
|
||||
onBack={() => history.push('/pools')}
|
||||
/>
|
||||
<FloatingElement>
|
||||
<Title level={4}>Pool {poolAddress}</Title>
|
||||
{!poolAccountLoaded || !poolTokenMintInfoLoaded ? (
|
||||
{!poolAccountLoaded || !mintAccountInfoLoaded ? (
|
||||
<Spin />
|
||||
) : (
|
||||
<Text>Invalid pool</Text>
|
||||
)}
|
||||
</FloatingElement>
|
||||
</Wrapper>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -76,21 +90,3 @@ function isPublicKey(address) {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function PoolPageInner({ poolInfo, mintInfo }) {
|
||||
return (
|
||||
<>
|
||||
<Row>
|
||||
<Col xs={24} lg={14} xl={12}>
|
||||
<PoolInfoPanel poolInfo={poolInfo} mintInfo={mintInfo} />
|
||||
</Col>
|
||||
<Col xs={24} lg={10} xl={12}>
|
||||
<PoolCreateRedeemPanel poolInfo={poolInfo} mintInfo={mintInfo} />
|
||||
</Col>
|
||||
<Col xs={24}>
|
||||
<PoolBalancesPanel poolInfo={poolInfo} />
|
||||
</Col>
|
||||
</Row>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import BasicLayout from './components/BasicLayout';
|
|||
import ListNewMarketPage from './pages/ListNewMarketPage';
|
||||
import NewPoolPage from './pages/pools/NewPoolPage';
|
||||
import PoolPage from './pages/pools/PoolPage';
|
||||
import PoolListPage from './pages/pools/PoolListPage';
|
||||
|
||||
export function Routes() {
|
||||
return (
|
||||
|
@ -24,6 +25,9 @@ export function Routes() {
|
|||
path="/list-new-market"
|
||||
component={ListNewMarketPage}
|
||||
/>
|
||||
<Route exact path="/pools">
|
||||
<PoolListPage />
|
||||
</Route>
|
||||
<Route exact path="/pools/new">
|
||||
<NewPoolPage />
|
||||
</Route>
|
||||
|
|
31
yarn.lock
31
yarn.lock
|
@ -1531,15 +1531,15 @@
|
|||
integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==
|
||||
|
||||
"@project-serum/pool@^0.1.1":
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@project-serum/pool/-/pool-0.1.1.tgz#c972213d28b3f3565dcd8a6ae960396430a76a8d"
|
||||
integrity sha512-ivZEvWky46Xnfud1kgF0rFHlkKA8bXZQFDjWLCyi6VIgzou8i5R5nfNZls1xThnUa6yRRAuo3Wmne0xRaEhKSg==
|
||||
version "0.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@project-serum/pool/-/pool-0.1.3.tgz#9f99e6046f4565e38896934b24d447eae1527a62"
|
||||
integrity sha512-wAO65EccmCCMmgolvVXIc3JbSapWxLWALuVuhbHiiYQjTCMolAYvGSzeJwur7Z7MjTuRJMc8z9/6rYNOQSAwaw==
|
||||
dependencies:
|
||||
"@project-serum/serum" "^0.13.8"
|
||||
bn.js "^5.1.2"
|
||||
buffer-layout "^1.2.0"
|
||||
|
||||
"@project-serum/serum@0.13.10":
|
||||
"@project-serum/serum@^0.13.10", "@project-serum/serum@^0.13.8":
|
||||
version "0.13.10"
|
||||
resolved "https://registry.yarnpkg.com/@project-serum/serum/-/serum-0.13.10.tgz#0c4fdcad34e5dcb11561b8dc650903d2420f91c4"
|
||||
integrity sha512-60Vl8pMiKSjdjRky4O9aajUMr0BIdYzHZyAX16Lr+gu03x1iMgL7bih23ywuNONo3vBhA1PjHpwA9J/fbrE2vQ==
|
||||
|
@ -1584,29 +1584,6 @@
|
|||
tweetnacl "^1.0.0"
|
||||
ws "^7.0.0"
|
||||
|
||||
"@solana/web3.js@0.86.1":
|
||||
version "0.86.1"
|
||||
resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-0.86.1.tgz#034a2cef742569f74dfc9960dfbcabc92e674b08"
|
||||
integrity sha512-9mjWs17ym7PIm7bHA37wnnYyD7rIVHwkx1RI6BzGhMO5h8E+HlZM8ISLgOx+NItg8XRCfFhlrVgJTzK4om1s0g==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.3.1"
|
||||
bn.js "^5.0.0"
|
||||
bs58 "^4.0.1"
|
||||
buffer "^5.4.3"
|
||||
buffer-layout "^1.2.0"
|
||||
crypto-hash "^1.2.2"
|
||||
esdoc-inject-style-plugin "^1.0.0"
|
||||
jayson "^3.0.1"
|
||||
keccak "^3.0.1"
|
||||
mz "^2.7.0"
|
||||
node-fetch "^2.2.0"
|
||||
npm-run-all "^4.1.5"
|
||||
rpc-websockets "^7.4.2"
|
||||
secp256k1 "^4.0.2"
|
||||
superstruct "^0.8.3"
|
||||
tweetnacl "^1.0.0"
|
||||
ws "^7.0.0"
|
||||
|
||||
"@svgr/babel-plugin-add-jsx-attribute@^4.2.0":
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-4.2.0.tgz#dadcb6218503532d6884b210e7f3c502caaa44b1"
|
||||
|
|
Loading…
Reference in New Issue