/
add-subsidy.ts
75 lines (62 loc) · 2.37 KB
/
add-subsidy.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import * as admin from 'firebase-admin'
import { Contract, CPMMContract } from 'common/contract'
import { User } from 'common/user'
import { getNewLiquidityProvision } from 'common/add-liquidity'
import { APIError, type APIHandler } from './helpers/endpoint'
import { SUBSIDY_FEE } from 'common/economy'
import { runTxn } from 'shared/txn/run-txn'
import { type Txn } from 'common/txn'
export const addLiquidity: APIHandler<
'market/:contractId/add-liquidity'
> = async ({ contractId, amount }, auth) => {
// 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(401, 'Your account was 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(404, 'Contract not found')
const contract = contractSnap.data() as Contract
if (
contract.mechanism !== 'cpmm-1' &&
contract.mechanism !== 'cpmm-multi-1'
)
throw new APIError(
500,
'Invalid contract, only cpmm-1 and cpmm-multi-1 are supported'
)
const { closeTime } = contract
if (closeTime && Date.now() > closeTime)
throw new APIError(403, 'Trading is closed')
if (user.balance < amount) throw new APIError(403, 'Insufficient balance')
const subsidyAmount = (1 - SUBSIDY_FEE) * amount
const { newTotalLiquidity, newSubsidyPool } = getNewLiquidityProvision(
subsidyAmount,
contract
)
const { status, message, txn } = await runTxn(transaction, {
fromId: user.id,
amount: amount,
toId: contractId,
toType: 'CONTRACT',
category: 'ADD_SUBSIDY',
token: 'M$',
fromType: 'USER',
})
if (status === 'error' || !txn) {
throw new APIError(500, message ?? 'Unknown error')
}
transaction.update(contractDoc, {
subsidyPool: newSubsidyPool,
totalLiquidity: newTotalLiquidity,
} as Partial<CPMMContract>)
const newBalance = user.balance - amount
if (!isFinite(newBalance)) {
throw new APIError(500, 'Invalid user balance for ' + user.username)
}
return txn as Txn
})
}
const firestore = admin.firestore()