Add a bunch of common components from lending that have css to common

This commit is contained in:
Dummy Tester 123 2021-02-14 18:49:31 -06:00
parent 511c9932fb
commit c46969eed0
15 changed files with 335 additions and 1 deletions

View File

@ -0,0 +1,31 @@
import React from 'react';
import { Button } from 'antd';
import { LABELS } from '../../constants';
import { Link } from 'react-router-dom';
import './style.css';
export const ActionConfirmation = (props: {
className?: string;
onClose: () => void;
}) => {
return (
<div
style={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-around',
alignItems: 'center',
}}
>
<h2>Congratulations!</h2>
<div>Your action has been successfully executed</div>
<div className="success-icon" />
<Link to="/dashboard">
<Button type="primary">{LABELS.DASHBOARD_ACTION}</Button>
</Link>
<Button type="text" onClick={props.onClose}>
{LABELS.GO_BACK_ACTION}
</Button>
</div>
);
};

View File

@ -0,0 +1,5 @@
.success-icon {
background-image: url('data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9JzMwMHB4JyB3aWR0aD0nMzAwcHgnICBmaWxsPSIjNzBjMDQxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGRhdGEtbmFtZT0iTGF5ZXIgMSIgdmlld0JveD0iMCAwIDY0IDY0IiB4PSIwcHgiIHk9IjBweCI+PHRpdGxlPmJ1c2luZXNzIGZpbmFuY2UgdXAgcmlzZSBhcnJvdyBkZW1hbmQ8L3RpdGxlPjxwYXRoIGQ9Ik01LDE0YTEsMSwwLDEsMC0xLTFINEExLDEsMCwwLDAsNSwxNFoiPjwvcGF0aD48cGF0aCBkPSJNNyw1Mkg1NWExLDEsMCwwLDAsMC0ySDUwVjI3YTEsMSwwLDAsMC0yLDBWNTBINDRWMzRhMSwxLDAsMCwwLTIsMFY1MEgzOFYzOWExLDEsMCwwLDAtMiwwVjUwSDMyVjQzYTEsMSwwLDAsMC0yLDB2N0gyNlY0NmExLDEsMCwwLDAtMiwwdjRIMjBWNDdhMSwxLDAsMCwwLTIsMHYzSDE0VjQ4YTEsMSwwLDAsMC0yLDB2Mkg3YTEsMSwwLDAsMS0xLTFWMTdhMSwxLDAsMCwwLTIsMFY0OUEzLDMsMCwwLDAsNyw1MloiPjwvcGF0aD48cGF0aCBkPSJNNTksNTBhMSwxLDAsMCwwLTEsMWgwYTEsMSwwLDEsMCwxLTFaIj48L3BhdGg+PHBhdGggZD0iTTExLDQ0aC4wN2E0OS4wNyw0OS4wNywwLDAsMCwyNS41Mi05LjE5QTQ4LjkxLDQ4LjkxLDAsMCwwLDQ5LjcsMjAuNTlMNTIuMzgsMjIsNTIsMTRsLTYuNzEsNC4zMSwyLjYzLDEuMzZBNDYuODEsNDYuODEsMCwwLDEsMzUuNDEsMzMuMTksNDYuOTQsNDYuOTQsMCwwLDEsMTAuOTMsNDIsMSwxLDAsMCwwLDExLDQ0WiI+PC9wYXRoPjwvc3ZnPg==');
width: 280px;
height: 280px;
}

View File

@ -0,0 +1,43 @@
import React from 'react';
import { Button, Popover } from 'antd';
import { CurrentUserBadge } from '../CurrentUserBadge';
import { SettingOutlined } from '@ant-design/icons';
import { Settings } from '../Settings';
import { LABELS } from '../../constants/labels';
import { ConnectButton } from '..';
import { useWallet } from '../../contexts/wallet';
import './style.css';
export const AppBar = (props: { left?: JSX.Element; right?: JSX.Element }) => {
const { connected, wallet } = useWallet();
const TopBar = (
<div className="App-Bar-right">
{connected ? (
<CurrentUserBadge />
) : (
<ConnectButton
type="text"
size="large"
allowWalletChange={true}
style={{ color: '#2abdd2' }}
/>
)}
<Popover
placement="topRight"
title={LABELS.SETTINGS_TOOLTIP}
content={<Settings />}
trigger="click"
>
<Button
shape="circle"
size="large"
type="text"
icon={<SettingOutlined />}
/>
</Popover>
{props.right}
</div>
);
return TopBar;
};

