track fees on contract and bets; change fee schedule for cpmm markets; only pay out creator fees at resolution

This commit is contained in:
mantikoros 2022-03-10 14:55:23 -06:00
parent a0833b4764
commit 6b30ed4513
17 changed files with 322 additions and 189 deletions

View File

@ -1,3 +1,5 @@
import { Fees } from './fees'
export type Bet = {
id: string
userId: string
@ -6,7 +8,7 @@ export type Bet = {
amount: number // bet size; negative if SELL bet
loanAmount?: number
outcome: string
shares: number // dynamic parimutuel pool weight; negative if SELL bet
shares: number // dynamic parimutuel pool weight or fixed ; negative if SELL bet
probBefore: number
probAfter: number
@ -17,6 +19,8 @@ export type Bet = {
// TODO: add sale time?
}
fees: Fees
isSold?: boolean // true if this BUY bet has been sold
isAnte?: boolean
isLiquidityProvision?: boolean

View File

@ -1,8 +1,8 @@
import * as _ from 'lodash'
import { Bet } from './bet'
import { deductFixedFees } from './calculate-fixed-payouts'
import { Binary, CPMM, FullContract } from './contract'
import { CREATOR_FEE } from './fees'
import { CREATOR_FEE, Fees, LIQUIDITY_FEE, PLATFORM_FEE } from './fees'
export function getCpmmProbability(pool: { [outcome: string]: number }) {
// For binary contracts only.
@ -35,8 +35,6 @@ function calculateCpmmShares(
return shares
}
export const CPMM_LIQUIDITY_FEE = 0.02
export function getCpmmLiquidityFee(
contract: FullContract<CPMM, Binary>,
bet: number,
@ -44,9 +42,16 @@ export function getCpmmLiquidityFee(
) {
const p = getCpmmProbability(contract.pool)
const betP = outcome === 'YES' ? 1 - p : p
const fee = CPMM_LIQUIDITY_FEE * betP * bet
const remainingBet = bet - fee
return { fee, remainingBet }
const liquidityFee = LIQUIDITY_FEE * betP * bet
const platformFee = PLATFORM_FEE * betP * bet
const creatorFee = CREATOR_FEE * betP * bet
const fees: Fees = { liquidityFee, platformFee, creatorFee }
const totalFees = liquidityFee + platformFee + creatorFee
const remainingBet = bet - totalFees
return { remainingBet, fees }
}
export function calculateCpmmSharesAfterFee(
@ -66,7 +71,7 @@ export function calculateCpmmPurchase(
outcome: string
) {
const { pool } = contract
const { remainingBet } = getCpmmLiquidityFee(contract, bet, outcome)
const { remainingBet, fees } = getCpmmLiquidityFee(contract, bet, outcome)
const shares = calculateCpmmShares(pool, remainingBet, outcome)
const { YES: y, NO: n } = pool
@ -78,7 +83,7 @@ export function calculateCpmmPurchase(
const newPool = { YES: newY, NO: newN }
return { shares, newPool }
return { shares, newPool, fees }
}
export function calculateCpmmShareValue(
@ -103,7 +108,7 @@ export function calculateCpmmSale(
const rawSaleValue = calculateCpmmShareValue(contract, shares, outcome)
const { fee, remainingBet: saleValue } = getCpmmLiquidityFee(
const { fees, remainingBet: saleValue } = getCpmmLiquidityFee(
contract,
rawSaleValue,
outcome === 'YES' ? 'NO' : 'YES'
@ -112,6 +117,8 @@ export function calculateCpmmSale(
const { pool } = contract
const { YES: y, NO: n } = pool
const { liquidityFee: fee } = fees
const [newY, newN] =
outcome === 'YES'
? [y + shares - saleValue + fee, n - saleValue + fee]
@ -119,11 +126,7 @@ export function calculateCpmmSale(
const newPool = { YES: newY, NO: newN }
const profit = saleValue - bet.amount
const creatorFee = CREATOR_FEE * Math.max(0, profit)
const saleAmount = deductFixedFees(bet.amount, saleValue)
return { saleValue, newPool, creatorFee, saleAmount }
return { saleValue, newPool, fees }
}
export function getCpmmProbabilityAfterSale(

View File

@ -1,7 +1,7 @@
import * as _ from 'lodash'
import { Bet } from './bet'
import { Binary, DPM, FullContract } from './contract'
import { FEES } from './fees'
import { DPM_FEES } from './fees'
export function getDpmProbability(totalShares: { [outcome: string]: number }) {
// For binary contracts only.
@ -176,7 +176,7 @@ export function calculateStandardDpmPayout(
const winnings = (shares / total) * poolTotal
// profit can be negative if using phantom shares
return amount + (1 - FEES) * Math.max(0, winnings - amount)
return amount + (1 - DPM_FEES) * Math.max(0, winnings - amount)
}
export function calculateDpmPayoutAfterCorrectBet(
@ -268,7 +268,7 @@ export function resolvedDpmPayout(contract: FullContract<DPM, any>, bet: Bet) {
export const deductDpmFees = (betAmount: number, winnings: number) => {
return winnings > betAmount
? betAmount + (1 - FEES) * (winnings - betAmount)
? betAmount + (1 - DPM_FEES) * (winnings - betAmount)
: winnings
}

View File

@ -1,7 +1,6 @@
import { Bet } from './bet'
import { getProbability } from './calculate'
import { Binary, FixedPayouts, FullContract } from './contract'
import { FEES } from './fees'
export function calculateFixedPayout(
contract: FullContract<FixedPayouts, Binary>,
@ -19,9 +18,9 @@ export function calculateFixedCancelPayout(bet: Bet) {
}
export function calculateStandardFixedPayout(bet: Bet, outcome: string) {
const { amount, outcome: betOutcome, shares } = bet
const { outcome: betOutcome, shares } = bet
if (betOutcome !== outcome) return 0
return deductFixedFees(amount, shares)
return shares
}
function calculateFixedMktPayout(
@ -34,17 +33,9 @@ function calculateFixedMktPayout(
? resolutionProbability
: getProbability(contract)
const { outcome, amount, shares } = bet
const { outcome, shares } = bet
const betP = outcome === 'YES' ? p : 1 - p
const winnings = betP * shares
return deductFixedFees(amount, winnings)
}
export const deductFixedFees = (betAmount: number, winnings: number) => {
return winnings
// return winnings > betAmount
// ? betAmount + (1 - FEES) * (winnings - betAmount)
// : winnings
return betP * shares
}

View File

@ -1,6 +1,6 @@
import { Bet } from './bet'
import {
calculateCpmmShareValue,
calculateCpmmSale,
getCpmmProbability,
getCpmmOutcomeProbabilityAfterBet,
getCpmmProbabilityAfterSale,
@ -16,10 +16,7 @@ import {
getDpmOutcomeProbabilityAfterBet,
getDpmProbabilityAfterSale,
} from './calculate-dpm'
import {
calculateFixedPayout,
deductFixedFees,
} from './calculate-fixed-payouts'
import { calculateFixedPayout } from './calculate-fixed-payouts'
import { Binary, Contract, CPMM, DPM, FullContract } from './contract'
export function getProbability(contract: FullContract<DPM | CPMM, Binary>) {
@ -72,16 +69,13 @@ export function calculateShares(
export function calculateSaleAmount(contract: Contract, bet: Bet) {
return contract.mechanism === 'cpmm-1' && contract.outcomeType === 'BINARY'
? deductFixedFees(
bet.amount,
calculateCpmmShareValue(contract, bet.shares, bet.outcome)
)
? calculateCpmmSale(contract, bet)
: calculateDpmSaleAmount(contract, bet)
}
export function calculatePayoutAfterCorrectBet(contract: Contract, bet: Bet) {
return contract.mechanism === 'cpmm-1'
? deductFixedFees(bet.amount, bet.shares)
? bet.shares
: calculateDpmPayoutAfterCorrectBet(contract, bet)
}

View File

@ -1,4 +1,5 @@
import { Answer } from './answer'
import { Fees } from './fees'
export type FullContract<
M extends DPM | CPMM,
@ -30,6 +31,8 @@ export type FullContract<
volume24Hours: number
volume7Days: number
collectedFees: Fees
} & M &
T

View File

@ -1,4 +1,19 @@
export const PLATFORM_FEE = 0.01
export const CREATOR_FEE = 0.04
export const PLATFORM_FEE = 0.005
export const CREATOR_FEE = 0.02
export const LIQUIDITY_FEE = 0.02
export const FEES = PLATFORM_FEE + CREATOR_FEE
export const DPM_PLATFORM_FEE = 2 * PLATFORM_FEE
export const DPM_CREATOR_FEE = 2 * CREATOR_FEE
export const DPM_FEES = DPM_PLATFORM_FEE + DPM_CREATOR_FEE
export type Fees = {
creatorFee: number
platformFee: number
liquidityFee: number
}
export const noFees: Fees = {
creatorFee: 0,
platformFee: 0,
liquidityFee: 0,
}

View File

@ -16,6 +16,7 @@ import {
Multi,
} from './contract'
import { User } from './user'
import { noFees } from './fees'
export const getNewBinaryCpmmBetInfo = (
user: User,
@ -25,7 +26,11 @@ export const getNewBinaryCpmmBetInfo = (
loanAmount: number,
newBetId: string
) => {
const { shares, newPool } = calculateCpmmPurchase(contract, amount, outcome)
const { shares, newPool, fees } = calculateCpmmPurchase(
contract,
amount,
outcome
)
const newBalance = user.balance - (amount - loanAmount)
@ -39,13 +44,14 @@ export const getNewBinaryCpmmBetInfo = (
amount,
shares,
outcome,
fees,
loanAmount,
probBefore,
probAfter,
createdTime: Date.now(),
}
return { newBet, newPool, newBalance }
return { newBet, newPool, newBalance, fees }
}
export const getNewBinaryDpmBetInfo = (
@ -93,6 +99,7 @@ export const getNewBinaryDpmBetInfo = (
probBefore,
probAfter,
createdTime: Date.now(),
fees: noFees,
}
const newBalance = user.balance - (amount - loanAmount)
@ -135,6 +142,7 @@ export const getNewMultiBetInfo = (
probBefore,
probAfter,
createdTime: Date.now(),
fees: noFees,
}
const newBalance = user.balance - (amount - loanAmount)

View File

@ -35,7 +35,7 @@ export function getNewContract(
? getBinaryCpmmProps(initialProb, ante) // getBinaryDpmProps(initialProb, ante)
: getFreeAnswerProps(ante)
const contract = removeUndefinedProps({
const contract: Contract = removeUndefinedProps({
id,
slug,
...propsByOutcomeType,
@ -57,6 +57,12 @@ export function getNewContract(
volume24Hours: 0,
volume7Days: 0,
collectedFees: {
creatorFee: 0,
liquidityFee: 0,
platformFee: 0,
},
})
return contract as Contract

View File

@ -3,7 +3,14 @@ import * as _ from 'lodash'
import { Bet } from './bet'
import { deductDpmFees, getDpmProbability } from './calculate-dpm'
import { DPM, FreeResponse, FullContract, Multi } from './contract'
import { CREATOR_FEE, FEES } from './fees'
import {
DPM_CREATOR_FEE,
DPM_FEES,
DPM_PLATFORM_FEE,
Fees,
noFees,
} from './fees'
import { addObjects } from './util/object'
export const getDpmCancelPayouts = (
contract: FullContract<DPM, any>,
@ -15,10 +22,12 @@ export const getDpmCancelPayouts = (
const betSum = _.sumBy(bets, (b) => b.amount)
return bets.map((bet) => ({
const payouts = bets.map((bet) => ({
userId: bet.userId,
payout: (bet.amount / betSum) * poolTotal,
}))
return [payouts, contract.collectedFees ?? noFees]
}
export const getDpmStandardPayouts = (
@ -36,12 +45,21 @@ export const getDpmStandardPayouts = (
const profit = winnings - amount
// profit can be negative if using phantom shares
const payout = amount + (1 - FEES) * Math.max(0, profit)
const payout = amount + (1 - DPM_FEES) * Math.max(0, profit)
return { userId, profit, payout }
})
const profits = _.sumBy(payouts, (po) => Math.max(0, po.profit))
const creatorPayout = CREATOR_FEE * profits
const creatorFee = DPM_CREATOR_FEE * profits
const platformFee = DPM_PLATFORM_FEE * profits
const finalFees: Fees = {
creatorFee,
platformFee,
liquidityFee: 0,
}
const fees = addObjects<Fees>(finalFees, contract.collectedFees ?? {})
console.log(
'resolved',
@ -51,12 +69,14 @@ export const getDpmStandardPayouts = (
'profits',
profits,
'creator fee',
creatorPayout
creatorFee
)
return payouts
const totalPayouts = payouts
.map(({ userId, payout }) => ({ userId, payout }))
.concat([{ userId: contract.creatorId, payout: creatorPayout }]) // add creator fee
.concat([{ userId: contract.creatorId, payout: creatorFee }]) // add creator fee
return [totalPayouts, fees]
}
export const getDpmMktPayouts = (
@ -84,7 +104,17 @@ export const getDpmMktPayouts = (
})
const profits = _.sumBy(payouts, (po) => Math.max(0, po.profit))
const creatorPayout = CREATOR_FEE * profits
const creatorFee = DPM_CREATOR_FEE * profits
const platformFee = DPM_PLATFORM_FEE * profits
const finalFees: Fees = {
creatorFee,
platformFee,
liquidityFee: 0,
}
const fees = addObjects<Fees>(finalFees, contract.collectedFees ?? {})
console.log(
'resolved MKT',
@ -93,13 +123,14 @@ export const getDpmMktPayouts = (
pool,
'profits',
profits,
'creator fee',
creatorPayout
'creator fee'
)
return payouts
const totalPayouts = payouts
.map(({ userId, payout }) => ({ userId, payout }))
.concat([{ userId: contract.creatorId, payout: creatorPayout }]) // add creator fee
.concat([{ userId: contract.creatorId, payout: creatorFee }]) // add creator fee
return [totalPayouts, fees]
}
export const getPayoutsMultiOutcome = (
@ -122,12 +153,22 @@ export const getPayoutsMultiOutcome = (
const winnings = (shares / sharesByOutcome[outcome]) * prob * poolTotal
const profit = winnings - amount
const payout = amount + (1 - FEES) * Math.max(0, profit)
const payout = amount + (1 - DPM_FEES) * Math.max(0, profit)
return { userId, profit, payout }
})
const profits = _.sumBy(payouts, (po) => po.profit)
const creatorPayout = CREATOR_FEE * profits
const creatorFee = DPM_CREATOR_FEE * profits
const platformFee = DPM_PLATFORM_FEE * profits
const finalFees: Fees = {
creatorFee,
platformFee,
liquidityFee: 0,
}
const fees = addObjects<Fees>(finalFees, contract.collectedFees ?? {})
console.log(
'resolved',
@ -137,10 +178,12 @@ export const getPayoutsMultiOutcome = (
'profits',
profits,
'creator fee',
creatorPayout
creatorFee
)
return payouts
const totalPayouts = payouts
.map(({ userId, payout }) => ({ userId, payout }))
.concat([{ userId: contract.creatorId, payout: creatorPayout }]) // add creator fee
.concat([{ userId: contract.creatorId, payout: creatorFee }]) // add creator fee
return [totalPayouts, fees]
}

View File

@ -2,13 +2,10 @@ import * as _ from 'lodash'
import { Bet } from './bet'
import { getProbability } from './calculate'
import { deductFixedFees } from './calculate-fixed-payouts'
import { Binary, CPMM, FixedPayouts, FullContract } from './contract'
import { CREATOR_FEE } from './fees'
import { LiquidityProvision } from './liquidity-provision'
export const getFixedCancelPayouts = (
contract: FullContract<FixedPayouts, Binary>,
bets: Bet[],
liquidities: LiquidityProvision[]
) => {
@ -34,23 +31,20 @@ export const getStandardFixedPayouts = (
) => {
const winningBets = bets.filter((bet) => bet.outcome === outcome)
const payouts = winningBets.map(({ userId, amount, shares }) => {
const winnings = shares
const profit = winnings - amount
const payout = deductFixedFees(amount, winnings)
return { userId, profit, payout }
})
const payouts = winningBets.map(({ userId, shares }) => ({
userId,
payout: shares,
}))
const profits = _.sumBy(payouts, (po) => Math.max(0, po.profit))
const creatorPayout = 0 // CREATOR_FEE * profits
const creatorPayout = contract.collectedFees.creatorFee
console.log(
'resolved',
outcome,
'pool',
contract.pool,
'profits',
profits,
contract.pool[outcome],
'payouts',
_.sum(payouts),
'creator fee',
creatorPayout
)
@ -88,24 +82,20 @@ export const getMktFixedPayouts = (
? getProbability(contract)
: resolutionProbability
const payouts = bets.map(({ userId, outcome, amount, shares }) => {
const payouts = bets.map(({ userId, outcome, shares }) => {
const betP = outcome === 'YES' ? p : 1 - p
const winnings = betP * shares
const profit = winnings - amount
const payout = deductFixedFees(amount, winnings)
return { userId, profit, payout }
return { userId, payout: betP * shares }
})
const profits = _.sumBy(payouts, (po) => Math.max(0, po.profit))
const creatorPayout = 0 // CREATOR_FEE * profits
const creatorPayout = contract.collectedFees.creatorFee
console.log(
'resolved MKT',
'resolved PROB',
p,
'pool',
contract.pool,
'profits',
profits,
p * contract.pool.YES + (1 - p) * contract.pool.NO,
'payouts',
_.sum(payouts),
'creator fee',
creatorPayout
)

View File

@ -1,7 +1,16 @@
import * as _ from 'lodash'
import { Bet } from './bet'
import { Contract, DPM, FreeResponse, FullContract, Multi } from './contract'
import {
Binary,
Contract,
DPM,
FixedPayouts,
FreeResponse,
FullContract,
Multi,
} from './contract'
import { Fees } from './fees'
import { LiquidityProvision } from './liquidity-provision'
import {
getDpmCancelPayouts,
@ -15,57 +24,12 @@ import {
getStandardFixedPayouts,
} from './payouts-fixed'
export const getPayouts = (
outcome:
| string
| {
[outcome: string]: number
},
contract: Contract,
allBets: Bet[],
liquidities: LiquidityProvision[],
resolutionProbability?: number
) => {
const bets = allBets.filter((b) => !b.isSold && !b.sale)
if (contract.mechanism === 'cpmm-1' && contract.outcomeType === 'BINARY') {
switch (outcome) {
case 'YES':
case 'NO':
return getStandardFixedPayouts(outcome, contract, bets, liquidities)
case 'MKT':
return getMktFixedPayouts(
contract,
bets,
liquidities,
resolutionProbability
)
case 'CANCEL':
return getFixedCancelPayouts(contract, allBets, liquidities)
}
}
switch (outcome) {
case 'YES':
case 'NO':
return getDpmStandardPayouts(outcome, contract, bets)
case 'MKT':
return getDpmMktPayouts(contract, bets, resolutionProbability)
case 'CANCEL':
return getDpmCancelPayouts(contract, bets)
default:
// Multi outcome.
return getPayoutsMultiOutcome(
outcome as {
[outcome: string]: number
},
contract as FullContract<DPM, Multi | FreeResponse>,
bets
)
}
export type Payout = {
userId: string
payout: number
}
export const getLoanPayouts = (bets: Bet[]) => {
export const getLoanPayouts = (bets: Bet[]): Payout[] => {
const betsWithLoans = bets.filter((bet) => bet.loanAmount)
const betsByUser = _.groupBy(betsWithLoans, (bet) => bet.userId)
const loansByUser = _.mapValues(betsByUser, (bets) =>
@ -73,3 +37,92 @@ export const getLoanPayouts = (bets: Bet[]) => {
)
return _.toPairs(loansByUser).map(([userId, payout]) => ({ userId, payout }))
}
export const getPayouts = (
outcome: string,
resolutions: {
[outcome: string]: number
},
contract: Contract,
bets: Bet[],
liquidities: LiquidityProvision[],
resolutionProbability?: number
): [Payout[], Fees] => {
if (contract.mechanism === 'cpmm-1' && contract.outcomeType === 'BINARY') {
const payouts = getFixedPayouts(
outcome,
contract,
bets,
liquidities,
resolutionProbability
)
return [payouts, contract.collectedFees]
}
return getDpmPayouts(
outcome,
resolutions,
contract,
bets,
resolutionProbability
)
}
export const getFixedPayouts = (
outcome: string,
contract: FullContract<FixedPayouts, Binary>,
bets: Bet[],
liquidities: LiquidityProvision[],
resolutionProbability?: number
): Payout[] => {
switch (outcome) {
case 'YES':
case 'NO':
return getStandardFixedPayouts(outcome, contract, bets, liquidities)
case 'MKT':
return getMktFixedPayouts(
contract,
bets,
liquidities,
resolutionProbability
)
default:
case 'CANCEL':
return getFixedCancelPayouts(bets, liquidities)
}
}
export const getDpmPayouts = (
outcome: string,
resolutions: {
[outcome: string]: number
},
contract: Contract,
bets: Bet[],
resolutionProbability?: number
) => {
const openBets = bets.filter((b) => !b.isSold && !b.sale)
switch (outcome) {
case 'YES':
case 'NO':
return getDpmStandardPayouts(outcome, contract, openBets) as [
Payout[],
Fees
]
case 'MKT':
return getDpmMktPayouts(contract, openBets, resolutionProbability) as [
Payout[],
Fees
]
case 'CANCEL':
return getDpmCancelPayouts(contract, openBets) as [Payout[], Fees]
default:
// Multi outcome.
return getPayoutsMultiOutcome(
resolutions,
contract as FullContract<DPM, Multi | FreeResponse>,
openBets
) as [Payout[], Fees]
}
}

View File

@ -6,7 +6,7 @@ import {
} from './calculate-dpm'
import { calculateCpmmSale, getCpmmProbability } from './calculate-cpmm'
import { Binary, DPM, CPMM, FullContract } from './contract'
import { CREATOR_FEE } from './fees'
import { DPM_CREATOR_FEE, DPM_PLATFORM_FEE, Fees } from './fees'
import { User } from './user'
export const getSellBetInfo = (
@ -33,7 +33,15 @@ export const getSellBetInfo = (
const probAfter = getDpmProbability(newTotalShares)
const profit = adjShareValue - amount
const creatorFee = CREATOR_FEE * Math.max(0, profit)
const creatorFee = DPM_CREATOR_FEE * Math.max(0, profit)
const platformFee = DPM_PLATFORM_FEE * Math.max(0, profit)
const fees: Fees = {
creatorFee,
platformFee,
liquidityFee: 0,
}
const saleAmount = deductDpmFees(amount, adjShareValue)
console.log(
@ -60,6 +68,7 @@ export const getSellBetInfo = (
amount: saleAmount,
betId,
},
fees,
}
const newBalance = user.balance + saleAmount - (loanAmount ?? 0)
@ -70,7 +79,7 @@ export const getSellBetInfo = (
newTotalShares,
newTotalBets,
newBalance,
creatorFee,
fees,
}
}
@ -83,10 +92,7 @@ export const getCpmmSellBetInfo = (
const { pool } = contract
const { id: betId, amount, shares, outcome } = bet
const { saleValue, newPool, creatorFee, saleAmount } = calculateCpmmSale(
contract,
bet
)
const { saleValue, newPool, fees } = calculateCpmmSale(contract, bet)
const probBefore = getCpmmProbability(pool)
const probAfter = getCpmmProbability(newPool)
@ -96,9 +102,9 @@ export const getCpmmSellBetInfo = (
amount,
outcome,
'for M$',
saleAmount,
saleValue,
'creator fee: M$',
creatorFee
fees.creatorFee
)
const newBet: Bet = {
@ -112,17 +118,18 @@ export const getCpmmSellBetInfo = (
probAfter,
createdTime: Date.now(),
sale: {
amount: saleAmount,
amount: saleValue,
betId,
},
fees,
}
const newBalance = user.balance + saleAmount
const newBalance = user.balance + saleValue
return {
newBet,
newPool,
newBalance,
creatorFee,
fees,
}
}

View File

@ -1,3 +1,5 @@
import * as _ from 'lodash'
export const removeUndefinedProps = <T>(obj: T): T => {
let newObj: any = {}
@ -7,3 +9,17 @@ export const removeUndefinedProps = <T>(obj: T): T => {
return newObj
}
export const addObjects = <T extends { [key: string]: number }>(
obj1: T,
obj2: T
) => {
const keys = _.union(Object.keys(obj1), Object.keys(obj2))
const newObj = {} as any
for (let key of keys) {
newObj[key] = (obj1[key] ?? 0) + (obj2[key] ?? 0)
}
return newObj as T
}

View File

@ -9,9 +9,10 @@ import {
getNewMultiBetInfo,
getLoanAmount,
} from '../../common/new-bet'
import { removeUndefinedProps } from '../../common/util/object'
import { addObjects, removeUndefinedProps } from '../../common/util/object'
import { Bet } from '../../common/bet'
import { redeemShares } from './redeem-shares'
import { Fees } from '../../common/fees'
export const placeBet = functions.runWith({ minInstances: 1 }).https.onCall(
async (
@ -48,7 +49,7 @@ export const placeBet = functions.runWith({ minInstances: 1 }).https.onCall(
return { status: 'error', message: 'Invalid contract' }
const contract = contractSnap.data() as Contract
const { closeTime, outcomeType, mechanism } = contract
const { closeTime, outcomeType, mechanism, collectedFees } = contract
if (closeTime && Date.now() > closeTime)
return { status: 'error', message: 'Trading is closed' }
@ -73,7 +74,14 @@ export const placeBet = functions.runWith({ minInstances: 1 }).https.onCall(
.collection(`contracts/${contractId}/bets`)
.doc()
const { newBet, newPool, newTotalShares, newTotalBets, newBalance } =
const {
newBet,
newPool,
newTotalShares,
newTotalBets,
newBalance,
fees,
} =
outcomeType === 'BINARY'
? mechanism === 'dpm-2'
? getNewBinaryDpmBetInfo(
@ -109,6 +117,7 @@ export const placeBet = functions.runWith({ minInstances: 1 }).https.onCall(
pool: newPool,
totalShares: newTotalShares,
totalBets: newTotalBets,
collectedFees: addObjects<Fees>(fees ?? {}, collectedFees ?? {}),
})
)

View File

@ -5,7 +5,7 @@ import * as _ from 'lodash'
import { Contract } from '../../common/contract'
import { User } from '../../common/user'
import { Bet } from '../../common/bet'
import { getUser, payUser } from './utils'
import { getUser, isProd, payUser } from './utils'
import { sendMarketResolutionEmail } from './emails'
import { getLoanPayouts, getPayouts } from '../../common/payouts'
import { removeUndefinedProps } from '../../common/util/object'
@ -75,19 +75,6 @@ export const resolveMarket = functions
? Math.min(closeTime, resolutionTime)
: closeTime
await contractDoc.update(
removeUndefinedProps({
isResolved: true,
resolution: outcome,
resolutionTime,
closeTime: newCloseTime,
resolutionProbability,
resolutions,
})
)
console.log('contract ', contractId, 'resolved to:', outcome)
const betsSnap = await firestore
.collection(`contracts/${contractId}/bets`)
.get()
@ -102,18 +89,33 @@ export const resolveMarket = functions
(doc) => doc.data() as LiquidityProvision
)
const payouts = getPayouts(
resolutions ?? outcome,
const [payouts, collectedFees] = getPayouts(
outcome,
resolutions ?? {},
contract,
bets,
liquidities,
resolutionProbability
)
await contractDoc.update(
removeUndefinedProps({
isResolved: true,
resolution: outcome,
resolutionTime,
closeTime: newCloseTime,
resolutionProbability,
resolutions,
collectedFees,
})
)
console.log('contract ', contractId, 'resolved to:', outcome)
const openBets = bets.filter((b) => !b.isSold && !b.sale)
const loanPayouts = getLoanPayouts(openBets)
console.log('payouts:', payouts)
if (!isProd) console.log('payouts:', payouts)
const groups = _.groupBy(
[...payouts, ...loanPayouts],

View File

@ -5,7 +5,8 @@ import { Contract } from '../../common/contract'
import { User } from '../../common/user'
import { Bet } from '../../common/bet'
import { getCpmmSellBetInfo, getSellBetInfo } from '../../common/sell-bet'
import { removeUndefinedProps } from '../../common/util/object'
import { addObjects, removeUndefinedProps } from '../../common/util/object'
import { Fees } from '../../common/fees'
export const sellBet = functions.runWith({ minInstances: 1 }).https.onCall(
async (
@ -34,7 +35,7 @@ export const sellBet = functions.runWith({ minInstances: 1 }).https.onCall(
return { status: 'error', message: 'Invalid contract' }
const contract = contractSnap.data() as Contract
const { closeTime, mechanism } = contract
const { closeTime, mechanism, collectedFees } = contract
if (closeTime && Date.now() > closeTime)
return { status: 'error', message: 'Trading is closed' }
@ -55,7 +56,7 @@ export const sellBet = functions.runWith({ minInstances: 1 }).https.onCall(
newTotalShares,
newTotalBets,
newBalance,
creatorFee,
fees,
} =
mechanism === 'dpm-2'
? getSellBetInfo(user, bet, contract, newBetDoc.id)
@ -66,20 +67,7 @@ export const sellBet = functions.runWith({ minInstances: 1 }).https.onCall(
newBetDoc.id
) as any)
if (contract.creatorId === userId) {
transaction.update(userDoc, { balance: newBalance + creatorFee })
} else {
const creatorDoc = firestore.doc(`users/${contract.creatorId}`)
const creatorSnap = await transaction.get(creatorDoc)
if (creatorSnap.exists) {
const creator = creatorSnap.data() as User
const creatorNewBalance = creator.balance + creatorFee
transaction.update(creatorDoc, { balance: creatorNewBalance })
}
transaction.update(userDoc, { balance: newBalance })
}
transaction.update(userDoc, { balance: newBalance })
transaction.update(betDoc, { isSold: true })
transaction.create(newBetDoc, newBet)
@ -89,6 +77,7 @@ export const sellBet = functions.runWith({ minInstances: 1 }).https.onCall(
pool: newPool,
totalShares: newTotalShares,
totalBets: newTotalBets,
collectedFees: addObjects<Fees>(fees ?? {}, collectedFees ?? {}),
})
)