Add pools landing page

This commit is contained in:
Gary Wang 2020-11-01 08:32:51 -08:00
parent 9af5bbb66c
commit 28ae0d3336
7 changed files with 117 additions and 75 deletions

View File

@ -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>
);
}

View File

@ -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>
);
}

View File

@ -27,7 +27,7 @@ export default function PoolCreateRedeemPanel({
mintInfo,
}: PoolCreateRedeemPanel) {
return (
<FloatingElement>
<FloatingElement stretchVertical>
<Tabs>
<TabPane tab="Create" key="create">
<CreateRedeemTab

View File

@ -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}

View File

@ -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>
</>
);
}

View File

@ -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>

View File

@ -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"