summaryrefslogtreecommitdiff
path: root/design-documents
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2023-04-09 17:22:43 +0200
committerChristian Grothoff <christian@grothoff.org>2023-04-09 17:22:43 +0200
commit9e148c42d940ddcfafe1394f0461d40bceabb008 (patch)
treeee4db2e4836e8194364488a2f152b98dac0b9a41 /design-documents
parent836ec500bdbdb91a07110b1455f0f6cf2d26fa7c (diff)
downloaddocs-9e148c42d940ddcfafe1394f0461d40bceabb008.tar.gz
docs-9e148c42d940ddcfafe1394f0461d40bceabb008.tar.bz2
docs-9e148c42d940ddcfafe1394f0461d40bceabb008.zip
more work on DD37 review
Diffstat (limited to 'design-documents')
-rw-r--r--design-documents/037-wallet-transactions-lifecycle.rst284
1 files changed, 210 insertions, 74 deletions
diff --git a/design-documents/037-wallet-transactions-lifecycle.rst b/design-documents/037-wallet-transactions-lifecycle.rst
index a08fe07f..3242e695 100644
--- a/design-documents/037-wallet-transactions-lifecycle.rst
+++ b/design-documents/037-wallet-transactions-lifecycle.rst
@@ -56,7 +56,9 @@ include more information information relevant to the transaction in `abortReason
``suspended``: Similar to a ``aborted`` transaction, but the transaction was could be
resumed and may then still succeed.
-``failed``: Similar to ``done``, but the transaction could not even be aborted properly.
+``failed``: Similar to ``done``, but the transaction could not even be aborted
+properly. The user may have lost money. This is likely a case for a report to
+the auditor.
``deleted``: A ``deleted`` state is always a final state. We only use this
state for illustrative purposes. In the implementation, the data associated
@@ -68,13 +70,6 @@ Common Transitions
Transitions are actions or other events.
-``[action:delete]``: Deleting a transaction
-completely deletes the transaction from the database. Depending on the type of
-transaction, some of the other data *resulting* from the transaction might
-still survive deletion. For example, deleting a withdrawal transaction does not
-delete already successfully withdrawn coins. Deleting is only safe (no money lost)
-on initial and final states (failed, aborted, done).
-
``[action:retry]``: Retrying a transaction *(1.)* stops ongoing long-polling
requests for the transaction *(2.)* resets the retry timeout *(3.)* re-runs the
handler to process the transaction. Retries are always possible the following
@@ -96,11 +91,6 @@ states: ``pending(*)`` and ``aborting(*)``.
retries should basically never be > 24h (we can impose a hard cap), the absolute
time can just be in the format HH:MM:SS (without day).
-``[action:abort]``: Aborting a transaction either directly stops processing for the
-transaction and puts it in an ``aborted`` state, or starts the necessary steps to
-actively abort the transaction (e.g. to avoid losing money) and puts it in an
-``aborting`` state.
-
``[action:suspend]``: Suspends a pending transaction, stopping any associated
network activities, but with a chance of trying again at a later time. This
could be useful if a user needs to save battery power or bandwidth and an
@@ -110,22 +100,43 @@ withdrawal operation).
``[action:resume]``: Suspended transactions may be resumed, placing them back
into a pending state.
-``[action:abort-force]``: Directly puts an ``aborting`` transaction into the
-``failed`` state.
+``[action:abort]``: Aborting a transaction either directly stops processing for the
+transaction and puts it in an ``aborted`` state, or starts the necessary steps to
+actively abort the transaction (e.g. to avoid losing money) and puts it in an
+``aborting`` state.
+
+``[action:force-abort]``: Directly puts an ``aborting`` transaction into a
+``failed`` state. May result in an ultimate loss of funds (beyond fees) to the
+user and thus requires additional consent.
+``[action:delete]``: Deleting a transaction completely deletes the transaction
+from the database. Depending on the type of transaction, some of the other
+data *resulting* from the transaction might still survive deletion. For
+example, deleting a withdrawal transaction does not delete already
+successfully withdrawn coins. Deleting is only safe (no money lost) on initial
+and final states (failed, aborted, done).
-Whether aborting or resuming are possible depends on the transaction type, and
-usually only one of the two choices should be offered.
+``[action:force-delete]``: Directly puts a transaction into a ``deleted``
+state. May result in an ultimate loss of funds (beyond fees) to the user and
+thus requires additional consent.
+
+
+Whether aborting, deleting or suspending are possible depends on the
+transaction type, and usually only one of the three choices should be offered.
.. image:: ../transaction-common-states.png
:width: 400
-Boxed labels indicate an end state in which it is safe to delete the
-transaction record since no work is due.
+Boxed labels indicate an end state in which there is no network activity and
+hence no need to give the user a way to abort or suspend the activity. The
+circle indicates the initial state. Ovals are states with network activity.
-Blue arrows are used for user-triggered actions (via UI buttons).
+Blue arrows are used for user-triggered actions (via UI buttons). Purple
+arrows are used to indicate externally triggered actions. Black arrows
+without labels are used for the normal successful path. Red arrows indicate
+failure paths.
Common pending sub-states
@@ -135,18 +146,18 @@ During the pending state the transaction can go through several sub-states befor
reaching a final state. Some of this sub-states are shared between different
transaction types:
-``kyc-required``: The transaction can't proceed because the user needs to actively
-finish a KYC process. Part of a withdrawal process or peer-to-peer push credit.
-
-``aml-required``: The transaction can't proceed because the user needs to wait for
-the exchange operator to conclude an AML investigation by the staff at the exchange.
-The user is not expected to take any action and should just wait for the investigation
-to conclude. Part of a withdrawal process or peer-to-peer push credit.
+``kyc``: The transaction cannot proceed because the user needs to actively
+finish a KYC process. The wallet should show the user a hint on how to
+start the KYC process.
-``aml-frozen``: The staff at the exchange decided that the account needed to be frozen.
-The user should contact the exchange provider's customer service department and
-seek resolution (possibly through the courts) to avoid loosing the funds for good.
-Part of a withdrawal process or peer-to-peer push credit.
+``aml``: The transaction can't proceed because the user needs to wait for the
+exchange operator to conclude an AML investigation by the staff at the
+exchange. There are two AML substates. In the substate ``pending`` the user
+is not expected to take any action and should just wait for the investigation
+to conclude. In the substate ``frozen`` the staff at the exchange decided that
+the account needed to be frozen. The user should contact the exchange
+provider's customer service department and seek resolution (possibly through
+the courts) to avoid loosing the funds for good.
Transaction Type: Withdrawal
@@ -193,15 +204,19 @@ Transaction Type: Withdrawal
``suspended(after-wired)`` (treating the ``abort`` action as a ``suspend``
action).
- * ``[processed-success] => deleted``: We show a transient message that the operation was aborted.
- * ``[processed-error(already-confirmed)] => suspended(after-wired)``: We keep a transaction history entry reminding the user about when the already wired funds will be returned.
+ * ``[processed-success] => deleted``: We show a transient message that the
+ operation was aborted.
+ * ``[processed-error(already-confirmed)] => suspended(after-wired)``: We
+ keep a transaction history entry reminding the user about when the already
+ wired funds will be returned.
* ``[processed-error(unknown-transaction)] => deleted``
* ``suspended(after-wired)``
- In this state, the wallet should show to the user that the money from the withdrawal
- reserve will be sent back to the originating bank account after ``$closing_delay``.
- Note that the ``resume`` action should be disabled after ``$closing_delay``.
+ In this state, the wallet should show to the user that the money from the
+ withdrawal reserve will be sent back to the originating bank account after
+ ``$closing_delay``. Note that the ``resume`` action should be disabled
+ after ``$closing_delay``.
* ``[action:delete] => deleted``
* ``[action:resume] => pending(exchange-wait-reserve)``
@@ -369,22 +384,31 @@ Transaction Type: Payment to Merchant
is active. If auto refunds are not enabled, we immediately continue to
``done``.
- * ``[timeout] => done`` -- This happens when the auto refund set by the contract expired.
- * ``[action:abort] => done`` -- The user may explicitly request to abort the auto-refund processing (for example to enable subsequent deletion before the auto-refund delay expires).
+ * ``[timeout] => done`` -- This happens when the auto refund set by the
+ contract expired.
+ * ``[long-poll:refund] => aborting(refund)`` -- An auto-refund was detected.
+ * ``[action:abort] => done`` -- The user may explicitly request to abort the
+ auto-refund processing (for example to enable subsequent deletion before
+ the auto-refund delay expires).
* ``aborting(refund)``
The wallet should interact with the merchant to confirm that a refund
was approved.
- * ``[success] => aborted(refunded)``
- * ``[failure] => aborting(refresh)``
+ * ``[success] => aborting(refresh)``
+ * ``[failure] => aborting(refresh)``: Try refresh anyway.
+ * ``[action:force-delete] => deleted``: User may loose money.
* ``aborting(refresh)``
The wallet should interact with the exchange to obtain fresh coins for
the refunded balance.
+ * ``[success] => aborted(refunded)``
+ * ``[failure] => failed``
+ * ``[action:force-delete] => deleted``: User may loose money.
+
* ``aborted(refunded)``
The purchase ended with a (partial) refund. The state (and UI) should show
@@ -392,8 +416,6 @@ Transaction Type: Payment to Merchant
balance (due to double-spending being detected during payment), and one or
more partial or full refunds.
- * ``[URI:refund] => aborting(refund)`` -- The previous refund was partial,
- and we have received an additional refund for this transaction.
* ``[action:delete] => deleted``
* ``done``
@@ -401,46 +423,49 @@ Transaction Type: Payment to Merchant
The purchase is completed.
* ``[action:delete] => deleted``
- * ``[repurchase] => pending(repurchase-session-reset)`` -- Another offer became pending for this product.
+ * ``[repurchase] => pending(repurchase-session-reset)``: Another offer
+ became pending for this product and we need to update the session so
+ that the user does not have to buy it again.
* ``pending(repurchase-session-reset)``
- The wallet should reset the associated session for the already purchased item.
+ The wallet should reset the associated session for the already purchased
+ (digital) item.
* ``[success] => done``
* ``[action:abort] => done`` -- User aborted the session reset.
* ``deleted``
- When a payment is deleted, associated refunds are always deleted with it.
+ When a payment is deleted, associated refund transactions are always deleted
+ with it.
.. image:: ../transaction-payment-states.png
:width: 800
-Purple arrows are used to indicate transitions triggered in special ways outside
-of the user interface for this transaction, such as side-effects of repurchase
-detection for another purchase or opening of a refund URI.
-
Transaction Type: Refund
------------------------
-A refund is a pseudo-transaction that is always associated with a merchant payment transaction.
+A refund is a pseudo-transaction that is always associated with a merchant
+payment transaction.
* ``pending(lookup-refund)``
- We received a ``refund`` URI. Download refund details (like the amount) from the merchant. If the merchant responds with a permanent failure, we only show a transient warning and delete the transaction.
+ We received a ``refund`` URI. Download refund details (like the amount) from
+ the merchant. If the merchant responds with a permanent failure, we only
+ show a transient warning and delete the transaction.
* ``[success] => pending(user-accept)``
* ``[action:suspend] => suspended(lookup-refund)``
- * ``[failure] => deleted``
+ * ``[failure] => deleted``: A transient warning is shown to the user about the failure.
* ``suspended(lookup-refund)``
The user suspended while we were looking up the refund details. Allow resuming or permanent deletion.
* ``[action:resume] => pending(lookup-refund)``
- * ``[action:delete] => deleted``
+ * ``[action:force-delete] => deleted``: Refund funds will be lost to the user.
* ``pending(user-accept)``
@@ -457,6 +482,13 @@ A refund is a pseudo-transaction that is always associated with a merchant payme
* ``[processed-success] => pending(refresh)``
* ``[processed-error] => failed``: we received a permanent failure (such as money already wired to the merchant)
+* ``suspended(merchant)``
+
+ Refund processing was suspended while waiting for the merchant.
+
+ * ``[action:resume] => pending(merchant)``
+ * ``[action:force-delete] => deleted``
+
* ``pending(refresh)``
The wallet is now refreshing the coins.
@@ -465,6 +497,12 @@ A refund is a pseudo-transaction that is always associated with a merchant payme
* ``[action:suspend] => suspended(refresh)``
* ``[processed-error] => failed``: we received a permanent failure.
+* ``suspended(refresh)``
+
+ Refund processing was suspended while waiting for the refresh to complete.
+
+ * ``[action:resume] => pending(refresh)``
+ * ``[action:force-delete] => deleted``
* ``failed``
@@ -497,13 +535,14 @@ the same as if the double-spending transaction had been deleted by the user.
* ``[processed-success] => done``
* ``[action:suspend] => suspended``
+ * ``[failed] => failed``
* ``suspended``
A refresh operation was suspended by the user.
* ``[action:resume] => pending``
- * ``[action:delete] => deleted``
+ * ``[action:force-delete] => deleted``
* ``done``
@@ -511,6 +550,12 @@ the same as if the double-spending transaction had been deleted by the user.
* ``[action:delete] => deleted``
+* ``failed``
+
+ The refresh operation failed. The user lost funds.
+
+ * ``[action:delete] => deleted``
+
* ``deleted``
All memory of the refresh operation is lost, but of course the resulting
@@ -536,7 +581,7 @@ Transaction Type: Tip
The user suspended the operation to download the tip data.
- * ``[action:delete] => deleted``
+ * ``[action:force-delete] => deleted``
* ``[action:resume] => pending(query)``
* ``pending(user)``
@@ -546,7 +591,7 @@ Transaction Type: Tip
* ``[tip-expired] => failed``
* ``[action:accept] => pending(pickup)``
- * ``[action:abort] => deleted``
+ * ``[action:force-delete] => deleted``
* ``pending(pickup)``
@@ -561,7 +606,7 @@ Transaction Type: Tip
The user suspended the operation while the tip was being picked up.
- * ``[action:delete] => deleted``
+ * ``[action:force-delete] => deleted``
* ``[tip-expired] => failed``
* ``[action:resume] => pending(pickup)``
@@ -579,7 +624,7 @@ Transaction Type: Tip
the tip expires, as the wallet balance threshold KYC likely applies even
without the tip.
- * ``[action:delete] => deleted``
+ * ``[action:force-delete] => deleted``
* ``[action:resume] => pending(kyc)``
* ``done``
@@ -641,7 +686,7 @@ Transaction Type: Deposit
The user suspended us while we were trying to get a refund.
* ``[action:resume] => aborting(refund)``
- * ``[action:delete] => deleted``
+ * ``[action:force-delete] => deleted``
* ``aborting(refresh)``
@@ -654,7 +699,7 @@ Transaction Type: Deposit
The user suspended us while we were trying to do the refresh.
* ``[action:resume] => aborting(refresh)``
- * ``[action:delete] => deleted``
+ * ``[action:force-delete] => deleted``
* ``aborted``
@@ -725,6 +770,7 @@ States and transitions:
* ``[processed-success] => aborting(refresh)``: After the refund, we still need to refresh the coins.
* ``[processed-failure] => aborting(refresh)``: The refund failed, we still try to refresh the coins.
+ * ``[action:abort-force] => failed``: The user explicitly asked us to give up and accepted the possible loss of funds.
* ``aborting(refresh)``
@@ -761,7 +807,7 @@ States and transitions:
All memory of the push debit operation is lost.
.. image:: ../transaction-push-debit-states.png
- :width: 400
+ :width: 600
Transaction Type: Peer Push Credit
@@ -772,34 +818,124 @@ a ``taler://pay-push`` URI.
States and transitions:
-* ``initial``
+* ``pending(download)``
- Wallet read the taler:// URI and the transaction was initialized
+ Wallet read the taler:// URI and is downloading the contract details for the user.
- * ``[processed-success] => pending(withdrawing)``: Merging the reserve was successful
+ * ``[processed-success] => pending(user)``: Contract can be shown to the user.
+ * ``[action:suspend] => suspended(download)``: User suspended the operation.
-* ``pending(withdrawing-coins)``
+* ``suspended(download)``
- * ``[processed-kyc-required] => pending(kyc-required)``
+ The download of the purse meta data was suspended by the user.
-* ``pending(kyc-required)``
+ * ``[action:resume] => pending(download)``
+ * ``[action:force-delete] => deleted``
+
+* ``pending(user)``
+
+ User needs to decide about accepting the money.
+
+ * ``[action:accept] => pending(merge)``
+ * ``[action:force-delete] => deleted``
+ * ``[timeout] => failed``: User took too long to decide.
+
+* ``pending(merge)``
+
+ * ``[processed-success] => pending(withdraw)``: Merging the reserve was successful.
+ * ``[kyc-required] => pending(merge-kyc)``: User must pass KYC checks before the purse can be merged.
+ * ``[timeout] => failed``: The purse expired before we could complete the merge.
+ * ``[failure] => failed``: The merge failed permanently.
+ * FIXME(CG): do we want to allow suspending here?
+
+* ``pending(merge-kyc)``
+
+ We cannot merge the purse until passing a KYC check.
+ The user is shown a hint where to begin the KYC
+ process and the wallet long-polls on the KYC status.
+
+ * ``[poll-success] => pending(withdraw)``
+ * ``[action:suspend] => suspended(kyc)``
+ * ``[timeout] => failed``: The purse expired before we could complete the merge.
+
+* ``suspended(merge-kyc)``
+
+ We cannot merge the purse until passing a KYC check,
+ and that check was suspended by the user.
+
+ * ``[action:resume] => pending(kyc)``
+ * ``[action:force-delete] => deleted``
+ * ``[timeout] => failed``: The purse expired before we could complete the merge.
+
+* ``pending(withdraw)``
+
+ The wallet is withdrawing coins from the reserve that was filled by merging
+ the purse.
+
+ * ``[kyc-required] => pending(withdraw-kyc)``
+ * ``[aml-required] => pending(withdraw-aml)``
+ * ``[withdraw-failure] => failed``
+ * ``[withdraw-success] => done``
+ * ``[action:suspend] => suspended(withdraw)``
+
+* ``suspended(withdraw)``
+
+ The user requested the withdraw operation to be suspended.
+
+ * ``[action:resume] => pending(withdraw)``
+ * ``[action:force-delete] => deleted``: Money is lost.
+
+* ``pending(withdraw-kyc)``
+
+ We cannot withdraw more coins until passing a KYC check.
+ The user is shown a hint where to begin the KYC
+ process and the wallet long-polls on the KYC status.
* ``[poll-success] => pending(withdrawing-coins)``
- * ``[action:abort] => aborted``: The user will lose the coins they were not able to withdraw yet, unless they
- resume the transaction again. Exchange should return non-withdrawn coins discounting closing fee.
+ * ``[action:suspend] => suspended(withdraw-kyc)``
-* ``aborted``
+* ``suspended(withdraw-kyc)``
+
+ We cannot withdraw from the reserve until passing a KYC check,
+ and that check was suspended by the user.
+
+ * ``[action:resume] => pending(withdraw-kyc)``
+ * ``[action:force-delete] => deleted``: Money is lost.
+
+* ``pending(withdraw-aml)``
- * ``[action:resume] => pending(withdrawing-coins)``
-(??) this is not possible since aborted is final
+ We cannot withdraw more coins until AML rules are satisfied.
+ The user is shown a hint as to the AML status (pending or frozen).
- * ``[action:delete] => deleted``: The user will irrevocable lose coins that were not withdrawn from the reserve yet.
-(??) no, i think aborting a push-credit should return to the sender, like a refund
+ * ``[poll-success] => pending(withdrawing-coins)``
+ * ``[action:suspend] => suspended(withdraw-aml)``
+
+* ``suspended(withdraw-aml)``
+
+ We cannot withdraw from the reserve until AML rules are satisfied,
+ and the status check was suspended by the user.
+
+ * ``[action:resume] => pending(withdraw-aml)``
+ * ``[action:delete] => deleted``
+
+* ``failed``
+
+ 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).
+
+ * ``[action:delete] => deleted``
* ``done``
+ The operation succeeded.
+
* ``[action:delete] => deleted``: No money will be lost, the withdrawn coins will be kept
+* ``deleted``
+
+ All memory of the push credit operation is lost.
+
+.. image:: ../transaction-push-credit-states.png
+ :width: 600
Transaction Type: Peer Pull Credit