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-10-10 18:01:57 +00:00
import { AlertBox } from '../alert-box'
import { Spacer } from '../layout/spacer'
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
2022-10-10 18:01:57 +00:00
text = { ` More liquidity stabilizes the market, encouraging ${ BETTORS } to ${ PRESENT_BET } . ` }
2022-09-15 15:12:56 +00:00
/ >
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-10-10 18:01:57 +00:00
< Spacer h = { 2 } / >
< AlertBox
title = "Withdrawals ending"
text = "Manifold is moving to a new system for handling subsidization. As part of this process, liquidity withdrawals will be disabled shortly. Feel free to withdraw any outstanding liquidity you've added now."
/ >
2022-06-08 18:00:49 +00:00
< / >
)
}
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 >
)
}