@@ -19,6 +19,10 @@ import {
19
19
TransactionPayload ,
20
20
Percentage ,
21
21
resolveOrCreateAssociatedTokenAddress ,
22
+ ZERO ,
23
+ DepositQuote ,
24
+ WithdrawQuote ,
25
+ DecimalUtil ,
22
26
} from "../../../public" ;
23
27
import {
24
28
createApprovalInstruction ,
@@ -49,6 +53,10 @@ export class OrcaPoolImpl implements OrcaPool {
49
53
return this . poolParams . tokens [ tokenId ] ;
50
54
}
51
55
56
+ public getPoolTokenMint ( ) : PublicKey {
57
+ return this . poolParams . poolTokenMint ;
58
+ }
59
+
52
60
public async getLPBalance ( owner : PublicKey ) : Promise < OrcaU64 > {
53
61
const address = await deriveAssociatedTokenAddress ( owner , this . poolParams . poolTokenMint ) ;
54
62
@@ -184,6 +192,57 @@ export class OrcaPoolImpl implements OrcaPool {
184
192
. build ( ) ;
185
193
}
186
194
195
+ public async getDepositQuote (
196
+ maxTokenAIn : Decimal | OrcaU64 ,
197
+ maxTokenBIn : Decimal | OrcaU64 ,
198
+ slippage ?: Decimal
199
+ ) : Promise < DepositQuote > {
200
+ const slippageTolerance =
201
+ slippage === undefined ? defaultSlippagePercentage : Percentage . fromDecimal ( slippage ) ;
202
+
203
+ const maxTokenAIn_U64 = U64Utils . toTokenU64 ( maxTokenAIn , this . getTokenA ( ) , "maxTokenAIn" ) ;
204
+ const maxTokenBIn_U64 = U64Utils . toTokenU64 ( maxTokenBIn , this . getTokenB ( ) , "maxTokenBIn" ) ;
205
+
206
+ const { inputTokenCount : tokenAAmount , outputTokenCount : tokenBAmount } = await getTokenCount (
207
+ this . connection ,
208
+ this . poolParams ,
209
+ this . getTokenA ( ) ,
210
+ this . getTokenB ( )
211
+ ) ;
212
+ const lpSupply = await this . getLPSupply ( ) ;
213
+
214
+ if ( tokenAAmount . eq ( ZERO ) || tokenBAmount . eq ( ZERO ) ) {
215
+ return {
216
+ minPoolTokenAmountOut : OrcaU64 . fromU64 ( ZERO , lpSupply . scale ) ,
217
+ maxTokenAIn : OrcaU64 . fromU64 ( maxTokenAIn_U64 , this . getTokenA ( ) . scale ) ,
218
+ maxTokenBIn : OrcaU64 . fromU64 ( maxTokenBIn_U64 , this . getTokenB ( ) . scale ) ,
219
+ } ;
220
+ }
221
+
222
+ const poolTokenAmountWithA = maxTokenAIn_U64
223
+ . mul ( slippageTolerance . denominator )
224
+ . mul ( lpSupply . toU64 ( ) )
225
+ . div ( tokenAAmount )
226
+ . div ( slippageTolerance . numerator . add ( slippageTolerance . denominator ) ) ;
227
+
228
+ const poolTokenAmountWithB = maxTokenBIn_U64
229
+ . mul ( slippageTolerance . denominator )
230
+ . mul ( lpSupply . toU64 ( ) )
231
+ . div ( tokenBAmount )
232
+ . div ( slippageTolerance . numerator . add ( slippageTolerance . denominator ) ) ;
233
+
234
+ // Pick the smaller value of the two to calculate the minimum poolTokenAmount out
235
+ const minPoolTokenAmountOut_U64 = poolTokenAmountWithA . gt ( poolTokenAmountWithB )
236
+ ? poolTokenAmountWithB
237
+ : poolTokenAmountWithA ;
238
+
239
+ return {
240
+ minPoolTokenAmountOut : OrcaU64 . fromU64 ( minPoolTokenAmountOut_U64 , lpSupply . scale ) ,
241
+ maxTokenAIn : OrcaU64 . fromU64 ( maxTokenAIn_U64 , this . getTokenA ( ) . scale ) ,
242
+ maxTokenBIn : OrcaU64 . fromU64 ( maxTokenBIn_U64 , this . getTokenB ( ) . scale ) ,
243
+ } ;
244
+ }
245
+
187
246
public async deposit (
188
247
owner : Keypair | PublicKey ,
189
248
maxTokenAIn : Decimal | OrcaU64 ,
@@ -270,6 +329,86 @@ export class OrcaPoolImpl implements OrcaPool {
270
329
. build ( ) ;
271
330
}
272
331
332
+ public async getWithdrawQuote (
333
+ withdrawTokenAmount : Decimal | OrcaU64 ,
334
+ withdrawTokenMint : PublicKey ,
335
+ slippage ?: Decimal
336
+ ) : Promise < WithdrawQuote > {
337
+ const slippageTolerance =
338
+ slippage === undefined ? defaultSlippagePercentage : Percentage . fromDecimal ( slippage ) ;
339
+
340
+ const lpSupply = await this . getLPSupply ( ) ;
341
+ const { inputTokenCount : tokenAAmount , outputTokenCount : tokenBAmount } = await getTokenCount (
342
+ this . connection ,
343
+ this . poolParams ,
344
+ this . getTokenA ( ) ,
345
+ this . getTokenB ( )
346
+ ) ;
347
+
348
+ // withdrawTokenAmount needs represent amounts for one of the following: poolTokenAmount, tokenAAmount, or tokenBAmount
349
+ // determine which token this amount represents, then calculate poolTokenIn_U64
350
+ let poolTokenIn_U64 = ZERO ;
351
+ if ( withdrawTokenMint . equals ( this . getPoolTokenMint ( ) ) ) {
352
+ poolTokenIn_U64 = U64Utils . toPoolU64 (
353
+ withdrawTokenAmount ,
354
+ this . poolParams ,
355
+ "withdrawTokenAmount"
356
+ ) ;
357
+ } else if (
358
+ withdrawTokenMint . equals ( this . getTokenA ( ) . mint ) ||
359
+ withdrawTokenMint . equals ( this . getTokenB ( ) . mint )
360
+ ) {
361
+ const token = withdrawTokenMint . equals ( this . getTokenA ( ) . mint )
362
+ ? this . getTokenA ( )
363
+ : this . getTokenB ( ) ;
364
+ const totalAmount = token . mint . equals ( this . getTokenA ( ) . mint ) ? tokenAAmount : tokenBAmount ;
365
+
366
+ const numerator =
367
+ withdrawTokenAmount instanceof OrcaU64
368
+ ? withdrawTokenAmount . toDecimal ( )
369
+ : withdrawTokenAmount ;
370
+ const denominator = DecimalUtil . fromU64 ( totalAmount , token . scale ) ;
371
+ const poolTokenIn = lpSupply . toDecimal ( ) . div ( denominator ) . mul ( numerator ) ;
372
+ poolTokenIn_U64 = U64Utils . toPoolU64 ( poolTokenIn , this . poolParams , "poolTokenIn" ) ;
373
+ } else {
374
+ throw new Error (
375
+ `Unable to get withdraw quote with an invalid withdrawTokenMint ${ withdrawTokenMint } `
376
+ ) ;
377
+ }
378
+
379
+ if ( poolTokenIn_U64 . eq ( ZERO ) ) {
380
+ return {
381
+ maxPoolTokenAmountIn : OrcaU64 . fromU64 ( ZERO , lpSupply . scale ) ,
382
+ minTokenAOut : OrcaU64 . fromU64 ( ZERO , this . getTokenA ( ) . scale ) ,
383
+ minTokenBOut : OrcaU64 . fromU64 ( ZERO , this . getTokenB ( ) . scale ) ,
384
+ } ;
385
+ }
386
+
387
+ const minTokenAOut = new OrcaU64 (
388
+ poolTokenIn_U64
389
+ . mul ( slippageTolerance . denominator )
390
+ . mul ( tokenAAmount )
391
+ . div ( lpSupply . toU64 ( ) )
392
+ . div ( slippageTolerance . numerator . add ( slippageTolerance . denominator ) ) ,
393
+ this . getTokenA ( ) . scale
394
+ ) ;
395
+
396
+ const minTokenBOut = new OrcaU64 (
397
+ poolTokenIn_U64
398
+ . mul ( slippageTolerance . denominator )
399
+ . mul ( tokenBAmount )
400
+ . div ( lpSupply . toU64 ( ) )
401
+ . div ( slippageTolerance . numerator . add ( slippageTolerance . denominator ) ) ,
402
+ this . getTokenB ( ) . scale
403
+ ) ;
404
+
405
+ return {
406
+ maxPoolTokenAmountIn : OrcaU64 . fromU64 ( poolTokenIn_U64 , lpSupply . scale ) ,
407
+ minTokenAOut,
408
+ minTokenBOut,
409
+ } ;
410
+ }
411
+
273
412
public async withdraw (
274
413
owner : Keypair | PublicKey ,
275
414
poolTokenAmountIn : Decimal | OrcaU64 ,
0 commit comments