2022-06-08 18:00:49 +00:00
|
|
|
import clsx from 'clsx'
|
|
|
|
import { useEffect, useState } from 'react'
|
|
|
|
|
2022-09-30 15:27:42 +00:00
|
|
|
import { Contract, CPMMContract } from 'common/contract'
|
2022-06-08 18:00:49 +00:00
|
|
|
import { formatMoney } from 'common/util/format'
|
|
|
|
import { useUser } from 'web/hooks/use-user'
|
2022-07-10 22:03:15 +00:00
|
|
|
import { addLiquidity, withdrawLiquidity } from 'web/lib/firebase/api'
|
2022-09-30 15:27:42 +00:00
|
|
|
import { AmountInput } from 'web/components/amount-input'
|
|
|
|
import { Row } from 'web/components/layout/row'
|
2022-06-08 18:00:49 +00:00
|
|
|
import { useUserLiquidity } from 'web/hooks/use-liquidity'
|
2022-09-30 15:27:42 +00:00
|
|
|
import { Tabs } from 'web/components/layout/tabs'
|
|
|
|
import { NoLabel, YesLabel } from 'web/components/outcome-label'
|
|
|
|
import { Col } from 'web/components/layout/col'
|
2022-06-15 21:34:34 +00:00
|
|
|
import { track } from 'web/lib/service/analytics'
|
2022-09-30 15:27:42 +00:00
|
|
|
import { InfoTooltip } from 'web/components/info-tooltip'
|
2022-09-15 15:12:56 +00:00
|
|
|
import { BETTORS, PRESENT_BET } from 'common/user'
|
2022-09-20 20:57:27 +00:00
|
|
|
import { buildArray } from 'common/util/array'
|
|
|
|
import { useAdmin } from 'web/hooks/use-admin'
|
2022-06-08 18:00:49 +00:00
|
|
|
|
2022-09-30 15:27:42 +00:00
|
|
|
export function LiquidityBountyPanel(props: { contract: Contract }) {
|
2022-06-08 18:00:49 +00:00
|
|
|
const { contract } = props
|
|
|
|
|
2022-09-30 15:27:42 +00:00
|
|
|
const isCPMM = contract.mechanism === 'cpmm-1'
|
2022-06-08 18:00:49 +00:00
|
|
|
const user = useUser()
|
2022-09-30 15:27:42 +00:00
|
|
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
|
|
const lpShares = isCPMM && useUserLiquidity(contract, user?.id ?? '')
|
2022-06-08 18:00:49 +00:00
|
|
|
|
|
|
|
const [showWithdrawal, setShowWithdrawal] = useState(false)
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
if (!showWithdrawal && lpShares && lpShares.YES && lpShares.NO)
|
|
|
|
setShowWithdrawal(true)
|
|
|
|
}, [showWithdrawal, lpShares])
|
|
|
|
|
2022-09-20 20:57:27 +00:00
|
|
|
const isCreator = user?.id === contract.creatorId
|
|
|
|
const isAdmin = useAdmin()
|
|
|
|
|
2022-10-07 21:26:23 +00:00
|
|
|
if (!isCreator && !isAdmin && !showWithdrawal) return <></>
|
|
|
|
|
2022-06-08 18:00:49 +00:00
|
|
|
return (
|
|
|
|
<Tabs
|
2022-09-20 20:57:27 +00:00
|
|
|
tabs={buildArray(
|
2022-09-30 15:27:42 +00:00
|
|
|
(isCreator || isAdmin) &&
|
|
|
|
isCPMM && {
|
|
|
|
title: (isAdmin ? '[Admin] ' : '') + 'Subsidize',
|
|
|
|
content: <AddLiquidityPanel contract={contract} />,
|
|
|
|
},
|
|
|
|
showWithdrawal &&
|
|
|
|
isCPMM && {
|
|
|
|
title: 'Withdraw',
|
|
|
|
content: (
|
|
|
|
<WithdrawLiquidityPanel
|
|
|
|
contract={contract}
|
|
|
|
lpShares={lpShares as { YES: number; NO: number }}
|
|
|
|
/>
|
|
|
|
),
|
|
|
|
},
|
|
|
|
|
|
|
|
(isCreator || isAdmin) &&
|
|
|
|
isCPMM && {
|
|
|
|
title: 'Pool',
|
|
|
|
content: <ViewLiquidityPanel contract={contract} />,
|
|
|
|
}
|
2022-09-20 20:57:27 +00:00
|
|
|
)}
|
2022-06-08 18:00:49 +00:00
|
|
|
/>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
function AddLiquidityPanel(props: { contract: CPMMContract }) {
|
|
|
|
const { contract } = props
|
2022-06-15 21:34:34 +00:00
|
|
|
const { id: contractId, slug } = contract
|
2022-06-08 18:00:49 +00:00
|
|
|
|
|
|
|
const user = useUser()
|
|
|
|
|
|
|
|
const [amount, setAmount] = useState<number | undefined>(undefined)
|
|
|
|
const [error, setError] = useState<string | undefined>(undefined)
|
|
|
|
const [isSuccess, setIsSuccess] = useState(false)
|
|
|
|
const [isLoading, setIsLoading] = useState(false)
|
|
|
|
|
|
|
|
const onAmountChange = (amount: number | undefined) => {
|
|
|
|
setIsSuccess(false)
|
|
|
|
setAmount(amount)
|
|
|
|
|
|
|
|
// Check for errors.
|
|
|
|
if (amount !== undefined) {
|
|
|
|
if (user && user.balance < amount) {
|
|
|
|
setError('Insufficient balance')
|
|
|
|
} else if (amount < 1) {
|
|
|
|
setError('Minimum amount: ' + formatMoney(1))
|
|
|
|
} else {
|
|
|
|
setError(undefined)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const submit = () => {
|
|
|
|
if (!amount) return
|
|
|
|
|
|
|
|
setIsLoading(true)
|
|
|
|
setIsSuccess(false)
|
|
|
|
|
|
|
|
addLiquidity({ amount, contractId })
|
2022-07-08 22:08:17 +00:00
|
|
|
.then((_) => {
|
|
|
|
setIsSuccess(true)
|
|
|
|
setError(undefined)
|
|
|
|
setIsLoading(false)
|
2022-06-08 18:00:49 +00:00
|
|
|
})
|
2022-06-13 04:42:41 +00:00
|
|
|
.catch((_) => setError('Server error'))
|
2022-06-15 21:34:34 +00:00
|
|
|
|
|
|
|
track('add liquidity', { amount, contractId, slug })
|
2022-06-08 18:00:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
2022-08-18 17:12:38 +00:00
|
|
|
<div className="mb-4 text-gray-500">
|
|
|
|
Contribute your M$ to make this market more accurate.{' '}
|
2022-09-15 15:12:56 +00:00
|
|
|
<InfoTooltip
|
|
|
|
text={`More liquidity stabilizes the market, encouraging ${BETTORS} to ${PRESENT_BET}. You can withdraw your subsidy at any time.`}
|
|
|
|
/>
|
2022-06-08 18:00:49 +00:00
|
|
|
</div>
|
|
|
|
|
|
|
|
<Row>
|
|
|
|
<AmountInput
|
|
|
|
amount={amount}
|
|
|
|
onChange={onAmountChange}
|
|
|
|
label="M$"
|
|
|
|
error={error}
|
|
|
|
disabled={isLoading}
|
2022-08-05 07:03:38 +00:00
|
|
|
inputClassName="w-28"
|
2022-06-08 18:00:49 +00:00
|
|
|
/>
|
|
|
|
<button
|
|
|
|
className={clsx('btn btn-primary ml-2', isLoading && 'btn-disabled')}
|
|
|
|
onClick={submit}
|
|
|
|
disabled={isLoading}
|
|
|
|
>
|
|
|
|
Add
|
|
|
|
</button>
|
|
|
|
</Row>
|
|
|
|
|
|
|
|
{isSuccess && amount && (
|
|
|
|
<div>Success! Added {formatMoney(amount)} in liquidity.</div>
|
|
|
|
)}
|
|
|
|
|
|
|
|
{isLoading && <div>Processing...</div>}
|
|
|
|
</>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-06-12 23:14:15 +00:00
|
|
|
function ViewLiquidityPanel(props: { contract: CPMMContract }) {
|
|
|
|
const { contract } = props
|
2022-06-13 04:44:35 +00:00
|
|
|
const { pool } = contract
|
2022-06-12 23:14:15 +00:00
|
|
|
const { YES: yesShares, NO: noShares } = pool
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Col className="mb-4">
|
|
|
|
<div className="mb-4 text-gray-500">
|
|
|
|
The liquidity pool for this market currently contains:
|
|
|
|
</div>
|
|
|
|
<span>
|
|
|
|
{yesShares.toFixed(2)} <YesLabel /> shares
|
|
|
|
</span>
|
|
|
|
|
|
|
|
<span>
|
|
|
|
{noShares.toFixed(2)} <NoLabel /> shares
|
|
|
|
</span>
|
|
|
|
</Col>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-06-08 18:00:49 +00:00
|
|
|
function WithdrawLiquidityPanel(props: {
|
|
|
|
contract: CPMMContract
|
|
|
|
lpShares: { YES: number; NO: number }
|
|
|
|
}) {
|
|
|
|
const { contract, lpShares } = props
|
|
|
|
const { YES: yesShares, NO: noShares } = lpShares
|
|
|
|
|
2022-06-13 04:42:41 +00:00
|
|
|
const [_error, setError] = useState<string | undefined>(undefined)
|
2022-06-08 18:00:49 +00:00
|
|
|
const [isSuccess, setIsSuccess] = useState(false)
|
|
|
|
const [isLoading, setIsLoading] = useState(false)
|
|
|
|
|
|
|
|
const submit = () => {
|
|
|
|
setIsLoading(true)
|
|
|
|
setIsSuccess(false)
|
|
|
|
|
|
|
|
withdrawLiquidity({ contractId: contract.id })
|
2022-06-13 04:42:41 +00:00
|
|
|
.then((_) => {
|
2022-06-08 18:00:49 +00:00
|
|
|
setIsSuccess(true)
|
|
|
|
setError(undefined)
|
|
|
|
setIsLoading(false)
|
|
|
|
})
|
2022-06-13 04:42:41 +00:00
|
|
|
.catch((_) => setError('Server error'))
|
2022-06-15 21:34:34 +00:00
|
|
|
|
|
|
|
track('withdraw liquidity')
|
2022-06-08 18:00:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (isSuccess)
|
|
|
|
return (
|
|
|
|
<div className="text-gray-500">
|
|
|
|
Success! Your liquidity was withdrawn.
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
|
|
|
|
if (!yesShares && !noShares)
|
|
|
|
return (
|
|
|
|
<div className="text-gray-500">
|
|
|
|
You do not have any liquidity positions to withdraw.
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Col>
|
|
|
|
<div className="mb-4 text-gray-500">
|
|
|
|
Your liquidity position is currently:
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<span>
|
|
|
|
{yesShares.toFixed(2)} <YesLabel /> shares
|
|
|
|
</span>
|
|
|
|
|
|
|
|
<span>
|
|
|
|
{noShares.toFixed(2)} <NoLabel /> shares
|
|
|
|
</span>
|
|
|
|
|
|
|
|
<Row className="mt-4 mb-2">
|
|
|
|
<button
|
|
|
|
className={clsx(
|
|
|
|
'btn btn-outline btn-sm ml-2',
|
|
|
|
isLoading && 'btn-disabled'
|
|
|
|
)}
|
|
|
|
onClick={submit}
|
|
|
|
disabled={isLoading}
|
|
|
|
>
|
|
|
|
Withdraw
|
|
|
|
</button>
|
|
|
|
</Row>
|
|
|
|
|
|
|
|
{isLoading && <div>Processing...</div>}
|
|
|
|
</Col>
|
|
|
|
)
|
|
|
|
}
|