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.