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`
|
### `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:
|
Parameters:
|
||||||
|
|
||||||
- `outcome`: Required. One of `YES`, `NO`, or a `number` indicating the numeric
|
- `outcome`: Optional. One of `YES`, or `NO`. If you leave it off, and you only
|
||||||
bucket ID, depending on the market type.
|
own one kind of shares, you will sell that kind of shares.
|
||||||
- `shares`: Optional. The amount of shares to sell of the outcome given
|
- `shares`: Optional. The amount of shares to sell of the outcome given
|
||||||
above. If not provided, all the shares you own will be sold.
|
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 * as admin from 'firebase-admin'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import { getCpmmSellBetInfo } from '../../common/sell-bet'
|
||||||
import { addObjects, removeUndefinedProps } from '../../common/util/object'
|
import { addObjects, removeUndefinedProps } from '../../common/util/object'
|
||||||
import { getValues, log } from './utils'
|
import { getValues, log } from './utils'
|
||||||
import { Bet } from '../../common/bet'
|
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 { getUnfilledBetsQuery, updateMakers } from './place-bet'
|
||||||
import { FieldValue } from 'firebase-admin/firestore'
|
import { FieldValue } from 'firebase-admin/firestore'
|
||||||
import { redeemShares } from './redeem-shares'
|
import { redeemShares } from './redeem-shares'
|
||||||
|
@ -17,7 +17,7 @@ import { redeemShares } from './redeem-shares'
|
||||||
const bodySchema = z.object({
|
const bodySchema = z.object({
|
||||||
contractId: z.string(),
|
contractId: z.string(),
|
||||||
shares: z.number().optional(), // leave it out to sell all shares
|
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) => {
|
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.')
|
throw new APIError(400, 'Trading is closed.')
|
||||||
|
|
||||||
const prevLoanAmount = sumBy(userBets, (bet) => bet.loanAmount ?? 0)
|
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)
|
let chosenOutcome: 'YES' | 'NO'
|
||||||
const maxShares = sumBy(outcomeBets, (bet) => bet.shares)
|
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
|
const sharesToSell = shares ?? maxShares
|
||||||
|
|
||||||
if (!floatingLesserEqual(sharesToSell, maxShares))
|
if (!floatingLesserEqual(sharesToSell, maxShares))
|
||||||
|
@ -63,7 +85,7 @@ export const sellshares = newEndpoint({}, async (req, auth) => {
|
||||||
|
|
||||||
const { newBet, newPool, newP, fees, makers } = getCpmmSellBetInfo(
|
const { newBet, newPool, newP, fees, makers } = getCpmmSellBetInfo(
|
||||||
soldShares,
|
soldShares,
|
||||||
outcome,
|
chosenOutcome,
|
||||||
contract,
|
contract,
|
||||||
prevLoanAmount,
|
prevLoanAmount,
|
||||||
unfilledBets
|
unfilledBets
|
||||||
|
|
Loading…
Reference in New Issue
Block a user