async function automationStart(speculos, interactionFunc) {
  // If this doens't exist, we're running against a hardware ledger; just call
  // interactionFunc with no events iterator.
  if(!speculos.automationEvents) {
    return new Promise(r=>r({ promptsPromise: interactionFunc(speculos) }));
  }

  // This is so that you can just "await flowAccept(this.speculos);" in a test
  // without actually waiting for the prompts.  If we don't do this, you can
  // end up with two flowAccept calls active at once, causing issues.
  let subNum = speculos.handlerNum++;
  let promptLockResolve;
  let promptsLock=new Promise(r=>{promptLockResolve=r});
  if(speculos.promptsEndPromise) {
    await speculos.promptsEndPromise;
  }
  speculos.promptsEndPromise = promptsLock; // Set ourselves as the interaction.

  // Make an async iterator we can push stuff into.
  let sendEvent;
  let sendPromise=new Promise(r=>{sendEvent = r;});
  let asyncEventIter = {
    next: async ()=>{
      promptVal=await sendPromise;
      sendPromise=new Promise(r=>{sendEvent = r;});
      return promptVal;
    },
    peek: async ()=>{
      return await sendPromise;
    }
  };

  // Sync up with the ledger; wait until we're on the home screen, and do some
  // clicking back and forth to make sure we see the event.
  // Then pass screens to interactionFunc.
  let readyPromise = syncWithLedger(speculos, asyncEventIter, interactionFunc);

  // Resolve our lock when we're done
  readyPromise.then(r=>r.promptsPromise.then(()=>{promptLockResolve(true)}));

  let header;
  let body;

  let subscript = speculos.automationEvents.subscribe({
    next: evt => {
      // Wrap up two-line prompts into one:
      if(evt.y == 3 && ! headerOnlyScreens[evt.text]) {
        header = evt.text;
        return; // The top line comes out first, so now wait for the next draw.
      } else {
        body = evt.text;
      }
      screen = { ...(header && {header}), body };
      if(process.env.DEBUG_SCREENS) console.log("SCREEN (" + subNum + "): " + JSON.stringify(screen));
      sendEvent(screen);
      body=undefined;
      header=undefined;
    }});

  asyncEventIter.unsubscribe = () => { subscript.unsubscribe(); };

  // Send a rightward-click to make sure we get _an_ event and our state
  // machine starts.
  speculos.button("Rr");

  return readyPromise.then(r=>{r.cancel = ()=>{subscript.unsubscribe(); promptLockResolve(true);}; return r;});
}
/* State machine to read screen events and turn them into screens of prompts. */
State machine to read screen events and turn them into screens of prompts.
State machine to read screen events and turn them into screens of prompts .
async function automationStart(speculos, interactionFunc) {
  if(!speculos.automationEvents) {
    return new Promise(r=>r({ promptsPromise: interactionFunc(speculos) }));
  }
  let subNum = speculos.handlerNum++;
  let promptLockResolve;
  let promptsLock=new Promise(r=>{promptLockResolve=r});
  if(speculos.promptsEndPromise) {
    await speculos.promptsEndPromise;
  }
  speculos.promptsEndPromise = promptsLock; 
  let sendEvent;
  let sendPromise=new Promise(r=>{sendEvent = r;});
  let asyncEventIter = {
    next: async ()=>{
      promptVal=await sendPromise;
      sendPromise=new Promise(r=>{sendEvent = r;});
      return promptVal;
    },
    peek: async ()=>{
      return await sendPromise;
    }
  };
  let readyPromise = syncWithLedger(speculos, asyncEventIter, interactionFunc);
  readyPromise.then(r=>r.promptsPromise.then(()=>{promptLockResolve(true)}));
  let header;
  let body;
  let subscript = speculos.automationEvents.subscribe({
    next: evt => {
      if(evt.y == 3 && ! headerOnlyScreens[evt.text]) {
        header = evt.text;
        return; 
      } else {
        body = evt.text;
      }
      screen = { ...(header && {header}), body };
      if(process.env.DEBUG_SCREENS) console.log("SCREEN (" + subNum + "): " + JSON.stringify(screen));
      sendEvent(screen);
      body=undefined;
      header=undefined;
    }});
  asyncEventIter.unsubscribe = () => { subscript.unsubscribe(); };
  speculos.button("Rr");
  return readyPromise.then(r=>{r.cancel = ()=>{subscript.unsubscribe(); promptLockResolve(true);}; return r;});
}
async function automationStart ( speculos , interactionFunc ) { if ( ! speculos . automationEvents ) { return new Promise ( r => r ( { promptsPromise : interactionFunc ( speculos ) } ) ) ; } let subNum = speculos . handlerNum ++ ; let promptLockResolve ; let promptsLock = new Promise ( r => { promptLockResolve = r } ) ; if ( speculos . promptsEndPromise ) { await speculos . promptsEndPromise ; } speculos . promptsEndPromise = promptsLock ; let sendEvent ; let sendPromise = new Promise ( r => { sendEvent = r ; } ) ; let asyncEventIter = { next : async ( ) => { promptVal = await sendPromise ; sendPromise = new Promise ( r => { sendEvent = r ; } ) ; return promptVal ; } , peek : async ( ) => { return await sendPromise ; } } ; let readyPromise = syncWithLedger ( speculos , asyncEventIter , interactionFunc ) ; readyPromise . then ( r => r . promptsPromise . then ( ( ) => { promptLockResolve ( true ) } ) ) ; let header ; let body ; let subscript = speculos . automationEvents . subscribe ( { next : evt => { if ( evt . y == 3 && ! headerOnlyScreens [ evt . text ] ) { header = evt . text ; return ; } else { body = evt . text ; } screen = { ... ( header && { header } ) , body } ; if ( process . env . DEBUG_SCREENS ) console . log ( "SCREEN (" + subNum + "): " + JSON . stringify ( screen ) ) ; sendEvent ( screen ) ; body = undefined ; header = undefined ; } } ) ; asyncEventIter . unsubscribe = ( ) => { subscript . unsubscribe ( ) ; } ; speculos . button ( "Rr" ) ; return readyPromise . then ( r => { r . cancel = ( ) => { subscript . unsubscribe ( ) ; promptLockResolve ( true ) ; } ; return r ; } ) ; }
State machine to read screen events and turn them into screens of prompts.
State machine to read screen events and turn them into screens of prompts .
// If this doens't exist, we're running against a hardware ledger; just call // interactionFunc with no events iterator. // This is so that you can just "await flowAccept(this.speculos);" in a test // without actually waiting for the prompts.  If we don't do this, you can // end up with two flowAccept calls active at once, causing issues. // Set ourselves as the interaction. // Make an async iterator we can push stuff into. // Sync up with the ledger; wait until we're on the home screen, and do some // clicking back and forth to make sure we see the event. // Then pass screens to interactionFunc. // Resolve our lock when we're done // Wrap up two-line prompts into one: // The top line comes out first, so now wait for the next draw. // Send a rightward-click to make sure we get _an_ event and our state // machine starts.