taler-docs

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

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


      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 ``kyc-init``: The transaction cannot proceed, as the user needs to actively
    168 finish a KYC process. The information for the KYC process is still loading.
    169 
    170 
    171 Transaction Type: Withdrawal
    172 ----------------------------
    173 
    174 * ``dialog(proposed)``
    175 
    176   Initial dialog state for bank-integrated withdrawals.  In this state, the user must confirm
    177   the withdrawal to proceed, and possibly provide further information (such as the amount).
    178 
    179   Depending on how a bank-integrated withdrawal transaction is created,
    180   it starts either in this state or in ``pending(bank-register-reserve)``.
    181   
    182 
    183 * ``pending(bank-register-reserve)``
    184 
    185   Initial active state for bank-integrated withdrawals.  The wallet submits the reserve public key
    186   and selected exchange to the bank (via the bank integration API).  Note that if the
    187   user aborts at this stage, we do not know if the bank is in the confirmation stage,
    188   so we must still *try* to abort the transaction at the bank.
    189 
    190   * ``[processed-success] => pending(bank-confirm-transfer)``
    191   * ``[processed-error] => failed``: On permanent errors (like 404 for the withdrawal operation),
    192     the wallet gives up.
    193   * ``[action:abort] => aborting(bank)``
    194 
    195 * ``pending(bank-confirm-transfer)``
    196 
    197   The wallet waits until the bank has confirmed the withdrawal operation;
    198   usually the user has to complete a 2FA step to *approve* that the money is
    199   wired to the chosen exchange.  Note that the user's *approve* action is done
    200   in the bank's user interface and not the wallet's user interface. The wallet
    201   internally merely *polls* for the success or failure of the approve action.
    202   The wallet **may** occasionally (after some initial delay, especially on
    203   failures from the bank-poll to return any result) long-poll for the reserve
    204   status and, if successful, may then directly jump to
    205   ``pending(withdraw-coins)`` if the reserve is filled even if the poll at
    206   the bank did not return success or failure.
    207 
    208   * ``[bank-poll-success] => pending(exchange-wait-reserve)``
    209   * ``[bank-aborted] => aborted``: Bank denied the operation.
    210   * ``[exchange-poll-success] => pending(withdraw-coins)``:  Optional
    211     short-cut transition. Exchange was faster than the bank.
    212   * ``[action:abort] => aborting(bank)``
    213 
    214 * ``aborting(bank)``
    215 
    216   The user aborted the withdraw operation in the wallet.  The wallet must now
    217   try to signal the bank that the wire transfer should no longer be performed.
    218   Note that it is possible that the bank registration never succeeded (if the
    219   user aborted us during ``pending(bank-register-reserve)``) and in this case
    220   we get an ``unknown transaction`` failure here.  It is also theoretically
    221   possible that the user approved the transaction in the bank while
    222   simultaneously aborting in the wallet. In this case, we transition to
    223   ``suspended(exchange-wait-reserve)`` (treating the ``abort`` action as a ``suspend``
    224   action).
    225 
    226   * ``[processed-success] => aborted``
    227   * ``[processed-error(already-confirmed)] => suspended(exchange-wait-reserve)``: We
    228     keep a transaction history entry reminding the user about when the already
    229     wired funds will be returned.
    230   * ``[processed-error(unknown-transaction)] => failed``
    231 
    232 * ``suspended(exchange-wait-reserve)``
    233 
    234   State where funds were (presumably) wired to the exchange but the wallet
    235   was asked to not proceed with the withdraw, but we still resume.
    236 
    237   In this state, the wallet should show to the user that the money from the
    238   withdrawal reserve will be sent back to the originating bank account after
    239   ``$closing_delay``.  Note that the ``resume`` action should be disabled
    240   after ``$closing_delay``.
    241 
    242   * ``[action:delete] => deleted``
    243   * ``[action:resume] => pending(exchange-wait-reserve)``
    244 
    245 * ``pending(exchange-wait-reserve)``
    246 
    247   Initial state for manual withdrawals.  Here, the wallet long-polls the
    248   exchange for the reserve status, waiting for the wire transfer to arrive
    249   at the exchange.
    250 
    251   * ``[exchange-poll-success] => pending(withdraw-coins)``
    252   * ``[action:suspend] => suspended(exchange-wait-reserve)``
    253 
    254 * ``pending(withdraw-coins)``
    255 
    256   State where we are finally withdrawing the actual coins. Depending on
    257   the AML and KYC thresholds, we may at any time transition into a
    258   holding pattern on the AML or KYC checks of the exchange.
    259 
    260   It is possible that the selected denominations expired.
    261   In that case, the wallet will re-select denominations.
    262 
    263   * ``[processed-success] => done``
    264   * ``[processed-kyc-required] => pending(kyc)``
    265   * ``[processed-aml-required] => pending(aml)``
    266   * ``[reserve-expired] => expired(reserve)``
    267   * ``[action:suspend] => suspended(withdraw-coins)``
    268 
    269 * ``pending(kyc)``
    270 
    271   State where the user needs to provide some identity data to pass a KYC
    272   check.  The wallet only shows the user the link for starting the KYC
    273   process and long-polls the exchange in anticipation of the user
    274   completing the KYC requirement.
    275 
    276   * ``[poll-success] => pending(withdraw-coins)``
    277   * ``[action:suspend] => suspended(kyc)``
    278 
    279 * ``suspended(kyc)``
    280 
    281   State where the user needs to provide some identity data to pass a KYC
    282   check, but the long-polling was explicitly stopped. The user can
    283   choose to resume or delete.
    284 
    285   * ``[action:delete] => deleted``
    286   * ``[action:resume] => pending(kyc)``
    287 
    288 * ``pending(aml)``
    289 
    290   State where the wallet needs to wait for completion of an AML process by an
    291   AML officer of the exchange. The wallet shows that the AML process is
    292   blocking progress. The message shown should distinguish between a mere
    293   pending AML process and an AML freezing decision in terms of the message
    294   shown to the user. If the AML decision is pending at the exchange, he user
    295   should be urged to simply wait.  If the funds were frozen, the wallet
    296   informs the user that their funds were frozen due to an AML decision.  The
    297   user is urged to contact the exchange operator's AML department out-of-band.
    298   In any case, the wallet long-polls for the AML decision to be made or change
    299   (possibly at a lower frequeny in case of a freeze).
    300 
    301   * ``[poll-success] => pending(withdraw-coins)``
    302   * ``[action:suspend] => suspended(aml)``
    303 
    304 * ``suspended(aml)``
    305 
    306   State where the user needs to await some AML decision by the exchange.
    307   The long-polling was explicitly stopped. The user can choose to resume or delete.
    308 
    309   * ``[action:delete] => deleted``
    310   * ``[action:resume] => pending(aml)``
    311 
    312 * ``suspended(withdraw-coins)``
    313 
    314   In this state, the wallet should show how much money arrived into the wallet
    315   and the rest of the money will be sent back to the originating bank account
    316   after ``$closing_delay``.  Note that the ``resume`` action should be
    317   disabled after ``$closing_delay``.
    318 
    319   * ``[action:delete] => deleted``
    320   * ``[action:resume] => pending(exchange-wait-reserve)``
    321 
    322 * ``done``
    323 
    324   The withdrawal operation is complete.
    325 
    326   * ``[action:delete] => deleted``
    327 
    328 * ``deleted``
    329 
    330   Withdrawn coins are preserved, as is reserve information for recoup.
    331   So this mostly removes the entry from the visible transaction history.
    332   Only once all coins were spent, the withdraw is fully removed.
    333 
    334 
    335 .. image:: ../images/transaction-withdrawal-states.png
    336 
    337 
    338 Transaction Type: Payment to Merchant
    339 -------------------------------------
    340 
    341 * ``pending(claim-proposal)``
    342 
    343   We received a ``pay`` URI. Download (claim) the proposal from the merchant.  Can fail if
    344   the proposal was already claimed by someone else.  If repurchase detection
    345   tells us that we already paid for this product, we go immediately to
    346   ``failed(repurchase)`` state for this transaction, but with a side-effect of
    347   transitioning the UI into a ``pending(repurchase-session-reset)`` on a
    348   *different* transaction (which before was in ``done``).
    349 
    350   A ``failed(repurchase)`` transaction will eventually be GCed (=deleted)
    351   automatically.
    352 
    353   * ``[error:already-claimed] => failed(already-claimed)`` -- the proposal was
    354     already claimed by someone else.
    355   * ``[error:invalid-proposal] => failed(invalid-proposal)`` -- the merchant provided a
    356     proposal that is invalid (e.g. malformed contract
    357     terms or bad signature).
    358 
    359 * ``dialog(merchant-order-proposed)``
    360 
    361   Let the user accept (or refuse) the payment.
    362 
    363   * ``[action:pay-accept] => pending(submit-payment)``
    364   * ``[action:pay-refuse] => ``aborted(refused)`` -- The user explicitly
    365     decided not to proceed (at least not with this wallet).
    366   * ``[expired] => failed(expired)`` -- The offer has expired before the user made any
    367     decision. Note that we should use this transition at
    368     least a few seconds before the offer *actually* expires to avoid
    369     encountering an expiration during ``pending(submit-payment)`` in most
    370     real-world scenarios. Basically, we should prevent last-second payments to
    371     be event attempted client-side.
    372 
    373     The ``failed(expired)`` might be automatically deleted upon GC.
    374 
    375 * ``pending(submit-payment)``
    376 
    377   Submit coin-by-coin (or in bulk groups) until payment is complete.
    378 
    379   * ``[action:abort] => aborting(pay-incomplete)`` -- The user explicitly decided to
    380     abort the process while the payment was happening.  Note that if the
    381     payment was already completed (and hence the merchant refuses any
    382     refunds), it is theoretically possible that pressing the abort button will
    383     nevertheless end up in a ``finalizing(auto-refund)`` state (and subsequently
    384     a ``done`` state) instead!
    385   * ``[success] => finalizing(auto-refund)`` -- Upon receiving confirmation from
    386     the merchant that the purchase was completed.
    387   * ``[error(insufficient balance)] => aborting(pay-incomplete)`` This transition
    388     happens if we detect double-spending and our balance is not sufficient
    389     after the double-spending. It is also conceivable (but should be rare)
    390     that this transition happens because the offer expired.
    391 
    392 * ``finalizing(auto-refund)``
    393 
    394   The payment succeed. We remain in this state as long as an auto-refund-check
    395   is active.  If auto refunds are not enabled, we immediately continue to
    396   ``done``.
    397 
    398   * ``[no-auto-refund] => done``
    399   * ``[timeout] => done`` -- This happens when the auto refund set by the
    400     contract expired.
    401   * ``[long-poll:refund] => aborting(pay-incomplete)`` -- An auto-refund was detected.
    402   * ``[action:abort] => done`` -- The user may explicitly request to abort the
    403     auto-refund processing (for example to enable subsequent deletion before
    404     the auto-refund delay expires).
    405 
    406 * ``aborting(pay-incomplete)``
    407 
    408   The wallet should interact with the merchant to request
    409   a refund on the incomplete payment.
    410 
    411   * ``[success] => aborted(pay-incomplete)``
    412   * ``[already-paid] => done``
    413 
    414 * ``aborted(refunded)``
    415 
    416   The purchase ended with a (partial) refund. The state (and UI) should show
    417   the specific provenance of the state, which may include an insufficient
    418   balance (due to double-spending being detected during payment), and one or
    419   more partial or full refunds.
    420 
    421   * ``[action:delete] => deleted``
    422 
    423 * ``done``
    424 
    425   The purchase is completed.
    426 
    427   * ``[action:delete] => deleted``
    428   * ``[repurchase] => pending(rebind-session)``: Another offer
    429     became pending for this product and we need to update the session so
    430     that the user does not have to buy it again.
    431   * ``[check-refunds]` => pending(check-refunds)``: New refunds
    432     might be available for this purchase.
    433 
    434 * ``pending(check-refund)``
    435 
    436   New refunds might be available for this purchase.
    437   This state must only be entered *after* the payment has successfully
    438   completed.  It is not relevant for auto-refunds or refunds for incomplete
    439   payments.
    440 
    441   * ``[refunds-checked] => pending(user-new-refund)`` --- New
    442     refund(s) are available, user needs to confirm.
    443   * ``[refunds-checked] => done`` --- Refunds were checked, but no
    444     new refunds are available.
    445   * ``[action:stop-refund-query] => done`` ---
    446     This action would usually only be offered when the state is pending
    447     with errors. It stops the refund query, but the payment of course
    448     is left intact.
    449 
    450 * ``pending(rebind-session)``
    451 
    452   The wallet should reset the associated session for the already purchased
    453   (digital) item.
    454 
    455   * ``[success] => done``
    456   * ``[action:abort] => done`` -- User aborted the session reset.
    457 
    458 * ``deleted``
    459 
    460   When a payment is deleted, associated refund transactions are always deleted
    461   with it.
    462 
    463 .. image:: ../images/transaction-payment-states.png
    464 
    465 
    466 Transaction Type: Refund
    467 ------------------------
    468 
    469 A refund is a pseudo-transaction that is always associated with a merchant
    470 payment transaction.
    471 
    472 * ``pending(accept)``
    473 
    474   Initial state for a refund.
    475 
    476   * ``[processed-error] => failed``: we received a permanent failure (such as money already wired to the merchant)
    477 
    478 * ``failed``
    479 
    480   The refund failed permanently.
    481 
    482 .. image:: ../images/transaction-refund-states.png
    483 
    484 
    485 Transaction Type: Refresh
    486 -------------------------
    487 
    488 This is about refreshes that are triggered via coin expiration or as part of
    489 getting change after making a payment.  In the first case, the refresh
    490 transaction is forever shown as a separate transaction in the history unless
    491 it did not affect the wallet balance (in which case we hide it). In the second
    492 case, the refresh transaction is folded into the payment transaction upon
    493 completion, so that the balance changes are included in the fees of the
    494 transaction that caused us to obtain change.
    495 
    496 If we have to adjust the refund amount (because a coin has fewer funds on it
    497 than we expect) the transaction only shows the changes due to the refresh, and
    498 we merely adjust the current balance of the wallet but without giving any
    499 justification (as we cannot give details we do not have). So this will look
    500 the same as if the double-spending transaction had been deleted by the user.
    501 
    502 * ``pending``
    503 
    504   A refresh operation is pending.
    505 
    506   * ``[processed-success] => done``
    507   * ``[action:suspend] => suspended``
    508   * ``[failed] => failed``
    509 
    510 * ``suspended``
    511 
    512   A refresh operation was suspended by the user.
    513 
    514   * ``[action:resume] => pending``
    515 
    516 * ``done``
    517 
    518   The refresh operation completed.
    519 
    520   * ``[action:delete] => deleted``
    521 
    522 * ``failed``
    523 
    524   The refresh operation failed. The user lost funds.
    525 
    526   * ``[action:delete] => deleted``
    527 
    528 * ``deleted``
    529 
    530   All memory of the refresh operation is lost, but of course the resulting
    531   fresh coins are preserved.
    532 
    533 .. image:: ../images/transaction-refresh-states.png
    534 
    535 
    536 Transaction Type: Deposit
    537 -------------------------
    538 
    539 * ``pending(deposit)``
    540 
    541   Initial state for deposit transactions.
    542   We deposit the amount coin-by-coin (or in bulk groups) until deposit is completed.
    543 
    544   * ``[action:suspend] => suspended(submit-deposit)``
    545   * ``[processed-success] => pending(track)``
    546   * ``[processed-failure] => aborting(refund)``
    547 
    548 * ``suspended(deposit)``
    549 
    550   The user suspended our ongoing deposit operation.
    551 
    552   * ``[action:resume] => pending(deposit)``
    553   * ``[action:abort] => aborting(refund)``
    554 
    555 * ``pending(track)``
    556 
    557   All the coins were submitted, waiting to be wired.
    558 
    559   * ``[poll-success] => done``
    560   * ``[poll-accepted-kyc] => pending(kyc)``
    561   * ``[poll-accepted-aml] => pending(aml)``
    562   * ``[action:abort] => aborting(refund)``
    563 
    564 * ``pending(kyc)``
    565 
    566   Exchange requires KYC before making the wire transfer.
    567 
    568   * ``[long-poll:kyc] => done``
    569   * ``[action:suspend] => suspended(kyc)``
    570 
    571 * ``suspended(kyc)``
    572 
    573   The user suspended us while we were waiting for KYC to be finished.
    574 
    575   * ``[action:resume] => pending(kyc)``
    576 
    577 * ``pending(aml)``
    578 
    579   Exchange requires AML before making the wire transfer.
    580 
    581   * ``[long-poll:aml] => done``
    582   * ``[action:suspend] => suspended(aml)``
    583 
    584 * ``suspended(aml)``
    585 
    586   The user suspended us while we were waiting for AML to be finished.
    587 
    588   * ``[action:resume] => pending(aml)``
    589 
    590 * ``aborting(refund)``
    591 
    592   Wallet should try to get the deposited amount back from the exchange (by submitting a refund).
    593 
    594   * ``[action:suspend] => suspended(refund)``
    595   * ``[processed-success] => aborting(refresh)``
    596   * ``[processed-error] => aborting(refresh)``: Even if the refund attempt failed, maybe the deposit failed as well and we can still succeed with a refresh.
    597 
    598 * ``suspended(refund)``
    599 
    600   The user suspended us while we were trying to get a refund.
    601 
    602   * ``[action:resume] => aborting(refund)``
    603 
    604 * ``aborting(refresh)``
    605 
    606   * ``[action:suspend] => suspended(refresh)``
    607   * ``[processed-success] => aborted``
    608   * ``[processed-error] => failed``
    609 
    610 * ``suspended(refresh)``
    611 
    612   The user suspended us while we were trying to do the refresh.
    613 
    614   * ``[action:resume] => aborting(refresh)``
    615 
    616 * ``aborted``
    617 
    618   The operation was aborted, some funds may have been lost (to fees or deposited anyway).
    619 
    620   * ``[action:delete] => deleted``
    621 
    622 * ``done``
    623 
    624   The deposit operation completed.
    625 
    626   * ``[action:delete] => deleted``
    627 
    628 * ``deleted``
    629 
    630   All memory of the deposit operation is lost.
    631 
    632 .. image:: ../images/transaction-deposit-states.png
    633 
    634 
    635 Transaction Type: Peer Push Debit
    636 ---------------------------------
    637 
    638 Peer Push Debit transactions are created when the user wants to transfer money
    639 to another wallet.
    640 
    641 States and transitions:
    642 
    643 * ``pending(purse-create)``
    644 
    645   The wallet is creating a purse. Initial state.
    646 
    647   * ``[process-success] => pending(ready)``: The wallet has created the purse.
    648   * ``[process-failure] => aborting(refund)``: The purse creation failed.
    649   * ``[action:suspend] => suspended(purse-create)``: The user suspended the operation.
    650 
    651 * ``suspended(purse-create)``
    652 
    653   * ``[action:resume] => pending(purse-create)``: The user resumed the operation.
    654   * ``[action:abort] => aborting(refund)``: The user aborted the operation.
    655 
    656 * ``pending(ready)``
    657 
    658   In this state, the user can send / show the ``taler://`` URI or QR code to somebody else.
    659 
    660   * ``[action:abort] => aborting(delete-purse)``: The user aborts the P2P payment. The wallet tries to reclaim money in the purse.
    661   * ``[purse-timeout] => aborting(refresh)``: The other party was too slow and the purse has now expired.
    662   * ``[poll-success] => done``: The other party has accepted the payment.
    663   * ``[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.)
    664 
    665 * ``aborting(delete-purse)``
    666 
    667   The wallet is deleting the purse to prevent the receiver from merging it and to reclaim the funds in it.
    668 
    669   * ``[processed-success] => aborting(refresh)``: The purse was deleted successfully, and refunded coins must be refreshed.
    670   * ``[processed-failed(already-merged)] => done``: The other party claimed the funds faster that we were able to abort.
    671   * ``[processed-failed(other)] => aborting(refresh)``:  The exchange reports a permanent error.  We still try to refresh.
    672   * ``[action:fail] => failed``: The user explicitly asked us to give up and accepted the possible loss of funds.
    673 
    674 * ``aborting(refund)``
    675 
    676   We abandon the purse that was never fully funded and ask for the deposited coins to be refunded.
    677 
    678   * ``[processed-success] => aborting(refresh)``: After the refund, we still need to refresh the coins.
    679   * ``[processed-failure] => aborting(refresh)``: The refund failed, we still try to refresh the coins.
    680   * ``[action:fail] => failed``: The user explicitly asked us to give up and accepted the possible loss of funds.
    681 
    682 * ``aborting(refresh)``
    683 
    684   * ``[processed-success] => aborted``: Refresh group finished. Aborting was successful, money was reclaimed.
    685   * ``[processed-failed] => failed``: Refresh group failed to complete with a permanent error.
    686   * ``[action:fail] => failed``: The user explicitly asked us to give up and accepted the possible loss of funds.
    687 
    688 * ``done``
    689 
    690   The transfer was successful.
    691 
    692   * ``[action:delete] => deleted``
    693 
    694 * ``aborted``
    695 
    696   The transfer was aborted. Except for fees, the money was recovered.
    697 
    698   * ``[action:delete] => deleted``
    699 
    700 * ``failed``
    701 
    702   The transfer failed. Money was lost. Unless on a forced abort, we should probably complain to the auditor.
    703 
    704   * ``[action:delete] => deleted``
    705 
    706 * ``deleted``
    707 
    708   All memory of the push debit operation is lost.
    709 
    710 .. image:: ../images/transaction-push-debit-states.png
    711 
    712 
    713 Transaction Type: Peer Push Credit
    714 ----------------------------------
    715 
    716 Peer Push Credit transactions are created when the user accepts to be paid via
    717 a ``taler://pay-push`` URI.
    718 
    719 States and transitions:
    720 
    721 * ``pending(download)``
    722 
    723   Wallet read the taler:// URI and is downloading the contract details for the user.
    724 
    725   * ``[processed-success] => pending(user)``: Contract can be shown to the user.
    726   * ``[action:suspend] => suspended(download)``: User suspended the operation.
    727 
    728 * ``suspended(download)``
    729 
    730   The download of the purse meta data was suspended by the user.
    731 
    732   * ``[action:resume] => pending(download)``
    733 
    734 * ``pending(user)``
    735 
    736   User needs to decide about accepting the money.
    737 
    738   * ``[action:accept] => pending(merge)``
    739   * ``[timeout] => failed``: User took too long to decide.
    740 
    741 * ``pending(merge)``
    742 
    743   * ``[processed-success] => pending(withdraw)``: Merging the reserve was successful.
    744   * ``[kyc-required] => pending(merge-kyc)``: User must pass KYC checks before the purse can be merged.
    745   * ``[timeout] => failed``: The purse expired before we could complete the merge.
    746   * ``[failure] => failed``: The merge failed permanently.
    747   * FIXME(CG): do we want to allow suspending here?
    748 
    749 * ``pending(merge-kyc)``
    750 
    751   We cannot merge the purse until passing a KYC check.
    752   The user is shown a hint where to begin the KYC
    753   process and the wallet long-polls on the KYC status.
    754 
    755   * ``[poll-success] => pending(withdraw)``
    756   * ``[action:suspend] => suspended(kyc)``
    757   * ``[timeout] => failed``: The purse expired before we could complete the merge.
    758 
    759 * ``suspended(merge-kyc)``
    760 
    761   We cannot merge the purse until passing a KYC check,
    762   and that check was suspended by the user.
    763 
    764   * ``[action:resume] => pending(kyc)``
    765   * ``[timeout] => failed``: The purse expired before we could complete the merge.
    766 
    767 * ``pending(withdraw)``
    768 
    769   The wallet is withdrawing coins from the reserve that was filled by merging
    770   the purse.
    771 
    772   * ``[kyc-required] => pending(withdraw-kyc)``
    773   * ``[aml-required] => pending(withdraw-aml)``
    774   * ``[withdraw-failure] => failed``
    775   * ``[withdraw-success] => done``
    776   * ``[action:suspend] => suspended(withdraw)``
    777 
    778 * ``suspended(withdraw)``
    779 
    780   The user requested the withdraw operation to be suspended.
    781 
    782   * ``[action:resume] => pending(withdraw)``
    783 
    784 * ``pending(withdraw-kyc)``
    785 
    786   We cannot withdraw more coins until passing a KYC check.
    787   The user is shown a hint where to begin the KYC
    788   process and the wallet long-polls on the KYC status.
    789 
    790   * ``[poll-success] => pending(withdraw-coins)``
    791   * ``[action:suspend] => suspended(withdraw-kyc)``
    792 
    793 * ``suspended(withdraw-kyc)``
    794 
    795   We cannot withdraw from the reserve until passing a KYC check,
    796   and that check was suspended by the user.
    797 
    798   * ``[action:resume] => pending(withdraw-kyc)``
    799 
    800 * ``pending(withdraw-aml)``
    801 
    802   We cannot withdraw more coins until AML rules are satisfied.
    803   The user is shown a hint as to the AML status (pending or frozen).
    804 
    805   * ``[poll-success] => pending(withdraw-coins)``
    806   * ``[action:suspend] => suspended(withdraw-aml)``
    807 
    808 * ``suspended(withdraw-aml)``
    809 
    810   We cannot withdraw from the reserve until AML rules are satisfied,
    811   and the status check was suspended by the user.
    812 
    813   * ``[action:resume] => pending(withdraw-aml)``
    814   * ``[action:delete] => deleted``
    815 
    816 * ``failed``
    817 
    818   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).
    819 
    820   * ``[action:delete] => deleted``
    821 
    822 * ``done``
    823 
    824   The operation succeeded.
    825 
    826   * ``[action:delete] => deleted``: No money will be lost, the withdrawn coins will be kept
    827 
    828 * ``deleted``
    829 
    830   All memory of the push credit operation is lost.
    831 
    832 .. image:: ../images/transaction-push-credit-states.png
    833 
    834 
    835 Transaction Type: Peer Pull Credit
    836 ----------------------------------
    837 
    838 TODO: Also specify variant where account reserve needs to be created / funded first (Note: post 1.0-feature).
    839 
    840 * ``pending(purse-create)``
    841 
    842   The wallet is creating a purse. Initial state.
    843 
    844   * ``[process-success] => pending(ready)``: The wallet has created the purse.
    845   * ``[process-failure] => deleted``: The purse creation failed. We only show a transient error.
    846   * ``[action:abort] => deleted``: The user aborted the operation.
    847 
    848 * ``pending(ready)``
    849 
    850   In this state, the user can send / show the ``taler://`` URI or QR code to
    851   somebody else.
    852 
    853   * ``[action:abort] => aborting(delete-purse)``: The user aborts the P2P payment.
    854   * ``[purse-timeout] => aborted``: The other party was too slow and the purse
    855     has now expired.
    856   * ``[poll-success] => pending(withdraw)``: The other party has made the payment.
    857   * ``[poll-error] => aborting(delete-purse)``: The exchange claims that there
    858     is a permanent error regarding the purse.  We should try to delete it.
    859 
    860 * ``aborting(delete-purse)``
    861 
    862   We are cleaning up the purse after the operation failed or was aborted by
    863   the user.
    864 
    865   * ``[failure:already-merged] => pending(withdraw)``: Too late to abort, the
    866     other side already paid the invoice.
    867   * ``[process-success] => aborted``: The wallet has deleted the purse.
    868   * ``[failure:other] => failed``: The purse deletion failed; we are
    869     nevertheless done.
    870   * ``[action:fail] => failed``: Money may be lost if it was deposited
    871     into the purse in the meantime.
    872 
    873 * ``aborted``
    874 
    875   The invoicing process ended without success.
    876 
    877   * ``[action:delete] => deleted``
    878 
    879 * ``pending(withdraw)``
    880 
    881   The wallet is withdrawing the money paid for the invoice.
    882 
    883   * ``[processed-success] => done``
    884   * ``[failure] => failed``
    885   * ``[processed-kyc] => pending(kyc)``
    886   * ``[processed-aml] => pending(aml)``
    887   * ``[action:suspend] => suspended(withdraw)``
    888 
    889 * ``suspended(withdraw)``
    890 
    891   The user suspended a withdraw operation.
    892 
    893   * ``[action:resume] => pending(withdraw)``
    894 
    895 * ``pending(kyc)``
    896 
    897   The user must supply KYC information before withdrawing can continue.
    898 
    899   * ``[poll-success] => pending(withdraw)``
    900   * ``[action:suspend] => suspended(kyc)``
    901 
    902 * ``suspended(kyc)``
    903 
    904   The user suspended waiting for the KYC operation to complete.
    905 
    906   * ``[action:resume] => pending(kyc)``
    907 
    908 * ``pending(aml)``
    909 
    910   The user must await a positive exchange AML decision.
    911 
    912   * ``[poll-success] => pending(withdraw)``
    913   * ``[action:suspend] => suspended(aml)``
    914 
    915 * ``suspended(aml)``
    916 
    917   The user suspended waiting for the AML decision to be successful.
    918 
    919   * ``[action:resume] => pending(aml)``
    920 
    921 * ``failed``
    922 
    923   Obtaining the money for the invoce failed. This is likely a case for the
    924   auditor.
    925 
    926   * ``[action:delete] => deleted``
    927 
    928 * ``done``
    929 
    930   The payment for the invoice was successfully received.
    931 
    932   * ``[action:delete] => deleted``
    933 
    934 * ``deleted``
    935 
    936 .. image:: ../images/transaction-pull-credit-states.png
    937 
    938 
    939 Transaction Type: Peer Pull Debit
    940 ---------------------------------
    941 
    942 * ``pending(download)``
    943 
    944   We are downloading the information about the invoice.  Initial state.
    945 
    946   * ``[action:suspend] => suspended(download)``
    947   * ``[success] => pending(user)``
    948 
    949 * ``suspended(download)``
    950 
    951   User suspended downloading the information about the invoice.
    952 
    953   * ``[action:resume] => pending(download)``
    954   * ``[action:delete] => deleted``
    955 
    956 * ``pending(user)``
    957 
    958   We have downloaded information about the pull payment and are waiting for
    959   the user to confirm.
    960 
    961   * ``[action:confirm-pay] => pending(submit-payment)``
    962   * ``[action:delete] => deleted``
    963   * ``[timeout] => aborted``
    964 
    965 * ``pending(deposit)``
    966 
    967   The user has confirmed the payment and the wallet tries to deposit
    968   into the provided purse.
    969 
    970   * ``[action:suspend] => suspended(deposit)``
    971   * ``[processed-success] => done``
    972   * ``[failure:timeout] => aborting(refresh)``
    973   * ``[processed-success] => done``
    974   * ``[failure:other] => aborting(refund)``
    975 
    976 * ``suspended(deposit)``
    977 
    978   User suspended depositing into the purse.
    979 
    980   * ``[action:resume] => pending(deposit)``
    981   * ``[action:abort] => aborting_refund``
    982 
    983 * ``aborting(refund)``
    984 
    985   Aborts the payment, asking for the already deposited coins to be refunded.
    986 
    987   * ``[processed-success] => aborted(refunded)``
    988   * ``[processed-failure] => aborting(refresh)``
    989   * ``[action:fail] => failed``
    990 
    991 * ``aborting(refresh)``
    992 
    993   Refreshes the coins that were previously deposited into the purse to recover their value.
    994 
    995   * ``[processed-success] => aborted``
    996   * ``[processed-failed] => failed``
    997 
    998 * ``done``
    999 
   1000   The invoice was successfully paid.
   1001 
   1002   * ``[action:delete] => deleted``
   1003 
   1004 * ``deleted``
   1005 
   1006   All information about the invoice has been deleted.
   1007 
   1008 .. image:: ../images/transaction-pull-debit-states.png
   1009 
   1010 
   1011 UI Strings for Transaction States
   1012 =================================
   1013 
   1014 * ``pending(kyc-init)``
   1015 
   1016   * Transactions: withdrawal, deposit, peer-push-credit, peer-pull-credit
   1017   * Title: "Preparing legitimization"
   1018 
   1019 * ``pending(kyc)``:
   1020 
   1021   * Transactions: withdrawal, deposit, peer-push-credit, peer-pull-credit
   1022   * Title: "Legitimization required"
   1023 
   1024 * ``pending(balance-kyc)``:
   1025 
   1026   * Transactions: withdrawal, deposit, peer-push-credit, peer-pull-credit, refund (?)
   1027   * Title: "Exceeds balance limit"
   1028 
   1029 * ``pending(kyc-auth)``:
   1030 
   1031   * Title: "Legitimization required"
   1032   * Alt Title: "Bank account verification required"
   1033   * Alt Title: "Verify bank account"
   1034 
   1035 * ``pending(accept-refund)``
   1036 
   1037   * Title: "Checking for refund"
   1038   * Alt title: "Processing refund"
   1039 
   1040     * User doesn't care about this info
   1041 
   1042 * ``finalizing(auto-refund)``
   1043 
   1044   * Title: TBD
   1045 
   1046 * ``pending(check-refund)``
   1047 
   1048   * Title: "Checking for refund"
   1049 
   1050 * ``aborted(completed-by-other-wallet)``
   1051 
   1052   * Title: "Completed by other wallet"
   1053 
   1054 * ``pending(bank-confirm-transfer)``
   1055 
   1056   * Title: "Waiting for bank transfer"
   1057 
   1058 * ``withdrawal:aborted(exchange)``
   1059 
   1060   * Title: "Aborted"
   1061   * Description: Mention that money will come back via bank account transfer.
   1062 
   1063 * ``pay:dialog(proposed)``
   1064 
   1065   * TBD (=> Vlada?)
   1066 
   1067 * ``pay:failed(paid-by-other)``
   1068 
   1069   * Title: "Paid with other wallet"
   1070 
   1071 * ``pending(ready)``
   1072 
   1073   * Title: "Ready"
   1074 
   1075 * ``pending(rebind-session)``
   1076 
   1077   * Title: "Restoring access"
   1078 
   1079 * ``finalizing(track)``
   1080 
   1081   * Title: TBD
   1082 
   1083 
   1084 Minor states just shown as ``pending/aborting/...`` (i.e. no more
   1085 details shown to the user):
   1086 
   1087 * ``failed(aborting-bank)``
   1088 * ``aborting(bank)``
   1089 * ``pending(bank-register-reserve)``
   1090 * ``pending(claim-proposal)``
   1091 * ``pending(create-purse)``
   1092 * ``aborting(delete-purse)``
   1093 * ``pending(deposit)``
   1094 * ``withdrawal:pending(exchange-wait-reserve)``
   1095 * ``peer-push-credit:pending(merge)``
   1096 * ``aborting(refresh)``
   1097 * ``aborted(refused)``
   1098 * ``pending(submit-payment)``
   1099 * ``pending(withdraw)``
   1100 * ``pending(withdraw-coins)``
   1101 * ``failed(repurchase)`` (anyway only shows in dev mode)
   1102 
   1103 
   1104 Alternatives
   1105 ============
   1106 
   1107 * Each transaction could be treated completely separately; however, uniform
   1108   terminology for actions (and thus button labels) is likely more helpful for
   1109   the user experience.
   1110 
   1111 * We could require user re-approval if fees changed when the available
   1112   denominations change during a *withdraw*.  This would require a different
   1113   state machine on withdraw. We believe the answer can be "no", for two
   1114   reasons: the wallet MUST pick denominations to withdraw with the "most
   1115   long-term" withdraw window (i.e. active denominations that have the longest
   1116   available withdraw durations). So in virtually all normal cases, this will
   1117   just succeed as a sane exchange will have a reasonable duration overlap, and
   1118   in the very few cases it's really the user's fault for going offline in the
   1119   middle of the operation. Plus, even in those few cases, it is highly
   1120   unlikely that the fee would actually change: again most key rotations can be
   1121   expected to be there to rotate the key, and not to adjust the withdraw fee.
   1122   And in the extremely rare case that the user went offline and in the
   1123   meantime the fees did *increase*, it's again unlikely to matter much to the
   1124   user. So special-casing this and testing this is probably not worth it.
   1125 
   1126 * We could require user re-approval if due to expired/invalid coins the coin
   1127   selection (and thus fees) changes during a *deposit*.  Again, expired coins
   1128   should virtually never happen unless a user goes offline for a long time in
   1129   the middle of a purchase (which would be very strange). If deposit fees
   1130   *increase* due to a double-spend detection during payment, we might want to
   1131   have an *optional* dialog ("Balance reduced by X as wallet state was not
   1132   up-to-date (did you restore from backup?).  Consequently, the fees for this
   1133   transactions increased from Y to Z.  [Abort] [Continue] + checkbox: [X] Do
   1134   not ask again."). Probably at best a post-1.0 feature.
   1135 
   1136 
   1137 Discussion / Q&A
   1138 ================
   1139 
   1140 * The diagrams only show what is happening **after** the wallet
   1141   has created the transaction.  It is possible that network requests
   1142   are happening before that, but they are not considered to be part
   1143   of the transaction.
   1144 * We have decided against a ``cancel`` state, because it resulted
   1145   in too much complexity.  Instead of doing a direct ``cancel``,
   1146   the user has to go to the transaction and abort and/or delete
   1147   it.
   1148 * We might add a ``revive`` action in the future that allows
   1149   to go from ``aborting`` back to ``pending`` for transactions
   1150   where this makes sense.  We're not doing it right now
   1151   to simplify things.