|
|
@@ -8,6 +8,7 @@ import {
|
|
|
openPosition,
|
|
|
closePosition,
|
|
|
rebalanceSwap,
|
|
|
+ findUserBinIds,
|
|
|
} from '../chain'
|
|
|
import {
|
|
|
getCurrentPosition,
|
|
|
@@ -53,12 +54,16 @@ export class RebalancerEngine {
|
|
|
return g[GLOBAL_KEY]
|
|
|
}
|
|
|
|
|
|
- start(): void {
|
|
|
+ async start(): Promise<void> {
|
|
|
if (this.running) return
|
|
|
this.status = 'running'
|
|
|
this.startedAt = Date.now()
|
|
|
this.stopRequested = false
|
|
|
setEngineState('status', 'running')
|
|
|
+
|
|
|
+ // Sync on-chain position to DB if DB is empty
|
|
|
+ await this.syncPositionFromChain()
|
|
|
+
|
|
|
console.log('[engine] Started')
|
|
|
this.runLoop()
|
|
|
}
|
|
|
@@ -151,6 +156,48 @@ export class RebalancerEngine {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // ── Sync on-chain position to DB ──
|
|
|
+
|
|
|
+ private async syncPositionFromChain(): Promise<void> {
|
|
|
+ const existing = getCurrentPosition()
|
|
|
+ if (existing) {
|
|
|
+ console.log(
|
|
|
+ `[engine] DB has position: bin=${existing.activeId}, range=[${existing.minBin}, ${existing.maxBin}]`,
|
|
|
+ )
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log('[engine] No position in DB, scanning chain...')
|
|
|
+ try {
|
|
|
+ const binIds = await findUserBinIds(100)
|
|
|
+ if (binIds.length === 0) {
|
|
|
+ console.log('[engine] No on-chain position found')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ const minBin = Math.min(...binIds)
|
|
|
+ const maxBin = Math.max(...binIds)
|
|
|
+ const centerBin = Math.round((minBin + maxBin) / 2)
|
|
|
+ const price = getPriceFromBinId(centerBin)
|
|
|
+
|
|
|
+ upsertPosition({
|
|
|
+ activeId: centerBin,
|
|
|
+ minBin,
|
|
|
+ maxBin,
|
|
|
+ numBins: binIds.length,
|
|
|
+ binIds,
|
|
|
+ amounts: binIds.map(() => '0'),
|
|
|
+ priceAtOpen: price,
|
|
|
+ })
|
|
|
+
|
|
|
+ console.log(
|
|
|
+ `[engine] Recovered on-chain position: ${binIds.length} bins, range=[${minBin}, ${maxBin}]`,
|
|
|
+ )
|
|
|
+ } catch (err) {
|
|
|
+ console.error('[engine] Chain sync failed:', err instanceof Error ? err.message : err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// ── Main loop: sequential, waits for each cycle to finish ──
|
|
|
|
|
|
private async runLoop(): Promise<void> {
|