manifold/web/components/limit-bets.tsx
James Grugett 80ae551ca9
🧾 Limit orders! (#495)
* Simple limit order UI

* Update bet schema

* Restrict bet panel / bet row to only CPMMBinaryContracts (all binary DPM are resolved)

* Limit orders partway implemented

* Update follow leaderboard copy

* Change cpmm code to take some state instead of whole contract

* Write more of matching algorithm

* Fill in more of placebet

* Use client side contract search for emulator

* More correct matching

* Merge branch 'main' into limit-orders

* Some cleanup

* Listen for unfilled bets in bet panel. Calculate how the probability moves based on open limit orders.

* Simpler switching between bet & limit bet.

* Render your open bets (unfilled limit orders)

* Cancel bet endpoint.

* Fix build error

* Rename open bets to limit bets. Tweak payout calculation

* Limit probability selector to 1-99

* Deduct user balance only on each fill. Store orderAmount of bet. Timestamp of fills.

* Use floating equal to check if have shares

* Add limit order switcher to mobile bet dialog

* Support limit orders on numeric markets

* Allow CORS exception for Vercel deployments

* Remove console.logs

* Update user balance by new bet amount

* Tweak vercel cors

* Try another regexp for vercel cors

* Test another vercel regex

* Slight notifications refactor

* Fix docs edit link (#624)

* Fix docs edit link

* Update github links

* Small groups UX changes

* Groups UX on mobile

* Leaderboards => Rankings on groups

* Unused vars

* create: remove automatic setting of log scale

* Use react-query to cache notifications (#625)

* Use react-query to cache notifications

* Fix imports

* Cleanup

* Limit unseen notifs query

* Catch the bounced query

* Don't use interval

* Unused var

* Avoid flash of page nav

* Give notification question priority & 2 lines

* Right justify timestamps

* Rewording

* Margin

* Simplify error msg

* Be explicit about limit for unseen notifs

* Pass limit > 0

* Remove category filters

* Remove category selector references

* Track notification clicks

* Analyze tab usage

* Bold more on new group chats

* Add API route for listing a bets by user (#567)

* Add API route for getting a user's bets

* Refactor bets API to use /bets

* Update /markets to use zod validation

* Update docs

* Clone missing indexes from firestore

* Minor notif spacing adjustments

* Enable tipping on group chats w/ notif (#629)

* Tweak cors regex for vercel

* Your limit bets

* Implement selling shares

* Merge branch 'main' into limit-orders

* Fix lint

* Move binary search to util file

* Add note that there might be closed form

* Add tooltip to explain limit probability

* Tweak

* Cancel your limit orders if you run out of money

* Don't show amount error in probability input

* Require limit prob to be >= .1% and <= 99.9%

* Fix focus input bug

* Simplify mobile betting dialog

* Move mobile limit bets list into bet dialog.

* Small fixes to existing sell shares client

* Lint

* Refactor useSaveShares to actually read from localStorage, use less bug-prone interface.

* Fix NaN error

* Remove TODO

* Simple bet fill notification

* Tweak wording

* Sort limit bets by limit prob

* Padding on limit bets

* Match header size

Co-authored-by: Ian Philips <iansphilips@gmail.com>
Co-authored-by: ahalekelly <ahalekelly@gmail.com>
Co-authored-by: mantikoros <sgrugett@gmail.com>
Co-authored-by: Ben Congdon <ben@congdon.dev>
Co-authored-by: Austin Chen <akrolsmir@gmail.com>
2022-07-10 13:05:44 -05:00

90 lines
2.5 KiB
TypeScript

import clsx from 'clsx'
import { LimitBet } from 'common/bet'
import { CPMMBinaryContract, PseudoNumericContract } from 'common/contract'
import { getFormattedMappedValue } from 'common/pseudo-numeric'
import { formatMoney, formatPercent } from 'common/util/format'
import { sortBy } from 'lodash'
import { useState } from 'react'
import { cancelBet } from 'web/lib/firebase/api-call'
import { Col } from './layout/col'
import { LoadingIndicator } from './loading-indicator'
import { BinaryOutcomeLabel, PseudoNumericOutcomeLabel } from './outcome-label'
export function LimitBets(props: {
contract: CPMMBinaryContract | PseudoNumericContract
bets: LimitBet[]
className?: string
}) {
const { contract, bets, className } = props
const recentBets = sortBy(
bets,
(bet) => -1 * bet.limitProb,
(bet) => -1 * bet.createdTime
)
return (
<Col
className={clsx(className, 'gap-2 overflow-hidden rounded bg-white py-3')}
>
<div className="px-6 py-3 text-2xl">Your limit bets</div>
<div className="px-4">
<table className="table-compact table w-full rounded text-gray-500">
<tbody>
{recentBets.map((bet) => (
<LimitBet key={bet.id} bet={bet} contract={contract} />
))}
</tbody>
</table>
</div>
</Col>
)
}
function LimitBet(props: {
contract: CPMMBinaryContract | PseudoNumericContract
bet: LimitBet
}) {
const { contract, bet } = props
const { orderAmount, amount, limitProb, outcome } = bet
const isPseudoNumeric = contract.outcomeType === 'PSEUDO_NUMERIC'
const [isCancelling, setIsCancelling] = useState(false)
const onCancel = () => {
cancelBet({ betId: bet.id })
setIsCancelling(true)
}
return (
<tr>
<td>
<div className="pl-2">
{isPseudoNumeric ? (
<PseudoNumericOutcomeLabel outcome={outcome as 'YES' | 'NO'} />
) : (
<BinaryOutcomeLabel outcome={outcome as 'YES' | 'NO'} />
)}
</div>
</td>
<td>{formatMoney(orderAmount - amount)}</td>
<td>
{isPseudoNumeric
? getFormattedMappedValue(contract)(limitProb)
: formatPercent(limitProb)}
</td>
<td>
{isCancelling ? (
<LoadingIndicator />
) : (
<button
className="btn btn-xs btn-outline my-auto normal-case"
onClick={onCancel}
>
Cancel
</button>
)}
</td>
</tr>
)
}