taler-docs

Documentation for GNU Taler components, APIs and protocols
Log | Files | Refs | README | LICENSE

037-wallet-transactions-lifecycle.rst (38744B)


      1 DD 37: Wallet Transaction Lifecycle
      2 ###################################
      3 
      4 .. contents:: Table of Contents
      5    :depth: 2
      6 
      7 Summary
      8 =======
      9 
     10 This design doc discusses the lifecycle of transactions in wallet-core.
     11 
     12 Motivation
     13 ==========
     14 
     15 The transactions in wallet-core all should have an associated state machine.  All transactions
     16 should have some common actions that work uniformly across all transactions.
     17 
     18 Requirements
     19 ============
     20 
     21 The underlying state machine should make it obvious what interactions
     22 are possible for the user.  The number of possible user interactions
     23 in any state should be small.
     24 
     25 Proposed Solution
     26 =================
     27 
     28 
     29 Common States
     30 -------------
     31 
     32 The following states apply to multiple different transactions.  Only pending
     33 and aborting have transaction-specific sub-states, denoted by ``state(substate)``.
     34 
     35 ``pending``: A pending transaction waits for some external event/service.
     36 The transaction stays pending until its change on the wallet's material balance
     37 is finished. Any pending state can be suspended and resumed.
     38 
     39 There are some other distinctions for pending transactions:
     40 
     41 * long-polling vs. exponential backoff: A pending transaction is either waiting
     42   on an external service by making a long-polling request or by repeating requests
     43   with exponential back-off.
     44 * ``lastError``: A pending transaction is either clean (i.e. the network interaction
     45   is literally active in transmission or the external service successfully
     46   communicated that it is not ready yet and this is perfectly normal)
     47   or has a ``lastError``, which is a ``TalerErrorDetails``
     48   object with details about what happened during the last attempt to proceed
     49   with the transaction.
     50 
     51 ``finalizing``: A finalizing transaction is functionally similar to a ``pending`` transaction,
     52 but is not shown to the user as a pending transaction. It is effectively finished from a user's
     53 perspective, but some processing can happen on the transaction that might lead to some
     54 other state than ``done``.
     55 
     56 ``done``: A transaction that is done does not require any more processing.  It also
     57 never has a ``lastError`` but is considered successful.
     58 
     59 ``dialog``: A transaction requires input from the user.
     60 
     61 ``aborting``: Similar to a pending transaction, but instead of taking active steps to
     62 complete the transaction, the wallet is taking active steps to abort it. The ``lastError``
     63 indicates errors the wallet experienced while taking active steps to abort the transaction.
     64 
     65 ``aborted``: Similar to ``done``, but the transaction was successfully aborted
     66 instead of successfully finished. It will have the information of when (timestamp) it was
     67 aborted and in which pending sub-state the abort action was initiated. Also, we can
     68 include more information information relevant to the transaction in ``abortReason``
     69 
     70 ``suspended``: Similar to a ``aborted`` transaction, but the transaction was could be
     71 resumed and may then still succeed.
     72 
     73 ``suspended-aborting``:  Network requests or other expensive work
     74 to abort a transaction is paused.
     75 
     76 ``failed``: Similar to ``done``, but the transaction could not be completed or
     77 possibly not even be aborted properly.  The user may have lost money.  In some
     78 cases, a report to the auditor would make sense in this state.
     79 
     80 ``expired``: Similar to ``failed``, but the failure was caused by a timeout.
     81 
     82 ``deleted``: A ``deleted`` state is always a final state.  We only use this
     83 state for illustrative purposes. In the implementation, the data associated
     84 with the transaction would be literally deleted.
     85 
     86 
     87 Common Transitions
     88 ------------------
     89 
     90 Transitions are actions or other events.
     91 
     92 ``[action:retry]``: Retrying a transaction *(1.)* stops ongoing long-polling
     93 requests for the transaction *(2.)* resets the retry timeout *(3.)* re-runs the
     94 handler to process the transaction. Retries are always possible the following
     95 states: ``pending(*)`` and ``aborting(*)``.
     96 
     97 .. attention::
     98 
     99    Should we show the retry timeout in the UI somewhere?  Should we show it in dev mode?
    100 
    101    SEBASJM: Since the wallet will retry anyway, maybe is better if we replace the "retry"
    102    button with a "try now" button and a side text "retrying in xxx seconds".
    103 
    104    CG: Instead of a side text, this *might* make a good mouse-over hint for
    105    a "retry" (or "try now") button. I would not make this overly visible with
    106    side-text as the information is not that important. The text should also be
    107    "retrying next at XXX" using an absolute time XXX --- otherwise the UI would
    108    be way too busy recomputing/updating all of these strings: Using an absolute time,
    109    we only have to redraw anything once a retry actually happened. Given that
    110    retries should basically never be > 24h (we can impose a hard cap), the absolute
    111    time can just be in the format HH:MM:SS (without day).
    112 
    113 ``[action:suspend]``: Suspends a pending transaction, stopping any associated
    114 network activities, but with a chance of trying again at a later time. This
    115 could be useful if a user needs to save battery power or bandwidth and an
    116 operation is expected to take longer (such as a backup, recovery or very large
    117 withdrawal operation).
    118 
    119 ``[action:resume]``: Suspended transactions may be resumed, placing them back
    120 into a pending state.
    121 
    122 ``[action:abort]``: Aborting a transaction either directly stops processing for the
    123 transaction and puts it in an ``aborted`` state, or starts the necessary steps to
    124 actively abort the transaction (e.g. to avoid losing money) and puts it in an
    125 ``aborting`` state.
    126 
    127 ``[action:fail]``: Directly puts an ``aborting`` or ``pending`` transaction into a
    128 ``failed`` state. May result in an ultimate loss of funds (beyond fees) to the
    129 user and thus requires additional consent.
    130 
    131 ``[action:delete]``: Deleting a transaction completely deletes the transaction
    132 from the database.  Depending on the type of transaction, some of the other
    133 data *resulting* from the transaction might still survive deletion. For
    134 example, deleting a withdrawal transaction does not delete already
    135 successfully withdrawn coins. Deleting is only safe (no money lost) on initial
    136 and final states (failed, aborted, done).
    137 
    138 Whether aborting, deleting or suspending are possible depends on
    139 the transaction type, and usually only one of the four choices should be
    140 offered.
    141 
    142 
    143 .. image:: ../images/transaction-common-states.png
    144 
    145 
    146 Boxed labels indicate an end state in which there is no network activity and
    147 hence no need to give the user a way to abort or suspend the activity.  The
    148 circle indicates the initial state.  Ovals are states with network activity.
    149 
    150 Blue arrows are used for user-triggered actions (via UI buttons).  Purple
    151 arrows are used to indicate externally triggered actions.  Black arrows
    152 without labels are used for the normal successful path.  Red arrows indicate
    153 failure paths.
    154 
    155 
    156 Common pending sub-states
    157 -------------------------
    158 
    159 During the pending state the transaction can go through several sub-states before
    160 reaching a final state. Some of this sub-states are shared between different
    161 transaction types:
    162 
    163 ``kyc``: The transaction cannot proceed because the user needs to actively
    164 finish a KYC process.  The wallet should show the user a hint on how to
    165 start the KYC process.
    166 
    167 ``aml``: The transaction can't proceed because the user needs to wait for the
    168 exchange operator to conclude an AML investigation by the staff at the
    169 exchange.  There are two AML substates. In the substate ``pending`` the user
    170 is not expected to take any action and should just wait for the investigation
    171 to conclude. In the substate ``frozen`` the staff at the exchange decided that
    172 the account needed to be frozen.  The user should contact the exchange
    173 provider's customer service department and seek resolution (possibly through
    174 the courts) to avoid losing the funds for good.
    175 
    176 
    177 Transaction Type: Withdrawal
    178 ----------------------------
    179 
    180 * ``dialog(proposed)``
    181 
    182   Initial dialog state for bank-integrated withdrawals.  In this state, the user must confirm
    183   the withdrawal to proceed, and possibly provide further information (such as the amount).
    184 
    185   Depending on how a bank-integrated withdrawal transaction is created,
    186   it starts either in this state or in ``pending(bank-register-reserve)``.
    187   
    188 
    189 * ``pending(bank-register-reserve)``
    190 
    191   Initial active state for bank-integrated withdrawals.  The wallet submits the reserve public key
    192   and selected exchange to the bank (via the bank integration API).  Note that if the
    193   user aborts at this stage, we do not know if the bank is in the confirmation stage,
    194   so we must still *try* to abort the transaction at the bank.
    195 
    196   * ``[processed-success] => pending(bank-confirm-transfer)``
    197   * ``[processed-error] => failed``: On permanent errors (like 404 for the withdrawal operation),
    198     the wallet gives up.
    199   * ``[action:abort] => aborting(bank)``
    200 
    201 * ``pending(bank-confirm-transfer)``
    202 
    203   The wallet waits until the bank has confirmed the withdrawal operation;
    204   usually the user has to complete a 2FA step to *approve* that the money is
    205   wired to the chosen exchange.  Note that the user's *approve* action is done
    206   in the bank's user interface and not the wallet's user interface. The wallet
    207   internally merely *polls* for the success or failure of the approve action.
    208   The wallet **may** occasionally (after some initial delay, especially on
    209   failures from the bank-poll to return any result) long-poll for the reserve
    210   status and, if successful, may then directly jump to
    211   ``pending(withdraw-coins)`` if the reserve is filled even if the poll at
    212   the bank did not return success or failure.
    213 
    214   * ``[bank-poll-success] => pending(exchange-wait-reserve)``
    215   * ``[bank-aborted] => aborted``: Bank denied the operation.
    216   * ``[exchange-poll-success] => pending(withdraw-coins)``:  Optional
    217     short-cut transition. Exchange was faster than the bank.
    218   * ``[action:abort] => aborting(bank)``
    219 
    220 * ``aborting(bank)``
    221 
    222   The user aborted the withdraw operation in the wallet.  The wallet must now
    223   try to signal the bank that the wire transfer should no longer be performed.
    224   Note that it is possible that the bank registration never succeeded (if the
    225   user aborted us during ``pending(bank-register-reserve)``) and in this case
    226   we get an ``unknown transaction`` failure here.  It is also theoretically
    227   possible that the user approved the transaction in the bank while
    228   simultaneously aborting in the wallet. In this case, we transition to
    229   ``suspended(exchange-wait-reserve)`` (treating the ``abort`` action as a ``suspend``
    230   action).
    231 
    232   * ``[processed-success] => aborted``
    233   * ``[processed-error(already-confirmed)] => suspended(exchange-wait-reserve)``: We
    234     keep a transaction history entry reminding the user about when the already
    235     wired funds will be returned.
    236   * ``[processed-error(unknown-transaction)] => failed``
    237 
    238 * ``suspended(exchange-wait-reserve)``
    239 
    240   State where funds were (presumably) wired to the exchange but the wallet
    241   was asked to not proceed with the withdraw, but we still resume.
    242 
    243   In this state, the wallet should show to the user that the money from the
    244   withdrawal reserve will be sent back to the originating bank account after
    245   ``$closing_delay``.  Note that the ``resume`` action should be disabled
    246   after ``$closing_delay``.
    247 
    248   * ``[action:delete] => deleted``
    249   * ``[action:resume] => pending(exchange-wait-reserve)``
    250 
    251 * ``pending(exchange-wait-reserve)``
    252 
    253   Initial state for manual withdrawals.  Here, the wallet long-polls the
    254   exchange for the reserve status, waiting for the wire transfer to arrive
    255   at the exchange.
    256 
    257   * ``[exchange-poll-success] => pending(withdraw-coins)``
    258   * ``[action:suspend] => suspended(exchange-wait-reserve)``
    259 
    260 * ``pending(withdraw-coins)``
    261 
    262   State where we are finally withdrawing the actual coins. Depending on
    263   the AML and KYC thresholds, we may at any time transition into a
    264   holding pattern on the AML or KYC checks of the exchange.
    265 
    266   It is possible that the selected denominations expired.
    267   In that case, the wallet will re-select denominations.
    268 
    269   * ``[processed-success] => done``
    270   * ``[processed-kyc-required] => pending(kyc)``
    271   * ``[processed-aml-required] => pending(aml)``
    272   * ``[reserve-expired] => expired(reserve)``
    273   * ``[action:suspend] => suspended(withdraw-coins)``
    274 
    275 * ``pending(kyc)``
    276 
    277   State where the user needs to provide some identity data to pass a KYC
    278   check.  The wallet only shows the user the link for starting the KYC
    279   process and long-polls the exchange in anticipation of the user
    280   completing the KYC requirement.
    281 
    282   * ``[poll-success] => pending(withdraw-coins)``
    283   * ``[action:suspend] => suspended(kyc)``
    284 
    285 * ``suspended(kyc)``
    286 
    287   State where the user needs to provide some identity data to pass a KYC
    288   check, but the long-polling was explicitly stopped. The user can
    289   choose to resume or delete.
    290 
    291   * ``[action:delete] => deleted``
    292   * ``[action:resume] => pending(kyc)``
    293 
    294 * ``pending(aml)``
    295 
    296   State where the wallet needs to wait for completion of an AML process by an
    297   AML officer of the exchange. The wallet shows that the AML process is
    298   blocking progress. The message shown should distinguish between a mere
    299   pending AML process and an AML freezing decision in terms of the message
    300   shown to the user. If the AML decision is pending at the exchange, he user
    301   should be urged to simply wait.  If the funds were frozen, the wallet
    302   informs the user that their funds were frozen due to an AML decision.  The
    303   user is urged to contact the exchange operator's AML department out-of-band.
    304   In any case, the wallet long-polls for the AML decision to be made or change
    305   (possibly at a lower frequeny in case of a freeze).
    306 
    307   * ``[poll-success] => pending(withdraw-coins)``
    308   * ``[action:suspend] => suspended(aml)``
    309 
    310 * ``suspended(aml)``
    311 
    312   State where the user needs to await some AML decision by the exchange.
    313   The long-polling was explicitly stopped. The user can choose to resume or delete.
    314 
    315   * ``[action:delete] => deleted``
    316   * ``[action:resume] => pending(aml)``
    317 
    318 * ``suspended(withdraw-coins)``
    319 
    320   In this state, the wallet should show how much money arrived into the wallet
    321   and the rest of the money will be sent back to the originating bank account
    322   after ``$closing_delay``.  Note that the ``resume`` action should be
    323   disabled after ``$closing_delay``.
    324 
    325   * ``[action:delete] => deleted``
    326   * ``[action:resume] => pending(exchange-wait-reserve)``
    327 
    328 * ``done``
    329 
    330   The withdrawal operation is complete.
    331 
    332   * ``[action:delete] => deleted``
    333 
    334 * ``deleted``
    335 
    336   Withdrawn coins are preserved, as is reserve information for recoup.
    337   So this mostly removes the entry from the visible transaction history.
    338   Only once all coins were spent, the withdraw is fully removed.
    339 
    340 
    341 .. image:: ../images/transaction-withdrawal-states.png
    342 
    343 
    344 Transaction Type: Payment to Merchant
    345 -------------------------------------
    346 
    347 * ``pending(claim-proposal)``
    348 
    349   We received a ``pay`` URI. Download (claim) the proposal from the merchant.  Can fail if
    350   the proposal was already claimed by someone else.  If repurchase detection
    351   tells us that we already paid for this product, we go immediately to
    352   ``failed(repurchase)`` state for this transaction, but with a side-effect of
    353   transitioning the UI into a ``pending(repurchase-session-reset)`` on a
    354   *different* transaction (which before was in ``done``).
    355 
    356   A ``failed(repurchase)`` transaction will eventually be GCed (=deleted)
    357   automatically.
    358 
    359   * ``[error:already-claimed] => failed(already-claimed)`` -- the proposal was
    360     already claimed by someone else.
    361   * ``[error:invalid-proposal] => failed(invalid-proposal)`` -- the merchant provided a
    362     proposal that is invalid (e.g. malformed contract
    363     terms or bad signature).
    364 
    365 * ``dialog(merchant-order-proposed)``
    366 
    367   Let the user accept (or refuse) the payment.
    368 
    369   * ``[action:pay-accept] => pending(submit-payment)``
    370   * ``[action:pay-refuse] => ``aborted(refused)`` -- The user explicitly
    371     decided not to proceed (at least not with this wallet).
    372   * ``[expired] => failed(expired)`` -- The offer has expired before the user made any
    373     decision. Note that we should use this transition at
    374     least a few seconds before the offer *actually* expires to avoid
    375     encountering an expiration during ``pending(submit-payment)`` in most
    376     real-world scenarios. Basically, we should prevent last-second payments to
    377     be event attempted client-side.
    378 
    379     The ``failed(expired)`` might be automatically deleted upon GC.
    380 
    381 * ``pending(submit-payment)``
    382 
    383   Submit coin-by-coin (or in bulk groups) until payment is complete.
    384 
    385   * ``[action:abort] => aborting(pay-incomplete)`` -- The user explicitly decided to
    386     abort the process while the payment was happening.  Note that if the
    387     payment was already completed (and hence the merchant refuses any
    388     refunds), it is theoretically possible that pressing the abort button will
    389     nevertheless end up in a ``finalizing(auto-refund)`` state (and subsequently
    390     a ``done`` state) instead!
    391   * ``[success] => finalizing(auto-refund)`` -- Upon receiving confirmation from
    392     the merchant that the purchase was completed.
    393   * ``[error(insufficient balance)] => aborting(pay-incomplete)`` This transition
    394     happens if we detect double-spending and our balance is not sufficient
    395     after the double-spending. It is also conceivable (but should be rare)
    396     that this transition happens because the offer expired.
    397 
    398 * ``finalizing(auto-refund)``
    399 
    400   The payment succeed. We remain in this state as long as an auto-refund-check
    401   is active.  If auto refunds are not enabled, we immediately continue to
    402   ``done``.
    403 
    404   * ``[no-auto-refund] => done``
    405   * ``[timeout] => done`` -- This happens when the auto refund set by the
    406     contract expired.
    407   * ``[long-poll:refund] => aborting(pay-incomplete)`` -- An auto-refund was detected.
    408   * ``[action:abort] => done`` -- The user may explicitly request to abort the
    409     auto-refund processing (for example to enable subsequent deletion before
    410     the auto-refund delay expires).
    411 
    412 * ``aborting(pay-incomplete)``
    413 
    414   The wallet should interact with the merchant to request
    415   a refund on the incomplete payment.
    416 
    417   * ``[success] => aborted(pay-incomplete)``
    418   * ``[already-paid] => done``
    419 
    420 * ``aborted(refunded)``
    421 
    422   The purchase ended with a (partial) refund. The state (and UI) should show
    423   the specific provenance of the state, which may include an insufficient
    424   balance (due to double-spending being detected during payment), and one or
    425   more partial or full refunds.
    426 
    427   * ``[action:delete] => deleted``
    428 
    429 * ``done``
    430 
    431   The purchase is completed.
    432 
    433   * ``[action:delete] => deleted``
    434   * ``[repurchase] => pending(rebind-session)``: Another offer
    435     became pending for this product and we need to update the session so
    436     that the user does not have to buy it again.
    437   * ``[check-refunds]` => pending(check-refunds)``: New refunds
    438     might be available for this purchase.
    439 
    440 * ``pending(check-refund)``
    441 
    442   New refunds might be available for this purchase.
    443   This state must only be entered *after* the payment has successfully
    444   completed.  It is not relevant for auto-refunds or refunds for incomplete
    445   payments.
    446 
    447   * ``[refunds-checked] => pending(user-new-refund)`` --- New
    448     refund(s) are available, user needs to confirm.
    449   * ``[refunds-checked] => done`` --- Refunds were checked, but no
    450     new refunds are available.
    451   * ``[action:stop-refund-query] => done`` ---
    452     This action would usually only be offered when the state is pending
    453     with errors. It stops the refund query, but the payment of course
    454     is left intact.
    455 
    456 * ``pending(rebind-session)``
    457 
    458   The wallet should reset the associated session for the already purchased
    459   (digital) item.
    460 
    461   * ``[success] => done``
    462   * ``[action:abort] => done`` -- User aborted the session reset.
    463 
    464 * ``deleted``
    465 
    466   When a payment is deleted, associated refund transactions are always deleted
    467   with it.
    468 
    469 .. image:: ../images/transaction-payment-states.png
    470 
    471 
    472 Transaction Type: Refund
    473 ------------------------
    474 
    475 A refund is a pseudo-transaction that is always associated with a merchant
    476 payment transaction.
    477 
    478 * ``pending(accept)``
    479 
    480   Initial state for a refund.
    481 
    482   * ``[processed-error] => failed``: we received a permanent failure (such as money already wired to the merchant)
    483 
    484 * ``failed``
    485 
    486   The refund failed permanently.
    487 
    488 .. image:: ../images/transaction-refund-states.png
    489 
    490 
    491 Transaction Type: Refresh
    492 -------------------------
    493 
    494 This is about refreshes that are triggered via coin expiration or as part of
    495 getting change after making a payment.  In the first case, the refresh
    496 transaction is forever shown as a separate transaction in the history unless
    497 it did not affect the wallet balance (in which case we hide it). In the second
    498 case, the refresh transaction is folded into the payment transaction upon
    499 completion, so that the balance changes are included in the fees of the
    500 transaction that caused us to obtain change.
    501 
    502 If we have to adjust the refund amount (because a coin has fewer funds on it
    503 than we expect) the transaction only shows the changes due to the refresh, and
    504 we merely adjust the current balance of the wallet but without giving any
    505 justification (as we cannot give details we do not have). So this will look
    506 the same as if the double-spending transaction had been deleted by the user.
    507 
    508 * ``pending``
    509 
    510   A refresh operation is pending.
    511 
    512   * ``[processed-success] => done``
    513   * ``[action:suspend] => suspended``
    514   * ``[failed] => failed``
    515 
    516 * ``suspended``
    517 
    518   A refresh operation was suspended by the user.
    519 
    520   * ``[action:resume] => pending``
    521 
    522 * ``done``
    523 
    524   The refresh operation completed.
    525 
    526   * ``[action:delete] => deleted``
    527 
    528 * ``failed``
    529 
    530   The refresh operation failed. The user lost funds.
    531 
    532   * ``[action:delete] => deleted``
    533 
    534 * ``deleted``
    535 
    536   All memory of the refresh operation is lost, but of course the resulting
    537   fresh coins are preserved.
    538 
    539 .. image:: ../images/transaction-refresh-states.png
    540 
    541 
    542 Transaction Type: Deposit
    543 -------------------------
    544 
    545 * ``pending(deposit)``
    546 
    547   Initial state for deposit transactions.
    548   We deposit the amount coin-by-coin (or in bulk groups) until deposit is completed.
    549 
    550   * ``[action:suspend] => suspended(submit-deposit)``
    551   * ``[processed-success] => pending(track)``
    552   * ``[processed-failure] => aborting(refund)``
    553 
    554 * ``suspended(deposit)``
    555 
    556   The user suspended our ongoing deposit operation.
    557 
    558   * ``[action:resume] => pending(deposit)``
    559   * ``[action:abort] => aborting(refund)``
    560 
    561 * ``pending(track)``
    562 
    563   All the coins were submitted, waiting to be wired.
    564 
    565   * ``[poll-success] => done``
    566   * ``[poll-accepted-kyc] => pending(kyc)``
    567   * ``[poll-accepted-aml] => pending(aml)``
    568   * ``[action:abort] => aborting(refund)``
    569 
    570 * ``pending(kyc)``
    571 
    572   Exchange requires KYC before making the wire transfer.
    573 
    574   * ``[long-poll:kyc] => done``
    575   * ``[action:suspend] => suspended(kyc)``
    576 
    577 * ``suspended(kyc)``
    578 
    579   The user suspended us while we were waiting for KYC to be finished.
    580 
    581   * ``[action:resume] => pending(kyc)``
    582 
    583 * ``pending(aml)``
    584 
    585   Exchange requires AML before making the wire transfer.
    586 
    587   * ``[long-poll:aml] => done``
    588   * ``[action:suspend] => suspended(aml)``
    589 
    590 * ``suspended(aml)``
    591 
    592   The user suspended us while we were waiting for AML to be finished.
    593 
    594   * ``[action:resume] => pending(aml)``
    595 
    596 * ``aborting(refund)``
    597 
    598   Wallet should try to get the deposited amount back from the exchange (by submitting a refund).
    599 
    600   * ``[action:suspend] => suspended(refund)``
    601   * ``[processed-success] => aborting(refresh)``
    602   * ``[processed-error] => aborting(refresh)``: Even if the refund attempt failed, maybe the deposit failed as well and we can still succeed with a refresh.
    603 
    604 * ``suspended(refund)``
    605 
    606   The user suspended us while we were trying to get a refund.
    607 
    608   * ``[action:resume] => aborting(refund)``
    609 
    610 * ``aborting(refresh)``
    611 
    612   * ``[action:suspend] => suspended(refresh)``
    613   * ``[processed-success] => aborted``
    614   * ``[processed-error] => failed``
    615 
    616 * ``suspended(refresh)``
    617 
    618   The user suspended us while we were trying to do the refresh.
    619 
    620   * ``[action:resume] => aborting(refresh)``
    621 
    622 * ``aborted``
    623 
    624   The operation was aborted, some funds may have been lost (to fees or deposited anyway).
    625 
    626   * ``[action:delete] => deleted``
    627 
    628 * ``done``
    629 
    630   The deposit operation completed.
    631 
    632   * ``[action:delete] => deleted``
    633 
    634 * ``deleted``
    635 
    636   All memory of the deposit operation is lost.
    637 
    638 .. image:: ../images/transaction-deposit-states.png
    639 
    640 
    641 Transaction Type: Peer Push Debit
    642 ---------------------------------
    643 
    644 Peer Push Debit transactions are created when the user wants to transfer money
    645 to another wallet.
    646 
    647 States and transitions:
    648 
    649 * ``pending(purse-create)``
    650 
    651   The wallet is creating a purse. Initial state.
    652 
    653   * ``[process-success] => pending(ready)``: The wallet has created the purse.
    654   * ``[process-failure] => aborting(refund)``: The purse creation failed.
    655   * ``[action:suspend] => suspended(purse-create)``: The user suspended the operation.
    656 
    657 * ``suspended(purse-create)``
    658 
    659   * ``[action:resume] => pending(purse-create)``: The user resumed the operation.
    660   * ``[action:abort] => aborting(refund)``: The user aborted the operation.
    661 
    662 * ``pending(ready)``
    663 
    664   In this state, the user can send / show the ``taler://`` URI or QR code to somebody else.
    665 
    666   * ``[action:abort] => aborting(delete-purse)``: The user aborts the P2P payment. The wallet tries to reclaim money in the purse.
    667   * ``[purse-timeout] => aborting(refresh)``: The other party was too slow and the purse has now expired.
    668   * ``[poll-success] => done``: The other party has accepted the payment.
    669   * ``[poll-error] => aborting(refresh)``: The exchange claims that there is a permanent error regarding the purse.  (FIXME(CG): not clear that this is the best transition! Could also go to ``aborting(refund)`` or ``aborting(delete-purse)``; best choice may depend on the specific error returned.)
    670 
    671 * ``aborting(delete-purse)``
    672 
    673   The wallet is deleting the purse to prevent the receiver from merging it and to reclaim the funds in it.
    674 
    675   * ``[processed-success] => aborting(refresh)``: The purse was deleted successfully, and refunded coins must be refreshed.
    676   * ``[processed-failed(already-merged)] => done``: The other party claimed the funds faster that we were able to abort.
    677   * ``[processed-failed(other)] => aborting(refresh)``:  The exchange reports a permanent error.  We still try to refresh.
    678   * ``[action:fail] => failed``: The user explicitly asked us to give up and accepted the possible loss of funds.
    679 
    680 * ``aborting(refund)``
    681 
    682   We abandon the purse that was never fully funded and ask for the deposited coins to be refunded.
    683 
    684   * ``[processed-success] => aborting(refresh)``: After the refund, we still need to refresh the coins.
    685   * ``[processed-failure] => aborting(refresh)``: The refund failed, we still try to refresh the coins.
    686   * ``[action:fail] => failed``: The user explicitly asked us to give up and accepted the possible loss of funds.
    687 
    688 * ``aborting(refresh)``
    689 
    690   * ``[processed-success] => aborted``: Refresh group finished. Aborting was successful, money was reclaimed.
    691   * ``[processed-failed] => failed``: Refresh group failed to complete with a permanent error.
    692   * ``[action:fail] => failed``: The user explicitly asked us to give up and accepted the possible loss of funds.
    693 
    694 * ``done``
    695 
    696   The transfer was successful.
    697 
    698   * ``[action:delete] => deleted``
    699 
    700 * ``aborted``
    701 
    702   The transfer was aborted. Except for fees, the money was recovered.
    703 
    704   * ``[action:delete] => deleted``
    705 
    706 * ``failed``
    707 
    708   The transfer failed. Money was lost. Unless on a forced abort, we should probably complain to the auditor.
    709 
    710   * ``[action:delete] => deleted``
    711 
    712 * ``deleted``
    713 
    714   All memory of the push debit operation is lost.
    715 
    716 .. image:: ../images/transaction-push-debit-states.png
    717 
    718 
    719 Transaction Type: Peer Push Credit
    720 ----------------------------------
    721 
    722 Peer Push Credit transactions are created when the user accepts to be paid via
    723 a ``taler://pay-push`` URI.
    724 
    725 States and transitions:
    726 
    727 * ``pending(download)``
    728 
    729   Wallet read the taler:// URI and is downloading the contract details for the user.
    730 
    731   * ``[processed-success] => pending(user)``: Contract can be shown to the user.
    732   * ``[action:suspend] => suspended(download)``: User suspended the operation.
    733 
    734 * ``suspended(download)``
    735 
    736   The download of the purse meta data was suspended by the user.
    737 
    738   * ``[action:resume] => pending(download)``
    739 
    740 * ``pending(user)``
    741 
    742   User needs to decide about accepting the money.
    743 
    744   * ``[action:accept] => pending(merge)``
    745   * ``[timeout] => failed``: User took too long to decide.
    746 
    747 * ``pending(merge)``
    748 
    749   * ``[processed-success] => pending(withdraw)``: Merging the reserve was successful.
    750   * ``[kyc-required] => pending(merge-kyc)``: User must pass KYC checks before the purse can be merged.
    751   * ``[timeout] => failed``: The purse expired before we could complete the merge.
    752   * ``[failure] => failed``: The merge failed permanently.
    753   * FIXME(CG): do we want to allow suspending here?
    754 
    755 * ``pending(merge-kyc)``
    756 
    757   We cannot merge the purse until passing a KYC check.
    758   The user is shown a hint where to begin the KYC
    759   process and the wallet long-polls on the KYC status.
    760 
    761   * ``[poll-success] => pending(withdraw)``
    762   * ``[action:suspend] => suspended(kyc)``
    763   * ``[timeout] => failed``: The purse expired before we could complete the merge.
    764 
    765 * ``suspended(merge-kyc)``
    766 
    767   We cannot merge the purse until passing a KYC check,
    768   and that check was suspended by the user.
    769 
    770   * ``[action:resume] => pending(kyc)``
    771   * ``[timeout] => failed``: The purse expired before we could complete the merge.
    772 
    773 * ``pending(withdraw)``
    774 
    775   The wallet is withdrawing coins from the reserve that was filled by merging
    776   the purse.
    777 
    778   * ``[kyc-required] => pending(withdraw-kyc)``
    779   * ``[aml-required] => pending(withdraw-aml)``
    780   * ``[withdraw-failure] => failed``
    781   * ``[withdraw-success] => done``
    782   * ``[action:suspend] => suspended(withdraw)``
    783 
    784 * ``suspended(withdraw)``
    785 
    786   The user requested the withdraw operation to be suspended.
    787 
    788   * ``[action:resume] => pending(withdraw)``
    789 
    790 * ``pending(withdraw-kyc)``
    791 
    792   We cannot withdraw more coins until passing a KYC check.
    793   The user is shown a hint where to begin the KYC
    794   process and the wallet long-polls on the KYC status.
    795 
    796   * ``[poll-success] => pending(withdraw-coins)``
    797   * ``[action:suspend] => suspended(withdraw-kyc)``
    798 
    799 * ``suspended(withdraw-kyc)``
    800 
    801   We cannot withdraw from the reserve until passing a KYC check,
    802   and that check was suspended by the user.
    803 
    804   * ``[action:resume] => pending(withdraw-kyc)``
    805 
    806 * ``pending(withdraw-aml)``
    807 
    808   We cannot withdraw more coins until AML rules are satisfied.
    809   The user is shown a hint as to the AML status (pending or frozen).
    810 
    811   * ``[poll-success] => pending(withdraw-coins)``
    812   * ``[action:suspend] => suspended(withdraw-aml)``
    813 
    814 * ``suspended(withdraw-aml)``
    815 
    816   We cannot withdraw from the reserve until AML rules are satisfied,
    817   and the status check was suspended by the user.
    818 
    819   * ``[action:resume] => pending(withdraw-aml)``
    820   * ``[action:delete] => deleted``
    821 
    822 * ``failed``
    823 
    824   The operation failed. Details are shown to the user. The money from the purse eventually goes to the sender (or some other wallet that merged it).
    825 
    826   * ``[action:delete] => deleted``
    827 
    828 * ``done``
    829 
    830   The operation succeeded.
    831 
    832   * ``[action:delete] => deleted``: No money will be lost, the withdrawn coins will be kept
    833 
    834 * ``deleted``
    835 
    836   All memory of the push credit operation is lost.
    837 
    838 .. image:: ../images/transaction-push-credit-states.png
    839 
    840 
    841 Transaction Type: Peer Pull Credit
    842 ----------------------------------
    843 
    844 TODO: Also specify variant where account reserve needs to be created / funded first (Note: post 1.0-feature).
    845 
    846 * ``pending(purse-create)``
    847 
    848   The wallet is creating a purse. Initial state.
    849 
    850   * ``[process-success] => pending(ready)``: The wallet has created the purse.
    851   * ``[process-failure] => deleted``: The purse creation failed. We only show a transient error.
    852   * ``[action:abort] => deleted``: The user aborted the operation.
    853 
    854 * ``pending(ready)``
    855 
    856   In this state, the user can send / show the ``taler://`` URI or QR code to
    857   somebody else.
    858 
    859   * ``[action:abort] => aborting(delete-purse)``: The user aborts the P2P payment.
    860   * ``[purse-timeout] => aborted``: The other party was too slow and the purse
    861     has now expired.
    862   * ``[poll-success] => pending(withdraw)``: The other party has made the payment.
    863   * ``[poll-error] => aborting(delete-purse)``: The exchange claims that there
    864     is a permanent error regarding the purse.  We should try to delete it.
    865 
    866 * ``aborting(delete-purse)``
    867 
    868   We are cleaning up the purse after the operation failed or was aborted by
    869   the user.
    870 
    871   * ``[failure:already-merged] => pending(withdraw)``: Too late to abort, the
    872     other side already paid the invoice.
    873   * ``[process-success] => aborted``: The wallet has deleted the purse.
    874   * ``[failure:other] => failed``: The purse deletion failed; we are
    875     nevertheless done.
    876   * ``[action:fail] => failed``: Money may be lost if it was deposited
    877     into the purse in the meantime.
    878 
    879 * ``aborted``
    880 
    881   The invoicing process ended without success.
    882 
    883   * ``[action:delete] => deleted``
    884 
    885 * ``pending(withdraw)``
    886 
    887   The wallet is withdrawing the money paid for the invoice.
    888 
    889   * ``[processed-success] => done``
    890   * ``[failure] => failed``
    891   * ``[processed-kyc] => pending(kyc)``
    892   * ``[processed-aml] => pending(aml)``
    893   * ``[action:suspend] => suspended(withdraw)``
    894 
    895 * ``suspended(withdraw)``
    896 
    897   The user suspended a withdraw operation.
    898 
    899   * ``[action:resume] => pending(withdraw)``
    900 
    901 * ``pending(kyc)``
    902 
    903   The user must supply KYC information before withdrawing can continue.
    904 
    905   * ``[poll-success] => pending(withdraw)``
    906   * ``[action:suspend] => suspended(kyc)``
    907 
    908 * ``suspended(kyc)``
    909 
    910   The user suspended waiting for the KYC operation to complete.
    911 
    912   * ``[action:resume] => pending(kyc)``
    913 
    914 * ``pending(aml)``
    915 
    916   The user must await a positive exchange AML decision.
    917 
    918   * ``[poll-success] => pending(withdraw)``
    919   * ``[action:suspend] => suspended(aml)``
    920 
    921 * ``suspended(aml)``
    922 
    923   The user suspended waiting for the AML decision to be successful.
    924 
    925   * ``[action:resume] => pending(aml)``
    926 
    927 * ``failed``
    928 
    929   Obtaining the money for the invoce failed. This is likely a case for the
    930   auditor.
    931 
    932   * ``[action:delete] => deleted``
    933 
    934 * ``done``
    935 
    936   The payment for the invoice was successfully received.
    937 
    938   * ``[action:delete] => deleted``
    939 
    940 * ``deleted``
    941 
    942 .. image:: ../images/transaction-pull-credit-states.png
    943 
    944 
    945 Transaction Type: Peer Pull Debit
    946 ---------------------------------
    947 
    948 * ``pending(download)``
    949 
    950   We are downloading the information about the invoice.  Initial state.
    951 
    952   * ``[action:suspend] => suspended(download)``
    953   * ``[success] => pending(user)``
    954 
    955 * ``suspended(download)``
    956 
    957   User suspended downloading the information about the invoice.
    958 
    959   * ``[action:resume] => pending(download)``
    960   * ``[action:delete] => deleted``
    961 
    962 * ``pending(user)``
    963 
    964   We have downloaded information about the pull payment and are waiting for
    965   the user to confirm.
    966 
    967   * ``[action:confirm-pay] => pending(submit-payment)``
    968   * ``[action:delete] => deleted``
    969   * ``[timeout] => aborted``
    970 
    971 * ``pending(deposit)``
    972 
    973   The user has confirmed the payment and the wallet tries to deposit
    974   into the provided purse.
    975 
    976   * ``[action:suspend] => suspended(deposit)``
    977   * ``[processed-success] => done``
    978   * ``[failure:timeout] => aborting(refresh)``
    979   * ``[processed-success] => done``
    980   * ``[failure:other] => aborting(refund)``
    981 
    982 * ``suspended(deposit)``
    983 
    984   User suspended depositing into the purse.
    985 
    986   * ``[action:resume] => pending(deposit)``
    987   * ``[action:abort] => aborting_refund``
    988 
    989 * ``aborting(refund)``
    990 
    991   Aborts the payment, asking for the already deposited coins to be refunded.
    992 
    993   * ``[processed-success] => aborted(refunded)``
    994   * ``[processed-failure] => aborting(refresh)``
    995   * ``[action:fail] => failed``
    996 
    997 * ``aborting(refresh)``
    998 
    999   Refreshes the coins that were previously deposited into the purse to recover their value.
   1000 
   1001   * ``[processed-success] => aborted``
   1002   * ``[processed-failed] => failed``
   1003 
   1004 * ``done``
   1005 
   1006   The invoice was successfully paid.
   1007 
   1008   * ``[action:delete] => deleted``
   1009 
   1010 * ``deleted``
   1011 
   1012   All information about the invoice has been deleted.
   1013 
   1014 .. image:: ../images/transaction-pull-debit-states.png
   1015 
   1016 Alternatives
   1017 ============
   1018 
   1019 * Each transaction could be treated completely separately; however, uniform
   1020   terminology for actions (and thus button labels) is likely more helpful for
   1021   the user experience.
   1022 
   1023 * We could require user re-approval if fees changed when the available
   1024   denominations change during a *withdraw*.  This would require a different
   1025   state machine on withdraw. We believe the answer can be "no", for two
   1026   reasons: the wallet MUST pick denominations to withdraw with the "most
   1027   long-term" withdraw window (i.e. active denominations that have the longest
   1028   available withdraw durations). So in virtually all normal cases, this will
   1029   just succeed as a sane exchange will have a reasonable duration overlap, and
   1030   in the very few cases it's really the user's fault for going offline in the
   1031   middle of the operation. Plus, even in those few cases, it is highly
   1032   unlikely that the fee would actually change: again most key rotations can be
   1033   expected to be there to rotate the key, and not to adjust the withdraw fee.
   1034   And in the extremely rare case that the user went offline and in the
   1035   meantime the fees did *increase*, it's again unlikely to matter much to the
   1036   user. So special-casing this and testing this is probably not worth it.
   1037 
   1038 * We could require user re-approval if due to expired/invalid coins the coin
   1039   selection (and thus fees) changes during a *deposit*.  Again, expired coins
   1040   should virtually never happen unless a user goes offline for a long time in
   1041   the middle of a purchase (which would be very strange). If deposit fees
   1042   *increase* due to a double-spend detection during payment, we might want to
   1043   have an *optional* dialog ("Balance reduced by X as wallet state was not
   1044   up-to-date (did you restore from backup?).  Consequently, the fees for this
   1045   transactions increased from Y to Z.  [Abort] [Continue] + checkbox: [X] Do
   1046   not ask again."). Probably at best a post-1.0 feature.
   1047 
   1048 
   1049 Discussion / Q&A
   1050 ================
   1051 
   1052 * The diagrams only show what is happening **after** the wallet
   1053   has created the transaction.  It is possible that network requests
   1054   are happening before that, but they are not considered to be part
   1055   of the transaction.
   1056 * We have decided against a ``cancel`` state, because it resulted
   1057   in too much complexity.  Instead of doing a direct ``cancel``,
   1058   the user has to go to the transaction and abort and/or delete
   1059   it.
   1060 * We might add a ``revive`` action in the future that allows
   1061   to go from ``aborting`` back to ``pending`` for transactions
   1062   where this makes sense.  We're not doing it right now
   1063   to simplify things.