Allow unspecfied outcome as input to sellshares
(#706)
* Allow unspecfied outcome as input to `sellshares` * Fix small details
This commit is contained in:
parent
0b06ded5e5
commit
6901507461
|
@ -599,12 +599,12 @@ $ curl https://manifold.markets/api/v0/market/{marketId}/resolve -X POST \
|
|||
|
||||
### `POST /v0/market/[marketId]/sell`
|
||||
|
||||
Sells some quantity of shares in a market on behalf of the authorized user.
|
||||
Sells some quantity of shares in a binary market on behalf of the authorized user.
|
||||
|
||||
Parameters:
|
||||
|
||||
- `outcome`: Required. One of `YES`, `NO`, or a `number` indicating the numeric
|
||||
bucket ID, depending on the market type.
|
||||
- `outcome`: Optional. One of `YES`, or `NO`. If you leave it off, and you only
|
||||
own one kind of shares, you will sell that kind of shares.
|
||||
- `shares`: Optional. The amount of shares to sell of the outcome given
|
||||
above. If not provided, all the shares you own will be sold.
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { sumBy, uniq } from 'lodash'
|
||||
import { mapValues, groupBy, sumBy, uniq } from 'lodash'
|
||||
import * as admin from 'firebase-admin'
|
||||
import { z } from 'zod'
|
||||
|
||||
|
@ -9,7 +9,7 @@ import { getCpmmSellBetInfo } from '../../common/sell-bet'
|
|||
import { addObjects, removeUndefinedProps } from '../../common/util/object'
|
||||
import { getValues, log } from './utils'
|
||||
import { Bet } from '../../common/bet'
|
||||
import { floatingLesserEqual } from '../../common/util/math'
|
||||
import { floatingEqual, floatingLesserEqual } from '../../common/util/math'
|
||||
import { getUnfilledBetsQuery, updateMakers } from './place-bet'
|
||||
import { FieldValue } from 'firebase-admin/firestore'
|
||||
import { redeemShares } from './redeem-shares'
|
||||
|
@ -17,7 +17,7 @@ import { redeemShares } from './redeem-shares'
|
|||
const bodySchema = z.object({
|
||||
contractId: z.string(),
|
||||
shares: z.number().optional(), // leave it out to sell all shares
|
||||
outcome: z.enum(['YES', 'NO']),
|
||||
outcome: z.enum(['YES', 'NO']).optional(), // leave it out to sell whichever you have
|
||||
})
|
||||
|
||||
export const sellshares = newEndpoint({}, async (req, auth) => {
|
||||
|
@ -46,9 +46,31 @@ export const sellshares = newEndpoint({}, async (req, auth) => {
|
|||
throw new APIError(400, 'Trading is closed.')
|
||||
|
||||
const prevLoanAmount = sumBy(userBets, (bet) => bet.loanAmount ?? 0)
|
||||
const betsByOutcome = groupBy(userBets, (bet) => bet.outcome)
|
||||
const sharesByOutcome = mapValues(betsByOutcome, (bets) =>
|
||||
sumBy(bets, (b) => b.shares)
|
||||
)
|
||||
|
||||
const outcomeBets = userBets.filter((bet) => bet.outcome == outcome)
|
||||
const maxShares = sumBy(outcomeBets, (bet) => bet.shares)
|
||||
let chosenOutcome: 'YES' | 'NO'
|
||||
if (outcome != null) {
|
||||
chosenOutcome = outcome
|
||||
} else {
|
||||
const nonzeroShares = Object.entries(sharesByOutcome).filter(
|
||||
([_k, v]) => !floatingEqual(0, v)
|
||||
)
|
||||
if (nonzeroShares.length == 0) {
|
||||
throw new APIError(400, "You don't own any shares in this market.")
|
||||
}
|
||||
if (nonzeroShares.length > 1) {
|
||||
throw new APIError(
|
||||
400,
|
||||
`You own multiple kinds of shares, but did not specify which to sell.`
|
||||
)
|
||||
}
|
||||
chosenOutcome = nonzeroShares[0][0] as 'YES' | 'NO'
|
||||
}
|
||||
|
||||
const maxShares = sharesByOutcome[chosenOutcome]
|
||||
const sharesToSell = shares ?? maxShares
|
||||
|
||||
if (!floatingLesserEqual(sharesToSell, maxShares))
|
||||
|
@ -63,7 +85,7 @@ export const sellshares = newEndpoint({}, async (req, auth) => {
|
|||
|
||||
const { newBet, newPool, newP, fees, makers } = getCpmmSellBetInfo(
|
||||
soldShares,
|
||||
outcome,
|
||||
chosenOutcome,
|
||||
contract,
|
||||
prevLoanAmount,
|
||||
unfilledBets
|
||||
|
|
Loading…
Reference in New Issue
Block a user