View File

@ -0,0 +1,58 @@
.App-Bar {
display: grid;
grid-template-columns: 1fr 120px;
-webkit-box-pack: justify;
justify-content: space-between;
-webkit-box-align: center;
align-items: center;
flex-direction: row;
width: 100%;
top: 0px;
position: relative;
padding: 1rem;
z-index: 2;
.ant-menu-horizontal {
border-bottom-color: transparent;
background-color: transparent;
line-height: inherit;
font-size: 16px;
margin: 0 10px;
.ant-menu-item {
margin: 0 10px;
color: lightgrey;
height: 35px;
line-height: 35px;
border-width: 0px !important;
}
.ant-menu-item:hover {
color: white;
border-width: 0px !important;
}
.ant-menu-item-selected {
font-weight: bold;
}
}
}
.App-Bar-left {
box-sizing: border-box;
margin: 0px;
min-width: 0px;
display: flex;
padding: 0px;
-webkit-box-align: center;
align-items: center;
width: fit-content;
}
.App-Bar-right {
display: flex;
flex-direction: row;
-webkit-box-align: center;
align-items: center;
justify-self: flex-end;
}

View File

@ -0,0 +1,13 @@
import React from 'react';
import { Button } from 'antd';
import { LABELS } from '../../constants';
import { useHistory } from 'react-router-dom';
export const BackButton = () => {
const history = useHistory();
return (
<Button type="text" onClick={history.goBack}>
{LABELS.GO_BACK_ACTION}
</Button>
);
};

View File

@ -0,0 +1,33 @@
import React from 'react';
import { Identicon } from '../Identicon';
import { LAMPORTS_PER_SOL } from '@solana/web3.js';
import { useWallet } from '../../contexts/wallet';
import { useNativeAccount } from '../../contexts/accounts';
import { formatNumber, shortenAddress } from '../../utils';
export const CurrentUserBadge = (props: {}) => {
const { wallet } = useWallet();
const { account } = useNativeAccount();
if (!wallet || !wallet.publicKey) {
return null;
}
// should use SOL ◎ ?
return (
<div className="wallet-wrapper">
<span>
{formatNumber.format((account?.lamports || 0) / LAMPORTS_PER_SOL)} SOL
</span>
<div className="wallet-key">
{shortenAddress(`${wallet.publicKey}`)}
<Identicon
address={wallet.publicKey?.toBase58()}
style={{ marginLeft: '0.5rem', display: 'flex' }}
/>
</div>
</div>
);
};

View File

@ -0,0 +1,20 @@
import { Button, Popover } from "antd";
import React from "react";
import { InfoCircleOutlined } from "@ant-design/icons";
export const Info = (props: {
text: React.ReactElement;
style?: React.CSSProperties;
}) => {
return (
<Popover
trigger="hover"
content={<div style={{ width: 300 }}>{props.text}</div>}
>
<Button type="text" shape="circle">
<InfoCircleOutlined style={props.style} />
</Button>
</Popover>
);
};

View File

@ -0,0 +1,36 @@
import React, { useEffect, useRef } from 'react';
import Jazzicon from 'jazzicon';
import bs58 from 'bs58';
import './style.css';
import { PublicKey } from '@solana/web3.js';
export const Identicon = (props: {
address?: string | PublicKey;
style?: React.CSSProperties;
className?: string;
}) => {
const { style, className } = props;
const address =
typeof props.address === 'string'
? props.address
: props.address?.toBase58();
const ref = useRef<HTMLDivElement>();
useEffect(() => {
if (address && ref.current) {
ref.current.innerHTML = '';
ref.current.className = className || '';
ref.current.appendChild(
Jazzicon(
style?.width || 16,
parseInt(bs58.decode(address).toString('hex').slice(5, 15), 16),
),
);
}
}, [address, style, className]);
return (
<div className="identicon-wrapper" ref={ref as any} style={props.style} />
);
};

View File

@ -0,0 +1,8 @@
.identicon-wrapper {
display: flex;
height: 1rem;
width: 1rem;
border-radius: 1.125rem;
margin: 0.2rem 0.2rem 0.2rem 0.1rem;
/* background-color: ${({ theme }) => theme.bg4}; */
}

