Refund unused bounties

This commit is contained in:
Ian Philips 2022-09-28 13:12:13 -04:00
parent 13e8c16928
commit 03957f0c22
3 changed files with 78 additions and 9 deletions

View File

@ -8,6 +8,7 @@ type AnyTxnType =
| UniqueBettorBonus
| BettingStreakBonus
| CancelUniqueBettorBonus
| CommentBountyRefund
type SourceType = 'USER' | 'CONTRACT' | 'CHARITY' | 'BANK'
export type Txn<T extends AnyTxnType = AnyTxnType> = {
@ -32,6 +33,7 @@ export type Txn<T extends AnyTxnType = AnyTxnType> = {
| 'BETTING_STREAK_BONUS'
| 'CANCEL_UNIQUE_BETTOR_BONUS'
| 'COMMENT_BOUNTY'
| 'REFUND_COMMENT_BOUNTY'
// Any extra data
data?: { [key: string]: any }
@ -118,6 +120,15 @@ type CommentBountyWithdrawal = {
}
}
type CommentBountyRefund = {
fromType: 'BANK'
toType: 'USER'
category: 'REFUND_COMMENT_BOUNTY'
data: {
contractId: string
}
}
export type DonationTxn = Txn & Donation
export type TipTxn = Txn & Tip
export type ManalinkTxn = Txn & Manalink

View File

@ -1,7 +1,11 @@
import * as functions from 'firebase-functions'
import { getUser } from './utils'
import { getUser, getValues, log } from './utils'
import { createCommentOrAnswerOrUpdatedContractNotification } from './create-notification'
import { Contract } from '../../common/contract'
import { Txn } from '../../common/txn'
import { partition, sortBy } from 'lodash'
import { runTxn, TxnData } from './transact'
import * as admin from 'firebase-admin'
export const onUpdateContract = functions.firestore
.document('contracts/{contractId}')
@ -14,9 +18,63 @@ export const onUpdateContract = functions.firestore
const previousValue = change.before.data() as Contract
// Resolution is handled in resolve-market.ts
if (!previousValue.isResolved && contract.isResolved) return
// Refund extra unused comment bounties
if (!previousValue.isResolved && contract.isResolved) {
const bountiesLeft = contract.openCommentBounties ?? 0
if (bountiesLeft <= 0) return
const outstandingCommentBounties = await getValues<Txn>(
firestore.collection('txns').where('category', '==', 'COMMENT_BOUNTY')
)
const commentBountiesOnThisContract = sortBy(
outstandingCommentBounties.filter(
(bounty) => bounty.data?.contractId === contract.id
),
(bounty) => bounty.createdTime
)
const [toBank, fromBank] = partition(
commentBountiesOnThisContract,
(bounty) => bounty.toType === 'BANK'
)
if (toBank.length <= fromBank.length) return
const refunds = toBank.slice(fromBank.length)
await Promise.all(
refunds.map(async (extraBountyTxn) => {
const result = await firestore.runTransaction(async (trans) => {
const bonusTxn: TxnData = {
fromId: extraBountyTxn.toId,
fromType: 'BANK',
toId: extraBountyTxn.fromId,
toType: 'USER',
amount: extraBountyTxn.amount,
token: 'M$',
category: 'REFUND_COMMENT_BOUNTY',
data: {
contractId: contract.id,
},
}
return await runTxn(trans, bonusTxn)
})
if (result.status != 'success' || !result.txn) {
log(
`Couldn't refund bonus for user: ${extraBountyTxn.fromId} - status:`,
result.status
)
log('message:', result.message)
} else {
log(
`Refund bonus txn for user: ${extraBountyTxn.fromId} completed:`,
result.txn?.id
)
}
})
)
return
}
if (
previousValue.closeTime !== contract.closeTime ||
previousValue.question !== contract.question
@ -42,3 +100,4 @@ export const onUpdateContract = functions.firestore
)
}
})
const firestore = admin.firestore()

View File

@ -36,8 +36,6 @@ export function LiquidityBountyPanel(props: { contract: Contract }) {
const isCreator = user?.id === contract.creatorId
const isAdmin = useAdmin()
if (!showWithdrawal && !isAdmin && !isCreator) return <></>
return (
<Tabs
tabs={buildArray(
@ -61,10 +59,11 @@ export function LiquidityBountyPanel(props: { contract: Contract }) {
),
},
isCPMM && {
title: 'Pool',
content: <ViewLiquidityPanel contract={contract} />,
}
(isCreator || isAdmin) &&
isCPMM && {
title: 'Pool',
content: <ViewLiquidityPanel contract={contract} />,
}
)}
/>
)