update placeholder page

This commit is contained in:
saml33 2023-03-06 13:44:20 +11:00
parent 65bc666c8f
commit 2a642816ec
39 changed files with 2567 additions and 4862 deletions

View File

@ -1,62 +0,0 @@
import {
AccountInfo,
Connection,
PublicKey,
Transaction,
} from '@solana/web3.js'
import Wallet from '@project-serum/sol-wallet-adapter'
export interface ConnectionContextValues {
endpoint: string
setEndpoint: (newEndpoint: string) => void
connection: Connection
sendConnection: Connection
availableEndpoints: EndpointInfo[]
setCustomEndpoints: (newCustomEndpoints: EndpointInfo[]) => void
}
export interface EndpointInfo {
name: string
url: string
websocket: string
}
export interface WalletContextValues {
wallet: Wallet
connected: boolean
providerUrl: string
setProviderUrl: (newProviderUrl: string) => void
providerName: string
}
export interface TokenAccount {
pubkey: PublicKey
account: AccountInfo<Buffer> | null
effectiveMint: PublicKey
}
/**
* {tokenMint: preferred token account's base58 encoded public key}
*/
export interface SelectedTokenAccounts {
[tokenMint: string]: string
}
// Token infos
export interface KnownToken {
tokenSymbol: string
tokenName: string
icon?: string
mintAddress: string
}
export interface WalletAdapter {
publicKey: PublicKey
autoApprove: boolean
connected: boolean
signTransaction: (transaction: Transaction) => Promise<Transaction>
signAllTransactions: (transaction: Transaction[]) => Promise<Transaction[]>
connect: () => any
disconnect: () => any
on(event: string, fn: () => void): this
}

View File

@ -1,35 +0,0 @@
import BN from 'bn.js'
import useWalletStore from '../stores/useWalletStore'
const Balances = () => {
const { tokenAccounts, mints } = useWalletStore((state) => state)
function fixedPointToNumber(value: BN, decimals: number) {
const divisor = new BN(10).pow(new BN(decimals))
const quotient = value.div(divisor)
const remainder = value.mod(divisor)
return quotient.toNumber() + remainder.toNumber() / divisor.toNumber()
}
function calculateBalance(a) {
const mint = mints[a.account.mint.toBase58()]
return mint ? fixedPointToNumber(a.account.amount, mint.decimals) : 0
}
const displayedBalances = tokenAccounts
.map((a) => ({ id: a.publicKey.toBase58(), balance: calculateBalance(a) }))
.sort((a, b) => (a.id > b.id ? 1 : -1))
return (
<ul>
{displayedBalances.map((b) => (
<li key={b.id}>
{b.id}: {b.balance}
</li>
))}
</ul>
)
}
export default Balances

View File

@ -1,45 +0,0 @@
import styled from '@emotion/styled'
import useWalletStore from '../stores/useWalletStore'
import { WALLET_PROVIDERS, DEFAULT_PROVIDER } from '../hooks/useWallet'
import useLocalStorageState from '../hooks/useLocalStorageState'
import WalletSelect from './WalletSelect'
import WalletIcon from './WalletIcon'
const StyledWalletTypeLabel = styled.div`
font-size: 0.6rem;
`
const ConnectWalletButton = () => {
const wallet = useWalletStore((s) => s.current)
const [savedProviderUrl] = useLocalStorageState(
'walletProvider',
DEFAULT_PROVIDER.url
)
return (
<div className="flex justify-between border border-th-primary rounded-md h-11 w-48">
<button
onClick={() => wallet.connect()}
disabled={!wallet}
className="text-th-primary hover:text-th-fgd-1 focus:outline-none disabled:text-th-fgd-4 disabled:cursor-wait"
>
<div className="flex flex-row items-center px-2 justify-center h-full rounded-l default-transition hover:bg-th-primary hover:text-th-fgd-1">
<WalletIcon className="w-5 h-5 mr-3 fill-current" />
<div>
<span className="whitespace-nowrap">Connect Wallet</span>
<StyledWalletTypeLabel className="font-normal text-th-fgd-1 text-left leading-3">
{WALLET_PROVIDERS.filter((p) => p.url === savedProviderUrl).map(
({ name }) => name
)}
</StyledWalletTypeLabel>
</div>
</div>
</button>
<div className="relative h-full">
<WalletSelect isPrimary />
</div>
</div>
)
}
export default ConnectWalletButton

View File

@ -1,71 +0,0 @@
import { Fragment, FunctionComponent, ReactNode } from 'react'
import { Listbox, Transition } from '@headlessui/react'
type DropMenuProps = {
button: ReactNode
buttonClassName?: string
disabled?: boolean
onChange: (...args: any[]) => any
options: Array<any>
value?: any
}
const DropMenu: FunctionComponent<DropMenuProps> = ({
button,
buttonClassName,
disabled,
value,
onChange,
options,
}) => {
return (
<div className={`relative`}>
<Listbox value={value} onChange={onChange}>
{({ open }) => (
<>
<Listbox.Button
className={`${buttonClassName} default-transition`}
disabled={disabled}
>
{button}
</Listbox.Button>
<Transition
show={open}
as={Fragment}
enter="transition ease-out duration-200"
enterFrom="opacity-0 translate-y-1"
enterTo="opacity-100 translate-y-0"
leave="transition ease-in duration-150"
leaveFrom="opacity-100 translate-y-0"
leaveTo="opacity-0 translate-y-1"
>
<Listbox.Options
className={`absolute z-50 mt-4 py-2 px-2 right-0 w-auto bg-th-bkg-2 shadow-lg rounded-md`}
>
{options.map((option) => (
<Listbox.Option key={option.name} value={option.name}>
{({ selected }) => (
<div
className={`p-2 hover:bg-th-bkg-3 hover:cursor-pointer hover:rounded-md hover:shadow-md tracking-wider ${
selected && `text-th-primary`
} ${option.icon && `flex items-center`}`}
>
{option.icon ? (
<div className="mr-2">{option.icon}</div>
) : null}
{option.name}
</div>
)}
</Listbox.Option>
))}
</Listbox.Options>
</Transition>
</>
)}
</Listbox>
</div>
)
}
export default DropMenu

View File

