From b4e98ac71d3f8d31d00179ec736f3ad26b80272a Mon Sep 17 00:00:00 2001 From: Sebastian Date: Thu, 6 Apr 2023 13:38:42 -0300 Subject: * added initial state description * new description for aborted * new description delete action * added initial state in every tx type * added questions with (??) * removed common state when it doesn't add extra info --- .../037-wallet-transactions-lifecycle.rst | 230 +++++++++++++-------- 1 file changed, 143 insertions(+), 87 deletions(-) (limited to 'design-documents') diff --git a/design-documents/037-wallet-transactions-lifecycle.rst b/design-documents/037-wallet-transactions-lifecycle.rst index b086787e..3cc807e4 100644 --- a/design-documents/037-wallet-transactions-lifecycle.rst +++ b/design-documents/037-wallet-transactions-lifecycle.rst @@ -18,11 +18,16 @@ Proposed Solution Common States ------------- -The following states apply to multiple different transactions. They can -have transaction-specific sub-states, denoted by ``state(substate)``. +The following states apply to multiple different transactions. Only pending +and aborting have transaction-specific sub-states, denoted by ``state(substate)``. + +``initial``: The initial state is the result a user interaction. A transaction +may have more than one initial state (if it is started in multiple ways) or none +(if it's the result of another process) ``pending``: A pending transaction waits for some external event/service. -The transaction stays pending until its change on the wallet's material balance is finished. +The transaction stays pending until its change on the wallet's material balance +is finished. Any pending state can be suspended and resumed. There are some other distinctions for pending transactions: @@ -42,15 +47,10 @@ never has a ``lastError`` but is considered successful. complete the transaction, the wallet is taking active steps to abort it. The ``lastError`` indicates errors the wallet experienced while taking active steps to abort the transaction. -.. attention:: - Should there be an abortReason for aborted transactions? - - sebasjm: yes, although it doesn't mean that the user need to add this information - manually. The information we save in the abort operation can help the user to know - how and when the operation was aborted. - ``aborted``: Similar to a ``done`` transaction, but the transaction was successfully aborted -instead of successfully finished. +instead of successfully finished. It will have the information of when (timestamp) it was +aborted and in which pending sub-state the abort action was initiated. Also, we can +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. @@ -71,7 +71,8 @@ Transitions are actions or other events. completely deletes the transaction in 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. +delete already successfully withdrawn coins. Deleting is only safe (no money lost) +on initial and final state (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 @@ -82,7 +83,7 @@ states: ``pending(*)`` and ``aborting(*)``. Should we show the retry timeout in the UI somewhere? Should we show it in dev mode? - sebasjm: Since the wallet will retry anyway, maybe is better if we replace the "retry" + SEBASJM: Since the wallet will retry anyway, maybe is better if we replace the "retry" button with a "try now" button and a side text "retrying in xxx seconds" ``[action:abort]``: Aborting a transaction either directly stops processing for the @@ -146,7 +147,7 @@ rotations can be expected to be there to rotate the key, and not to adjust the w And in the 1:1M case that the fee does *increase*, it's again unlikely to matter much to the user. So special-casing this and testing this is IMO just not worth it. -* ``pending(bank-register-reserve)`` +* ``initial(bank-register-reserve)`` Initial state for bank-integrated withdrawals. The wallet submits the reserve public key and selected exchange to the bank (via the bank integration API). @@ -160,9 +161,16 @@ user. So special-casing this and testing this is IMO just not worth it. the user has to complete a 2FA step to confirm that the money is wired to the chosen exchange. + (??) is this needed? let say that the money is wired but the signal + never of the bank confirmation reached the wallet, what should happen? + * ``[poll-success] => pending(exchange-wait-reserve)`` * ``[action:abort] => aborting(wallet-to-bank)`` +* ``initial(manual-withdraw)`` + + * ``[process-success] => pending(exchange-wait-reserve)``: reserve created + * ``pending(exchange-wait-reserve)`` Initial state for manual withdrawals. @@ -232,7 +240,10 @@ 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. -* ``pending(download-proposal)`` +(??) 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. @@ -243,6 +254,8 @@ something like that. 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. @@ -258,28 +271,23 @@ something like that. * ``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(paid-auto-refund-check)`` + * ``[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") -* ``pending(submit-payment-replay)`` +* ``pending(refundable)`` -* ``pending(paid-auto-refund-check)`` +The payment succeed but if auto-refund-check is active it will be checking for refunds * ``[auto-refund-timeout] => done`` -* ``pending(paid-check-refund)`` - -* ``done`` - - * ``[action:check-refund] => pending(paid-check-refund)`` - * ``[action:pay-replay] => pending(submit-payment-replay)`` - * ``[action:delete] => deleted`` - * ``aborting(refund)`` * ``[processed-success] => aborted(refunded)`` @@ -306,6 +314,14 @@ Transaction Type: Refund A refund is a pseudo-transaction that is always associated with a merchant payment transaction. +* ``initial`` + + The wallet has downloaded metadata for the refund from the merchant and + stored it in the database. The user needs to accept/refuse it. + + * ``[processed-success] => pending``: the refund is accepted + * ``[processed-abort] => aborted`` : the refund is not accepted + * ``pending`` A refund is pending when the merchant is getting a non-permanent error from @@ -314,21 +330,13 @@ A refund is a pseudo-transaction that is always associated with a merchant payme * ``[processed-success] => done`` * ``[processed-error] => failed`` -* ``done`` - * ``failed`` A failed refund can technically still transition to ``done``, because the wallet doesn't query some refund resource, but the purchase for refunds. Thus, a previously - failed refund can suddenly transition to ``done``. - - * ``[payment-refund-processed-success] => done`` - -* ``*`` + failed refund can suddenly transition to ``done``. - Transitions from any state: - - * ``[action:delete] => deleted`` Deleting a refund has no effect on the wallet's balance. + (??) separate transient error vs permanent error ? Transaction Type: Refresh ------------------------- @@ -349,13 +357,17 @@ cannot give details). * ``done`` +(??) should this be like ``pending(exchange-wait-reserve)`` from withdraw? +(??) can refresh trigger kyc? + + Transaction Type: Tip --------------------- -* ``pending(initial)`` +* ``initial`` The wallet has downloaded metadata for the tip from the merchant and - stored it in the databse. The user needs to accept/refuse it. + stored it in the database. The user needs to accept/refuse it. * ``[tip-expired] => failed(expired)`` * ``[action:accept-tip] => pending(pickup)`` @@ -364,9 +376,14 @@ Transaction Type: Tip * ``pending(pickup)`` * ``[tip-expired] => failed(expired)`` + * ``[processed-kyc-required] => pending(kyc-required)`` * ``[processed-success] => done`` * ``[action:abort] => aborted`` +* ``pending(kyc-required)`` + + * ``[poll-success] => pending(pickup)`` + Transaction Type: Deposit ------------------------- @@ -379,36 +396,48 @@ _optional_ dialog ("Balance reduced by X as wallet state was not up-to-date (did you restore from backup?). Consequently, the fees for this transactions increased from Y to Z. [Abort] [Continue] + checkbox: [X] Do not ask again." -* ``pending(initial)`` +* ``initial`` - The wallet deposits coins with the exchange. + Deposit is created, effective amount is removed from balance - * ``[processed-success] => pending(track)`` - * ``[action:abort] => aborting(refund)`` + * ``[processed-success] => pending(submit-deposit)``: reserve created + * ``[action:abort] => aborted`` -* ``pending(kyc-required)`` +* ``pending(submit-deposit)`` - The exchange requires KYC before it can proceed with the withdrawal. Note that - we only find this out via the tracking API *after* the deposit has been - successfully made. +Submit coin by coin (or in bulk groups) until deposit is completed. - * ``[poll-success] => pending(track)`` * ``[action:abort] => aborting(refund)`` + * ``[processed-success] => pending(track)`` + * ``[processed-error] => aborting(refresh)`` * ``pending(track)`` +All the coins were submitted, waiting to be wired. + * ``[poll-success] => done`` - * ``[processed-kyc-required] => pending(kyc-required)`` + * ``[action:abort] => aborting(partially-wired)`` * ``aborting(refund)`` - * ``[processed-success] => aborting(refresh)`` - * ``[processed-error] => aborting(refresh)`` XXX Shouldn't this be some error state? +Trying to get the deposited amount back from the exchange. + + ``[processed-success] => aborting(refresh)`` + ``[processed-error] => aborting(refresh)`` XXX Shouldn't this be some error state? +(??) why it moves to the same state? + +* ``aborting(partially-wired)`` + +Should cancel all pending wire transfer. + + ``[processed-success] => aborting(refund)`` + ``[processed-error] => aborting(refresh)`` XXX Shouldn't this be some error state? + * ``aborting(refresh)`` - * ``[processed-success] => aborted`` - * ``[processed-error] => failed`` + ``[processed-success] => aborted`` + ``[processed-error] => failed`` * ``done`` @@ -421,14 +450,13 @@ to another wallet. States and transitions: -* ``pending(initial)`` +* ``initial`` In this state, the user is not yet able to send the payment to somebody else. * ``[action:abort] => aborted``: The payment is aborted early, before the wallet even had the chance to create a purse. No fees are incurred. - * ``[action:delete] => deleted``: No funds are lost. - * ``[processsing-success] => pending(purse-created)``: The wallet was able to successfully create a purse. + * ``[processing-success] => pending(purse-created)``: The wallet was able to successfully create a purse. * ``pending(purse-created)`` @@ -436,7 +464,7 @@ States and transitions: * ``[action:abort] => aborting(delete-purse)``: The user aborts the P2P payment. The wallet tries to reclaim money in the purse. * ``[purse-timeout] => aborting(refresh)``: The other party was too slow. - * ``[poll-success] => done``: The other party has accepted the payment. + * ``[poll-success] => pending(refundable)``: The other party has accepted the payment. * ``[poll-error] => aborting(refresh)``: The exchange claims that there is a permanent error regarding the purse. * ``aborting(delete-purse)`` @@ -444,7 +472,6 @@ States and transitions: * ``[processed-success] => aborting(refresh)``: The purse was deleted successfully, and refunded coins must be refreshed. * ``[processed-failed(already-merged)] => done``: The other party claimed the funds faster that we were able to abort. * ``[processed-failed(other)] => aborting(refresh)``: The exchange reports a permanent error. We still try to refresh. - * ``[action:abort-force] => failed`` * ``aborting(refresh)`` @@ -453,17 +480,15 @@ States and transitions: * ``[processed-failed] => failed)``: Refresh group failed to complete with a permanent error. * ``[action:abort-force] => failed``: XXX will this abort the refresh session or just orphan it? -* ``done`` - - * ``[action:delete]`` No money should be lost in this case. +* ``pending(refundable)`` -* ``aborted`` + * ``[auto-refund-timeout] => done`` - * ``[action:delete]`` No additional money is lost other than fees from aborting/refreshing. +* ``aborting(refund)`` -* ``failed`` + * ``[processed-success] => aborted(refunded)`` + * ``[processed-failure] => aborting(refresh)`` - * ``[action:delete]``: Money will be lost. Transaction Type: Peer Push Credit @@ -474,24 +499,29 @@ a ``taler://pay-push`` URI. States and transitions: -* ``pending(initial)`` +* ``initial`` + +Wallet read the taler:// URI and the transaction was initialized * ``[processed-success] => pending(withdrawing)``: Merging the reserve was successful -* ``pending(withdrawing)`` +* ``pending(withdrawing-coins)`` - * ``[processed-kyc-required] => kyc-required`` + * ``[processed-kyc-required] => pending(kyc-required)`` -* ``kyc-required`` +* ``pending(kyc-required)`` - * ``[poll-success] => pending(withdrawing)`` + * ``[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. + resume the transaction again. Exchange should return non-withdrawn coins discounting closing fee. * ``aborted`` - * ``[action:resume] => pending(withdrawing)`` + * ``[action:resume] => pending(withdrawing-coins)`` +(??) this is not possible since aborted is final + * ``[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 * ``done`` @@ -503,12 +533,19 @@ Transaction Type: Peer Pull Credit ---------------------------------- TODO: Also specify variant where account reserve needs to be created / funded first. +?? which is this case? + +* ``initial`` -* ``pending(initial)`` +Wallet created the transaction - In this state, the purse is created (already in a merged state, with the initiator - providing the reserve). + * ``[action:success] => pending(purse-created)`` +* ``pending(purse-created)`` + + In this state, the purse is created (already in a merged state, with the initiator providing the reserve). + + * ``[action:success] => pending(wait-deposit)``: * ``[action:abort] => aborted``: At this stage, it's safe to just abort. CG: is this not 'suspend' (safe to resume!). Also, deletion transitions are missing. @@ -523,41 +560,60 @@ TODO: Also specify variant where account reserve needs to be created / funded fi * ``pending(withdrawing)`` * ``[processed-success] => done`` + * ``[processed-kyc-required] => pending(kyc-required)`` + +* ``pending(kyc-required)`` + + * ``[poll-success] => pending(withdrawing)`` * ``aborting(delete-purse)`` * ``[processed-success] => aborted`` - * ``[processed-failed(merge)] => done`` + * ``[processed-failed(was-merged)] => done`` * ``[processed-failed(expired)] => failed(expired)`` -* ``aborted`` -* ``done`` +Transaction Type: Peer Pull Debit +--------------------------------- -* ``failed(expired)`` +* ``initial`` - +Wallet read the taler:// URI -Transaction Type: Peer Pull Debit ---------------------------------- + * ``[action:success] => pending(invoice-downloaded)`` -* ``pending(initial)`` + +* ``pending(invoice-downloaded)`` We've downloaded information about the pull payment and are waiting for the user to confirm. * ``[action:abort] => aborted``: Safe to abort! - * ``[action:confirm-pay] => pending(deposit)``: Safe to abort! + * ``[action:confirm-pay] => pending(submit-payment)`` -* ``pending(deposit)`` +* ``pending(submit-payment)`` The user has confirmed the payment and the wallet tries to deposit into the provided purse. + * ``[action:abort] => aborting(refund)`` + * ``[processed-success(auto-refund-enabled)] => pending(refundable)`` + * ``[processed-success(auto-refund-disabled)] => done`` + * ``[processed-error(expired)] => aborting(refresh)`` * ``[processed-success] => done`` - * ``[action:abort] => aborting(refresh)``: Wallet tries to refresh coins - that were not already deposited. XXX Do we really always refresh even if no deposit - attempt has been made yet? CG: only every refresh those coins that are dirty. + * ``[action:abort] => aborting(refresh)`` + +* ``pending(refundable)`` + +The payment succeed but if auto-refund-check is active it will be checking for refunds + + * ``[auto-refund-timeout] => done`` + +* ``aborting(refund)`` + + * ``[processed-success] => aborted(refunded)`` + * ``[processed-failure] => aborting(refresh)`` + * ``aborting(refresh)`` -- cgit v1.2.3