Implement "sell all shares" functionality in sellshares
and expose API (#696)
* Change `sellshares` to be able to sell all shares * Sell all shares properly on bet panel UI * Add API route for selling shares, document
This commit is contained in:
parent
ad46a60c4f
commit
b506e96548
|
@ -579,6 +579,26 @@ $ 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.
|
||||
|
||||
Parameters:
|
||||
|
||||
- `outcome`: Required. One of `YES`, `NO`, or a `number` indicating the numeric
|
||||
bucket ID, depending on the market type.
|
||||
- `shares`: Optional. The amount of shares to sell of the outcome given
|
||||
above. If not provided, all the shares you own will be sold.
|
||||
|
||||
Example request:
|
||||
|
||||
```
|
||||
$ curl https://manifold.markets/api/v0/market/{marketId}/sell -X POST \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Authorization: Key {...}' \
|
||||
--data-raw '{"outcome": "YES", "shares": 10}'
|
||||
```
|
||||
|
||||
### `GET /v0/bets`
|
||||
|
||||
Gets a list of bets, ordered by creation date descending.
|
||||
|
|
|
@ -16,7 +16,7 @@ import { redeemShares } from './redeem-shares'
|
|||
|
||||
const bodySchema = z.object({
|
||||
contractId: z.string(),
|
||||
shares: z.number(),
|
||||
shares: z.number().optional(), // leave it out to sell all shares
|
||||
outcome: z.enum(['YES', 'NO']),
|
||||
})
|
||||
|
||||
|
@ -49,11 +49,12 @@ export const sellshares = newEndpoint({}, async (req, auth) => {
|
|||
|
||||
const outcomeBets = userBets.filter((bet) => bet.outcome == outcome)
|
||||
const maxShares = sumBy(outcomeBets, (bet) => bet.shares)
|
||||
const sharesToSell = shares ?? maxShares
|
||||
|
||||
if (!floatingLesserEqual(shares, maxShares))
|
||||
if (!floatingLesserEqual(sharesToSell, maxShares))
|
||||
throw new APIError(400, `You can only sell up to ${maxShares} shares.`)
|
||||
|
||||
const soldShares = Math.min(shares, maxShares)
|
||||
const soldShares = Math.min(sharesToSell, maxShares)
|
||||
|
||||
const unfilledBetsSnap = await transaction.get(
|
||||
getUnfilledBetsQuery(contractDoc)
|
||||
|
|
|
@ -771,7 +771,9 @@ export function SellPanel(props: {
|
|||
const betDisabled = isSubmitting || !amount || error
|
||||
|
||||
// Sell all shares if remaining shares would be < 1
|
||||
const sellQuantity = amount === Math.floor(shares) ? shares : amount
|
||||
const isSellingAllShares = amount === Math.floor(shares)
|
||||
|
||||
const sellQuantity = isSellingAllShares ? shares : amount
|
||||
|
||||
async function submitSell() {
|
||||
if (!user || !amount) return
|
||||
|
@ -780,7 +782,7 @@ export function SellPanel(props: {
|
|||
setIsSubmitting(true)
|
||||
|
||||
await sellShares({
|
||||
shares: sellQuantity,
|
||||
shares: isSellingAllShares ? undefined : amount,
|
||||
outcome: sharesOutcome,
|
||||
contractId: contract.id,
|
||||
})
|
||||
|
|
28
web/pages/api/v0/market/[id]/sell.ts
Normal file
28
web/pages/api/v0/market/[id]/sell.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
import { NextApiRequest, NextApiResponse } from 'next'
|
||||
import {
|
||||
CORS_ORIGIN_MANIFOLD,
|
||||
CORS_ORIGIN_LOCALHOST,
|
||||
} from 'common/envs/constants'
|
||||
import { applyCorsHeaders } from 'web/lib/api/cors'
|
||||
import { fetchBackend, forwardResponse } from 'web/lib/api/proxy'
|
||||
|
||||
export const config = { api: { bodyParser: true } }
|
||||
|
||||
export default async function route(req: NextApiRequest, res: NextApiResponse) {
|
||||
await applyCorsHeaders(req, res, {
|
||||
origin: [CORS_ORIGIN_MANIFOLD, CORS_ORIGIN_LOCALHOST],
|
||||
methods: 'POST',
|
||||
})
|
||||
|
||||
const { id } = req.query
|
||||
const contractId = id as string
|
||||
|
||||
if (req.body) req.body.contractId = contractId
|
||||
try {
|
||||
const backendRes = await fetchBackend(req, 'sellshares')
|
||||
await forwardResponse(res, backendRes)
|
||||
} catch (err) {
|
||||
console.error('Error talking to cloud function: ', err)
|
||||
res.status(500).json({ message: 'Error communicating with backend.' })
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user