View File

@ -0,0 +1,33 @@
import React from 'react';
import { Button, Select } from 'antd';
import { useWallet } from '../../contexts/wallet';
import { ENDPOINTS, useConnectionConfig } from '../../contexts/connection';
export const Settings = () => {
const { connected, disconnect } = useWallet();
const { endpoint, setEndpoint } = useConnectionConfig();
return (
<>
<div style={{ display: 'grid' }}>
Network:{' '}
<Select
onSelect={setEndpoint}
value={endpoint}
style={{ marginBottom: 20 }}
>
{ENDPOINTS.map(({ name, endpoint }) => (
<Select.Option value={endpoint} key={endpoint}>
{name}
</Select.Option>
))}
</Select>
{connected && (
<Button type="primary" onClick={disconnect}>
Disconnect
</Button>
)}
</div>
</>
);
};

View File

@ -1,2 +1,8 @@
export { ExplorerLink } from './ExplorerLink/index'; export { ExplorerLink } from './ExplorerLink/index';
export { ConnectButton } from './ConnectButton/index'; export { ConnectButton } from './ConnectButton/index';
export { CurrentUserBadge } from './CurrentUserBadge/index';
export { Identicon } from './Identicon/index';
export { Info } from './Icons/info';
export { NumericInput } from './Input/numeric';
export { AppBar } from './AppBar/index';
export { Settings } from './Settings/index';

View File

@ -1 +1,2 @@
export * from './math'; export * from './math';
export * from './labels';

View File

@ -0,0 +1,15 @@
export const LABELS = {
CONNECT_LABEL: 'Connect Wallet',
AUDIT_WARNING:
'Oyster is an unaudited software project used for internal purposes at the Solana Foundation. This app is not for public use.',
FOOTER:
'This page was produced by the Solana Foundation ("SF") for internal educational and inspiration purposes only. SF does not encourage, induce or sanction the deployment, integration or use of Oyster or any similar application (including its code) in violation of applicable laws or regulations and hereby prohibits any such deployment, integration or use. Anyone using this code or a derivation thereof must comply with applicable laws and regulations when releasing related software.',
MENU_HOME: 'Home',
MENU_DASHBOARD: 'Dashboard',
CONNECT_BUTTON: 'Connect',
WALLET_TOOLTIP: 'Wallet public key',
WALLET_BALANCE: 'Wallet balance',
SETTINGS_TOOLTIP: 'Settings',
DASHBOARD_ACTION: 'Go to dashboard',
GO_BACK_ACTION: 'Go back',
};

View File

@ -1,5 +1,5 @@
export * as actions from './actions'; export * as actions from './actions';
export * from './components'; export * as components from './components';
export * as config from './config'; export * as config from './config';
export * as constants from './constants'; export * as constants from './constants';
export * as hooks from './hooks'; export * as hooks from './hooks';

View File

