@@ -17,6 +17,9 @@ import {
17
17
standardizePrice ,
18
18
SwapDirection ,
19
19
ZERO ,
20
+ PRICE_PRECISION ,
21
+ AMM_TO_QUOTE_PRECISION_RATIO ,
22
+ standardizeBaseAssetAmount ,
20
23
} from '..' ;
21
24
import { PublicKey } from '@solana/web3.js' ;
22
25
import { assert } from '../assert/assert' ;
@@ -66,6 +69,13 @@ export const DEFAULT_TOP_OF_BOOK_QUOTE_AMOUNTS = [
66
69
new BN ( 5000 ) . mul ( QUOTE_PRECISION ) ,
67
70
] ;
68
71
72
+ export const MAJORS_TOP_OF_BOOK_QUOTE_AMOUNTS = [
73
+ new BN ( 5000 ) . mul ( QUOTE_PRECISION ) ,
74
+ new BN ( 10000 ) . mul ( QUOTE_PRECISION ) ,
75
+ new BN ( 20000 ) . mul ( QUOTE_PRECISION ) ,
76
+ new BN ( 50000 ) . mul ( QUOTE_PRECISION ) ,
77
+ ] ;
78
+
69
79
/**
70
80
* Get an {@link Generator<L2Level>} generator from a {@link Generator<DLOBNode>}
71
81
* @param dlobNodes e.g. {@link DLOB#getRestingLimitAsks} or {@link DLOB#getRestingLimitBids}
@@ -162,29 +172,21 @@ export function getVammL2Generator({
162
172
marketAccount,
163
173
oraclePriceData,
164
174
numOrders,
165
- now,
166
- topOfBookQuoteAmounts,
175
+ now = new BN ( Math . floor ( Date . now ( ) / 1000 ) ) ,
176
+ topOfBookQuoteAmounts = [ ] ,
167
177
} : {
168
178
marketAccount : PerpMarketAccount ;
169
179
oraclePriceData : OraclePriceData ;
170
180
numOrders : number ;
171
181
now ?: BN ;
172
182
topOfBookQuoteAmounts ?: BN [ ] ;
173
183
} ) : L2OrderBookGenerator {
174
- let numBaseOrders = numOrders ;
175
- if ( topOfBookQuoteAmounts ) {
176
- numBaseOrders = numOrders - topOfBookQuoteAmounts . length ;
177
- assert ( topOfBookQuoteAmounts . length < numOrders ) ;
178
- }
179
-
180
184
const updatedAmm = calculateUpdatedAMM ( marketAccount . amm , oraclePriceData ) ;
181
-
182
- const vammFillsDisabled = isOperationPaused (
185
+ const paused = isOperationPaused (
183
186
marketAccount . pausedOperations ,
184
187
PerpOperation . AMM_FILL
185
188
) ;
186
-
187
- let [ openBids , openAsks ] = vammFillsDisabled
189
+ let [ openBids , openAsks ] = paused
188
190
? [ ZERO , ZERO ]
189
191
: calculateMarketOpenBidAsk (
190
192
updatedAmm . baseAssetReserve ,
@@ -193,194 +195,110 @@ export function getVammL2Generator({
193
195
updatedAmm . orderStepSize
194
196
) ;
195
197
196
- const minOrderSize = marketAccount . amm . minOrderSize ;
197
- if ( openBids . lt ( minOrderSize . muln ( 2 ) ) ) {
198
- openBids = ZERO ;
199
- }
200
-
201
- if ( openAsks . abs ( ) . lt ( minOrderSize . muln ( 2 ) ) ) {
198
+ if ( openBids . lt ( marketAccount . amm . minOrderSize . muln ( 2 ) ) ) openBids = ZERO ;
199
+ if ( openAsks . abs ( ) . lt ( marketAccount . amm . minOrderSize . muln ( 2 ) ) )
202
200
openAsks = ZERO ;
203
- }
204
201
205
- now = now ?? new BN ( Date . now ( ) / 1000 ) ;
206
202
const [ bidReserves , askReserves ] = calculateSpreadReserves (
207
203
updatedAmm ,
208
204
oraclePriceData ,
209
205
now ,
210
206
isVariant ( marketAccount . contractType , 'prediction' )
211
207
) ;
212
208
213
- let numBids = 0 ;
214
-
215
- let topOfBookBidSize = ZERO ;
216
- let bidSize = openBids . div ( new BN ( numBaseOrders ) ) ;
217
- const bidAmm = {
218
- baseAssetReserve : bidReserves . baseAssetReserve ,
219
- quoteAssetReserve : bidReserves . quoteAssetReserve ,
220
- sqrtK : updatedAmm . sqrtK ,
209
+ const numBaseOrders = Math . max ( 1 , numOrders - topOfBookQuoteAmounts . length ) ;
210
+ const commonOpts = {
211
+ numOrders,
212
+ numBaseOrders,
213
+ oraclePriceData,
214
+ orderTickSize : marketAccount . amm . orderTickSize ,
215
+ orderStepSize : marketAccount . amm . orderStepSize ,
221
216
pegMultiplier : updatedAmm . pegMultiplier ,
217
+ sqrtK : updatedAmm . sqrtK ,
218
+ topOfBookQuoteAmounts,
222
219
} ;
223
220
224
- const getL2Bids = function * ( ) {
225
- while ( numBids < numOrders && bidSize . gt ( ZERO ) ) {
226
- let quoteSwapped = ZERO ;
227
- let baseSwapped = ZERO ;
228
- let [ afterSwapQuoteReserves , afterSwapBaseReserves ] = [ ZERO , ZERO ] ;
229
-
230
- if ( topOfBookQuoteAmounts && numBids < topOfBookQuoteAmounts ?. length ) {
231
- const remainingBaseLiquidity = openBids . sub ( topOfBookBidSize ) ;
232
- quoteSwapped = topOfBookQuoteAmounts [ numBids ] ;
233
- [ afterSwapQuoteReserves , afterSwapBaseReserves ] =
234
- calculateAmmReservesAfterSwap (
235
- bidAmm ,
236
- 'quote' ,
237
- quoteSwapped ,
238
- SwapDirection . REMOVE
239
- ) ;
240
-
241
- baseSwapped = bidAmm . baseAssetReserve . sub ( afterSwapBaseReserves ) . abs ( ) ;
242
- if ( baseSwapped . eq ( ZERO ) ) {
243
- return ;
244
- }
245
- if ( remainingBaseLiquidity . lt ( baseSwapped ) ) {
246
- baseSwapped = remainingBaseLiquidity ;
247
- [ afterSwapQuoteReserves , afterSwapBaseReserves ] =
248
- calculateAmmReservesAfterSwap (
249
- bidAmm ,
250
- 'base' ,
251
- baseSwapped ,
252
- SwapDirection . ADD
253
- ) ;
254
-
255
- quoteSwapped = calculateQuoteAssetAmountSwapped (
256
- bidAmm . quoteAssetReserve . sub ( afterSwapQuoteReserves ) . abs ( ) ,
257
- bidAmm . pegMultiplier ,
258
- SwapDirection . ADD
259
- ) ;
260
- }
261
- topOfBookBidSize = topOfBookBidSize . add ( baseSwapped ) ;
262
- bidSize = openBids . sub ( topOfBookBidSize ) . div ( new BN ( numBaseOrders ) ) ;
263
- } else {
264
- baseSwapped = bidSize ;
265
- [ afterSwapQuoteReserves , afterSwapBaseReserves ] =
266
- calculateAmmReservesAfterSwap (
267
- bidAmm ,
268
- 'base' ,
269
- baseSwapped ,
270
- SwapDirection . ADD
271
- ) ;
272
-
273
- quoteSwapped = calculateQuoteAssetAmountSwapped (
274
- bidAmm . quoteAssetReserve . sub ( afterSwapQuoteReserves ) . abs ( ) ,
275
- bidAmm . pegMultiplier ,
276
- SwapDirection . ADD
277
- ) ;
278
- }
279
-
280
- const price = quoteSwapped . mul ( BASE_PRECISION ) . div ( baseSwapped ) ;
281
-
282
- bidAmm . baseAssetReserve = afterSwapBaseReserves ;
283
- bidAmm . quoteAssetReserve = afterSwapQuoteReserves ;
284
-
285
- yield {
286
- price,
287
- size : baseSwapped ,
288
- sources : { vamm : baseSwapped } ,
221
+ const makeL2Gen = ( {
222
+ openLiquidity,
223
+ startReserves,
224
+ swapDir,
225
+ positionDir,
226
+ } : {
227
+ openLiquidity : BN ;
228
+ startReserves : { baseAssetReserve : BN ; quoteAssetReserve : BN } ;
229
+ swapDir : SwapDirection ;
230
+ positionDir : PositionDirection ;
231
+ } ) => {
232
+ return function * ( ) {
233
+ let count = 0 ;
234
+ let topSize = ZERO ;
235
+ let size = openLiquidity . abs ( ) . divn ( commonOpts . numBaseOrders ) ;
236
+ const amm = {
237
+ ...startReserves ,
238
+ sqrtK : commonOpts . sqrtK ,
239
+ pegMultiplier : commonOpts . pegMultiplier ,
289
240
} ;
290
241
291
- numBids ++ ;
292
- }
293
- } ;
294
-
295
- let numAsks = 0 ;
296
- let topOfBookAskSize = ZERO ;
297
- let askSize = openAsks . abs ( ) . div ( new BN ( numBaseOrders ) ) ;
298
- const askAmm = {
299
- baseAssetReserve : askReserves . baseAssetReserve ,
300
- quoteAssetReserve : askReserves . quoteAssetReserve ,
301
- sqrtK : updatedAmm . sqrtK ,
302
- pegMultiplier : updatedAmm . pegMultiplier ,
303
- } ;
304
-
305
- const getL2Asks = function * ( ) {
306
- while ( numAsks < numOrders && askSize . gt ( ZERO ) ) {
307
- let quoteSwapped : BN = ZERO ;
308
- let baseSwapped : BN = ZERO ;
309
- let [ afterSwapQuoteReserves , afterSwapBaseReserves ] = [ ZERO , ZERO ] ;
310
-
311
- if ( topOfBookQuoteAmounts && numAsks < topOfBookQuoteAmounts ?. length ) {
312
- const remainingBaseLiquidity = openAsks
313
- . mul ( new BN ( - 1 ) )
314
- . sub ( topOfBookAskSize ) ;
315
- quoteSwapped = topOfBookQuoteAmounts [ numAsks ] ;
316
- [ afterSwapQuoteReserves , afterSwapBaseReserves ] =
317
- calculateAmmReservesAfterSwap (
318
- askAmm ,
319
- 'quote' ,
320
- quoteSwapped ,
321
- SwapDirection . ADD
322
- ) ;
323
-
324
- baseSwapped = askAmm . baseAssetReserve . sub ( afterSwapBaseReserves ) . abs ( ) ;
325
- if ( baseSwapped . eq ( ZERO ) ) {
326
- return ;
242
+ while ( count < commonOpts . numOrders && size . gt ( ZERO ) ) {
243
+ let baseSwap = size ;
244
+ if ( count < commonOpts . topOfBookQuoteAmounts . length ) {
245
+ const raw = commonOpts . topOfBookQuoteAmounts [ count ]
246
+ . mul ( AMM_TO_QUOTE_PRECISION_RATIO )
247
+ . mul ( PRICE_PRECISION )
248
+ . div ( commonOpts . oraclePriceData . price ) ;
249
+ baseSwap = standardizeBaseAssetAmount ( raw , commonOpts . orderStepSize ) ;
250
+ const remaining = openLiquidity . abs ( ) . sub ( topSize ) ;
251
+ if ( remaining . lt ( baseSwap ) ) baseSwap = remaining ;
327
252
}
328
- if ( remainingBaseLiquidity . lt ( baseSwapped ) ) {
329
- baseSwapped = remainingBaseLiquidity ;
330
- [ afterSwapQuoteReserves , afterSwapBaseReserves ] =
331
- calculateAmmReservesAfterSwap (
332
- askAmm ,
333
- 'base' ,
334
- baseSwapped ,
335
- SwapDirection . REMOVE
336
- ) ;
337
-
338
- quoteSwapped = calculateQuoteAssetAmountSwapped (
339
- askAmm . quoteAssetReserve . sub ( afterSwapQuoteReserves ) . abs ( ) ,
340
- askAmm . pegMultiplier ,
341
- SwapDirection . REMOVE
342
- ) ;
343
- }
344
- topOfBookAskSize = topOfBookAskSize . add ( baseSwapped ) ;
345
- askSize = openAsks
346
- . abs ( )
347
- . sub ( topOfBookAskSize )
348
- . div ( new BN ( numBaseOrders ) ) ;
349
- } else {
350
- baseSwapped = askSize ;
351
- [ afterSwapQuoteReserves , afterSwapBaseReserves ] =
352
- calculateAmmReservesAfterSwap (
353
- askAmm ,
354
- 'base' ,
355
- askSize ,
356
- SwapDirection . REMOVE
357
- ) ;
358
-
359
- quoteSwapped = calculateQuoteAssetAmountSwapped (
360
- askAmm . quoteAssetReserve . sub ( afterSwapQuoteReserves ) . abs ( ) ,
361
- askAmm . pegMultiplier ,
362
- SwapDirection . REMOVE
363
- ) ;
364
- }
253
+ if ( baseSwap . isZero ( ) ) return ;
365
254
366
- const price = quoteSwapped . mul ( BASE_PRECISION ) . div ( baseSwapped ) ;
255
+ const [ newQuoteRes , newBaseRes ] = calculateAmmReservesAfterSwap (
256
+ amm ,
257
+ 'base' ,
258
+ baseSwap ,
259
+ swapDir
260
+ ) ;
261
+ const quoteSwapped = calculateQuoteAssetAmountSwapped (
262
+ amm . quoteAssetReserve . sub ( newQuoteRes ) . abs ( ) ,
263
+ amm . pegMultiplier ,
264
+ swapDir
265
+ ) ;
266
+ const price = standardizePrice (
267
+ quoteSwapped . mul ( BASE_PRECISION ) . div ( baseSwap ) ,
268
+ commonOpts . orderTickSize ,
269
+ positionDir
270
+ ) ;
367
271
368
- askAmm . baseAssetReserve = afterSwapBaseReserves ;
369
- askAmm . quoteAssetReserve = afterSwapQuoteReserves ;
272
+ amm . baseAssetReserve = newBaseRes ;
273
+ amm . quoteAssetReserve = newQuoteRes ;
370
274
371
- yield {
372
- price,
373
- size : baseSwapped ,
374
- sources : { vamm : baseSwapped } ,
375
- } ;
275
+ if ( count < commonOpts . topOfBookQuoteAmounts . length ) {
276
+ topSize = topSize . add ( baseSwap ) ;
277
+ size = openLiquidity
278
+ . abs ( )
279
+ . sub ( topSize )
280
+ . divn ( commonOpts . numBaseOrders ) ;
281
+ }
376
282
377
- numAsks ++ ;
378
- }
283
+ yield { price, size : baseSwap , sources : { vamm : baseSwap } } ;
284
+ count ++ ;
285
+ }
286
+ } ;
379
287
} ;
380
288
381
289
return {
382
- getL2Bids,
383
- getL2Asks,
290
+ getL2Bids : makeL2Gen ( {
291
+ openLiquidity : openBids ,
292
+ startReserves : bidReserves ,
293
+ swapDir : SwapDirection . ADD ,
294
+ positionDir : PositionDirection . LONG ,
295
+ } ) ,
296
+ getL2Asks : makeL2Gen ( {
297
+ openLiquidity : openAsks ,
298
+ startReserves : askReserves ,
299
+ swapDir : SwapDirection . REMOVE ,
300
+ positionDir : PositionDirection . SHORT ,
301
+ } ) ,
384
302
} ;
385
303
}
386
304
0 commit comments