@ -1,337 +0,0 @@
import Button from './Button'
//import ButtonWhite from './ButtonWhite'
import {
ReceiptTaxIcon,
LightningBoltIcon,
CurrencyDollarIcon,
LibraryIcon,
} from '@heroicons/react/outline'
import LinkLeft from './LinkLeft'
const features = [
{
name: 'Maximum capital efficiency.',
description:
"Every market is cross-collateralized. Mango's risk engine let's you utilize all your assets and derivative contracts as collateral.",
icon: CurrencyDollarIcon,
},
{
name: 'Sub-second latency.',
description:
'Instant order execution at the price of less than a cent. Low latency allows market makers to post tight spreads on the books. Oh, and liquidations are instant as well, so watch your exposure.',
icon: LightningBoltIcon,
},
{
name: 'The lowest fees.',
description:
'Trade with the lowest fee possible. SRM deposits are pooled for a collective discount. Mango is the first protocol to charge zero fees on margin borrowing & lending.',
icon: ReceiptTaxIcon,
},
{
name: 'Spot & perpetual markets.',
description:
'Trade spot markets and derivitive assets all in one unified experience. Spot margin with up to 5x leverage, perpetuals futures with up to 20x.',
icon: LibraryIcon,
},
]
const FeatureSection = () => {
return (
<>
<div className="bg-th-bkg-3 transform -skew-y-3 pt-16 pb-32 lg:pb-48 mb-48 lg:mb-48 -mt-64">
<div className="max-w-7xl mx-auto px-4 transform skew-y-3">
<section className="py-16 md:py-28 px-4">
<div className="relative pt-16 pb-12">
<div className="relative">
<div className="lg:mx-auto lg:max-w-7xl lg:px-8 lg:grid lg:grid-cols-2 lg:grid-flow-col-dense lg:gap-24">
<div className="px-4 max-w-xl mx-auto sm:px-6 lg:py-16 lg:max-w-none lg:mx-0 lg:px-0">
<div>
<div className="mt-6">
<h2 className="lg:text-4xl sm:text-3xl text-3xl text-white font-bold font-heading">
Completely permissionless.
</h2>
<p className="mt-4 text-xl text-gray-400">
Open source, all data is on-chain. Trade spot margined
markets and leveraged perpetual futures all
cross-collateralized with up to 10x leverage.
</p>
<div className="mt-6">
<a
rel="noreferrer"
target="_blank"
href="https://trade.mango.markets/accounts"
>
<Button>Start trading today</Button>
</a>
</div>
</div>
</div>
</div>
<div className="mt-12 sm:mt-16 lg:mt-0">
<div className="pl-4 -mr-48 sm:pl-6 md:-mr-16 lg:px-0 lg:m-0 lg:relative lg:h-650">
<img
className="-mt-20 w-full rounded-xl shadow-xl lg:absolute lg:left-0 lg:h-full lg:w-auto lg:max-w-none"
src="../img/feature-cta2.png"
alt="mango markets"
/>
</div>
</div>
</div>
</div>
</div>
<div className="overflow-hidden">
<div className="relative max-w-7xl mx-auto py-12 px-4 sm:px-6 lg:px-8">
<svg
className="absolute top-0 left-full transform -translate-x-1/2 -translate-y-3/4 lg:left-auto lg:right-full lg:translate-x-2/3 lg:translate-y-1/4"
width={404}
height={784}
fill="none"
viewBox="0 0 404 784"
aria-hidden="true"
>
<defs>
<pattern
id="8b1b5f72-e944-4457-af67-0c6d15a99f38"
x={0}
y={0}
width={20}
height={20}
patternUnits="userSpaceOnUse"
>
<rect
x={0}
y={0}
width={4}
height={4}
className="text-th-fgd-4"
fill="currentColor"
/>
</pattern>
</defs>
<rect
width={404}
height={784}
fill="url(#8b1b5f72-e944-4457-af67-0c6d15a99f38)"
/>
</svg>
<div className="relative lg:grid lg:grid-cols-3 lg:gap-x-8">
<div className="lg:col-span-1">
<h2 className="lg:text-4xl sm:text-3xl text-3xl text-white font-bold font-heading">
Love trading again.
</h2>
{/*
<div className="pt-6">
<blockquote>
<div>
<p className="text-base text-gray-500">
&ldquo;Cras velit quis eros eget rhoncus lacus
ultrices sed diam. Sit orci risus aenean curabitur
donec aliquet. Mi venenatis in euismod ut.&rdquo;
</p>
</div>
<footer className="mt-3">
<div className="flex items-center space-x-3">
<div className="flex-shrink-0">
<img
className="h-6 w-6 rounded-full"
src="https://images.unsplash.com/photo-1509783236416-c9ad59bae472?ixlib=rb-=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=8&w=1024&h=1024&q=80"
alt=""
/>
</div>
<div className="text-base font-bold text-mango-yellow">
@troll_arse
</div>
</div>
</footer>
</blockquote>
</div>
*/}
</div>
<dl className="mt-10 space-y-10 sm:space-y-0 sm:grid sm:grid-cols-2 sm:gap-x-8 sm:gap-y-10 lg:mt-0 lg:col-span-2">
{features.map((feature) => (
<div key={feature.name}>
<dt>
<div className="flex items-center justify-center h-12 w-12 rounded-md bg-bkg-3 text-mango-yellow">
<feature.icon
className="h-6 w-6"
aria-hidden="true"
/>
</div>
<p className="mt-5 text-xl my-3 font-semibold font-heading">
{feature.name}
</p>
</dt>
<dd className="mt-2 text-base text-gray-500">
{feature.description}
</dd>
</div>
))}
</dl>
</div>
</div>
</div>
</section>
</div>
</div>
<section className="py-16 md:py-28 px-4">
<div className="relative pt-16 pb-12">
<div className="relative">
<div className="lg:mx-auto lg:max-w-7xl lg:px-8 lg:grid lg:grid-cols-2 lg:grid-flow-col-dense lg:gap-24">
<div className="px-4 max-w-xl mx-auto sm:px-6 lg:py-16 lg:max-w-none lg:mx-0 lg:px-0">
<div>
<div className="mt-6">
<h2 className="lg:text-4xl sm:text-3xl text-3xl text-white font-bold font-heading">
More than an exchange.
</h2>
<p className="mt-4 text-xl text-gray-400">
Mango gives full control and tracking over assets right
from the account hub. Earn interest on deposits and borrow
against collateral all in one single place.
</p>
<div className="mt-6">
<a
rel="noreferrer"
target="_blank"
href="https://trade.mango.markets/accounts"
>
<Button>Open a 🥭 account</Button>
</a>
</div>
</div>
{/*
<div className="mt-8 pt-6">
<blockquote>
<div>
<p className="text-base text-gray-400">
&ldquo;Cras velit quis eros eget rhoncus lacus
ultrices sed diam. Sit orci risus aenean curabitur
donec aliquet. Mi venenatis in euismod ut.&rdquo;
</p>
</div>
<div className="z-0 relative -bottom-72 -right-96 lg:-bottom-96 ">
<div className="absolute bottom-4 left-8 w-450 h-450 bg-mango-yellow mix-blend-screen rounded-full filter blur-3xl opacity-5 animate-blob"></div>
<div className="absolute bottom-4 w-450 h-450 bg-mango-red mix-blend-screen rounded-full filter blur-2xl opacity-20 animate-blob animation-delay-4000"></div>
<div className="absolute bottom-8 left-20 w-450 h-450 bg-mango-green mix-blend-screen rounded-full filter blur-2xl opacity-10 animate-blob animation-delay-2000"></div>
</div>
<footer className="mt-3">
<div className="flex items-center space-x-3">
<div className="flex-shrink-0">
<img
className="h-6 w-6 rounded-full"
src="https://images.unsplash.com/photo-1509783236416-c9ad59bae472?ixlib=rb-=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=8&w=1024&h=1024&q=80"
alt=""
/>
</div>
<div className="text-base font-bold text-mango-yellow">
@troll_arse
</div>
</div>
</footer>
</blockquote>
</div>
*/}
<div className="z-0 relative -bottom-72 -right-96 lg:-bottom-96 ">
<div className="absolute bottom-4 left-8 w-450 h-450 bg-mango-yellow mix-blend-screen rounded-full filter blur-3xl opacity-5 animate-blob"></div>
<div className="absolute bottom-4 w-450 h-450 bg-mango-red mix-blend-screen rounded-full filter blur-2xl opacity-20 animate-blob animation-delay-4000"></div>
<div className="absolute bottom-8 left-20 w-450 h-450 bg-mango-green mix-blend-screen rounded-full filter blur-2xl opacity-10 animate-blob animation-delay-2000"></div>
</div>
</div>
</div>
<div className="mt-12 sm:mt-16 lg:mt-0">
<div className="z-10 pl-4 -mr-48 sm:pl-6 md:-mr-16 lg:px-0 lg:m-0 lg:relative lg:h-650">
<img
className="-mt-12 w-full rounded-xl shadow-xl lg:absolute lg:left-0 lg:h-full lg:w-auto lg:max-w-none"
src="../img/feature-cta1.png"
alt="Inbox user interface"
/>
</div>
</div>
</div>
</div>
</div>
</section>
<section className="max-w-7xl mx-auto px-8">
<div className="grid grid-cols-3 gap-6 mb-6">
<div className="lg:col-span-1 md:col-span-3 sm:col-span-3 xs:col-span-3">
<div className="z-10 bg-th-fgd-4 border border-bkg-3 bg-product-one bg-cover bg-no-repeat h-650 w-full shadow-md rounded-xl overflow-hidden mx-auto">
<div className="py-4 px-8 mt-3">
<div className="flex flex-col mb-8">
<h2 className="text-yellow-300 font-semibold text-xl tracking-wide mb-2">
You are in control.
</h2>
<p className="text-white text-opacity-50 text-lg">
You have self-custody of your assets; no more centralized
counter-party risk.
</p>
</div>
</div>
</div>
</div>
<div className="lg:col-span-2 md:col-span-3 sm:col-span-3 xs:col-span-3">
<div className="z-50 bg-th-fgd-4 border border-bkg-3 bg-product-two bg-cover bg-no-repeat h-650 w-full shadow-md rounded-xl overflow-hidden mx-auto">
<div className="py-4 px-8 mt-3">
<div className="flex flex-col mb-8">
<h2 className="text-yellow-300 font-semibold text-xl tracking-wide mb-2">
Fully customize your experience.
</h2>
<p className="text-white text-opacity-50 text-lg">
Complete control over layout, theme, and your trading view.
</p>
</div>
</div>
</div>
</div>
</div>
<div className="grid grid-cols-3 gap-6">
<div className="lg:col-span-2 md:col-span-3 sm:col-span-3 xs:col-span-3">
<div className="z-10 bg-th-fgd-4 border border-bkg-3 bg-product-three bg-cover bg-no-repeat h-650 w-full shadow-md rounded-xl overflow-hidden mx-auto">
<div className="py-4 px-8 mt-3">
<div className="flex flex-col mb-8">
<h2 className="text-yellow-300 font-semibold text-xl tracking-wide mb-2">
Trade management simplified.
</h2>
<p className="text-white text-opacity-50 text-lg">
Track your futures positions, liabilities, create
sub-accounts and track progress overtime.
</p>
</div>
</div>
</div>
</div>
<div className="lg:col-span-1 md:col-span-3 sm:col-span-3 xs:col-span-3">
<div className="z-10 bg-th-fgd-4 border border-bkg-3 bg-product-four bg-cover bg-no-repeat h-650 w-full shadow-md rounded-xl overflow-hidden mx-auto">
<div className="py-4 px-8 mt-3">
<div className="flex flex-col mb-8">
<h2 className="text-yellow-300 font-semibold text-xl tracking-wide mb-2">
Organically grown, fully opensource.
</h2>
<p className="text-white text-opacity-50 text-lg">
Mango markets are grown organically with no pesticides,
trade and manage your assets with the best in class user
interface, built by traders for traders.
</p>
<br />
<a
rel="noreferrer"
target="_blank"
href="https://github.com/blockworks-foundation/mango-ui-v3"
>
<LinkLeft>Run it yourself locally</LinkLeft>
</a>
</div>
</div>
</div>
</div>
</div>
</section>
</>
)
}
export default FeatureSection

