track fees on contract and bets; change fee schedule for cpmm markets; only pay out creator fees at resolution
This commit is contained in:
parent
a0833b4764
commit
6b30ed4513
|
@ -1,3 +1,5 @@
|
||||||
|
import { Fees } from './fees'
|
||||||
|
|
||||||
export type Bet = {
|
export type Bet = {
|
||||||
id: string
|
id: string
|
||||||
userId: string
|
userId: string
|
||||||
|
@ -6,7 +8,7 @@ export type Bet = {
|
||||||
amount: number // bet size; negative if SELL bet
|
amount: number // bet size; negative if SELL bet
|
||||||
loanAmount?: number
|
loanAmount?: number
|
||||||
outcome: string
|
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
|
probBefore: number
|
||||||
probAfter: number
|
probAfter: number
|
||||||
|
@ -17,6 +19,8 @@ export type Bet = {
|
||||||
// TODO: add sale time?
|
// TODO: add sale time?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fees: Fees
|
||||||
|
|
||||||
isSold?: boolean // true if this BUY bet has been sold
|
isSold?: boolean // true if this BUY bet has been sold
|
||||||
isAnte?: boolean
|
isAnte?: boolean
|
||||||
isLiquidityProvision?: boolean
|
isLiquidityProvision?: boolean
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import * as _ from 'lodash'
|
import * as _ from 'lodash'
|
||||||
|
|
||||||
import { Bet } from './bet'
|
import { Bet } from './bet'
|
||||||
import { deductFixedFees } from './calculate-fixed-payouts'
|
|
||||||
import { Binary, CPMM, FullContract } from './contract'
|
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 }) {
|
export function getCpmmProbability(pool: { [outcome: string]: number }) {
|
||||||
// For binary contracts only.
|
// For binary contracts only.
|
||||||
|
@ -35,8 +35,6 @@ function calculateCpmmShares(
|
||||||
return shares
|
return shares
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CPMM_LIQUIDITY_FEE = 0.02
|
|
||||||
|
|
||||||
export function getCpmmLiquidityFee(
|
export function getCpmmLiquidityFee(
|
||||||
contract: FullContract<CPMM, Binary>,
|
contract: FullContract<CPMM, Binary>,
|
||||||
bet: number,
|
bet: number,
|
||||||
|
@ -44,9 +42,16 @@ export function getCpmmLiquidityFee(
|
||||||
) {
|
) {
|
||||||
const p = getCpmmProbability(contract.pool)
|
const p = getCpmmProbability(contract.pool)
|
||||||
const betP = outcome === 'YES' ? 1 - p : p
|
const betP = outcome === 'YES' ? 1 - p : p
|
||||||
const fee = CPMM_LIQUIDITY_FEE * betP * bet
|
|
||||||
const remainingBet = bet - fee
|
const liquidityFee = LIQUIDITY_FEE * betP * bet
|
||||||
return { fee, remainingBet }
|
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(
|
export function calculateCpmmSharesAfterFee(
|
||||||
|
@ -66,7 +71,7 @@ export function calculateCpmmPurchase(
|
||||||
outcome: string
|
outcome: string
|
||||||
) {
|
) {
|
||||||
const { pool } = contract
|
const { pool } = contract
|
||||||
const { remainingBet } = getCpmmLiquidityFee(contract, bet, outcome)
|
const { remainingBet, fees } = getCpmmLiquidityFee(contract, bet, outcome)
|
||||||
|
|
||||||
const shares = calculateCpmmShares(pool, remainingBet, outcome)
|
const shares = calculateCpmmShares(pool, remainingBet, outcome)
|
||||||
const { YES: y, NO: n } = pool
|
const { YES: y, NO: n } = pool
|
||||||
|
@ -78,7 +83,7 @@ export function calculateCpmmPurchase(
|
||||||
|
|
||||||
const newPool = { YES: newY, NO: newN }
|
const newPool = { YES: newY, NO: newN }
|
||||||
|
|
||||||
return { shares, newPool }
|
return { shares, newPool, fees }
|
||||||
}
|
}
|
||||||
|
|
||||||
export function calculateCpmmShareValue(
|
export function calculateCpmmShareValue(
|
||||||
|
@ -103,7 +108,7 @@ export function calculateCpmmSale(
|
||||||
|
|
||||||
const rawSaleValue = calculateCpmmShareValue(contract, shares, outcome)
|
const rawSaleValue = calculateCpmmShareValue(contract, shares, outcome)
|
||||||
|
|
||||||
const { fee, remainingBet: saleValue } = getCpmmLiquidityFee(
|
const { fees, remainingBet: saleValue } = getCpmmLiquidityFee(
|
||||||
contract,
|
contract,
|
||||||
rawSaleValue,
|
rawSaleValue,
|
||||||
outcome === 'YES' ? 'NO' : 'YES'
|
outcome === 'YES' ? 'NO' : 'YES'
|
||||||
|
@ -112,6 +117,8 @@ export function calculateCpmmSale(
|
||||||
const { pool } = contract
|
const { pool } = contract
|
||||||
const { YES: y, NO: n } = pool
|
const { YES: y, NO: n } = pool
|
||||||
|
|
||||||
|
const { liquidityFee: fee } = fees
|
||||||
|
|
||||||
const [newY, newN] =
|
const [newY, newN] =
|
||||||
outcome === 'YES'
|
outcome === 'YES'
|
||||||
? [y + shares - saleValue + fee, n - saleValue + fee]
|
? [y + shares - saleValue + fee, n - saleValue + fee]
|
||||||
|
@ -119,11 +126,7 @@ export function calculateCpmmSale(
|
||||||
|
|
||||||
const newPool = { YES: newY, NO: newN }
|
const newPool = { YES: newY, NO: newN }
|
||||||
|
|
||||||
const profit = saleValue - bet.amount
|
return { saleValue, newPool, fees }
|
||||||
const creatorFee = CREATOR_FEE * Math.max(0, profit)
|
|
||||||
const saleAmount = deductFixedFees(bet.amount, saleValue)
|
|
||||||
|
|
||||||
return { saleValue, newPool, creatorFee, saleAmount }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCpmmProbabilityAfterSale(
|
export function getCpmmProbabilityAfterSale(
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import * as _ from 'lodash'
|
import * as _ from 'lodash'
|
||||||
import { Bet } from './bet'
|
import { Bet } from './bet'
|
||||||
import { Binary, DPM, FullContract } from './contract'
|
import { Binary, DPM, FullContract } from './contract'
|
||||||
import { FEES } from './fees'
|
import { DPM_FEES } from './fees'
|
||||||
|
|
||||||
export function getDpmProbability(totalShares: { [outcome: string]: number }) {
|
export function getDpmProbability(totalShares: { [outcome: string]: number }) {
|
||||||
// For binary contracts only.
|
// For binary contracts only.
|
||||||
|
@ -176,7 +176,7 @@ export function calculateStandardDpmPayout(
|
||||||
|
|
||||||
const winnings = (shares / total) * poolTotal
|
const winnings = (shares / total) * poolTotal
|
||||||
// profit can be negative if using phantom shares
|
// 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(
|
export function calculateDpmPayoutAfterCorrectBet(
|
||||||
|
@ -268,7 +268,7 @@ export function resolvedDpmPayout(contract: FullContract<DPM, any>, bet: Bet) {
|
||||||
|
|
||||||
export const deductDpmFees = (betAmount: number, winnings: number) => {
|
export const deductDpmFees = (betAmount: number, winnings: number) => {
|
||||||
return winnings > betAmount
|
return winnings > betAmount
|
||||||
? betAmount + (1 - FEES) * (winnings - betAmount)
|
? betAmount + (1 - DPM_FEES) * (winnings - betAmount)
|
||||||
: winnings
|
: winnings
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { Bet } from './bet'
|
import { Bet } from './bet'
|
||||||
import { getProbability } from './calculate'
|
import { getProbability } from './calculate'
|
||||||
import { Binary, FixedPayouts, FullContract } from './contract'
|
import { Binary, FixedPayouts, FullContract } from './contract'
|
||||||
import { FEES } from './fees'
|
|
||||||
|
|
||||||
export function calculateFixedPayout(
|
export function calculateFixedPayout(
|
||||||
contract: FullContract<FixedPayouts, Binary>,
|
contract: FullContract<FixedPayouts, Binary>,
|
||||||
|
@ -19,9 +18,9 @@ export function calculateFixedCancelPayout(bet: Bet) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function calculateStandardFixedPayout(bet: Bet, outcome: string) {
|
export function calculateStandardFixedPayout(bet: Bet, outcome: string) {
|
||||||
const { amount, outcome: betOutcome, shares } = bet
|
const { outcome: betOutcome, shares } = bet
|
||||||
if (betOutcome !== outcome) return 0
|
if (betOutcome !== outcome) return 0
|
||||||
return deductFixedFees(amount, shares)
|
return shares
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculateFixedMktPayout(
|
function calculateFixedMktPayout(
|
||||||
|
@ -34,17 +33,9 @@ function calculateFixedMktPayout(
|
||||||
? resolutionProbability
|
? resolutionProbability
|
||||||
: getProbability(contract)
|
: getProbability(contract)
|
||||||
|
|
||||||
const { outcome, amount, shares } = bet
|
const { outcome, shares } = bet
|
||||||
|
|
||||||
const betP = outcome === 'YES' ? p : 1 - p
|
const betP = outcome === 'YES' ? p : 1 - p
|
||||||
const winnings = betP * shares
|
|
||||||
|
|
||||||
return deductFixedFees(amount, winnings)
|
return betP * shares
|
||||||
}
|
|
||||||
|
|
||||||
export const deductFixedFees = (betAmount: number, winnings: number) => {
|
|
||||||
return winnings
|
|
||||||
// return winnings > betAmount
|
|
||||||
// ? betAmount + (1 - FEES) * (winnings - betAmount)
|
|
||||||
// : winnings
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Bet } from './bet'
|
import { Bet } from './bet'
|
||||||
import {
|
import {
|
||||||
calculateCpmmShareValue,
|
calculateCpmmSale,
|
||||||
getCpmmProbability,
|
getCpmmProbability,
|
||||||
getCpmmOutcomeProbabilityAfterBet,
|
getCpmmOutcomeProbabilityAfterBet,
|
||||||
getCpmmProbabilityAfterSale,
|
getCpmmProbabilityAfterSale,
|
||||||
|
@ -16,10 +16,7 @@ import {
|
||||||
getDpmOutcomeProbabilityAfterBet,
|
getDpmOutcomeProbabilityAfterBet,
|
||||||
getDpmProbabilityAfterSale,
|
getDpmProbabilityAfterSale,
|
||||||
} from './calculate-dpm'
|
} from './calculate-dpm'
|
||||||
import {
|
import { calculateFixedPayout } from './calculate-fixed-payouts'
|
||||||
calculateFixedPayout,
|
|
||||||
deductFixedFees,
|
|
||||||
} from './calculate-fixed-payouts'
|
|
||||||
import { Binary, Contract, CPMM, DPM, FullContract } from './contract'
|
import { Binary, Contract, CPMM, DPM, FullContract } from './contract'
|
||||||
|
|
||||||
export function getProbability(contract: FullContract<DPM | CPMM, Binary>) {
|
export function getProbability(contract: FullContract<DPM | CPMM, Binary>) {
|
||||||
|
@ -72,16 +69,13 @@ export function calculateShares(
|
||||||
|
|
||||||
export function calculateSaleAmount(contract: Contract, bet: Bet) {
|
export function calculateSaleAmount(contract: Contract, bet: Bet) {
|
||||||
return contract.mechanism === 'cpmm-1' && contract.outcomeType === 'BINARY'
|
return contract.mechanism === 'cpmm-1' && contract.outcomeType === 'BINARY'
|
||||||
? deductFixedFees(
|
? calculateCpmmSale(contract, bet)
|
||||||
bet.amount,
|
|
||||||
calculateCpmmShareValue(contract, bet.shares, bet.outcome)
|
|
||||||
)
|
|
||||||
: calculateDpmSaleAmount(contract, bet)
|
: calculateDpmSaleAmount(contract, bet)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function calculatePayoutAfterCorrectBet(contract: Contract, bet: Bet) {
|
export function calculatePayoutAfterCorrectBet(contract: Contract, bet: Bet) {
|
||||||
return contract.mechanism === 'cpmm-1'
|
return contract.mechanism === 'cpmm-1'
|
||||||
? deductFixedFees(bet.amount, bet.shares)
|
? bet.shares
|
||||||
: calculateDpmPayoutAfterCorrectBet(contract, bet)
|
: calculateDpmPayoutAfterCorrectBet(contract, bet)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { Answer } from './answer'
|
import { Answer } from './answer'
|
||||||
|
import { Fees } from './fees'
|
||||||
|
|
||||||
export type FullContract<
|
export type FullContract<
|
||||||
M extends DPM | CPMM,
|
M extends DPM | CPMM,
|
||||||
|
@ -30,6 +31,8 @@ export type FullContract<
|
||||||
|
|
||||||
volume24Hours: number
|
volume24Hours: number
|
||||||
volume7Days: number
|
volume7Days: number
|
||||||
|
|
||||||
|
collectedFees: Fees
|
||||||
} & M &
|
} & M &
|
||||||
T
|
T
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,19 @@
|
||||||
export const PLATFORM_FEE = 0.01
|
export const PLATFORM_FEE = 0.005
|
||||||
export const CREATOR_FEE = 0.04
|
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,
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import {
|
||||||
Multi,
|
Multi,
|
||||||
} from './contract'
|
} from './contract'
|
||||||
import { User } from './user'
|
import { User } from './user'
|
||||||
|
import { noFees } from './fees'
|
||||||
|
|
||||||
export const getNewBinaryCpmmBetInfo = (
|
export const getNewBinaryCpmmBetInfo = (
|
||||||
user: User,
|
user: User,
|
||||||
|
@ -25,7 +26,11 @@ export const getNewBinaryCpmmBetInfo = (
|
||||||
loanAmount: number,
|
loanAmount: number,
|
||||||
newBetId: string
|
newBetId: string
|
||||||
) => {
|
) => {
|
||||||
const { shares, newPool } = calculateCpmmPurchase(contract, amount, outcome)
|
const { shares, newPool, fees } = calculateCpmmPurchase(
|
||||||
|
contract,
|
||||||
|
amount,
|
||||||
|
outcome
|
||||||
|
)
|
||||||
|
|
||||||
const newBalance = user.balance - (amount - loanAmount)
|
const newBalance = user.balance - (amount - loanAmount)
|
||||||
|
|
||||||
|
@ -39,13 +44,14 @@ export const getNewBinaryCpmmBetInfo = (
|
||||||
amount,
|
amount,
|
||||||
shares,
|
shares,
|
||||||
outcome,
|
outcome,
|
||||||
|
fees,
|
||||||
loanAmount,
|
loanAmount,
|
||||||
probBefore,
|
probBefore,
|
||||||
probAfter,
|
probAfter,
|
||||||
createdTime: Date.now(),
|
createdTime: Date.now(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return { newBet, newPool, newBalance }
|
return { newBet, newPool, newBalance, fees }
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getNewBinaryDpmBetInfo = (
|
export const getNewBinaryDpmBetInfo = (
|
||||||
|
@ -93,6 +99,7 @@ export const getNewBinaryDpmBetInfo = (
|
||||||
probBefore,
|
probBefore,
|
||||||
probAfter,
|
probAfter,
|
||||||
createdTime: Date.now(),
|
createdTime: Date.now(),
|
||||||
|
fees: noFees,
|
||||||
}
|
}
|
||||||
|
|
||||||
const newBalance = user.balance - (amount - loanAmount)
|
const newBalance = user.balance - (amount - loanAmount)
|
||||||
|
@ -135,6 +142,7 @@ export const getNewMultiBetInfo = (
|
||||||
probBefore,
|
probBefore,
|
||||||
probAfter,
|
probAfter,
|
||||||
createdTime: Date.now(),
|
createdTime: Date.now(),
|
||||||
|
fees: noFees,
|
||||||
}
|
}
|
||||||
|
|
||||||
const newBalance = user.balance - (amount - loanAmount)
|
const newBalance = user.balance - (amount - loanAmount)
|
||||||
|
|
|
@ -35,7 +35,7 @@ export function getNewContract(
|
||||||
? getBinaryCpmmProps(initialProb, ante) // getBinaryDpmProps(initialProb, ante)
|
? getBinaryCpmmProps(initialProb, ante) // getBinaryDpmProps(initialProb, ante)
|
||||||
: getFreeAnswerProps(ante)
|
: getFreeAnswerProps(ante)
|
||||||
|
|
||||||
const contract = removeUndefinedProps({
|
const contract: Contract = removeUndefinedProps({
|
||||||
id,
|
id,
|
||||||
slug,
|
slug,
|
||||||
...propsByOutcomeType,
|
...propsByOutcomeType,
|
||||||
|
@ -57,6 +57,12 @@ export function getNewContract(
|
||||||
|
|
||||||
volume24Hours: 0,
|
volume24Hours: 0,
|
||||||
volume7Days: 0,
|
volume7Days: 0,
|
||||||
|
|
||||||
|
collectedFees: {
|
||||||
|
creatorFee: 0,
|
||||||
|
liquidityFee: 0,
|
||||||
|
platformFee: 0,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
return contract as Contract
|
return contract as Contract
|
||||||
|
|
|
@ -3,7 +3,14 @@ import * as _ from 'lodash'
|
||||||
import { Bet } from './bet'
|
import { Bet } from './bet'
|
||||||
import { deductDpmFees, getDpmProbability } from './calculate-dpm'
|
import { deductDpmFees, getDpmProbability } from './calculate-dpm'
|
||||||
import { DPM, FreeResponse, FullContract, Multi } from './contract'
|
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 = (
|
export const getDpmCancelPayouts = (
|
||||||
contract: FullContract<DPM, any>,
|
contract: FullContract<DPM, any>,
|
||||||
|
@ -15,10 +22,12 @@ export const getDpmCancelPayouts = (
|
||||||
|
|
||||||
const betSum = _.sumBy(bets, (b) => b.amount)
|
const betSum = _.sumBy(bets, (b) => b.amount)
|
||||||
|
|
||||||
return bets.map((bet) => ({
|
const payouts = bets.map((bet) => ({
|
||||||
userId: bet.userId,
|
userId: bet.userId,
|
||||||
payout: (bet.amount / betSum) * poolTotal,
|
payout: (bet.amount / betSum) * poolTotal,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
return [payouts, contract.collectedFees ?? noFees]
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getDpmStandardPayouts = (
|
export const getDpmStandardPayouts = (
|
||||||
|
@ -36,12 +45,21 @@ export const getDpmStandardPayouts = (
|
||||||
const profit = winnings - amount
|
const profit = winnings - amount
|
||||||
|
|
||||||
// profit can be negative if using phantom shares
|
// 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 }
|
return { userId, profit, payout }
|
||||||
})
|
})
|
||||||
|
|
||||||
const profits = _.sumBy(payouts, (po) => Math.max(0, po.profit))
|
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(
|
console.log(
|
||||||
'resolved',
|
'resolved',
|
||||||
|
@ -51,12 +69,14 @@ export const getDpmStandardPayouts = (
|
||||||
'profits',
|
'profits',
|
||||||
profits,
|
profits,
|
||||||
'creator fee',
|
'creator fee',
|
||||||
creatorPayout
|
creatorFee
|
||||||
)
|
)
|
||||||
|
|
||||||
return payouts
|
const totalPayouts = payouts
|
||||||
.map(({ userId, payout }) => ({ userId, payout }))
|
.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 = (
|
export const getDpmMktPayouts = (
|
||||||
|
@ -84,7 +104,17 @@ export const getDpmMktPayouts = (
|
||||||
})
|
})
|
||||||
|
|
||||||
const profits = _.sumBy(payouts, (po) => Math.max(0, po.profit))
|
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(
|
console.log(
|
||||||
'resolved MKT',
|
'resolved MKT',
|
||||||
|
@ -93,13 +123,14 @@ export const getDpmMktPayouts = (
|
||||||
pool,
|
pool,
|
||||||
'profits',
|
'profits',
|
||||||
profits,
|
profits,
|
||||||
'creator fee',
|
'creator fee'
|
||||||
creatorPayout
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return payouts
|
const totalPayouts = payouts
|
||||||
.map(({ userId, payout }) => ({ userId, payout }))
|
.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 = (
|
export const getPayoutsMultiOutcome = (
|
||||||
|
@ -122,12 +153,22 @@ export const getPayoutsMultiOutcome = (
|
||||||
const winnings = (shares / sharesByOutcome[outcome]) * prob * poolTotal
|
const winnings = (shares / sharesByOutcome[outcome]) * prob * poolTotal
|
||||||
const profit = winnings - amount
|
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 }
|
return { userId, profit, payout }
|
||||||
})
|
})
|
||||||
|
|
||||||
const profits = _.sumBy(payouts, (po) => po.profit)
|
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(
|
console.log(
|
||||||
'resolved',
|
'resolved',
|
||||||
|
@ -137,10 +178,12 @@ export const getPayoutsMultiOutcome = (
|
||||||
'profits',
|
'profits',
|
||||||
profits,
|
profits,
|
||||||
'creator fee',
|
'creator fee',
|
||||||
creatorPayout
|
creatorFee
|
||||||
)
|
)
|
||||||
|
|
||||||
return payouts
|
const totalPayouts = payouts
|
||||||
.map(({ userId, payout }) => ({ userId, payout }))
|
.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]
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,10 @@ import * as _ from 'lodash'
|
||||||
|
|
||||||
import { Bet } from './bet'
|
import { Bet } from './bet'
|
||||||
import { getProbability } from './calculate'
|
import { getProbability } from './calculate'
|
||||||
import { deductFixedFees } from './calculate-fixed-payouts'
|
|
||||||
import { Binary, CPMM, FixedPayouts, FullContract } from './contract'
|
import { Binary, CPMM, FixedPayouts, FullContract } from './contract'
|
||||||
import { CREATOR_FEE } from './fees'
|
|
||||||
import { LiquidityProvision } from './liquidity-provision'
|
import { LiquidityProvision } from './liquidity-provision'
|
||||||
|
|
||||||
export const getFixedCancelPayouts = (
|
export const getFixedCancelPayouts = (
|
||||||
contract: FullContract<FixedPayouts, Binary>,
|
|
||||||
bets: Bet[],
|
bets: Bet[],
|
||||||
liquidities: LiquidityProvision[]
|
liquidities: LiquidityProvision[]
|
||||||
) => {
|
) => {
|
||||||
|
@ -34,23 +31,20 @@ export const getStandardFixedPayouts = (
|
||||||
) => {
|
) => {
|
||||||
const winningBets = bets.filter((bet) => bet.outcome === outcome)
|
const winningBets = bets.filter((bet) => bet.outcome === outcome)
|
||||||
|
|
||||||
const payouts = winningBets.map(({ userId, amount, shares }) => {
|
const payouts = winningBets.map(({ userId, shares }) => ({
|
||||||
const winnings = shares
|
userId,
|
||||||
const profit = winnings - amount
|
payout: shares,
|
||||||
const payout = deductFixedFees(amount, winnings)
|
}))
|
||||||
return { userId, profit, payout }
|
|
||||||
})
|
|
||||||
|
|
||||||
const profits = _.sumBy(payouts, (po) => Math.max(0, po.profit))
|
const creatorPayout = contract.collectedFees.creatorFee
|
||||||
const creatorPayout = 0 // CREATOR_FEE * profits
|
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
'resolved',
|
'resolved',
|
||||||
outcome,
|
outcome,
|
||||||
'pool',
|
'pool',
|
||||||
contract.pool,
|
contract.pool[outcome],
|
||||||
'profits',
|
'payouts',
|
||||||
profits,
|
_.sum(payouts),
|
||||||
'creator fee',
|
'creator fee',
|
||||||
creatorPayout
|
creatorPayout
|
||||||
)
|
)
|
||||||
|
@ -88,24 +82,20 @@ export const getMktFixedPayouts = (
|
||||||
? getProbability(contract)
|
? getProbability(contract)
|
||||||
: resolutionProbability
|
: resolutionProbability
|
||||||
|
|
||||||
const payouts = bets.map(({ userId, outcome, amount, shares }) => {
|
const payouts = bets.map(({ userId, outcome, shares }) => {
|
||||||
const betP = outcome === 'YES' ? p : 1 - p
|
const betP = outcome === 'YES' ? p : 1 - p
|
||||||
const winnings = betP * shares
|
return { userId, payout: betP * shares }
|
||||||
const profit = winnings - amount
|
|
||||||
const payout = deductFixedFees(amount, winnings)
|
|
||||||
return { userId, profit, payout }
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const profits = _.sumBy(payouts, (po) => Math.max(0, po.profit))
|
const creatorPayout = contract.collectedFees.creatorFee
|
||||||
const creatorPayout = 0 // CREATOR_FEE * profits
|
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
'resolved MKT',
|
'resolved PROB',
|
||||||
p,
|
p,
|
||||||
'pool',
|
'pool',
|
||||||
contract.pool,
|
p * contract.pool.YES + (1 - p) * contract.pool.NO,
|
||||||
'profits',
|
'payouts',
|
||||||
profits,
|
_.sum(payouts),
|
||||||
'creator fee',
|
'creator fee',
|
||||||
creatorPayout
|
creatorPayout
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,7 +1,16 @@
|
||||||
import * as _ from 'lodash'
|
import * as _ from 'lodash'
|
||||||
|
|
||||||
import { Bet } from './bet'
|
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 { LiquidityProvision } from './liquidity-provision'
|
||||||
import {
|
import {
|
||||||
getDpmCancelPayouts,
|
getDpmCancelPayouts,
|
||||||
|
@ -15,57 +24,12 @@ import {
|
||||||
getStandardFixedPayouts,
|
getStandardFixedPayouts,
|
||||||
} from './payouts-fixed'
|
} from './payouts-fixed'
|
||||||
|
|
||||||
export const getPayouts = (
|
export type Payout = {
|
||||||
outcome:
|
userId: string
|
||||||
| string
|
payout: number
|
||||||
| {
|
|
||||||
[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 const getLoanPayouts = (bets: Bet[]) => {
|
export const getLoanPayouts = (bets: Bet[]): Payout[] => {
|
||||||
const betsWithLoans = bets.filter((bet) => bet.loanAmount)
|
const betsWithLoans = bets.filter((bet) => bet.loanAmount)
|
||||||
const betsByUser = _.groupBy(betsWithLoans, (bet) => bet.userId)
|
const betsByUser = _.groupBy(betsWithLoans, (bet) => bet.userId)
|
||||||
const loansByUser = _.mapValues(betsByUser, (bets) =>
|
const loansByUser = _.mapValues(betsByUser, (bets) =>
|
||||||
|
@ -73,3 +37,92 @@ export const getLoanPayouts = (bets: Bet[]) => {
|
||||||
)
|
)
|
||||||
return _.toPairs(loansByUser).map(([userId, payout]) => ({ userId, payout }))
|
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]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import {
|
||||||
} from './calculate-dpm'
|
} from './calculate-dpm'
|
||||||
import { calculateCpmmSale, getCpmmProbability } from './calculate-cpmm'
|
import { calculateCpmmSale, getCpmmProbability } from './calculate-cpmm'
|
||||||
import { Binary, DPM, CPMM, FullContract } from './contract'
|
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'
|
import { User } from './user'
|
||||||
|
|
||||||
export const getSellBetInfo = (
|
export const getSellBetInfo = (
|
||||||
|
@ -33,7 +33,15 @@ export const getSellBetInfo = (
|
||||||
const probAfter = getDpmProbability(newTotalShares)
|
const probAfter = getDpmProbability(newTotalShares)
|
||||||
|
|
||||||
const profit = adjShareValue - amount
|
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)
|
const saleAmount = deductDpmFees(amount, adjShareValue)
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
|
@ -60,6 +68,7 @@ export const getSellBetInfo = (
|
||||||
amount: saleAmount,
|
amount: saleAmount,
|
||||||
betId,
|
betId,
|
||||||
},
|
},
|
||||||
|
fees,
|
||||||
}
|
}
|
||||||
|
|
||||||
const newBalance = user.balance + saleAmount - (loanAmount ?? 0)
|
const newBalance = user.balance + saleAmount - (loanAmount ?? 0)
|
||||||
|
@ -70,7 +79,7 @@ export const getSellBetInfo = (
|
||||||
newTotalShares,
|
newTotalShares,
|
||||||
newTotalBets,
|
newTotalBets,
|
||||||
newBalance,
|
newBalance,
|
||||||
creatorFee,
|
fees,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,10 +92,7 @@ export const getCpmmSellBetInfo = (
|
||||||
const { pool } = contract
|
const { pool } = contract
|
||||||
const { id: betId, amount, shares, outcome } = bet
|
const { id: betId, amount, shares, outcome } = bet
|
||||||
|
|
||||||
const { saleValue, newPool, creatorFee, saleAmount } = calculateCpmmSale(
|
const { saleValue, newPool, fees } = calculateCpmmSale(contract, bet)
|
||||||
contract,
|
|
||||||
bet
|
|
||||||
)
|
|
||||||
|
|
||||||
const probBefore = getCpmmProbability(pool)
|
const probBefore = getCpmmProbability(pool)
|
||||||
const probAfter = getCpmmProbability(newPool)
|
const probAfter = getCpmmProbability(newPool)
|
||||||
|
@ -96,9 +102,9 @@ export const getCpmmSellBetInfo = (
|
||||||
amount,
|
amount,
|
||||||
outcome,
|
outcome,
|
||||||
'for M$',
|
'for M$',
|
||||||
saleAmount,
|
saleValue,
|
||||||
'creator fee: M$',
|
'creator fee: M$',
|
||||||
creatorFee
|
fees.creatorFee
|
||||||
)
|
)
|
||||||
|
|
||||||
const newBet: Bet = {
|
const newBet: Bet = {
|
||||||
|
@ -112,17 +118,18 @@ export const getCpmmSellBetInfo = (
|
||||||
probAfter,
|
probAfter,
|
||||||
createdTime: Date.now(),
|
createdTime: Date.now(),
|
||||||
sale: {
|
sale: {
|
||||||
amount: saleAmount,
|
amount: saleValue,
|
||||||
betId,
|
betId,
|
||||||
},
|
},
|
||||||
|
fees,
|
||||||
}
|
}
|
||||||
|
|
||||||
const newBalance = user.balance + saleAmount
|
const newBalance = user.balance + saleValue
|
||||||
|
|
||||||
return {
|
return {
|
||||||
newBet,
|
newBet,
|
||||||
newPool,
|
newPool,
|
||||||
newBalance,
|
newBalance,
|
||||||
creatorFee,
|
fees,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import * as _ from 'lodash'
|
||||||
|
|
||||||
export const removeUndefinedProps = <T>(obj: T): T => {
|
export const removeUndefinedProps = <T>(obj: T): T => {
|
||||||
let newObj: any = {}
|
let newObj: any = {}
|
||||||
|
|
||||||
|
@ -7,3 +9,17 @@ export const removeUndefinedProps = <T>(obj: T): T => {
|
||||||
|
|
||||||
return newObj
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -9,9 +9,10 @@ import {
|
||||||
getNewMultiBetInfo,
|
getNewMultiBetInfo,
|
||||||
getLoanAmount,
|
getLoanAmount,
|
||||||
} from '../../common/new-bet'
|
} from '../../common/new-bet'
|
||||||
import { removeUndefinedProps } from '../../common/util/object'
|
import { addObjects, removeUndefinedProps } from '../../common/util/object'
|
||||||
import { Bet } from '../../common/bet'
|
import { Bet } from '../../common/bet'
|
||||||
import { redeemShares } from './redeem-shares'
|
import { redeemShares } from './redeem-shares'
|
||||||
|
import { Fees } from '../../common/fees'
|
||||||
|
|
||||||
export const placeBet = functions.runWith({ minInstances: 1 }).https.onCall(
|
export const placeBet = functions.runWith({ minInstances: 1 }).https.onCall(
|
||||||
async (
|
async (
|
||||||
|
@ -48,7 +49,7 @@ export const placeBet = functions.runWith({ minInstances: 1 }).https.onCall(
|
||||||
return { status: 'error', message: 'Invalid contract' }
|
return { status: 'error', message: 'Invalid contract' }
|
||||||
const contract = contractSnap.data() as Contract
|
const contract = contractSnap.data() as Contract
|
||||||
|
|
||||||
const { closeTime, outcomeType, mechanism } = contract
|
const { closeTime, outcomeType, mechanism, collectedFees } = contract
|
||||||
if (closeTime && Date.now() > closeTime)
|
if (closeTime && Date.now() > closeTime)
|
||||||
return { status: 'error', message: 'Trading is closed' }
|
return { status: 'error', message: 'Trading is closed' }
|
||||||
|
|
||||||
|
@ -73,7 +74,14 @@ export const placeBet = functions.runWith({ minInstances: 1 }).https.onCall(
|
||||||
.collection(`contracts/${contractId}/bets`)
|
.collection(`contracts/${contractId}/bets`)
|
||||||
.doc()
|
.doc()
|
||||||
|
|
||||||
const { newBet, newPool, newTotalShares, newTotalBets, newBalance } =
|
const {
|
||||||
|
newBet,
|
||||||
|
newPool,
|
||||||
|
newTotalShares,
|
||||||
|
newTotalBets,
|
||||||
|
newBalance,
|
||||||
|
fees,
|
||||||
|
} =
|
||||||
outcomeType === 'BINARY'
|
outcomeType === 'BINARY'
|
||||||
? mechanism === 'dpm-2'
|
? mechanism === 'dpm-2'
|
||||||
? getNewBinaryDpmBetInfo(
|
? getNewBinaryDpmBetInfo(
|
||||||
|
@ -109,6 +117,7 @@ export const placeBet = functions.runWith({ minInstances: 1 }).https.onCall(
|
||||||
pool: newPool,
|
pool: newPool,
|
||||||
totalShares: newTotalShares,
|
totalShares: newTotalShares,
|
||||||
totalBets: newTotalBets,
|
totalBets: newTotalBets,
|
||||||
|
collectedFees: addObjects<Fees>(fees ?? {}, collectedFees ?? {}),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import * as _ from 'lodash'
|
||||||
import { Contract } from '../../common/contract'
|
import { Contract } from '../../common/contract'
|
||||||
import { User } from '../../common/user'
|
import { User } from '../../common/user'
|
||||||
import { Bet } from '../../common/bet'
|
import { Bet } from '../../common/bet'
|
||||||
import { getUser, payUser } from './utils'
|
import { getUser, isProd, payUser } from './utils'
|
||||||
import { sendMarketResolutionEmail } from './emails'
|
import { sendMarketResolutionEmail } from './emails'
|
||||||
import { getLoanPayouts, getPayouts } from '../../common/payouts'
|
import { getLoanPayouts, getPayouts } from '../../common/payouts'
|
||||||
import { removeUndefinedProps } from '../../common/util/object'
|
import { removeUndefinedProps } from '../../common/util/object'
|
||||||
|
@ -75,19 +75,6 @@ export const resolveMarket = functions
|
||||||
? Math.min(closeTime, resolutionTime)
|
? Math.min(closeTime, resolutionTime)
|
||||||
: closeTime
|
: 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
|
const betsSnap = await firestore
|
||||||
.collection(`contracts/${contractId}/bets`)
|
.collection(`contracts/${contractId}/bets`)
|
||||||
.get()
|
.get()
|
||||||
|
@ -102,18 +89,33 @@ export const resolveMarket = functions
|
||||||
(doc) => doc.data() as LiquidityProvision
|
(doc) => doc.data() as LiquidityProvision
|
||||||
)
|
)
|
||||||
|
|
||||||
const payouts = getPayouts(
|
const [payouts, collectedFees] = getPayouts(
|
||||||
resolutions ?? outcome,
|
outcome,
|
||||||
|
resolutions ?? {},
|
||||||
contract,
|
contract,
|
||||||
bets,
|
bets,
|
||||||
liquidities,
|
liquidities,
|
||||||
resolutionProbability
|
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 openBets = bets.filter((b) => !b.isSold && !b.sale)
|
||||||
const loanPayouts = getLoanPayouts(openBets)
|
const loanPayouts = getLoanPayouts(openBets)
|
||||||
|
|
||||||
console.log('payouts:', payouts)
|
if (!isProd) console.log('payouts:', payouts)
|
||||||
|
|
||||||
const groups = _.groupBy(
|
const groups = _.groupBy(
|
||||||
[...payouts, ...loanPayouts],
|
[...payouts, ...loanPayouts],
|
||||||
|
|
|
@ -5,7 +5,8 @@ import { Contract } from '../../common/contract'
|
||||||
import { User } from '../../common/user'
|
import { User } from '../../common/user'
|
||||||
import { Bet } from '../../common/bet'
|
import { Bet } from '../../common/bet'
|
||||||
import { getCpmmSellBetInfo, getSellBetInfo } from '../../common/sell-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(
|
export const sellBet = functions.runWith({ minInstances: 1 }).https.onCall(
|
||||||
async (
|
async (
|
||||||
|
@ -34,7 +35,7 @@ export const sellBet = functions.runWith({ minInstances: 1 }).https.onCall(
|
||||||
return { status: 'error', message: 'Invalid contract' }
|
return { status: 'error', message: 'Invalid contract' }
|
||||||
const contract = contractSnap.data() as Contract
|
const contract = contractSnap.data() as Contract
|
||||||
|
|
||||||
const { closeTime, mechanism } = contract
|
const { closeTime, mechanism, collectedFees } = contract
|
||||||
if (closeTime && Date.now() > closeTime)
|
if (closeTime && Date.now() > closeTime)
|
||||||
return { status: 'error', message: 'Trading is closed' }
|
return { status: 'error', message: 'Trading is closed' }
|
||||||
|
|
||||||
|
@ -55,7 +56,7 @@ export const sellBet = functions.runWith({ minInstances: 1 }).https.onCall(
|
||||||
newTotalShares,
|
newTotalShares,
|
||||||
newTotalBets,
|
newTotalBets,
|
||||||
newBalance,
|
newBalance,
|
||||||
creatorFee,
|
fees,
|
||||||
} =
|
} =
|
||||||
mechanism === 'dpm-2'
|
mechanism === 'dpm-2'
|
||||||
? getSellBetInfo(user, bet, contract, newBetDoc.id)
|
? getSellBetInfo(user, bet, contract, newBetDoc.id)
|
||||||
|
@ -66,20 +67,7 @@ export const sellBet = functions.runWith({ minInstances: 1 }).https.onCall(
|
||||||
newBetDoc.id
|
newBetDoc.id
|
||||||
) as any)
|
) as any)
|
||||||
|
|
||||||
if (contract.creatorId === userId) {
|
transaction.update(userDoc, { balance: newBalance })
|
||||||
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(betDoc, { isSold: true })
|
transaction.update(betDoc, { isSold: true })
|
||||||
transaction.create(newBetDoc, newBet)
|
transaction.create(newBetDoc, newBet)
|
||||||
|
@ -89,6 +77,7 @@ export const sellBet = functions.runWith({ minInstances: 1 }).https.onCall(
|
||||||
pool: newPool,
|
pool: newPool,
|
||||||
totalShares: newTotalShares,
|
totalShares: newTotalShares,
|
||||||
totalBets: newTotalBets,
|
totalBets: newTotalBets,
|
||||||
|
collectedFees: addObjects<Fees>(fees ?? {}, collectedFees ?? {}),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user