@@ -288,14 +288,14 @@ export const processPortfolioEvents = async (
288288 const flowId = flowIdFromKey ( flowKey ) ;
289289 const scope = [ portfolioId , flowId ] as const ;
290290 const { policyVersion, rebalanceCount, targetAllocation } = portfolioStatus ;
291- const conditions = [ policyVersion , rebalanceCount ] as const ;
291+ const versions = [ policyVersion , rebalanceCount ] as const ;
292292
293293 const currentBalances = await getNonDustBalances (
294294 portfolioStatus ,
295295 depositBrand ,
296296 balanceQueryPowers ,
297297 ) ;
298- const errorContext = {
298+ const logContext = {
299299 path,
300300 flowKey,
301301 flowDetail,
@@ -304,40 +304,37 @@ export const processPortfolioEvents = async (
304304 rebalanceCount,
305305 targetAllocation,
306306 } ;
307- const plannerContext = {
308- ...errorContext ,
309- // @ts -expect-error "amount" is not present on all varieties of
310- // FlowDetail, but we need it here when it is present (i.e., for types
311- // "deposit" and "withdraw" and it's harmless otherwise.
312- amount : flowDetail . amount ,
313- network,
314- brand : depositBrand ,
315- feeBrand,
316- gasEstimator,
317- } ;
318-
319- const { network : _network , ...logContext } = plannerContext ;
320- logger . debug ( `Starting flow` , flowDetail , inspectForStdout ( logContext ) ) ;
321307 const settle = async < M extends string & keyof PortfolioPlanner > (
322308 methodName : M ,
323309 args : PortfolioPlanner [ M ] extends ( ...args : infer Args ) => any
324310 ? Args
325311 : never ,
312+ extraDetails ?: object ,
326313 ) => {
327- const planReceiver = walletStore . get < PortfolioPlanner > ( 'planner' , {
328- sendOnly : true ,
329- } ) ;
314+ const txOpts = { sendOnly : true } ;
315+ const planReceiver = walletStore . get < PortfolioPlanner > ( 'planner' , txOpts ) ;
330316 const { tx, id } = await planReceiver [ methodName ] ! ( ...args ) ;
331- // The transaction has been submitted, but we won't know about a rejection
332- // for at least another block.
317+ // tx has been submitted, but we won't know its fate until a future block.
333318 if ( ! isDryRun ) {
334319 void getWalletInvocationUpdate ( id as any ) . catch ( err => {
335320 logger . warn ( `⚠️ Failure for ${ methodName } ` , args , err ) ;
336321 } ) ;
337322 }
338- return tx ;
323+ const details = inspectForStdout ( { ...logContext , ...extraDetails } ) ;
324+ logger . info ( methodName , flowDetail , currentBalances , details , tx ) ;
339325 } ;
340326
327+ const plannerContext = {
328+ ...logContext ,
329+ // @ts -expect-error "amount" is not present on all varieties of
330+ // FlowDetail, but we need it here when it is present (i.e., for types
331+ // "deposit" and "withdraw" and it's harmless otherwise.
332+ amount : flowDetail . amount ,
333+ network,
334+ brand : depositBrand ,
335+ feeBrand,
336+ gasEstimator,
337+ } ;
341338 try {
342339 let steps : MovementDesc [ ] ;
343340 const { type } = flowDetail ;
@@ -351,43 +348,29 @@ export const processPortfolioEvents = async (
351348 case 'withdraw' :
352349 steps = await planWithdrawFromAllocations ( plannerContext ) ;
353350 break ;
354- default : {
351+ default :
355352 logger . warn ( `⚠️ Unknown flow type ${ type } ` ) ;
356353 return ;
357- }
358354 }
359- ( errorContext as any ) . steps = steps ;
360-
361- const tx = await ( steps . length === 0
362- ? settle ( 'rejectPlan' , [
363- ...scope ,
364- 'Nothing to do for this operation.' ,
365- ...conditions ,
366- ] )
367- : settle ( 'resolvePlan' , [ ...scope , steps , ...conditions ] ) ) ;
368- logger . info (
369- `Resolving` ,
370- flowDetail ,
371- currentBalances ,
372- inspectForStdout ( {
373- policyVersion,
374- rebalanceCount,
375- targetAllocation,
376- steps,
377- } ) ,
378- tx ,
379- ) ;
355+ ( logContext as any ) . steps = steps ;
356+
357+ if ( steps . length > 0 ) {
358+ await settle ( 'resolvePlan' , [ ...scope , steps , ...versions ] , { steps } ) ;
359+ } else {
360+ const reason = 'Nothing to do for this operation.' ;
361+ await settle ( 'rejectPlan' , [ ...scope , reason , ...versions ] ) ;
362+ }
380363 } catch ( err ) {
364+ annotateError ( err , inspect ( logContext , { depth : 4 } ) ) ;
381365 if ( err instanceof UserInputError || err instanceof NoSolutionError ) {
382- try {
383- await settle ( 'rejectPlan' , [ ...scope , err . message , ...conditions ] ) ;
384- } catch ( settleErr ) {
385- // eslint-disable-next-line no-ex-assign
386- err = AggregateError ( [ err , settleErr ] ) ;
387- }
366+ await settle ( 'rejectPlan' , [ ...scope , err . message , ...versions ] , {
367+ cause : err ,
368+ } ) . catch ( err2 => {
369+ throw AggregateError ( [ err , err2 ] ) ;
370+ } ) ;
371+ } else {
372+ throw err ;
388373 }
389- annotateError ( err , inspect ( errorContext , { depth : 4 } ) ) ;
390- throw err ;
391374 }
392375 } ;
393376 const handledPortfolioKeys = new Set < string > ( ) ;
@@ -413,7 +396,7 @@ export const processPortfolioEvents = async (
413396 }
414397
415398 // If this (portfolio, flows) data hasn't changed since our last
416- // submission, there's no point in trying again.
399+ // successful submission, there's no point in trying again.
417400 memory . snapshots ||= new Map ( ) ;
418401 const oldState = memory . snapshots . get ( portfolioKey ) ;
419402 const oldFingerprint = oldState ?. fingerprint ;
@@ -424,7 +407,6 @@ export const processPortfolioEvents = async (
424407 oldState . repeats += 1 ;
425408 return ;
426409 }
427- memory . snapshots . set ( portfolioKey , { fingerprint, repeats : 0 } ) ;
428410
429411 // If any in-progress flows need activation (as indicated by not having
430412 // its own dedicated vstorage data), then find the first such flow and
@@ -439,8 +421,9 @@ export const processPortfolioEvents = async (
439421 portfolioKey , flowKey ,
440422 ( ) => startFlow ( status , portfolioKey , flowKey , flowDetail ) ,
441423 ) ;
442- return ;
424+ break ;
443425 }
426+ memory . snapshots . set ( portfolioKey , { fingerprint, repeats : 0 } ) ;
444427 } catch ( err ) {
445428 const age = blockHeight - eventRecord . blockHeight ;
446429 if ( err . code === STALE_RESPONSE ) {
0 commit comments