View File

@ -1,199 +0,0 @@
import { ChevronRightIcon } from '@heroicons/react/solid'
import {
BookmarkAltIcon,
BookOpenIcon,
RssIcon,
ViewListIcon,
} from '@heroicons/react/outline'
import GradientText from './GradientText'
const links = [
{
title: 'Documentation',
description: 'Learn how to integrate our tools with your app',
icon: BookOpenIcon,
},
{
title: 'API Reference',
description: 'A complete API reference for our libraries',
icon: ViewListIcon,
},
{
title: 'Guides',
description: 'Installation guides that cover popular setups',
icon: BookmarkAltIcon,
},
{
title: 'Blog',
description: 'Read our latest news and articles',
icon: RssIcon,
},
]
const social = [
{
name: 'Facebook',
href: '#',
icon: (props) => (
<svg fill="currentColor" viewBox="0 0 24 24" {...props}>
<path
fillRule="evenodd"
d="M22 12c0-5.523-4.477-10-10-10S2 6.477 2 12c0 4.991 3.657 9.128 8.438 9.878v-6.987h-2.54V12h2.54V9.797c0-2.506 1.492-3.89 3.777-3.89 1.094 0 2.238.195 2.238.195v2.46h-1.26c-1.243 0-1.63.771-1.63 1.562V12h2.773l-.443 2.89h-2.33v6.988C18.343 21.128 22 16.991 22 12z"
clipRule="evenodd"
/>
</svg>
),
},
{
name: 'Instagram',
href: '#',
icon: (props) => (
<svg fill="currentColor" viewBox="0 0 24 24" {...props}>
<path
fillRule="evenodd"
d="M12.315 2c2.43 0 2.784.013 3.808.06 1.064.049 1.791.218 2.427.465a4.902 4.902 0 011.772 1.153 4.902 4.902 0 011.153 1.772c.247.636.416 1.363.465 2.427.048 1.067.06 1.407.06 4.123v.08c0 2.643-.012 2.987-.06 4.043-.049 1.064-.218 1.791-.465 2.427a4.902 4.902 0 01-1.153 1.772 4.902 4.902 0 01-1.772 1.153c-.636.247-1.363.416-2.427.465-1.067.048-1.407.06-4.123.06h-.08c-2.643 0-2.987-.012-4.043-.06-1.064-.049-1.791-.218-2.427-.465a4.902 4.902 0 01-1.772-1.153 4.902 4.902 0 01-1.153-1.772c-.247-.636-.416-1.363-.465-2.427-.047-1.024-.06-1.379-.06-3.808v-.63c0-2.43.013-2.784.06-3.808.049-1.064.218-1.791.465-2.427a4.902 4.902 0 011.153-1.772A4.902 4.902 0 015.45 2.525c.636-.247 1.363-.416 2.427-.465C8.901 2.013 9.256 2 11.685 2h.63zm-.081 1.802h-.468c-2.456 0-2.784.011-3.807.058-.975.045-1.504.207-1.857.344-.467.182-.8.398-1.15.748-.35.35-.566.683-.748 1.15-.137.353-.3.882-.344 1.857-.047 1.023-.058 1.351-.058 3.807v.468c0 2.456.011 2.784.058 3.807.045.975.207 1.504.344 1.857.182.466.399.8.748 1.15.35.35.683.566 1.15.748.353.137.882.3 1.857.344 1.054.048 1.37.058 4.041.058h.08c2.597 0 2.917-.01 3.96-.058.976-.045 1.505-.207 1.858-.344.466-.182.8-.398 1.15-.748.35-.35.566-.683.748-1.15.137-.353.3-.882.344-1.857.048-1.055.058-1.37.058-4.041v-.08c0-2.597-.01-2.917-.058-3.96-.045-.976-.207-1.505-.344-1.858a3.097 3.097 0 00-.748-1.15 3.098 3.098 0 00-1.15-.748c-.353-.137-.882-.3-1.857-.344-1.023-.047-1.351-.058-3.807-.058zM12 6.865a5.135 5.135 0 110 10.27 5.135 5.135 0 010-10.27zm0 1.802a3.333 3.333 0 100 6.666 3.333 3.333 0 000-6.666zm5.338-3.205a1.2 1.2 0 110 2.4 1.2 1.2 0 010-2.4z"
clipRule="evenodd"
/>
</svg>
),
},
{
name: 'Twitter',
href: '#',
icon: (props) => (
<svg fill="currentColor" viewBox="0 0 24 24" {...props}>
<path d="M8.29 20.251c7.547 0 11.675-6.253 11.675-11.675 0-.178 0-.355-.012-.53A8.348 8.348 0 0022 5.92a8.19 8.19 0 01-2.357.646 4.118 4.118 0 001.804-2.27 8.224 8.224 0 01-2.605.996 4.107 4.107 0 00-6.993 3.743 11.65 11.65 0 01-8.457-4.287 4.106 4.106 0 001.27 5.477A4.072 4.072 0 012.8 9.713v.052a4.105 4.105 0 003.292 4.022 4.095 4.095 0 01-1.853.07 4.108 4.108 0 003.834 2.85A8.233 8.233 0 012 18.407a11.616 11.616 0 006.29 1.84" />
</svg>
),
},
{
name: 'GitHub',
href: '#',
icon: (props) => (
<svg fill="currentColor" viewBox="0 0 24 24" {...props}>
<path
fillRule="evenodd"
d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z"
clipRule="evenodd"
/>
</svg>
),
},
{
name: 'Dribbble',
href: '#',
icon: (props) => (
<svg fill="currentColor" viewBox="0 0 24 24" {...props}>
<path
fillRule="evenodd"
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10c5.51 0 10-4.48 10-10S17.51 2 12 2zm6.605 4.61a8.502 8.502 0 011.93 5.314c-.281-.054-3.101-.629-5.943-.271-.065-.141-.12-.293-.184-.445a25.416 25.416 0 00-.564-1.236c3.145-1.28 4.577-3.124 4.761-3.362zM12 3.475c2.17 0 4.154.813 5.662 2.148-.152.216-1.443 1.941-4.48 3.08-1.399-2.57-2.95-4.675-3.189-5A8.687 8.687 0 0112 3.475zm-3.633.803a53.896 53.896 0 013.167 4.935c-3.992 1.063-7.517 1.04-7.896 1.04a8.581 8.581 0 014.729-5.975zM3.453 12.01v-.26c.37.01 4.512.065 8.775-1.215.25.477.477.965.694 1.453-.109.033-.228.065-.336.098-4.404 1.42-6.747 5.303-6.942 5.629a8.522 8.522 0 01-2.19-5.705zM12 20.547a8.482 8.482 0 01-5.239-1.8c.152-.315 1.888-3.656 6.703-5.337.022-.01.033-.01.054-.022a35.318 35.318 0 011.823 6.475 8.4 8.4 0 01-3.341.684zm4.761-1.465c-.086-.52-.542-3.015-1.659-6.084 2.679-.423 5.022.271 5.314.369a8.468 8.468 0 01-3.655 5.715z"
clipRule="evenodd"
/>
</svg>
),
},
]
const FourOhfour = () => {
return (
<div className="bg-bg-texture bg-cover bg-bottom bg-no-repeat">
<main className="max-w-7xl w-full mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex-shrink-0 pt-16">
<img
className="mx-auto h-12 w-auto"
src="../img/logo_mango.svg"
alt="Workflow"
/>
</div>
<div className="max-w-xl mx-auto py-16 sm:py-24">
<div className="text-center">
<p className="text-sm font-semibold uppercase tracking-wide">
<GradientText>404 error</GradientText>
</p>
<h1 className="mt-2 text-4xl font-extrabold text-white tracking-tight sm:text-5xl">
Hmm... you must be lost!
</h1>
<p className="mt-2 text-lg text-gray-500">
The page you are looking for could not be found.
</p>
</div>
<div className="mt-12">
<h2 className="text-sm font-semibold text-white text-opacity-50 tracking-wide uppercase">
Popular pages
</h2>
<ul
role="list"
className="mt-4 border-t border-b border-white divide-y divide-white divide-opacity-20 border-opacity-20"
>
{links.map((link, linkIdx) => (
<li
key={linkIdx}
className="relative py-6 flex items-start space-x-4"
>
<div className="flex-shrink-0">
<span className="flex items-center justify-center h-12 w-12 rounded-lg bg-indigo-50">
<link.icon
className="h-6 w-6 text-mango-yellow"
aria-hidden="true"
/>
</span>
</div>
<div className="min-w-0 flex-1">
<h3 className="text-base font-medium text-white">
<span className="rounded-sm focus-within:ring-2 focus-within:ring-offset-2 focus-within:ring-mango-yellow">
<a href="#" className="focus:outline-none">
<span
className="absolute inset-0"
aria-hidden="true"
/>
{link.title}
</a>
</span>
</h3>
<p className="text-base text-white text-opacity-50">
{link.description}
</p>
</div>
<div className="flex-shrink-0 self-center">
<ChevronRightIcon
className="h-5 w-5 text-mango-yellow"
aria-hidden="true"
/>
</div>
</li>
))}
</ul>
<div className="mt-8">
<a
href="#"
className="text-base font-medium text-mango-orange hover:text-mango-yellow"
>
Or go back home<span aria-hidden="true"> &rarr;</span>
</a>
</div>
</div>
</div>
</main>
<footer className="max-w-7xl w-full mx-auto px-4 sm:px-6 lg:px-8">
<div className="border-t border-gray-200 py-12 text-center md:flex md:justify-between">
<p className="text-base text-gray-400">
&copy; Workflow, Inc. All rights reserved.
</p>
<div className="mt-6 flex justify-center space-x-8 md:mt-0">
{social.map((item, itemIdx) => (
<a
key={itemIdx}
href={item.href}
className="inline-flex text-gray-400 hover:text-gray-500"
>
<span className="sr-only">{item.name}</span>
<item.icon className="h-6 w-6" aria-hidden="true" />
</a>
))}
</div>
</div>
</footer>
</div>
)
}
export default FourOhfour

