fix: implement fund dissolution for insolvent funds after SELL_SHORT trades
Build Images and Deploy / Update-PROD-Stack (push) Successful in 1m21s
Build Images and Deploy / Update-PROD-Stack (push) Successful in 1m21s
This commit is contained in:
@@ -112,7 +112,7 @@ export async function DELETE(
|
||||
const portfolioValue = fund.user.positions.reduce((sum, p) => {
|
||||
const val = p.positionType === 'LONG'
|
||||
? p.shares * p.hashtag.currentPrice
|
||||
: p.avgBuyPrice * p.shares - (p.hashtag.currentPrice - p.avgBuyPrice) * p.shares
|
||||
: (2 * p.avgBuyPrice - p.hashtag.currentPrice) * p.shares
|
||||
return sum + val
|
||||
}, 0)
|
||||
const nav = calcFundNav(fund.user.balance + portfolioValue, fund.sharesOutstanding)
|
||||
|
||||
@@ -2,7 +2,7 @@ import { NextRequest, NextResponse } from 'next/server'
|
||||
import { getServerSession } from 'next-auth'
|
||||
import { authOptions } from '@/lib/auth'
|
||||
import { prisma } from '@/lib/prisma'
|
||||
import { calcTrade } from '@/lib/pricing'
|
||||
import { calcTrade, calcFundNav } from '@/lib/pricing'
|
||||
import { formatCurrency } from '@/lib/utils'
|
||||
import { z } from 'zod'
|
||||
|
||||
@@ -169,5 +169,68 @@ export async function POST(req: NextRequest) {
|
||||
}
|
||||
}
|
||||
|
||||
// If this was a fund's SELL_SHORT and the fund is now insolvent, dissolve it
|
||||
if (type === 'SELL_SHORT' && fundId) {
|
||||
const updatedFundUser = await prisma.user.findUnique({
|
||||
where: { id: user.id },
|
||||
select: { balance: true, fund: { select: { id: true } } },
|
||||
})
|
||||
if (updatedFundUser && updatedFundUser.balance < 0 && updatedFundUser.fund) {
|
||||
await dissolveFund(updatedFundUser.fund.id)
|
||||
return NextResponse.json({ ok: true, dissolved: true })
|
||||
}
|
||||
}
|
||||
|
||||
return NextResponse.json({ ok: true })
|
||||
}
|
||||
|
||||
/**
|
||||
* Dissolves an insolvent fund: pays investors at current mark-to-market NAV
|
||||
* (floored to $0), then deletes the HedgeFund record and its shadow User.
|
||||
* Called automatically when a SELL_SHORT trade pushes a fund balance negative.
|
||||
*/
|
||||
async function dissolveFund(fundId: string) {
|
||||
const fund = await prisma.hedgeFund.findUnique({
|
||||
where: { id: fundId },
|
||||
select: {
|
||||
id: true,
|
||||
userId: true,
|
||||
sharesOutstanding: true,
|
||||
investments: { select: { userId: true, shares: true } },
|
||||
user: {
|
||||
select: {
|
||||
balance: true,
|
||||
positions: {
|
||||
where: { shares: { gt: 0 } },
|
||||
select: {
|
||||
shares: true,
|
||||
avgBuyPrice: true,
|
||||
positionType: true,
|
||||
hashtag: { select: { currentPrice: true } },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
if (!fund) return
|
||||
|
||||
const portfolioValue = fund.user.positions.reduce((sum, p) => {
|
||||
const val =
|
||||
p.positionType === 'LONG'
|
||||
? p.shares * p.hashtag.currentPrice
|
||||
: (2 * p.avgBuyPrice - p.hashtag.currentPrice) * p.shares
|
||||
return sum + val
|
||||
}, 0)
|
||||
const nav = calcFundNav(fund.user.balance + portfolioValue, fund.sharesOutstanding)
|
||||
|
||||
for (const inv of fund.investments) {
|
||||
const payout = Math.max(0, inv.shares * nav)
|
||||
if (payout > 0) {
|
||||
await prisma.user.update({ where: { id: inv.userId }, data: { balance: { increment: payout } } })
|
||||
}
|
||||
}
|
||||
|
||||
await prisma.hedgeFund.delete({ where: { id: fund.id } })
|
||||
await prisma.user.delete({ where: { id: fund.userId } })
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user