@@ -17,6 +17,9 @@ import {
1717 standardizePrice ,
1818 SwapDirection ,
1919 ZERO ,
20+ PRICE_PRECISION ,
21+ AMM_TO_QUOTE_PRECISION_RATIO ,
22+ standardizeBaseAssetAmount ,
2023} from '..' ;
2124import { PublicKey } from '@solana/web3.js' ;
2225import { assert } from '../assert/assert' ;
@@ -66,6 +69,13 @@ export const DEFAULT_TOP_OF_BOOK_QUOTE_AMOUNTS = [
6669 new BN ( 5000 ) . mul ( QUOTE_PRECISION ) ,
6770] ;
6871
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+
6979/**
7080 * Get an {@link Generator<L2Level>} generator from a {@link Generator<DLOBNode>}
7181 * @param dlobNodes e.g. {@link DLOB#getRestingLimitAsks} or {@link DLOB#getRestingLimitBids}
@@ -162,29 +172,21 @@ export function getVammL2Generator({
162172 marketAccount,
163173 oraclePriceData,
164174 numOrders,
165- now,
166- topOfBookQuoteAmounts,
175+ now = new BN ( Math . floor ( Date . now ( ) / 1000 ) ) ,
176+ topOfBookQuoteAmounts = [ ] ,
167177} : {
168178 marketAccount : PerpMarketAccount ;
169179 oraclePriceData : OraclePriceData ;
170180 numOrders : number ;
171181 now ?: BN ;
172182 topOfBookQuoteAmounts ?: BN [ ] ;
173183} ) : L2OrderBookGenerator {
174- let numBaseOrders = numOrders ;
175- if ( topOfBookQuoteAmounts ) {
176- numBaseOrders = numOrders - topOfBookQuoteAmounts . length ;
177- assert ( topOfBookQuoteAmounts . length < numOrders ) ;
178- }
179-
180184 const updatedAmm = calculateUpdatedAMM ( marketAccount . amm , oraclePriceData ) ;
181-
182- const vammFillsDisabled = isOperationPaused (
185+ const paused = isOperationPaused (
183186 marketAccount . pausedOperations ,
184187 PerpOperation . AMM_FILL
185188 ) ;
186-
187- let [ openBids , openAsks ] = vammFillsDisabled
189+ let [ openBids , openAsks ] = paused
188190 ? [ ZERO , ZERO ]
189191 : calculateMarketOpenBidAsk (
190192 updatedAmm . baseAssetReserve ,
@@ -193,194 +195,110 @@ export function getVammL2Generator({
193195 updatedAmm . orderStepSize
194196 ) ;
195197
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 ) ) )
202200 openAsks = ZERO ;
203- }
204201
205- now = now ?? new BN ( Date . now ( ) / 1000 ) ;
206202 const [ bidReserves , askReserves ] = calculateSpreadReserves (
207203 updatedAmm ,
208204 oraclePriceData ,
209205 now ,
210206 isVariant ( marketAccount . contractType , 'prediction' )
211207 ) ;
212208
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 ,
221216 pegMultiplier : updatedAmm . pegMultiplier ,
217+ sqrtK : updatedAmm . sqrtK ,
218+ topOfBookQuoteAmounts,
222219 } ;
223220
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 ,
289240 } ;
290241
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 ;
327252 }
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 ;
365254
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+ ) ;
367271
368- askAmm . baseAssetReserve = afterSwapBaseReserves ;
369- askAmm . quoteAssetReserve = afterSwapQuoteReserves ;
272+ amm . baseAssetReserve = newBaseRes ;
273+ amm . quoteAssetReserve = newQuoteRes ;
370274
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+ }
376282
377- numAsks ++ ;
378- }
283+ yield { price, size : baseSwap , sources : { vamm : baseSwap } } ;
284+ count ++ ;
285+ }
286+ } ;
379287 } ;
380288
381289 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+ } ) ,
384302 } ;
385303}
386304
0 commit comments