View File

@ -1,5 +1,5 @@
import { FunctionComponent } from 'react'
import { useRef, useEffect } from 'react'
import Button from './Button'
import { gsap, Power3 } from 'gsap'
const HeroSectionHome = () => {
@ -15,16 +15,46 @@ const HeroSectionHome = () => {
ease: Power3.easeOut,
})
}, [])
return (
<div className="relative" style={{ height: 'calc(100vh - 160px)' }}>
<div className="lg:px-20 xs:px-6 max-w-xl lg:max-w-3xl h-full pb-20 flex flex-col justify-center w-full">
<div className="lg:px-20 xs:px-6 sm:max-w-xl lg:max-w-3xl h-full flex flex-col justify-center w-full">
<div>
<h1 className="mb-3 lg:text-6xl text-5xl text-white font-bold font-heading">
A New Dawn.{' '}
<h1 className="mb-4">
Live to{' '}
<span className="bg-gradient-to-br from-secondary-1-light via-primary-dark to-secondary-2-light bg-clip-text text-transparent">
trade
</span>
.
</h1>
<p className="text-base text-th-fgd-3 mb-6">
Mango v4 is in public beta. Re-designed from the ground up with
innovative new features and risk mitigation strategies, you can
finally ditch your CEX.
</p>
<CheckBullet>Trade spot & perpetuals up to 10x leverage.</CheckBullet>
<CheckBullet>Earn interest on all deposits.</CheckBullet>
<CheckBullet>Borrow any listed token.</CheckBullet>
<CheckBullet showNewBadge>Permissionless token listings.</CheckBullet>
{/* <CheckBullet showNewBadge>{t('home:bullet-5')}</CheckBullet> */}
<div className="flex items-center mt-10 space-x-8">
<ButtonLink
linkText="Trade Now"
path="https://app.mango.markets"
size="large"
/>
<a
href="https://docs.mango.markets"
rel="noopener noreferrer"
className="font-bold flex items-center text-th-fgd-2 md:hover:text-th-fgd-3 default-transition"
target="_blank"
>
View Docs
<ChevronRightIcon className="h-6 w-6 mt-0.5" />
</a>
</div>
<p className="mt-8 text-xs">Website under contruction.</p>
<p className="mb-3 opacity-80 text-lg">
{/* <p className="mb-3 opacity-80 text-lg">
The next generation of Mango is on the horizon. With exciting new
features and risk mitigation strategies, Mango v4 is your one-stop
DeFi shop.
@ -47,9 +77,9 @@ const HeroSectionHome = () => {
<span>Join Discord</span>
</Button>
</a>
</div>
</div> */}
</div>
<div>
{/* <div>
<p className="mt-16 py-4 text-xs text-white text-opacity-50 uppercase tracking-wide font-normal sm:mt-16">
Powered by
</p>
@ -63,11 +93,11 @@ const HeroSectionHome = () => {
</a>
</div>
</div>
</div>
</div> */}
</div>
<img
ref={sideImage}
className="hidden md:block absolute -bottom-20 z-10 right-0 w-full md:w-2/3 lg:w-3/5 h-auto opacity-0 transform translate-y-40"
className="hidden sm:block absolute -bottom-20 z-10 right-0 w-3/4 sm:w-2/3 lg:w-3/5 h-auto opacity-0 transform translate-y-40"
src="../img/trade.png"
alt=""
/>
@ -81,3 +111,65 @@ const HeroSectionHome = () => {
}
export default HeroSectionHome
import { CheckCircleIcon, ChevronRightIcon } from '@heroicons/react/20/solid'
import { ReactNode } from 'react'
const CheckBullet = ({
children,
showNewBadge,
}: {
children: ReactNode
showNewBadge?: boolean
}) => {
return (
<div className="mb-2 flex items-center space-x-2.5">
<CheckCircleIcon className="h-6 w-6 text-th-fgd-3 flex-shrink-0" />
<p className="text-base lg:text-lg text-th-fgd-2">
{children}
{showNewBadge ? (
<span className="py-0.5 px-1 rounded bg-th-fgd-1 font-medium text-sm uppercase text-th-bkg-1 ml-2">
New
</span>
) : null}
</p>
</div>
)
}
interface ButtonLinkProps {
path: string
className?: string
secondary?: boolean
linkText: string
size?: 'large' | 'medium' | 'small'
}
const ButtonLink: FunctionComponent<ButtonLinkProps> = ({
linkText,
path,
className,
secondary,
size = 'medium',
}) => {
return (
<a
className={`flex sm:w-max items-center justify-center rounded-md ${
secondary
? 'border border-th-red-dark'
: 'bg-th-red-dark md:hover:brightness-90'
} ${
size === 'medium'
? 'h-10 px-4 text-sm'
: size === 'large'
? 'h-12 px-6'
: 'h-8 px-3'
} default-transition font-display focus:outline-none text-th-fgd-1 ${className}`}
href={path}
rel="noopener noreferrer"
target="_blank"
>
{linkText}
</a>
)
}

View File

@ -2,17 +2,13 @@ const NavBarBeta = () => {
return (
<div className="">
{/* Main Menu */}
<div className="lg:px-20 lg:py-8 xs:px-6 xs:py-1 bg-transparent">
<div className="lg:px-20 xs:px-6 xs:py-1 bg-transparent">
<div className="flex justify-between items-center py-6">
<div className="flex justify-start lg:w-0 lg:flex-1">
<a href="https://mango.markets">
<a className="flex items-center" href="https://mango.markets">
<span className="sr-only">Mango</span>
<img
className="h-8"
src="img/logo_mango.svg"
alt=""
width="auto"
/>
<img className="h-8" src="/logo.svg" alt="" width="auto" />
<span className="font-display text-2xl ml-2">Mango</span>
</a>
</div>
<div className="flex flex-row">

View File

@ -1,113 +0,0 @@
import { useEffect, useState } from 'react'
import {
CheckCircleIcon,
InformationCircleIcon,
XCircleIcon,
} from '@heroicons/react/outline'
import useNotificationStore from '../stores/useNotificationStore'
const NotificationList = () => {
const { notifications, set: setNotificationStore } = useNotificationStore(
(s) => s
)
useEffect(() => {
if (notifications.length > 0) {
const id = setInterval(() => {
setNotificationStore((state) => {
state.notifications = notifications.slice(1, notifications.length)
})
}, 5000)
return () => {
clearInterval(id)
}
}
}, [notifications, setNotificationStore])
const reversedNotifications = [...notifications].reverse()
return (
<div
className={`fixed inset-0 flex items-end px-4 py-6 pointer-events-none sm:p-6`}
>
<div className={`flex flex-col w-full`}>
{reversedNotifications.map((n, idx) => (
<Notification
key={`${n.message}${idx}`}
type={n.type}
message={n.message}
description={n.description}
txid={n.txid}
/>
))}
</div>
</div>
)
}
const Notification = ({ type, message, description, txid }) => {
const [showNotification, setShowNotification] = useState(true)
if (!showNotification) return null
return (
<div
className={`max-w-sm w-full bg-th-bkg-3 shadow-lg rounded-md mt-2 pointer-events-auto ring-1 ring-black ring-opacity-5 overflow-hidden`}
>
<div className={`p-4`}>
<div className={`flex items-center`}>
<div className={`flex-shrink-0`}>
{type === 'success' ? (
<CheckCircleIcon className={`text-th-green h-9 w-9 mr-1`} />
) : null}
{type === 'info' && (
<XCircleIcon className={`text-th-primary h-9 w-9 mr-1`} />
)}
{type === 'error' && (
<InformationCircleIcon className={`text-th-red h-9 w-9 mr-1`} />
)}
</div>
<div className={`ml-2 w-0 flex-1`}>
<div className={`text-lg text-th-fgd-1`}>{message}</div>
{description ? (
<p className={`mt-0.5 text-base text-th-fgd-2`}>{description}</p>
) : null}
{txid ? (
<a
href={'https://explorer.solana.com/tx/' + txid}
className="text-th-primary"
>
View transaction {txid.slice(0, 8)}...
{txid.slice(txid.length - 8)}
</a>
) : null}
</div>
<div className={`ml-4 flex-shrink-0 self-start flex`}>
<button
onClick={() => setShowNotification(false)}
className={`bg-th-bkg-3 rounded-md inline-flex text-fgd-3 hover:text-th-fgd-4 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-th-primary`}
>
<span className={`sr-only`}>Close</span>
<svg
className={`h-5 w-5`}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
aria-hidden="true"
>
<path
fillRule="evenodd"
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
clipRule="evenodd"
/>
</svg>
</button>
</div>
</div>
</div>
</div>
)
}
export default NotificationList

View File

@ -1,36 +0,0 @@
import { useEffect, useState } from 'react'
import { useTheme } from 'next-themes'
import { MoonIcon, SunIcon } from '@heroicons/react/outline'
import DropMenu from './DropMenu'
import { MangoIcon } from './icons'
const THEMES = [
{ name: 'Light', icon: <SunIcon className="h-4 w-4" /> },
{ name: 'Dark', icon: <MoonIcon className="h-4 w-4" /> },
{ name: 'Mango', icon: <MangoIcon className="stroke-current h-4 w-4" /> },
]
const ThemeSwitch = () => {
const [mounted, setMounted] = useState(false)
const { theme, setTheme } = useTheme()
// When mounted on client, now we can show the UI
useEffect(() => setMounted(true), [])
return mounted ? (
<DropMenu
button={
<div className="bg-th-bkg-4 flex items-center justify-center rounded-full w-8 h-8 text-th-fgd-1 focus:outline-none hover:text-th-primary">
{THEMES.find((t) => t.name === theme).icon}
</div>
}
value={theme}
onChange={(theme) => setTheme(theme)}
options={THEMES}
/>
) : (
<div className="bg-th-bkg-3 rounded-full w-8 h-8" />
)
}
export default ThemeSwitch

View File

@ -1,116 +0,0 @@
import { useEffect, useState } from 'react'
import { Menu } from '@headlessui/react'
import styled from '@emotion/styled'
import {
ChevronUpIcon,
ChevronDownIcon,
DuplicateIcon,
LogoutIcon,
} from '@heroicons/react/outline'
import ConnectWalletButton from './ConnectWalletButton'
import WalletIcon from './WalletIcon'
import useWalletStore from '../stores/useWalletStore'
const Code = styled.code`
border: 1px solid hsla(0, 0%, 39.2%, 0.2);
border-radius: 3px;
background: hsla(0, 0%, 58.8%, 0.1);
font-size: 13px;
`
const WALLET_OPTIONS = [
{ name: 'Copy address', icon: <DuplicateIcon /> },
{ name: 'Disconnect', icon: <LogoutIcon /> },
]
const TopBar = () => {
const { connected, current: wallet } = useWalletStore((s) => s)
const [isCopied, setIsCopied] = useState(false)
useEffect(() => {
if (isCopied) {
const timer = setTimeout(() => {
setIsCopied(false)
}, 2000)
return () => clearTimeout(timer)
}
}, [isCopied])
const handleWalletMenu = (option) => {
if (option === 'Copy address') {
const el = document.createElement('textarea')
el.value = wallet.publicKey.toString()
document.body.appendChild(el)
el.select()
document.execCommand('copy')
document.body.removeChild(el)
setIsCopied(true)
} else {
wallet.disconnect()
}
}
return (
<nav className={`bg-th-bkg-2`}>
<div className={`px-4 sm:px-6 lg:px-8`}>
<div className={`flex justify-between h-16`}>
<div className={`flex`}>
<div className={`flex-shrink-0 flex items-center`}>
<img className={`h-8 w-auto`} src="/logo.svg" alt="logo" />
</div>
</div>
<div className="flex">
<div className="flex items-center">
<div className="hidden sm:ml-4 sm:block">
{connected && wallet?.publicKey ? (
<Menu>
{({ open }) => (
<div className="relative">
<Menu.Button className="w-48 h-11 pl-2 pr-2.5 border border-th-green hover:border-th-fgd-1 focus:outline-none rounded-md text-th-fgd-4 hover:text-th-fgd-1">
<div className="flex flex-row items-center justify-between">
<div className="flex items-center">
<WalletIcon className="w-5 h-5 mr-2 fill-current text-th-green" />
<Code className="p-1 text-th-fgd-3 font-light">
{isCopied
? 'Copied!'
: wallet.publicKey.toString().substr(0, 5) +
'...' +
wallet.publicKey.toString().substr(-5)}
</Code>
</div>
{open ? (
<ChevronUpIcon className="h-5 w-5" />
) : (
<ChevronDownIcon className="h-5 w-5" />
)}
</div>
</Menu.Button>
<Menu.Items className="z-20 p-1 absolute right-0 top-11 bg-th-bkg-1 divide-y divide-th-bkg-3 shadow-lg outline-none rounded-md w-48">
{WALLET_OPTIONS.map(({ name, icon }) => (
<Menu.Item key={name}>
<button
className="flex flex-row items-center w-full p-2 hover:bg-th-bkg-2 hover:cursor-pointer font-normal"
onClick={() => handleWalletMenu(name)}
>
<div className="w-5 h-5 mr-2">{icon}</div>
{name}
</button>
</Menu.Item>
))}
</Menu.Items>
</div>
)}
</Menu>
) : (
<ConnectWalletButton />
)}
</div>
</div>
</div>
</div>
</div>
</nav>
)
}
export default TopBar

View File

@ -1,64 +0,0 @@
import { Menu } from '@headlessui/react'
import {
ChevronDownIcon,
ChevronUpIcon,
CheckCircleIcon,
} from '@heroicons/react/outline'
import useWalletStore from '../stores/useWalletStore'
import { WALLET_PROVIDERS, DEFAULT_PROVIDER } from '../hooks/useWallet'
import useLocalStorageState from '../hooks/useLocalStorageState'
export default function WalletSelect({ isPrimary = false }) {
const setWalletStore = useWalletStore((s) => s.set)
const [savedProviderUrl] = useLocalStorageState(
'walletProvider',
DEFAULT_PROVIDER.url
)
const handleSelectProvider = (url) => {
setWalletStore((state) => {
state.providerUrl = url
})
}
return (
<Menu>
{({ open }) => (
<>
<Menu.Button
className={`flex justify-center items-center h-full rounded-r rounded-l-none focus:outline-none text-th-primary hover:text-th-fgd-1 ${
isPrimary
? 'px-3 hover:bg-th-primary'
: 'px-2 hover:bg-th-bkg-3 border-l border-th-fgd-4'
} cursor-pointer`}
>
{open ? (
<ChevronUpIcon className="h-5 w-5" />
) : (
<ChevronDownIcon className="h-5 w-5" />
)}
</Menu.Button>
<Menu.Items className="z-20 p-1 absolute right-0 top-11 bg-th-bkg-1 divide-y divide-th-bkg-3 shadow-lg outline-none rounded-md w-48">
{WALLET_PROVIDERS.map(({ name, url, icon }) => (
<Menu.Item key={name}>
<button
className="flex flex-row items-center justify-between w-full p-2 hover:bg-th-bkg-2 hover:cursor-pointer font-normal focus:outline-none"
onClick={() => handleSelectProvider(url)}
>
<div className="flex">
<img src={icon} className="w-5 h-5 mr-2" />
{name}
</div>
{savedProviderUrl === url ? (
<CheckCircleIcon className="h-4 w-4 text-th-green" />
) : null}{' '}
</button>
</Menu.Item>
))}
</Menu.Items>
</>
)}
</Menu>
)
}

View File

@ -1,135 +0,0 @@
import { useEffect, useMemo } from 'react'
import Wallet from '@project-serum/sol-wallet-adapter'
import { WalletAdapter } from '../@types/types'
import useWalletStore from '../stores/useWalletStore'
import { notify } from '../utils/notifications'
import {
PhantomWalletAdapter,
SolletExtensionAdapter,
} from '../utils/wallet-adapters'
import useInterval from './useInterval'
import useLocalStorageState from './useLocalStorageState'
const SECONDS = 1000
const ASSET_URL =
'https://cdn.jsdelivr.net/gh/solana-labs/oyster@main/assets/wallets'
export const WALLET_PROVIDERS = [
{
name: 'Sollet.io',
url: 'https://www.sollet.io',
icon: `${ASSET_URL}/sollet.svg`,
},
{
name: 'Sollet Extension',
url: 'https://www.sollet.io/extension',
icon: `${ASSET_URL}/sollet.svg`,
adapter: SolletExtensionAdapter as any,
},
{
name: 'Phantom',
url: 'https://www.phantom.app',
icon: `https://www.phantom.app/img/logo.png`,
adapter: PhantomWalletAdapter,
},
]
export const DEFAULT_PROVIDER = WALLET_PROVIDERS[0]
export default function useWallet() {
const {
connected,
connection: { endpoint },
current: wallet,
providerUrl: selectedProviderUrl,
set: setWalletStore,
actions,
} = useWalletStore((state) => state)
const [savedProviderUrl, setSavedProviderUrl] = useLocalStorageState(
'walletProvider',
DEFAULT_PROVIDER.url
)
const provider = useMemo(
() => WALLET_PROVIDERS.find(({ url }) => url === savedProviderUrl),
[savedProviderUrl]
)
useEffect(() => {
if (selectedProviderUrl) {
setSavedProviderUrl(selectedProviderUrl)
}
}, [selectedProviderUrl])
useEffect(() => {
if (provider) {
const updateWallet = () => {
// hack to also update wallet synchronously in case it disconnects
const wallet = new (provider.adapter || Wallet)(
savedProviderUrl,
endpoint
) as WalletAdapter
setWalletStore((state) => {
state.current = wallet
})
}
if (document.readyState !== 'complete') {
// wait to ensure that browser extensions are loaded
const listener = () => {
updateWallet()
window.removeEventListener('load', listener)
}
window.addEventListener('load', listener)
return () => window.removeEventListener('load', listener)
} else {
updateWallet()
}
}
}, [provider, savedProviderUrl, endpoint])
useEffect(() => {
if (!wallet) return
wallet.on('connect', async () => {
setWalletStore((state) => {
state.connected = true
})
notify({
message: 'Wallet connected',
description:
'Connected to wallet ' +
wallet.publicKey.toString().substr(0, 5) +
'...' +
wallet.publicKey.toString().substr(-5),
})
await actions.fetchWalletTokenAccounts()
await actions.fetchWalletMints()
})
wallet.on('disconnect', () => {
setWalletStore((state) => {
state.connected = false
state.tokenAccounts = []
state.mints = {}
})
notify({
type: 'info',
message: 'Disconnected from wallet',
})
})
return () => {
if (wallet && wallet.connected) {
wallet.disconnect()
}
setWalletStore((state) => {
state.connected = false
})
}
}, [wallet, setWalletStore])
useInterval(async () => {
await actions.fetchWalletTokenAccounts()
await actions.fetchWalletMints()
}, 20 * SECONDS)
return { connected, wallet }
}

5
next-env.d.ts vendored
View File

@ -1,2 +1,5 @@
/// <reference types="next" />
/// <reference types="next/types/global" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.

View File

@ -1,15 +1,29 @@
module.exports = {
target: 'serverless',
webpack(config) {
config.module.rules.push({
test: /\.svg$/,
use: ['@svgr/webpack'],
})
config.node = {
fs: 'empty',
module: 'empty',
const webpack = require('webpack')
/** @type {import('next').NextConfig} */
const nextConfig = {
images: {
domains: ['raw.githubusercontent.com', 'arweave.net'],
},
reactStrictMode: true,
webpack: (config, opts) => {
if (!opts.isServer) {
// don't resolve 'fs' module on the client to prevent this error on build --> Error: Can't resolve 'fs'
config.resolve.fallback = {
fs: false,
}
}
config.plugins.push(
new webpack.DefinePlugin({
'process.env': {
BUILD_ID: JSON.stringify(opts.buildId),
},
})
)
return config
},
}
module.exports = nextConfig

View File

@ -24,8 +24,7 @@
"@emotion/react": "^11.1.5",
"@emotion/styled": "^11.3.0",
"@headlessui/react": "^1.0.0",
"@heroicons/react": "^1.0.1",
"@project-serum/sol-wallet-adapter": "^0.2.0",
"@heroicons/react": "^2.0.16",
"@sendgrid/client": "^7.4.3",
"@solana/spl-token": "^0.1.3",
"@solana/web3.js": "^1.5.0",
@ -34,8 +33,8 @@
"moment": "^2.29.1",
"next": "latest",
"next-themes": "^0.0.14",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-fast-marquee": "^1.2.1",
"recharts": "^2.0.10",
"zustand": "^3.4.1"

View File

@ -1,13 +0,0 @@
import FourOhfour from '../components/FourOhFour'
const FourOh = () => {
return (
<div className={`bg-th-bkg-1 text-th-fgd-1 transition-all overflow-hidden`}>
<div className="w-screen h-2 bg-gradient-to-r from-mango-red via-mango-yellow to-mango-green"></div>
<FourOhfour />
<div className="w-screen h-2 bg-gradient-to-r from-mango-red via-mango-yellow to-mango-green"></div>
</div>
)
}
export default FourOh

View File

@ -1,11 +1,8 @@
import Head from 'next/head'
import { ThemeProvider } from 'next-themes'
import '../styles/index.css'
import useWallet from '../hooks/useWallet'
function App({ Component, pageProps }) {
useWallet()
const title = 'Mango Markets'
const description =
'Decentralised, cross-margin trading up to 20x leverage with lightning speed and near-zero fees.'

View File

@ -1,19 +0,0 @@
import NavBarBeta from '../components/NavBarBeta'
import HeroSectionMarkets from '../components/HeroSectionMarkets'
import FeatureSection from '../components/FeatureSection'
import FooterSection from '../components/FooterSection'
const Markets = () => {
return (
<div className={`bg-th-bkg-1 text-th-fgd-1 transition-all overflow-hidden`}>
<div className="w-screen h-2 bg-gradient-to-r from-mango-red via-mango-yellow to-mango-green"></div>
<NavBarBeta />
<HeroSectionMarkets />
<FeatureSection />
<FooterSection />
<div className="w-screen h-2 bg-gradient-to-r from-mango-red via-mango-yellow to-mango-green"></div>
</div>
)
}
export default Markets

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

View File

@ -1,3 +1,3 @@
<svg width="28" height="20" viewBox="0 0 28 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M23.7187 1.67497C21.9061 0.89249 19.9681 0.323786 17.9421 0C17.6932 0.41511 17.4025 0.973432 17.2021 1.4176C15.0482 1.11872 12.9142 1.11872 10.8 1.4176C10.5996 0.973432 10.3023 0.41511 10.0513 0C8.02293 0.323786 6.08271 0.894565 4.27023 1.67912C0.614418 6.77668 -0.376613 11.7477 0.118903 16.648C2.54363 18.3188 4.89347 19.3337 7.20367 19.9979C7.77407 19.2736 8.2828 18.5036 8.72106 17.692C7.88639 17.3993 7.08696 17.0382 6.33156 16.6189C6.53197 16.482 6.72798 16.3387 6.91738 16.1914C11.5246 18.1797 16.5304 18.1797 21.0826 16.1914C21.2741 16.3387 21.4701 16.482 21.6683 16.6189C20.9107 17.0402 20.1091 17.4014 19.2744 17.6941C19.7127 18.5036 20.2192 19.2757 20.7918 20C23.1042 19.3358 25.4563 18.3209 27.881 16.648C28.4624 10.9672 26.8878 6.04193 23.7187 1.67497ZM9.34871 13.6343C7.96567 13.6343 6.83149 12.4429 6.83149 10.9922C6.83149 9.54132 7.94144 8.34791 9.34871 8.34791C10.756 8.34791 11.8901 9.53924 11.8659 10.9922C11.8682 12.4429 10.756 13.6343 9.34871 13.6343ZM18.6512 13.6343C17.2682 13.6343 16.1339 12.4429 16.1339 10.9922C16.1339 9.54132 17.2439 8.34791 18.6512 8.34791C20.0584 8.34791 21.1926 9.53924 21.1684 10.9922C21.1684 12.4429 20.0584 13.6343 18.6512 13.6343Z" fill="#4F4C67"/>
<path d="M23.7187 1.67497C21.9061 0.89249 19.9681 0.323786 17.9421 0C17.6932 0.41511 17.4025 0.973432 17.2021 1.4176C15.0482 1.11872 12.9142 1.11872 10.8 1.4176C10.5996 0.973432 10.3023 0.41511 10.0513 0C8.02293 0.323786 6.08271 0.894565 4.27023 1.67912C0.614418 6.77668 -0.376613 11.7477 0.118903 16.648C2.54363 18.3188 4.89347 19.3337 7.20367 19.9979C7.77407 19.2736 8.2828 18.5036 8.72106 17.692C7.88639 17.3993 7.08696 17.0382 6.33156 16.6189C6.53197 16.482 6.72798 16.3387 6.91738 16.1914C11.5246 18.1797 16.5304 18.1797 21.0826 16.1914C21.2741 16.3387 21.4701 16.482 21.6683 16.6189C20.9107 17.0402 20.1091 17.4014 19.2744 17.6941C19.7127 18.5036 20.2192 19.2757 20.7918 20C23.1042 19.3358 25.4563 18.3209 27.881 16.648C28.4624 10.9672 26.8878 6.04193 23.7187 1.67497ZM9.34871 13.6343C7.96567 13.6343 6.83149 12.4429 6.83149 10.9922C6.83149 9.54132 7.94144 8.34791 9.34871 8.34791C10.756 8.34791 11.8901 9.53924 11.8659 10.9922C11.8682 12.4429 10.756 13.6343 9.34871 13.6343ZM18.6512 13.6343C17.2682 13.6343 16.1339 12.4429 16.1339 10.9922C16.1339 9.54132 17.2439 8.34791 18.6512 8.34791C20.0584 8.34791 21.1926 9.53924 21.1684 10.9922C21.1684 12.4429 20.0584 13.6343 18.6512 13.6343Z" fill="#B9B5CE"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1,3 +1,3 @@
<svg width="28" height="27" viewBox="0 0 28 27" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14 0C6.26967 0 0 6.19744 0 13.8413C0 19.9568 4.011 25.145 9.57483 26.9755C10.2737 27.1035 10.5 26.6745 10.5 26.31V23.7332C6.60567 24.5706 5.79483 22.0999 5.79483 22.0999C5.15783 20.5001 4.23967 20.0745 4.23967 20.0745C2.96917 19.2152 4.3365 19.2336 4.3365 19.2336C5.74233 19.3305 6.482 20.6604 6.482 20.6604C7.73033 22.7758 9.75683 22.1645 10.556 21.8104C10.6808 20.9165 11.0437 20.3052 11.445 19.9603C8.33583 19.6085 5.06683 18.4216 5.06683 13.1192C5.06683 11.6071 5.614 10.3729 6.50883 9.404C6.36417 9.05451 5.88467 7.64616 6.64533 5.74067C6.64533 5.74067 7.82133 5.36926 10.4965 7.1594C11.613 6.85259 12.81 6.69918 14 6.69341C15.19 6.69918 16.3882 6.85259 17.507 7.1594C20.1798 5.36926 21.3535 5.74067 21.3535 5.74067C22.1153 7.64731 21.6358 9.05566 21.4912 9.404C22.3895 10.3729 22.932 11.6082 22.932 13.1192C22.932 18.4354 19.6572 19.6062 16.5398 19.9488C17.0415 20.3778 17.5 21.2198 17.5 22.5117V26.31C17.5 26.6779 17.724 27.1105 18.4345 26.9744C23.9937 25.1415 28 19.9545 28 13.8413C28 6.19744 21.7315 0 14 0Z" fill="#4F4C67"/>
<path d="M14 0C6.26967 0 0 6.19744 0 13.8413C0 19.9568 4.011 25.145 9.57483 26.9755C10.2737 27.1035 10.5 26.6745 10.5 26.31V23.7332C6.60567 24.5706 5.79483 22.0999 5.79483 22.0999C5.15783 20.5001 4.23967 20.0745 4.23967 20.0745C2.96917 19.2152 4.3365 19.2336 4.3365 19.2336C5.74233 19.3305 6.482 20.6604 6.482 20.6604C7.73033 22.7758 9.75683 22.1645 10.556 21.8104C10.6808 20.9165 11.0437 20.3052 11.445 19.9603C8.33583 19.6085 5.06683 18.4216 5.06683 13.1192C5.06683 11.6071 5.614 10.3729 6.50883 9.404C6.36417 9.05451 5.88467 7.64616 6.64533 5.74067C6.64533 5.74067 7.82133 5.36926 10.4965 7.1594C11.613 6.85259 12.81 6.69918 14 6.69341C15.19 6.69918 16.3882 6.85259 17.507 7.1594C20.1798 5.36926 21.3535 5.74067 21.3535 5.74067C22.1153 7.64731 21.6358 9.05566 21.4912 9.404C22.3895 10.3729 22.932 11.6082 22.932 13.1192C22.932 18.4354 19.6572 19.6062 16.5398 19.9488C17.0415 20.3778 17.5 21.2198 17.5 22.5117V26.31C17.5 26.6779 17.724 27.1105 18.4345 26.9744C23.9937 25.1415 28 19.9545 28 13.8413C28 6.19744 21.7315 0 14 0Z" fill="#B9B5CE"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1,3 +1,3 @@
<svg width="28" height="23" viewBox="0 0 28 23" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.78874 23C5.55374 23 2.53817 22.0591 0 20.4356C2.15499 20.5751 5.95807 20.2411 8.32358 17.9848C4.76508 17.8215 3.16026 15.0923 2.95094 13.926C3.25329 14.0426 4.6953 14.1826 5.50934 13.856C1.4159 12.8296 0.787928 9.23732 0.927477 8.14097C1.695 8.67749 2.99745 8.8641 3.50913 8.81744C-0.305207 6.08823 1.06703 1.98276 1.74151 1.09635C4.47882 4.88867 8.5812 7.01857 13.6564 7.13704C13.5607 6.71736 13.5102 6.28042 13.5102 5.83164C13.5102 2.61092 16.1134 0 19.3247 0C21.0025 0 22.5144 0.712754 23.5757 1.85284C24.6969 1.59011 26.3843 0.975068 27.2092 0.443205C26.7934 1.93611 25.4989 3.18149 24.7159 3.64308C24.7224 3.65878 24.7095 3.62731 24.7159 3.64308C25.4037 3.53904 27.2648 3.18137 28 2.68256C27.6364 3.52125 26.264 4.91573 25.1377 5.69642C25.3473 14.9381 18.2765 23 8.78874 23Z" fill="#4F4C67"/>
<path d="M8.78874 23C5.55374 23 2.53817 22.0591 0 20.4356C2.15499 20.5751 5.95807 20.2411 8.32358 17.9848C4.76508 17.8215 3.16026 15.0923 2.95094 13.926C3.25329 14.0426 4.6953 14.1826 5.50934 13.856C1.4159 12.8296 0.787928 9.23732 0.927477 8.14097C1.695 8.67749 2.99745 8.8641 3.50913 8.81744C-0.305207 6.08823 1.06703 1.98276 1.74151 1.09635C4.47882 4.88867 8.5812 7.01857 13.6564 7.13704C13.5607 6.71736 13.5102 6.28042 13.5102 5.83164C13.5102 2.61092 16.1134 0 19.3247 0C21.0025 0 22.5144 0.712754 23.5757 1.85284C24.6969 1.59011 26.3843 0.975068 27.2092 0.443205C26.7934 1.93611 25.4989 3.18149 24.7159 3.64308C24.7224 3.65878 24.7095 3.62731 24.7159 3.64308C25.4037 3.53904 27.2648 3.18137 28 2.68256C27.6364 3.52125 26.264 4.91573 25.1377 5.69642C25.3473 14.9381 18.2765 23 8.78874 23Z" fill="#B9B5CE"/>
</svg>

Before

Width:  |  Height:  |  Size: 913 B

After

Width:  |  Height:  |  Size: 913 B

View File

@ -1,113 +0,0 @@
import create, { State } from 'zustand'
import produce from 'immer'
import { Connection } from '@solana/web3.js'
import { EndpointInfo, WalletAdapter } from '../@types/types'
import {
getOwnedTokenAccounts,
getMint,
ProgramAccount,
TokenAccount,
MintAccount,
} from '../utils/tokens'
export const ENDPOINTS: EndpointInfo[] = [
{
name: 'mainnet-beta',
url: 'https://solana-api.projectserum.com/',
websocket: 'https://api.mainnet-beta.solana.com/',
},
{
name: 'devnet',
url: 'https://devnet.solana.com',
websocket: 'https://devnet.solana.com',
},
]
const CLUSTER = 'mainnet-beta'
const ENDPOINT = ENDPOINTS.find((e) => e.name === CLUSTER)
const DEFAULT_CONNECTION = new Connection(ENDPOINT.url, 'recent')
const WEBSOCKET_CONNECTION = new Connection(ENDPOINT.websocket, 'recent')
interface WalletStore extends State {
connected: boolean
connection: {
cluster: string
current: Connection
websocket: Connection
endpoint: string
}
current: WalletAdapter | undefined
providerUrl: string
tokenAccounts: ProgramAccount<TokenAccount>[]
mints: { [pubkey: string]: MintAccount }
set: (x: any) => void
actions: any
}
const useWalletStore = create<WalletStore>((set, get) => ({
connected: false,
connection: {
cluster: CLUSTER,
current: DEFAULT_CONNECTION,
websocket: WEBSOCKET_CONNECTION,
endpoint: ENDPOINT.url,
},
current: null,
providerUrl: null,
tokenAccounts: [],
mints: {},
actions: {
async fetchWalletTokenAccounts() {
const connection = get().connection.current
const connected = get().connected
const wallet = get().current
const walletOwner = wallet?.publicKey
const set = get().set
if (connected && walletOwner) {
const ownedTokenAccounts = await getOwnedTokenAccounts(
connection,
walletOwner
)
set((state) => {
state.tokenAccounts = ownedTokenAccounts
})
} else {
set((state) => {
state.tokenAccounts = []
})
}
},
async fetchWalletMints() {
const connection = get().connection.current
const connected = get().connected
const tokenAccounts = get().tokenAccounts
const set = get().set
if (connected) {
const fetchMints = tokenAccounts.map((a) =>
getMint(connection, a.account.mint)
)
const mintResults = await Promise.all(fetchMints)
const newMints: { [pubkey: string]: MintAccount } = {}
mintResults.forEach(
(m) => (newMints[m.publicKey.toBase58()] = m.account)
)
set((state) => {
state.mints = newMints
})
} else {
set((state) => {
state.mints = {}
})
}
},
},
set: (fn) => set(produce(fn)),
}))
export default useWalletStore

View File

@ -2,6 +2,104 @@
@tailwind components;
@tailwind utilities;
@font-face {
font-family: 'TT Mono';
src: url('/fonts/TT_Commons_Pro_Mono_Regular.woff2') format('woff2');
}
@font-face {
font-family: 'TT Commons Expanded';
src: url('/fonts/TT_Commons_Pro_Expanded_DemiBold.woff2') format('woff2');
}
@font-face {
font-family: 'TT Commons';
font-weight: normal;
src: url('/fonts/TT_Commons_Pro_Regular.woff2') format('woff2');
}
@font-face {
font-family: 'TT Commons';
font-weight: medium;
src: url('/fonts/TT_Commons_Pro_Medium.woff2') format('woff2');
}
@font-face {
font-family: 'TT Commons';
font-weight: bold;
src: url('/fonts/TT_Commons_Pro_DemiBold.woff2') format('woff2');
}
/* Reset */
html,
body,
p,
ol,
ul,
li,
dl,
dt,
dd,
blockquote,
figure,
fieldset,
legend,
textarea,
pre,
iframe,
hr,
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 0;
padding: 0;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-size: 100%;
font-weight: normal;
}
ul {
list-style: none;
}
button,
input,
select {
margin: 0;
}
html {
box-sizing: border-box;
}
*,
*::before,
*::after {
box-sizing: inherit;
}
img,
video {
height: auto;
max-width: 100%;
}
iframe {
border: 0;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
td,
th {
padding: 0;
}
/* Theme */
:root {
@ -49,6 +147,66 @@
--fgd-4: theme('colors.mango-theme["fgd-4"]');
}
/* Base */
body {
@apply font-body text-sm;
}
button {
@apply tracking-wider focus:outline-none;
}
svg {
@apply transition duration-500 ease-out;
}
.default-transition {
@apply transition duration-300 ease-out;
}
.page-x-padding {
@apply px-6 md:px-12 lg:px-20;
}
/* Type */
h1,
h2,
h3,
h4 {
@apply font-display text-th-fgd-1;
}
h1 {
@apply text-5xl sm:text-6xl lg:text-7xl;
}
h2 {
@apply text-3xl md:text-4xl lg:text-5xl;
}
h3 {
@apply text-xl lg:text-2xl;
}
h4 {
@apply text-base;
}
p {
@apply tracking-wider text-th-fgd-3 text-base xl:text-lg;
}
a {
@apply tracking-wider text-base lg:text-lg;
}
.font-mono {
-webkit-font-feature-settings: 'zero' 1;
font-feature-settings: 'zero' 1;
}
@layer utilities {
.animation-delay-2000 {
animation-delay: 2s;

View File

@ -11,9 +11,10 @@ module.exports = {
darkMode: false,
theme: {
fontFamily: {
sans: ['Lato', 'sans-serif'],
display: ['TT Commons Expanded, sans-serif'],
body: 'TT Commons, sans-serif',
mono: ['TT Mono, mono'],
},
screens: {
xs: '240px',
// => @media (min-width: 340px) { ... }
@ -132,16 +133,17 @@ module.exports = {
'fgd-4': '#878787',
},
'mango-theme': {
yellow: '#F2C94C',
red: { DEFAULT: '#E54033', dark: '#C7251A' },
// yellow: '#603BCF',
yellow: 'hsl(45, 86%, 62%)',
red: { DEFAULT: '#E54033', dark: '#603BCF' },
green: { DEFAULT: '#AFD803', dark: '#91B503' },
'bkg-1': '#141026',
'bkg-1': '#1C1924',
'bkg-2': '#1D1832',
'bkg-3': '#252238',
'fgd-1': '#F0EDFF',
'fgd-2': '#FCFCFF',
'fgd-2': '#ddd',
'fgd-3': '#B9B5CE',
'fgd-4': '#2F2C45',
'fgd-4': '#5A5775',
},
'th-bkg-1': 'var(--bkg-1)',
'th-bkg-2': 'var(--bkg-2)',

View File

@ -12,7 +12,8 @@
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve"
"jsx": "preserve",
"incremental": true
},
"exclude": ["node_modules", ".next", "out"],
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.js"]

1
tsconfig.tsbuildinfo Normal file

File diff suppressed because one or more lines are too long

View File

@ -6,10 +6,8 @@ export function notify(newNotification: {
description?: string
txid?: string
}) {
const {
notifications,
set: setNotificationStore,
} = useNotificationStore.getState()
const { notifications, set: setNotificationStore } =
useNotificationStore.getState()
setNotificationStore((state) => {
state.notifications = [

View File

@ -1,2 +0,0 @@
export * from './phantom'
export * from './sollet-extension'

View File

@ -1,102 +0,0 @@
import EventEmitter from 'eventemitter3'
import { PublicKey, Transaction } from '@solana/web3.js'
import { notify } from '../../utils/notifications'
import { WalletAdapter } from '../../@types/types'
type PhantomEvent = 'disconnect' | 'connect'
type PhantomRequestMethod =
| 'connect'
| 'disconnect'
| 'signTransaction'
| 'signAllTransactions'
interface PhantomProvider {
publicKey?: PublicKey
isConnected?: boolean
autoApprove?: boolean
signTransaction: (transaction: Transaction) => Promise<Transaction>
signAllTransactions: (transactions: Transaction[]) => Promise<Transaction[]>
connect: () => Promise<void>
disconnect: () => Promise<void>
on: (event: PhantomEvent, handler: (args: any) => void) => void
request: (method: PhantomRequestMethod, params: any) => Promise<any>
listeners: (event: PhantomEvent) => (() => void)[]
}
export class PhantomWalletAdapter
extends EventEmitter
implements WalletAdapter {
constructor() {
super()
this.connect = this.connect.bind(this)
}
private get _provider(): PhantomProvider | undefined {
if ((window as any)?.solana?.isPhantom) {
return (window as any).solana
}
return undefined
}
private _handleConnect = (...args) => {
this.emit('connect', ...args)
}
private _handleDisconnect = (...args) => {
this.emit('disconnect', ...args)
}
get connected() {
return this._provider?.isConnected || false
}
get autoApprove() {
return this._provider?.autoApprove || false
}
async signAllTransactions(
transactions: Transaction[]
): Promise<Transaction[]> {
if (!this._provider) {
return transactions
}
return this._provider.signAllTransactions(transactions)
}
get publicKey() {
return this._provider?.publicKey
}
async signTransaction(transaction: Transaction) {
if (!this._provider) {
return transaction
}
return this._provider.signTransaction(transaction)
}
connect() {
if (!this._provider) {
window.open('https://phantom.app/', '_blank')
notify({
message: 'Connection Error',
description: 'Please install Phantom wallet and then reload this page.',
})
return
}
if (!this._provider.listeners('connect').length) {
this._provider?.on('connect', this._handleConnect)
}
if (!this._provider.listeners('disconnect').length) {
this._provider?.on('disconnect', this._handleDisconnect)
}
return this._provider?.connect()
}
disconnect() {
if (this._provider) {
this._provider.disconnect()
}
}
}

View File

@ -1,22 +0,0 @@
import Wallet from '@project-serum/sol-wallet-adapter'
import { notify } from '../../utils/notifications'
export function SolletExtensionAdapter(_, network) {
const sollet = (window as any).sollet
if (sollet) {
return new Wallet(sollet, network)
}
return {
on: () => {
/* do nothing */
},
connect: () => {
notify({
message: 'Sollet Extension Error',
description:
'Please install the Sollet Extension for Chrome and then reload this page.',
})
},
}
}

5582
yarn.lock

File diff suppressed because it is too large Load Diff