@@ -32,6 +32,10 @@ import {
3232 QUOTE_PRECISION ,
3333 ClockSubscriber ,
3434 DriftEnv ,
35+ OraclePriceData ,
36+ StateAccount ,
37+ getUserStatsAccountPublicKey ,
38+ PositionDirection ,
3539 PerpMarkets ,
3640} from '@drift-labs/sdk' ;
3741import { Mutex , tryAcquire , E_ALREADY_LOCKED } from 'async-mutex' ;
@@ -97,6 +101,7 @@ import { LRUCache } from 'lru-cache';
97101import { bs58 } from '@project-serum/anchor/dist/cjs/utils/bytes' ;
98102import { PythPriceFeedSubscriber } from '../pythPriceFeedSubscriber' ;
99103import { TxThreaded } from './common/txThreaded' ;
104+ import { NodeToTriggerWithMakers } from '../experimental-bots/filler-common/types' ;
100105import { PythLazerSubscriber } from '../pythLazerSubscriber' ;
101106
102107const TX_COUNT_COOLDOWN_ON_BURST = 10 ; // send this many tx before resetting burst mode
@@ -118,6 +123,7 @@ export const CACHED_BLOCKHASH_OFFSET = 5;
118123const DUMP_TXS_IN_SIM = false ;
119124
120125const EXPIRE_ORDER_BUFFER_SEC = 60 ; // add extra time before trying to expire orders (want to avoid 6252 error due to clock drift)
126+ const NUM_MAKERS = 4 ; // number of makers to pull for triggerable orders
121127
122128const errorCodesToSuppress = [
123129 6004 , // 0x1774 Error Number: 6004. Error Message: SufficientCollateral.
@@ -775,7 +781,7 @@ export class FillerBot extends TxThreaded implements Bot {
775781 dlob : DLOB
776782 ) : {
777783 nodesToFill : Array < NodeToFill > ;
778- nodesToTrigger : Array < NodeToTrigger > ;
784+ nodesToTrigger : Array < NodeToTriggerWithMakers > ;
779785 } {
780786 const marketIndex = market . marketIndex ;
781787
@@ -786,6 +792,14 @@ export class FillerBot extends TxThreaded implements Bot {
786792 const vBid = calculateBidPrice ( market , oraclePriceData ) ;
787793
788794 const fillSlot = this . getMaxSlot ( ) ;
795+ const nodesToTrigger = this . findTriggerableNodesWithMakers (
796+ dlob ,
797+ marketIndex ,
798+ fillSlot ,
799+ oraclePriceData ,
800+ MarketType . PERP ,
801+ this . driftClient . getStateAccount ( )
802+ ) ;
789803
790804 return {
791805 nodesToFill : dlob . findNodesToFill (
@@ -799,13 +813,7 @@ export class FillerBot extends TxThreaded implements Bot {
799813 this . driftClient . getStateAccount ( ) ,
800814 this . driftClient . getPerpMarketAccount ( marketIndex ) !
801815 ) ,
802- nodesToTrigger : dlob . findNodesToTrigger (
803- marketIndex ,
804- fillSlot ,
805- oraclePriceData . price ,
806- MarketType . PERP ,
807- this . driftClient . getStateAccount ( )
808- ) ,
816+ nodesToTrigger,
809817 } ;
810818 }
811819
@@ -1881,10 +1889,10 @@ export class FillerBot extends TxThreaded implements Bot {
18811889
18821890 protected filterPerpNodesForMarket (
18831891 fillableNodes : Array < NodeToFill > ,
1884- triggerableNodes : Array < NodeToTrigger >
1892+ triggerableNodes : Array < NodeToTriggerWithMakers >
18851893 ) : {
18861894 filteredFillableNodes : Array < NodeToFill > ;
1887- filteredTriggerableNodes : Array < NodeToTrigger > ;
1895+ filteredTriggerableNodes : Array < NodeToTriggerWithMakers > ;
18881896 } {
18891897 const seenFillableNodes = new Set < string > ( ) ;
18901898 const filteredFillableNodes = fillableNodes . filter ( ( node ) => {
@@ -1920,7 +1928,7 @@ export class FillerBot extends TxThreaded implements Bot {
19201928 }
19211929
19221930 protected async executeTriggerablePerpNodesForMarket (
1923- triggerableNodes : Array < NodeToTrigger > ,
1931+ triggerableNodes : Array < NodeToTriggerWithMakers > ,
19241932 buildForBundle : boolean
19251933 ) {
19261934 for ( const nodeToTrigger of triggerableNodes ) {
@@ -1929,9 +1937,11 @@ export class FillerBot extends TxThreaded implements Bot {
19291937 nodeToTrigger . node . userAccount . toString ( )
19301938 ) ;
19311939 logger . info (
1932- `trying to trigger (account: ${ nodeToTrigger . node . userAccount . toString ( ) } , slot: ${
1940+ `Processing node: account= ${ nodeToTrigger . node . userAccount . toString ( ) } , slot= ${
19331941 user . slot
1934- } ) order ${ nodeToTrigger . node . order . orderId . toString ( ) } `
1942+ } , orderId=${ nodeToTrigger . node . order . orderId . toString ( ) } , numMakers=${
1943+ nodeToTrigger . makers ?. length ?? 0
1944+ } `
19351945 ) ;
19361946
19371947 const nodeSignature = getNodeToTriggerSignature ( nodeToTrigger ) ;
@@ -1970,6 +1980,36 @@ export class FillerBot extends TxThreaded implements Bot {
19701980 )
19711981 ) ;
19721982
1983+ logger . info ( `Triggrable node has ${ nodeToTrigger . makers . length } makers` ) ;
1984+ const makerInfos = await Promise . all (
1985+ nodeToTrigger . makers . map ( async ( m ) => {
1986+ const maker = new PublicKey ( m ) ;
1987+ logger . info ( `Getting maker info for ${ maker . toString ( ) } ` ) ;
1988+ const { data } = await this . getUserAccountAndSlotFromMap (
1989+ maker . toString ( )
1990+ ) ;
1991+ const makerUserAccount = data ;
1992+ const makerAuthority = makerUserAccount . authority ;
1993+ const makerStats = getUserStatsAccountPublicKey (
1994+ this . driftClient . program . programId ,
1995+ makerAuthority
1996+ ) ;
1997+ return {
1998+ maker,
1999+ makerStats,
2000+ makerUserAccount,
2001+ } ;
2002+ } )
2003+ ) ;
2004+
2005+ const fillIx = await this . driftClient . getFillPerpOrderIx (
2006+ new PublicKey ( nodeToTrigger . node . userAccount ) ,
2007+ user . data ,
2008+ nodeToTrigger . node . order ,
2009+ makerInfos
2010+ ) ;
2011+ ixs . push ( fillIx ) ;
2012+
19732013 if ( this . revertOnFailure ) {
19742014 ixs . push ( await this . driftClient . getRevertFillIx ( ) ) ;
19752015 }
@@ -2296,6 +2336,51 @@ export class FillerBot extends TxThreaded implements Bot {
22962336 return true ;
22972337 }
22982338
2339+ public findTriggerableNodesWithMakers (
2340+ dlob : DLOB ,
2341+ marketIndex : number ,
2342+ slot : number ,
2343+ oraclePriceData : OraclePriceData ,
2344+ marketType : MarketType ,
2345+ stateAccount : StateAccount
2346+ ) : NodeToTriggerWithMakers [ ] {
2347+ const baseTriggerable = dlob . findNodesToTrigger (
2348+ marketIndex ,
2349+ slot ,
2350+ oraclePriceData . price ,
2351+ marketType ,
2352+ stateAccount
2353+ ) ;
2354+ if ( baseTriggerable . length > 0 ) {
2355+ logger . info (
2356+ `Found ${ baseTriggerable . length } nodes to trigger for market ${ marketIndex } `
2357+ ) ;
2358+ }
2359+
2360+ const triggerWithMaker : NodeToTriggerWithMakers [ ] = [ ] ;
2361+
2362+ for ( const nodeObj of baseTriggerable ) {
2363+ const order = nodeObj . node . order ;
2364+
2365+ const makers = dlob . getBestMakers ( {
2366+ marketIndex,
2367+ marketType,
2368+ direction : isVariant ( order . direction , 'long' )
2369+ ? PositionDirection . SHORT
2370+ : PositionDirection . LONG ,
2371+ slot,
2372+ oraclePriceData,
2373+ numMakers : NUM_MAKERS ,
2374+ } ) ;
2375+ triggerWithMaker . push ( {
2376+ ...nodeObj ,
2377+ makers,
2378+ } ) ;
2379+ }
2380+
2381+ return triggerWithMaker ;
2382+ }
2383+
22992384 protected async tryFill ( ) {
23002385 const startTime = Date . now ( ) ;
23012386 let ran = false ;
@@ -2325,7 +2410,7 @@ export class FillerBot extends TxThreaded implements Bot {
23252410
23262411 // 1) get all fillable nodes
23272412 let fillableNodes : Array < NodeToFill > = [ ] ;
2328- let triggerableNodes : Array < NodeToTrigger > = [ ] ;
2413+ let triggerableNodes : Array < NodeToTriggerWithMakers > = [ ] ;
23292414 for ( const market of this . driftClient . getPerpMarketAccounts ( ) ) {
23302415 try {
23312416 const { nodesToFill, nodesToTrigger } = this . getPerpNodesForMarket (
0 commit comments