digraph G { initial[label="", shape="circle"]; pending_create[label="pending(purse-create)"]; suspended_create[label="suspended(purse-create)", shape="box"]; pending_qr[label="pending(qr-ready)"]; aborting_delete[label="aborting(delete-purse)"]; aborting_refresh[label="aborting(refresh)"]; aborting_refund[label="aborting(refund)"]; // FIXME(CG): operation unclear // pending_refundable[label="pending(refundable)"]; done[label="done", shape="box"]; aborted[label="aborted", shape="box"]; failed[label="failed", shape="box"]; deleted[label="deleted", shape="box"]; subgraph { rank = same; done; aborted; failed; } initial->pending_create [color="blue", label="push debit form data"]; pending_create->suspended_create [color="blue", label="suspend"]; pending_create->aborting_refund [color="red", label="failure"]; pending_create->pending_qr; suspended_create->pending_create [color="blue", label="resume"]; suspended_create->aborting_refund [color="blue", label="abort"]; pending_qr->aborting_delete [color="blue", label="abort"]; pending_qr->aborting_refresh [label="purse-timeout"]; pending_qr->done [label="poll-success"]; // FIXME(CG): or go to delete_purse? Or just retry? pending_qr->aborting_refresh [color="red", label="poll-failure"]; aborting_delete->aborting_refresh; aborting_delete->done [color="red", label="processed-failed\n(already-merged)"]; aborting_delete->aborting_refresh [color="red", label="failed(other)"]; aborting_delete->failed [color="blue", label="abort-force"]; aborting_refresh->aborted; aborting_refresh->failed [color="red", label="failed"]; aborting_refresh->failed [color="blue", label="abort-force"]; aborting_refund->aborting_refresh; aborting_refund->aborting_refresh [color="red", label="failed"]; aborting_refund->failed [color="blue", label="abort-force"]; done->deleted [color="blue", label="delete"]; aborted->deleted [color="blue", label="delete"]; failed->deleted [color="blue", label="delete"]; }