@@ -2,6 +2,8 @@ package controller
22
33import (
44 "log"
5+ "math"
6+ "math/big"
57 "time"
68
79 "github.com/CrocSwap/graphcache-go/cache"
@@ -47,7 +49,7 @@ func (c *Controller) SpinUntilLiqSync() {
4749 nowTime := time .Now ().Unix ()
4850 syncSec := c .refresher .lastRefreshSec
4951 if nowTime < syncSec + REFRESH_PAUSE_SECS {
50- log .Println ("Waiting for liquidity sync pause. Last refresh:" , syncSec , "now:" , nowTime )
52+ // log.Println("Waiting for liquidity sync pause. Last refresh:", syncSec, "now:", nowTime)
5153 } else {
5254 return
5355 }
@@ -82,6 +84,9 @@ func (c *ControllerOverNetwork) IngestBalance(b tables.Balance) {
8284}
8385
8486func (c * ControllerOverNetwork ) IngestLiqChange (l tables.LiqChange ) {
87+ if l .ChangeType == tables .ChangeTypeCross {
88+ c .IngestKnockout (l )
89+ }
8590 c .applyToPosition (l )
8691 c .applyToLiqCurve (l )
8792 c .ctrl .history .CommitLiqChange (l )
@@ -101,7 +106,7 @@ func (c *ControllerOverNetwork) applyToPosition(l tables.LiqChange) {
101106 User : types .RequireEthAddr (l .User ),
102107 }
103108
104- if l .PositionType == "knockout" {
109+ if l .PositionType == tables . PosTypeKnockout {
105110 c .applyToKnockout (l , loc )
106111 } else {
107112 c .applyToPassiveLiq (l , loc )
@@ -121,11 +126,63 @@ func (c *ControllerOverNetwork) applyToLiqCurve(l tables.LiqChange) {
121126}
122127
123128func (c * ControllerOverNetwork ) applyToKnockout (l tables.LiqChange , loc types.PositionLocation ) {
124- if l .ChangeType == "cross" {
125- return // Cross events are handled KnockoutCross table
129+ pivotLoc := loc .ToBookLoc ()
130+ if l .IsBid == 1 {
131+ pivotLoc .LiquidityLocation .AskTick = l .BidTick
132+ } else {
133+ pivotLoc .LiquidityLocation .BidTick = l .AskTick
134+ }
135+ if l .ChangeType == tables .ChangeTypeCross {
136+ c .ctrl .cache .SetPivotTime (pivotLoc , 0 )
137+ return
138+ }
139+ pivotTime := c .ctrl .cache .RetrievePivotTime (pivotLoc )
140+ if l .ChangeType == tables .ChangeTypeMint && pivotTime == 0 {
141+ c .ctrl .cache .SetPivotTime (pivotLoc , l .Time )
142+ pivotTime = l .Time
143+ }
144+
145+ event := model.KnockoutSagaTx {
146+ TxTime : l .Time ,
147+ TxHash : l .TX ,
148+ PivotTime : pivotTime ,
126149 }
127150 pos := c .ctrl .cache .MaterializeKnockoutPos (loc )
151+ if l .ChangeType == tables .ChangeTypeMint {
152+ pos .AppendMint (event )
153+ } else if l .ChangeType == tables .ChangeTypeBurn {
154+ pos .AppendBurn (event )
155+ }
156+
128157 c .ctrl .workers .omniUpdates <- & koPosUpdateMsg {liq : l , pos : pos , loc : loc }
158+
159+ // Estimate position liquidity from the flows
160+ if (l .ChangeType == tables .ChangeTypeMint || l .ChangeType == tables .ChangeTypeBurn || l .ChangeType == tables .ChangeTypeRecover ) && l .BaseFlow != nil && l .QuoteFlow != nil {
161+ liq := model .DeriveLiquidityFromConcFlow (* l .BaseFlow , * l .QuoteFlow , l .BidTick , l .AskTick )
162+ if math .IsInf (liq , 0 ) || math .IsNaN (liq ) {
163+ log .Println ("Invalid liq" , liq , "for" , l )
164+ liq = 0
165+ }
166+ liqBigInt , _ := big .NewFloat (liq ).Int (nil )
167+
168+ activeLiq := pos .Liq .GetActiveLiq ()
169+ pos .Liq .UpdateActiveLiq (* big .NewInt (0 ).Add (activeLiq , liqBigInt ), 0 )
170+ afterLiq := pos .Liq .GetActiveLiq ()
171+ if afterLiq .Cmp (big .NewInt (0 )) < 0 {
172+ pos .Liq .UpdateActiveLiq (* big .NewInt (0 ), 0 )
173+ afterLiq = big .NewInt (0 )
174+ }
175+ afterLiqFloat , _ := afterLiq .Float64 ()
176+
177+ // If it's a burn and the remaining liq is less than 10% of the liq change, set it to 0
178+ if l .ChangeType == tables .ChangeTypeBurn && afterLiqFloat > 0 && math .Abs (liq )* 0.10 > math .Abs (afterLiqFloat ) {
179+ pos .Liq .UpdateActiveLiq (* big .NewInt (0 ), 0 )
180+ }
181+ if l .ChangeType == tables .ChangeTypeRecover || l .ChangeType == tables .ChangeTypeClaim {
182+ pos .Liq .UpdateActiveLiq (* big .NewInt (0 ), 0 )
183+ pos .Liq .UpdatePostKOLiq (* l .PivotTime , * big .NewInt (0 ), 0 )
184+ }
185+ }
129186}
130187
131188func (c * ControllerOverNetwork ) applyToPassiveLiq (l tables.LiqChange , loc types.PositionLocation ) {
@@ -158,20 +215,21 @@ func (c *ControllerOverNetwork) IngestAggEvent(r tables.AggEvent) {
158215 hist .NextEvent (r )
159216}
160217
161- func (c * ControllerOverNetwork ) IngestKnockout (r tables.KnockoutCross ) {
162- liq := types .KnockoutTickLocation (r . Tick , r .IsBid > 0 , c .knockoutTickWidth ())
218+ func (c * ControllerOverNetwork ) IngestKnockout (l tables.LiqChange ) {
219+ liq := types .KnockoutTickLocation (l . BidTick , l .IsBid > 0 , c .knockoutTickWidth ())
163220 pool := types.PoolLocation {
164221 ChainId : c .chainId ,
165- PoolIdx : r .PoolIdx ,
166- Base : types .RequireEthAddr (r .Base ),
167- Quote : types .RequireEthAddr (r .Quote ),
222+ PoolIdx : l .PoolIdx ,
223+ Base : types .RequireEthAddr (l .Base ),
224+ Quote : types .RequireEthAddr (l .Quote ),
168225 }
169226 loc := types.BookLocation {
170227 PoolLocation : pool ,
171228 LiquidityLocation : liq ,
172229 }
173- pos := c .ctrl .cache .MaterializeKnockoutBook (loc )
174- c .ctrl .workers .omniUpdates <- & koCrossUpdateMsg {loc : loc , pos : pos , cross : r }
230+ pos := c .ctrl .cache .MaterializeKnockoutSaga (loc )
231+ pos .UpdateCross (l )
232+ c .ctrl .workers .omniUpdates <- & koCrossUpdateMsg {loc : loc , pos : pos , cross : l }
175233}
176234
177235/* Called to indicate that all tables have completed the most recent sync cycle up
@@ -188,9 +246,9 @@ func (c *ControllerOverNetwork) knockoutTickWidth() int {
188246}
189247
190248func formLiqLoc (l tables.LiqChange ) types.LiquidityLocation {
191- if l .PositionType == "ambient" {
249+ if l .PositionType == tables . PosTypeAmbient {
192250 return types .AmbientLiquidityLocation ()
193- } else if l .PositionType == "knockout" {
251+ } else if l .PositionType == tables . PosTypeKnockout {
194252 return types .KnockoutRangeLocation (l .BidTick , l .AskTick , l .IsBid > 0 )
195253 } else {
196254 return types .RangeLiquidityLocation (l .BidTick , l .AskTick )
@@ -199,7 +257,7 @@ func formLiqLoc(l tables.LiqChange) types.LiquidityLocation {
199257
200258func (c * Controller ) resyncFullCycle (time int ) {
201259 for poolLoc , poolPos := range c .cache .RetrieveAllPositions () {
202- if ! poolPos .IsEmpty () {
260+ if ! poolPos .IsEmpty () || poolPos . RefreshTime == 0 {
203261 c .workers .omniUpdates <- & posImpactMsg {poolLoc , poolPos , time }
204262 }
205263 }
@@ -208,9 +266,12 @@ func (c *Controller) resyncFullCycle(time int) {
208266const REFRESH_CYCLE_TIME = 30 * 60
209267
210268func (c * Controller ) runPeriodicRefresh () {
269+ // To prevent running periodic refreshes while the startup sync is still running
270+ c .SpinUntilLiqSync ()
211271 for {
212272 time .Sleep (time .Second * REFRESH_CYCLE_TIME )
213273 refreshTime := time .Now ().Unix ()
274+ log .Println ("Running full refresh at" , refreshTime )
214275 c .resyncFullCycle (int (refreshTime ))
215276 }
216277}
0 commit comments