From 5fd42df1edc474b19d66bb7a63dcefa39307694b Mon Sep 17 00:00:00 2001 From: Marshall Polaris Date: Tue, 12 Jul 2022 12:36:31 -0700 Subject: [PATCH] Don't run share redemption after adding liquidity (#631) --- functions/src/add-liquidity.ts | 114 ++++++++++++++++----------------- 1 file changed, 54 insertions(+), 60 deletions(-) diff --git a/functions/src/add-liquidity.ts b/functions/src/add-liquidity.ts index 3ef453c2..6746486e 100644 --- a/functions/src/add-liquidity.ts +++ b/functions/src/add-liquidity.ts @@ -4,7 +4,6 @@ import { z } from 'zod' import { Contract } from '../../common/contract' import { User } from '../../common/user' import { removeUndefinedProps } from '../../common/util/object' -import { redeemShares } from './redeem-shares' import { getNewLiquidityProvision } from '../../common/add-liquidity' import { APIError, newEndpoint, validate } from './api' @@ -19,78 +18,73 @@ export const addliquidity = newEndpoint({}, async (req, auth) => { if (!isFinite(amount)) throw new APIError(400, 'Invalid amount') // run as transaction to prevent race conditions - return await firestore - .runTransaction(async (transaction) => { - const userDoc = firestore.doc(`users/${auth.uid}`) - const userSnap = await transaction.get(userDoc) - if (!userSnap.exists) throw new APIError(400, 'User not found') - const user = userSnap.data() as User + return await firestore.runTransaction(async (transaction) => { + const userDoc = firestore.doc(`users/${auth.uid}`) + const userSnap = await transaction.get(userDoc) + if (!userSnap.exists) throw new APIError(400, 'User not found') + const user = userSnap.data() as User - const contractDoc = firestore.doc(`contracts/${contractId}`) - const contractSnap = await transaction.get(contractDoc) - if (!contractSnap.exists) throw new APIError(400, 'Invalid contract') - const contract = contractSnap.data() as Contract - if ( - contract.mechanism !== 'cpmm-1' || - (contract.outcomeType !== 'BINARY' && - contract.outcomeType !== 'PSEUDO_NUMERIC') - ) - throw new APIError(400, 'Invalid contract') + const contractDoc = firestore.doc(`contracts/${contractId}`) + const contractSnap = await transaction.get(contractDoc) + if (!contractSnap.exists) throw new APIError(400, 'Invalid contract') + const contract = contractSnap.data() as Contract + if ( + contract.mechanism !== 'cpmm-1' || + (contract.outcomeType !== 'BINARY' && + contract.outcomeType !== 'PSEUDO_NUMERIC') + ) + throw new APIError(400, 'Invalid contract') - const { closeTime } = contract - if (closeTime && Date.now() > closeTime) - throw new APIError(400, 'Trading is closed') + const { closeTime } = contract + if (closeTime && Date.now() > closeTime) + throw new APIError(400, 'Trading is closed') - if (user.balance < amount) throw new APIError(400, 'Insufficient balance') + if (user.balance < amount) throw new APIError(400, 'Insufficient balance') - const newLiquidityProvisionDoc = firestore - .collection(`contracts/${contractId}/liquidity`) - .doc() + const newLiquidityProvisionDoc = firestore + .collection(`contracts/${contractId}/liquidity`) + .doc() - const { newLiquidityProvision, newPool, newP, newTotalLiquidity } = - getNewLiquidityProvision( - user, - amount, - contract, - newLiquidityProvisionDoc.id - ) - - if (newP !== undefined && !isFinite(newP)) { - return { - status: 'error', - message: 'Liquidity injection rejected due to overflow error.', - } - } - - transaction.update( - contractDoc, - removeUndefinedProps({ - pool: newPool, - p: newP, - totalLiquidity: newTotalLiquidity, - }) + const { newLiquidityProvision, newPool, newP, newTotalLiquidity } = + getNewLiquidityProvision( + user, + amount, + contract, + newLiquidityProvisionDoc.id ) - const newBalance = user.balance - amount - const newTotalDeposits = user.totalDeposits - amount - - if (!isFinite(newBalance)) { - throw new APIError(500, 'Invalid user balance for ' + user.username) + if (newP !== undefined && !isFinite(newP)) { + return { + status: 'error', + message: 'Liquidity injection rejected due to overflow error.', } + } - transaction.update(userDoc, { - balance: newBalance, - totalDeposits: newTotalDeposits, + transaction.update( + contractDoc, + removeUndefinedProps({ + pool: newPool, + p: newP, + totalLiquidity: newTotalLiquidity, }) + ) - transaction.create(newLiquidityProvisionDoc, newLiquidityProvision) + const newBalance = user.balance - amount + const newTotalDeposits = user.totalDeposits - amount - return newLiquidityProvision - }) - .then(async (result) => { - await redeemShares(auth.uid, contractId) - return result + if (!isFinite(newBalance)) { + throw new APIError(500, 'Invalid user balance for ' + user.username) + } + + transaction.update(userDoc, { + balance: newBalance, + totalDeposits: newTotalDeposits, }) + + transaction.create(newLiquidityProvisionDoc, newLiquidityProvision) + + return newLiquidityProvision + }) }) const firestore = admin.firestore()