-
Notifications
You must be signed in to change notification settings - Fork 33
/
Copy pathpools.ts
150 lines (143 loc) · 4.78 KB
/
pools.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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
import { Zero } from '@ethersproject/constants'
import { BigNumber } from '@ethersproject/bignumber'
import { Pool, PoolInfo, PoolToken } from '../router'
import { SynapseSDK } from '../sdk'
/**
* Gets pool tokens for a pool address.
*
* @param chainId The chain ID
* @param poolAddress The pool address
* @returns The pool tokens
* @throws Will throw an error if SynapseRouter is not deployed on the given chain.
*/
export async function getPoolTokens(
this: SynapseSDK,
chainId: number,
poolAddress: string
): Promise<PoolToken[]> {
return this.synapseRouterSet
.getSynapseRouter(chainId)
.getPoolTokens(poolAddress)
}
/**
* Gets info for a pool (number of tokens and LP token).
*
* @param chainId The chain ID
* @param poolAddress The pool address
* @returns The pool info (number of tokens and LP token)
* @throws Will throw an error if SynapseRouter is not deployed on the given chain.
*/
export async function getPoolInfo(
this: SynapseSDK,
chainId: number,
poolAddress: string
): Promise<PoolInfo> {
return this.synapseRouterSet
.getSynapseRouter(chainId)
.getPoolInfo(poolAddress)
}
/**
* Gets all pools for a chain ID.
*
* @param chainId The chain ID
* @returns An array of all pools (address, tokens, LP token)
* @throws Will throw an error if SynapseRouter is not deployed on the given chain.
*/
export async function getAllPools(
this: SynapseSDK,
chainId: number
): Promise<Pool[]> {
return this.synapseRouterSet.getSynapseRouter(chainId).getAllPools()
}
/**
* Calculates the amount required to add liquidity for amounts of each token.
*
* @param chainId The chain ID
* @param poolAddress The pool address
* @param amounts The amounts of each token to add
* @returns The amount of LP tokens needed and router address
* @throws Will throw an error if SynapseRouter is not deployed on the given chain.
*/
export async function calculateAddLiquidity(
this: SynapseSDK,
chainId: number,
poolAddress: string,
amounts: Record<string, BigNumber>
): Promise<{ amount: BigNumber; routerAddress: string }> {
// TODO (Chi): use amounts array as the input instead of map in the first place
const router = this.synapseRouterSet.getSynapseRouter(chainId)
const routerAddress = router.address
const poolTokens = await router.getPoolTokens(poolAddress)
// Create a map that uses lowercase token addresses as keys
const lowerCaseAmounts: Record<string, BigNumber> = {}
Object.keys(amounts).forEach((key) => {
lowerCaseAmounts[key.toLowerCase()] = amounts[key]
})
// Populate amounts array by combining amounts map and pool tokens, preserving tokens order
// and adding 0 for tokens not in the map
const amountsArray: BigNumber[] = poolTokens.map(
(poolToken) => lowerCaseAmounts[poolToken.token.toLowerCase()] ?? Zero
)
// Don't do a contract call if all amounts are 0
const amount = amountsArray.every((value) => value.isZero())
? Zero
: await router.calculateAddLiquidity(poolAddress, amountsArray)
return { amount, routerAddress }
}
/**
* Calculates the amounts received when removing liquidity.
*
* @param chainId The chain ID
* @param poolAddress The pool address
* @param amount The amount of LP tokens to remove
* @returns The amounts of each token received and router address
* @throws Will throw an error if SynapseRouter is not deployed on the given chain.
*/
export async function calculateRemoveLiquidity(
this: SynapseSDK,
chainId: number,
poolAddress: string,
amount: BigNumber
): Promise<{
amounts: Array<{ value: BigNumber; index: number }>
routerAddress: string
}> {
const router = this.synapseRouterSet.getSynapseRouter(chainId)
const routerAddress = router.address
const amountsOut = await router.calculateRemoveLiquidity(poolAddress, amount)
// Zip amounts with token indexes
const amounts = amountsOut.map((value, index) => ({ value, index }))
return { amounts, routerAddress }
}
/**
* Calculates the amount of one token received when removing liquidity.
*
* @param chainId The chain ID
* @param poolAddress The pool address
* @param amount The amount of LP tokens to remove
* @param poolIndex The index of the token to receive
* @returns The amount received and router address
* @throws Will throw an error if SynapseRouter is not deployed on the given chain.
*/
export async function calculateRemoveLiquidityOne(
this: SynapseSDK,
chainId: number,
poolAddress: string,
amount: BigNumber,
poolIndex: number
): Promise<{
amount: { value: BigNumber; index: number }
routerAddress: string
}> {
const router = this.synapseRouterSet.getSynapseRouter(chainId)
const routerAddress = router.address
const amountOut = {
value: await router.calculateWithdrawOneToken(
poolAddress,
amount,
poolIndex
),
index: poolIndex,
}
return { amount: amountOut, routerAddress }
}