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