@ -18,6 +18,11 @@ let WORMHOLE_BRIDGE: {
wrappedMaster: string; wrappedMaster: string;
}; };
let TIMELOCK: {
programId: PublicKey;
programAccountId: PublicKey;
};
let SWAP_PROGRAM_ID: PublicKey; let SWAP_PROGRAM_ID: PublicKey;
let SWAP_PROGRAM_LEGACY_IDS: PublicKey[]; let SWAP_PROGRAM_LEGACY_IDS: PublicKey[];
let SWAP_PROGRAM_LAYOUT: any; let SWAP_PROGRAM_LAYOUT: any;
@ -34,6 +39,12 @@ export const ENABLE_FEES_INPUT = false;
export const PROGRAM_IDS = [ export const PROGRAM_IDS = [
{ {
name: 'mainnet-beta', name: 'mainnet-beta',
timelock: () => ({
programAccountId: new PublicKey(
'9gBhDCCKV7KELLFRY8sAJZXqDmvUfmNzFzpB2b4FUVVr',
),
programId: new PublicKey('9iAeqqppjn7g1Jn8o2cQCqU5aQVV3h4q9bbWdKRbeC2w'),
}),
wormhole: () => ({ wormhole: () => ({
pubkey: new PublicKey('WormT3McKhFJ2RkiGpdw9GKvNCrB2aB54gb2uV9MfQC'), pubkey: new PublicKey('WormT3McKhFJ2RkiGpdw9GKvNCrB2aB54gb2uV9MfQC'),
bridge: '0xf92cD566Ea4864356C5491c177A430C222d7e678', bridge: '0xf92cD566Ea4864356C5491c177A430C222d7e678',
@ -52,6 +63,12 @@ export const PROGRAM_IDS = [
}, },
{ {
name: 'testnet', name: 'testnet',
timelock: () => ({
programAccountId: new PublicKey(
'9gBhDCCKV7KELLFRY8sAJZXqDmvUfmNzFzpB2b4FUVVr',
),
programId: new PublicKey('9iAeqqppjn7g1Jn8o2cQCqU5aQVV3h4q9bbWdKRbeC2w'),
}),
wormhole: () => ({ wormhole: () => ({
pubkey: new PublicKey('5gQf5AUhAgWYgUCt9ouShm9H7dzzXUsLdssYwe5krKhg'), pubkey: new PublicKey('5gQf5AUhAgWYgUCt9ouShm9H7dzzXUsLdssYwe5krKhg'),
bridge: '0x251bBCD91E84098509beaeAfF0B9951859af66D3', bridge: '0x251bBCD91E84098509beaeAfF0B9951859af66D3',
@ -67,6 +84,12 @@ export const PROGRAM_IDS = [
}, },
{ {
name: 'devnet', name: 'devnet',
timelock: () => ({
programAccountId: new PublicKey(
'9gBhDCCKV7KELLFRY8sAJZXqDmvUfmNzFzpB2b4FUVVr',
),
programId: new PublicKey('9iAeqqppjn7g1Jn8o2cQCqU5aQVV3h4q9bbWdKRbeC2w'),
}),
wormhole: () => ({ wormhole: () => ({
pubkey: new PublicKey('WormT3McKhFJ2RkiGpdw9GKvNCrB2aB54gb2uV9MfQC'), pubkey: new PublicKey('WormT3McKhFJ2RkiGpdw9GKvNCrB2aB54gb2uV9MfQC'),
bridge: '0xf92cD566Ea4864356C5491c177A430C222d7e678', bridge: '0xf92cD566Ea4864356C5491c177A430C222d7e678',
@ -82,6 +105,12 @@ export const PROGRAM_IDS = [
}, },
{ {
name: 'localnet', name: 'localnet',
timelock: () => ({
programAccountId: new PublicKey(
'9gBhDCCKV7KELLFRY8sAJZXqDmvUfmNzFzpB2b4FUVVr',
),
programId: new PublicKey('9iAeqqppjn7g1Jn8o2cQCqU5aQVV3h4q9bbWdKRbeC2w'),
}),
wormhole: () => ({ wormhole: () => ({
pubkey: new PublicKey('WormT3McKhFJ2RkiGpdw9GKvNCrB2aB54gb2uV9MfQC'), pubkey: new PublicKey('WormT3McKhFJ2RkiGpdw9GKvNCrB2aB54gb2uV9MfQC'),
bridge: '0xf92cD566Ea4864356C5491c177A430C222d7e678', bridge: '0xf92cD566Ea4864356C5491c177A430C222d7e678',
@ -111,6 +140,8 @@ export const setProgramIds = (envName: string) => {
SWAP_PROGRAM_LAYOUT = swap.current.layout; SWAP_PROGRAM_LAYOUT = swap.current.layout;
SWAP_PROGRAM_LEGACY_IDS = swap.legacy; SWAP_PROGRAM_LEGACY_IDS = swap.legacy;
TIMELOCK = instance.timelock();
if (envName === 'mainnet-beta') { if (envName === 'mainnet-beta') {
LENDING_PROGRAM_ID = new PublicKey( LENDING_PROGRAM_ID = new PublicKey(
'LendZqTs7gn5CTSJU1jWKhKuVpjJGom45nnwPb2AMTi', 'LendZqTs7gn5CTSJU1jWKhKuVpjJGom45nnwPb2AMTi',
@ -125,5 +156,6 @@ export const programIds = () => {
swapLayout: SWAP_PROGRAM_LAYOUT, swapLayout: SWAP_PROGRAM_LAYOUT,
lending: LENDING_PROGRAM_ID, lending: LENDING_PROGRAM_ID,
wormhole: WORMHOLE_BRIDGE, wormhole: WORMHOLE_BRIDGE,
timelock: TIMELOCK,
}; };
}; };