import { useEffect, useState, useCallback } from 'react'
import PageBodyContainer from '../components/PageBodyContainer'
import TopBar from '../components/TopBar'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import useMangoStore from '../stores/useMangoStore'
import {
mangoCacheSelector,
mangoGroupConfigSelector,
mangoGroupSelector,
walletSelector,
} from '../stores/selectors'
import Button, { IconButton } from '../components/Button'
import {
abbreviateAddress,
copyToClipboard,
formatUsdValue,
usdFormatter,
} from '../utils'
import { notify } from '../utils/notifications'
import {
getMarketIndexBySymbol,
ReferrerIdRecord,
} from '@blockworks-foundation/mango-client'
import { useTranslation } from 'next-i18next'
import EmptyState from '../components/EmptyState'
import {
CheckIcon,
CurrencyDollarIcon,
DuplicateIcon,
LinkIcon,
} from '@heroicons/react/outline'
import { MngoMonoIcon } from '../components/icons'
import Link from 'next/link'
import { Table, Td, Th, TrBody, TrHead } from '../components/TableElements'
import AccountsModal from '../components/AccountsModal'
import { useViewport } from '../hooks/useViewport'
import { breakpoints } from '../components/TradePageGrid'
import { ExpandableRow } from '../components/TableElements'
import MobileTableHeader from '../components/mobile/MobileTableHeader'
import Input, { Label } from '../components/Input'
import InlineNotification from '../components/InlineNotification'
import useMangoAccount from '../hooks/useMangoAccount'
import { DateDisplay } from '../components/DateDisplay'
export async function getStaticProps({ locale }) {
return {
props: {
...(await serverSideTranslations(locale, ['common', 'referrals'])),
// Will be passed to the page component as props
},
}
}
const ProgramDetails = () => {
const { t } = useTranslation('referrals')
return (
<>
{t('referrals:program-details')}
- {t('referrals:program-details-1')}
- {t('referrals:program-details-2')}
- {t('referrals:program-details-3')}
- {t('referrals:program-details-4')}
>
)
}
export default function Referral() {
const { t } = useTranslation(['common', 'referrals'])
const mangoGroup = useMangoStore(mangoGroupSelector)
const mangoCache = useMangoStore(mangoCacheSelector)
const { mangoAccount } = useMangoAccount()
const groupConfig = useMangoStore(mangoGroupConfigSelector)
const wallet = useMangoStore(walletSelector)
const connected = useMangoStore((s) => s.wallet.connected)
const actions = useMangoStore((s) => s.actions)
const referralHistory = useMangoStore((s) => s.referrals.history)
const referralTotalAmount = useMangoStore((s) => s.referrals.total)
const hasReferrals = referralHistory.length > 0
const [customRefLinkInput, setCustomRefLinkInput] = useState('')
const [existingCustomRefLinks, setexistingCustomRefLinks] = useState<
ReferrerIdRecord[]
>([])
const [hasCopied, setHasCopied] = useState(null)
const [showAccountsModal, setShowAccountsModal] = useState(false)
const [loading, setLoading] = useState(false)
const [inputError, setInputError] = useState('')
const { width } = useViewport()
const isMobile = width ? width < breakpoints.sm : false
const fetchCustomReferralLinks = useCallback(async () => {
setLoading(true)
const mangoClient = useMangoStore.getState().connection.client
const referrerIds = await mangoClient.getReferrerIdsForMangoAccount(
mangoAccount
)
setexistingCustomRefLinks(referrerIds)
setLoading(false)
}, [mangoAccount])
useEffect(() => {
if (mangoAccount) {
fetchCustomReferralLinks()
}
}, [mangoAccount])
useEffect(() => {
let timer
if (hasCopied) {
timer = setTimeout(() => setHasCopied(null), 1000)
}
return () => {
clearTimeout(timer)
}
}, [hasCopied])
useEffect(() => {
if (mangoAccount) {
actions.loadReferralData()
}
}, [mangoAccount])
const onChangeRefIdInput = (value) => {
const id = value.replace(/ /g, '')
setCustomRefLinkInput(id)
if (id.length > 32) {
setInputError(t('referrals:too-long-error'))
} else {
setInputError('')
}
}
const validateRefIdInput = () => {
if (customRefLinkInput.length >= 33) {
setInputError(t('referrals:too-long-error'))
}
if (customRefLinkInput.length === 0) {
setInputError(t('referrals:enter-referral-id'))
}
}
const submitRefLink = async () => {
let encodedRefLink: string
try {
encodedRefLink = encodeURIComponent(customRefLinkInput)
} catch (e) {
notify({
type: 'error',
title: 'Invalid custom referral link',
})
}
if (!inputError) {
try {
const mangoClient = useMangoStore.getState().connection.client
const txid = await mangoClient.registerReferrerId(
mangoGroup,
mangoAccount,
wallet,
encodedRefLink
)
notify({
txid,
title: t('referrals:link-created'),
})
fetchCustomReferralLinks()
} catch (e) {
notify({
type: 'error',
title: t('referrals:link-not-created'),
description: e.message,
txid: e.txid,
})
}
} else return
}
const handleCopyLink = (link, index) => {
copyToClipboard(link)
setHasCopied(index)
}
const mngoIndex = getMarketIndexBySymbol(groupConfig, 'MNGO')
const hasRequiredMngo =
mangoGroup && mangoAccount
? mangoAccount
.getUiDeposit(
mangoCache.rootBankCache[mngoIndex],
mangoGroup,
mngoIndex
)
.toNumber() >= 10000
: false
const hasCustomRefLinks =
existingCustomRefLinks && existingCustomRefLinks.length > 0
return (
{t('referrals:sow-seed')}
{connected ? (
mangoAccount ? (
<>
{hasReferrals ? (
{t('referrals:your-referrals')}
{t('referrals:total-earnings')}
{formatUsdValue(referralTotalAmount)}
{t('referrals:total-referrals')}
{referralHistory.length}
) : null}
{hasRequiredMngo ? (
{t('referrals:your-links')}
{!loading ? (
!hasCustomRefLinks ? (
{t('referrlals:link')} |
{t('referrlals:copy-link')} |
{!isMobile ? (
) : null}
{isMobile
? abbreviateAddress(
mangoAccount.publicKey
)
: `https://trade.mango.markets?ref=${mangoAccount.publicKey.toString()}`}
|
handleCopyLink(
`https://trade.mango.markets?ref=${mangoAccount.publicKey.toString()}`,
1
)
}
>
{hasCopied === 1 ? (
) : (
)}
|
) : (
{t('referrals:link')} |
{t('referrals:copy-link')}
|
{existingCustomRefLinks.map(
(customRefs, index) => (
{!isMobile ? (
) : null}
{isMobile
? customRefs.referrerId
: `https://trade.mango.markets?ref=${customRefs.referrerId}`}
|
handleCopyLink(
`https://trade.mango.markets?ref=${customRefs.referrerId}`,
index + 1
)
}
>
{hasCopied === index + 1 ? (
) : (
)}
|
)
)}
)
) : (
)}
) : (
)}
{hasRequiredMngo ? (
{t('referrals:custom-links')}
{t('referrals:custom-links-limit')}
onChangeRefIdInput(e.target.value)}
value={customRefLinkInput}
disabled={existingCustomRefLinks.length === 5}
/>
{inputError ? (
) : null}
) : null}
{referralHistory.length > 0 ? (
{t('referrals:earnings-history')}
{!isMobile ? (
{t('date')} |
{t('referrals:referee')} |
{t('referrals:fee-earned')}
|
{referralHistory.map((ref) => {
const pk = ref.referrer_mango_account
const acct = pk.slice(0, 5) + '…' + pk.slice(-5)
return (
|
{acct}
|
{usdFormatter(ref.referral_fee_accrual, 4)}
|
)
})}
) : (
<>
{referralHistory.map((ref, index) => (
{usdFormatter(ref.referral_fee_accrual, 4)}
}
key={`${ref.referral_fee_accrual + index}`}
panelTemplate={
<>
>
}
/>
))}
>
)}
) : null}
>
) : (
<>
}
onClickButton={() => setShowAccountsModal(true)}
title={t('no-account-found')}
/>
>
)
) : (
<>
}
onClickButton={() => wallet.connect()}
title={t('connect-wallet')}
/>
>
)}
{showAccountsModal ? (
setShowAccountsModal(false)}
isOpen={showAccountsModal}
/>
) : null}
)
}