diff options
author | Christian Grothoff <christian@grothoff.org> | 2023-04-08 22:13:55 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2023-04-08 22:13:55 +0200 |
commit | b617c6452ec92c06533e98a26b09c23165fbbf44 (patch) | |
tree | d5e12c87517c813a14eecd8d7e7e20bbc7a2cd86 /design-documents | |
parent | 343f392149caadaf8e4209863364a61672f5c876 (diff) | |
download | docs-b617c6452ec92c06533e98a26b09c23165fbbf44.tar.gz docs-b617c6452ec92c06533e98a26b09c23165fbbf44.tar.bz2 docs-b617c6452ec92c06533e98a26b09c23165fbbf44.zip |
review payment states
Diffstat (limited to 'design-documents')
-rw-r--r-- | design-documents/037-wallet-transactions-lifecycle.rst | 137 |
1 files changed, 84 insertions, 53 deletions
diff --git a/design-documents/037-wallet-transactions-lifecycle.rst b/design-documents/037-wallet-transactions-lifecycle.rst index e2a04820..366079a2 100644 --- a/design-documents/037-wallet-transactions-lifecycle.rst +++ b/design-documents/037-wallet-transactions-lifecycle.rst @@ -286,87 +286,120 @@ shown in the above diagram to keep it on point. Transaction Type: Payment to Merchant ------------------------------------- -XXX: Also consider re-selection when the wallet accidentally double-spends coins -or the selected coins have expired. Do we ask the user in this case? +* ``pending(claim-proposal)`` -CG: I think no. We correct our balance (after all, we got a proof of -double-spending) and try other coins. If we do not have enough money left, we -abort and simply inform the user that their balance was insufficient to make -the payment after all (very sorry...). + Initial state. Download (claim) the proposal from the merchant. Can fail if + the proposal was already claimed by someone else. If repurchase detection + tells us that we already paid for this product, we go immediately to + ``delete`` state for this transaction, but with a side-effect of + transitioning the UI into a ``pending(repurchase-session-reset)`` on a + *different* transaction (which before was in ``done``). -Note that the case of selected coins having expired shouldn't really happen, -as the wallet should have noticed that when is started up, tried to refresh, -and if that already failed should have update the balance with a transaction -history entry saying something like "coins expired, offline too long" or -something like that. + * ``[error: already claimed] => deleted`` -- the proposal was + already claimed by someone else; we go directly into the ``deleted`` + state and only show a transient warning. + * ``[error: invalid proposal] => deleted`` -- the merchant provided a + proposal that is invalid (e.g. malformed contract + terms or bad signature); we go directly into the ``deleted`` state + and only show a transient warning. -(??) If transaction can be aborted while in-progress then it should return -instructedAmount, effectiveAmount and the affectedAmount (partially effective amount) - -* ``initial(download-proposal)`` - - Initial state. Download (claim) the proposal from the merchant. - - XXX: Also consider repurchase detection here? - - CG: Well, we could mention that this is a possible transition from - ``pending(download-proposal)`` to ``deleted`` with a side-effect - of transitioning the UI into a ``pending(repurchase-session-reset)`` - on a different transaction (which before was in ``done``). - - (??) should not reset another transaction? * ``pending(proposed)`` Let the user accept (or refuse) the payment. * ``[action:pay-accept] => pending(submit-payment)`` - * ``[action:abort] => deleted`` -- user explicitly decides not - to proceed - * ``[action:expired] => deleted`` -- when the offer expires - before the user decides to make the payment! (We can keep - pending contracts even in a 'pending transaction' list to - allow the user to choose to not proceed, but then this - transition would clean up that list). + * ``[action:pay-refuse] => ``aborting(unclaim)`` -- The user explicitly + decided not to proceed (at least not with this wallet). + * ``[expired] => deleted`` -- The offer has expired before the user made any + decision. (We can keep pending contracts even in a 'pending transaction' + list to allow the user to choose to not proceed, but then this transition + would clean up that list). Note that we should use this transition at + least a few seconds before the offer *actually* expires to avoid + encountering an expiration during ``pending(submit-payment)`` in most + real-world scenarios. Basically, we should prevent last-second payments to + be event attempted client-side. + +* ``aborting(unclaim)`` + + Tells the merchant that some *other* wallet is now again free to claim this + offer. * ``pending(submit-payment)`` -Submit coin by coin (or in bulk groups) until payment is complete. - - * ``[action:abort] => aborting(refund)`` - * ``[processed-success(auto-refund-enabled)] => pending(refundable)`` - * ``[processed-success(auto-refund-disabled)] => done`` - * ``[processed-error(expired)] => aborting(refresh)`` XXX: If the order is expired but the payment - succeeded partially before, do we still try an abort-refund? CG: YES, but of course - we probably should use the ``expired`` transition above a few seconds before the - offer *actually* expires to avoid this problem in 99.9% of real-world scenarios - ("prevent last-second payments client-side") + Submit coin-by-coin (or in bulk groups) until payment is complete. + + * ``[action:abort] => aborting(refund)`` -- The user explicitly decided to + abort the process while the payment was happening. Note that if the + payment was already completed (and hence the merchant refuses any + refunds), it is theoretically possible that pressing the abort button will + nevertheless end up in a ``pending(refundable)`` state (and subsequently + a ``done`` state) instead! + * ``[success] => pending(refundable)`` -- Upon receiving confirmation from + the merchant that the purchase was completed. + * ``[error(insufficient balance)] => aborting(refresh)`` This transition + happens if we detect double-spending and our balance is not sufficient + after the double-spending. It is also conceivable (but should be rare) + that this transition happens because the offer expired. * ``pending(refundable)`` -The payment succeed but if auto-refund-check is active it will be checking for refunds + The payment succeed. We remain in this tate as long as an auto-refund-check + is active. If auto refunds are not enabled, we immediately continue to + ``done``. - * ``[auto-refund-timeout] => 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). * ``aborting(refund)`` - * ``[processed-success] => aborted(refunded)`` - * ``[processed-failure] => aborting(refresh)`` + The wallet should interact with the merchant to confirm that a refund + was approved. -* ``aborting(refresh)`` + * ``[success] => aborted(refunded)`` + * ``[failure] => aborting(refresh)`` -* ``failed(invalid-proposal)`` +* ``aborting(refresh)`` - The merchant provided a proposal that is invalid (e.g. malformed contract terms or bad signature). + The wallet should interact with the exchange to obtain fresh coins for + the refunded balance. * ``aborted(refunded)`` + The purchase ended with a (partial) refund. The state (and UI) should show + the specific provenance of the state, which may include an insufficient + 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`` + + The purchase is completed. + * ``[action:delete] => deleted`` + * ``[refund URI trigger] => aborting(refund)`` -- A refund was initiated for the purchase. + * ``[repurchase] => pending(repurchase-session-reset)`` -- Another offer became pending for this product. + +* ``pending(repurchase-session-reset)`` + + The wallet should reset the associated session for the already purchased 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 refunds 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 @@ -709,8 +742,6 @@ Alternatives not ask again."). Probably at best a post-1.0 feature. - - Drawbacks ========= |